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

View File

@ -5,7 +5,6 @@ import android.content.res.ColorStateList
import android.graphics.Color import android.graphics.Color
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.graphics.ColorUtils import androidx.core.graphics.ColorUtils
@ -14,10 +13,10 @@ import coil.request.CachePolicy
import com.google.android.material.button.MaterialButton 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.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
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder 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.getResourceColor
import eu.kanade.tachiyomi.util.system.isLTR import eu.kanade.tachiyomi.util.system.isLTR
import eu.kanade.tachiyomi.util.view.gone 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.updateLayoutParams
import eu.kanade.tachiyomi.util.view.visible import eu.kanade.tachiyomi.util.view.visible
import eu.kanade.tachiyomi.util.view.visibleIf 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") @SuppressLint("ClickableViewAccessibility")
class MangaHeaderHolder( class MangaHeaderHolder(
@ -37,20 +34,21 @@ class MangaHeaderHolder(
startExpanded: Boolean startExpanded: Boolean
) : BaseFlexibleViewHolder(view, adapter) { ) : BaseFlexibleViewHolder(view, adapter) {
val binding = MangaHeaderItemBinding.bind(view)
private var showReadingButton = true private var showReadingButton = true
private var showMoreButton = true private var showMoreButton = true
var hadSelection = false var hadSelection = false
init { init {
chapter_layout.setOnClickListener { adapter.delegate.showChapterFilter() } binding.chapterLayout.setOnClickListener { adapter.delegate.showChapterFilter() }
if (start_reading_button != null) { binding.startReadingButton.setOnClickListener { adapter.delegate.readNextChapter() }
start_reading_button.setOnClickListener { adapter.delegate.readNextChapter() } binding.topView.updateLayoutParams<ConstraintLayout.LayoutParams> {
top_view.updateLayoutParams<ConstraintLayout.LayoutParams> {
height = adapter.delegate.topCoverHeight() height = adapter.delegate.topCoverHeight()
} }
more_button.setOnClickListener { expandDesc() } binding.moreButton.setOnClickListener { expandDesc() }
manga_summary.setOnClickListener { binding.mangaSummary.setOnClickListener {
if (more_button.isVisible()) { if (binding.moreButton.isVisible()) {
expandDesc() expandDesc()
} else if (!hadSelection) { } else if (!hadSelection) {
collapseDesc() collapseDesc()
@ -58,79 +56,74 @@ class MangaHeaderHolder(
hadSelection = false hadSelection = false
} }
} }
manga_summary.setOnLongClickListener { binding.mangaSummary.setOnLongClickListener {
if (manga_summary.isTextSelectable && !adapter.recyclerView.canScrollVertically(-1)) { if (binding.mangaSummary.isTextSelectable && !adapter.recyclerView.canScrollVertically(-1)) {
(adapter.delegate as MangaDetailsController).swipe_refresh.isEnabled = false (adapter.delegate as MangaDetailsController).binding.swipeRefresh.isEnabled = false
} }
false false
} }
manga_summary.setOnTouchListener { _, event -> binding.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 = manga_summary.hasSelection() hadSelection = binding.mangaSummary.hasSelection()
(adapter.delegate as MangaDetailsController).swipe_refresh.isEnabled = (adapter.delegate as MangaDetailsController).binding.swipeRefresh.isEnabled =
true true
} }
false false
} }
if (!itemView.resources.isLTR) { if (!itemView.resources.isLTR) {
more_bg_gradient.rotation = 180f binding.moreBgGradient.rotation = 180f
} }
less_button.setOnClickListener { collapseDesc() } binding.lessButton.setOnClickListener { collapseDesc() }
manga_genres_tags.setOnTagClickListener { binding.mangaGenresTags.setOnTagClickListener {
adapter.delegate.tagClicked(it) adapter.delegate.tagClicked(it)
} }
webview_button.setOnClickListener { adapter.delegate.openInWebView() } binding.webviewButton.setOnClickListener { adapter.delegate.openInWebView() }
share_button.setOnClickListener { adapter.delegate.prepareToShareManga() } binding.shareButton.setOnClickListener { adapter.delegate.prepareToShareManga() }
favorite_button.setOnClickListener { binding.favoriteButton.setOnClickListener {
adapter.delegate.favoriteManga(false) adapter.delegate.favoriteManga(false)
} }
title.setOnClickListener { binding.title.setOnClickListener {
title.text?.let { adapter.delegate.globalSearch(it.toString()) } binding.title.text?.let { adapter.delegate.globalSearch(it.toString()) }
} }
title.setOnLongClickListener { binding.title.setOnLongClickListener {
adapter.delegate.copyToClipboard(title.text.toString(), R.string.title) adapter.delegate.copyToClipboard(binding.title.text.toString(), R.string.title)
true true
} }
manga_author.setOnClickListener { binding.mangaAuthor.setOnClickListener {
manga_author.text?.let { adapter.delegate.globalSearch(it.toString()) } binding.mangaAuthor.text?.let { adapter.delegate.globalSearch(it.toString()) }
} }
manga_author.setOnLongClickListener { binding.mangaAuthor.setOnLongClickListener {
adapter.delegate.copyToClipboard(manga_author.text.toString(), R.string.author) adapter.delegate.copyToClipboard(binding.mangaAuthor.text.toString(), R.string.author)
true true
} }
manga_cover.setOnClickListener { adapter.delegate.zoomImageFromThumb(cover_card) } binding.mangaCover.setOnClickListener { adapter.delegate.zoomImageFromThumb(binding.coverCard) }
track_button.setOnClickListener { adapter.delegate.showTrackingSheet() } binding.trackButton.setOnClickListener { adapter.delegate.showTrackingSheet() }
if (startExpanded) expandDesc() if (startExpanded) expandDesc()
else collapseDesc() else collapseDesc()
} else {
filter_button.updateLayoutParams<ViewGroup.MarginLayoutParams> {
marginEnd = 12.dpToPx
}
}
} }
private fun expandDesc() { private fun expandDesc() {
if (more_button.visibility == View.VISIBLE) { if (binding.moreButton.visibility == View.VISIBLE) {
manga_summary.maxLines = Integer.MAX_VALUE binding.mangaSummary.maxLines = Integer.MAX_VALUE
manga_summary.setTextIsSelectable(true) binding.mangaSummary.setTextIsSelectable(true)
manga_genres_tags.visible() binding.mangaGenresTags.visible()
less_button.visible() binding.lessButton.visible()
more_button_group.gone() binding.moreButtonGroup.gone()
title.maxLines = Integer.MAX_VALUE binding.title.maxLines = Integer.MAX_VALUE
} }
} }
private fun collapseDesc() { private fun collapseDesc() {
manga_summary.setTextIsSelectable(false) binding.mangaSummary.setTextIsSelectable(false)
manga_summary.isClickable = true binding.mangaSummary.isClickable = true
manga_summary.maxLines = 3 binding.mangaSummary.maxLines = 3
manga_genres_tags.gone() binding.mangaGenresTags.gone()
less_button.gone() binding.lessButton.gone()
more_button_group.visible() binding.moreButtonGroup.visible()
title.maxLines = 4 binding.title.maxLines = 4
adapter.recyclerView.post { adapter.recyclerView.post {
adapter.delegate.updateScroll() adapter.delegate.updateScroll()
} }
@ -139,48 +132,48 @@ 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
chapters_title.text = itemView.resources.getQuantityString(R.plurals.chapters_plural, count, count) binding.chaptersTitle.text = itemView.resources.getQuantityString(R.plurals.chapters_plural, count, count)
filters_text.text = presenter.currentFilters() binding.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()
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) 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()) { if (manga.author == manga.artist || manga.artist.isNullOrBlank()) {
manga_author.text = manga.author?.trim() binding.mangaAuthor.text = manga.author?.trim()
} else { } 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) if (manga.description.isNullOrBlank()) itemView.context.getString(R.string.no_description)
else manga.description?.trim() else manga.description?.trim()
manga_summary.post { binding.mangaSummary.post {
manga_summary ?: return@post binding.mangaSummary
if (sub_item_group.visibility != View.GONE) { if (binding.subItemGroup.visibility != View.GONE) {
if ((manga_summary.lineCount < 3 && manga.genre.isNullOrBlank()) || less_button.isVisible()) { if ((binding.mangaSummary.lineCount < 3 && manga.genre.isNullOrBlank()) || binding.lessButton.isVisible()) {
manga_summary.setTextIsSelectable(true) binding.mangaSummary.setTextIsSelectable(true)
more_button_group.gone() binding.moreButtonGroup.gone()
showMoreButton = less_button.isVisible() showMoreButton = binding.lessButton.isVisible()
} else { } else {
more_button_group.visible() binding.moreButtonGroup.visible()
} }
} }
if (adapter.hasFilter()) collapse() if (adapter.hasFilter()) collapse()
else expand() else expand()
} }
manga_summary_label.text = itemView.context.getString( binding.mangaSummaryLabel.text = itemView.context.getString(
R.string.about_this_, R.string.about_this_,
manga.mangaType(itemView.context) manga.mangaType(itemView.context)
) )
with(favorite_button) { with(binding.favoriteButton) {
icon = ContextCompat.getDrawable( icon = ContextCompat.getDrawable(
itemView.context, itemView.context,
when { when {
@ -199,14 +192,14 @@ class MangaHeaderHolder(
checked(!item.isLocked && manga.favorite) checked(!item.isLocked && manga.favorite)
adapter.delegate.setFavButtonPopup(this) adapter.delegate.setFavButtonPopup(this)
} }
true_backdrop.setBackgroundColor( binding.trueBackdrop.setBackgroundColor(
adapter.delegate.coverColor() adapter.delegate.coverColor()
?: itemView.context.getResourceColor(android.R.attr.colorBackground) ?: itemView.context.getResourceColor(android.R.attr.colorBackground)
) )
val tracked = presenter.isTracked() && !item.isLocked val tracked = presenter.isTracked() && !item.isLocked
with(track_button) { with(binding.trackButton) {
visibleIf(presenter.hasTrackers()) visibleIf(presenter.hasTrackers())
text = itemView.context.getString( text = itemView.context.getString(
if (tracked) R.string.tracked if (tracked) R.string.tracked
@ -220,7 +213,7 @@ class MangaHeaderHolder(
checked(tracked) checked(tracked)
} }
with(start_reading_button) { with(binding.startReadingButton) {
val nextChapter = presenter.getNextUnreadChapter() val nextChapter = presenter.getNextUnreadChapter()
visibleIf(presenter.chapters.isNotEmpty() && !item.isLocked && !adapter.hasFilter()) visibleIf(presenter.chapters.isNotEmpty() && !item.isLocked && !adapter.hasFilter())
showReadingButton = isVisible() showReadingButton = isVisible()
@ -244,14 +237,14 @@ class MangaHeaderHolder(
} }
val count = presenter.chapters.size 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() height = adapter.delegate.topCoverHeight()
} }
manga_status.visibleIf(manga.status != 0) binding.mangaStatus.visibleIf(manga.status != 0)
manga_status.text = ( binding.mangaStatus.text = (
itemView.context.getString( itemView.context.getString(
when (manga.status) { when (manga.status) {
SManga.ONGOING -> R.string.ongoing 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) { if (manga.source == LocalSource.ID) {
webview_button.gone() binding.webviewButton.gone()
share_button.gone() binding.shareButton.gone()
} }
if (!manga.initialized) return if (!manga.initialized) return
@ -291,19 +284,19 @@ class MangaHeaderHolder(
} }
fun setTopHeight(newHeight: Int) { fun setTopHeight(newHeight: Int) {
top_view.updateLayoutParams<ConstraintLayout.LayoutParams> { binding.topView.updateLayoutParams<ConstraintLayout.LayoutParams> {
height = newHeight height = newHeight
} }
} }
fun setBackDrop(color: Int) { fun setBackDrop(color: Int) {
true_backdrop.setBackgroundColor(color) binding.trueBackdrop.setBackgroundColor(color)
} }
fun updateTracking() { fun updateTracking() {
val presenter = adapter.delegate.mangaPresenter() val presenter = adapter.delegate.mangaPresenter()
val tracked = presenter.isTracked() val tracked = presenter.isTracked()
with(track_button) { with(binding.trackButton) {
text = itemView.context.getString( text = itemView.context.getString(
if (tracked) R.string.tracked if (tracked) R.string.tracked
else R.string.tracking else R.string.tracking
@ -319,20 +312,20 @@ class MangaHeaderHolder(
} }
fun collapse() { fun collapse() {
sub_item_group.gone() binding.subItemGroup.gone()
start_reading_button.gone() binding.startReadingButton.gone()
if (more_button.visibility == View.VISIBLE || more_button.visibility == View.INVISIBLE) { if (binding.moreButton.visibility == View.VISIBLE || binding.moreButton.visibility == View.INVISIBLE) {
more_button_group.invisible() binding.moreButtonGroup.invisible()
} else { } else {
less_button.gone() binding.lessButton.gone()
manga_genres_tags.gone() binding.mangaGenresTags.gone()
} }
} }
fun updateCover(manga: Manga) { fun updateCover(manga: Manga) {
if (!manga.initialized) return if (!manga.initialized) return
val drawable = adapter.controller.manga_cover_full?.drawable val drawable = adapter.controller.binding.mangaCoverFull.drawable
manga_cover.loadAny( binding.mangaCover.loadAny(
manga, manga,
builder = { builder = {
placeholder(drawable) placeholder(drawable)
@ -340,7 +333,7 @@ class MangaHeaderHolder(
if (manga.favorite) networkCachePolicy(CachePolicy.DISABLED) if (manga.favorite) networkCachePolicy(CachePolicy.DISABLED)
} }
) )
backdrop.loadAny( binding.backdrop.loadAny(
manga, manga,
builder = { builder = {
placeholder(drawable) placeholder(drawable)
@ -351,16 +344,16 @@ class MangaHeaderHolder(
} }
fun expand() { fun expand() {
sub_item_group.visible() binding.subItemGroup.visible()
if (!showMoreButton) more_button_group.gone() if (!showMoreButton) binding.moreButtonGroup.gone()
else { else {
if (manga_summary.maxLines != Integer.MAX_VALUE) more_button_group.visible() if (binding.mangaSummary.maxLines != Integer.MAX_VALUE) binding.moreButtonGroup.visible()
else { else {
less_button.visible() binding.lessButton.visible()
manga_genres_tags.visible() binding.mangaGenresTags.visible()
} }
} }
start_reading_button.visibleIf(showReadingButton) binding.startReadingButton.visibleIf(showReadingButton)
} }
override fun onLongClick(view: View?): Boolean { 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.R
import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
import kotlinx.android.synthetic.main.download_button.*
open class BaseChapterHolder( open class BaseChapterHolder(
view: View, view: View,
@ -13,17 +12,19 @@ open class BaseChapterHolder(
) : BaseFlexibleViewHolder(view, adapter) { ) : BaseFlexibleViewHolder(view, adapter) {
init { init {
download_button?.setOnClickListener { downloadOrRemoveMenu() } view.findViewById<View>(R.id.download_button)?.setOnClickListener { downloadOrRemoveMenu() }
} }
private fun downloadOrRemoveMenu() { private fun downloadOrRemoveMenu() {
val chapter = adapter.getItem(flexibleAdapterPosition) as? BaseChapterItem<*, *> ?: return 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) { if (chapter.status == Download.NOT_DOWNLOADED || chapter.status == Download.ERROR) {
adapter.baseDelegate.downloadChapter(flexibleAdapterPosition) adapter.baseDelegate.downloadChapter(flexibleAdapterPosition)
} else { } else {
download_button.post { downloadButton.post {
// Create a PopupMenu, giving it the clicked view for an anchor // 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 // Inflate our menu resource into the PopupMenu's Menu
popup.menuInflater.inflate(R.menu.chapter_download, popup.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 popup.menu.findItem(R.id.action_start).isVisible = chapter.status == Download.QUEUE
// Hide download and show delete if the chapter is downloaded // 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 R.string.cancel
) )

View File

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

View File

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

View File

@ -382,7 +382,7 @@
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" />