mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-11-20 06:09:19 +01:00
Tablet UI for manga details
It returns for some reason... even I'm trying to figure out why enjoy my 8 tablet users Also kinda fix the view scrolling down a bit when tapping on the expanded summary when the summary is extremely long
This commit is contained in:
parent
0c2262ccba
commit
4999db33f4
@ -11,6 +11,7 @@ import android.content.ClipData
|
|||||||
import android.content.ClipboardManager
|
import android.content.ClipboardManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.res.Configuration
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.graphics.drawable.BitmapDrawable
|
import android.graphics.drawable.BitmapDrawable
|
||||||
@ -30,6 +31,7 @@ import androidx.appcompat.view.ActionMode
|
|||||||
import androidx.appcompat.widget.PopupMenu
|
import androidx.appcompat.widget.PopupMenu
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.core.graphics.ColorUtils
|
import androidx.core.graphics.ColorUtils
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.palette.graphics.Palette
|
import androidx.palette.graphics.Palette
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
@ -95,15 +97,18 @@ import eu.kanade.tachiyomi.util.system.getPrefTheme
|
|||||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||||
import eu.kanade.tachiyomi.util.system.isInNightMode
|
import eu.kanade.tachiyomi.util.system.isInNightMode
|
||||||
import eu.kanade.tachiyomi.util.system.isOnline
|
import eu.kanade.tachiyomi.util.system.isOnline
|
||||||
|
import eu.kanade.tachiyomi.util.system.isTablet
|
||||||
import eu.kanade.tachiyomi.util.system.launchUI
|
import eu.kanade.tachiyomi.util.system.launchUI
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import eu.kanade.tachiyomi.util.view.activityBinding
|
import eu.kanade.tachiyomi.util.view.activityBinding
|
||||||
|
import eu.kanade.tachiyomi.util.view.doOnApplyWindowInsets
|
||||||
import eu.kanade.tachiyomi.util.view.getText
|
import eu.kanade.tachiyomi.util.view.getText
|
||||||
import eu.kanade.tachiyomi.util.view.requestPermissionsSafe
|
import eu.kanade.tachiyomi.util.view.requestPermissionsSafe
|
||||||
import eu.kanade.tachiyomi.util.view.scrollViewWith
|
import eu.kanade.tachiyomi.util.view.scrollViewWith
|
||||||
import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener
|
import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener
|
||||||
import eu.kanade.tachiyomi.util.view.setStyle
|
import eu.kanade.tachiyomi.util.view.setStyle
|
||||||
import eu.kanade.tachiyomi.util.view.snack
|
import eu.kanade.tachiyomi.util.view.snack
|
||||||
|
import eu.kanade.tachiyomi.util.view.toolbarHeight
|
||||||
import eu.kanade.tachiyomi.util.view.updateLayoutParams
|
import eu.kanade.tachiyomi.util.view.updateLayoutParams
|
||||||
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
|
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
|
||||||
import eu.kanade.tachiyomi.util.view.withFadeTransaction
|
import eu.kanade.tachiyomi.util.view.withFadeTransaction
|
||||||
@ -172,6 +177,10 @@ class MangaDetailsController :
|
|||||||
var refreshTracker: Int? = null
|
var refreshTracker: Int? = null
|
||||||
var chapterPopupMenu: Pair<Int, PopupMenu>? = null
|
var chapterPopupMenu: Pair<Int, PopupMenu>? = null
|
||||||
|
|
||||||
|
// Tablet Layout
|
||||||
|
var isTablet = false
|
||||||
|
private var tabletAdapter: MangaDetailsAdapter? = null
|
||||||
|
|
||||||
private var query = ""
|
private var query = ""
|
||||||
private var adapter: MangaDetailsAdapter? = null
|
private var adapter: MangaDetailsAdapter? = null
|
||||||
|
|
||||||
@ -195,6 +204,7 @@ class MangaDetailsController :
|
|||||||
coverColor = null
|
coverColor = null
|
||||||
fullCoverActive = false
|
fullCoverActive = false
|
||||||
|
|
||||||
|
setTabletMode(view)
|
||||||
setRecycler(view)
|
setRecycler(view)
|
||||||
setPaletteColor()
|
setPaletteColor()
|
||||||
adapter?.fastScroller = binding.fastScroller
|
adapter?.fastScroller = binding.fastScroller
|
||||||
@ -208,6 +218,21 @@ class MangaDetailsController :
|
|||||||
requestPermissionsSafe(arrayOf(WRITE_EXTERNAL_STORAGE), 301)
|
requestPermissionsSafe(arrayOf(WRITE_EXTERNAL_STORAGE), 301)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Check if device is tablet, and use a second recycler to hold the details header if so */
|
||||||
|
private fun setTabletMode(view: View) {
|
||||||
|
isTablet = view.context.isTablet() &&
|
||||||
|
view.context.resources.configuration?.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||||
|
binding.tabletOverlay.isVisible = isTablet
|
||||||
|
binding.tabletRecycler.isVisible = isTablet
|
||||||
|
binding.tabletDivider.isVisible = isTablet
|
||||||
|
if (isTablet) {
|
||||||
|
binding.recycler.updateLayoutParams<ViewGroup.LayoutParams> { width = 0 }
|
||||||
|
tabletAdapter = MangaDetailsAdapter(this)
|
||||||
|
binding.tabletRecycler.adapter = tabletAdapter
|
||||||
|
binding.tabletRecycler.layoutManager = LinearLayoutManager(view.context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onDestroyView(view: View) {
|
override fun onDestroyView(view: View) {
|
||||||
snack?.dismiss()
|
snack?.dismiss()
|
||||||
presenter.onDestroy()
|
presenter.onDestroy()
|
||||||
@ -236,6 +261,14 @@ class MangaDetailsController :
|
|||||||
binding.swipeRefresh.setDistanceToTriggerSync(70.dpToPx)
|
binding.swipeRefresh.setDistanceToTriggerSync(70.dpToPx)
|
||||||
activityBinding!!.appBar.elevation = 0f
|
activityBinding!!.appBar.elevation = 0f
|
||||||
|
|
||||||
|
if (isTablet) {
|
||||||
|
val tHeight = toolbarHeight.takeIf { it ?: 0 > 0 } ?: appbarHeight
|
||||||
|
headerHeight = tHeight + (activityBinding?.root?.rootWindowInsets?.systemWindowInsetTop ?: 0)
|
||||||
|
binding.recycler.updatePaddingRelative(top = headerHeight + 4.dpToPx)
|
||||||
|
binding.recycler.doOnApplyWindowInsets { _, insets, _ ->
|
||||||
|
setInsets(insets, appbarHeight, offset)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
scrollViewWith(
|
scrollViewWith(
|
||||||
binding.recycler,
|
binding.recycler,
|
||||||
padBottom = true,
|
padBottom = true,
|
||||||
@ -247,16 +280,19 @@ class MangaDetailsController :
|
|||||||
colorToolbar(it)
|
colorToolbar(it)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
binding.recycler.addOnScrollListener(
|
binding.recycler.addOnScrollListener(
|
||||||
object : RecyclerView.OnScrollListener() {
|
object : RecyclerView.OnScrollListener() {
|
||||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||||
super.onScrolled(recyclerView, dx, dy)
|
super.onScrolled(recyclerView, dx, dy)
|
||||||
|
if (!isTablet) {
|
||||||
val atTop = !recyclerView.canScrollVertically(-1)
|
val atTop = !recyclerView.canScrollVertically(-1)
|
||||||
val tY = getHeader()?.binding?.backdrop?.translationY ?: 0f
|
val tY = getHeader()?.binding?.backdrop?.translationY ?: 0f
|
||||||
getHeader()?.binding?.backdrop?.translationY = max(0f, tY + dy * 0.25f)
|
getHeader()?.binding?.backdrop?.translationY = max(0f, tY + dy * 0.25f)
|
||||||
if (atTop) getHeader()?.binding?.backdrop?.translationY = 0f
|
if (atTop) getHeader()?.binding?.backdrop?.translationY = 0f
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||||
val atTop = !recyclerView.canScrollVertically(-1)
|
val atTop = !recyclerView.canScrollVertically(-1)
|
||||||
@ -268,9 +304,15 @@ class MangaDetailsController :
|
|||||||
|
|
||||||
private fun setInsets(insets: WindowInsets, appbarHeight: Int, offset: Int) {
|
private fun setInsets(insets: WindowInsets, appbarHeight: Int, offset: Int) {
|
||||||
binding.recycler.updatePaddingRelative(bottom = insets.systemWindowInsetBottom)
|
binding.recycler.updatePaddingRelative(bottom = insets.systemWindowInsetBottom)
|
||||||
headerHeight = appbarHeight + insets.systemWindowInsetTop
|
binding.tabletRecycler.updatePaddingRelative(bottom = insets.systemWindowInsetBottom)
|
||||||
|
val tHeight = toolbarHeight.takeIf { it ?: 0 > 0 } ?: appbarHeight
|
||||||
|
headerHeight = tHeight + insets.systemWindowInsetTop
|
||||||
binding.swipeRefresh.setProgressViewOffset(false, (-40).dpToPx, headerHeight + offset)
|
binding.swipeRefresh.setProgressViewOffset(false, (-40).dpToPx, headerHeight + offset)
|
||||||
// 1dp extra to line up chapter header and manga header
|
if (isTablet) {
|
||||||
|
binding.tabletOverlay.updateLayoutParams<ViewGroup.LayoutParams> { height = headerHeight }
|
||||||
|
// 4dp extra to line up chapter header and manga header
|
||||||
|
binding.recycler.updatePaddingRelative(top = headerHeight + 4.dpToPx)
|
||||||
|
}
|
||||||
getHeader()?.setTopHeight(headerHeight)
|
getHeader()?.setTopHeight(headerHeight)
|
||||||
binding.fastScroller.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
binding.fastScroller.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||||
topMargin = headerHeight
|
topMargin = headerHeight
|
||||||
@ -280,8 +322,8 @@ class MangaDetailsController :
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Set the toolbar to fully transparent or colored and translucent */
|
/** Set the toolbar to fully transparent or colored and translucent */
|
||||||
fun colorToolbar(isColor: Boolean, animate: Boolean = true) {
|
private fun colorToolbar(isColor: Boolean, animate: Boolean = true) {
|
||||||
if (isColor == toolbarIsColored) return
|
if (isColor == toolbarIsColored || (isTablet && isColor)) return
|
||||||
toolbarIsColored = isColor
|
toolbarIsColored = isColor
|
||||||
val isCurrentController =
|
val isCurrentController =
|
||||||
router?.backstack?.lastOrNull()?.controller == this@MangaDetailsController
|
router?.backstack?.lastOrNull()?.controller == this@MangaDetailsController
|
||||||
@ -538,12 +580,14 @@ class MangaDetailsController :
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getHeader(): MangaHeaderHolder? {
|
private fun getHeader(): MangaHeaderHolder? {
|
||||||
return binding.recycler.findViewHolderForAdapterPosition(0) as? MangaHeaderHolder
|
return if (isTablet) binding.tabletRecycler.findViewHolderForAdapterPosition(0) as? MangaHeaderHolder
|
||||||
|
else binding.recycler.findViewHolderForAdapterPosition(0) as? MangaHeaderHolder
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateHeader() {
|
fun updateHeader() {
|
||||||
binding.swipeRefresh.isRefreshing = presenter.isLoading
|
binding.swipeRefresh.isRefreshing = presenter.isLoading
|
||||||
adapter?.setChapters(presenter.chapters)
|
adapter?.setChapters(presenter.chapters)
|
||||||
|
tabletAdapter?.notifyDataSetChanged()
|
||||||
addMangaHeader()
|
addMangaHeader()
|
||||||
activity?.invalidateOptionsMenu()
|
activity?.invalidateOptionsMenu()
|
||||||
}
|
}
|
||||||
@ -555,6 +599,7 @@ class MangaDetailsController :
|
|||||||
launchUI { binding.swipeRefresh.isRefreshing = true }
|
launchUI { binding.swipeRefresh.isRefreshing = true }
|
||||||
presenter.fetchChaptersFromSource()
|
presenter.fetchChaptersFromSource()
|
||||||
}
|
}
|
||||||
|
tabletAdapter?.notifyDataSetChanged()
|
||||||
adapter?.setChapters(chapters)
|
adapter?.setChapters(chapters)
|
||||||
addMangaHeader()
|
addMangaHeader()
|
||||||
colorToolbar(binding.recycler.canScrollVertically(-1))
|
colorToolbar(binding.recycler.canScrollVertically(-1))
|
||||||
@ -562,7 +607,12 @@ class MangaDetailsController :
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addMangaHeader() {
|
private fun addMangaHeader() {
|
||||||
if (adapter?.scrollableHeaders?.isEmpty() == true) {
|
if (tabletAdapter?.scrollableHeaders?.isEmpty() == true) {
|
||||||
|
tabletAdapter?.removeAllScrollableHeaders()
|
||||||
|
tabletAdapter?.addScrollableHeader(presenter.headerItem)
|
||||||
|
adapter?.removeAllScrollableHeaders()
|
||||||
|
adapter?.addScrollableHeader(presenter.tabletChapterHeaderItem!!)
|
||||||
|
} else if (!isTablet && adapter?.scrollableHeaders?.isEmpty() == true) {
|
||||||
adapter?.removeAllScrollableHeaders()
|
adapter?.removeAllScrollableHeaders()
|
||||||
adapter?.addScrollableHeader(presenter.headerItem)
|
adapter?.addScrollableHeader(presenter.headerItem)
|
||||||
}
|
}
|
||||||
@ -819,8 +869,10 @@ class MangaDetailsController :
|
|||||||
|
|
||||||
setOnQueryTextChangeListener(searchView) {
|
setOnQueryTextChangeListener(searchView) {
|
||||||
query = it ?: ""
|
query = it ?: ""
|
||||||
|
if (!isTablet) {
|
||||||
if (query.isNotEmpty()) getHeader()?.collapse()
|
if (query.isNotEmpty()) getHeader()?.collapse()
|
||||||
else getHeader()?.expand()
|
else getHeader()?.expand()
|
||||||
|
}
|
||||||
|
|
||||||
adapter?.setFilter(query)
|
adapter?.setFilter(query)
|
||||||
adapter?.performFilter()
|
adapter?.performFilter()
|
||||||
|
@ -46,6 +46,7 @@ import eu.kanade.tachiyomi.util.storage.DiskUtil
|
|||||||
import eu.kanade.tachiyomi.util.system.ImageUtil
|
import eu.kanade.tachiyomi.util.system.ImageUtil
|
||||||
import eu.kanade.tachiyomi.util.manga.MangaShortcutManager
|
import eu.kanade.tachiyomi.util.manga.MangaShortcutManager
|
||||||
import eu.kanade.tachiyomi.util.system.executeOnIO
|
import eu.kanade.tachiyomi.util.system.executeOnIO
|
||||||
|
import eu.kanade.tachiyomi.util.system.isTablet
|
||||||
import eu.kanade.tachiyomi.util.system.launchIO
|
import eu.kanade.tachiyomi.util.system.launchIO
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -97,8 +98,14 @@ class MangaDetailsPresenter(
|
|||||||
private set
|
private set
|
||||||
|
|
||||||
var headerItem = MangaHeaderItem(manga, controller.fromCatalogue)
|
var headerItem = MangaHeaderItem(manga, controller.fromCatalogue)
|
||||||
|
var tabletChapterHeaderItem: MangaHeaderItem? = null
|
||||||
|
|
||||||
fun onCreate() {
|
fun onCreate() {
|
||||||
|
headerItem.isTablet = controller.isTablet
|
||||||
|
if (controller.isTablet) {
|
||||||
|
tabletChapterHeaderItem = MangaHeaderItem(manga, false)
|
||||||
|
tabletChapterHeaderItem?.isChapterHeader = true
|
||||||
|
}
|
||||||
isLockedFromSearch = SecureActivityDelegate.shouldBeLocked()
|
isLockedFromSearch = SecureActivityDelegate.shouldBeLocked()
|
||||||
headerItem.isLocked = isLockedFromSearch
|
headerItem.isLocked = isLockedFromSearch
|
||||||
downloadManager.addListener(this)
|
downloadManager.addListener(this)
|
||||||
|
@ -15,6 +15,7 @@ import com.google.android.material.button.MaterialButton
|
|||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.image.coil.loadManga
|
import eu.kanade.tachiyomi.data.image.coil.loadManga
|
||||||
|
import eu.kanade.tachiyomi.databinding.ChapterHeaderItemBinding
|
||||||
import eu.kanade.tachiyomi.databinding.MangaHeaderItemBinding
|
import eu.kanade.tachiyomi.databinding.MangaHeaderItemBinding
|
||||||
import eu.kanade.tachiyomi.source.LocalSource
|
import eu.kanade.tachiyomi.source.LocalSource
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
@ -28,24 +29,43 @@ import eu.kanade.tachiyomi.util.view.updateLayoutParams
|
|||||||
class MangaHeaderHolder(
|
class MangaHeaderHolder(
|
||||||
private val view: View,
|
private val view: View,
|
||||||
private val adapter: MangaDetailsAdapter,
|
private val adapter: MangaDetailsAdapter,
|
||||||
startExpanded: Boolean
|
startExpanded: Boolean,
|
||||||
|
isTablet: Boolean = false
|
||||||
) : BaseFlexibleViewHolder(view, adapter) {
|
) : BaseFlexibleViewHolder(view, adapter) {
|
||||||
|
|
||||||
val binding = MangaHeaderItemBinding.bind(view)
|
val binding: MangaHeaderItemBinding? = try {
|
||||||
|
MangaHeaderItemBinding.bind(view)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
private val chapterBinding: ChapterHeaderItemBinding? = try {
|
||||||
|
ChapterHeaderItemBinding.bind(view)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
private var showReadingButton = true
|
private var showReadingButton = true
|
||||||
private var showMoreButton = true
|
private var showMoreButton = true
|
||||||
var hadSelection = false
|
var hadSelection = false
|
||||||
|
|
||||||
init {
|
init {
|
||||||
binding.chapterLayout.setOnClickListener { adapter.delegate.showChapterFilter() }
|
|
||||||
binding.startReadingButton.setOnClickListener { adapter.delegate.readNextChapter() }
|
if (binding == null) {
|
||||||
binding.topView.updateLayoutParams<ConstraintLayout.LayoutParams> {
|
with(chapterBinding) {
|
||||||
|
this ?: return@with
|
||||||
|
chapterLayout.setOnClickListener { adapter.delegate.showChapterFilter() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
with(binding) {
|
||||||
|
this ?: return@with
|
||||||
|
chapterLayout.setOnClickListener { adapter.delegate.showChapterFilter() }
|
||||||
|
startReadingButton.setOnClickListener { adapter.delegate.readNextChapter() }
|
||||||
|
topView.updateLayoutParams<ConstraintLayout.LayoutParams> {
|
||||||
height = adapter.delegate.topCoverHeight()
|
height = adapter.delegate.topCoverHeight()
|
||||||
}
|
}
|
||||||
binding.moreButton.setOnClickListener { expandDesc() }
|
moreButton.setOnClickListener { expandDesc() }
|
||||||
binding.mangaSummary.setOnClickListener {
|
mangaSummary.setOnClickListener {
|
||||||
if (binding.moreButton.isVisible) {
|
if (moreButton.isVisible) {
|
||||||
expandDesc()
|
expandDesc()
|
||||||
} else if (!hadSelection) {
|
} else if (!hadSelection) {
|
||||||
collapseDesc()
|
collapseDesc()
|
||||||
@ -53,56 +73,66 @@ class MangaHeaderHolder(
|
|||||||
hadSelection = false
|
hadSelection = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.mangaSummary.setOnLongClickListener {
|
mangaSummary.setOnLongClickListener {
|
||||||
if (binding.mangaSummary.isTextSelectable && !adapter.recyclerView.canScrollVertically(-1)) {
|
if (mangaSummary.isTextSelectable && !adapter.recyclerView.canScrollVertically(
|
||||||
(adapter.delegate as MangaDetailsController).binding.swipeRefresh.isEnabled = false
|
-1
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
(adapter.delegate as MangaDetailsController).binding.swipeRefresh.isEnabled =
|
||||||
|
false
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
binding.mangaSummary.setOnTouchListener { _, event ->
|
mangaSummary.setOnTouchListener { _, event ->
|
||||||
if (event.action == MotionEvent.ACTION_DOWN) {
|
if (event.action == MotionEvent.ACTION_DOWN) {
|
||||||
view.requestFocus()
|
view.requestFocus()
|
||||||
}
|
}
|
||||||
if (event.actionMasked == MotionEvent.ACTION_UP) {
|
if (event.actionMasked == MotionEvent.ACTION_UP) {
|
||||||
hadSelection = binding.mangaSummary.hasSelection()
|
hadSelection = mangaSummary.hasSelection()
|
||||||
(adapter.delegate as MangaDetailsController).binding.swipeRefresh.isEnabled =
|
(adapter.delegate as MangaDetailsController).binding.swipeRefresh.isEnabled =
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
if (!itemView.resources.isLTR) {
|
if (!itemView.resources.isLTR) {
|
||||||
binding.moreBgGradient.rotation = 180f
|
moreBgGradient.rotation = 180f
|
||||||
}
|
}
|
||||||
binding.lessButton.setOnClickListener { collapseDesc() }
|
lessButton.setOnClickListener { collapseDesc() }
|
||||||
binding.mangaGenresTags.setOnTagClickListener {
|
mangaGenresTags.setOnTagClickListener {
|
||||||
adapter.delegate.tagClicked(it)
|
adapter.delegate.tagClicked(it)
|
||||||
}
|
}
|
||||||
binding.webviewButton.setOnClickListener { adapter.delegate.openInWebView() }
|
webviewButton.setOnClickListener { adapter.delegate.openInWebView() }
|
||||||
binding.shareButton.setOnClickListener { adapter.delegate.prepareToShareManga() }
|
shareButton.setOnClickListener { adapter.delegate.prepareToShareManga() }
|
||||||
binding.favoriteButton.setOnClickListener {
|
favoriteButton.setOnClickListener {
|
||||||
adapter.delegate.favoriteManga(false)
|
adapter.delegate.favoriteManga(false)
|
||||||
}
|
}
|
||||||
binding.title.setOnClickListener {
|
title.setOnClickListener {
|
||||||
binding.title.text?.let { adapter.delegate.globalSearch(it.toString()) }
|
title.text?.let { adapter.delegate.globalSearch(it.toString()) }
|
||||||
}
|
}
|
||||||
binding.title.setOnLongClickListener {
|
title.setOnLongClickListener {
|
||||||
adapter.delegate.copyToClipboard(binding.title.text.toString(), R.string.title)
|
adapter.delegate.copyToClipboard(title.text.toString(), R.string.title)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
binding.mangaAuthor.setOnClickListener {
|
mangaAuthor.setOnClickListener {
|
||||||
binding.mangaAuthor.text?.let { adapter.delegate.globalSearch(it.toString()) }
|
mangaAuthor.text?.let { adapter.delegate.globalSearch(it.toString()) }
|
||||||
}
|
}
|
||||||
binding.mangaAuthor.setOnLongClickListener {
|
mangaAuthor.setOnLongClickListener {
|
||||||
adapter.delegate.copyToClipboard(binding.mangaAuthor.text.toString(), R.string.author)
|
adapter.delegate.copyToClipboard(
|
||||||
|
mangaAuthor.text.toString(),
|
||||||
|
R.string.author
|
||||||
|
)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
binding.mangaCover.setOnClickListener { adapter.delegate.zoomImageFromThumb(binding.coverCard) }
|
mangaCover.setOnClickListener { adapter.delegate.zoomImageFromThumb(coverCard) }
|
||||||
binding.trackButton.setOnClickListener { adapter.delegate.showTrackingSheet() }
|
trackButton.setOnClickListener { adapter.delegate.showTrackingSheet() }
|
||||||
if (startExpanded) expandDesc()
|
if (startExpanded) expandDesc()
|
||||||
else collapseDesc()
|
else collapseDesc()
|
||||||
|
if (isTablet) chapterLayout.isVisible = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun expandDesc() {
|
private fun expandDesc() {
|
||||||
|
binding ?: return
|
||||||
if (binding.moreButton.visibility == View.VISIBLE) {
|
if (binding.moreButton.visibility == View.VISIBLE) {
|
||||||
binding.mangaSummary.maxLines = Integer.MAX_VALUE
|
binding.mangaSummary.maxLines = Integer.MAX_VALUE
|
||||||
binding.mangaSummary.setTextIsSelectable(true)
|
binding.mangaSummary.setTextIsSelectable(true)
|
||||||
@ -110,10 +140,12 @@ class MangaHeaderHolder(
|
|||||||
binding.lessButton.isVisible = true
|
binding.lessButton.isVisible = true
|
||||||
binding.moreButtonGroup.isVisible = false
|
binding.moreButtonGroup.isVisible = false
|
||||||
binding.title.maxLines = Integer.MAX_VALUE
|
binding.title.maxLines = Integer.MAX_VALUE
|
||||||
|
binding.mangaSummary.requestFocus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun collapseDesc() {
|
private fun collapseDesc() {
|
||||||
|
binding ?: return
|
||||||
binding.mangaSummary.setTextIsSelectable(false)
|
binding.mangaSummary.setTextIsSelectable(false)
|
||||||
binding.mangaSummary.isClickable = true
|
binding.mangaSummary.isClickable = true
|
||||||
binding.mangaSummary.maxLines = 3
|
binding.mangaSummary.maxLines = 3
|
||||||
@ -129,13 +161,29 @@ class MangaHeaderHolder(
|
|||||||
fun bindChapters() {
|
fun bindChapters() {
|
||||||
val presenter = adapter.delegate.mangaPresenter()
|
val presenter = adapter.delegate.mangaPresenter()
|
||||||
val count = presenter.chapters.size
|
val count = presenter.chapters.size
|
||||||
binding.chaptersTitle.text = itemView.resources.getQuantityString(R.plurals.chapters_plural, count, count)
|
if (binding != null) {
|
||||||
|
binding.chaptersTitle.text =
|
||||||
|
itemView.resources.getQuantityString(R.plurals.chapters_plural, count, count)
|
||||||
binding.filtersText.text = presenter.currentFilters()
|
binding.filtersText.text = presenter.currentFilters()
|
||||||
|
} else if (chapterBinding != null) {
|
||||||
|
chapterBinding.chaptersTitle.text =
|
||||||
|
itemView.resources.getQuantityString(R.plurals.chapters_plural, count, count)
|
||||||
|
chapterBinding.filtersText.text = presenter.currentFilters()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
fun bind(item: MangaHeaderItem, manga: Manga) {
|
fun bind(item: MangaHeaderItem, manga: Manga) {
|
||||||
val presenter = adapter.delegate.mangaPresenter()
|
val presenter = adapter.delegate.mangaPresenter()
|
||||||
|
if (binding == null) {
|
||||||
|
if (chapterBinding != null) {
|
||||||
|
val count = presenter.chapters.size
|
||||||
|
chapterBinding.chaptersTitle.text =
|
||||||
|
itemView.resources.getQuantityString(R.plurals.chapters_plural, count, count)
|
||||||
|
chapterBinding.filtersText.text = presenter.currentFilters()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
binding.title.text = manga.title
|
binding.title.text = manga.title
|
||||||
|
|
||||||
if (manga.genre.isNullOrBlank().not()) binding.mangaGenresTags.setTags(
|
if (manga.genre.isNullOrBlank().not()) binding.mangaGenresTags.setTags(
|
||||||
@ -281,16 +329,20 @@ class MangaHeaderHolder(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun setTopHeight(newHeight: Int) {
|
fun setTopHeight(newHeight: Int) {
|
||||||
|
binding ?: return
|
||||||
|
if (newHeight == binding.topView.height) return
|
||||||
binding.topView.updateLayoutParams<ConstraintLayout.LayoutParams> {
|
binding.topView.updateLayoutParams<ConstraintLayout.LayoutParams> {
|
||||||
height = newHeight
|
height = newHeight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setBackDrop(color: Int) {
|
fun setBackDrop(color: Int) {
|
||||||
|
binding ?: return
|
||||||
binding.trueBackdrop.setBackgroundColor(color)
|
binding.trueBackdrop.setBackgroundColor(color)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateTracking() {
|
fun updateTracking() {
|
||||||
|
binding ?: return
|
||||||
val presenter = adapter.delegate.mangaPresenter()
|
val presenter = adapter.delegate.mangaPresenter()
|
||||||
val tracked = presenter.isTracked()
|
val tracked = presenter.isTracked()
|
||||||
with(binding.trackButton) {
|
with(binding.trackButton) {
|
||||||
@ -309,6 +361,7 @@ class MangaHeaderHolder(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun collapse() {
|
fun collapse() {
|
||||||
|
binding ?: return
|
||||||
binding.subItemGroup.isVisible = false
|
binding.subItemGroup.isVisible = false
|
||||||
binding.startReadingButton.isVisible = false
|
binding.startReadingButton.isVisible = false
|
||||||
if (binding.moreButton.isVisible || binding.moreButton.isInvisible) {
|
if (binding.moreButton.isVisible || binding.moreButton.isInvisible) {
|
||||||
@ -320,6 +373,7 @@ class MangaHeaderHolder(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun updateCover(manga: Manga) {
|
fun updateCover(manga: Manga) {
|
||||||
|
binding ?: return
|
||||||
if (!manga.initialized) return
|
if (!manga.initialized) return
|
||||||
val drawable = adapter.controller.binding.mangaCoverFull.drawable
|
val drawable = adapter.controller.binding.mangaCoverFull.drawable
|
||||||
binding.mangaCover.loadManga(
|
binding.mangaCover.loadManga(
|
||||||
@ -343,6 +397,7 @@ class MangaHeaderHolder(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun expand() {
|
fun expand() {
|
||||||
|
binding ?: return
|
||||||
binding.subItemGroup.isVisible = true
|
binding.subItemGroup.isVisible = true
|
||||||
if (!showMoreButton) binding.moreButtonGroup.isVisible = false
|
if (!showMoreButton) binding.moreButtonGroup.isVisible = false
|
||||||
else {
|
else {
|
||||||
|
@ -13,6 +13,7 @@ class MangaHeaderItem(val manga: Manga, var startExpanded: Boolean) :
|
|||||||
|
|
||||||
var isChapterHeader = false
|
var isChapterHeader = false
|
||||||
var isLocked = false
|
var isLocked = false
|
||||||
|
var isTablet = false
|
||||||
|
|
||||||
override fun getLayoutRes(): Int {
|
override fun getLayoutRes(): Int {
|
||||||
return if (isChapterHeader) R.layout.chapter_header_item else R.layout.manga_header_item
|
return if (isChapterHeader) R.layout.chapter_header_item else R.layout.manga_header_item
|
||||||
@ -27,7 +28,7 @@ class MangaHeaderItem(val manga: Manga, var startExpanded: Boolean) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): MangaHeaderHolder {
|
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): MangaHeaderHolder {
|
||||||
return MangaHeaderHolder(view, adapter as MangaDetailsAdapter, startExpanded)
|
return MangaHeaderHolder(view, adapter as MangaDetailsAdapter, startExpanded, isTablet)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun bindViewHolder(
|
override fun bindViewHolder(
|
||||||
|
@ -31,11 +31,11 @@
|
|||||||
android:id="@+id/webview_button"
|
android:id="@+id/webview_button"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="20dp"
|
android:layout_marginEnd="12dp"
|
||||||
android:background="@null"
|
android:background="@null"
|
||||||
android:padding="5dp"
|
android:padding="5dp"
|
||||||
android:src="@drawable/ic_filter_list_24dp"
|
android:src="@drawable/ic_filter_list_24dp"
|
||||||
android:tint="?colorAccent"
|
app:tint="?colorAccent"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/chapters_title"
|
app:layout_constraintBottom_toBottomOf="@id/chapters_title"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@id/chapters_title" />
|
app:layout_constraintTop_toTopOf="@id/chapters_title" />
|
||||||
|
@ -13,19 +13,58 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="?android:colorBackground">
|
android:background="?android:colorBackground">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/linear_recycler_layout"
|
android:id="@+id/linear_recycler_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/tablet_recycler"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/recycler"
|
||||||
|
app:layout_constraintWidth_percent="0.4"
|
||||||
|
tools:itemCount="1"
|
||||||
|
tools:listitem="@layout/manga_header_item" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/recycler"
|
android:id="@+id/recycler"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/tablet_recycler"
|
||||||
tools:listitem="@layout/chapters_item" />
|
tools:listitem="@layout/chapters_item" />
|
||||||
</FrameLayout>
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/tablet_overlay"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:background="?android:attr/colorBackground"
|
||||||
|
android:alpha=".80"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="20dp"
|
||||||
|
app:layout_constraintWidth_percent=".6"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/tablet_divider"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_width="1dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/divider"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/tablet_overlay"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
<eu.kanade.tachiyomi.ui.base.MaterialFastScroll
|
<eu.kanade.tachiyomi.ui.base.MaterialFastScroll
|
||||||
@ -45,7 +84,6 @@
|
|||||||
android:visibility="invisible"
|
android:visibility="invisible"
|
||||||
tools:background="@color/md_black_1000" />
|
tools:background="@color/md_black_1000" />
|
||||||
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/manga_cover_full"
|
android:id="@+id/manga_cover_full"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -356,6 +356,7 @@
|
|||||||
android:tooltipText="@string/sort_and_filter"
|
android:tooltipText="@string/sort_and_filter"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/start_reading_button">
|
app:layout_constraintTop_toBottomOf="@id/start_reading_button">
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
Loading…
Reference in New Issue
Block a user