diff --git a/app/src/main/java/io/legato/kazusa/data/dao/BookGroupDao.kt b/app/src/main/java/io/legato/kazusa/data/dao/BookGroupDao.kt index e46f5259a..3ed2c9339 100644 --- a/app/src/main/java/io/legato/kazusa/data/dao/BookGroupDao.kt +++ b/app/src/main/java/io/legato/kazusa/data/dao/BookGroupDao.kt @@ -85,6 +85,9 @@ interface BookGroupDao { @Delete fun delete(vararg bookGroup: BookGroup) + @Query("UPDATE book_groups SET cover = NULL WHERE groupId = :groupId") + fun clearCover(groupId: Long) + fun isInRules(id: Long): Boolean { if (id < 0) { return true diff --git a/app/src/main/java/io/legato/kazusa/lib/prefs/NameListPreference.kt b/app/src/main/java/io/legato/kazusa/lib/prefs/NameListPreference.kt index 1265a0eda..91a1fb84e 100644 --- a/app/src/main/java/io/legato/kazusa/lib/prefs/NameListPreference.kt +++ b/app/src/main/java/io/legato/kazusa/lib/prefs/NameListPreference.kt @@ -18,7 +18,6 @@ class NameListPreference(context: Context, attrs: AttributeSet) : ListPreference init { layoutResource = R.layout.view_preference - widgetLayoutResource = R.layout.item_fillet_text context.withStyledAttributes(attrs, R.styleable.Preference) { isBottomBackground = getBoolean(R.styleable.Preference_isBottomBackground, false) } @@ -26,16 +25,16 @@ class NameListPreference(context: Context, attrs: AttributeSet) : ListPreference override fun onBindViewHolder(holder: PreferenceViewHolder) { val v = Preference.bindView( - context, holder, icon, title, summary, widgetLayoutResource, + context, holder, icon, title, entry, R.id.text_view, isBottomBackground = isBottomBackground ) if (v is TextView) { v.text = entry - if (isBottomBackground) { +// if (isBottomBackground) { // val bgColor = context.bottomBackground -// val pTextColor = context.getPrimaryTextColor(ColorUtils.isColorLight(bgColor)) - //v.setTextColor(pTextColor) - } +// val pTextColor = context.getPrimaryTextColor(ColorUtils.isColorLight(bgColor)) +// //v.setTextColor(pTextColor) +// } } super.onBindViewHolder(holder) } diff --git a/app/src/main/java/io/legato/kazusa/ui/book/group/GroupEditDialog.kt b/app/src/main/java/io/legato/kazusa/ui/book/group/GroupEditDialog.kt index dd9ba9732..20e83d4a3 100644 --- a/app/src/main/java/io/legato/kazusa/ui/book/group/GroupEditDialog.kt +++ b/app/src/main/java/io/legato/kazusa/ui/book/group/GroupEditDialog.kt @@ -67,7 +67,8 @@ class GroupEditDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_book_gro bookGroup?.let { binding.btnDelete.visible(it.groupId > 0 || it.groupId == Long.MIN_VALUE) binding.tieGroupName.setText(it.groupName) - binding.ivCover.load(it.cover) + if (bookGroup?.cover != null) + binding.ivCover.load(it.cover) binding.spSort.setSelection(it.bookSort + 1) binding.cbEnableRefresh.isChecked = it.enableRefresh } ?: let { @@ -79,6 +80,14 @@ class GroupEditDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_book_gro ivCover.onClick { selectImage.launch() } + btnReset.onClick { + bookGroup?.let { + viewModel.clearCover(it) { + toastOnUi("封面已重置") + dismiss() + } + } + } btnCancel.onClick { dismiss() } diff --git a/app/src/main/java/io/legato/kazusa/ui/book/group/GroupViewModel.kt b/app/src/main/java/io/legato/kazusa/ui/book/group/GroupViewModel.kt index 5f9618ac1..4703788d9 100644 --- a/app/src/main/java/io/legato/kazusa/ui/book/group/GroupViewModel.kt +++ b/app/src/main/java/io/legato/kazusa/ui/book/group/GroupViewModel.kt @@ -48,5 +48,12 @@ class GroupViewModel(application: Application) : BaseViewModel(application) { } } + fun clearCover(bookGroup: BookGroup, finally: () -> Unit) { + execute { + appDb.bookGroupDao.clearCover(bookGroup.groupId) + }.onFinally { + finally() + } + } } \ No newline at end of file diff --git a/app/src/main/java/io/legato/kazusa/ui/book/read/ReadMenu.kt b/app/src/main/java/io/legato/kazusa/ui/book/read/ReadMenu.kt index 9a450d29d..f05218d1d 100644 --- a/app/src/main/java/io/legato/kazusa/ui/book/read/ReadMenu.kt +++ b/app/src/main/java/io/legato/kazusa/ui/book/read/ReadMenu.kt @@ -4,7 +4,6 @@ import android.annotation.SuppressLint import android.content.Context import android.graphics.drawable.GradientDrawable import android.util.AttributeSet -import android.util.Log import android.view.LayoutInflater import android.view.WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE import android.view.animation.Animation @@ -19,19 +18,10 @@ import io.legato.kazusa.constant.PreferKey import io.legato.kazusa.databinding.ViewReadMenuBinding import io.legato.kazusa.help.config.AppConfig import io.legato.kazusa.help.config.LocalConfig -import io.legato.kazusa.help.config.ReadBookConfig -import io.legato.kazusa.help.config.ThemeConfig import io.legato.kazusa.help.coroutine.Coroutine import io.legato.kazusa.help.source.getSourceType import io.legato.kazusa.lib.dialogs.alert -//import io.legado.app.lib.theme.accentColor -//import io.legado.app.lib.theme.bottomBackground -//import io.legado.app.lib.theme.buttonDisabledColor -//import io.legado.app.lib.theme.getPrimaryTextColor -//import io.legado.app.lib.theme.primaryColor -//import io.legado.app.lib.theme.primaryTextColor import io.legato.kazusa.model.ReadBook -import io.legato.kazusa.ui.book.read.config.MoreConfigDialog import io.legato.kazusa.ui.browser.WebViewActivity import io.legato.kazusa.ui.widget.seekbar.SeekBarChangeListener import io.legato.kazusa.utils.ConstraintModify @@ -45,7 +35,6 @@ import io.legato.kazusa.utils.loadAnimation import io.legato.kazusa.utils.modifyBegin import io.legato.kazusa.utils.openUrl import io.legato.kazusa.utils.putPrefBoolean -import io.legato.kazusa.utils.showDialogFragment import io.legato.kazusa.utils.startActivity import io.legato.kazusa.utils.visible import splitties.views.onClick @@ -75,8 +64,8 @@ class ReadMenu @JvmOverloads constructor( private val menuBottomOut: Animation by lazy { loadAnimation(context, R.anim.anim_readbook_bottom_out) } - private val immersiveMenu: Boolean - get() = AppConfig.readBarStyleFollowPage && ReadBookConfig.durConfig.curBgType() == 0 +// private val immersiveMenu: Boolean +// get() = AppConfig.readBarStyleFollowPage && ReadBookConfig.durConfig.curBgType() == 0 // private var bgColor: Int = if (immersiveMenu) { // kotlin.runCatching { // ReadBookConfig.durConfig.curBgStr().toColorInt() @@ -160,29 +149,29 @@ class ReadMenu @JvmOverloads constructor( bindEvent() } - private fun initView(reset: Boolean = false) = binding.run { + private fun initView() = binding.run { // if (AppConfig.isNightTheme) { // fabNightTheme.setIconResource(R.drawable.ic_daytime) // } else { // fabNightTheme.setIconResource(R.drawable.ic_brightness) // } initAnimation() - if (immersiveMenu) { -// val lightTextColor = ColorUtils.withAlpha(ColorUtils.lightenColor(textColor), 0.75f) -// titleBar.setTextColor(textColor) -// titleBar.setBackgroundColor(bgColor) -// titleBar.setColorFilter(textColor) -// tvChapterName.setTextColor(lightTextColor) -// tvChapterUrl.setTextColor(lightTextColor) - } else if (reset) { -// val bgColor = context.primaryColor -// val textColor = context.primaryTextColor -// titleBar.setTextColor(textColor) -// titleBar.setBackgroundColor(bgColor) -// titleBar.setColorFilter(textColor) -// tvChapterName.setTextColor(textColor) -// tvChapterUrl.setTextColor(textColor) - } +// if (immersiveMenu) { +//// val lightTextColor = ColorUtils.withAlpha(ColorUtils.lightenColor(textColor), 0.75f) +//// titleBar.setTextColor(textColor) +//// titleBar.setBackgroundColor(bgColor) +//// titleBar.setColorFilter(textColor) +//// tvChapterName.setTextColor(lightTextColor) +//// tvChapterUrl.setTextColor(lightTextColor) +// } else if (reset) { +//// val bgColor = context.primaryColor +//// val textColor = context.primaryTextColor +//// titleBar.setTextColor(textColor) +//// titleBar.setBackgroundColor(bgColor) +//// titleBar.setColorFilter(textColor) +//// tvChapterName.setTextColor(textColor) +//// tvChapterUrl.setTextColor(textColor) +// } val brightnessBackground = GradientDrawable() brightnessBackground.cornerRadius = 5F.dpToPx() //brightnessBackground.setColor(ColorUtils.adjustAlpha(bgColor, 0.5f)) @@ -230,13 +219,13 @@ class ReadMenu @JvmOverloads constructor( fun reset() { upColorConfig() - initView(true) + initView() } fun refreshMenuColorFilter() { - if (immersiveMenu) { - //binding.titleBar.setColorFilter(textColor) - } +// if (immersiveMenu) { +// //binding.titleBar.setColorFilter(textColor) +// } } private fun upColorConfig() { @@ -514,8 +503,6 @@ class ReadMenu @JvmOverloads constructor( fun upSeekBar() { binding.seekReadPage.apply { - Log.d("SliderDebug", "durPageIndex: ${ReadBook.durPageIndex}, pageSize: ${ReadBook.curTextChapter?.pageSize}") - Log.d("SliderDebug", "durChapterIndex: ${ReadBook.durChapterIndex}, simulatedChapterSize: ${ReadBook.simulatedChapterSize}") when (AppConfig.progressBarBehavior) { "page" -> { ReadBook.curTextChapter?.let { chapter -> diff --git a/app/src/main/java/io/legato/kazusa/ui/main/MainActivity.kt b/app/src/main/java/io/legato/kazusa/ui/main/MainActivity.kt index 73cd83792..529d74ff6 100644 --- a/app/src/main/java/io/legato/kazusa/ui/main/MainActivity.kt +++ b/app/src/main/java/io/legato/kazusa/ui/main/MainActivity.kt @@ -9,7 +9,6 @@ import android.view.MenuItem import android.view.MotionEvent import android.view.ViewGroup import androidx.activity.addCallback -import androidx.activity.enableEdgeToEdge import androidx.activity.viewModels import androidx.core.view.postDelayed import androidx.fragment.app.Fragment @@ -33,7 +32,6 @@ import io.legato.kazusa.help.config.LocalConfig import io.legato.kazusa.help.coroutine.Coroutine import io.legato.kazusa.help.storage.Backup import io.legato.kazusa.lib.dialogs.alert -//import io.legado.app.lib.theme.primaryColor import io.legato.kazusa.service.BaseReadAloudService import io.legato.kazusa.ui.about.CrashLogsDialog import io.legato.kazusa.ui.main.bookshelf.BaseBookshelfFragment @@ -45,9 +43,7 @@ import io.legato.kazusa.ui.main.rss.RssFragment import io.legato.kazusa.ui.widget.dialog.TextDialog import io.legato.kazusa.utils.hideSoftInput import io.legato.kazusa.utils.isCreated -import io.legato.kazusa.utils.navigationBarHeight import io.legato.kazusa.utils.observeEvent -import io.legato.kazusa.utils.setOnApplyWindowInsetsListenerCompat import io.legato.kazusa.utils.shouldHideSoftInput import io.legato.kazusa.utils.showDialogFragment import io.legato.kazusa.utils.toastOnUi @@ -55,14 +51,11 @@ import io.legato.kazusa.utils.viewbindingdelegate.viewBinding import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import splitties.views.bottomPadding import kotlin.coroutines.resume import kotlin.coroutines.suspendCoroutine import androidx.core.view.get import com.google.android.material.navigation.NavigationBarView -import io.legato.kazusa.ui.welcome.WelcomeActivity -import io.legato.kazusa.utils.applyNavigationBarPadding -import io.legato.kazusa.utils.applyStatusBarPadding +import io.legato.kazusa.ui.main.bookshelf.style1.BookshelfFragment3 /** * 主界面 @@ -76,6 +69,7 @@ class MainActivity : VMBaseActivity(), private val idBookshelf = 0 private val idBookshelf1 = 11 private val idBookshelf2 = 12 + private val idBookshelf3 = 13 private val idExplore = 1 private val idRss = 2 private val idMy = 3 @@ -424,11 +418,17 @@ class MainActivity : VMBaseActivity(), private fun getFragmentId(position: Int): Int { val id = realPositions[position] if (id == idBookshelf) { - return if (AppConfig.bookGroupStyle == 1) idBookshelf2 else idBookshelf1 + return when (AppConfig.bookGroupStyle) { + 0 -> idBookshelf1 + 1 -> idBookshelf2 + 2 -> idBookshelf3 + else -> idBookshelf1 + } } return id } + private inner class PageChangeCallback : ViewPager.SimpleOnPageChangeListener() { override fun onPageSelected(position: Int) { @@ -447,24 +447,28 @@ class MainActivity : VMBaseActivity(), } override fun getItemPosition(any: Any): Int { - val position = (any as MainFragmentInterface).position - ?: return POSITION_NONE + val position = (any as? MainFragmentInterface)?.position ?: return POSITION_NONE val fragmentId = getId(position) - if ((fragmentId == idBookshelf1 && any is BookshelfFragment1) - || (fragmentId == idBookshelf2 && any is BookshelfFragment2) - || (fragmentId == idExplore && any is ExploreFragment) - || (fragmentId == idRss && any is RssFragment) - || (fragmentId == idMy && any is MyFragment) + + if ( + (fragmentId == idBookshelf1 && any is BookshelfFragment1) || + (fragmentId == idBookshelf2 && any is BookshelfFragment2) || + (fragmentId == idBookshelf3 && any is BookshelfFragment3) || + (fragmentId == idExplore && any is ExploreFragment) || + (fragmentId == idRss && any is RssFragment) || + (fragmentId == idMy && any is MyFragment) ) { return POSITION_UNCHANGED } return POSITION_NONE } + override fun getItem(position: Int): Fragment { return when (getId(position)) { idBookshelf1 -> BookshelfFragment1(position) idBookshelf2 -> BookshelfFragment2(position) + idBookshelf3 -> BookshelfFragment3(position) idExplore -> ExploreFragment(position) idRss -> RssFragment(position) else -> MyFragment(position) diff --git a/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/BaseBookshelfFragment.kt b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/BaseBookshelfFragment.kt index c091db0a6..b8fd86bd8 100644 --- a/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/BaseBookshelfFragment.kt +++ b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/BaseBookshelfFragment.kt @@ -4,10 +4,12 @@ import android.annotation.SuppressLint import android.content.res.Configuration import android.view.Menu import android.view.MenuItem +import android.view.View import androidx.core.view.isVisible import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels import androidx.lifecycle.LiveData +import com.google.android.material.chip.Chip import io.legato.kazusa.R import io.legato.kazusa.base.VMBaseFragment import io.legato.kazusa.constant.EventBus @@ -30,9 +32,6 @@ import io.legato.kazusa.ui.file.HandleFileContract import io.legato.kazusa.ui.main.MainFragmentInterface import io.legato.kazusa.ui.main.MainViewModel import io.legato.kazusa.ui.widget.dialog.WaitDialog -import io.legato.kazusa.utils.bookshelfLayout -import io.legato.kazusa.utils.checkByIndex -import io.legato.kazusa.utils.getCheckedIndex import io.legato.kazusa.utils.isAbsUrl import io.legato.kazusa.utils.postEvent import io.legato.kazusa.utils.readText @@ -166,7 +165,7 @@ abstract class BaseBookshelfFragment(layoutId: Int) : VMBaseFragment + val chip = Chip(context).apply { + text = label + isCheckable = true + isClickable = true + id = View.generateViewId() + } + chipGroupStyle.addView(chip) + if (index == AppConfig.bookGroupStyle) { + chipGroupStyle.check(chip.id) + } + } + + val sortArray = resources.getStringArray(R.array.bookshelf_px_array) + val chipGroupSort = chipGroupSort + + sortArray.forEachIndexed { index, label -> + val chip = Chip(context).apply { + text = label + isCheckable = true + isClickable = true + id = View.generateViewId() + } + chipGroupSort.addView(chip) + if (index == AppConfig.bookshelfSort) { + chipGroupSort.check(chip.id) + } + } + swShowUnread.isChecked = AppConfig.showUnread swShowLastUpdateTime.isChecked = AppConfig.showLastUpdateTime swShowWaitUpBooks.isChecked = AppConfig.showWaitUpCount swShowBookshelfFastScroller.isChecked = AppConfig.showBookshelfFastScroller - rgSort.checkByIndex(bookshelfSort) chipList.isChecked = !isGrid chipGrid.isChecked = isGrid - llGridSlider.isVisible = isGrid + sliderText.isVisible = isGrid + sliderGridCount.isVisible = isGrid sliderGridCount.value = columnCount.toFloat() - chipGroupLayout.setOnCheckedChangeListener { _, checkedId -> - llGridSlider.isVisible = checkedId == R.id.chip_grid + chipGroupLayout.setOnCheckedStateChangeListener { group, checkedIds -> + sliderText.isVisible = checkedIds.firstOrNull() == R.id.chip_grid + sliderGridCount.isVisible = checkedIds.firstOrNull() == R.id.chip_grid } } @@ -205,10 +237,12 @@ abstract class BaseBookshelfFragment(layoutId: Int) : VMBaseFragment() private val fragmentMap = hashMapOf() override val groupId: Long get() = selectedGroup?.groupId ?: 0 diff --git a/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/style1/BookshelfFragment3.kt b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/style1/BookshelfFragment3.kt new file mode 100644 index 000000000..b8ce04bcc --- /dev/null +++ b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/style1/BookshelfFragment3.kt @@ -0,0 +1,144 @@ +@file:Suppress("DEPRECATION") + +package io.legato.kazusa.ui.main.bookshelf.style1 + +import android.annotation.SuppressLint +import android.os.Bundle +import android.view.View +import androidx.appcompat.widget.SearchView +import androidx.fragment.app.Fragment +import androidx.viewpager2.adapter.FragmentStateAdapter +import androidx.viewpager2.widget.ViewPager2 +import com.google.android.material.tabs.TabLayout +import io.legato.kazusa.R +import io.legato.kazusa.data.appDb +import io.legato.kazusa.data.entities.Book +import io.legato.kazusa.data.entities.BookGroup +import io.legato.kazusa.databinding.FragmentBookshelf3Binding +import io.legato.kazusa.help.config.AppConfig +import io.legato.kazusa.ui.book.search.SearchActivity +import io.legato.kazusa.ui.main.bookshelf.BaseBookshelfFragment +import io.legato.kazusa.ui.main.bookshelf.style1.books.BooksFragment +import io.legato.kazusa.utils.viewbindingdelegate.viewBinding +import kotlin.collections.set + +/** + * 书架界面 + */ +class BookshelfFragment3() : BaseBookshelfFragment(R.layout.fragment_bookshelf3), + TabLayout.OnTabSelectedListener, + SearchView.OnQueryTextListener { + + constructor(position: Int) : this() { + val bundle = Bundle() + bundle.putInt("position", position) + arguments = bundle + } + + private val binding by viewBinding(FragmentBookshelf3Binding::bind) + + private val bookGroups = mutableListOf() + private val fragmentMap = hashMapOf() + override val groupId: Long get() = selectedGroup?.groupId ?: 0 + + private lateinit var adapter: TabFragmentPageAdapter + + override val books: List + get() { + val fragment = fragmentMap[groupId] + return fragment?.getBooks() ?: emptyList() + } + + override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { + setSupportToolbar(binding.topBar) + initView() + initBookGroupData() + } + + private val selectedGroup: BookGroup? + get() = bookGroups.getOrNull(binding.viewPagerBookshelf.currentItem) + + private fun initView() { + adapter = TabFragmentPageAdapter(this) + binding.viewPagerBookshelf.adapter = adapter + binding.viewPagerBookshelf.offscreenPageLimit = 1 + + binding.viewPagerBookshelf.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { + override fun onPageSelected(position: Int) { + super.onPageSelected(position) + updateToolbarTitle(position) + } + }) + } + + private fun updateToolbarTitle(position: Int) { + if (bookGroups.isNotEmpty() && position in 0 until bookGroups.size) { + binding.collTopBar.title = bookGroups[position].groupName + } + } + + override fun onQueryTextSubmit(query: String?): Boolean { + SearchActivity.start(requireContext(), query) + return false + } + + override fun onQueryTextChange(newText: String?): Boolean { + return false + } + + @SuppressLint("NotifyDataSetChanged") + @Synchronized + override fun upGroup(data: List) { + if (data.isEmpty()) { + appDb.bookGroupDao.enableGroup(BookGroup.IdAll) + } else { + if (data != bookGroups) { + bookGroups.clear() + bookGroups.addAll(data) + adapter.notifyDataSetChanged() + adapter = TabFragmentPageAdapter(this) + binding.viewPagerBookshelf.adapter = adapter + + updateToolbarTitle(binding.viewPagerBookshelf.currentItem) + } + } + } + + override fun upSort() { + childFragmentManager.fragments.forEach { + if (it is BooksFragment) { + val position = it.position + val group = bookGroups.getOrNull(position) ?: return@forEach + val newSort = group.getRealBookSort() + it.setEnableRefresh(group.enableRefresh) + if (it.bookSort != newSort) { + it.upBookSort(newSort) + } + } + } + } + + override fun onTabReselected(tab: TabLayout.Tab) { + } + + override fun onTabUnselected(tab: TabLayout.Tab) = Unit + + override fun onTabSelected(tab: TabLayout.Tab) { + AppConfig.saveTabPosition = tab.position + } + + override fun gotoTop() { + fragmentMap[groupId]?.gotoTop() + } + + private inner class TabFragmentPageAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) { + override fun getItemCount(): Int = bookGroups.size + + override fun createFragment(position: Int): Fragment { + val group = bookGroups[position] + val fragment = BooksFragment(position, group) + fragmentMap[group.groupId] = fragment + return fragment + } + } +} \ No newline at end of file diff --git a/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/style1/books/BooksAdapterList.kt b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/style1/books/BooksAdapterList.kt index 4d967a8dc..8b79b9589 100644 --- a/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/style1/books/BooksAdapterList.kt +++ b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/style1/books/BooksAdapterList.kt @@ -3,6 +3,7 @@ package io.legato.kazusa.ui.main.bookshelf.style1.books import android.content.Context import android.os.Bundle import android.view.ViewGroup +import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.lifecycle.Lifecycle import io.legato.kazusa.base.adapter.ItemViewHolder @@ -10,7 +11,6 @@ import io.legato.kazusa.data.entities.Book import io.legato.kazusa.databinding.ItemBookshelfListBinding import io.legato.kazusa.help.book.isLocal import io.legato.kazusa.help.config.AppConfig -import io.legato.kazusa.utils.invisible import io.legato.kazusa.utils.toTimeAgo import splitties.views.onLongClick @@ -68,15 +68,16 @@ class BooksAdapterList( private fun upRefresh(binding: ItemBookshelfListBinding, item: Book) { if (!item.isLocal && callBack.isUpdate(item.bookUrl)) { - binding.bvUnread.invisible() - binding.rlLoading.visible() + binding.tvUnread.isVisible = false + binding.rlLoading.isVisible = true } else { - binding.rlLoading.gone() + binding.rlLoading.isVisible = false if (AppConfig.showUnread) { - binding.bvUnread.setHighlight(item.lastCheckCount > 0) - binding.bvUnread.setBadgeCount(item.getUnreadChapterNum()) + //binding.tvUnread.setHighlight(item.lastCheckCount > 0) + binding.tvUnread.isVisible = true + binding.tvUnread.text = item.getUnreadChapterNum().toString() } else { - binding.bvUnread.invisible() + binding.tvUnread.isVisible = false } } } @@ -94,13 +95,13 @@ class BooksAdapterList( override fun registerListener(holder: ItemViewHolder, binding: ItemBookshelfListBinding) { holder.itemView.apply { - setOnClickListener { + binding.cvContent.setOnClickListener { getItem(holder.layoutPosition)?.let { callBack.open(it) } } - onLongClick { + binding.cvContent.onLongClick { getItem(holder.layoutPosition)?.let { callBack.openBookInfo(it) } diff --git a/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/style2/BaseBooksAdapter.kt b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/style2/BaseBooksAdapter.kt index 4d057ad7b..e1ce29dd1 100644 --- a/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/style2/BaseBooksAdapter.kt +++ b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/style2/BaseBooksAdapter.kt @@ -46,10 +46,7 @@ abstract class BaseBooksAdapter( oldItem.getUnreadChapterNum() == newItem.getUnreadChapterNum() } - oldItem is BookGroup && newItem is BookGroup -> { - oldItem.groupName == newItem.groupName && - oldItem.cover == newItem.cover - } + oldItem is BookGroup && newItem is BookGroup -> false else -> false } @@ -120,6 +117,12 @@ abstract class BaseBooksAdapter( fun getItem(position: Int) = getItems().getOrNull(position) + internal var allBooks: List = emptyList() + + fun setAllBooks(all: List) { + this.allBooks = all + } + override fun getItemCount(): Int { return getItems().size } diff --git a/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/style2/BooksAdapterGrid.kt b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/style2/BooksAdapterGrid.kt index fd3963c4b..f33c81a14 100644 --- a/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/style2/BooksAdapterGrid.kt +++ b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/style2/BooksAdapterGrid.kt @@ -4,13 +4,16 @@ import android.content.Context import android.os.Bundle import android.view.View import android.view.ViewGroup +import androidx.core.content.ContextCompat import androidx.recyclerview.widget.RecyclerView +import io.legato.kazusa.R import io.legato.kazusa.data.entities.Book import io.legato.kazusa.data.entities.BookGroup import io.legato.kazusa.databinding.ItemBookshelfGridBinding import io.legato.kazusa.databinding.ItemBookshelfGridGroupBinding import io.legato.kazusa.help.book.isLocal import io.legato.kazusa.help.config.AppConfig +import io.legato.kazusa.utils.gone import splitties.views.onLongClick @Suppress("UNUSED_PARAMETER") @@ -32,31 +35,40 @@ class BooksAdapterGrid(context: Context, callBack: CallBack) : position: Int, payloads: MutableList ) { + when (holder) { is BookViewHolder -> (getItem(position) as? Book)?.let { holder.registerListener(it) - holder.onBind(it, position, payloads) + holder.onBind(it, payloads) } is GroupViewHolder -> (getItem(position) as? BookGroup)?.let { holder.registerListener(it) - holder.onBind(it, position, payloads) + holder.onBind(it, payloads) } } } + private fun getBooksForGroup(group: BookGroup): List { + return if (group.groupId == -1L) { + allBooks.take(4) + } else { + allBooks.filter { (it.group and group.groupId) != 0L }.take(4) + } + } + inner class BookViewHolder(val binding: ItemBookshelfGridBinding) : RecyclerView.ViewHolder(binding.root) { - fun onBind(item: Book, position: Int) = binding.run { + fun onBind(item: Book) = binding.run { tvName.text = item.name ivCover.load(item.getDisplayCover(), item.name, item.author, false, item.origin) upRefresh(this, item) } - fun onBind(item: Book, position: Int, payloads: MutableList) = binding.run { + fun onBind(item: Book, payloads: MutableList) = binding.run { if (payloads.isEmpty()) { - onBind(item, position) + onBind(item) } else { for (i in payloads.indices) { val bundle = payloads[i] as Bundle @@ -79,10 +91,10 @@ class BooksAdapterGrid(context: Context, callBack: CallBack) : } fun registerListener(item: Any) { - binding.root.setOnClickListener { + binding.cvContent.setOnClickListener { callBack.onItemClick(item) } - binding.root.onLongClick { + binding.cvContent.onLongClick { callBack.onItemLongClick(item) } } @@ -113,21 +125,22 @@ class BooksAdapterGrid(context: Context, callBack: CallBack) : inner class GroupViewHolder(val binding: ItemBookshelfGridGroupBinding) : RecyclerView.ViewHolder(binding.root) { - fun onBind(item: BookGroup, position: Int) = binding.run { + fun onBind(item: BookGroup) = binding.run { tvName.text = item.groupName - ivCover.load(item.cover) + loadGroupCover(item) + cdUnread.gone() } - fun onBind(item: BookGroup, position: Int, payloads: MutableList) = binding.run { + fun onBind(item: BookGroup, payloads: MutableList) = binding.run { if (payloads.isEmpty()) { - onBind(item, position) + onBind(item) } else { for (i in payloads.indices) { val bundle = payloads[i] as Bundle bundle.keySet().forEach { when (it) { "groupName" -> tvName.text = item.groupName - "cover" -> ivCover.load(item.cover) + "cover" -> loadGroupCover(item) } } } @@ -143,6 +156,28 @@ class BooksAdapterGrid(context: Context, callBack: CallBack) : } } + private fun loadGroupCover(item: BookGroup) = binding.run { + + binding.ivCover.setImageDrawable( + ContextCompat.getDrawable(binding.root.context, R.drawable.bg_surface_variant) + ) + binding.ivCover1.setImageDrawable(null) + binding.ivCover2.setImageDrawable(null) + binding.ivCover3.setImageDrawable(null) + binding.ivCover4.setImageDrawable(null) + if (!item.cover.isNullOrEmpty()) { + ivCover.load(item.cover) + } else { + + val books = getBooksForGroup(item) + + if (books.size > 0) binding.ivCover1.load(books[0].getDisplayCover()) + if (books.size > 1) binding.ivCover2.load(books[1].getDisplayCover()) + if (books.size > 2) binding.ivCover3.load(books[2].getDisplayCover()) + if (books.size > 3) binding.ivCover4.load(books[3].getDisplayCover()) + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/style2/BooksAdapterList.kt b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/style2/BooksAdapterList.kt index 058aaf5c2..8cc050944 100644 --- a/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/style2/BooksAdapterList.kt +++ b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/style2/BooksAdapterList.kt @@ -3,7 +3,10 @@ package io.legato.kazusa.ui.main.bookshelf.style2 import android.content.Context import android.os.Bundle import android.view.ViewGroup +import androidx.core.content.ContextCompat +import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView +import io.legato.kazusa.R import io.legato.kazusa.data.entities.Book import io.legato.kazusa.data.entities.BookGroup import io.legato.kazusa.databinding.ItemBookshelfListBinding @@ -11,7 +14,7 @@ import io.legato.kazusa.databinding.ItemBookshelfListGroupBinding import io.legato.kazusa.help.book.isLocal import io.legato.kazusa.help.config.AppConfig import io.legato.kazusa.utils.gone -import io.legato.kazusa.utils.invisible +import io.legato.kazusa.utils.toTimeAgo import io.legato.kazusa.utils.visible import splitties.views.onLongClick @@ -34,35 +37,44 @@ class BooksAdapterList(context: Context, callBack: CallBack) : when (holder) { is BookViewHolder -> (getItem(position) as? Book)?.let { holder.registerListener(it) - holder.onBind(it, position, payloads) + holder.onBind(it, payloads) } is GroupViewHolder -> (getItem(position) as? BookGroup)?.let { holder.registerListener(it) - holder.onBind(it, position, payloads) + holder.onBind(it, payloads) } } } + private fun getBooksForGroup(group: BookGroup): List { + return if (group.groupId == -1L) { + allBooks.take(4) + } else { + allBooks.filter { (it.group and group.groupId) != 0L }.take(4) + } + } + inner class BookViewHolder(val binding: ItemBookshelfListBinding) : RecyclerView.ViewHolder(binding.root) { - fun onBind(item: Book, position: Int) = binding.run { + fun onBind(item: Book) = binding.run { tvName.text = item.name tvAuthor.text = item.author tvRead.text = item.durChapterTitle tvLast.text = item.latestChapterTitle ivCover.load(item.getDisplayCover(), item.name, item.author, false, item.origin) - flHasNew.visible() + cdUnread.visible() ivAuthor.visible() ivLast.visible() ivRead.visible() upRefresh(this, item) + upLastUpdateTime(binding, item) } - fun onBind(item: Book, position: Int, payloads: MutableList) = binding.run { + fun onBind(item: Book, payloads: MutableList) = binding.run { if (payloads.isEmpty()) { - onBind(item, position) + onBind(item) } else { for (i in payloads.indices) { val bundle = payloads[i] as Bundle @@ -81,32 +93,45 @@ class BooksAdapterList(context: Context, callBack: CallBack) : ) "refresh" -> upRefresh(this, item) + "lastUpdateTime" -> upLastUpdateTime(binding, item) } } } } } + private fun upLastUpdateTime(binding: ItemBookshelfListBinding, item: Book) { + if (AppConfig.showLastUpdateTime && !item.isLocal) { + val time = item.latestChapterTime.toTimeAgo() + if (binding.tvLastUpdateTime.text != time) { + binding.tvLastUpdateTime.text = time + } + } else { + binding.tvLastUpdateTime.text = "" + } + } + fun registerListener(item: Any) { - binding.root.setOnClickListener { + binding.cvContent.setOnClickListener { callBack.onItemClick(item) } - binding.root.onLongClick { + binding.cvContent.onLongClick { callBack.onItemLongClick(item) } } private fun upRefresh(binding: ItemBookshelfListBinding, item: Book) { if (!item.isLocal && callBack.isUpdate(item.bookUrl)) { - binding.bvUnread.invisible() - binding.rlLoading.visible() + binding.tvUnread.isVisible = false + binding.rlLoading.isVisible = true } else { - binding.rlLoading.gone() + binding.rlLoading.isVisible = false if (AppConfig.showUnread) { - binding.bvUnread.setHighlight(item.lastCheckCount > 0) - binding.bvUnread.setBadgeCount(item.getUnreadChapterNum()) + //binding.tvUnread.setHighlight(item.lastCheckCount > 0) + binding.tvUnread.isVisible = true + binding.tvUnread.text = item.getUnreadChapterNum().toString() } else { - binding.bvUnread.invisible() + binding.tvUnread.isVisible = false } } } @@ -116,28 +141,23 @@ class BooksAdapterList(context: Context, callBack: CallBack) : inner class GroupViewHolder(val binding: ItemBookshelfListGroupBinding) : RecyclerView.ViewHolder(binding.root) { - fun onBind(item: BookGroup, position: Int) = binding.run { + fun onBind(item: BookGroup) = binding.run { tvName.text = item.groupName - ivCover.load(item.cover) - flHasNew.gone() - ivAuthor.gone() - ivLast.gone() - ivRead.gone() - tvAuthor.gone() - tvLast.gone() - tvRead.gone() + loadGroupCover(item) + cdUnread.gone() } - fun onBind(item: BookGroup, position: Int, payloads: MutableList) = binding.run { + + fun onBind(item: BookGroup, payloads: MutableList) = binding.run { if (payloads.isEmpty()) { - onBind(item, position) + onBind(item) } else { for (i in payloads.indices) { val bundle = payloads[i] as Bundle bundle.keySet().forEach { when (it) { "groupName" -> tvName.text = item.groupName - "cover" -> ivCover.load(item.cover) + "cover" -> loadGroupCover(item) } } } @@ -145,14 +165,36 @@ class BooksAdapterList(context: Context, callBack: CallBack) : } fun registerListener(item: Any) { - binding.root.setOnClickListener { + binding.cvContent.setOnClickListener { callBack.onItemClick(item) } - binding.root.onLongClick { + binding.cvContent.onLongClick { callBack.onItemLongClick(item) } } + private fun loadGroupCover(item: BookGroup) = binding.run { + + binding.ivCover.setImageDrawable( + ContextCompat.getDrawable(binding.root.context, R.drawable.bg_surface_variant) + ) + binding.ivCover1.setImageDrawable(null) + binding.ivCover2.setImageDrawable(null) + binding.ivCover3.setImageDrawable(null) + binding.ivCover4.setImageDrawable(null) + if (!item.cover.isNullOrEmpty()) { + ivCover.load(item.cover) + } else { + + val books = getBooksForGroup(item) + + if (books.size > 0) binding.ivCover1.load(books[0].getDisplayCover()) + if (books.size > 1) binding.ivCover2.load(books[1].getDisplayCover()) + if (books.size > 2) binding.ivCover3.load(books[2].getDisplayCover()) + if (books.size > 3) binding.ivCover4.load(books[3].getDisplayCover()) + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/style2/BookshelfFragment2.kt b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/style2/BookshelfFragment2.kt index 2fd729138..2d75a2d10 100644 --- a/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/style2/BookshelfFragment2.kt +++ b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/style2/BookshelfFragment2.kt @@ -7,6 +7,7 @@ import androidx.appcompat.widget.SearchView import androidx.core.view.isGone import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope +import androidx.recyclerview.widget.DefaultItemAnimator import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -19,8 +20,6 @@ import io.legato.kazusa.data.entities.Book import io.legato.kazusa.data.entities.BookGroup import io.legato.kazusa.databinding.FragmentBookshelf2Binding import io.legato.kazusa.help.config.AppConfig -//import io.legado.app.lib.theme.accentColor -//import io.legado.app.lib.theme.primaryColor import io.legato.kazusa.ui.book.group.GroupEditDialog import io.legato.kazusa.ui.book.info.BookInfoActivity import io.legato.kazusa.ui.book.search.SearchActivity @@ -35,7 +34,6 @@ import io.legato.kazusa.utils.startActivityForBook import io.legato.kazusa.utils.viewbindingdelegate.viewBinding import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job -import kotlinx.coroutines.delay import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.conflate import kotlinx.coroutines.flow.flowOn @@ -67,9 +65,11 @@ class BookshelfFragment2() : BaseBookshelfFragment(R.layout.fragment_bookshelf2) BooksAdapterGrid(requireContext(), this) } } + private var bookGroups: List = emptyList() private var booksFlowJob: Job? = null override var groupId = BookGroup.IdRoot + private var allBooks: List = emptyList() override var books: List = emptyList() private var enableRefresh = true @@ -77,12 +77,11 @@ class BookshelfFragment2() : BaseBookshelfFragment(R.layout.fragment_bookshelf2) setSupportToolbar(binding.titleBar.toolbar) initRecyclerView() initBookGroupData() + initAllBooksData() initBooksData() } private fun initRecyclerView() { -// binding.rvBookshelf.setEdgeEffectColor(primaryColor) -// binding.refreshLayout.setColorSchemeColors(accentColor) binding.refreshLayout.setOnRefreshListener { binding.refreshLayout.isRefreshing = false activityViewModel.upToc(books) @@ -111,6 +110,7 @@ class BookshelfFragment2() : BaseBookshelfFragment(R.layout.fragment_bookshelf2) } } }) + binding.rvBookshelf.itemAnimator = DefaultItemAnimator() } override fun upGroup(data: List) { @@ -123,9 +123,37 @@ class BookshelfFragment2() : BaseBookshelfFragment(R.layout.fragment_bookshelf2) } override fun upSort() { + initAllBooksData() initBooksData() } + private var allBooksFlowJob: Job? = null + + private fun initAllBooksData() { + allBooksFlowJob?.cancel() + allBooksFlowJob = viewLifecycleOwner.lifecycleScope.launch { + appDb.bookDao.flowAll().map { list -> + when (AppConfig.getBookSortByGroupId(BookGroup.IdRoot)) { + 1 -> list.sortedByDescending { it.latestChapterTime } + 2 -> list.sortedWith { o1, o2 -> o1.name.cnCompare(o2.name) } + 3 -> list.sortedBy { it.order } + 4 -> list.sortedByDescending { max(it.latestChapterTime, it.durChapterTime) } + else -> list.sortedByDescending { it.durChapterTime } + } + }.flowWithLifecycleAndDatabaseChangeFirst( + viewLifecycleOwner.lifecycle, + Lifecycle.State.RESUMED, + AppDatabase.BOOK_TABLE_NAME + ).catch { + AppLog.put("所有书籍更新出错", it) + }.conflate().flowOn(Dispatchers.Default).collect { list -> + allBooks = list + booksAdapter.setAllBooks(allBooks) + booksAdapter.updateItems() + } + } + } + private fun initBooksData() { if (groupId == BookGroup.IdRoot) { if (isAdded) { @@ -137,14 +165,16 @@ class BookshelfFragment2() : BaseBookshelfFragment(R.layout.fragment_bookshelf2) bookGroups.firstOrNull { groupId == it.groupId }?.let { - binding.titleBar.title = "${getString(R.string.bookshelf)}(${it.groupName})" + binding.titleBar.title = it.groupName binding.refreshLayout.isEnabled = it.enableRefresh enableRefresh = it.enableRefresh } } booksFlowJob?.cancel() booksFlowJob = viewLifecycleOwner.lifecycleScope.launch { + appDb.bookDao.flowByGroup(groupId).map { list -> + //排序 when (AppConfig.getBookSortByGroupId(groupId)) { 1 -> list.sortedByDescending { @@ -178,7 +208,6 @@ class BookshelfFragment2() : BaseBookshelfFragment(R.layout.fragment_bookshelf2) booksAdapter.updateItems() binding.tvEmptyMsg.isGone = getItemCount() > 0 binding.refreshLayout.isEnabled = enableRefresh && getItemCount() > 0 - delay(100) } } } @@ -244,12 +273,14 @@ class BookshelfFragment2() : BaseBookshelfFragment(R.layout.fragment_bookshelf2) } override fun getItems(): List { - if (groupId != BookGroup.IdRoot) { - return books + return if (groupId == BookGroup.IdRoot) { + bookGroups + books + } else { + books } - return bookGroups + books } + @SuppressLint("NotifyDataSetChanged") override fun observeLiveBus() { super.observeLiveBus() diff --git a/app/src/main/java/io/legato/kazusa/ui/widget/LabelsBar.kt b/app/src/main/java/io/legato/kazusa/ui/widget/LabelsBar.kt index a8ecda5ae..7e85edb77 100644 --- a/app/src/main/java/io/legato/kazusa/ui/widget/LabelsBar.kt +++ b/app/src/main/java/io/legato/kazusa/ui/widget/LabelsBar.kt @@ -2,11 +2,10 @@ package io.legato.kazusa.ui.widget import android.content.Context import android.content.res.ColorStateList -import android.graphics.Color import android.util.AttributeSet import com.google.android.material.chip.Chip import com.google.android.material.chip.ChipGroup -import com.google.android.material.color.MaterialColors +import io.legato.kazusa.utils.themeColor @Suppress("unused", "MemberVisibilityCanBePrivate") class LabelsBar @JvmOverloads constructor( @@ -44,10 +43,9 @@ class LabelsBar @JvmOverloads constructor( chipStrokeWidth = 0f chipBackgroundColor = ColorStateList.valueOf( - MaterialColors.getColor(this, com.google.android.material.R.attr.colorPrimaryContainer, Color.LTGRAY) + context.themeColor(com.google.android.material.R.attr.colorPrimaryContainer) ) - usedChips.add(this) } } else { diff --git a/app/src/main/res/anim/anim_readbook_bottom_in.xml b/app/src/main/res/anim/anim_readbook_bottom_in.xml index 792ae66b0..3c2a68d11 100644 --- a/app/src/main/res/anim/anim_readbook_bottom_in.xml +++ b/app/src/main/res/anim/anim_readbook_bottom_in.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_book_mask_land.xml b/app/src/main/res/drawable/bg_book_mask_land.xml new file mode 100644 index 000000000..f250bea0c --- /dev/null +++ b/app/src/main/res/drawable/bg_book_mask_land.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_gradient.xml b/app/src/main/res/drawable/bg_gradient.xml deleted file mode 100644 index 6c2f91672..000000000 --- a/app/src/main/res/drawable/bg_gradient.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_gradient_mask_land.xml b/app/src/main/res/drawable/bg_gradient_mask_land.xml index f81651d17..3a17e83a2 100644 --- a/app/src/main/res/drawable/bg_gradient_mask_land.xml +++ b/app/src/main/res/drawable/bg_gradient_mask_land.xml @@ -2,7 +2,7 @@ - + + + + diff --git a/app/src/main/res/layout-land/activity_book_info.xml b/app/src/main/res/layout-land/activity_book_info.xml index 560bef1ad..468ad46ef 100644 --- a/app/src/main/res/layout-land/activity_book_info.xml +++ b/app/src/main/res/layout-land/activity_book_info.xml @@ -10,7 +10,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:contentDescription="@string/bg_image" - android:foreground="@drawable/bg_book_mask" + android:foreground="@drawable/bg_book_mask_land" android:scaleType="centerCrop" /> - + android:layout_weight="2" + android:fillViewport="true" + android:fitsSystemWindows="false" + android:focusable="true" + android:padding="0dp" + android:scrollbarStyle="outsideOverlay" + android:scrollbars="vertical"> - - - - - - + android:baselineAligned="false" + android:orientation="horizontal"> + android:paddingHorizontal="32dp" + tools:ignore="RtlSymmetry"> - + android:layout_marginTop="16dp" + android:layout_marginStart="32dp" + app:cardCornerRadius="16dp"> + + + + - - - - - - - - - - - - - - - - - - - - + android:paddingTop="16dp" + android:paddingHorizontal="30dp"> - - - - - + android:text="@string/book_name" + style="@style/TextAppearance.Material3.ActionBar.Title" + tools:ignore="RtlHardcoded" /> + android:gravity="center" + android:orientation="horizontal" + android:paddingTop="6dp" + android:paddingBottom="2dp" + tools:ignore="UseCompoundDrawables"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + tools:ignore="NestedWeights,RtlHardcoded,RtlSymmetry" + tools:text="@string/read_chapter_total" /> + + - - - - - - - - - - + tools:text="@string/read_chapter_index"/> - - - - + + + + + + @@ -275,7 +275,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingBottom="6dp" - android:singleLine="true" android:textSize="14sp" tools:ignore="NestedWeights,RtlHardcoded,RtlSymmetry" tools:text="@string/read_dur_progress" /> @@ -289,7 +288,7 @@ android:id="@+id/tv_chapter" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textColor="?attr/colorSecondaryVariant" + android:textColor="?attr/colorPrimaryVariant" android:singleLine="true" android:paddingEnd="8dp" android:textSize="14sp" diff --git a/app/src/main/res/layout/dialog_book_group_edit.xml b/app/src/main/res/layout/dialog_book_group_edit.xml index be5fe2c2c..b44a2fcd5 100644 --- a/app/src/main/res/layout/dialog_book_group_edit.xml +++ b/app/src/main/res/layout/dialog_book_group_edit.xml @@ -19,7 +19,7 @@ @@ -30,7 +30,7 @@ android:layout_margin="8dp" android:contentDescription="@string/img_cover" android:scaleType="centerCrop" - android:src="@drawable/image_cover_default" + android:src="?attr/colorSurfaceVariant" tools:ignore="ImageContrastCheck" /> + @@ -95,10 +96,18 @@ android:id="@+id/btn_delete" android:layout_width="wrap_content" android:layout_height="wrap_content" - style="@style/Widget.Material3.Button.OutlinedButton" - android:text="@string/delete" + style="@style/Widget.Material3.Button.IconButton.Outlined" + android:layout_marginEnd="4dp" + app:icon="@drawable/ic_clear_all" tools:ignore="RtlHardcoded" /> + + + + @@ -24,7 +31,6 @@ android:id="@+id/sw_show_last_update_time" android:layout_width="match_parent" android:layout_height="wrap_content" - android:padding="8dp" android:text="@string/show_last_update_time" tools:ignore="TouchTargetSizeCheck" /> @@ -32,7 +38,6 @@ android:id="@+id/sw_show_wait_up_books" android:layout_width="match_parent" android:layout_height="wrap_content" - android:padding="8dp" android:text="@string/show_wait_up_count" tools:ignore="TouchTargetSizeCheck" /> @@ -40,31 +45,35 @@ android:id="@+id/sw_show_bookshelf_fast_scroller" android:layout_width="match_parent" android:layout_height="wrap_content" - android:padding="8dp" android:text="@string/show_bookshelf_fast_scroller" tools:ignore="TouchTargetSizeCheck" /> - + android:paddingTop="8dp" + android:text="@string/group_style" + android:textSize="14sp" + android:textStyle="bold" /> - + + - - + + android:paddingBottom="8dp"> - + android:text="每行列数" + android:textSize="14sp" + android:textStyle="bold" + android:paddingTop="8dp" /> - - - - - - + android:paddingVertical="8dp" + android:valueFrom="1" + android:valueTo="9" + android:stepSize="1" + android:value="3" /> - + - + - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/fragment_bookshelf1.xml b/app/src/main/res/layout/fragment_bookshelf1.xml index d62d0b5cd..f6a5a16ec 100644 --- a/app/src/main/res/layout/fragment_bookshelf1.xml +++ b/app/src/main/res/layout/fragment_bookshelf1.xml @@ -16,8 +16,8 @@ - + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_bookshelf_grid_group.xml b/app/src/main/res/layout/item_bookshelf_grid_group.xml index 18913c712..27838835e 100644 --- a/app/src/main/res/layout/item_bookshelf_grid_group.xml +++ b/app/src/main/res/layout/item_bookshelf_grid_group.xml @@ -2,88 +2,150 @@ + android:layout_height="wrap_content"> - - - - - - - - - - - - - + android:orientation="vertical"> - + - + + + + + + + + + + + + + + + + + + + + + + + - - - diff --git a/app/src/main/res/layout/item_bookshelf_list.xml b/app/src/main/res/layout/item_bookshelf_list.xml index 8ecb8ba74..0234b2dbc 100644 --- a/app/src/main/res/layout/item_bookshelf_list.xml +++ b/app/src/main/res/layout/item_bookshelf_list.xml @@ -1,196 +1,199 @@ - + android:layout_marginVertical="4dp" + app:strokeWidth="0dp"> - - - + android:clickable="true" + android:focusable="true" + android:background="?attr/selectableItemBackground" + tools:ignore="UnusedAttribute"> - + + + + + + + + + + + + + + + + + + + android:singleLine="true" + android:text="@string/author" + android:textSize="13sp" + tools:ignore="RtlSymmetry,TextContrastCheck" + app:layout_constraintStart_toEndOf="@+id/iv_author" + app:layout_constraintBottom_toTopOf="@+id/iv_author" + app:layout_constraintTop_toBottomOf="@+id/iv_author" /> - - + - + - + - + - + - - + - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/item_bookshelf_list_group.xml b/app/src/main/res/layout/item_bookshelf_list_group.xml index 47d6d1ece..da6c4b32a 100644 --- a/app/src/main/res/layout/item_bookshelf_list_group.xml +++ b/app/src/main/res/layout/item_bookshelf_list_group.xml @@ -1,165 +1,152 @@ - + android:layout_marginVertical="4dp" + app:strokeWidth="0dp"> - - - - - - - - - - - - - - - - - - - - - - - - + android:layout_height="wrap_content" + android:clickable="true" + android:focusable="true" + android:background="?attr/selectableItemBackground" + tools:ignore="UnusedAttribute"> - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_preference.xml b/app/src/main/res/layout/view_preference.xml index ddc03acb6..2bc507f1d 100644 --- a/app/src/main/res/layout/view_preference.xml +++ b/app/src/main/res/layout/view_preference.xml @@ -39,7 +39,7 @@ 标签 文件夹 + 隐藏标签 @@ -113,4 +114,14 @@ 自定义 + + @string/bookshelf_px_0 + @string/bookshelf_px_1 + @string/bookshelf_px_2 + @string/bookshelf_px_3 + @string/bookshelf_px_4 + @string/bookshelf_px_5 + + + \ No newline at end of file diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 239d1d40c..521bb7110 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -2,7 +2,7 @@ 阅读 阅读·A - 阅读·搜索 + 阅读 · 搜索 阅读需要访问存储卡权限,请前往“设置”—“应用权限”,打开所需权限 @@ -42,7 +42,7 @@ 配置替换净化规则 暂无 启用 - 替换净化-搜索 + 替换净化 - 搜索 书架 收藏夹 收藏 @@ -449,7 +449,7 @@ 图片 URL 规则(ruleImage) 内容规则(ruleContent) 样式(style) - 注入Js(injectJs) + 注入Js (injectJs) 链接规则(ruleLink) 校验关键字(checkKeyWord) 操作(actions) @@ -461,7 +461,7 @@ 书籍信息获取失败 内容获取失败 目录获取失败 - 访问网站失败:%s + 访问网站失败: %s 文件读取失败 加载目录失败 获取数据失败! @@ -501,10 +501,10 @@ 确认 - 是否确认删除? - 是否确认删除 %s? - 是否删除全部书籍? - 是否同时删除已下载的书籍目录? + 是否确认删除? + 是否确认删除 %s ? + 是否删除全部书籍? + 是否同时删除已下载的书籍目录? 扫描二维码需相机权限 朗读正在运行,不能自动翻页 输入编码 @@ -648,7 +648,7 @@ 自带文件夹选择器 自带文件选择器 Android 10 以上因系统权限限制可能无法读写文件 - 长按文字在操作菜单中显示阅读·搜索 + 长按文字在操作菜单中显示阅读 · 搜索 文字操作显示搜索 记录日志 日志 @@ -690,7 +690,7 @@ 默认 主菜单 点击授予权限 - 阅读需要访问存储卡权限,请点击下方的“授予权限”按钮,或前往“设置”—“应用权限”,打开所需权限。如果授予权限后仍然不正常,请点击右上角的“选择文件夹”,使用系统文件夹选择器。 + 阅读需要访问存储卡权限,请点击下方的“授予权限”按钮,或前往“设置” — “应用权限”,打开所需权限。如果授予权限后仍然不正常,请点击右上角的“选择文件夹”,使用系统文件夹选择器。 全文朗读中不能朗读选中文字 扩展到刘海 更新目录中 @@ -756,7 +756,7 @@ 清除已下载书籍和字体缓存 默认封面 恢复忽略列表 - 恢复时忽略一些内容不恢复,方便不同手机配置不同 + 选择恢复忽略内容 阅读界面设置 分组名称 备注内容 @@ -882,7 +882,7 @@ 自动备份失败\n%s 结束 关闭替换分组/开启添加分组 - 媒体按钮•上一首|下一首 + 媒体按钮 • 上一首|下一首 上一段|下一段/上一章|下一章 及时翻页,翻页时会停顿一下 校验显示详细信息 @@ -932,7 +932,7 @@ 查看登录头 登录头 字体大小 - 当前字体大小:%.1f + 当前字体大小: %.1f 语速减 语速加 打开系统文件夹选择器出错,将自动打开应用文件夹选择器 @@ -951,7 +951,7 @@ 超时 小于 - 校验超时:%1$s秒\n校验项目:%2$s + 校验超时: %1$s秒\n校验项目: %2$s 记录调试日志 子文件夹 全局 @@ -1022,8 +1022,8 @@ 远程书籍 阅读时长排序 阅读时间排序 - 阅读时长: - 最后阅读时间: + 阅读时长: + 最后阅读时间: 滑动翻页阈值 滑动翻页阈值(0 = 系统默认值) 滑动多长距离才会触发滑动翻页(系统默认值 %s px) @@ -1059,19 +1059,19 @@ 多线程导出 进度条行为 源编辑框最大行数 - %s,设置行数小于屏幕可显示的最大行数可以更方便的滑动到其他的字段进行编辑 + %s,设置行数小于屏幕可显示的最大行数可以更方便的滑动到其他的字段进行编辑 是否恢复到跳转前的阅读进度? 搜索范围 切换 是否确认清除所有搜索历史记录 禁用滚动点击动画 设备名称 - WebService唤醒锁 - 开启web服务的时候启用唤醒锁,有些手机开启唤醒锁会被杀后台 + WebService 唤醒锁 + 开启 Web 服务的时候启用唤醒锁,有些手机开启唤醒锁会被杀后台 朗读服务唤醒锁 - 开启朗读的时候启用唤醒锁,有些手机开启唤醒锁会被杀后台 + 开启朗读的时候启用唤醒锁,有些手机开启唤醒锁会被杀后台 音频服务唤醒锁 - 播放音频的时候启用唤醒锁,有些手机开启唤醒锁会被杀后台 + 播放音频的时候启用唤醒锁,有些手机开启唤醒锁会被杀后台 切换搜索范围 拷贝规则 粘贴规则 @@ -1083,7 +1083,7 @@ 移除重复标题 更新失败 阅读需要发送通知来显示朗读控制和下载进度 - webDav书源比本地新,是否恢复 + WebDav 书源比本地新,是否恢复 白名单(contentWhitelist) 黑名单(contentBlacklist) 确认 @@ -1094,13 +1094,13 @@ 字典规则 配置字典规则 新建 - url规则(urlRule) - 显示规则(showRule) + Url规则 (urlRule) + 显示规则 (showRule) 配置 TXT 目录规则 导入字典规则 保留分组 服务器配置 - 远程webDav链接已存在,是否继续 + 远程 WebDav 链接已存在,是否继续 压缩文件内没有支持的文件 没有设置书籍保存位置! 删除提醒 @@ -1117,10 +1117,10 @@ 选中新增源 选中更新源 设置本地密码 - 本地密码用来对备份的敏感信息加密和解密,如需在不同设备之间同步,本地密码需一致. + 本地密码用来对备份的敏感信息加密和解密,如需在不同设备之间同步,本地密码需一致。 仅保留最新备份 本地备份仅保留最新备份文件 - webDav应用验证失败 + WebDav 应用验证失败 加载字数 排除范围,选填书名或者书源 URL 格式化规则(formatJs) @@ -1141,7 +1141,7 @@ 按作者 起效的替换 导出书籍 - 正在导出(%1$s),还有%2$d本待导出 + 正在导出 (%1$s) ,还有 %2$d 本待导出 导出(MD) 换源间隔 结果 %1$d, 当前进度 %2$d / %3$d: %4$s @@ -1181,7 +1181,7 @@ 测试版 共存版 流式播放音频 - 即边下边播,网络不好时播放会断断续续,仅TTS源有效 + 边下边播,网络不好时播放会断断续续,仅TTS源有效 来电期间暂停朗读 在通话期间暂停朗读,需要读取手机状态权限 阅读需要读取手机状态实现来电期间暂停朗读功能 @@ -1197,7 +1197,7 @@ 开启滚动 页脚配置 设置自动翻页速度 - 页数. %1$d/%2$d 章节. %3$d/%4$d -> %5$s%% + 页数. %1$d/%2$d 章节. %3$d/%4$d -> %5$s%% 下载之后章节 下载全部章节 《章节和文案》隐藏 diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 9bdd2d108..dd3eed654 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -15,6 +15,7 @@ Tab Folder + Hide Tab @@ -195,4 +196,13 @@ Customize + + @string/bookshelf_px_0 + @string/bookshelf_px_1 + @string/bookshelf_px_2 + @string/bookshelf_px_3 + @string/bookshelf_px_4 + @string/bookshelf_px_5 + +