diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-08-22 01:01:05 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-08-22 01:01:05 +0000 |
| commit | a3296f5c14a5fb95feaa3751044a1995935e6f3e (patch) | |
| tree | 6e1c1399c1a04ef4c7f24b573e48fd7de4f6d547 /app/src/main/java/org/terst/feedreader/data/Daos.kt | |
| parent | fd49bacfb92ef8d29cbad56419acd016ff40f357 (diff) | |
Feed writes: bulk OPML upsert, targeted fetch-result update, shared toggle
- 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.
Diffstat (limited to 'app/src/main/java/org/terst/feedreader/data/Daos.kt')
| -rw-r--r-- | app/src/main/java/org/terst/feedreader/data/Daos.kt | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/app/src/main/java/org/terst/feedreader/data/Daos.kt b/app/src/main/java/org/terst/feedreader/data/Daos.kt index 8a5f50e..ecaac43 100644 --- a/app/src/main/java/org/terst/feedreader/data/Daos.kt +++ b/app/src/main/java/org/terst/feedreader/data/Daos.kt @@ -22,13 +22,55 @@ interface FeedDao { @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun upsert(feed: FeedEntity) + // Batched, not one upsert() call per feed in a loop: an OPML import can realistically + // be 100+ feeds (this app has seen a 107-feed subscription list in the wild -- see + // AppDatabase's v9 migration comments), and a per-feed getById()+upsert() pair is 2N + // sequential suspend DB round-trips for N feeds. One @Insert(REPLACE) call covers the + // whole list. + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun upsertAll(feeds: List<FeedEntity>) + @Update suspend fun update(feed: FeedEntity) + // Targeted, not the full-row @Update above: FeedFetchWorker reads every subscribed + // feed once at the start of a fetch cycle, then (after a per-feed network round-trip + // that can take a while, especially across 100+ feeds) writes back a `.copy()` of + // that now-possibly-stale snapshot. If the user toggles readerModeEnabled or edits a + // feed's folder via FeedListScreen while that feed's fetch is still in flight, a + // full-row update() overwrites the WHOLE row from the stale pre-fetch copy -- + // including the field the user just changed -- silently reverting their edit. This + // only ever touches the columns a fetch actually produces, so it can't clobber + // anything the user might be changing concurrently. + @Query( + "UPDATE feeds SET title = :title, siteUrl = :siteUrl, lastFetchedAt = :lastFetchedAt, " + + "etag = :etag, lastModified = :lastModified, lastError = :lastError WHERE id = :id" + ) + suspend fun updateFetchResult( + id: String, + title: String, + siteUrl: String?, + lastFetchedAt: Long, + etag: String?, + lastModified: String?, + lastError: String? + ) + @Query("DELETE FROM feeds WHERE id = :id") suspend fun delete(id: String) } +// Persists the toggle and returns the exact confirmation-snackbar text, shared by +// FeedListScreen's per-row toggle and ReaderScreen's toggleFeedReaderMode (which layers +// its own extraction logic around this same persist-and-message step) -- previously two +// independently-typed copies of "Reader mode enabled/disabled for $label", one edit away +// from silently drifting to say different things for the same action. +suspend fun FeedDao.setReaderModeEnabled(feed: FeedEntity, enabled: Boolean): String { + update(feed.copy(readerModeEnabled = enabled)) + val label = feed.title.ifBlank { "this feed" } + return if (enabled) "Reader mode enabled for $label" else "Reader mode disabled for $label" +} + data class FeedUnreadCount(val feedId: String, val count: Int) // A projection excluding feedContentHtml/extractedContent -- the potentially |
