书架更新时显示剩余更新数量,在书架布局里配置

This commit is contained in:
kunfei
2023-06-23 18:18:35 +08:00
parent 1054cb470b
commit 299fe58891
15 changed files with 100 additions and 4 deletions
@@ -127,6 +127,7 @@ object PreferKey {
const val audioPlayWakeLock = "audioPlayWakeLock" const val audioPlayWakeLock = "audioPlayWakeLock"
const val readAloudWakeLock = "readAloudWakeLock" const val readAloudWakeLock = "readAloudWakeLock"
const val showLastUpdateTime = "showLastUpdateTime" const val showLastUpdateTime = "showLastUpdateTime"
const val showWaitUpCount = "showWaitUpCount"
const val clearWebViewData = "clearWebViewData" const val clearWebViewData = "clearWebViewData"
const val onlyLatestBackup = "onlyLatestBackup" const val onlyLatestBackup = "onlyLatestBackup"
const val brightnessVwPos = "brightnessVwPos" const val brightnessVwPos = "brightnessVwPos"
@@ -88,6 +88,12 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
appCtx.putPrefBoolean(PreferKey.showLastUpdateTime, value) appCtx.putPrefBoolean(PreferKey.showLastUpdateTime, value)
} }
var showWaitUpCount: Boolean
get() = appCtx.getPrefBoolean(PreferKey.showWaitUpCount, false)
set(value) {
appCtx.putPrefBoolean(PreferKey.showWaitUpCount, value)
}
var readBrightness: Int var readBrightness: Int
get() = if (isNightTheme) { get() = if (isNightTheme) {
appCtx.getPrefInt(PreferKey.nightBrightness, 100) appCtx.getPrefInt(PreferKey.nightBrightness, 100)
@@ -2,11 +2,16 @@ package io.legado.app.lib.theme.view
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.view.LayoutInflater
import com.google.android.material.bottomnavigation.BottomNavigationItemView
import com.google.android.material.bottomnavigation.BottomNavigationMenuView
import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.bottomnavigation.BottomNavigationView
import io.legado.app.databinding.ViewNavigationBadgeBinding
import io.legado.app.lib.theme.Selector import io.legado.app.lib.theme.Selector
import io.legado.app.lib.theme.ThemeStore import io.legado.app.lib.theme.ThemeStore
import io.legado.app.lib.theme.bottomBackground import io.legado.app.lib.theme.bottomBackground
import io.legado.app.lib.theme.getSecondaryTextColor import io.legado.app.lib.theme.getSecondaryTextColor
import io.legado.app.ui.widget.text.BadgeView
import io.legado.app.utils.ColorUtils import io.legado.app.utils.ColorUtils
class ThemeBottomNavigationVIew(context: Context, attrs: AttributeSet) : class ThemeBottomNavigationVIew(context: Context, attrs: AttributeSet) :
@@ -24,4 +29,14 @@ class ThemeBottomNavigationVIew(context: Context, attrs: AttributeSet) :
itemTextColor = colorStateList itemTextColor = colorStateList
} }
fun addBadgeView(index: Int): BadgeView {
//获取底部菜单view
val menuView = getChildAt(0) as BottomNavigationMenuView
//获取第index个itemView
val itemView = menuView.getChildAt(index) as BottomNavigationItemView
val badgeBinding = ViewNavigationBadgeBinding.inflate(LayoutInflater.from(context))
itemView.addView(badgeBinding.root)
return badgeBinding.viewBadge
}
} }
@@ -74,6 +74,9 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
private val adapter by lazy { private val adapter by lazy {
TabFragmentPageAdapter(supportFragmentManager) TabFragmentPageAdapter(supportFragmentManager)
} }
private val onUpBooksBadgeView by lazy {
binding.bottomNavigationView.addBadgeView(0)
}
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
upBottomMenu() upBottomMenu()
@@ -128,10 +131,13 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
when (item.itemId) { when (item.itemId) {
R.id.menu_bookshelf -> R.id.menu_bookshelf ->
viewPagerMain.setCurrentItem(0, false) viewPagerMain.setCurrentItem(0, false)
R.id.menu_discovery -> R.id.menu_discovery ->
viewPagerMain.setCurrentItem(realPositions.indexOf(idExplore), false) viewPagerMain.setCurrentItem(realPositions.indexOf(idExplore), false)
R.id.menu_rss -> R.id.menu_rss ->
viewPagerMain.setCurrentItem(realPositions.indexOf(idRss), false) viewPagerMain.setCurrentItem(realPositions.indexOf(idRss), false)
R.id.menu_my_config -> R.id.menu_my_config ->
viewPagerMain.setCurrentItem(realPositions.indexOf(idMy), false) viewPagerMain.setCurrentItem(realPositions.indexOf(idMy), false)
} }
@@ -147,6 +153,7 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
(fragmentMap[getFragmentId(0)] as? BaseBookshelfFragment)?.gotoTop() (fragmentMap[getFragmentId(0)] as? BaseBookshelfFragment)?.gotoTop()
} }
} }
R.id.menu_discovery -> { R.id.menu_discovery -> {
if (System.currentTimeMillis() - exploreReselected > 300) { if (System.currentTimeMillis() - exploreReselected > 300) {
exploreReselected = System.currentTimeMillis() exploreReselected = System.currentTimeMillis()
@@ -304,6 +311,9 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
} }
override fun observeLiveBus() { override fun observeLiveBus() {
viewModel.onUpBooksLiveData.observe(this) {
onUpBooksBadgeView.setBadgeCount(it)
}
observeEvent<String>(EventBus.RECREATE) { observeEvent<String>(EventBus.RECREATE) {
recreate() recreate()
} }
@@ -400,9 +410,11 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
} }
interface Callback { interface Callback {
fun onActive() fun onActive()
fun onInactive() fun onInactive()
} }
} }
@@ -1,6 +1,7 @@
package io.legado.app.ui.main package io.legado.app.ui.main
import android.app.Application import android.app.Application
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import io.legado.app.base.BaseViewModel import io.legado.app.base.BaseViewModel
import io.legado.app.constant.AppConst import io.legado.app.constant.AppConst
@@ -12,15 +13,25 @@ import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookSource import io.legado.app.data.entities.BookSource
import io.legado.app.help.AppWebDav import io.legado.app.help.AppWebDav
import io.legado.app.help.DefaultData import io.legado.app.help.DefaultData
import io.legado.app.help.book.* import io.legado.app.help.book.BookHelp
import io.legado.app.help.book.addType
import io.legado.app.help.book.isLocal
import io.legado.app.help.book.isSameNameAuthor
import io.legado.app.help.book.isUpError
import io.legado.app.help.book.removeType
import io.legado.app.help.book.sync
import io.legado.app.help.config.AppConfig import io.legado.app.help.config.AppConfig
import io.legado.app.model.CacheBook import io.legado.app.model.CacheBook
import io.legado.app.model.ReadBook import io.legado.app.model.ReadBook
import io.legado.app.model.webBook.WebBook import io.legado.app.model.webBook.WebBook
import io.legado.app.service.CacheBookService import io.legado.app.service.CacheBookService
import io.legado.app.utils.postEvent import io.legado.app.utils.postEvent
import kotlinx.coroutines.*
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Job
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import java.util.concurrent.CopyOnWriteArraySet import java.util.concurrent.CopyOnWriteArraySet
import java.util.concurrent.Executors import java.util.concurrent.Executors
import kotlin.math.min import kotlin.math.min
@@ -31,6 +42,7 @@ class MainViewModel(application: Application) : BaseViewModel(application) {
Executors.newFixedThreadPool(min(threadCount, AppConst.MAX_THREAD)).asCoroutineDispatcher() Executors.newFixedThreadPool(min(threadCount, AppConst.MAX_THREAD)).asCoroutineDispatcher()
private val waitUpTocBooks = arrayListOf<String>() private val waitUpTocBooks = arrayListOf<String>()
private val onUpTocBooks = CopyOnWriteArraySet<String>() private val onUpTocBooks = CopyOnWriteArraySet<String>()
val onUpBooksLiveData = MutableLiveData<Int>()
private var upTocJob: Job? = null private var upTocJob: Job? = null
private var cacheBookJob: Job? = null private var cacheBookJob: Job? = null
@@ -79,6 +91,7 @@ class MainViewModel(application: Application) : BaseViewModel(application) {
} }
private fun startUpTocJob() { private fun startUpTocJob() {
postUpBooksLiveData()
upTocJob = viewModelScope.launch(upTocPool) { upTocJob = viewModelScope.launch(upTocPool) {
while (isActive) { while (isActive) {
when { when {
@@ -104,11 +117,13 @@ class MainViewModel(application: Application) : BaseViewModel(application) {
val bookUrl = waitUpTocBooks.firstOrNull() ?: return val bookUrl = waitUpTocBooks.firstOrNull() ?: return
if (onUpTocBooks.contains(bookUrl)) { if (onUpTocBooks.contains(bookUrl)) {
waitUpTocBooks.remove(bookUrl) waitUpTocBooks.remove(bookUrl)
postUpBooksLiveData()
return return
} }
val book = appDb.bookDao.getBook(bookUrl) val book = appDb.bookDao.getBook(bookUrl)
if (book == null) { if (book == null) {
waitUpTocBooks.remove(bookUrl) waitUpTocBooks.remove(bookUrl)
postUpBooksLiveData()
return return
} }
val source = appDb.bookSourceDao.getBookSource(book.origin) val source = appDb.bookSourceDao.getBookSource(book.origin)
@@ -118,6 +133,7 @@ class MainViewModel(application: Application) : BaseViewModel(application) {
appDb.bookDao.update(book) appDb.bookDao.update(book)
} }
waitUpTocBooks.remove(book.bookUrl) waitUpTocBooks.remove(book.bookUrl)
postUpBooksLiveData()
return return
} }
waitUpTocBooks.remove(bookUrl) waitUpTocBooks.remove(bookUrl)
@@ -160,6 +176,15 @@ class MainViewModel(application: Application) : BaseViewModel(application) {
}.onFinally(upTocPool) { }.onFinally(upTocPool) {
upTocFinally(bookUrl) upTocFinally(bookUrl)
upTocFinally(book.bookUrl) upTocFinally(book.bookUrl)
postUpBooksLiveData()
}
}
fun postUpBooksLiveData() {
if (AppConfig.showWaitUpCount) {
onUpBooksLiveData.postValue(waitUpTocBooks.size + onUpTocBooks.size)
} else {
onUpBooksLiveData.postValue(0)
} }
} }
@@ -135,6 +135,7 @@ abstract class BaseBookshelfFragment(layoutId: Int) : VMBaseFragment<BookshelfVi
spGroupStyle.setSelection(AppConfig.bookGroupStyle) spGroupStyle.setSelection(AppConfig.bookGroupStyle)
swShowUnread.isChecked = AppConfig.showUnread swShowUnread.isChecked = AppConfig.showUnread
swShowLastUpdateTime.isChecked = AppConfig.showLastUpdateTime swShowLastUpdateTime.isChecked = AppConfig.showLastUpdateTime
swShowWaitUpBooks.isChecked = AppConfig.showWaitUpCount
rgLayout.checkByIndex(bookshelfLayout) rgLayout.checkByIndex(bookshelfLayout)
rgSort.checkByIndex(bookshelfSort) rgSort.checkByIndex(bookshelfSort)
} }
@@ -153,6 +154,10 @@ abstract class BaseBookshelfFragment(layoutId: Int) : VMBaseFragment<BookshelfVi
AppConfig.showLastUpdateTime = swShowLastUpdateTime.isChecked AppConfig.showLastUpdateTime = swShowLastUpdateTime.isChecked
postEvent(EventBus.BOOKSHELF_REFRESH, "") postEvent(EventBus.BOOKSHELF_REFRESH, "")
} }
if (AppConfig.showWaitUpCount != swShowWaitUpBooks.isChecked) {
AppConfig.showWaitUpCount = swShowWaitUpBooks.isChecked
activityViewModel.postUpBooksLiveData()
}
var changed = false var changed = false
if (bookshelfLayout != rgLayout.getCheckedIndex()) { if (bookshelfLayout != rgLayout.getCheckedIndex()) {
putPrefInt(PreferKey.bookshelfLayout, rgLayout.getCheckedIndex()) putPrefInt(PreferKey.bookshelfLayout, rgLayout.getCheckedIndex())
@@ -49,13 +49,22 @@
app:layout_constraintTop_toBottomOf="@+id/sw_show_unread" app:layout_constraintTop_toBottomOf="@+id/sw_show_unread"
tools:ignore="TouchTargetSizeCheck" /> tools:ignore="TouchTargetSizeCheck" />
<io.legado.app.lib.theme.view.ThemeSwitch
android:id="@+id/sw_show_wait_up_books"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="6dp"
android:text="@string/show_wait_up_count"
app:layout_constraintTop_toBottomOf="@+id/sw_show_last_update_time"
tools:ignore="TouchTargetSizeCheck" />
<LinearLayout <LinearLayout
android:id="@+id/ll_layout" android:id="@+id/ll_layout"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
app:layout_constraintRight_toLeftOf="@+id/ll_sort" app:layout_constraintRight_toLeftOf="@+id/ll_sort"
app:layout_constraintTop_toBottomOf="@+id/sw_show_last_update_time" app:layout_constraintTop_toBottomOf="@+id/sw_show_wait_up_books"
app:layout_constraintLeft_toLeftOf="parent"> app:layout_constraintLeft_toLeftOf="parent">
<io.legado.app.ui.widget.text.AccentTextView <io.legado.app.ui.widget.text.AccentTextView
@@ -110,7 +119,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
app:layout_constraintLeft_toRightOf="@+id/ll_layout" app:layout_constraintLeft_toRightOf="@+id/ll_layout"
app:layout_constraintTop_toBottomOf="@id/sw_show_last_update_time" app:layout_constraintTop_toBottomOf="@id/sw_show_wait_up_books"
app:layout_constraintRight_toRightOf="parent"> app:layout_constraintRight_toRightOf="parent">
<io.legado.app.ui.widget.text.AccentTextView <io.legado.app.ui.widget.text.AccentTextView
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<io.legado.app.ui.widget.text.BadgeView
android:id="@+id/view_badge"
android:layout_width="wrap_content"
android:layout_height="18dp"
android:layout_marginLeft="12dp"
android:layout_marginTop="2dp"
android:layout_gravity="center_horizontal"
tools:ignore="RtlHardcoded" />
</FrameLayout>
@@ -1115,4 +1115,5 @@
<string name="is_compress">是否压缩</string> <string name="is_compress">是否压缩</string>
<string name="sort_desc">反序</string> <string name="sort_desc">反序</string>
<string name="test">测试</string> <string name="test">测试</string>
<string name="show_wait_up_count">显示等待更新数量</string>
</resources> </resources>
@@ -1118,4 +1118,5 @@
<string name="is_compress">是否压缩</string> <string name="is_compress">是否压缩</string>
<string name="sort_desc">反序</string> <string name="sort_desc">反序</string>
<string name="test">测试</string> <string name="test">测试</string>
<string name="show_wait_up_count">显示等待更新数量</string>
</resources> </resources>
@@ -1118,4 +1118,5 @@
<string name="is_compress">是否压缩</string> <string name="is_compress">是否压缩</string>
<string name="sort_desc">反序</string> <string name="sort_desc">反序</string>
<string name="test">测试</string> <string name="test">测试</string>
<string name="show_wait_up_count">显示等待更新数量</string>
</resources> </resources>
@@ -1115,4 +1115,5 @@
<string name="is_compress">是否压缩</string> <string name="is_compress">是否压缩</string>
<string name="sort_desc">反序</string> <string name="sort_desc">反序</string>
<string name="test">测试</string> <string name="test">测试</string>
<string name="show_wait_up_count">显示等待更新数量</string>
</resources> </resources>
@@ -1117,4 +1117,5 @@
<string name="is_compress">是否压缩</string> <string name="is_compress">是否压缩</string>
<string name="sort_desc">反序</string> <string name="sort_desc">反序</string>
<string name="test">测试</string> <string name="test">测试</string>
<string name="show_wait_up_count">显示等待更新数量</string>
</resources> </resources>
+1
View File
@@ -1117,4 +1117,5 @@
<string name="is_compress">是否压缩</string> <string name="is_compress">是否压缩</string>
<string name="sort_desc">反序</string> <string name="sort_desc">反序</string>
<string name="test">测试</string> <string name="test">测试</string>
<string name="show_wait_up_count">显示等待更新数量</string>
</resources> </resources>
+1
View File
@@ -1118,4 +1118,5 @@
<string name="is_compress">是否压缩</string> <string name="is_compress">是否压缩</string>
<string name="sort_desc">反序</string> <string name="sort_desc">反序</string>
<string name="test">测试</string> <string name="test">测试</string>
<string name="show_wait_up_count">显示等待更新数量</string>
</resources> </resources>