Commit 8cb1aaee authored by Christophe Henry's avatar Christophe Henry

Add synchonizer between subscriptions and synchronisation categories

Add a delayed initialisation mecanism to synchronise between subscriptions and synchronisation categories
that will add the sources to the mediator live data only when both sources have started yielding their
first results. This prevents categories awkwardly showing first long before subscriptions.
parent 5de5f6f5
......@@ -23,7 +23,7 @@ class MainActivity: AppCompatActivity() {
Navigation.findNavController(this, R.id.main_activity_host_fragment)
}
val drawerLayout: DrawerLayout by lazy {
private val drawerLayout: DrawerLayout by lazy {
findViewById<DrawerLayout>(R.id.activity_main_navigation_drawer)
}
......@@ -39,7 +39,6 @@ class MainActivity: AppCompatActivity() {
restoreState()
setContentView(R.layout.activity_main)
F.app.refresherService.value?.apply {refresh()}
NavigationUI.setupActionBarWithNavController(this, navigation, appBarConfiguration)
setupActionBarWithNavController(navigation, appBarConfiguration)
drawerLayout.addDrawerListener(BurgerMenuDrawerListener(this))
}
......
......@@ -11,8 +11,7 @@ import androidx.lifecycle.Observer
import androidx.viewpager.widget.ViewPager.SimpleOnPageChangeListener
import com.google.android.material.bottomnavigation.BottomNavigationItemView
import com.google.android.material.bottomnavigation.BottomNavigationView
import fr.chenry.android.freshrss.MainNavDirections
import fr.chenry.android.freshrss.R
import fr.chenry.android.freshrss.*
import fr.chenry.android.freshrss.store.Store
import fr.chenry.android.freshrss.store.database.models.VoidCategory
import kotlinx.android.synthetic.main.fragment_main_subscription.*
......@@ -54,6 +53,7 @@ class MainSubscriptionFragment: Fragment(), BottomNavigationView.OnNavigationIte
}
fun onPageSelected(position: Int) = SubscriptionSection.byPosition(position).let {
F.app.preferences.subscriptionSection = it
Store.subscriptionsSection.value = it
subcription_bottom_navigation.selectedItemId = it.navigationButtonId
}
......
package fr.chenry.android.freshrss.store
import android.content.SharedPreferences
import androidx.core.content.edit
import androidx.preference.PreferenceManager
import fr.chenry.android.freshrss.FreshRSSApplication
import fr.chenry.android.freshrss.R
......@@ -30,7 +31,7 @@ class FreshRSSPreferences(private val application: FreshRSSApplication) {
return Try{SubscriptionSection.valueOf(pref)}.getOrDefault(SubscriptionSection.ALL)
}
set(value) {
sharedPreferences.edit().putString(subscriptionSectionKey, value.name).apply()
sharedPreferences.edit {putString(subscriptionSectionKey, value.name)}
}
private val refreshFrequencies by lazy {application.resources.getStringArray(R.array.refresh_frequencies)}
......
......@@ -18,13 +18,14 @@ sealed class SubscriptionsVM: ViewModel(), Observer<SubscriptionDisplayables> {
protected abstract val grouper: Grouper
protected abstract val comparator: Comparator<Subscription>
protected abstract val subscriptionsOrigin: LiveData<Subscriptions>
protected abstract val subscriptionCategories: LiveData<SubscriptionCategories>
protected abstract val rawSubscriptions: LiveData<Subscriptions>
protected abstract val rawCategories: LiveData<SubscriptionCategories>
private val mSubscriptions: MediatorLiveData<SubscriptionViewItems> by lazy {
MediatorLiveData<SubscriptionViewItems>().apply {
addSource(subscriptionsOrigin, this@SubscriptionsVM)
addSource(subscriptionCategories, this@SubscriptionsVM)
value = listOf()
if(this@SubscriptionsVM !is SubscriptionsForCategoryVM) MediatorInit(this)
else addSource(rawSubscriptions, this@SubscriptionsVM)
}
}
......@@ -51,32 +52,65 @@ sealed class SubscriptionsVM: ViewModel(), Observer<SubscriptionDisplayables> {
}
private fun computeNewDataSet(): SubscriptionViewItems {
val subcs = (subscriptionCategories.value ?: listOf()).sortedWith(LabelComparator)
val subc = (subscriptionsOrigin.value ?: listOf()).sortedWith(comparator)
val subcs = (rawCategories.value ?: listOf()).sortedWith(LabelComparator)
val subc = (rawSubscriptions.value ?: listOf()).sortedWith(comparator)
val targetSize = subcs.size + subc.size
val result = ArrayList<AbstractSubscriptionViewItem>(targetSize)
(0 until targetSize).forEach {
val newElt = if(it < subcs.size)
SubscriptionCategoryViewItem(subcs[it]) else
SubscriptionViewItem(
subc[it - subcs.size],
grouper(subc[it - subcs.size])
)
val newElt =
if(it < subcs.size) SubscriptionCategoryViewItem(subcs[it])
else SubscriptionViewItem(subc[it - subcs.size], grouper(subc[it - subcs.size]))
result.add(newElt)
}
return result
}
/**
* This class is used only to synchrinoze the results of subscriptionsOrigin and subscriptionCategories.
* It will start to populate the mediator only when the first results have started yielding for both sources.
* This is mainly used to avoid categories awkwardly showing first long before subscriptions.
*/
inner class MediatorInit(private val mediator: MediatorLiveData<SubscriptionViewItems>) {
private val subscriptionsOriginInitObserver = Observer<Subscriptions>(::onSubscriptionsChanged)
private val subscriptionCategoriesObserver = Observer<SubscriptionCategories>(::onSubscriptionsCategoriesChanged)
private var subscriptionsOriginInitialized = false
private var subscriptionCategoriesInitialized = false
init {
mediator.addSource(rawSubscriptions, subscriptionsOriginInitObserver)
mediator.addSource(rawCategories, subscriptionCategoriesObserver)
}
private fun onSubscriptionsChanged(s: Subscriptions) {
if(s.isNotEmpty()) subscriptionsOriginInitialized = true
if(subscriptionCategoriesInitialized && subscriptionsOriginInitialized) initMediator()
}
private fun onSubscriptionsCategoriesChanged(s: SubscriptionCategories) {
if(s.isNotEmpty()) subscriptionCategoriesInitialized = true
if(subscriptionCategoriesInitialized && subscriptionsOriginInitialized) initMediator()
}
private fun initMediator() {
mediator.removeSource(rawCategories)
mediator.addSource(rawCategories, this@SubscriptionsVM)
mediator.removeSource(rawSubscriptions)
mediator.addSource(rawSubscriptions, this@SubscriptionsVM)
}
}
}
class AllSubscriptionsVM: SubscriptionsVM() {
override val comparator get() = TitleComparator
override val grouper get() = TitleGrouper
override val subscriptionsOrigin = F.db.getAllSubcriptions().toLiveData()
override val subscriptionCategories = F.db.getAllCategories().toLiveData()
override val rawSubscriptions = F.db.getAllSubcriptions().toLiveData()
override val rawCategories = F.db.getAllCategories().toLiveData()
}
class UnreadSubscriptionsVM: SubscriptionsVM() {
......@@ -84,47 +118,40 @@ class UnreadSubscriptionsVM: SubscriptionsVM() {
override val comparator: Comparator<Subscription> get() = DateComparator
override val grouper get() = DateGrouper
override val subscriptionsOrigin = mSubscriptionsOrigin.toLiveData()
override val subscriptionCategories = MutableLiveData<SubscriptionCategories>(listOf())
override val rawSubscriptions = mSubscriptionsOrigin.toLiveData()
override val rawCategories = MutableLiveData<SubscriptionCategories>(listOf())
init {
val firstVal = mSubscriptionsOrigin.blockingFirst(listOf())
onChanged(firstVal)
subscriptionsOrigin.observeForever(Observer(::onSubscriptionChanged))
rawSubscriptions.observeForever(Observer(::onSubscriptionChanged))
}
private fun onSubscriptionChanged(subs: Subscriptions?) {
val categories = subs?.flatMap {it.subscriptionCategories} ?: listOf()
subscriptionCategories.postValue(F.db.getCategoriesById(categories).blockingFirst())
rawCategories.postValue(F.db.getCategoriesById(categories).blockingFirst())
}
}
class FavoritesSubscriptionsVM: SubscriptionsVM() {
override val comparator get() = TitleComparator
override val grouper get() = TitleGrouper
override val subscriptionCategories = MutableLiveData<SubscriptionCategories>(listOf())
override val subscriptionsOrigin: LiveData<Subscriptions> = MutableLiveData<Subscriptions>(listOf())
override val rawCategories = MutableLiveData<SubscriptionCategories>(listOf())
override val rawSubscriptions: LiveData<Subscriptions> = MutableLiveData<Subscriptions>(listOf())
}
class SubscriptionsForCategoryVM(
subscriptionCategory: SubscriptionCategory,
subscriptionSection: SubscriptionSection
): SubscriptionsVM() {
class SubscriptionsForCategoryVM(category: SubscriptionCategory, section: SubscriptionSection): SubscriptionsVM() {
override val comparator: Comparator<Subscription> =
if(subscriptionSection == UNREAD) DateComparator else TitleComparator
if(section == UNREAD) DateComparator else TitleComparator
override val grouper: Grouper =
if(subscriptionSection == UNREAD) DateGrouper else TitleGrouper
override val subscriptionsOrigin: LiveData<Subscriptions> by lazy {
when(subscriptionSection) {
FAVORITES -> F.db.getSubcriptionsBySubscriptionCategory(subscriptionCategory).toLiveData()
ALL -> F.db.getSubcriptionsBySubscriptionCategory(subscriptionCategory).toLiveData()
UNREAD -> F.db.getSubcriptionsBySubscriptionCategoryAndUnreadCount(subscriptionCategory).toLiveData()
if(section == UNREAD) DateGrouper else TitleGrouper
override val rawSubscriptions: LiveData<Subscriptions> by lazy {
when(section) {
FAVORITES -> F.db.getSubcriptionsBySubscriptionCategory(category).toLiveData()
ALL -> F.db.getSubcriptionsBySubscriptionCategory(category).toLiveData()
UNREAD -> F.db.getSubcriptionsBySubscriptionCategoryAndUnreadCount(category).toLiveData()
}
}
override val subscriptionCategories = MutableLiveData<SubscriptionCategories>(listOf())
override val rawCategories = MutableLiveData<SubscriptionCategories>(listOf())
}
class SubscriptionsFragmentCategoryVMF(
......
......@@ -29,7 +29,7 @@ class BurgerMenuDrawerListener(private val activity: MainActivity): DrawerLayout
private fun setPosition(rawPosition: Float) {
val position = min(1f, max(0f, rawPosition))
drawerArrowDrawable.progress = position
when(rawPosition) {
when(position) {
1f -> drawerArrowDrawable.setVerticalMirror(true)
0f -> drawerArrowDrawable.setVerticalMirror(false)
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment