summaryrefslogtreecommitdiff
path: root/app/src/main/java/org/terst/feedreader/data
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-07-23 07:38:28 +0000
committerPeter Stone <thepeterstone@gmail.com>2026-07-23 07:38:28 +0000
commitecdb45778e274126737aa87e27ed1b1c00cda01c (patch)
treeb632e53bc91475ba49094539e04b51e7a5eaa41c /app/src/main/java/org/terst/feedreader/data
parent3bec692d9613b9b3e688441e5945424bd0fe20f0 (diff)
Rebrand to FeeDreader; overflow-menu cleanup; deferred read-marking; folder-organized feed list
- 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 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL
Diffstat (limited to 'app/src/main/java/org/terst/feedreader/data')
-rw-r--r--app/src/main/java/org/terst/feedreader/data/AppDatabase.kt13
-rw-r--r--app/src/main/java/org/terst/feedreader/data/Daos.kt9
-rw-r--r--app/src/main/java/org/terst/feedreader/data/Entities.kt1
3 files changed, 19 insertions, 4 deletions
diff --git a/app/src/main/java/org/terst/feedreader/data/AppDatabase.kt b/app/src/main/java/org/terst/feedreader/data/AppDatabase.kt
index 66722fd..3367a71 100644
--- a/app/src/main/java/org/terst/feedreader/data/AppDatabase.kt
+++ b/app/src/main/java/org/terst/feedreader/data/AppDatabase.kt
@@ -9,7 +9,7 @@ import androidx.room.migration.Migration
@Database(
entities = [FeedEntity::class, ArticleEntity::class, FilterRuleEntity::class],
- version = 5,
+ version = 6,
exportSchema = false
)
abstract class AppDatabase : RoomDatabase() {
@@ -90,12 +90,21 @@ abstract class AppDatabase : RoomDatabase() {
}
}
+ // v6: added FeedEntity.folder (OPML category, for grouping the feed list). A plain
+ // ADD COLUMN is safe here (unlike v3->v4) since folder is a genuinely new field with
+ // no prior column it needs to replace/rebuild around.
+ private val MIGRATION_5_6 = object : Migration(5, 6) {
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("ALTER TABLE feeds ADD COLUMN folder TEXT")
+ }
+ }
+
fun get(context: Context): AppDatabase = instance ?: synchronized(this) {
instance ?: Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"feedreader.db"
- ).addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5).build().also { instance = it }
+ ).addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5, MIGRATION_5_6).build().also { instance = it }
}
}
}
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 22f1d22..0b763e1 100644
--- a/app/src/main/java/org/terst/feedreader/data/Daos.kt
+++ b/app/src/main/java/org/terst/feedreader/data/Daos.kt
@@ -10,10 +10,10 @@ import kotlinx.coroutines.flow.Flow
@Dao
interface FeedDao {
- @Query("SELECT * FROM feeds ORDER BY title ASC")
+ @Query("SELECT * FROM feeds ORDER BY title COLLATE NOCASE ASC")
fun observeAll(): Flow<List<FeedEntity>>
- @Query("SELECT * FROM feeds ORDER BY title ASC")
+ @Query("SELECT * FROM feeds ORDER BY title COLLATE NOCASE ASC")
suspend fun getAll(): List<FeedEntity>
@Query("SELECT * FROM feeds WHERE id = :id")
@@ -98,6 +98,11 @@ interface ArticleDao {
@Query("SELECT $ARTICLE_LIST_COLUMNS FROM $ARTICLE_LIST_FROM WHERE articles.isSaved = 1 ORDER BY articles.createdAt DESC")
fun observeSaved(): Flow<List<ArticleListItem>>
+ // The Saved count is a "how much is on my shelf" total, not an unread badge --
+ // includes already-read articles, unlike every other count in this DAO.
+ @Query("SELECT COUNT(*) FROM articles WHERE isSaved = 1")
+ fun observeSavedCount(): Flow<Int>
+
@Query("SELECT * FROM articles WHERE id = :id")
suspend fun getById(id: String): ArticleEntity?
diff --git a/app/src/main/java/org/terst/feedreader/data/Entities.kt b/app/src/main/java/org/terst/feedreader/data/Entities.kt
index f4be19e..5f6a28c 100644
--- a/app/src/main/java/org/terst/feedreader/data/Entities.kt
+++ b/app/src/main/java/org/terst/feedreader/data/Entities.kt
@@ -13,6 +13,7 @@ data class FeedEntity(
val etag: String? = null, // conditional-GET caching (If-None-Match) to avoid re-downloading unchanged feeds
val lastModified: String? = null, // conditional-GET caching (If-Modified-Since)
val lastError: String? = null, // set when a fetch fails; cleared on the next successful fetch
+ val folder: String? = null, // OPML category/outline this feed was imported under, if any -- null for ungrouped feeds
val readerModeEnabled: Boolean = false // per-feed opt-IN, set only by explicitly tapping the reader-mode
// toggle (never automatic/heuristic) -- once on, articles from this feed default to the
// extracted view and auto-extract on open instead of requiring a per-article tap each time.