<feed xmlns='http://www.w3.org/2005/Atom'>
<title>feedreader.git/app/src/main/java/org/terst/feedreader/ui/AddFeedScreen.kt, branch master</title>
<subtitle>FeeDreader — personal Android RSS reader
</subtitle>
<id>https://git.terst.org/feedreader.git/atom?h=master</id>
<link rel='self' href='https://git.terst.org/feedreader.git/atom?h=master'/>
<link rel='alternate' type='text/html' href='https://git.terst.org/feedreader.git/'/>
<updated>2026-10-21T19:07:17+00:00</updated>
<entry>
<title>Fix stray promo headers, site-URL subscribing, and YouTube playback</title>
<updated>2026-10-21T19:07:17+00:00</updated>
<author>
<name>Peter Stone</name>
<email>thepeterstone@gmail.com</email>
</author>
<published>2026-10-21T19:07:17+00:00</published>
<link rel='alternate' type='text/html' href='https://git.terst.org/feedreader.git/commit/?id=9210bf463a8818595f7ca42486a787d4f1941d55'/>
<id>urn:sha1:9210bf463a8818595f7ca42486a787d4f1941d55</id>
<content type='text'>
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 &lt;link rel="alternate"&gt; 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 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
</content>
</entry>
<entry>
<title>Feed writes: bulk OPML upsert, targeted fetch-result update, shared toggle</title>
<updated>2026-08-22T01:01:05+00:00</updated>
<author>
<name>Peter Stone</name>
<email>thepeterstone@gmail.com</email>
</author>
<published>2026-08-22T01:01:05+00:00</published>
<link rel='alternate' type='text/html' href='https://git.terst.org/feedreader.git/commit/?id=a3296f5c14a5fb95feaa3751044a1995935e6f3e'/>
<id>urn:sha1:a3296f5c14a5fb95feaa3751044a1995935e6f3e</id>
<content type='text'>
- AddFeedScreen: OPML import no longer crashes the app on a
  non-XML/corrupt file (try/catch around the whole import). Bulk
  upsertAll() instead of a per-feed getById()+upsert() loop -- 2N
  sequential DB round-trips for N feeds otherwise, real cost at 100+
  feed subscription lists.
- FeedDao.updateFetchResult only writes the columns a fetch actually
  produces, instead of a full-row @Update built from a feed snapshot
  read before a (possibly slow) network round-trip -- the old path
  could silently revert a readerModeEnabled/folder edit made via
  FeedListScreen while that feed's fetch was still in flight.
- setReaderModeEnabled(feed, enabled) persists the toggle and returns
  the exact confirmation text, shared by FeedListScreen's per-row
  toggle and ReaderScreen's toggleFeedReaderMode -- previously two
  independently-typed copies of the same snackbar message.
</content>
</entry>
<entry>
<title>Migrate http:// feeds to https:// where it actually works; add feeds as https-only going forward</title>
<updated>2026-07-25T01:30:21+00:00</updated>
<author>
<name>Peter Stone</name>
<email>thepeterstone@gmail.com</email>
</author>
<published>2026-07-25T01:30:21+00:00</published>
<link rel='alternate' type='text/html' href='https://git.terst.org/feedreader.git/commit/?id=72214b9d3617a66a70727819dbf7fe59ea037264'/>
<id>urn:sha1:72214b9d3617a66a70727819dbf7fe59ea037264</id>
<content type='text'>
Android blocks cleartext by default (targetSdk 28+), so every http:// feed was
failing every single fetch ("CLEARTEXT communication ... not permitted"). Checked
each of this user's 9 http feeds live via curl:

