From e7d6dfff530db08a8380e68425b9f9d11da497cb Mon Sep 17 00:00:00 2001 From: Andreas Date: Sat, 28 Aug 2021 22:53:59 +0200 Subject: [PATCH] Replace MotionLayout with full screen dialog (#5806) * Remove MotionLayout and add full screen dialog for enlarged cover * Address some of the review comments --- .../tachiyomi/ui/manga/MangaController.kt | 25 +++- .../ui/manga/info/MangaFullCoverDialog.kt | 119 +++++++++++++++++ .../ui/manga/info/MangaInfoHeaderAdapter.kt | 25 +--- .../ui/manga/track/TrackSearchDialog.kt | 6 +- .../widget/TachiyomiFullscreenDialog.kt | 13 ++ app/src/main/res/drawable/ic_save_24dp.xml | 10 ++ .../res/layout-sw720dp/manga_info_header.xml | 5 +- .../res/layout/manga_full_cover_dialog.xml | 35 +++++ app/src/main/res/layout/manga_info_header.xml | 10 +- app/src/main/res/menu/full_cover.xml | 24 ++++ app/src/main/res/menu/manga.xml | 17 --- .../main/res/xml/manga_info_header_scene.xml | 122 ------------------ .../xml/manga_info_header_scene_sw720dp.xml | 60 --------- 13 files changed, 237 insertions(+), 234 deletions(-) create mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaFullCoverDialog.kt create mode 100644 app/src/main/java/eu/kanade/tachiyomi/widget/TachiyomiFullscreenDialog.kt create mode 100644 app/src/main/res/drawable/ic_save_24dp.xml create mode 100644 app/src/main/res/layout/manga_full_cover_dialog.xml create mode 100644 app/src/main/res/menu/full_cover.xml delete mode 100644 app/src/main/res/xml/manga_info_header_scene.xml delete mode 100644 app/src/main/res/xml/manga_info_header_scene_sw720dp.xml diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt index d258032d3c..93c47dd156 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt @@ -30,6 +30,7 @@ import androidx.recyclerview.widget.RecyclerView import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import coil.imageLoader import coil.request.ImageRequest +import com.bluelinelabs.conductor.Controller import com.bluelinelabs.conductor.ControllerChangeHandler import com.bluelinelabs.conductor.ControllerChangeType import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton @@ -73,6 +74,7 @@ import eu.kanade.tachiyomi.ui.manga.chapter.DeleteChaptersDialog import eu.kanade.tachiyomi.ui.manga.chapter.DownloadCustomChaptersDialog import eu.kanade.tachiyomi.ui.manga.chapter.MangaChaptersHeaderAdapter import eu.kanade.tachiyomi.ui.manga.chapter.base.BaseChaptersAdapter +import eu.kanade.tachiyomi.ui.manga.info.MangaFullCoverDialog import eu.kanade.tachiyomi.ui.manga.info.MangaInfoHeaderAdapter import eu.kanade.tachiyomi.ui.manga.track.TrackItem import eu.kanade.tachiyomi.ui.manga.track.TrackSearchDialog @@ -179,6 +181,8 @@ class MangaController : private var trackSheet: TrackSheet? = null + private var dialog: MangaFullCoverDialog? = null + init { setHasOptionsMenu(true) } @@ -435,7 +439,6 @@ class MangaController : // Hide options for non-library manga menu.findItem(R.id.action_edit_categories).isVisible = presenter.manga.favorite && presenter.getCategories().isNotEmpty() - menu.findItem(R.id.action_edit_cover).isVisible = presenter.manga.favorite menu.findItem(R.id.action_migrate).isVisible = presenter.manga.favorite } @@ -446,10 +449,6 @@ class MangaController : R.id.download_custom, R.id.download_unread, R.id.download_all -> downloadChapters(item.itemId) - R.id.action_share_cover -> shareCover() - R.id.action_save_cover -> saveCover() - R.id.action_edit_cover -> changeCover() - R.id.action_edit_categories -> onCategoriesClick() R.id.action_migrate -> migrateManga() } @@ -728,6 +727,21 @@ class MangaController : context.imageLoader.enqueue(req) } + fun showFullCoverDialog() { + if (dialog != null) return + val manga = manga ?: return + dialog = MangaFullCoverDialog(this, manga) + dialog?.addLifecycleListener( + object : LifecycleListener() { + override fun postDestroy(controller: Controller) { + super.postDestroy(controller) + dialog = null + } + } + ) + dialog?.showDialog(router) + } + fun shareCover() { try { val activity = activity!! @@ -800,6 +814,7 @@ class MangaController : fun onSetCoverSuccess() { mangaInfoAdapter?.notifyDataSetChanged() + dialog?.setImage(manga) activity?.toast(R.string.cover_updated) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaFullCoverDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaFullCoverDialog.kt new file mode 100644 index 0000000000..bc0ec8811a --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaFullCoverDialog.kt @@ -0,0 +1,119 @@ +package eu.kanade.tachiyomi.ui.manga.info + +import android.app.Dialog +import android.graphics.drawable.BitmapDrawable +import android.graphics.drawable.ColorDrawable +import android.os.Bundle +import android.util.TypedValue +import android.view.View +import androidx.core.graphics.ColorUtils +import androidx.core.os.bundleOf +import androidx.core.view.WindowCompat +import coil.imageLoader +import coil.request.Disposable +import coil.request.ImageRequest +import com.davemorrissey.labs.subscaleview.ImageSource +import dev.chrisbanes.insetter.applyInsetter +import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.data.database.DatabaseHelper +import eu.kanade.tachiyomi.data.database.models.Manga +import eu.kanade.tachiyomi.databinding.MangaFullCoverDialogBinding +import eu.kanade.tachiyomi.ui.base.controller.DialogController +import eu.kanade.tachiyomi.ui.manga.MangaController +import eu.kanade.tachiyomi.util.view.setNavigationBarTransparentCompat +import eu.kanade.tachiyomi.widget.TachiyomiFullscreenDialog +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get + +class MangaFullCoverDialog : DialogController { + + private var manga: Manga? = null + + private var binding: MangaFullCoverDialogBinding? = null + + private var disposable: Disposable? = null + + private val mangaController + get() = targetController as MangaController + + constructor(targetController: MangaController, manga: Manga) : super(bundleOf("mangaId" to manga.id)) { + this.targetController = targetController + this.manga = manga + } + + @Suppress("unused") + constructor(bundle: Bundle) : super(bundle) { + val db = Injekt.get() + manga = db.getManga(bundle.getLong("mangaId")).executeAsBlocking() + } + + override fun onCreateDialog(savedViewState: Bundle?): Dialog { + binding = MangaFullCoverDialogBinding.inflate(activity!!.layoutInflater) + + binding?.toolbar?.apply { + setNavigationOnClickListener { dialog?.dismiss() } + setOnMenuItemClickListener { + when (it.itemId) { + R.id.action_share_cover -> mangaController.shareCover() + R.id.action_save_cover -> mangaController.saveCover() + R.id.action_edit_cover -> mangaController.changeCover() + } + true + } + menu?.findItem(R.id.action_edit_cover)?.isVisible = manga?.favorite ?: false + } + + binding?.fullCover?.setOnClickListener { + dialog?.dismiss() + } + setImage(manga) + + binding?.appbar?.applyInsetter { + type(navigationBars = true, statusBars = true) { + padding(left = true, top = true, right = true) + } + } + + binding?.fullCover?.applyInsetter { + type(navigationBars = true) { + // Padding will make to image top align + // This is likely an issue with SubsamplingScaleImageView + margin(bottom = true) + } + } + + return TachiyomiFullscreenDialog(activity!!, binding!!.root).apply { + val typedValue = TypedValue() + val theme = context.theme + theme.resolveAttribute(android.R.attr.colorBackground, typedValue, true) + window?.setBackgroundDrawable(ColorDrawable(ColorUtils.setAlphaComponent(typedValue.data, 230))) + } + } + + override fun onAttach(view: View) { + super.onAttach(view) + dialog?.window?.let { window -> + window.setNavigationBarTransparentCompat(window.context) + WindowCompat.setDecorFitsSystemWindows(window, false) + } + } + + override fun onDetach(view: View) { + super.onDetach(view) + disposable?.dispose() + disposable = null + } + + fun setImage(manga: Manga?) { + val manga = manga ?: return + val request = ImageRequest.Builder(applicationContext!!) + .data(manga) + .target { + val bitmap = (it as BitmapDrawable).bitmap + binding?.fullCover?.setImage(ImageSource.cachedBitmap(bitmap)) + } + .build() + + disposable = applicationContext?.imageLoader?.enqueue(request) + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt index 2d06383665..57608d5e3e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt @@ -3,11 +3,9 @@ package eu.kanade.tachiyomi.ui.manga.info import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.isVisible import androidx.core.view.updateLayoutParams import androidx.recyclerview.widget.RecyclerView -import coil.target.ImageViewTarget import com.google.android.material.dialog.MaterialAlertDialogBuilder import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Manga @@ -87,15 +85,10 @@ class MangaInfoHeaderAdapter( binding.mangaCover.updateLayoutParams { topMargin += appBarHeight } - binding.root.getConstraintSet(R.id.end) - ?.setMargin(R.id.manga_cover, ConstraintLayout.LayoutParams.TOP, appBarHeight) } inner class HeaderViewHolder(private val view: View) : RecyclerView.ViewHolder(view) { fun bind() { - val headerTransition = binding.root.getTransition(R.id.manga_info_header_transition) - headerTransition.applySystemAnimatorScale(view.context) - val summaryTransition = binding.mangaSummarySection.getTransition(R.id.manga_summary_section_transition) summaryTransition.applySystemAnimatorScale(view.context) @@ -199,6 +192,12 @@ class MangaInfoHeaderAdapter( } .launchIn(controller.viewScope) + binding.mangaCover.clicks() + .onEach { + controller.showFullCoverDialog() + } + .launchIn(controller.viewScope) + binding.mangaCover.longClicks() .onEach { showCoverOptionsDialog() @@ -286,17 +285,7 @@ class MangaInfoHeaderAdapter( // Set cover if changed. binding.backdrop.loadAnyAutoPause(manga) - binding.mangaCover.loadAnyAutoPause(manga) { - listener( - onSuccess = { request, _ -> - (request.target as? ImageViewTarget)?.drawable?.let { drawable -> - val ratio = drawable.minimumWidth / drawable.minimumHeight.toFloat() - binding.root.getConstraintSet(R.id.end) - ?.setDimensionRatio(R.id.manga_cover, ratio.toString()) - } - } - ) - } + binding.mangaCover.loadAnyAutoPause(manga) // Manga info section val hasInfoContent = !manga.description.isNullOrBlank() || !manga.genre.isNullOrBlank() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackSearchDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackSearchDialog.kt index e365911ea5..00f8f6e7a7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackSearchDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackSearchDialog.kt @@ -7,7 +7,6 @@ import android.view.LayoutInflater import android.view.View import android.view.inputmethod.EditorInfo import android.view.inputmethod.InputMethodManager -import androidx.appcompat.app.AppCompatDialog import androidx.core.content.getSystemService import androidx.core.os.bundleOf import androidx.core.view.WindowCompat @@ -21,6 +20,7 @@ import eu.kanade.tachiyomi.databinding.TrackSearchDialogBinding import eu.kanade.tachiyomi.ui.base.controller.DialogController import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.util.view.setNavigationBarTransparentCompat +import eu.kanade.tachiyomi.widget.TachiyomiFullscreenDialog import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -142,9 +142,7 @@ class TrackSearchDialog : DialogController { } } - return AppCompatDialog(activity!!, R.style.ThemeOverlay_Tachiyomi_Dialog_Fullscreen).apply { - setContentView(binding!!.root) - } + return TachiyomiFullscreenDialog(activity!!, binding!!.root) } override fun onAttach(view: View) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/TachiyomiFullscreenDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/TachiyomiFullscreenDialog.kt new file mode 100644 index 0000000000..1dea274e7f --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/TachiyomiFullscreenDialog.kt @@ -0,0 +1,13 @@ +package eu.kanade.tachiyomi.widget + +import android.content.Context +import android.view.View +import androidx.appcompat.app.AppCompatDialog +import eu.kanade.tachiyomi.R + +class TachiyomiFullscreenDialog(context: Context, view: View) : AppCompatDialog(context, R.style.ThemeOverlay_Tachiyomi_Dialog_Fullscreen) { + + init { + setContentView(view) + } +} diff --git a/app/src/main/res/drawable/ic_save_24dp.xml b/app/src/main/res/drawable/ic_save_24dp.xml new file mode 100644 index 0000000000..1a8d86d20c --- /dev/null +++ b/app/src/main/res/drawable/ic_save_24dp.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout-sw720dp/manga_info_header.xml b/app/src/main/res/layout-sw720dp/manga_info_header.xml index f0b381ba9a..782d0086a2 100644 --- a/app/src/main/res/layout-sw720dp/manga_info_header.xml +++ b/app/src/main/res/layout-sw720dp/manga_info_header.xml @@ -1,11 +1,10 @@ - - + diff --git a/app/src/main/res/layout/manga_full_cover_dialog.xml b/app/src/main/res/layout/manga_full_cover_dialog.xml new file mode 100644 index 0000000000..ce0f181e9f --- /dev/null +++ b/app/src/main/res/layout/manga_full_cover_dialog.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/manga_info_header.xml b/app/src/main/res/layout/manga_info_header.xml index 4ac271701d..c37060b1b8 100644 --- a/app/src/main/res/layout/manga_info_header.xml +++ b/app/src/main/res/layout/manga_info_header.xml @@ -1,11 +1,10 @@ - + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/manga_actions" + app:layoutDescription="@xml/manga_summary_section_scene"> - + diff --git a/app/src/main/res/menu/full_cover.xml b/app/src/main/res/menu/full_cover.xml new file mode 100644 index 0000000000..5b339e706a --- /dev/null +++ b/app/src/main/res/menu/full_cover.xml @@ -0,0 +1,24 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/manga.xml b/app/src/main/res/menu/manga.xml index 4cec21edaf..b1227e72c0 100644 --- a/app/src/main/res/menu/manga.xml +++ b/app/src/main/res/menu/manga.xml @@ -37,23 +37,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/xml/manga_info_header_scene_sw720dp.xml b/app/src/main/res/xml/manga_info_header_scene_sw720dp.xml deleted file mode 100644 index 691b683030..0000000000 --- a/app/src/main/res/xml/manga_info_header_scene_sw720dp.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - -