| Age | Commit message (Collapse) | Author |
|
Peter, three builds running: audio plays, YouTube's title, controls and
scrubber thumbnails all draw, and where the picture belongs there is a
blank rectangle.
None of my guesses were right. It is not the embed, not the window, and
not the surface. It is layout. YouTube's player sizes itself with
`body { position: absolute; height: 100% }`, and in this WebView
percentage heights resolve against a containing block of zero height.
Measured in the running app: window.innerHeight correctly reports 214,
while 100vh and every percentage height resolve to 0. The body
collapsed, the player chain under it collapsed, and the video element
was laid out 380x0.
That explains the whole symptom, including the part I kept failing to
account for. The page, the chrome and the stream were all healthy --
the picture simply had nowhere to go, and what showed through the
zero-height player was YouTube's own white <html> background.
So the fix pins the player chain to the pixel height the page does
know and dispatches a resize so YouTube's own code re-measures.
Verified on a device, with the shipped code and nothing injected by
hand: the video element goes 380x0 -> 380x214 and the video plays.
Two things ruled out along the way, recorded so they are not retried:
hardware-accelerating the dialog's window changed nothing, and nor did
moving the player out of a dialog into an in-window overlay. An A/B
against BrowserScreen looked decisive for the window and was not --
that WebView differs in layout too, and layout was the real variable.
This treats the symptom. Why the viewport has no height is below this
app, in WebView.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
- 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.
|
|
- 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.
|
|
- 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).
|
|
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
|