FreshRSSDabatabase.kt 3.73 KB
Newer Older
Christophe Henry's avatar
Christophe Henry committed
1
package fr.chenry.android.freshrss.store.database
2 3

import androidx.room.*
4 5
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
6 7
import fr.chenry.android.freshrss.FreshRSSApplication
import fr.chenry.android.freshrss.R
Christophe Henry's avatar
Christophe Henry committed
8 9
import fr.chenry.android.freshrss.store.api.models.StreamId
import fr.chenry.android.freshrss.store.database.models.*
10
import fr.chenry.android.freshrss.utils.Try
11 12 13 14
import fr.chenry.android.freshrss.utils.getOrDefault
import nl.komponents.kovenant.task
import kotlin.reflect.KProperty

15
@Database(version = 2, entities = [Account::class, Article::class, Subscription::class])
Christophe Henry's avatar
Christophe Henry committed
16
@TypeConverters(Converters::class)
17 18 19 20 21 22
abstract class FreshRSSDabatabase: RoomDatabase() {
    private val authTokensDelegate = AuthTokensDelegate()
    var account: Account by authTokensDelegate
    val authTokensExistInDB get() = authTokensDelegate.isInitialized

    protected abstract fun getAuthTokensDAO(): AuthTokensDAO
Christophe Henry's avatar
Christophe Henry committed
23
    protected abstract fun getArticlesDAO(): ArticlesDAO
24
    protected abstract fun getSubscriptionsDAO(): SubscriptionsDAO
Christophe Henry's avatar
Christophe Henry committed
25 26 27 28 29

    fun getArticleByStreamId(streamId: StreamId) = getArticlesDAO().getByStreamId(streamId)
    fun getArticleById(id: ItemId) = getArticlesDAO().getById(id)
    fun getArticleByStreamIdAndUnread(streamId: StreamId) =
        getArticlesDAO().getByStreamIdAndUnread(streamId, ReadStatus.UNREAD.name)
30

Christophe Henry's avatar
Christophe Henry committed
31
    fun upsertArticle(article: Article) =
32 33
        Try{getArticlesDAO().update(article)}.orElseDo {getArticlesDAO().insert(article)}

Christophe Henry's avatar
Christophe Henry committed
34
    fun insertArticle(article: Article) = getArticlesDAO().forceInsert(article)
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
    fun syncSubscriptions(subscriptions: Subscriptions) {
        task {
            getSubscriptionsDAO().insertAll(subscriptions)
        }
        task {
            getSubscriptionsDAO()
                .getAllIds()
                .blockingFirst()
                .subtract(subscriptions.map {it.id})
                .let {getSubscriptionsDAO().deleteAllById(it.toList())}
        }
    }
    fun updateSubscriptionCount(id: String, count: Int) = getSubscriptionsDAO().updateCount(id, count)
    fun incrementSubscriptionCount(id: String) = getSubscriptionsDAO().incrementCount(id)
    fun decrementSubscriptionCount(id: String) = getSubscriptionsDAO().decrementCount(id)
    fun getAllSubcriptions() = getSubscriptionsDAO().getAll()
    fun getAllSubcriptionsIds() = getSubscriptionsDAO().getAllIds()
52 53 54 55 56 57 58

    companion object {
        private val dbName by lazy {
            "${FreshRSSApplication.context.getString(R.string.app_name).toLowerCase()}.db"
        }
        val instance by lazy {
            val instance =
59 60 61
                Room
                    .databaseBuilder(FreshRSSApplication.context, FreshRSSDabatabase::class.java, dbName)
                    .addMigrations(MIGRATION_1_2)
Christophe Henry's avatar
Christophe Henry committed
62
                    .build()
63 64 65
            instance.authTokensDelegate.fetchAuthtokensFromDB()
            instance
        }
66 67 68 69

        private val MIGRATION_1_2 = object: Migration(1, 2) {
            override fun migrate(database: SupportSQLiteDatabase) = Unit
        }
70 71 72 73 74 75 76 77 78 79 80
    }

    inner class AuthTokensDelegate {
        private lateinit var cachedAccount: Account
        val isInitialized
            get() = ::cachedAccount.isInitialized

        operator fun getValue(thisRef: Any?, property: KProperty<*>): Account = cachedAccount

        operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Account) {
            cachedAccount = value
81
            task {getAuthTokensDAO().insert(account)}.getOrDefault(Unit)
82 83 84 85 86 87 88 89 90
        }

        fun fetchAuthtokensFromDB() {
            if(!isInitialized) {
                val authTokensFromDB = task {getAuthTokensDAO().getAuthTokens()[0]}.getOrDefault(null)
                if(authTokensFromDB != null) cachedAccount = authTokensFromDB
            }
        }
    }
Christophe Henry's avatar
Christophe Henry committed
91
}