summaryrefslogtreecommitdiff
path: root/app/src/main/java/org/terst/feedreader/data
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-08-22 01:01:05 +0000
committerPeter Stone <thepeterstone@gmail.com>2026-08-22 01:01:05 +0000
commita3296f5c14a5fb95feaa3751044a1995935e6f3e (patch)
tree6e1c1399c1a04ef4c7f24b573e48fd7de4f6d547 /app/src/main/java/org/terst/feedreader/data
parentfd49bacfb92ef8d29cbad56419acd016ff40f357 (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')
-rw-r--r--app/src/main/java/org/terst/feedreader/data/Daos.kt42
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