diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-07-22 16:54:03 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-07-22 16:54:03 +0000 |
| commit | 39cca1cb3650edb066f57d0891b1873b767b1c43 (patch) | |
| tree | 0a966be07f4d4440cfad0f4eeb8bffd1617f3ea0 /app/src/main/java/org/terst/feedreader/data/Daos.kt | |
| parent | 52d7877fccd60a1dae33d877ba6aa765dc098a52 (diff) | |
Fix Unread/startup crash; add reader-mode toggle and swipe navigation
- Root cause of the reported crashes: observeUnread/observeByFeed/
observeSaved used SELECT *, pulling feedContentHtml/extractedContent
(potentially large per-article blobs) just to render a list row.
With 107 feeds worth of real articles this blows past Android's
CursorWindow/memory limits, scaling with item count -- and since
Unread is now the landing screen, it crashed at startup too. Added
an ArticleListItem projection excluding the heavy content columns;
list queries now only select what a row actually renders.
- FilterRuleEngine now takes a small Titled interface (title/feedId)
instead of the full entity, so it works with both ArticleEntity and
the new lighter projection.
- Reader-mode toggle: a button in the reader to manually switch
between feed-provided content and Readability-extracted full text,
matching Inoreader's full-text-view toggle (previously only an
automatic fallback when feed content was thin).
- Swipe between articles: ReaderScreen now wraps a HorizontalPager over
a snapshot of the current list's article-id order, so swiping moves
to the next/previous article. Snapshotted rather than live, since
marking an article read would otherwise drop it from the live Unread
query mid-swipe and shift every later page underneath the user.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL
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 | 35 |
1 files changed, 29 insertions, 6 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 2240ff4..f80cce3 100644 --- a/app/src/main/java/org/terst/feedreader/data/Daos.kt +++ b/app/src/main/java/org/terst/feedreader/data/Daos.kt @@ -31,20 +31,43 @@ interface FeedDao { data class FeedUnreadCount(val feedId: String, val count: Int) +// A projection excluding feedContentHtml/extractedContent -- the potentially +// large per-article content blobs that list views (row title/date/thumbnail) +// never need. Selecting them for every row of a big result set is what was +// crashing the Unread view once real feed volume (107 feeds worth of +// articles) hit it: Android's per-row/CursorWindow limits are sized for +// "many small rows," not "many rows each carrying a full article's HTML." +data class ArticleListItem( + val id: String, + override val feedId: String?, + override val title: String, + val link: String, + val author: String?, + val publishedAt: Long?, + val imageUrl: String?, + val isRead: Boolean, + val isSaved: Boolean, + val stashArtifactId: String?, + val createdAt: Long +) : Titled + +private const val ARTICLE_LIST_COLUMNS = + "id, feedId, title, link, author, publishedAt, imageUrl, isRead, isSaved, stashArtifactId, createdAt" + @Dao interface ArticleDao { // Unread-first, newest-first -- the default "what's new" view across every feed. - @Query("SELECT * FROM articles WHERE isRead = 0 ORDER BY publishedAt DESC") - fun observeUnread(): Flow<List<ArticleEntity>> + @Query("SELECT $ARTICLE_LIST_COLUMNS FROM articles WHERE isRead = 0 ORDER BY publishedAt DESC") + fun observeUnread(): Flow<List<ArticleListItem>> @Query("SELECT feedId, COUNT(*) as count FROM articles WHERE isRead = 0 AND feedId IS NOT NULL GROUP BY feedId") fun observeUnreadCounts(): Flow<List<FeedUnreadCount>> - @Query("SELECT * FROM articles WHERE feedId = :feedId ORDER BY publishedAt DESC") - fun observeByFeed(feedId: String): Flow<List<ArticleEntity>> + @Query("SELECT $ARTICLE_LIST_COLUMNS FROM articles WHERE feedId = :feedId ORDER BY publishedAt DESC") + fun observeByFeed(feedId: String): Flow<List<ArticleListItem>> - @Query("SELECT * FROM articles WHERE isSaved = 1 ORDER BY createdAt DESC") - fun observeSaved(): Flow<List<ArticleEntity>> + @Query("SELECT $ARTICLE_LIST_COLUMNS FROM articles WHERE isSaved = 1 ORDER BY createdAt DESC") + fun observeSaved(): Flow<List<ArticleListItem>> @Query("SELECT * FROM articles WHERE id = :id") suspend fun getById(id: String): ArticleEntity? |
