Source kinds, Learn tab and catalog update #9

Open
Cedric wants to merge 18 commits from feature/source-kinds into main
pull from: feature/source-kinds
Owner

Implements the source-kinds plan from the grilling session (terms in GLOSSARY.md).

  • Every Source is a News, Learning or Fun source. NewsSource is renamed to Source.
  • Newly added on-by-default Sources switch on once; saved toggles are kept, and toggles for removed Sources are cleaned up (#1).
  • New Learn tab (Today · Briefing · Learn · Sources · Settings) with a Learning section (14 days) and a Fun section (3 days); Today and the Briefing use News sources only (#2, #3).
  • Sources tab grouped by kind; custom feeds get a kind picker (#4).
  • Catalog: 42 curated Sources (23 News, 16 Learning, 3 Fun). Added Techmeme, Lobsters, The Decoder, Simon Willison; Hacker News filtered to 150+ points; WIRED and Engadget removed (#5, #6, #3).
  • Reader view shows comics whole, with xkcd's title text as caption (#3).
  • "Hide paid articles" also hides paid Substack posts (#7).
  • Code-review fixes: README brought up to date, glossary vocabulary, per-kind facts on SourceKind, shared Today/Learn list scaffolding, tolerant Substack link matching.

Checks: flutter test 73 passed (3 live tests skipped), flutter analyze clean, live feed test passes for all 42 Sources.

Closes #1
Closes #2
Closes #3
Closes #4
Closes #5
Closes #6
Closes #7

#8 (reading list) stays open; it needs triage first.

🤖 Generated with Claude Code

Implements the source-kinds plan from the grilling session (terms in `GLOSSARY.md`). - Every Source is a News, Learning or Fun source. `NewsSource` is renamed to `Source`. - Newly added on-by-default Sources switch on once; saved toggles are kept, and toggles for removed Sources are cleaned up (#1). - New **Learn** tab (Today · Briefing · Learn · Sources · Settings) with a Learning section (14 days) and a Fun section (3 days); Today and the Briefing use News sources only (#2, #3). - Sources tab grouped by kind; custom feeds get a kind picker (#4). - Catalog: 42 curated Sources (23 News, 16 Learning, 3 Fun). Added Techmeme, Lobsters, The Decoder, Simon Willison; Hacker News filtered to 150+ points; WIRED and Engadget removed (#5, #6, #3). - Reader view shows comics whole, with xkcd's title text as caption (#3). - "Hide paid articles" also hides paid Substack posts (#7). - Code-review fixes: README brought up to date, glossary vocabulary, per-kind facts on `SourceKind`, shared Today/Learn list scaffolding, tolerant Substack link matching. Checks: `flutter test` 73 passed (3 live tests skipped), `flutter analyze` clean, live feed test passes for all 42 Sources. Closes #1 Closes #2 Closes #3 Closes #4 Closes #5 Closes #6 Closes #7 #8 (reading list) stays open; it needs triage first. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Cedric added 2 commits 2026-10-16 15:36:23 +02:00
The app now remembers which curated Sources it has seen. A Source that is on
by default is enabled the first time it appears, also on installs with saved
toggles; Sources seen before keep the user's choice. Installs from before this
change count the current catalog as seen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cedric added 1 commit 2026-10-16 15:42:41 +02:00
Adds Techmeme, Lobsters, The Decoder and Simon Willison, all on by default.
Hacker News now reads hnrss.org's front page with 150+ points. t3n,
ComputerBase, TechCrunch and The Verge stay in the catalog but are off by
default. heise Security and heise Developer are described as sections of
heise online. WIRED and Engadget are removed.

Saved toggles for Sources that are no longer in the catalog are dropped on
launch, so they don't count towards "n of m enabled". The README source
table matches the catalog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cedric added 2 commits 2026-10-16 15:46:45 +02:00
Every Source now has a kind: News, Learning or Fun. Curated Sources default
to News, and custom Sources persist their kind (ones saved before default
to News). Each kind has its own time window: News follows the 12/24/48 h
setting, Learning reaches back 14 days, Fun 3 days.

A new Learn tab between Briefing and Sources lists Learning articles with
the same paid/sponsored filters and reader view as Today. It is built from
a list of kinds so a Fun section can follow. Today and the Briefing only
use News. ByteByteGo is the first Learning source, on by default.

The home shell names its tabs instead of using hard-coded indexes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in the News catalog update (#5). ByteByteGo joins the expected
on-by-default sets for updated installs, and the catalog test checks the
on-by-default set among News sources.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cedric added 1 commit 2026-10-16 15:51:29 +02:00
The Sources tab shows News, Learning and Fun sections, each split by
language; kinds or languages without Sources get no header. The add-feed
dialog has a kind picker that defaults to News.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cedric added 2 commits 2026-10-16 15:52:12 +02:00
Fifteen English Learning sources join ByteByteGo in the catalog: System
Design One, The Pragmatic Engineer (blog), Martin Fowler, Julia Evans,
Dan Luu, The Cloudflare Blog, Netflix Technology Blog, Engineering at
Meta, GitHub Blog: Engineering, Latent Space, Import AI, Interconnects,
Ahead of AI and Lilian Weng (on by default), and InfoQ (off).

Tests pin the Learning catalog, check that existing installs get the
new on-by-default Sources and that the Learn tab shows their posts from
the last 14 days. A live test times a full refresh. The README gets a
Learn feature bullet and a Learning sources table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cedric added 1 commit 2026-10-16 15:58:35 +02:00
Substack cuts paid-subscriber posts short in the feed and ends their
content with a "Read more" link to the post itself. PaywallService.isPaid
now recognizes that ending, so "hide paid articles" hides these posts in
Today and the Learn tab and counts them as hidden, without a page request.
Free posts that ask readers to subscribe or end with the subscribe widget
are not affected.

Tests use trimmed real items from the Interconnects and Ahead of AI feeds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cedric added 3 commits 2026-10-16 15:59:15 +02:00
The Learn tab gets a Fun section below Learning with the last 3 days of
Fun articles. Fun articles stay out of Today and the Briefing. New curated
Fun sources: xkcd and The Daily WTF (on by default) and r/ProgrammerHumor
top of the day (off).

Reader view for Fun articles shows the picture whole in the body instead
of as a 16:9 banner cropped to fit, and doesn't call a comic without text
a teaser. When the page gives no picture (Reddit blocks reader view), the
feed's image is shown. The extractor now keeps an image's title text as a
caption (xkcd's last joke), images in blockquotes and behind in-page
anchors (The Daily WTF's Error'd screenshots), drops image maps and
license boxes, and on a text tie prefers the page with more blocks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keeps the Learning catalog from #6 and puts the Fun group after it, in the
catalog and the README. Adds the end-to-end check #4 left for Fun: a custom
Fun feed added on the Sources tab shows up in the Learn tab's Fun section,
not in Today.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cedric marked the pull request as ready for review 2026-10-16 16:11:03 +02:00
Cedric added 6 commits 2026-10-16 16:11:03 +02:00
The class and its file (lib/models/source.dart) follow the glossary term.
Persisted JSON keys are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A trailing slash, tracking query, fragment, other scheme or host case on
either link no longer lets a paid post through the paid filter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- SourceKind carries whether it feeds the Briefing, its fixed time window
  (Learning, Fun) and whether reading is picture-led (Fun); windowOf and
  the reader read from it.
- AppState.briefingArticles is the one place that says only News sources
  feed the Briefing; generateBriefing and the Briefing tab use it.
- articlesOf, hiddenCountOf and briefingArticles share one filter.
- FeedService.fetchAll takes windowOf: like AppState.windowOf.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
articleCountLine, RefreshButton and RefreshableList live in common.dart.
LearnScreen._describe becomes _windowLabel there, and LearnScreen._section
is _kindSection like in SourcesScreen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
"Feed" no longer stands for a Source and "newsletter" no longer for a
Learning source; paid_newsletter_posts_test.dart becomes
paid_substack_posts_test.dart.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The catalog has 42 Sources (13 German, 29 English; 23 News, 16 Learning,
3 Fun). Today shows News sources only, Learn has a Learning (14 days) and
a Fun (3 days) section, neither feeds the Briefing, and the time window
setting is for News. The project layout lists the UI files including
learn_screen.dart.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
You are not authorized to merge this pull request.
This pull request can be merged automatically.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feature/source-kinds:feature/source-kinds
git checkout feature/source-kinds
Sign in to join this conversation.