| Age | Commit message (Collapse) | Author |
|
Feeds like West Hawaii Today need Readability to strip a paywall/
boilerplate wrapper, and that extraction was happening lazily the
first time an article was opened -- a hidden WebView load + JS eval
that left the reader sitting on a spinner. Do it for new articles from
reader-mode feeds right inside FeedFetchWorker.fetchOne instead, so
it's already cached (both on the launch fetch and the 5am morning
fetch) by the time the article is actually opened.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017GMEkHeqKz6FLkmizowBTK
|
|
Reverts part of the previous commit: the explicit refresh button and
fetch-on-launch stay, but the user still wants the background 5am alarm so
articles are fresh before the app is opened, not just the periodic hourly
WorkManager job.
|
|
Periodic hourly WorkManager fetches and the 5am exact-alarm morning fetch
both refreshed without any visible trigger, which surprised the user more
than it helped. Refreshing now only ever happens on a fresh app launch
(MainActivity.onCreate) or an explicit tap of the new refresh button on the
Unread/Older screens' top bar (wired to the fetch-status state that was
already being computed there but never rendered). Drops MorningFetchReceiver
entirely along with its exact-alarm permission and boot receiver.
|
|
FeedFetchWorker's periodic 60-minute WorkManager job can (and does)
get silently deferred for hours by Doze on an idle overnight device.
An exact alarm (setExactAndAllowWhileIdle) wakes the device at a fixed
5am to run a fetch, without requesting the much broader "ignore
battery optimizations" exemption -- battery optimization stays on
otherwise, just this one daily wake-up.
Android 12+ requires a one-time user grant for exact alarms (no in-app
permission dialog); MainActivity requests it via Settings if not
already granted, tracked across rotation via savedInstanceState so a
config change doesn't re-trigger the Settings screen. The alarm also
gets re-armed on BOOT_COMPLETED, since AlarmManager alarms don't
survive a device restart on their own.
|
|
Feeds are fetched with bounded concurrency (semaphore of 8) instead of
strictly sequentially -- with 100+ subscriptions, one slow/stalling
server no longer delays every feed queued behind it. A process-local
mutex prevents the periodic and manual/alarm-triggered one-time
fetches (two different WorkManager unique-work names, so its own dedup
doesn't cover this) from ever running concurrently and racing writes
to the same feed rows.
Settings.recordFetchResult persists lastFetchAt/lastFetchNewArticles
on every run, not derived from WorkInfo.State -- a PeriodicWorkRequest
cycles back to ENQUEUED after every successful run and never reaches
SUCCEEDED, so anything watching for that only ever saw manual fetches.
ArticleListScreen surfaces this as a "N new articles" snackbar
(acknowledged durably, so returning to the screen doesn't re-show it)
and computes live "Checking feed X of Y" progress from the worker's
tagged WorkInfo, scoped to the Unread/Older views that actually
aggregate every subscription.
|
|
- 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
<img> 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->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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL
|
|
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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL
|