Binding for manga details

This commit is contained in:
Jays2Kings 2021-03-28 23:01:53 -04:00
parent bde20b8135
commit fa01471728
6 changed files with 226 additions and 238 deletions

View File

@ -102,9 +102,6 @@ import eu.kanade.tachiyomi.util.view.snack
import eu.kanade.tachiyomi.util.view.updateLayoutParams
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
import eu.kanade.tachiyomi.util.view.withFadeTransaction
import kotlinx.android.synthetic.main.main_activity.*
import kotlinx.android.synthetic.main.manga_details_controller.*
import kotlinx.android.synthetic.main.manga_header_item.*
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -187,7 +184,8 @@ class MangaDetailsController :
}
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
return inflater.inflate(R.layout.manga_details_controller, container, false)
binding = MangaDetailsControllerBinding.inflate(inflater)
return binding.root
}
//region UI Methods
@ -198,14 +196,14 @@ class MangaDetailsController :
setRecycler(view)
setPaletteColor()
adapter?.fastScroller = fast_scroller
fast_scroller.addOnScrollStateChangeListener {
adapter?.fastScroller = binding.fastScroller
binding.fastScroller.addOnScrollStateChangeListener {
activityBinding?.appBar?.y = 0f
}
presenter.onCreate()
swipe_refresh.isRefreshing = presenter.isLoading
swipe_refresh.setOnRefreshListener { presenter.refreshAll() }
binding.swipeRefresh.isRefreshing = presenter.isLoading
binding.swipeRefresh.setOnRefreshListener { presenter.refreshAll() }
requestPermissionsSafe(arrayOf(WRITE_EXTERNAL_STORAGE), 301)
}
@ -221,24 +219,24 @@ class MangaDetailsController :
private fun setRecycler(view: View) {
adapter = MangaDetailsAdapter(this)
recycler.adapter = adapter
binding.recycler.adapter = adapter
adapter?.isSwipeEnabled = true
recycler.layoutManager = LinearLayoutManager(view.context)
recycler.addItemDecoration(
binding.recycler.layoutManager = LinearLayoutManager(view.context)
binding.recycler.addItemDecoration(
MangaDetailsDivider(view.context)
)
recycler.setHasFixedSize(true)
binding.recycler.setHasFixedSize(true)
val attrsArray = intArrayOf(android.R.attr.actionBarSize)
val array = view.context.obtainStyledAttributes(attrsArray)
val appbarHeight = array.getDimensionPixelSize(0, 0)
array.recycle()
val offset = 10.dpToPx
swipe_refresh.setStyle()
swipe_refresh.setDistanceToTriggerSync(70.dpToPx)
binding.swipeRefresh.setStyle()
binding.swipeRefresh.setDistanceToTriggerSync(70.dpToPx)
activityBinding!!.appBar.elevation = 0f
scrollViewWith(
recycler,
binding.recycler,
padBottom = true,
customPadding = true,
afterInsets = { insets ->
@ -249,36 +247,35 @@ class MangaDetailsController :
}
)
recycler.addOnScrollListener(
binding.recycler.addOnScrollListener(
object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
val atTop = !recyclerView.canScrollVertically(-1)
val tY = getHeader()?.backdrop?.translationY ?: 0f
getHeader()?.backdrop?.translationY = max(0f, tY + dy * 0.25f)
if (atTop) getHeader()?.backdrop?.translationY = 0f
val tY = getHeader()?.binding?.backdrop?.translationY ?: 0f
getHeader()?.binding?.backdrop?.translationY = max(0f, tY + dy * 0.25f)
if (atTop) getHeader()?.binding?.backdrop?.translationY = 0f
}
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
val atTop = !recyclerView.canScrollVertically(-1)
if (atTop) getHeader()?.backdrop?.translationY = 0f
if (atTop) getHeader()?.binding?.backdrop?.translationY = 0f
}
}
)
}
private fun setInsets(insets: WindowInsets, appbarHeight: Int, offset: Int) {
val recycler = recycler ?: return
recycler.updatePaddingRelative(bottom = insets.systemWindowInsetBottom)
binding.recycler.updatePaddingRelative(bottom = insets.systemWindowInsetBottom)
headerHeight = appbarHeight + insets.systemWindowInsetTop
swipe_refresh.setProgressViewOffset(false, (-40).dpToPx, headerHeight + offset)
binding.swipeRefresh.setProgressViewOffset(false, (-40).dpToPx, headerHeight + offset)
// 1dp extra to line up chapter header and manga header
getHeader()?.setTopHeight(headerHeight)
fast_scroller.updateLayoutParams<ViewGroup.MarginLayoutParams> {
binding.fastScroller.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = headerHeight
bottomMargin = insets.systemWindowInsetBottom
}
fast_scroller.scrollOffset = headerHeight
binding.fastScroller.scrollOffset = headerHeight
}
/** Set the toolbar to fully transparent or colored and translucent */
@ -289,7 +286,7 @@ class MangaDetailsController :
router?.backstack?.lastOrNull()?.controller() == this@MangaDetailsController
if (isCurrentController) setTitle()
if (actionMode != null) {
(activity as MainActivity).toolbar.setBackgroundColor(Color.TRANSPARENT)
activityBinding?.toolbar?.setBackgroundColor(Color.TRANSPARENT)
return
}
val color =
@ -314,12 +311,12 @@ class MangaDetailsController :
)
colorAnimator?.duration = 250 // milliseconds
colorAnimator?.addUpdateListener { animator ->
(activity as MainActivity).toolbar.setBackgroundColor(animator.animatedValue as Int)
activityBinding?.toolbar?.setBackgroundColor(animator.animatedValue as Int)
activity?.window?.statusBarColor = (animator.animatedValue as Int)
}
colorAnimator?.start()
} else {
(activity as MainActivity).toolbar.setBackgroundColor(colorTo)
activityBinding?.toolbar?.setBackgroundColor(colorTo)
activity?.window?.statusBarColor = colorTo
}
}
@ -334,7 +331,7 @@ class MangaDetailsController :
val bitmap = (drawable as BitmapDrawable).bitmap
// Generate the Palette on a background thread.
Palette.from(bitmap).generate {
if (recycler == null || it == null) return@generate
if (it == null) return@generate
val colorBack = view.context.getResourceColor(
android.R.attr.colorBackground
)
@ -346,11 +343,11 @@ class MangaDetailsController :
getHeader()?.setBackDrop(backDropColor)
if (toolbarIsColored) {
val translucentColor = ColorUtils.setAlphaComponent(backDropColor, 175)
(activity as MainActivity).toolbar.setBackgroundColor(translucentColor)
activityBinding?.toolbar?.setBackgroundColor(translucentColor)
activity?.window?.statusBarColor = translucentColor
}
}
manga_cover_full.setImageDrawable(drawable)
binding.mangaCoverFull.setImageDrawable(drawable)
getHeader()?.updateCover(manga!!)
},
onError = {
@ -381,24 +378,23 @@ class MangaDetailsController :
if (forThis) android.R.attr.textColorPrimary
else R.attr.actionBarTintColor
) ?: Color.BLACK
activity.toolbar.setTitleTextColor(iconPrimary)
activityBinding.toolbar.setTitleTextColor(iconPrimary)
activity.drawerArrow?.color = iconPrimary
activity.toolbar.overflowIcon?.setTint(iconPrimary)
if (forThis) activity.main_content.systemUiVisibility =
activity.main_content.systemUiVisibility.or(
View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
)
else activity.main_content.systemUiVisibility =
activity.main_content.systemUiVisibility.rem(
activityBinding.toolbar.overflowIcon?.setTint(iconPrimary)
activityBinding.mainContent.systemUiVisibility = if (forThis) {
activityBinding.mainContent.systemUiVisibility.or(
View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
)
} else activityBinding.mainContent.systemUiVisibility.rem(
View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
)
}
}
private fun setStatusBarAndToolbar() {
activity?.window?.statusBarColor = if (toolbarIsColored) {
val translucentColor = ColorUtils.setAlphaComponent(coverColor ?: Color.TRANSPARENT, 175)
(activity as MainActivity).toolbar.setBackgroundColor(translucentColor)
activityBinding?.toolbar?.setBackgroundColor(translucentColor)
translucentColor
} else Color.TRANSPARENT
activityBinding?.appBar?.setBackgroundColor(Color.TRANSPARENT)
@ -468,13 +464,13 @@ class MangaDetailsController :
) {
super.onChangeEnded(changeHandler, type)
if (type == ControllerChangeType.PUSH_ENTER) {
swipe_refresh?.isRefreshing = presenter.isLoading
binding.swipeRefresh.isRefreshing = presenter.isLoading
}
}
override fun handleBack(): Boolean {
if (manga_cover_full?.visibility == View.VISIBLE) {
manga_cover_full?.performClick()
if (binding.mangaCoverFull.visibility == View.VISIBLE) {
binding.mangaCoverFull.performClick()
return true
}
return super.handleBack()
@ -490,7 +486,7 @@ class MangaDetailsController :
}
fun showError(message: String) {
swipe_refresh?.isRefreshing = presenter.isLoading
binding.swipeRefresh.isRefreshing = presenter.isLoading
view?.snack(message)
}
@ -509,7 +505,7 @@ class MangaDetailsController :
R.plurals.deleted_chapters,
deletedChapters.size,
deletedChapters.size,
deletedChapters.joinToString("\n") { "${it.name}" }
deletedChapters.joinToString("\n") { it.name }
)
).positiveButton(R.string.delete) {
presenter.deleteChapters(deletedChapters, false)
@ -522,7 +518,7 @@ class MangaDetailsController :
}
fun setRefresh(enabled: Boolean) {
swipe_refresh.isRefreshing = enabled
binding.swipeRefresh.isRefreshing = enabled
}
//region Recycler methods
@ -535,15 +531,15 @@ class MangaDetailsController :
}
private fun getHolder(chapter: Chapter): ChapterHolder? {
return recycler?.findViewHolderForItemId(chapter.id!!) as? ChapterHolder
return binding.recycler.findViewHolderForItemId(chapter.id!!) as? ChapterHolder
}
private fun getHeader(): MangaHeaderHolder? {
return recycler?.findViewHolderForAdapterPosition(0) as? MangaHeaderHolder
return binding.recycler.findViewHolderForAdapterPosition(0) as? MangaHeaderHolder
}
fun updateHeader() {
swipe_refresh?.isRefreshing = presenter.isLoading
binding.swipeRefresh.isRefreshing = presenter.isLoading
adapter?.setChapters(presenter.chapters)
addMangaHeader()
activity?.invalidateOptionsMenu()
@ -551,14 +547,14 @@ class MangaDetailsController :
fun updateChapters(chapters: List<ChapterItem>) {
view ?: return
swipe_refresh?.isRefreshing = presenter.isLoading
binding.swipeRefresh.isRefreshing = presenter.isLoading
if (presenter.chapters.isEmpty() && fromCatalogue && !presenter.hasRequested) {
launchUI { swipe_refresh?.isRefreshing = true }
launchUI { binding.swipeRefresh.isRefreshing = true }
presenter.fetchChaptersFromSource()
}
adapter?.setChapters(chapters)
addMangaHeader()
colorToolbar(recycler?.canScrollVertically(-1) == true)
colorToolbar(binding.recycler.canScrollVertically(-1))
activity?.invalidateOptionsMenu()
}
@ -577,9 +573,9 @@ class MangaDetailsController :
if (actionMode != null) {
if (startingDLChapterPos == null) {
adapter?.addSelection(position)
(recycler.findViewHolderForAdapterPosition(position) as? BaseFlexibleViewHolder)
(binding.recycler.findViewHolderForAdapterPosition(position) as? BaseFlexibleViewHolder)
?.toggleActivation()
(recycler.findViewHolderForAdapterPosition(position) as? ChapterHolder)
(binding.recycler.findViewHolderForAdapterPosition(position) as? ChapterHolder)
?.notifyStatus(Download.CHECKED, false, 0)
startingDLChapterPos = position
actionMode?.invalidate()
@ -595,7 +591,7 @@ class MangaDetailsController :
downloadChapters(chapterList)
presenter.fetchChapters(false)
adapter?.removeSelection(startingPosition)
(recycler.findViewHolderForAdapterPosition(startingPosition) as? BaseFlexibleViewHolder)
(binding.recycler.findViewHolderForAdapterPosition(startingPosition) as? BaseFlexibleViewHolder)
?.toggleActivation()
startingDLChapterPos = null
destroyActionModeIfNeeded()
@ -631,7 +627,7 @@ class MangaDetailsController :
}
override fun onActionStateChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
swipe_refresh.isEnabled = actionState != ItemTouchHelper.ACTION_STATE_SWIPE
binding.swipeRefresh.isEnabled = actionState != ItemTouchHelper.ACTION_STATE_SWIPE
}
override fun onItemMove(fromPosition: Int, toPosition: Int) {
@ -664,7 +660,6 @@ class MangaDetailsController :
fun bookmarkChapter(position: Int) {
val item = adapter?.getItem(position) as? ChapterItem ?: return
val chapter = item.chapter
val bookmarked = item.bookmark
bookmarkChapters(listOf(item), !bookmarked)
snack?.dismiss()
@ -975,8 +970,8 @@ class MangaDetailsController :
// In case the recycler is at the bottom and collapsing the header makes it unscrollable
override fun updateScroll() {
if (recycler?.canScrollVertically(-1) == false) {
getHeader()?.backdrop?.translationY = 0f
if (!binding.recycler.canScrollVertically(-1)) {
getHeader()?.binding?.backdrop?.translationY = 0f
activityBinding?.appBar?.y = 0f
colorToolbar(isColor = false, animate = false)
}
@ -1083,7 +1078,7 @@ class MangaDetailsController :
if (!manga.favorite) {
toggleMangaFavorite()
} else {
val favButton = getHeader()?.favorite_button ?: return
val favButton = getHeader()?.binding?.favoriteButton ?: return
val popup = makeFavPopup(favButton, manga, categories)
popup.show()
}
@ -1184,7 +1179,7 @@ class MangaDetailsController :
}
)
}
val favButton = getHeader()?.favorite_button
val favButton = getHeader()?.binding?.favoriteButton
(activity as? MainActivity)?.setUndoSnackBar(snack, favButton)
}
@ -1261,7 +1256,7 @@ class MangaDetailsController :
private fun createActionModeIfNeeded() {
if (actionMode == null) {
actionMode = (activity as AppCompatActivity).startSupportActionMode(this)
(activity as MainActivity).toolbar.setBackgroundColor(Color.TRANSPARENT)
activityBinding?.toolbar?.setBackgroundColor(Color.TRANSPARENT)
val view = activity?.window?.currentFocus ?: return
val imm = activity?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
?: return
@ -1301,7 +1296,7 @@ class MangaDetailsController :
setStatusBarAndToolbar()
if (startingDLChapterPos != null) {
val item = adapter?.getItem(startingDLChapterPos!!) as? ChapterItem
(recycler.findViewHolderForAdapterPosition(startingDLChapterPos!!) as? ChapterHolder)?.notifyStatus(
(binding.recycler.findViewHolderForAdapterPosition(startingDLChapterPos!!) as? ChapterHolder)?.notifyStatus(
item?.status ?: Download.NOT_DOWNLOADED,
false,
0
@ -1352,8 +1347,8 @@ class MangaDetailsController :
currentAnimator?.cancel()
// Load the high-resolution "zoomed-in" image.
val expandedImageView = manga_cover_full ?: return
val fullBackdrop = full_backdrop
val expandedImageView = binding.mangaCoverFull
val fullBackdrop = binding.fullBackdrop
// Hide the thumbnail and show the zoomed-in view. When the animation
// begins, it will position the zoomed-in view in the place of the
@ -1364,7 +1359,7 @@ class MangaDetailsController :
// Set the pivot point to 0 to match thumbnail
swipe_refresh.isEnabled = false
binding.swipeRefresh.isEnabled = false
val rect = Rect()
thumbView.getGlobalVisibleRect(rect)
@ -1379,15 +1374,14 @@ class MangaDetailsController :
expandedImageView.requestLayout()
val activity = activity as? MainActivity ?: return
val currTheme = activityBinding!!.appBar.context.theme
val currColor = activity.drawerArrow?.color
if (!activity.isInNightMode()) {
activityBinding?.appBar?.context?.setTheme(R.style.ThemeOverlay_AppCompat_Dark_ActionBar)
val iconPrimary = Color.WHITE
activity.toolbar.setTitleTextColor(iconPrimary)
activityBinding?.toolbar?.setTitleTextColor(iconPrimary)
activity.drawerArrow?.color = iconPrimary
activity.toolbar.overflowIcon?.setTint(iconPrimary)
activityBinding?.toolbar?.overflowIcon?.setTint(iconPrimary)
activity.window.decorView.systemUiVisibility =
activity.window.decorView.systemUiVisibility.rem(
View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
@ -1398,14 +1392,13 @@ class MangaDetailsController :
expandedImageView.post {
val defMargin = 16.dpToPx
manga_cover_full ?: return@post
expandedImageView.updateLayoutParams<ViewGroup.MarginLayoutParams> {
height = ViewGroup.LayoutParams.MATCH_PARENT
width = ViewGroup.LayoutParams.MATCH_PARENT
topMargin = defMargin + headerHeight
leftMargin = defMargin
rightMargin = defMargin
bottomMargin = defMargin + recycler.paddingBottom
bottomMargin = defMargin + binding.recycler.paddingBottom
}
val shortAnimationDuration = resources?.getInteger(
android.R.integer.config_shortAnimTime
@ -1418,7 +1411,7 @@ class MangaDetailsController :
val changeImageTransform = ChangeImageTransform()
transitionSet.addTransition(changeImageTransform)
transitionSet.duration = shortAnimationDuration.toLong()
TransitionManager.beginDelayedTransition(frame_layout, transitionSet)
TransitionManager.beginDelayedTransition(binding.frameLayout, transitionSet)
// AnimationSet for backdrop because idk how to use TransitionSet
currentAnimator = AnimatorSet().apply {
@ -1431,12 +1424,12 @@ class MangaDetailsController :
object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
TransitionManager.endTransitions(frame_layout)
TransitionManager.endTransitions(binding.frameLayout)
currentAnimator = null
}
override fun onAnimationCancel(animation: Animator) {
TransitionManager.endTransitions(frame_layout)
TransitionManager.endTransitions(binding.frameLayout)
currentAnimator = null
}
}
@ -1467,7 +1460,7 @@ class MangaDetailsController :
val changeImageTransform2 = ChangeImageTransform()
transitionSet2.addTransition(changeImageTransform2)
transitionSet2.duration = shortAnimationDuration.toLong()
TransitionManager.beginDelayedTransition(frame_layout, transitionSet2)
TransitionManager.beginDelayedTransition(binding.frameLayout, transitionSet2)
// Animation to remove backdrop and hide the full cover
currentAnimator = AnimatorSet().apply {
@ -1481,9 +1474,9 @@ class MangaDetailsController :
)
val iconPrimary = currColor ?: Color.WHITE
activity.toolbar.setTitleTextColor(iconPrimary)
activityBinding?.toolbar?.setTitleTextColor(iconPrimary)
activity.drawerArrow?.color = iconPrimary
activity.toolbar.overflowIcon?.setTint(iconPrimary)
activityBinding?.toolbar?.overflowIcon?.setTint(iconPrimary)
activity.window.decorView.systemUiVisibility =
activity.window.decorView.systemUiVisibility.or(
View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
@ -1496,7 +1489,7 @@ class MangaDetailsController :
thumbView.alpha = 1f
expandedImageView.visibility = View.GONE
fullBackdrop.visibility = View.GONE
swipe_refresh.isEnabled = true
binding.swipeRefresh.isEnabled = true
currentAnimator = null
}
@ -1504,7 +1497,7 @@ class MangaDetailsController :
thumbView.alpha = 1f
expandedImageView.visibility = View.GONE
fullBackdrop.visibility = View.GONE
swipe_refresh.isEnabled = true
binding.swipeRefresh.isEnabled = true
currentAnimator = null
}
}

View File

@ -5,7 +5,6 @@ import android.content.res.ColorStateList
import android.graphics.Color
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import androidx.core.graphics.ColorUtils
@ -14,10 +13,10 @@ import coil.request.CachePolicy
import com.google.android.material.button.MaterialButton
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.databinding.MangaHeaderItemBinding
import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.system.isLTR
import eu.kanade.tachiyomi.util.view.gone
@ -27,8 +26,6 @@ import eu.kanade.tachiyomi.util.view.resetStrokeColor
import eu.kanade.tachiyomi.util.view.updateLayoutParams
import eu.kanade.tachiyomi.util.view.visible
import eu.kanade.tachiyomi.util.view.visibleIf
import kotlinx.android.synthetic.main.manga_details_controller.*
import kotlinx.android.synthetic.main.manga_header_item.*
@SuppressLint("ClickableViewAccessibility")
class MangaHeaderHolder(
@ -37,100 +34,96 @@ class MangaHeaderHolder(
startExpanded: Boolean
) : BaseFlexibleViewHolder(view, adapter) {
val binding = MangaHeaderItemBinding.bind(view)
private var showReadingButton = true
private var showMoreButton = true
var hadSelection = false
init {
chapter_layout.setOnClickListener { adapter.delegate.showChapterFilter() }
if (start_reading_button != null) {
start_reading_button.setOnClickListener { adapter.delegate.readNextChapter() }
top_view.updateLayoutParams<ConstraintLayout.LayoutParams> {
height = adapter.delegate.topCoverHeight()
}
more_button.setOnClickListener { expandDesc() }
manga_summary.setOnClickListener {
if (more_button.isVisible()) {
expandDesc()
} else if (!hadSelection) {
collapseDesc()
} else {
hadSelection = false
}
}
manga_summary.setOnLongClickListener {
if (manga_summary.isTextSelectable && !adapter.recyclerView.canScrollVertically(-1)) {
(adapter.delegate as MangaDetailsController).swipe_refresh.isEnabled = false
}
false
}
manga_summary.setOnTouchListener { _, event ->
if (event.action == MotionEvent.ACTION_DOWN) {
view.requestFocus()
}
if (event.actionMasked == MotionEvent.ACTION_UP) {
hadSelection = manga_summary.hasSelection()
(adapter.delegate as MangaDetailsController).swipe_refresh.isEnabled =
true
}
false
}
if (!itemView.resources.isLTR) {
more_bg_gradient.rotation = 180f
}
less_button.setOnClickListener { collapseDesc() }
manga_genres_tags.setOnTagClickListener {
adapter.delegate.tagClicked(it)
}
webview_button.setOnClickListener { adapter.delegate.openInWebView() }
share_button.setOnClickListener { adapter.delegate.prepareToShareManga() }
favorite_button.setOnClickListener {
adapter.delegate.favoriteManga(false)
}
title.setOnClickListener {
title.text?.let { adapter.delegate.globalSearch(it.toString()) }
}
title.setOnLongClickListener {
adapter.delegate.copyToClipboard(title.text.toString(), R.string.title)
true
}
manga_author.setOnClickListener {
manga_author.text?.let { adapter.delegate.globalSearch(it.toString()) }
}
manga_author.setOnLongClickListener {
adapter.delegate.copyToClipboard(manga_author.text.toString(), R.string.author)
true
}
manga_cover.setOnClickListener { adapter.delegate.zoomImageFromThumb(cover_card) }
track_button.setOnClickListener { adapter.delegate.showTrackingSheet() }
if (startExpanded) expandDesc()
else collapseDesc()
} else {
filter_button.updateLayoutParams<ViewGroup.MarginLayoutParams> {
marginEnd = 12.dpToPx
binding.chapterLayout.setOnClickListener { adapter.delegate.showChapterFilter() }
binding.startReadingButton.setOnClickListener { adapter.delegate.readNextChapter() }
binding.topView.updateLayoutParams<ConstraintLayout.LayoutParams> {
height = adapter.delegate.topCoverHeight()
}
binding.moreButton.setOnClickListener { expandDesc() }
binding.mangaSummary.setOnClickListener {
if (binding.moreButton.isVisible()) {
expandDesc()
} else if (!hadSelection) {
collapseDesc()
} else {
hadSelection = false
}
}
binding.mangaSummary.setOnLongClickListener {
if (binding.mangaSummary.isTextSelectable && !adapter.recyclerView.canScrollVertically(-1)) {
(adapter.delegate as MangaDetailsController).binding.swipeRefresh.isEnabled = false
}
false
}
binding.mangaSummary.setOnTouchListener { _, event ->
if (event.action == MotionEvent.ACTION_DOWN) {
view.requestFocus()
}
if (event.actionMasked == MotionEvent.ACTION_UP) {
hadSelection = binding.mangaSummary.hasSelection()
(adapter.delegate as MangaDetailsController).binding.swipeRefresh.isEnabled =
true
}
false
}
if (!itemView.resources.isLTR) {
binding.moreBgGradient.rotation = 180f
}
binding.lessButton.setOnClickListener { collapseDesc() }
binding.mangaGenresTags.setOnTagClickListener {
adapter.delegate.tagClicked(it)
}
binding.webviewButton.setOnClickListener { adapter.delegate.openInWebView() }
binding.shareButton.setOnClickListener { adapter.delegate.prepareToShareManga() }
binding.favoriteButton.setOnClickListener {
adapter.delegate.favoriteManga(false)
}
binding.title.setOnClickListener {
binding.title.text?.let { adapter.delegate.globalSearch(it.toString()) }
}
binding.title.setOnLongClickListener {
adapter.delegate.copyToClipboard(binding.title.text.toString(), R.string.title)
true
}
binding.mangaAuthor.setOnClickListener {
binding.mangaAuthor.text?.let { adapter.delegate.globalSearch(it.toString()) }
}
binding.mangaAuthor.setOnLongClickListener {
adapter.delegate.copyToClipboard(binding.mangaAuthor.text.toString(), R.string.author)
true
}
binding.mangaCover.setOnClickListener { adapter.delegate.zoomImageFromThumb(binding.coverCard) }
binding.trackButton.setOnClickListener { adapter.delegate.showTrackingSheet() }
if (startExpanded) expandDesc()
else collapseDesc()
}
private fun expandDesc() {
if (more_button.visibility == View.VISIBLE) {
manga_summary.maxLines = Integer.MAX_VALUE
manga_summary.setTextIsSelectable(true)
manga_genres_tags.visible()
less_button.visible()
more_button_group.gone()
title.maxLines = Integer.MAX_VALUE
if (binding.moreButton.visibility == View.VISIBLE) {
binding.mangaSummary.maxLines = Integer.MAX_VALUE
binding.mangaSummary.setTextIsSelectable(true)
binding.mangaGenresTags.visible()
binding.lessButton.visible()
binding.moreButtonGroup.gone()
binding.title.maxLines = Integer.MAX_VALUE
}
}
private fun collapseDesc() {
manga_summary.setTextIsSelectable(false)
manga_summary.isClickable = true
manga_summary.maxLines = 3
manga_genres_tags.gone()
less_button.gone()
more_button_group.visible()
title.maxLines = 4
binding.mangaSummary.setTextIsSelectable(false)
binding.mangaSummary.isClickable = true
binding.mangaSummary.maxLines = 3
binding.mangaGenresTags.gone()
binding.lessButton.gone()
binding.moreButtonGroup.visible()
binding.title.maxLines = 4
adapter.recyclerView.post {
adapter.delegate.updateScroll()
}
@ -139,48 +132,48 @@ class MangaHeaderHolder(
fun bindChapters() {
val presenter = adapter.delegate.mangaPresenter()
val count = presenter.chapters.size
chapters_title.text = itemView.resources.getQuantityString(R.plurals.chapters_plural, count, count)
filters_text.text = presenter.currentFilters()
binding.chaptersTitle.text = itemView.resources.getQuantityString(R.plurals.chapters_plural, count, count)
binding.filtersText.text = presenter.currentFilters()
}
@SuppressLint("SetTextI18n")
fun bind(item: MangaHeaderItem, manga: Manga) {
val presenter = adapter.delegate.mangaPresenter()
title.text = manga.title
binding.title.text = manga.title
if (manga.genre.isNullOrBlank().not()) manga_genres_tags.setTags(
if (manga.genre.isNullOrBlank().not()) binding.mangaGenresTags.setTags(
manga.genre?.split(",")?.map(String::trim)
)
else manga_genres_tags.setTags(emptyList())
else binding.mangaGenresTags.setTags(emptyList())
if (manga.author == manga.artist || manga.artist.isNullOrBlank()) {
manga_author.text = manga.author?.trim()
binding.mangaAuthor.text = manga.author?.trim()
} else {
manga_author.text = listOfNotNull(manga.author?.trim(), manga.artist?.trim()).joinToString(", ")
binding.mangaAuthor.text = listOfNotNull(manga.author?.trim(), manga.artist?.trim()).joinToString(", ")
}
manga_summary.text =
binding.mangaSummary.text =
if (manga.description.isNullOrBlank()) itemView.context.getString(R.string.no_description)
else manga.description?.trim()
manga_summary.post {
manga_summary ?: return@post
if (sub_item_group.visibility != View.GONE) {
if ((manga_summary.lineCount < 3 && manga.genre.isNullOrBlank()) || less_button.isVisible()) {
manga_summary.setTextIsSelectable(true)
more_button_group.gone()
showMoreButton = less_button.isVisible()
binding.mangaSummary.post {
binding.mangaSummary
if (binding.subItemGroup.visibility != View.GONE) {
if ((binding.mangaSummary.lineCount < 3 && manga.genre.isNullOrBlank()) || binding.lessButton.isVisible()) {
binding.mangaSummary.setTextIsSelectable(true)
binding.moreButtonGroup.gone()
showMoreButton = binding.lessButton.isVisible()
} else {
more_button_group.visible()
binding.moreButtonGroup.visible()
}
}
if (adapter.hasFilter()) collapse()
else expand()
}
manga_summary_label.text = itemView.context.getString(
binding.mangaSummaryLabel.text = itemView.context.getString(
R.string.about_this_,
manga.mangaType(itemView.context)
)
with(favorite_button) {
with(binding.favoriteButton) {
icon = ContextCompat.getDrawable(
itemView.context,
when {
@ -199,14 +192,14 @@ class MangaHeaderHolder(
checked(!item.isLocked && manga.favorite)
adapter.delegate.setFavButtonPopup(this)
}
true_backdrop.setBackgroundColor(
binding.trueBackdrop.setBackgroundColor(
adapter.delegate.coverColor()
?: itemView.context.getResourceColor(android.R.attr.colorBackground)
)
val tracked = presenter.isTracked() && !item.isLocked
with(track_button) {
with(binding.trackButton) {
visibleIf(presenter.hasTrackers())
text = itemView.context.getString(
if (tracked) R.string.tracked
@ -220,7 +213,7 @@ class MangaHeaderHolder(
checked(tracked)
}
with(start_reading_button) {
with(binding.startReadingButton) {
val nextChapter = presenter.getNextUnreadChapter()
visibleIf(presenter.chapters.isNotEmpty() && !item.isLocked && !adapter.hasFilter())
showReadingButton = isVisible()
@ -244,14 +237,14 @@ class MangaHeaderHolder(
}
val count = presenter.chapters.size
chapters_title.text = itemView.resources.getQuantityString(R.plurals.chapters_plural, count, count)
binding.chaptersTitle.text = itemView.resources.getQuantityString(R.plurals.chapters_plural, count, count)
top_view.updateLayoutParams<ConstraintLayout.LayoutParams> {
binding.topView.updateLayoutParams<ConstraintLayout.LayoutParams> {
height = adapter.delegate.topCoverHeight()
}
manga_status.visibleIf(manga.status != 0)
manga_status.text = (
binding.mangaStatus.visibleIf(manga.status != 0)
binding.mangaStatus.text = (
itemView.context.getString(
when (manga.status) {
SManga.ONGOING -> R.string.ongoing
@ -261,13 +254,13 @@ class MangaHeaderHolder(
}
)
)
manga_source.text = presenter.source.toString()
binding.mangaSource.text = presenter.source.toString()
filters_text.text = presenter.currentFilters()
binding.filtersText.text = presenter.currentFilters()
if (manga.source == LocalSource.ID) {
webview_button.gone()
share_button.gone()
binding.webviewButton.gone()
binding.shareButton.gone()
}
if (!manga.initialized) return
@ -291,19 +284,19 @@ class MangaHeaderHolder(
}
fun setTopHeight(newHeight: Int) {
top_view.updateLayoutParams<ConstraintLayout.LayoutParams> {
binding.topView.updateLayoutParams<ConstraintLayout.LayoutParams> {
height = newHeight
}
}
fun setBackDrop(color: Int) {
true_backdrop.setBackgroundColor(color)
binding.trueBackdrop.setBackgroundColor(color)
}
fun updateTracking() {
val presenter = adapter.delegate.mangaPresenter()
val tracked = presenter.isTracked()
with(track_button) {
with(binding.trackButton) {
text = itemView.context.getString(
if (tracked) R.string.tracked
else R.string.tracking
@ -319,20 +312,20 @@ class MangaHeaderHolder(
}
fun collapse() {
sub_item_group.gone()
start_reading_button.gone()
if (more_button.visibility == View.VISIBLE || more_button.visibility == View.INVISIBLE) {
more_button_group.invisible()
binding.subItemGroup.gone()
binding.startReadingButton.gone()
if (binding.moreButton.visibility == View.VISIBLE || binding.moreButton.visibility == View.INVISIBLE) {
binding.moreButtonGroup.invisible()
} else {
less_button.gone()
manga_genres_tags.gone()
binding.lessButton.gone()
binding.mangaGenresTags.gone()
}
}
fun updateCover(manga: Manga) {
if (!manga.initialized) return
val drawable = adapter.controller.manga_cover_full?.drawable
manga_cover.loadAny(
val drawable = adapter.controller.binding.mangaCoverFull.drawable
binding.mangaCover.loadAny(
manga,
builder = {
placeholder(drawable)
@ -340,7 +333,7 @@ class MangaHeaderHolder(
if (manga.favorite) networkCachePolicy(CachePolicy.DISABLED)
}
)
backdrop.loadAny(
binding.backdrop.loadAny(
manga,
builder = {
placeholder(drawable)
@ -351,16 +344,16 @@ class MangaHeaderHolder(
}
fun expand() {
sub_item_group.visible()
if (!showMoreButton) more_button_group.gone()
binding.subItemGroup.visible()
if (!showMoreButton) binding.moreButtonGroup.gone()
else {
if (manga_summary.maxLines != Integer.MAX_VALUE) more_button_group.visible()
if (binding.mangaSummary.maxLines != Integer.MAX_VALUE) binding.moreButtonGroup.visible()
else {
less_button.visible()
manga_genres_tags.visible()
binding.lessButton.visible()
binding.mangaGenresTags.visible()
}
}
start_reading_button.visibleIf(showReadingButton)
binding.startReadingButton.visibleIf(showReadingButton)
}
override fun onLongClick(view: View?): Boolean {

View File

@ -5,7 +5,6 @@ import androidx.appcompat.widget.PopupMenu
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
import kotlinx.android.synthetic.main.download_button.*
open class BaseChapterHolder(
view: View,
@ -13,17 +12,19 @@ open class BaseChapterHolder(
) : BaseFlexibleViewHolder(view, adapter) {
init {
download_button?.setOnClickListener { downloadOrRemoveMenu() }
view.findViewById<View>(R.id.download_button)?.setOnClickListener { downloadOrRemoveMenu() }
}
private fun downloadOrRemoveMenu() {
val chapter = adapter.getItem(flexibleAdapterPosition) as? BaseChapterItem<*, *> ?: return
val downloadButton = itemView.findViewById<View>(R.id.download_button) ?: return
if (chapter.status == Download.NOT_DOWNLOADED || chapter.status == Download.ERROR) {
adapter.baseDelegate.downloadChapter(flexibleAdapterPosition)
} else {
download_button.post {
downloadButton.post {
// Create a PopupMenu, giving it the clicked view for an anchor
val popup = PopupMenu(download_button.context, download_button)
val popup = PopupMenu(downloadButton.context, downloadButton)
// Inflate our menu resource into the PopupMenu's Menu
popup.menuInflater.inflate(R.menu.chapter_download, popup.menu)
@ -31,7 +32,7 @@ open class BaseChapterHolder(
popup.menu.findItem(R.id.action_start).isVisible = chapter.status == Download.QUEUE
// Hide download and show delete if the chapter is downloaded
if (chapter.status != Download.DOWNLOADED) popup.menu.findItem(R.id.action_delete).title = download_button.context.getString(
if (chapter.status != Download.DOWNLOADED) popup.menu.findItem(R.id.action_delete).title = downloadButton.context.getString(
R.string.cancel
)

View File

@ -6,6 +6,7 @@ import android.view.View
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.databinding.ChaptersItemBinding
import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.ui.manga.MangaDetailsAdapter
import eu.kanade.tachiyomi.util.chapter.ChapterUtil
@ -16,18 +17,17 @@ import eu.kanade.tachiyomi.util.view.visible
import eu.kanade.tachiyomi.util.view.visibleIf
import eu.kanade.tachiyomi.widget.EndAnimatorListener
import eu.kanade.tachiyomi.widget.StartAnimatorListener
import kotlinx.android.synthetic.main.chapters_item.*
import kotlinx.android.synthetic.main.download_button.*
class ChapterHolder(
view: View,
private val adapter: MangaDetailsAdapter
) : BaseChapterHolder(view, adapter) {
private val binding = ChaptersItemBinding.bind(view)
private var localSource = false
init {
download_button.setOnLongClickListener {
binding.downloadButton.downloadButton.setOnLongClickListener {
adapter.delegate.startDownloadRange(flexibleAdapterPosition)
true
}
@ -36,7 +36,7 @@ class ChapterHolder(
fun bind(item: ChapterItem, manga: Manga) {
val chapter = item.chapter
val isLocked = item.isLocked
chapter_title.text = when (manga.displayMode) {
binding.chapterTitle.text = when (manga.displayMode) {
Manga.DISPLAY_NUMBER -> {
val number = adapter.decimalFormat.format(chapter.chapter_number.toDouble())
itemView.context.getString(R.string.chapter_, number)
@ -45,9 +45,9 @@ class ChapterHolder(
}
localSource = manga.source == LocalSource.ID
download_button.visibleIf(!localSource && !isLocked)
binding.downloadButton.downloadButton.visibleIf(!localSource && !isLocked)
ChapterUtil.setTextViewForChapter(chapter_title, item, hideStatus = isLocked)
ChapterUtil.setTextViewForChapter(binding.chapterTitle, item, hideStatus = isLocked)
val statuses = mutableListOf<String>()
@ -74,22 +74,22 @@ class ChapterHolder(
chapter.scanlator?.isNotBlank()?.let { statuses.add(chapter.scanlator!!) }
if (front_view.translationX == 0f) {
read.setImageResource(
if (binding.frontView.translationX == 0f) {
binding.read.setImageResource(
if (item.read) R.drawable.ic_eye_off_24dp else R.drawable.ic_eye_24dp
)
bookmark.setImageResource(
binding.bookmark.setImageResource(
if (item.bookmark) R.drawable.ic_bookmark_off_24dp else R.drawable.ic_bookmark_24dp
)
}
// this will color the scanlator the same bookmarks
ChapterUtil.setTextViewForChapter(
chapter_scanlator,
binding.chapterScanlator,
item,
showBookmark = false,
hideStatus = isLocked
)
chapter_scanlator.text = statuses.joinToString("")
binding.chapterScanlator.text = statuses.joinToString("")
val status = when {
adapter.isSelected(flexibleAdapterPosition) -> Download.CHECKED
@ -108,14 +108,14 @@ class ChapterHolder(
val animatorSet = AnimatorSet()
val anim1 = slideAnimation(0f, slide)
anim1.startDelay = 1000
anim1.addListener(StartAnimatorListener { left_view.visible() })
anim1.addListener(StartAnimatorListener { binding.leftView.visible() })
val anim2 = slideAnimation(slide, -slide)
anim2.duration = 600
anim2.startDelay = 500
anim2.addUpdateListener {
if (left_view.isVisible() && front_view.translationX <= 0) {
left_view.gone()
right_view.visible()
if (binding.leftView.isVisible() && binding.frontView.translationX <= 0) {
binding.leftView.gone()
binding.rightView.visible()
}
}
val anim3 = slideAnimation(-slide, 0f)
@ -130,32 +130,32 @@ class ChapterHolder(
}
private fun slideAnimation(from: Float, to: Float): ObjectAnimator {
return ObjectAnimator.ofFloat(front_view, View.TRANSLATION_X, from, to)
return ObjectAnimator.ofFloat(binding.frontView, View.TRANSLATION_X, from, to)
.setDuration(300)
}
override fun getFrontView(): View {
return front_view
return binding.frontView
}
override fun getRearRightView(): View {
return right_view
return binding.rightView
}
override fun getRearLeftView(): View {
return left_view
return binding.leftView
}
private fun resetFrontView() {
if (front_view.translationX != 0f) itemView.post { adapter.notifyItemChanged(flexibleAdapterPosition) }
if (binding.frontView.translationX != 0f) itemView.post { adapter.notifyItemChanged(flexibleAdapterPosition) }
}
fun notifyStatus(status: Int, locked: Boolean, progress: Int) = with(download_button) {
fun notifyStatus(status: Int, locked: Boolean, progress: Int) = with(binding.downloadButton.downloadButton) {
if (locked) {
gone()
return
}
download_button.visibleIf(!localSource)
visibleIf(!localSource)
setDownloadStatus(status, progress)
}
}

View File

@ -92,6 +92,7 @@
<include
layout="@layout/download_button"
android:id="@+id/download_button"
android:layout_width="50dp"
android:layout_height="0dp"
android:layout_marginEnd="4dp"

View File

@ -382,7 +382,7 @@
android:background="@null"
android:padding="5dp"
android:src="@drawable/ic_filter_list_24dp"
android:tint="?colorAccent"
app:tint="?colorAccent"
app:layout_constraintBottom_toBottomOf="@id/chapters_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/chapters_title" />