|
|
|
@ -1,15 +1,11 @@
|
|
|
|
|
package bou.amine.apps.readerforselfossv2.repository
|
|
|
|
|
|
|
|
|
|
import bou.amine.apps.readerforselfossv2.dao.ACTION
|
|
|
|
|
import bou.amine.apps.readerforselfossv2.dao.ReaderForSelfossDB
|
|
|
|
|
import bou.amine.apps.readerforselfossv2.dao.SOURCE
|
|
|
|
|
import bou.amine.apps.readerforselfossv2.dao.TAG
|
|
|
|
|
import bou.amine.apps.readerforselfossv2.dao.*
|
|
|
|
|
import bou.amine.apps.readerforselfossv2.model.NetworkUnavailableException
|
|
|
|
|
import bou.amine.apps.readerforselfossv2.rest.SelfossApi
|
|
|
|
|
import bou.amine.apps.readerforselfossv2.rest.SelfossModel
|
|
|
|
|
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
|
|
|
|
import bou.amine.apps.readerforselfossv2.service.ApiDetailsService
|
|
|
|
|
import bou.amine.apps.readerforselfossv2.utils.DateUtils
|
|
|
|
|
import bou.amine.apps.readerforselfossv2.utils.ItemType
|
|
|
|
|
import bou.amine.apps.readerforselfossv2.utils.toEntity
|
|
|
|
|
import bou.amine.apps.readerforselfossv2.utils.*
|
|
|
|
|
import com.github.ln_12.library.ConnectivityStatus
|
|
|
|
|
import com.russhwolf.settings.Settings
|
|
|
|
|
import io.github.aakira.napier.Napier
|
|
|
|
@ -17,7 +13,7 @@ import kotlinx.coroutines.CoroutineScope
|
|
|
|
|
import kotlinx.coroutines.Dispatchers
|
|
|
|
|
import kotlinx.coroutines.launch
|
|
|
|
|
|
|
|
|
|
class Repository(private val api: SelfossApi, private val apiDetails: ApiDetailsService, val connectivityStatus: ConnectivityStatus, private val db: ReaderForSelfossDB) {
|
|
|
|
|
class Repository(private val api: SelfossApi, private val apiDetails: ApiDetailsService, private val connectivityStatus: ConnectivityStatus, private val db: ReaderForSelfossDB) {
|
|
|
|
|
val settings = Settings()
|
|
|
|
|
|
|
|
|
|
var items = ArrayList<SelfossModel.Item>()
|
|
|
|
@ -67,11 +63,14 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
|
|
|
|
|
null
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
// TODO: Get items from the database
|
|
|
|
|
if (itemsCaching) {
|
|
|
|
|
fetchedItems = getDBItems().map { it.toView() }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fetchedItems != null) {
|
|
|
|
|
items = ArrayList(fetchedItems)
|
|
|
|
|
sortItems()
|
|
|
|
|
}
|
|
|
|
|
return items
|
|
|
|
|
}
|
|
|
|
@ -89,17 +88,16 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
|
|
|
|
|
searchFilter,
|
|
|
|
|
null
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
// TODO: Get items from the database
|
|
|
|
|
}
|
|
|
|
|
} // When using the db cache, we load everything the first time, so there should be nothing more to load.
|
|
|
|
|
|
|
|
|
|
if (fetchedItems != null) {
|
|
|
|
|
appendItems(fetchedItems)
|
|
|
|
|
items.addAll(fetchedItems)
|
|
|
|
|
sortItems()
|
|
|
|
|
}
|
|
|
|
|
return items
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
suspend fun allItems(itemType: ItemType): List<SelfossModel.Item>? {
|
|
|
|
|
suspend fun getMaxItemsForBackground(itemType: ItemType): List<SelfossModel.Item>? {
|
|
|
|
|
return if (isNetworkAvailable()) {
|
|
|
|
|
api.getItems(
|
|
|
|
|
itemType.type,
|
|
|
|
@ -111,21 +109,11 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
|
|
|
|
|
null
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
// TODO: Provide an error message
|
|
|
|
|
null
|
|
|
|
|
emptyList()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun appendItems(fetchedItems: List<SelfossModel.Item>) {
|
|
|
|
|
// TODO: Store in DB if enabled by user
|
|
|
|
|
val fetchedIDS = fetchedItems.map { it.id }
|
|
|
|
|
val tmpItems = ArrayList(items.filterNot { it.id in fetchedIDS })
|
|
|
|
|
tmpItems.addAll(fetchedItems)
|
|
|
|
|
sortItems(tmpItems)
|
|
|
|
|
items = tmpItems
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun sortItems(items: ArrayList<SelfossModel.Item>) {
|
|
|
|
|
private fun sortItems() {
|
|
|
|
|
items.sortByDescending { dateUtils.parseDate(it.datetime) }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -140,38 +128,37 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
|
|
|
|
|
success = true
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// TODO: Compute badges from database
|
|
|
|
|
// TODO: do this differently, because it's not efficient
|
|
|
|
|
val dbItems = getDBItems()
|
|
|
|
|
badgeUnread = dbItems.filter { item -> item.unread }.size
|
|
|
|
|
badgeStarred = dbItems.filter { item -> item.starred }.size
|
|
|
|
|
badgeAll = items.size
|
|
|
|
|
}
|
|
|
|
|
return success
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
suspend fun getTags(): List<SelfossModel.Tag>? {
|
|
|
|
|
// TODO: Store in DB
|
|
|
|
|
return if (isNetworkAvailable()) {
|
|
|
|
|
api.tags()
|
|
|
|
|
} else {
|
|
|
|
|
// TODO: Compute from database
|
|
|
|
|
null
|
|
|
|
|
getDBTags().map { it.toView() }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
suspend fun getSpouts(): Map<String, SelfossModel.Spout>? {
|
|
|
|
|
// TODO: Store in DB
|
|
|
|
|
return if (isNetworkAvailable()) {
|
|
|
|
|
api.spouts()
|
|
|
|
|
} else {
|
|
|
|
|
// TODO: Compute from database
|
|
|
|
|
null
|
|
|
|
|
throw NetworkUnavailableException()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
suspend fun getSources(): ArrayList<SelfossModel.Source>? {
|
|
|
|
|
// TODO: Store in DB
|
|
|
|
|
|
|
|
|
|
return if (isNetworkAvailable()) {
|
|
|
|
|
api.sources()
|
|
|
|
|
} else {
|
|
|
|
|
// TODO: Compute from database
|
|
|
|
|
null
|
|
|
|
|
ArrayList(getDBSources().map { it.toView() })
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -184,8 +171,14 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
|
|
|
|
|
return success
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
suspend fun markAsReadById(id: Int): Boolean =
|
|
|
|
|
isNetworkAvailable() && api.markAsRead(id.toString())?.isSuccess == true
|
|
|
|
|
suspend fun markAsReadById(id: Int): Boolean {
|
|
|
|
|
return if (isNetworkAvailable()) {
|
|
|
|
|
api.markAsRead(id.toString())?.isSuccess == true
|
|
|
|
|
} else {
|
|
|
|
|
insertDBAction(id.toString(), read = true)
|
|
|
|
|
true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
suspend fun unmarkAsRead(item: SelfossModel.Item): Boolean {
|
|
|
|
@ -197,8 +190,14 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
|
|
|
|
|
return success
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
suspend fun unmarkAsReadById(id: Int): Boolean =
|
|
|
|
|
isNetworkAvailable() && api.unmarkAsRead(id.toString())?.isSuccess == true
|
|
|
|
|
suspend fun unmarkAsReadById(id: Int): Boolean {
|
|
|
|
|
return if (isNetworkAvailable()) {
|
|
|
|
|
api.unmarkAsRead(id.toString())?.isSuccess == true
|
|
|
|
|
} else {
|
|
|
|
|
insertDBAction(id.toString(), unread = true)
|
|
|
|
|
true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
suspend fun starr(item: SelfossModel.Item): Boolean {
|
|
|
|
|
val success = starrById(item.id)
|
|
|
|
@ -209,8 +208,14 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
|
|
|
|
|
return success
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
suspend fun starrById(id: Int): Boolean =
|
|
|
|
|
isNetworkAvailable() && api.starr(id.toString())?.isSuccess == true
|
|
|
|
|
suspend fun starrById(id: Int): Boolean {
|
|
|
|
|
return if (isNetworkAvailable()) {
|
|
|
|
|
api.starr(id.toString())?.isSuccess == true
|
|
|
|
|
} else {
|
|
|
|
|
insertDBAction(id.toString(), starred = true)
|
|
|
|
|
true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
suspend fun unstarr(item: SelfossModel.Item): Boolean {
|
|
|
|
|
val success = unstarrById(item.id)
|
|
|
|
@ -221,9 +226,14 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
|
|
|
|
|
return success
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
suspend fun unstarrById(id: Int): Boolean =
|
|
|
|
|
isNetworkAvailable() && api.unstarr(id.toString())?.isSuccess == true
|
|
|
|
|
|
|
|
|
|
suspend fun unstarrById(id: Int): Boolean {
|
|
|
|
|
return if (isNetworkAvailable()) {
|
|
|
|
|
api.unstarr(id.toString())?.isSuccess == true
|
|
|
|
|
} else {
|
|
|
|
|
insertDBAction(id.toString(), starred = true)
|
|
|
|
|
true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
suspend fun markAllAsRead(items: ArrayList<SelfossModel.Item>): Boolean {
|
|
|
|
|
var success = false
|
|
|
|
@ -238,35 +248,47 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun markAsReadLocally(item: SelfossModel.Item) {
|
|
|
|
|
// TODO: Mark also in the database
|
|
|
|
|
if (item.unread) {
|
|
|
|
|
item.unread = false
|
|
|
|
|
badgeUnread -= 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CoroutineScope(Dispatchers.Main).launch {
|
|
|
|
|
updateDBItem(item)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun unmarkAsReadLocally(item: SelfossModel.Item) {
|
|
|
|
|
// TODO: Mark also in the database
|
|
|
|
|
if (!item.unread) {
|
|
|
|
|
item.unread = true
|
|
|
|
|
badgeUnread += 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CoroutineScope(Dispatchers.Main).launch {
|
|
|
|
|
updateDBItem(item)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun starrLocally(item: SelfossModel.Item) {
|
|
|
|
|
// TODO: Mark also in the database
|
|
|
|
|
if (!item.starred) {
|
|
|
|
|
item.starred = true
|
|
|
|
|
badgeStarred += 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CoroutineScope(Dispatchers.Main).launch {
|
|
|
|
|
updateDBItem(item)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun unstarrLocally(item: SelfossModel.Item) {
|
|
|
|
|
// TODO: Mark also in the database
|
|
|
|
|
if (item.starred) {
|
|
|
|
|
item.starred = false
|
|
|
|
|
badgeStarred -= 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CoroutineScope(Dispatchers.Main).launch {
|
|
|
|
|
updateDBItem(item)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
suspend fun createSource(
|
|
|
|
@ -292,7 +314,6 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
suspend fun deleteSource(id: Int): Boolean {
|
|
|
|
|
// TODO: Store in DB
|
|
|
|
|
var success = false
|
|
|
|
|
if (isNetworkAvailable()) {
|
|
|
|
|
val response = api.deleteSource(id)
|
|
|
|
@ -376,4 +397,20 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun insertDBItems(items: List<SelfossModel.Item>) {
|
|
|
|
|
db.itemsQueries.transaction {
|
|
|
|
|
items.forEach { item ->
|
|
|
|
|
db.itemsQueries.insertItem(item.toEntity())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun getDBItems(): List<ITEM> = db.itemsQueries.items().executeAsList()
|
|
|
|
|
|
|
|
|
|
private fun insertDBAction(articleid: String, read: Boolean = false, unread: Boolean = false, starred: Boolean = false, unstarred: Boolean = false) =
|
|
|
|
|
db.actionsQueries.insertAction(articleid, read, unread, starred, unstarred)
|
|
|
|
|
|
|
|
|
|
private fun updateDBItem(item: SelfossModel.Item) =
|
|
|
|
|
db.itemsQueries.updateItem(item.datetime, item.getTitleDecoded(), item.content, item.unread, item.starred, item.thumbnail, item.icon, item.link, item.sourcetitle, item.tags.joinToString(","), item.id.toString())
|
|
|
|
|
}
|