summaryrefslogtreecommitdiff
path: root/app/src/main/java/org/terst/feedreader/data/Daos.kt
blob: 2240ff4b6f452751a928ec2dbba128012c7b4353 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package org.terst.feedreader.data

import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Update
import kotlinx.coroutines.flow.Flow

@Dao
interface FeedDao {
    @Query("SELECT * FROM feeds ORDER BY title ASC")
    fun observeAll(): Flow<List<FeedEntity>>

    @Query("SELECT * FROM feeds ORDER BY title ASC")
    suspend fun getAll(): List<FeedEntity>

    @Query("SELECT * FROM feeds WHERE id = :id")
    suspend fun getById(id: String): FeedEntity?

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun upsert(feed: FeedEntity)

    @Update
    suspend fun update(feed: FeedEntity)

    @Query("DELETE FROM feeds WHERE id = :id")
    suspend fun delete(id: String)
}

data class FeedUnreadCount(val feedId: String, val count: Int)

@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 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 * FROM articles WHERE isSaved = 1 ORDER BY createdAt DESC")
    fun observeSaved(): Flow<List<ArticleEntity>>

    @Query("SELECT * FROM articles WHERE id = :id")
    suspend fun getById(id: String): ArticleEntity?

    // IGNORE, not REPLACE: a re-fetch of a feed re-parses items we already have:
    // this keeps the existing row (read state, extracted content, saved state)
    // untouched instead of clobbering it with the freshly-parsed feed data.
    @Insert(onConflict = OnConflictStrategy.IGNORE)
    suspend fun insertNew(articles: List<ArticleEntity>): List<Long>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun upsert(article: ArticleEntity)

    @Query("UPDATE articles SET isRead = :read WHERE id = :id")
    suspend fun setRead(id: String, read: Boolean)

    @Query("UPDATE articles SET isRead = 1 WHERE feedId = :feedId")
    suspend fun markAllReadForFeed(feedId: String)

    // Run when unsubscribing from a feed. Saved articles are deliberately kept
    // regardless (isSaved is a separate, durable "keep forever" concept,
    // independent of subscription) -- everything else is deleted so it doesn't
    // linger forever as an orphaned row cluttering the cross-feed Unread view.
    @Query("DELETE FROM articles WHERE feedId = :feedId AND isSaved = 0")
    suspend fun deleteUnsavedByFeed(feedId: String)

    @Query("UPDATE articles SET extractedContent = :content WHERE id = :id")
    suspend fun setExtractedContent(id: String, content: String)

    @Query("UPDATE articles SET isSaved = :saved WHERE id = :id")
    suspend fun setSaved(id: String, saved: Boolean)

    @Query("UPDATE articles SET stashArtifactId = :artifactId WHERE id = :id")
    suspend fun setStashArtifactId(id: String, artifactId: String)

    @Delete
    suspend fun delete(article: ArticleEntity)
}

@Dao
interface FilterRuleDao {
    @Query("SELECT * FROM filter_rules ORDER BY createdAt DESC")
    fun observeAll(): Flow<List<FilterRuleEntity>>

    @Query("SELECT * FROM filter_rules")
    suspend fun getAll(): List<FilterRuleEntity>

    @Insert
    suspend fun insert(rule: FilterRuleEntity): Long

    @Query("DELETE FROM filter_rules WHERE id = :id")
    suspend fun delete(id: Long)
}