Application update indicator

This commit is contained in:
Koitharu
2023-07-13 14:39:55 +03:00
parent 4c201bf950
commit 2d670418c7
4 changed files with 68 additions and 3 deletions

View File

@@ -0,0 +1,38 @@
package org.koitharu.kotatsu.core.ui.util
import androidx.annotation.IdRes
import androidx.appcompat.widget.Toolbar
import com.google.android.material.badge.BadgeDrawable
import com.google.android.material.badge.BadgeUtils
import com.google.android.material.badge.ExperimentalBadgeUtils
@androidx.annotation.OptIn(ExperimentalBadgeUtils::class)
class OptionsMenuBadgeHelper(
private val toolbar: Toolbar,
@IdRes private val itemId: Int,
) {
private var badge: BadgeDrawable? = null
fun setBadgeVisible(isVisible: Boolean) {
if (isVisible) {
showBadge()
} else {
hideBadge()
}
}
private fun hideBadge() {
badge?.let {
BadgeUtils.detachBadgeDrawable(it, toolbar, itemId)
}
badge = null
}
private fun showBadge() {
val badgeDrawable = badge ?: BadgeDrawable.create(toolbar.context).also {
badge = it
}
BadgeUtils.attachBadgeDrawable(badgeDrawable, toolbar, itemId)
}
}

View File

@@ -40,6 +40,7 @@ import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.util.OptionsMenuBadgeHelper
import org.koitharu.kotatsu.core.ui.widgets.SlidingBottomNavigationView
import org.koitharu.kotatsu.core.util.ext.hideKeyboard
import org.koitharu.kotatsu.core.util.ext.observe
@@ -63,6 +64,7 @@ import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionFragment
import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionListener
import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionViewModel
import org.koitharu.kotatsu.settings.SettingsActivity
import org.koitharu.kotatsu.settings.about.AppUpdateDialog
import org.koitharu.kotatsu.settings.newsources.NewSourcesDialogFragment
import org.koitharu.kotatsu.settings.onboard.OnboardDialogFragment
import javax.inject.Inject
@@ -81,6 +83,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>(), AppBarOwner, BottomNav
private val searchSuggestionViewModel by viewModels<SearchSuggestionViewModel>()
private val closeSearchCallback = CloseSearchCallback()
private lateinit var navigationDelegate: MainNavigationDelegate
private lateinit var appUpdateBadge: OptionsMenuBadgeHelper
override val appBar: AppBarLayout
get() = viewBinding.appbar
@@ -119,6 +122,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>(), AppBarOwner, BottomNav
navigationDelegate.addOnFragmentChangedListener(this)
navigationDelegate.onCreate()
appUpdateBadge = OptionsMenuBadgeHelper(viewBinding.toolbar, R.id.action_app_update)
onBackPressedDispatcher.addCallback(ExitCallback(this, viewBinding.container))
onBackPressedDispatcher.addCallback(navigationDelegate)
onBackPressedDispatcher.addCallback(closeSearchCallback)
@@ -132,6 +137,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>(), AppBarOwner, BottomNav
viewModel.isLoading.observe(this, this::onLoadingStateChanged)
viewModel.isResumeEnabled.observe(this, this::onResumeEnabledChanged)
viewModel.counters.observe(this, ::onCountersChanged)
viewModel.appUpdate.observe(this) { invalidateMenu() }
viewModel.isFeedAvailable.observe(this, ::onFeedAvailabilityChanged)
searchSuggestionViewModel.isIncognitoModeEnabled.observe(this, this::onIncognitoModeChanged)
}
@@ -158,6 +164,9 @@ class MainActivity : BaseActivity<ActivityMainBinding>(), AppBarOwner, BottomNav
override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
menu?.findItem(R.id.action_incognito)?.isChecked = searchSuggestionViewModel.isIncognitoModeEnabled.value
val hasAppUpdate = viewModel.appUpdate.value != null
menu?.findItem(R.id.action_app_update)?.isVisible = hasAppUpdate
appUpdateBadge.setBadgeVisible(hasAppUpdate)
return super.onPrepareOptionsMenu(menu)
}
@@ -179,6 +188,13 @@ class MainActivity : BaseActivity<ActivityMainBinding>(), AppBarOwner, BottomNav
true
}
R.id.action_app_update -> {
viewModel.appUpdate.value?.also {
AppUpdateDialog(this)
.show(it)
} != null
}
else -> super.onOptionsItemSelected(item)
}

View File

@@ -7,6 +7,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.plus
import org.koitharu.kotatsu.R
@@ -46,12 +47,14 @@ class MainViewModel @Inject constructor(
valueProducer = { isTrackerEnabled },
)
val appUpdate = appUpdateRepository.observeAvailableUpdate()
val counters = combine(
appUpdateRepository.observeAvailableUpdate(),
trackingRepository.observeUpdatedMangaCount(),
) { appUpdate, tracks ->
flow { emit(settings.newSources) },
) { tracks, newSources ->
val a = SparseIntArray(2)
// a[R.id.nav_tools] = if (appUpdate != null) 1 else 0
a[R.id.nav_explore] = newSources.size
a[R.id.nav_feed] = tracks
a
}.stateIn(

View File

@@ -3,6 +3,14 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_app_update"
android:icon="@drawable/ic_app_update"
android:orderInCategory="1"
android:title="@string/update"
android:visible="false"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_incognito"
android:checkable="true"