Compare commits

..

No commits in common. "8c817b59383ce5016b35590c7cb666012f7d361d" and "fbcb428e96d66e9384b74f7b38a0bc22d88bc991" have entirely different histories.

4 changed files with 206 additions and 216 deletions

View File

@ -17,7 +17,6 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.core.view.doOnNextLayout import androidx.core.view.doOnNextLayout
import androidx.drawerlayout.widget.DrawerLayout import androidx.drawerlayout.widget.DrawerLayout
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.* import androidx.recyclerview.widget.*
import androidx.work.Constraints import androidx.work.Constraints
import androidx.work.ExistingPeriodicWorkPolicy import androidx.work.ExistingPeriodicWorkPolicy
@ -35,13 +34,10 @@ import bou.amine.apps.readerforselfossv2.android.utils.Config
import bou.amine.apps.readerforselfossv2.android.utils.bottombar.maybeShow import bou.amine.apps.readerforselfossv2.android.utils.bottombar.maybeShow
import bou.amine.apps.readerforselfossv2.android.utils.bottombar.removeBadge import bou.amine.apps.readerforselfossv2.android.utils.bottombar.removeBadge
import bou.amine.apps.readerforselfossv2.android.utils.customtabs.CustomTabActivityHelper import bou.amine.apps.readerforselfossv2.android.utils.customtabs.CustomTabActivityHelper
import bou.amine.apps.readerforselfossv2.android.viewmodel.AppViewModel import bou.amine.apps.readerforselfossv2.dao.ACTION
import bou.amine.apps.readerforselfossv2.model.SelfossModel
import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.repository.Repository
import bou.amine.apps.readerforselfossv2.utils.ItemType import bou.amine.apps.readerforselfossv2.model.SelfossModel
import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded import bou.amine.apps.readerforselfossv2.utils.*
import bou.amine.apps.readerforselfossv2.utils.getIcon
import bou.amine.apps.readerforselfossv2.utils.longHash
import com.ashokvarma.bottomnavigation.BottomNavigationBar import com.ashokvarma.bottomnavigation.BottomNavigationBar
import com.ashokvarma.bottomnavigation.BottomNavigationItem import com.ashokvarma.bottomnavigation.BottomNavigationItem
import com.ashokvarma.bottomnavigation.TextBadgeItem import com.ashokvarma.bottomnavigation.TextBadgeItem
@ -70,6 +66,7 @@ import org.kodein.di.DIAware
import org.kodein.di.android.closestDI import org.kodein.di.android.closestDI
import org.kodein.di.instance import org.kodein.di.instance
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlin.concurrent.thread
class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAware { class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAware {
@ -121,7 +118,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
override val di by closestDI() override val di by closestDI()
private val repository : Repository by instance() private val repository : Repository by instance()
private val viewModel: AppViewModel by instance()
data class DrawerData(val tags: List<SelfossModel.Tag>?, val sources: List<SelfossModel.Source>?) data class DrawerData(val tags: List<SelfossModel.Tag>?, val sources: List<SelfossModel.Source>?)
@ -146,11 +142,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
} }
setContentView(view) setContentView(view)
lifecycleScope.launch {
viewModel.refreshingIndicatorProvider.collect { showRefresh ->
binding.swipeRefreshLayout.isRefreshing = showRefresh
}
}
handleThemeBinding() handleThemeBinding()
@ -162,25 +153,18 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
mDrawerToggle.syncState() mDrawerToggle.syncState()
customTabActivityHelper = CustomTabActivityHelper() customTabActivityHelper = CustomTabActivityHelper()
handleSettings()
lifecycleScope.launch {
viewModel.items.collect { fetchedItems ->
items = fetchedItems
handleListResult()
}
}
handleBottomBar() handleBottomBar()
handleDrawer() handleDrawer()
handleSwipeRefreshLayout() handleSwipeRefreshLayout()
handleSettings()
getElementsAccordingToTab() getElementsAccordingToTab()
handleBadgesContent()
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.Main).launch {
repository.tryToCacheItemsAndGetNewOnes() repository.tryToCacheItemsAndGetNewOnes()
} }
@ -196,7 +180,10 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
repository.offlineOverride = false repository.offlineOverride = false
lastFetchDone = false lastFetchDone = false
handleDrawerItems() handleDrawerItems()
viewModel.getItems(false, elementsShown) CoroutineScope(Dispatchers.Main).launch {
getElementsAccordingToTab()
binding.swipeRefreshLayout.isRefreshing = false
}
} }
val simpleItemTouchCallback = val simpleItemTouchCallback =
@ -232,6 +219,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
adapter.handleItemAtIndex(position) adapter.handleItemAtIndex(position)
reloadBadgeContent()
val tagHashes = i.tags.map { it.longHash() } val tagHashes = i.tags.map { it.longHash() }
tagsBadge = tagsBadge.map { tagsBadge = tagsBadge.map {
if (tagHashes.contains(it.key)) { if (tagHashes.contains(it.key)) {
@ -263,23 +252,16 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
tabNewBadge = TextBadgeItem() tabNewBadge = TextBadgeItem()
.setText("") .setText("")
.setHideOnSelect(false) .setHideOnSelect(false).hide(false)
.setBackgroundColor(appColors.colorPrimary) .setBackgroundColor(appColors.colorPrimary)
if (!displayUnreadCount) {
tabNewBadge.hide(false)
}
tabArchiveBadge = TextBadgeItem() tabArchiveBadge = TextBadgeItem()
.setText("") .setText("")
.setHideOnSelect(false) .setHideOnSelect(false).hide(false)
.setBackgroundColor(appColors.colorPrimary) .setBackgroundColor(appColors.colorPrimary)
tabStarredBadge = TextBadgeItem() tabStarredBadge = TextBadgeItem()
.setText("") .setText("")
.setHideOnSelect(false) .setHideOnSelect(false).hide(false)
.setBackgroundColor(appColors.colorPrimary) .setBackgroundColor(appColors.colorPrimary)
if (!displayAllCount) {
tabArchiveBadge.hide(false)
tabStarredBadge.hide(false)
}
val tabNew = val tabNew =
BottomNavigationItem( BottomNavigationItem(
@ -471,7 +453,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
// TODO: refactor this. // TODO: refactor this.
private fun handleDrawerItems() { private fun handleDrawerItems() {
tagsBadge = emptyMap() tagsBadge = emptyMap()
fun handleDrawerData(maybeDrawerData: DrawerData?) { fun handleDrawerData(maybeDrawerData: DrawerData?, loadedFromCache: Boolean = false) {
fun createDrawerItem( fun createDrawerItem(
it: SelfossModel.Tag it: SelfossModel.Tag
) { ) {
@ -513,10 +495,12 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
fun handleTags(maybeTags: List<SelfossModel.Tag>?) { fun handleTags(maybeTags: List<SelfossModel.Tag>?) {
if (maybeTags == null) { if (maybeTags == null) {
binding.mainDrawer.itemAdapter.add( if (loadedFromCache) {
SecondaryDrawerItem() binding.mainDrawer.itemAdapter.add(
.apply { nameRes = R.string.drawer_error_loading_tags; isSelectable = false } SecondaryDrawerItem()
) .apply { nameRes = R.string.drawer_error_loading_tags; isSelectable = false }
)
}
} else { } else {
val filteredTags = maybeTags val filteredTags = maybeTags
.filterNot { hiddenTags.contains(it.tag) } .filterNot { hiddenTags.contains(it.tag) }
@ -531,12 +515,14 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
fun handleHiddenTags(maybeTags: List<SelfossModel.Tag>?) { fun handleHiddenTags(maybeTags: List<SelfossModel.Tag>?) {
if (maybeTags == null) { if (maybeTags == null) {
binding.mainDrawer.itemAdapter.add( if (loadedFromCache) {
SecondaryDrawerItem().apply { binding.mainDrawer.itemAdapter.add(
nameRes = R.string.drawer_error_loading_tags SecondaryDrawerItem().apply {
isSelectable = false nameRes = R.string.drawer_error_loading_tags
} isSelectable = false
) }
)
}
} else { } else {
val filteredHiddenTags: List<SelfossModel.Tag> = val filteredHiddenTags: List<SelfossModel.Tag> =
maybeTags.filter { hiddenTags.contains(it.tag) } maybeTags.filter { hiddenTags.contains(it.tag) }
@ -550,12 +536,14 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
fun handleSources(maybeSources: List<SelfossModel.Source>?) { fun handleSources(maybeSources: List<SelfossModel.Source>?) {
if (maybeSources == null) { if (maybeSources == null) {
binding.mainDrawer.itemAdapter.add( if (loadedFromCache) {
SecondaryDrawerItem().apply { binding.mainDrawer.itemAdapter.add(
nameRes = R.string.drawer_error_loading_sources SecondaryDrawerItem().apply {
isSelectable = false nameRes = R.string.drawer_error_loading_sources
} isSelectable = false
) }
)
}
} else { } else {
for (source in maybeSources) { for (source in maybeSources) {
val item = PrimaryDrawerItem().apply { val item = PrimaryDrawerItem().apply {
@ -644,19 +632,61 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
} }
) )
} else { if (!loadedFromCache) {
binding.mainDrawer.itemAdapter.add( if (maybeDrawerData.tags != null) {
PrimaryDrawerItem().apply { thread {
nameRes = R.string.no_tags_loaded repository.resetDBTagsWithData(maybeDrawerData.tags)
identifier = DRAWER_ID_TAGS }
isSelectable = false
},
PrimaryDrawerItem().apply {
nameRes = R.string.no_sources_loaded
identifier = DRAWER_ID_SOURCES
isSelectable = false
} }
) if (maybeDrawerData.sources != null) {
thread {
repository.resetDBSourcesWithData(maybeDrawerData.sources)
}
}
}
} else {
if (!loadedFromCache) {
binding.mainDrawer.itemAdapter.add(
PrimaryDrawerItem().apply {
nameRes = R.string.no_tags_loaded
identifier = DRAWER_ID_TAGS
isSelectable = false
},
PrimaryDrawerItem().apply {
nameRes = R.string.no_sources_loaded
identifier = DRAWER_ID_SOURCES
isSelectable = false
}
)
}
}
}
fun drawerApiCalls(maybeDrawerData: DrawerData?) {
var tags: List<SelfossModel.Tag>? = null
var sources: List<SelfossModel.Source>?
fun sourcesApiCall() {
CoroutineScope(Dispatchers.Main).launch {
val response = repository.getSources()
if (response != null) {
sources = response
val apiDrawerData = DrawerData(tags, sources)
if ((maybeDrawerData != null && maybeDrawerData != apiDrawerData) || maybeDrawerData == null) {
handleDrawerData(apiDrawerData)
}
} else {
val apiDrawerData = DrawerData(tags, null)
if ((maybeDrawerData != null && maybeDrawerData != apiDrawerData) || maybeDrawerData == null) {
handleDrawerData(apiDrawerData)
}
}
}
}
CoroutineScope(Dispatchers.IO).launch {
tags = repository.getTags()
sourcesApiCall()
} }
} }
@ -667,11 +697,12 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
} }
) )
CoroutineScope(Dispatchers.IO).launch { thread {
val drawerData = DrawerData(repository.getTags(), val drawerData = DrawerData(repository.getDBTags().map { it.toView() },
repository.getSources()) repository.getDBSources().map { it.toView() })
runOnUiThread { runOnUiThread {
handleDrawerData(drawerData) handleDrawerData(drawerData, loadedFromCache = true)
drawerApiCalls(drawerData)
} }
} }
} }
@ -808,7 +839,21 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
} }
firstVisible = if (appendResults) firstVisible else 0 firstVisible = if (appendResults) firstVisible else 0
viewModel.getItems(appendResults, elementsShown) getItems(appendResults, elementsShown)
}
private fun getItems(appendResults: Boolean, itemType: ItemType) {
CoroutineScope(Dispatchers.Main).launch {
binding.swipeRefreshLayout.isRefreshing = true
repository.displayedItems = itemType
items = if (appendResults) {
repository.getOlderItems()
} else {
repository.getNewerItems()
}
binding.swipeRefreshLayout.isRefreshing = false
handleListResult()
}
} }
private fun handleListResult(appendResults: Boolean = false) { private fun handleListResult(appendResults: Boolean = false) {
@ -870,50 +915,26 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
private fun reloadBadges() { private fun reloadBadges() {
if (displayUnreadCount || displayAllCount) { if (displayUnreadCount || displayAllCount) {
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.Main).launch {
repository.reloadBadges() repository.reloadBadges()
reloadBadgeContent()
} }
} }
} }
private fun handleBadgesContent() { private fun reloadBadgeContent() {
if (displayUnreadCount) { if (displayUnreadCount) {
lifecycleScope.launch { tabNewBadge
repository.badgeUnread.collect { unreadCount -> .setText(repository.badgeUnread.toString())
if (unreadCount > 0) { .maybeShow()
tabNewBadge
.setText(unreadCount.toString())
.maybeShow()
} else {
tabNewBadge.removeBadge()
}
}
}
} }
if (displayAllCount) { if (displayAllCount) {
lifecycleScope.launch { tabArchiveBadge
repository.badgeAll.collect { itemsCount -> .setText(repository.badgeAll.toString())
if (itemsCount > 0) { .maybeShow()
tabArchiveBadge tabStarredBadge
.setText(itemsCount.toString()) .setText(repository.badgeStarred.toString())
.maybeShow() .maybeShow()
} else {
tabArchiveBadge.removeBadge()
}
}
}
lifecycleScope.launch {
repository.badgeStarred.collect { starredCount ->
if (starredCount > 0) {
tabStarredBadge
.setText(starredCount.toString())
.maybeShow()
} else {
tabStarredBadge.removeBadge()
}
}
}
} }
} }
@ -971,14 +992,56 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
when (item.itemId) { when (item.itemId) {
R.id.refresh -> { R.id.refresh -> {
needsConfirmation(R.string.menu_home_refresh, R.string.refresh_dialog_message) { needsConfirmation(R.string.menu_home_refresh, R.string.refresh_dialog_message) {
viewModel.updateRemote() Toast.makeText(this, R.string.refresh_in_progress, Toast.LENGTH_SHORT).show()
// TODO: Use Dispatchers.IO
CoroutineScope(Dispatchers.Main).launch {
val updatedRemote = repository.updateRemote()
if (updatedRemote) {
// TODO: Send toast messages from the repository
Toast.makeText(
this@HomeActivity,
R.string.refresh_success_response, Toast.LENGTH_LONG
)
.show()
} else {
Toast.makeText(
this@HomeActivity,
R.string.refresh_failer_message,
Toast.LENGTH_SHORT
).show()
}
}
} }
return true return true
} }
R.id.readAll -> { R.id.readAll -> {
if (elementsShown == ItemType.UNREAD) { if (elementsShown == ItemType.UNREAD) {
needsConfirmation(R.string.readAll, R.string.markall_dialog_message) { needsConfirmation(R.string.readAll, R.string.markall_dialog_message) {
viewModel.markAllAsRead() binding.swipeRefreshLayout.isRefreshing = true
CoroutineScope(Dispatchers.Main).launch {
val success = repository.markAllAsRead(items)
if (success) {
Toast.makeText(
this@HomeActivity,
R.string.all_posts_read,
Toast.LENGTH_SHORT
).show()
tabNewBadge.removeBadge()
handleDrawerItems()
getElementsAccordingToTab()
} else {
Toast.makeText(
this@HomeActivity,
R.string.all_posts_not_read,
Toast.LENGTH_SHORT
).show()
}
handleListResult()
binding.swipeRefreshLayout.isRefreshing = false
}
} }
} }
return true return true
@ -992,10 +1055,10 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
private fun maxItemNumber(): Int = private fun maxItemNumber(): Int =
when (elementsShown) { when (elementsShown) {
ItemType.UNREAD -> repository.badgeUnread.value ItemType.UNREAD -> repository.badgeUnread
ItemType.ALL -> repository.badgeAll.value ItemType.ALL -> repository.badgeAll
ItemType.STARRED -> repository.badgeStarred.value ItemType.STARRED -> repository.badgeStarred
else -> repository.badgeUnread.value // if !elementsShown then unread are fetched. else -> repository.badgeUnread // if !elementsShown then unread are fetched.
} }
private fun updateItems(adapterItems: ArrayList<SelfossModel.Item>) { private fun updateItems(adapterItems: ArrayList<SelfossModel.Item>) {
@ -1019,4 +1082,9 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
WorkManager.getInstance(baseContext).enqueueUniquePeriodicWork("selfoss-loading", ExistingPeriodicWorkPolicy.KEEP, backgroundWork) WorkManager.getInstance(baseContext).enqueueUniquePeriodicWork("selfoss-loading", ExistingPeriodicWorkPolicy.KEEP, backgroundWork)
} }
} }
private fun handleOfflineActions() {
}
} }

View File

@ -84,15 +84,6 @@ class MyApp : MultiDexApplication(), DIAware {
).show() ).show()
} }
} }
CoroutineScope(Dispatchers.Main).launch {
viewModel.toastMessageProvider.collect { toastMessage ->
Toast.makeText(
applicationContext,
toastMessage,
Toast.LENGTH_SHORT
).show()
}
}
} }

View File

@ -3,29 +3,16 @@ package bou.amine.apps.readerforselfossv2.android.viewmodel
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import bou.amine.apps.readerforselfossv2.android.R import bou.amine.apps.readerforselfossv2.android.R
import bou.amine.apps.readerforselfossv2.model.SelfossModel
import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.repository.Repository
import bou.amine.apps.readerforselfossv2.utils.ItemType
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class AppViewModel(private val repository: Repository) : ViewModel() { class AppViewModel(private val repository: Repository) : ViewModel() {
private val _networkAvailableProvider = MutableSharedFlow<Boolean>() private val _networkAvailableProvider = MutableSharedFlow<Boolean>()
val networkAvailableProvider = _networkAvailableProvider.asSharedFlow() val networkAvailableProvider = _networkAvailableProvider.asSharedFlow()
private val _refreshingIndicatorProvider = MutableSharedFlow<Boolean>()
val refreshingIndicatorProvider = _refreshingIndicatorProvider.asSharedFlow()
private val _toastMessageProvider = MutableSharedFlow<Int>()
val toastMessageProvider = _toastMessageProvider.asSharedFlow()
private var wasConnected = true private var wasConnected = true
private val _items = MutableStateFlow(ArrayList<SelfossModel.Item>())
val items = _items.asStateFlow()
init { init {
viewModelScope.launch { viewModelScope.launch {
repository.isConnectionAvailable.collect { isConnected -> repository.isConnectionAvailable.collect { isConnected ->
@ -41,43 +28,4 @@ class AppViewModel(private val repository: Repository) : ViewModel() {
} }
} }
} }
fun updateRemote() {
CoroutineScope(Dispatchers.IO).launch {
_toastMessageProvider.emit(R.string.refresh_in_progress)
val updatedRemote = repository.updateRemote()
if (updatedRemote) {
_toastMessageProvider.emit(R.string.refresh_success_response)
} else {
_toastMessageProvider.emit(R.string.refresh_failer_message)
}
}
}
fun getItems(appendResults: Boolean, itemType: ItemType) {
CoroutineScope(Dispatchers.Main).launch {
_refreshingIndicatorProvider.emit(true)
repository.displayedItems = itemType
val items = if (appendResults) {
repository.getOlderItems()
} else {
repository.getNewerItems()
}
_items.emit(items)
_refreshingIndicatorProvider.emit(false)
}
}
fun markAllAsRead() {
CoroutineScope(Dispatchers.IO).launch {
_refreshingIndicatorProvider.emit(true)
val success = repository.markAllAsRead(items.value)
if (success) {
_toastMessageProvider.emit(R.string.all_posts_read)
} else {
_toastMessageProvider.emit(R.string.all_posts_not_read)
}
_refreshingIndicatorProvider.emit(false)
}
}
} }

View File

@ -11,8 +11,6 @@ import com.russhwolf.settings.Settings
import io.github.aakira.napier.Napier import io.github.aakira.napier.Napier
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class Repository(private val api: SelfossApi, private val apiDetails: ApiDetailsService, private 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) {
@ -35,23 +33,18 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
var offlineOverride = false var offlineOverride = false
var apiMajorVersion = 0 var apiMajorVersion = 0
private val _badgeUnread = MutableStateFlow(0) var badgeUnread = 0
val badgeUnread = _badgeUnread.asStateFlow() set(value) {field = if (value < 0) { 0 } else { value } }
private val _badgeAll = MutableStateFlow(0) var badgeAll = 0
val badgeAll = _badgeAll.asStateFlow() set(value) {field = if (value < 0) { 0 } else { value } }
private val _badgeStarred = MutableStateFlow(0) var badgeStarred = 0
val badgeStarred = _badgeStarred.asStateFlow() set(value) {field = if (value < 0) { 0 } else { value } }
init { init {
// TODO: Dispatchers.IO not available in KMM, an alternative solution should be found // TODO: Dispatchers.IO not available in KMM, an alternative solution should be found
CoroutineScope(Dispatchers.Main).launch { CoroutineScope(Dispatchers.Main).launch {
updateApiVersion() updateApiVersion()
isConnectionAvailable.collect { connectionAvailable -> reloadBadges()
if (connectionAvailable) {
updateApiVersion()
reloadBadges()
}
}
} }
} }
@ -132,31 +125,27 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
if (isNetworkAvailable()) { if (isNetworkAvailable()) {
val response = api.stats() val response = api.stats()
if (response != null) { if (response != null) {
_badgeUnread.value = response.unread badgeUnread = response.unread
_badgeAll.value = response.total badgeAll = response.total
_badgeStarred.value = response.starred badgeStarred = response.starred
success = true success = true
} }
} else if (itemsCaching) { } else {
// TODO: do this differently, because it's not efficient // TODO: do this differently, because it's not efficient
val dbItems = getDBItems() val dbItems = getDBItems()
_badgeUnread.value = dbItems.filter { item -> item.unread }.size badgeUnread = dbItems.filter { item -> item.unread }.size
_badgeStarred.value = dbItems.filter { item -> item.starred }.size badgeStarred = dbItems.filter { item -> item.starred }.size
_badgeAll.value = dbItems.size badgeAll = items.size
} }
return success return success
} }
suspend fun getTags(): List<SelfossModel.Tag>? { suspend fun getTags(): List<SelfossModel.Tag>? {
val tags = if (isNetworkAvailable()) { return if (isNetworkAvailable()) {
api.tags() api.tags()
} else { } else {
getDBTags().map { it.toView() } getDBTags().map { it.toView() }
} }
if (tags != null) {
resetDBTagsWithData(tags)
}
return tags
} }
suspend fun getSpouts(): Map<String, SelfossModel.Spout>? { suspend fun getSpouts(): Map<String, SelfossModel.Spout>? {
@ -168,15 +157,12 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
} }
suspend fun getSources(): ArrayList<SelfossModel.Source>? { suspend fun getSources(): ArrayList<SelfossModel.Source>? {
val sources = if (isNetworkAvailable()) {
return if (isNetworkAvailable()) {
api.sources() api.sources()
} else { } else {
ArrayList(getDBSources().map { it.toView() }) ArrayList(getDBSources().map { it.toView() })
} }
if (sources != null) {
resetDBSourcesWithData(sources)
}
return sources
} }
suspend fun markAsRead(item: SelfossModel.Item): Boolean { suspend fun markAsRead(item: SelfossModel.Item): Boolean {
@ -267,7 +253,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
private fun markAsReadLocally(item: SelfossModel.Item) { private fun markAsReadLocally(item: SelfossModel.Item) {
if (item.unread) { if (item.unread) {
item.unread = false item.unread = false
_badgeUnread.value -= 1 badgeUnread -= 1
} }
CoroutineScope(Dispatchers.Main).launch { CoroutineScope(Dispatchers.Main).launch {
@ -278,7 +264,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
private fun unmarkAsReadLocally(item: SelfossModel.Item) { private fun unmarkAsReadLocally(item: SelfossModel.Item) {
if (!item.unread) { if (!item.unread) {
item.unread = true item.unread = true
_badgeUnread.value += 1 badgeUnread += 1
} }
CoroutineScope(Dispatchers.Main).launch { CoroutineScope(Dispatchers.Main).launch {
@ -289,7 +275,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
private fun starrLocally(item: SelfossModel.Item) { private fun starrLocally(item: SelfossModel.Item) {
if (!item.starred) { if (!item.starred) {
item.starred = true item.starred = true
_badgeStarred.value += 1 badgeStarred += 1
} }
CoroutineScope(Dispatchers.Main).launch { CoroutineScope(Dispatchers.Main).launch {
@ -300,7 +286,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
private fun unstarrLocally(item: SelfossModel.Item) { private fun unstarrLocally(item: SelfossModel.Item) {
if (item.starred) { if (item.starred) {
item.starred = false item.starred = false
_badgeStarred.value -= 1 badgeStarred -= 1
} }
CoroutineScope(Dispatchers.Main).launch { CoroutineScope(Dispatchers.Main).launch {
@ -442,16 +428,13 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
suspend fun tryToCacheItemsAndGetNewOnes(): List<SelfossModel.Item>? { suspend fun tryToCacheItemsAndGetNewOnes(): List<SelfossModel.Item>? {
if (itemsCaching) { try {
try { val newItems = getMaxItemsForBackground(ItemType.UNREAD)
val newItems = getMaxItemsForBackground(ItemType.UNREAD) val allItems = getMaxItemsForBackground(ItemType.ALL)
val allItems = getMaxItemsForBackground(ItemType.ALL) val starredItems = getMaxItemsForBackground(ItemType.STARRED)
val starredItems = getMaxItemsForBackground(ItemType.STARRED) insertDBItems(newItems.orEmpty() + allItems.orEmpty() + starredItems.orEmpty())
insertDBItems(newItems.orEmpty() + allItems.orEmpty() + starredItems.orEmpty()) return newItems
return newItems } catch (e: Throwable) {}
} catch (e: Throwable) {
}
}
return emptyList() return emptyList()
} }