- 6 work fine over https (5 are a plain scheme swap; divingforpearlsblog.com's own
  https endpoint redirects through an insecure feedburner hop, so that one points
  straight at feedburner's https endpoint instead) -- migrated via a new Room
  migration (v6-&gt;v7), rewriting both the feed row and its articles' feedId so
  read history isn't orphaned. Confirmed live: all 6 now fetch clean with no
  lastError.
- 3 have no usable https at all (bit-player.org: connection refused, no TLS
  listener; blog.securitymouse.com: broken TLS handshake; webpolicy.org: a
  certificate that doesn't match the hostname) and are deliberately left alone.

Going forward, adding a feed (manually or via OPML import) upgrades a given
http:// URL to https:// before using it -- most sites serve identical content
either way, and a site with no real https support just fails its very next
fetch attempt the normal way instead of silently subscribing to a feed that
can never actually update.

Co-Authored-By: Claude Sonnet 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL
</content>
</entry>
<entry>
<title>Rebrand to FeeDreader; overflow-menu cleanup; deferred read-marking; folder-organized feed list</title>
<updated>2026-07-23T07:38:28+00:00</updated>
<author>
<name>Peter Stone</name>
<email>thepeterstone@gmail.com</email>
</author>
<published>2026-07-23T07:38:28+00:00</published>
<link rel='alternate' type='text/html' href='https://git.terst.org/feedreader.git/commit/?id=ecdb45778e274126737aa87e27ed1b1c00cda01c'/>
<id>urn:sha1:ecdb45778e274126737aa87e27ed1b1c00cda01c</id>
<content type='text'>
- 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 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL
</content>
</entry>
<entry>
<title>Fix scroll regression and feed-setting reset on re-import</title>
<updated>2026-07-22T19:14:44+00:00</updated>
<author>
<name>Peter Stone</name>
<email>thepeterstone@gmail.com</email>
</author>
<published>2026-07-22T19:14:44+00:00</published>
<link rel='alternate' type='text/html' href='https://git.terst.org/feedreader.git/commit/?id=7b0be4757356af46df1eb55d596f819c21b00f3e'/>
<id>urn:sha1:7b0be4757356af46df1eb55d596f819c21b00f3e</id>
<content type='text'>
- ReaderScreen: the direction-ratio gesture rewrite (using a generic,
  non-oriented detectDragGestures to compute a custom dx/dy ratio) broke
  scrolling entirely -- reported live as "the article view doesn't scroll
  at all anymore." Root cause: detectDragGestures' touch-slop detection is
  isotropic (claims the first bit of movement in ANY direction before it
  knows which way the gesture is going), unlike detectHorizontalDragGestures
  which is orientation-aware and simply never engages for a vertical-
  dominant drag. Reverted to detectHorizontalDragGestures, keeping the
  distance-based (not edge-anchored) commit threshold from the previous
  fix. Verified live: a long article now scrolls properly on a diagonal
  swipe, and a deliberate horizontal swipe still changes pages.

- AddFeedScreen: both the OPML import and single-URL add built a bare
  FeedEntity(id, title, siteUrl) and upserted it (REPLACE) even when a
  feed with that id already existed -- silently wiping readerModeDisabled
  (and etag/lastModified/lastError) back to defaults on every re-import or
  re-add. This is exactly what made a feed's reader-mode toggle appear not
  to persist. Now preserves the existing row via .copy() when one exists.
  Verified live: set kottke.org's readerModeDisabled=1, re-imported the
  same OPML file (107 feeds), and confirmed the flag was still 1 afterward.
</content>
</entry>
<entry>
<title>First round of testing feedback: images, unread landing, dark, delete</title>
<updated>2026-07-22T16:26:45+00:00</updated>
<author>
<name>Peter Stone</name>
<email>thepeterstone@gmail.com</email>
</author>
<published>2026-07-22T16:26:45+00:00</published>
<link rel='alternate' type='text/html' href='https://git.terst.org/feedreader.git/commit/?id=52d7877fccd60a1dae33d877ba6aa765dc098a52'/>
<id>urn:sha1:52d7877fccd60a1dae33d877ba6aa765dc098a52</id>
<content type='text'>
- Fix OPML import status message reporting the raw pre-dedup count
  (144) instead of the actual unique feed count after Room's upsert
  collapses duplicates (108) -- cosmetic bug, the DB was already
  correct.
- Article thumbnails: extract media:thumbnail/enclosure or the first
  &lt;img&gt; in feed content, show via Coil in the article list.
- App now lands on Unread instead of the feed list; a top-bar icon
  gets from there to the feed list (forward nav, not back-stack pop,
  since Unread is now the root).
- Dark color scheme by default.
- Delete-feed action (with confirmation) on each feed row -- was
  entirely missing. Deletes its non-saved articles too, so they don't
  linger as orphaned rows in the cross-feed Unread view; saved articles
  are kept regardless.
- Room migration 1-&gt;2 for the new imageUrl column (real migration, not
  destructive fallback, since there's now real on-device subscription
  data from testing).

Co-Authored-By: Claude Sonnet 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL
</content>
</entry>
<entry>
<title>Initial commit: Feeds, an Android RSS reader</title>
<updated>2026-07-22T08:08:58+00:00</updated>
<author>
<name>Peter Stone</name>
<email>thepeterstone@gmail.com</email>
</author>
<published>2026-07-22T08:08:58+00:00</published>
<link rel='alternate' type='text/html' href='https://git.terst.org/feedreader.git/commit/?id=d8ce4b3c0f383e844b125d2d3abd618715bb3c89'/>
<id>urn:sha1:d8ce4b3c0f383e844b125d2d3abd618715bb3c89</id>
<content type='text'>
Feed subscriptions (RSS 2.0 + Atom, hand-rolled parser), OPML
import/export, WorkManager periodic fetch with conditional GET,
Room-backed local storage (feeds/articles/filter rules), keyword
mute/highlight filtering.

Reader mode: on-device extraction via Mozilla's Readability.js
(vendored from github.com/mozilla/readability, pinned to release
0.6.0) run in a hidden WebView, for feed articles whose provided
content is too thin to be the real article body.

Save: explicit action (from a feed article, or the Android share-sheet
target for any URL) archives to Stash via POST /artifacts?sync=true,
while a local on-device copy (Readability-extracted) is always kept so
saved articles read offline regardless of Stash's reachability.

Co-Authored-By: Claude Sonnet 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL
</content>
</entry>
</feed>
