diff --git a/app/src/main/java/io/legato/kazusa/constant/PreferKey.kt b/app/src/main/java/io/legato/kazusa/constant/PreferKey.kt index b2e8d8bd4..9646c95b4 100644 --- a/app/src/main/java/io/legato/kazusa/constant/PreferKey.kt +++ b/app/src/main/java/io/legato/kazusa/constant/PreferKey.kt @@ -37,8 +37,8 @@ object PreferKey { const val enableReview = "enableReview" const val showRss = "showRss" const val bookshelfLayout = "bookshelfLayout" - const val bookshelfLayoutPortrait = "bookshelfLayoutPortrait" - const val bookshelfLayoutLandscape = "bookshelf_layout_landscape" + const val bookshelfLayoutModePortrait = "bookshelfLayoutPortrait" + const val bookshelfLayoutModeLandscape = "bookshelf_layout_landscape" const val bookshelfSort = "bookshelfSort" const val bookExportFileName = "bookExportFileName" const val bookImportFileName = "bookImportFileName" @@ -206,4 +206,10 @@ object PreferKey { const val notificationsPost = "notificationsPost" const val ignoreBatteryPermission = "ignoreBatteryPermission" const val paddingDisplayCutouts = "paddingDisplayCutouts" + + const val delayBookLoadEnable = "delayBookLoadEnable" + + const val bookshelfLayoutGridLandscape = "bookshelfLayoutGridLandscape" + + const val bookshelfLayoutGridPortrait = "bookshelfLayoutGridPortrait" } diff --git a/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/BookshelfConfigBottomSheet.kt b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/BookshelfConfigBottomSheet.kt index 682f87ef8..a6293e4db 100644 --- a/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/BookshelfConfigBottomSheet.kt +++ b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/BookshelfConfigBottomSheet.kt @@ -13,6 +13,7 @@ import io.legato.kazusa.constant.EventBus import io.legato.kazusa.databinding.DialogBookshelfConfigBinding import io.legato.kazusa.help.config.AppConfig import io.legato.kazusa.ui.main.MainViewModel +import io.legato.kazusa.utils.bookshelfLayoutGrid import io.legato.kazusa.utils.postEvent import io.legato.kazusa.utils.viewbindingdelegate.viewBinding @@ -26,13 +27,18 @@ class BookshelfConfigBottomSheet : BaseBottomSheetDialogFragment(R.layout.dialog val orientation = requireContext().resources.configuration.orientation val bookshelfLayout = if (orientation == Configuration.ORIENTATION_LANDSCAPE) { - AppConfig.bookshelfLayoutLandscape + AppConfig.bookshelfLayoutModeLandscape } else { - AppConfig.bookshelfLayoutPortrait + AppConfig.bookshelfLayoutModePortrait } - val isGrid = bookshelfLayout > 0 - val columnCount = bookshelfLayout.takeIf { it > 0 } ?: 1 + val isList = bookshelfLayout == 0 + val isGrid = bookshelfLayout == 1 + val isGridCompact = bookshelfLayout == 2 + val isGridCover = bookshelfLayout == 3 + + val columnCount = requireContext().bookshelfLayoutGrid.takeIf { it > 0 } ?: 1 + val bookshelfSort = AppConfig.bookshelfSort @@ -69,10 +75,12 @@ class BookshelfConfigBottomSheet : BaseBottomSheetDialogFragment(R.layout.dialog swShowWaitUpBooks.isChecked = AppConfig.showWaitUpCount swShowBookshelfFastScroller.isChecked = AppConfig.showBookshelfFastScroller - chipList.isChecked = !isGrid + chipList.isChecked = isList chipGrid.isChecked = isGrid - sliderText.isVisible = isGrid - sliderGridCount.isVisible = isGrid + chipGridCompact.isChecked = isGridCompact + chipGridCover.isChecked = isGridCover + sliderText.isVisible = isGrid || isGridCompact || isGridCover + sliderGridCount.isVisible = isGrid || isGridCompact || isGridCover sliderGridCount.value = columnCount.toFloat() when (AppConfig.bookshelfSortOrder) { @@ -80,10 +88,13 @@ class BookshelfConfigBottomSheet : BaseBottomSheetDialogFragment(R.layout.dialog 1 -> binding.chipGroupOrder.check(binding.chipDesc.id) } - chipGroupLayout.setOnCheckedStateChangeListener { group, checkedIds -> - sliderText.isVisible = checkedIds.firstOrNull() == R.id.chip_grid + chipGroupLayout.setOnCheckedStateChangeListener { _, checkedIds -> + val checkedId = checkedIds.firstOrNull() + val showSlider = + checkedId == R.id.chip_grid || checkedId == R.id.chip_grid_compact || checkedId == R.id.chip_grid_cover + sliderText.isVisible = showSlider TransitionManager.beginDelayedTransition(root) - sliderGridCount.isVisible = checkedIds.firstOrNull() == R.id.chip_grid + sliderGridCount.isVisible = showSlider } btnOk.setOnClickListener { @@ -91,7 +102,9 @@ class BookshelfConfigBottomSheet : BaseBottomSheetDialogFragment(R.layout.dialog var recreate = false if (AppConfig.bookGroupStyle != chipGroupStyle.checkedChipId) { - AppConfig.bookGroupStyle = chipGroupStyle.indexOfChild(chipGroupStyle.findViewById(chipGroupStyle.checkedChipId)) + AppConfig.bookGroupStyle = chipGroupStyle.indexOfChild( + chipGroupStyle.findViewById(chipGroupStyle.checkedChipId) + ) notifyMain = true } @@ -107,7 +120,6 @@ class BookshelfConfigBottomSheet : BaseBottomSheetDialogFragment(R.layout.dialog AppConfig.showWaitUpCount = swShowWaitUpBooks.isChecked activityViewModel.postUpBooksLiveData(true) } - if (AppConfig.showBookshelfFastScroller != swShowBookshelfFastScroller.isChecked) { AppConfig.showBookshelfFastScroller = swShowBookshelfFastScroller.isChecked postEvent(EventBus.BOOKSHELF_REFRESH, "") @@ -118,25 +130,29 @@ class BookshelfConfigBottomSheet : BaseBottomSheetDialogFragment(R.layout.dialog (requireParentFragment() as? BaseBookshelfFragment)?.upSort() } - val isNowGrid = chipGrid.isChecked val selectedColumn = sliderGridCount.value.toInt() - val newLayout = if (isNowGrid) selectedColumn else 0 + val newLayout = when { + chipList.isChecked -> 0 + chipGrid.isChecked -> 1 + chipGridCompact.isChecked -> 2 + chipGridCover.isChecked -> 3 + else -> 0 + } - if (bookshelfLayout != newLayout) { + val oldColumn = requireContext().bookshelfLayoutGrid + if (bookshelfLayout != newLayout || oldColumn != selectedColumn) { if (orientation == Configuration.ORIENTATION_LANDSCAPE) { - AppConfig.bookshelfLayoutLandscape = newLayout - if (newLayout == 0) { - activityViewModel.booksGridRecycledViewPool.clear() - } else { - activityViewModel.booksListRecycledViewPool.clear() - } + AppConfig.bookshelfLayoutModeLandscape = newLayout + AppConfig.bookshelfLayoutGridLandscape = selectedColumn } else { - AppConfig.bookshelfLayoutPortrait = newLayout - if (newLayout == 0) { - activityViewModel.booksGridRecycledViewPool.clear() - } else { - activityViewModel.booksListRecycledViewPool.clear() - } + AppConfig.bookshelfLayoutModePortrait = newLayout + AppConfig.bookshelfLayoutGridPortrait = selectedColumn + } + + if (newLayout == 0) { + activityViewModel.booksGridRecycledViewPool.clear() + } else { + activityViewModel.booksListRecycledViewPool.clear() } recreate = true } @@ -146,7 +162,6 @@ class BookshelfConfigBottomSheet : BaseBottomSheetDialogFragment(R.layout.dialog binding.chipDesc.id -> 1 else -> 1 } - if (AppConfig.bookshelfSortOrder != newOrder) { AppConfig.bookshelfSortOrder = newOrder (requireParentFragment() as? BaseBookshelfFragment)?.upSort() diff --git a/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/books/BooksFragment.kt b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/books/BooksFragment.kt index d966344ab..1746261d9 100644 --- a/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/books/BooksFragment.kt +++ b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/books/BooksFragment.kt @@ -36,8 +36,11 @@ import io.legato.kazusa.ui.book.read.ReadBookActivity import io.legato.kazusa.ui.main.MainViewModel import io.legato.kazusa.ui.main.bookshelf.books.styleDefalut.BaseBooksAdapter import io.legato.kazusa.ui.main.bookshelf.books.styleDefalut.BooksAdapterGrid +import io.legato.kazusa.ui.main.bookshelf.books.styleDefalut.BooksAdapterGridCompact +import io.legato.kazusa.ui.main.bookshelf.books.styleDefalut.BooksAdapterGridCover import io.legato.kazusa.ui.main.bookshelf.books.styleDefalut.BooksAdapterList -import io.legato.kazusa.utils.bookshelfLayout +import io.legato.kazusa.utils.bookshelfLayoutGrid +import io.legato.kazusa.utils.bookshelfLayoutMode import io.legato.kazusa.utils.cnCompare import io.legato.kazusa.utils.flowWithLifecycleAndDatabaseChangeFirst import io.legato.kazusa.utils.observeEvent @@ -71,14 +74,27 @@ class BooksFragment() : BaseFragment(R.layout.fragment_books), private val binding by viewBinding(FragmentBooksBinding::bind) private val activityViewModel by activityViewModels() - private val bookshelfLayout by lazy { requireContext().bookshelfLayout } + private val bookshelfLayoutMode by lazy { requireContext().bookshelfLayoutMode } + private val bookshelfLayoutGrid by lazy { requireContext().bookshelfLayoutGrid } private val booksAdapter: BaseBooksAdapter<*> by lazy { - if (bookshelfLayout == 0) { - BooksAdapterList(requireContext(), this, this, viewLifecycleOwner.lifecycle) - } else { - BooksAdapterGrid(requireContext(), this) + when (bookshelfLayoutMode) { + 0 -> { + BooksAdapterList(requireContext(), this, this, viewLifecycleOwner.lifecycle) + } + + 1 -> { + BooksAdapterGrid(requireContext(), this) + } + + 2 -> { + BooksAdapterGridCompact(requireContext(), this) + } + + else -> { + BooksAdapterGridCover(requireContext(), this) + } } } private var booksFlowJob: Job? = null @@ -111,14 +127,11 @@ class BooksFragment() : BaseFragment(R.layout.fragment_books), binding.refreshLayout.isRefreshing = false activityViewModel.upToc(booksAdapter.getItems()) } - if (bookshelfLayout == 0) { + if (bookshelfLayoutMode == 0) { binding.rvBookshelf.layoutManager = LinearLayoutManager(context) - } else { - binding.rvBookshelf.layoutManager = GridLayoutManager(context, bookshelfLayout) - } - if (bookshelfLayout == 0) { binding.rvBookshelf.setRecycledViewPool(activityViewModel.booksListRecycledViewPool) } else { + binding.rvBookshelf.layoutManager = GridLayoutManager(context, bookshelfLayoutGrid) binding.rvBookshelf.setRecycledViewPool(activityViewModel.booksGridRecycledViewPool) } booksAdapter.stateRestorationPolicy = StateRestorationPolicy.PREVENT_WHEN_EMPTY @@ -219,7 +232,7 @@ class BooksFragment() : BaseFragment(R.layout.fragment_books), private fun startLastUpdateTimeJob() { upLastUpdateTimeJob?.cancel() - if (!AppConfig.showLastUpdateTime || bookshelfLayout != 0) { + if (!AppConfig.showLastUpdateTime || bookshelfLayoutMode != 0) { return } upLastUpdateTimeJob = lifecycleScope.launch { diff --git a/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/books/BookshelfFragment2.kt b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/books/BookshelfFragment2.kt index 1d12a3cde..b460a116d 100644 --- a/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/books/BookshelfFragment2.kt +++ b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/books/BookshelfFragment2.kt @@ -33,8 +33,11 @@ import io.legato.kazusa.ui.book.search.SearchActivity import io.legato.kazusa.ui.main.bookshelf.BaseBookshelfFragment import io.legato.kazusa.ui.main.bookshelf.books.styleFold.BaseBooksAdapter import io.legato.kazusa.ui.main.bookshelf.books.styleFold.BooksAdapterGrid +import io.legato.kazusa.ui.main.bookshelf.books.styleFold.BooksAdapterGridCompact +import io.legato.kazusa.ui.main.bookshelf.books.styleFold.BooksAdapterGridCover import io.legato.kazusa.ui.main.bookshelf.books.styleFold.BooksAdapterList -import io.legato.kazusa.utils.bookshelfLayout +import io.legato.kazusa.utils.bookshelfLayoutGrid +import io.legato.kazusa.utils.bookshelfLayoutMode import io.legato.kazusa.utils.cnCompare import io.legato.kazusa.utils.flowWithLifecycleAndDatabaseChangeFirst import io.legato.kazusa.utils.observeEvent @@ -64,13 +67,27 @@ class BookshelfFragment2() : BaseBookshelfFragment(R.layout.fragment_bookshelf2) private val binding by viewBinding(FragmentBookshelf2Binding::bind) - private val bookshelfLayout by lazy { requireContext().bookshelfLayout } + private val bookshelfLayoutMode by lazy { requireContext().bookshelfLayoutMode } + + private val bookshelfLayoutGrid by lazy { requireContext().bookshelfLayoutGrid } private val booksAdapter: BaseBooksAdapter<*> by lazy { - if (bookshelfLayout == 0) { - BooksAdapterList(requireContext(), this) - } else { - BooksAdapterGrid(requireContext(), this) + when (bookshelfLayoutMode) { + 0 -> { + BooksAdapterList(requireContext(), this) + } + + 1 -> { + BooksAdapterGrid(requireContext(), this) + } + + 2 -> { + BooksAdapterGridCompact(requireContext(), this) + } + + else -> { + BooksAdapterGridCover(requireContext(), this) + } } } @@ -94,10 +111,10 @@ class BookshelfFragment2() : BaseBookshelfFragment(R.layout.fragment_bookshelf2) binding.refreshLayout.isRefreshing = false activityViewModel.upToc(books) } - if (bookshelfLayout == 0) { + if (bookshelfLayoutMode == 0) { binding.rvBookshelf.layoutManager = LinearLayoutManager(context) } else { - binding.rvBookshelf.layoutManager = GridLayoutManager(context, bookshelfLayout) + binding.rvBookshelf.layoutManager = GridLayoutManager(context, bookshelfLayoutGrid) } binding.rvBookshelf.itemAnimator = null binding.rvBookshelf.adapter = booksAdapter diff --git a/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/books/styleDefalut/BooksAdapterGridCompact.kt b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/books/styleDefalut/BooksAdapterGridCompact.kt new file mode 100644 index 000000000..dea21bbfe --- /dev/null +++ b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/books/styleDefalut/BooksAdapterGridCompact.kt @@ -0,0 +1,90 @@ +package io.legato.kazusa.ui.main.bookshelf.books.styleDefalut + +import android.content.Context +import android.os.Bundle +import android.view.View +import android.view.ViewGroup +import io.legato.kazusa.base.adapter.ItemViewHolder +import io.legato.kazusa.data.entities.Book +import io.legato.kazusa.databinding.ItemBookshelfGridCompactBinding +import io.legato.kazusa.help.book.isLocal +import io.legato.kazusa.help.config.AppConfig + +class BooksAdapterGridCompact(context: Context, private val callBack: CallBack) : + BaseBooksAdapter(context) { + + override fun getViewBinding(parent: ViewGroup): ItemBookshelfGridCompactBinding { + return ItemBookshelfGridCompactBinding.inflate(inflater, parent, false) + } + + override fun convert( + holder: ItemViewHolder, + binding: ItemBookshelfGridCompactBinding, + item: Book, + payloads: MutableList + ) = binding.run { + binding.ivCover.transitionName = "book_${item.bookUrl}" + if (payloads.isEmpty()) { + tvName.text = item.name + ivCover.load(item.getDisplayCover(), item.name, item.author, false, item.origin) + upRefresh(binding, item) + } else { + for (i in payloads.indices) { + val bundle = payloads[i] as Bundle + bundle.keySet().forEach { + when (it) { + "name" -> tvName.text = item.name + "cover" -> ivCover.load( + item.getDisplayCover(), + item.name, + item.author, + false, + item.origin + ) + + "refresh" -> upRefresh(binding, item) + } + } + } + } + } + + private fun upRefresh(binding: ItemBookshelfGridCompactBinding, item: Book) { + if (!item.isLocal && callBack.isUpdate(item.bookUrl)) { + binding.cdUnread.visibility = View.GONE + binding.rlLoading.visibility = View.VISIBLE + } else { + binding.rlLoading.visibility = View.GONE + if (AppConfig.showUnread) { + val unreadCount = item.getUnreadChapterNum() + if (unreadCount > 0) { + binding.cdUnread.visibility = View.VISIBLE + binding.tvUnread.text = unreadCount.toString() + } else { + binding.cdUnread.visibility = View.GONE + } + } else { + binding.cdUnread.visibility = View.GONE + } + } + } + + override fun registerListener( + holder: ItemViewHolder, + binding: ItemBookshelfGridCompactBinding + ) { + + binding.cvContent.setOnClickListener { + getItem(holder.layoutPosition)?.let { + callBack.open(it, binding.ivCover) + } + } + + binding.cvContent.setOnLongClickListener { + getItem(holder.layoutPosition)?.let { + callBack.openBookInfo(it, binding.ivCover) + } + true + } + } +} \ No newline at end of file diff --git a/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/books/styleDefalut/BooksAdapterGridCover.kt b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/books/styleDefalut/BooksAdapterGridCover.kt new file mode 100644 index 000000000..5c7bb289d --- /dev/null +++ b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/books/styleDefalut/BooksAdapterGridCover.kt @@ -0,0 +1,91 @@ +package io.legato.kazusa.ui.main.bookshelf.books.styleDefalut + +import android.content.Context +import android.os.Bundle +import android.view.View +import android.view.ViewGroup +import io.legato.kazusa.base.adapter.ItemViewHolder +import io.legato.kazusa.data.entities.Book +import io.legato.kazusa.databinding.ItemBookshelfGridCompactBinding +import io.legato.kazusa.help.book.isLocal +import io.legato.kazusa.help.config.AppConfig +import io.legato.kazusa.utils.gone + +class BooksAdapterGridCover(context: Context, private val callBack: CallBack) : + BaseBooksAdapter(context) { + + override fun getViewBinding(parent: ViewGroup): ItemBookshelfGridCompactBinding { + return ItemBookshelfGridCompactBinding.inflate(inflater, parent, false) + } + + override fun convert( + holder: ItemViewHolder, + binding: ItemBookshelfGridCompactBinding, + item: Book, + payloads: MutableList + ) = binding.run { + binding.ivCover.transitionName = "book_${item.bookUrl}" + if (payloads.isEmpty()) { + tvName.gone() + ivCover.load(item.getDisplayCover(), item.name, item.author, false, item.origin) + upRefresh(binding, item) + } else { + for (i in payloads.indices) { + val bundle = payloads[i] as Bundle + bundle.keySet().forEach { + when (it) { + "name" -> tvName.gone() + "cover" -> ivCover.load( + item.getDisplayCover(), + item.name, + item.author, + false, + item.origin + ) + + "refresh" -> upRefresh(binding, item) + } + } + } + } + } + + private fun upRefresh(binding: ItemBookshelfGridCompactBinding, item: Book) { + if (!item.isLocal && callBack.isUpdate(item.bookUrl)) { + binding.cdUnread.visibility = View.GONE + binding.rlLoading.visibility = View.VISIBLE + } else { + binding.rlLoading.visibility = View.GONE + if (AppConfig.showUnread) { + val unreadCount = item.getUnreadChapterNum() + if (unreadCount > 0) { + binding.cdUnread.visibility = View.VISIBLE + binding.tvUnread.text = unreadCount.toString() + } else { + binding.cdUnread.visibility = View.GONE + } + } else { + binding.cdUnread.visibility = View.GONE + } + } + } + + override fun registerListener( + holder: ItemViewHolder, + binding: ItemBookshelfGridCompactBinding + ) { + + binding.cvContent.setOnClickListener { + getItem(holder.layoutPosition)?.let { + callBack.open(it, binding.ivCover) + } + } + + binding.cvContent.setOnLongClickListener { + getItem(holder.layoutPosition)?.let { + callBack.openBookInfo(it, binding.ivCover) + } + true + } + } +} \ No newline at end of file diff --git a/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/books/styleFold/BooksAdapterGridCompact.kt b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/books/styleFold/BooksAdapterGridCompact.kt new file mode 100644 index 000000000..7c604c8d6 --- /dev/null +++ b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/books/styleFold/BooksAdapterGridCompact.kt @@ -0,0 +1,190 @@ +package io.legato.kazusa.ui.main.bookshelf.books.styleFold + +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.ItemBookshelfGridCompactBinding +import io.legato.kazusa.databinding.ItemBookshelfGridCompactGroupBinding +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") +class BooksAdapterGridCompact(context: Context, callBack: CallBack) : + BaseBooksAdapter(context, callBack) { + + override fun onCreateViewHolder( + parent: ViewGroup, + viewType: Int + ): RecyclerView.ViewHolder { + return when (viewType) { + 1 -> GroupViewHolder( + ItemBookshelfGridCompactGroupBinding.inflate( + inflater, + parent, + false + ) + ) + + else -> BookViewHolder(ItemBookshelfGridCompactBinding.inflate(inflater, parent, false)) + } + } + + override fun onBindViewHolder( + holder: RecyclerView.ViewHolder, + position: Int, + payloads: MutableList + ) { + + when (holder) { + is BookViewHolder -> (getItem(position) as? Book)?.let { + holder.registerListener(it) + holder.onBind(it, payloads) + } + + is GroupViewHolder -> (getItem(position) as? BookGroup)?.let { + holder.registerListener(it) + 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: ItemBookshelfGridCompactBinding) : + RecyclerView.ViewHolder(binding.root) { + + 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, payloads: MutableList) = binding.run { + if (payloads.isEmpty()) { + onBind(item) + } else { + for (i in payloads.indices) { + val bundle = payloads[i] as Bundle + bundle.keySet().forEach { + when (it) { + "name" -> tvName.text = item.name + "cover" -> ivCover.load( + item.getDisplayCover(), + item.name, + item.author, + false, + item.origin + ) + + "refresh" -> upRefresh(this, item) + } + } + } + } + } + + fun registerListener(item: Any) { + binding.cvContent.setOnClickListener { + callBack.onItemClick(item, binding.ivCover) + } + binding.cvContent.onLongClick { + callBack.onItemLongClick(item, binding.ivCover) + } + } + + private fun upRefresh(binding: ItemBookshelfGridCompactBinding, item: Book) { + if (!item.isLocal && callBack.isUpdate(item.bookUrl)) { + binding.cdUnread.visibility = View.GONE + binding.rlLoading.visibility = View.VISIBLE + } else { + binding.rlLoading.visibility = View.GONE + if (AppConfig.showUnread) { + val unreadCount = item.getUnreadChapterNum() + if (unreadCount > 0) { + binding.cdUnread.visibility = View.VISIBLE + binding.tvUnread.text = unreadCount.toString() + } else { + binding.cdUnread.visibility = View.GONE + } + } else { + binding.cdUnread.visibility = View.GONE + } + } + } + + + } + + inner class GroupViewHolder(val binding: ItemBookshelfGridCompactGroupBinding) : + RecyclerView.ViewHolder(binding.root) { + + fun onBind(item: BookGroup) = binding.run { + tvName.text = item.groupName + loadGroupCover(item) + cdUnread.gone() + } + + fun onBind(item: BookGroup, payloads: MutableList) = binding.run { + if (payloads.isEmpty()) { + 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" -> loadGroupCover(item) + } + } + } + } + } + + fun registerListener(item: Any) { + binding.cvContent.setOnClickListener { + callBack.onItemClick(item, binding.ivCover) + } + binding.cvContent.onLongClick { + callBack.onItemLongClick(item, binding.ivCover) + } + } + + 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/books/styleFold/BooksAdapterGridCover.kt b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/books/styleFold/BooksAdapterGridCover.kt new file mode 100644 index 000000000..37cca56ca --- /dev/null +++ b/app/src/main/java/io/legato/kazusa/ui/main/bookshelf/books/styleFold/BooksAdapterGridCover.kt @@ -0,0 +1,190 @@ +package io.legato.kazusa.ui.main.bookshelf.books.styleFold + +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.ItemBookshelfGridCompactBinding +import io.legato.kazusa.databinding.ItemBookshelfGridCompactGroupBinding +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") +class BooksAdapterGridCover(context: Context, callBack: CallBack) : + BaseBooksAdapter(context, callBack) { + + override fun onCreateViewHolder( + parent: ViewGroup, + viewType: Int + ): RecyclerView.ViewHolder { + return when (viewType) { + 1 -> GroupViewHolder( + ItemBookshelfGridCompactGroupBinding.inflate( + inflater, + parent, + false + ) + ) + + else -> BookViewHolder(ItemBookshelfGridCompactBinding.inflate(inflater, parent, false)) + } + } + + override fun onBindViewHolder( + holder: RecyclerView.ViewHolder, + position: Int, + payloads: MutableList + ) { + + when (holder) { + is BookViewHolder -> (getItem(position) as? Book)?.let { + holder.registerListener(it) + holder.onBind(it, payloads) + } + + is GroupViewHolder -> (getItem(position) as? BookGroup)?.let { + holder.registerListener(it) + 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: ItemBookshelfGridCompactBinding) : + RecyclerView.ViewHolder(binding.root) { + + fun onBind(item: Book) = binding.run { + tvName.gone() + ivCover.load(item.getDisplayCover(), item.name, item.author, false, item.origin) + upRefresh(this, item) + } + + fun onBind(item: Book, payloads: MutableList) = binding.run { + if (payloads.isEmpty()) { + onBind(item) + } else { + for (i in payloads.indices) { + val bundle = payloads[i] as Bundle + bundle.keySet().forEach { + when (it) { + "name" -> tvName.gone() + "cover" -> ivCover.load( + item.getDisplayCover(), + item.name, + item.author, + false, + item.origin + ) + + "refresh" -> upRefresh(this, item) + } + } + } + } + } + + fun registerListener(item: Any) { + binding.cvContent.setOnClickListener { + callBack.onItemClick(item, binding.ivCover) + } + binding.cvContent.onLongClick { + callBack.onItemLongClick(item, binding.ivCover) + } + } + + private fun upRefresh(binding: ItemBookshelfGridCompactBinding, item: Book) { + if (!item.isLocal && callBack.isUpdate(item.bookUrl)) { + binding.cdUnread.visibility = View.GONE + binding.rlLoading.visibility = View.VISIBLE + } else { + binding.rlLoading.visibility = View.GONE + if (AppConfig.showUnread) { + val unreadCount = item.getUnreadChapterNum() + if (unreadCount > 0) { + binding.cdUnread.visibility = View.VISIBLE + binding.tvUnread.text = unreadCount.toString() + } else { + binding.cdUnread.visibility = View.GONE + } + } else { + binding.cdUnread.visibility = View.GONE + } + } + } + + + } + + inner class GroupViewHolder(val binding: ItemBookshelfGridCompactGroupBinding) : + RecyclerView.ViewHolder(binding.root) { + + fun onBind(item: BookGroup) = binding.run { + tvName.gone() + loadGroupCover(item) + cdUnread.gone() + } + + fun onBind(item: BookGroup, payloads: MutableList) = binding.run { + if (payloads.isEmpty()) { + onBind(item) + } else { + for (i in payloads.indices) { + val bundle = payloads[i] as Bundle + bundle.keySet().forEach { + when (it) { + "groupName" -> tvName.gone() + "cover" -> loadGroupCover(item) + } + } + } + } + } + + fun registerListener(item: Any) { + binding.cvContent.setOnClickListener { + callBack.onItemClick(item, binding.ivCover) + } + binding.cvContent.onLongClick { + callBack.onItemLongClick(item, binding.ivCover) + } + } + + 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/utils/ContextExtensions.kt b/app/src/main/java/io/legato/kazusa/utils/ContextExtensions.kt index b194bb53e..8804513d6 100644 --- a/app/src/main/java/io/legato/kazusa/utils/ContextExtensions.kt +++ b/app/src/main/java/io/legato/kazusa/utils/ContextExtensions.kt @@ -420,11 +420,18 @@ val Context.isDebuggable: Boolean val Context.dataStore by preferencesDataStore(name = "settings") -val Context.bookshelfLayout: Int +val Context.bookshelfLayoutMode: Int get() = if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) { - AppConfig.bookshelfLayoutLandscape + AppConfig.bookshelfLayoutModeLandscape } else { - AppConfig.bookshelfLayoutPortrait + AppConfig.bookshelfLayoutModePortrait + } + +val Context.bookshelfLayoutGrid: Int + get() = if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) { + AppConfig.bookshelfLayoutGridLandscape + } else { + AppConfig.bookshelfLayoutGridPortrait } fun Context.themeColor(attr: Int): Int { diff --git a/app/src/main/res/drawable/bg_gradient_black.xml b/app/src/main/res/drawable/bg_gradient_black.xml new file mode 100644 index 000000000..4d3a211d1 --- /dev/null +++ b/app/src/main/res/drawable/bg_gradient_black.xml @@ -0,0 +1,8 @@ + + + + diff --git a/app/src/main/res/layout/dialog_bookshelf_config.xml b/app/src/main/res/layout/dialog_bookshelf_config.xml index 5a2149b09..6a8e925eb 100644 --- a/app/src/main/res/layout/dialog_bookshelf_config.xml +++ b/app/src/main/res/layout/dialog_bookshelf_config.xml @@ -80,55 +80,59 @@ - + android:layout_gravity="center_vertical" + android:text="@string/sortview" + android:textSize="14sp" + android:textStyle="bold" /> - + + + android:checkable="true" + android:text="@string/list" /> - - - + android:checkable="true" + android:text="@string/grid" /> - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/item_bookshelf_grid_compact_group.xml b/app/src/main/res/layout/item_bookshelf_grid_compact_group.xml new file mode 100644 index 000000000..8fa91c8ec --- /dev/null +++ b/app/src/main/res/layout/item_bookshelf_grid_compact_group.xml @@ -0,0 +1,159 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +