summaryrefslogtreecommitdiff
path: root/BACKLOG.md
AgeCommit message (Collapse)Author
2026-10-22Plan: gift links in the reader, and whether to use kottke's PrometheusPeter Stone
Research + plan document only, no code. Covers what Prometheus actually is (member-only beta gift-link search at kottke.org/prometheus, no API, no RSS, no terms page -- all verified at the source, including 404s on every plausible endpoint), where a gift-link action would slot into the existing reader ("Find another source" in ReaderScreen/LinkReaderScreen overflow, the process-wide CookieManager seam BrowserScreen already documents), and what it would cost. Recommends NOT building against Prometheus: it is member-only (Peter isn't a member), one day old, and the only available integration would be scraping a members-only page. Recommends instead subscribing to the public sources it harvests -- mastodon.social's #giftlink RSS and the public Bluesky gift-link feed, both verified reachable unauthenticated -- and waiting for Prometheus to ship a feed or a URL-lookup endpoint before building anything. Two findings worth keeping either way: the app has no paywall state at all (a paywalled page lands as NoContent or a successful teaser extraction, and ReaderExtractor's own comment records why thin-result detection must stay narrow), so there is no reliable automatic trigger for a gift-link offer; and Mastodon tag feeds carry no <item><title>, which FeedParser leaves as "", so subscribing to #giftlink today would show blank titles. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
2026-10-21Play the YouTube embed with a referrer instead of in an iframePeter Stone
Peter, on the previous build: "the inline player now plays the audio but the video is a black screen." So Error 153 is gone and the stream is decoding -- what is left is a display problem. The iframe was not needed in the first place. A `Referer` header alone satisfies the embed, which means the player can be the WebView's own ordinary top-level document again. That drops two constructs the last build added: a `loadDataWithBaseURL` page, whose origin is synthetic, and a cross-origin subframe inside it. Both have a history of rendering video oddly in WebView, and the black screen appeared with them. Measured on an Android user agent -- no referrer: Error 153; `&origin=` in the query: Error 153; inside an iframe: plays; with a `Referer` header: plays. The referrer is a constant on a reserved `.invalid` domain rather than the article's URL, so YouTube learns which app asked and nothing about what is being read -- the same reason the nocookie domain is used. Confirmed in the app's own WebView: the embed loads with no error, 854x480, readyState 4, playing. NOT confirmed: that a picture now reaches the screen. This emulator cannot render video in a WebView at all -- it hard-crashed the AVD twice, including on a plain <video> in an ordinary non-dialog WebView -- so the one thing that matters here can only be checked on real hardware. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
2026-10-21Fix stray promo headers, site-URL subscribing, and YouTube playbackPeter Stone
Three reported bugs. **"West Hawaii today articles get a bunch of stray Trending headers."** The publisher's widget platform injects promo blocks between the real paragraphs, inside the article's own container, so every structural signal tells Readability they belong. What survives is a heading labelling nothing, because the links under it are filled in by a script that never runs in the reader. Confirmed on 9 of the 12 articles in that feed, two each. Blocks marked `data-mrf-recirculation` are now removed -- the attribute says what the block is for in the widget platform's own words, which is a better signal than the word "Trending", since an article may legitimately discuss what is trending. Nothing longer than a label and a few headlines is ever removed. Also applied to already-cached articles, in place rather than by discarding them: the article was fine, only the litter has to go. **"Can't subscribe to heathercoxrichardson.substack.com."** Adding a feed handed whatever URL it was given straight to the XML parser, so a site's home page -- the only URL a reader can actually see and copy -- failed on the root element. That page advertises its feed the way sites have since 2002, in a <link rel="alternate"> in the head. It is now read, resolved against the page, and fetched. Only what the page declares: guessing /feed and /rss would add a burst of 404s to every failed add and eventually subscribe somebody to the wrong thing. **"YouTube play is misconfigured."** It was, and YouTube said so: the player dialog loaded the embed as its own top-level document, which answers with "Video player configuration error -- Error 153". An embed has to be embedded. It now sits in an iframe on a minimal host page. Measured in the app's own WebView: top-level, no requests for the video stream and the error on screen; framed, the stream loads and there is no error. **"Long click on YouTube placeholder should open the URL directly."** It does now. Worth recording why this is not simply the link's href: for an image inside a link, WebView's hit test reports the image's URL, so a long-press on the thumbnail arrives as the i.ytimg.com JPEG. The video id is resolved out of that. Verified on a device for all four: the Substack site URL adds "Letters from an American" and fetches 20 articles; a West Hawaii Today article extracts with no Trending headers and its body intact; the video plays; and a long-press reaches the YouTube app. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
2026-08-24Batch-upgrade dependencies: 4 of ~14 safely bumped, rest blocked on compileSdkPeter Stone
DataStore, security-crypto (out of alpha), and the two androidx.test libs upgraded cleanly. Everything else in the Compose/Activity/ Navigation/Lifecycle/Room/WorkManager family's current releases requires compileSdk 35+/AGP 8.6+ (this project is on AGP 8.3.2/ compileSdk 34) -- reverted those to original versions rather than force a much bigger AGP/compileSdk upgrade into what was scoped as a routine freshness pass. Documented as its own BACKLOG item, along with the EncryptedSharedPreferences/MasterKey deprecation the security-crypto bump surfaced. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017GMEkHeqKz6FLkmizowBTK
2026-08-24Document the bug-report clipboard tool as intentional, not unfinishedPeter Stone
An audit flagged it as looking half-built (builds a full diagnostic report but has no submission endpoint). Confirmed intentional: no backend exists to submit to on this single-user app, and the real destination is pasting it into a message during the normal hands-on-testing workflow. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017GMEkHeqKz6FLkmizowBTK
2026-08-24Mark YouTube embeds backlog item donePeter Stone
Audit found the code already fully implements this (and further than scoped: in-app playback via a sandboxed player, not just an external hand-off) -- the backlog entry was stale. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017GMEkHeqKz6FLkmizowBTK
2026-07-23Rebrand to FeeDreader; overflow-menu cleanup; deferred read-marking; ↵Peter Stone
folder-organized feed list - Rename app to FeeDreader with an owl launcher icon and a paywall-avoidance note in Settings - Move Open original/Save to Stash into the reader's overflow menu; add Mark unread there too - Only mark an article read when navigating away via Previous/Next, not on open or on back - Saved list no longer crosses out read items; its count includes them - Back from Unread (the root screen) now opens the feed list instead of exiting the app - Feed list: clearer separator above the per-feed list, folder grouping (from OPML categories) with case-insensitive sort, and a virtual "Last fetch failed" section at the top - Reader extraction: cap unsized decorative SVG icons (fixes Ars Technica's giant section-badge icon), force native loading="lazy" images to load eagerly in the hidden extraction WebView, and drop a lightbox's duplicate caption only when a real figcaption sibling exists - Backlog notes on swipe-to-next research, extraction test coverage, and an async-rendered-gallery race confirmed live on Ars Technica Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL
2026-07-23Drop swipe-to-next-article; bottom Previous/Next bar; smaller titles; bug reportPeter Stone
- Dropped swipe-to-next-article entirely, per explicit instruction. Two different fixes for the gesture interfering with WebView scrolling had already been tried and didn't resolve the reported jerkiness (one even broke swipe outright and was reverted) -- rather than keep tuning gesture detection, removed the gesture altogether. - ReaderScreen: new bottom bar with explicit Previous/Next buttons (disabled at the ends of the article queue), replacing swipe. This is the first slice of the "bottom action strip" backlog item. Verified live: Previous/Next correctly page through the article queue with the right enabled/disabled state at each end. - Smaller title text: reader top bar title (titleMedium, was TopAppBar's default titleLarge) and article list row titles (bodyMedium, was ListItem's default bodyLarge). - New "Report bug" action in the reader's overflow menu: a dialog for a short description, which gets bundled with the article's title/URL/id, feed id, reader-mode state, and save/Stash state into one text block copied to the clipboard on confirm (verified live, including the "Copied to clipboard" confirmation) -- enough to reproduce an issue in the tungsten emulator without needing live device access. - BACKLOG.md: marked the done slice of the bottom-strip item, added a note on the scroll-jerkiness investigation so far (two ruled-out theories) since swipe removal may or may not affect it -- worth a fresh look now that nothing intercepts touches above the WebView at all.
2026-07-23Fix crash on blank-guid articles; simplify browser back; backlog notesPeter Stone
- FeedParser: a feed with a literal empty <guid>/<id> element (confirmed live: a Mother Jones entry) produced an ArticleEntity with id = "" -- the fallback chain only checked for null, not blank, so an empty-but- present tag passed straight through. An empty-string primary key broke Navigation Compose's route matching and crashed on tap ("tapping this article crashes the app"). Fixed both RSS and Atom paths to treat blank the same as null before falling back to a link-based id. Schema v5 migration deletes any row already on-device with the bad id; it'll come back with a real, hash-based id on the next fetch of that feed. Verified live: zero blank-id rows after the migration and a fresh fetch, no crash. - BrowserScreen: back (both the system gesture and the in-app arrow) now always closes the screen directly, rather than stepping through in-page WebView history first. Reported live as not making sense for multi-page browsing (search results -> article -> another link, etc.) -- you'd have to tap back that many times just to leave. There's no separate in-page-back affordance now, matching how every other screen in this app behaves. - Tried moving swipe-to-next-article detection off Compose's gesture system entirely (a passive native OnTouchListener on the WebView, never consuming) on the theory that Compose's gesture arbitration was the source of reported scroll jerkiness. Reverted after confirming live that swipe stopped working at all with that approach -- a worse regression than unproven jerkiness. Back to the known-working Compose-based detector; the jerkiness complaint itself is still open. - BACKLOG.md: added bug-report-button, smaller-title-text, and bottom-action-strip-with-auto-hide notes.
2026-07-22Fix extraction regression on kottke; add Older view, mark-read-from-herePeter Stone
- ReaderExtractor: the un-hide-before-extracting fix (for soft paywalls like West Hawaii Today) was unconditional -- it also un-hid normal, legitimately-collapsed chrome (kottke's footer/membership notice), which Readability then folded into the result alongside the real article. Reported live with a screenshot showing the extracted content wrapped in site footer boilerplate. Now tries the normal (hidden-respecting) pass first and only falls back to the un-hide pass if that came back thin (<500 chars), keeping whichever pass actually found more text. Verified live: the same kottke article now stays clean and stable (no delayed switch to the footer version). - New Unread/Older split: the default Unread view is now clamped to the last 72 hours (RECENT_WINDOW_MS); the rest of the unread backlog moved to a new "Older" view (new FeedListScreen row, ArticleDao.observeUnread now takes a cutoff, observeOlderUnread/observeUnreadCount/ observeOlderUnreadCount added). Undated articles are kept in the main Unread view rather than silently dropped from both. Verified live: 150 recent / 1172 older, summing to the prior combined total. - "Mark read from here": long-press an article row to mark it and everything older in that same filtered list as read in one batch (re-added ArticleDao.markReadBatch, this time as an explicit, confirmed action -- not the implicit on-scroll version that was reverted earlier). Verified live: confirmed a 147-article batch: the tapped article and older were marked read, newer ones above it were not. - BACKLOG.md: added a YouTube-embeds note (JS is off in the reader WebView, so embeds currently show broken -- rough shape is a tap-to-play thumbnail rather than turning JS on for third-party content).
2026-07-22Add backlog note: feed health (recency/frequency, dead-feed detection)Peter Stone
Captured while migrating 108 feeds from Inoreader, which surfaced ~19 feeds manually flagged dead over there with no equivalent detection in this app yet. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL