From fa01471728e0c2a859e7505fe81d49cb880c76eb Mon Sep 17 00:00:00 2001 From: Jays2Kings Date: Sun, 28 Mar 2021 23:01:53 -0400 Subject: [PATCH] Binding for manga details --- .../ui/manga/MangaDetailsController.kt | 151 +++++------ .../tachiyomi/ui/manga/MangaHeaderHolder.kt | 255 +++++++++--------- .../ui/manga/chapter/BaseChapterHolder.kt | 11 +- .../ui/manga/chapter/ChapterHolder.kt | 44 +-- app/src/main/res/layout/chapters_item.xml | 1 + app/src/main/res/layout/manga_header_item.xml | 2 +- 6 files changed, 226 insertions(+), 238 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaDetailsController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaDetailsController.kt index 702af1a2f5..5c224f44f2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaDetailsController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaDetailsController.kt @@ -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 { + binding.fastScroller.updateLayoutParams { 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) { 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 { 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 } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaHeaderHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaHeaderHolder.kt index e4a04517c4..deed1fd37c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaHeaderHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaHeaderHolder.kt @@ -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 { - 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 { - marginEnd = 12.dpToPx + binding.chapterLayout.setOnClickListener { adapter.delegate.showChapterFilter() } + binding.startReadingButton.setOnClickListener { adapter.delegate.readNextChapter() } + binding.topView.updateLayoutParams { + 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 { + binding.topView.updateLayoutParams { 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 { + binding.topView.updateLayoutParams { 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 { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/BaseChapterHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/BaseChapterHolder.kt index ba384aa129..125738b12e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/BaseChapterHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/BaseChapterHolder.kt @@ -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(R.id.download_button)?.setOnClickListener { downloadOrRemoveMenu() } } private fun downloadOrRemoveMenu() { val chapter = adapter.getItem(flexibleAdapterPosition) as? BaseChapterItem<*, *> ?: return + val downloadButton = itemView.findViewById(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 ) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterHolder.kt index d69cbd2a80..0f1821b137 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterHolder.kt @@ -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() @@ -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) } } diff --git a/app/src/main/res/layout/chapters_item.xml b/app/src/main/res/layout/chapters_item.xml index 22e7c7bc12..6a10d153c0 100644 --- a/app/src/main/res/layout/chapters_item.xml +++ b/app/src/main/res/layout/chapters_item.xml @@ -92,6 +92,7 @@