From df69559b39244ad18a75f99fff209d9f6d6d4b08 Mon Sep 17 00:00:00 2001 From: arkon Date: Sat, 18 Apr 2020 12:40:47 -0400 Subject: [PATCH] Collapsable manga summary/genre section --- .../tachiyomi/ui/manga/MangaController.kt | 12 +-- .../ui/manga/chapter/ChaptersController.kt | 2 +- .../ui/manga/info/MangaInfoController.kt | 99 ++++++++++++++----- .../tachiyomi/util/view/ViewExtensions.kt | 4 + .../main/res/layout/manga_info_controller.xml | 23 ++++- app/src/main/res/values/strings.xml | 3 + 6 files changed, 111 insertions(+), 32 deletions(-) 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 fa68cd31b8..fa6e404392 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 @@ -35,9 +35,9 @@ import uy.kohesive.injekt.api.get class MangaController : RxController, TabbedController { - constructor(manga: Manga?, fromCatalogue: Boolean = false) : super(Bundle().apply { + constructor(manga: Manga?, fromSource: Boolean = false) : super(Bundle().apply { putLong(MANGA_EXTRA, manga?.id ?: 0) - putBoolean(FROM_CATALOGUE_EXTRA, fromCatalogue) + putBoolean(FROM_SOURCE_EXTRA, fromSource) }) { this.manga = manga if (manga != null) { @@ -59,7 +59,7 @@ class MangaController : RxController, TabbedController { private var adapter: MangaDetailAdapter? = null - val fromCatalogue = args.getBoolean(FROM_CATALOGUE_EXTRA, false) + val fromSource = args.getBoolean(FROM_SOURCE_EXTRA, false) val mangaFavoriteRelay: PublishRelay = PublishRelay.create() @@ -89,7 +89,7 @@ class MangaController : RxController, TabbedController { binding.mangaPager.offscreenPageLimit = 3 binding.mangaPager.adapter = adapter - if (!fromCatalogue) + if (!fromSource) binding.mangaPager.currentItem = CHAPTERS_CONTROLLER } @@ -156,7 +156,7 @@ class MangaController : RxController, TabbedController { override fun configureRouter(router: Router, position: Int) { if (!router.hasRootController()) { val controller = when (position) { - INFO_CONTROLLER -> MangaInfoController() + INFO_CONTROLLER -> MangaInfoController(fromSource) CHAPTERS_CONTROLLER -> ChaptersController() TRACK_CONTROLLER -> TrackController() else -> error("Wrong position $position") @@ -171,7 +171,7 @@ class MangaController : RxController, TabbedController { } companion object { - const val FROM_CATALOGUE_EXTRA = "from_catalogue" + const val FROM_SOURCE_EXTRA = "from_source" const val MANGA_EXTRA = "manga" const val INFO_CONTROLLER = 0 diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersController.kt index e4b1f37d83..9d4f8822b3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersController.kt @@ -269,7 +269,7 @@ class ChaptersController : NucleusController(), private fun initialFetchChapters() { // Only fetch if this view is from the catalog and it hasn't requested previously - if ((parentController as MangaController).fromCatalogue && !presenter.hasRequested) { + if ((parentController as MangaController).fromSource && !presenter.hasRequested) { fetchChaptersFromSource() } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoController.kt index cc8a2147f4..6134c1e077 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoController.kt @@ -10,6 +10,7 @@ import android.graphics.Bitmap import android.graphics.drawable.Drawable import android.os.Build import android.os.Bundle +import android.text.TextUtils import android.view.LayoutInflater import android.view.Menu import android.view.MenuInflater @@ -51,7 +52,9 @@ import eu.kanade.tachiyomi.ui.webview.WebViewActivity import eu.kanade.tachiyomi.util.lang.launchInUI import eu.kanade.tachiyomi.util.lang.truncateCenter import eu.kanade.tachiyomi.util.system.toast +import eu.kanade.tachiyomi.util.view.gone import eu.kanade.tachiyomi.util.view.snack +import eu.kanade.tachiyomi.util.view.toggle import eu.kanade.tachiyomi.util.view.visible import jp.wasabeef.glide.transformations.CropSquareTransformation import kotlinx.coroutines.flow.onEach @@ -67,8 +70,9 @@ import uy.kohesive.injekt.injectLazy * Uses R.layout.manga_info_controller. * UI related actions should be called from here. */ -class MangaInfoController : NucleusController(), - ChangeMangaCategoriesDialog.Listener { +class MangaInfoController(private val fromSource: Boolean = false) : + NucleusController(), + ChangeMangaCategoriesDialog.Listener { private val preferences: PreferencesHelper by injectLazy() @@ -241,27 +245,6 @@ class MangaInfoController : NucleusController(), } } - // Update genres list - if (!manga.genre.isNullOrBlank()) { - binding.mangaGenresTags.removeAllViews() - - manga.getGenres()?.forEach { genre -> - val chip = Chip(view.context).apply { - text = genre - setOnClickListener { performSearch(genre) } - } - - binding.mangaGenresTags.addView(chip) - } - } - - // Update description TextView. - binding.mangaSummary.text = if (manga.description.isNullOrBlank()) { - view.context.getString(R.string.unknown) - } else { - manga.description - } - // Update status TextView. binding.mangaStatus.setText(when (manga.status) { SManga.ONGOING -> R.string.ongoing @@ -289,6 +272,76 @@ class MangaInfoController : NucleusController(), .into(binding.backdrop!!) } } + + // Manga info section + if (manga.description.isNullOrBlank() && manga.genre.isNullOrBlank()) { + hideMangaInfo() + } else { + // Update description TextView. + binding.mangaSummary.text = if (manga.description.isNullOrBlank()) { + view.context.getString(R.string.unknown) + } else { + manga.description + } + + // Update genres list + if (!manga.genre.isNullOrBlank()) { + binding.mangaGenresTags.removeAllViews() + + manga.getGenres()?.forEach { genre -> + val chip = Chip(view.context).apply { + text = genre + setOnClickListener { performSearch(genre) } + } + + binding.mangaGenresTags.addView(chip) + } + } + + // Handle showing more or less info + binding.mangaSummary.clicks() + .onEach { toggleMangaInfo(view.context) } + .launchInUI() + binding.mangaInfoToggle.clicks() + .onEach { toggleMangaInfo(view.context) } + .launchInUI() + + // Expand manga info if navigated from source listing + if (fromSource) { + toggleMangaInfo(view.context) + } + } + } + + private fun hideMangaInfo() { + binding.mangaSummaryLabel.gone() + binding.mangaSummary.gone() + binding.mangaGenresTags.gone() + binding.mangaInfoToggle.gone() + } + + private fun toggleMangaInfo(context: Context) { + binding.mangaInfoToggle.text = + if (binding.mangaInfoToggle.text == context.getString(R.string.manga_info_expand)) + context.getString(R.string.manga_info_collapse) + else + context.getString(R.string.manga_info_expand) + + with(binding.mangaSummary) { + maxLines = + if (maxLines == Int.MAX_VALUE) + 3 + else + Int.MAX_VALUE + + ellipsize = + if (ellipsize == TextUtils.TruncateAt.END) + null + else + TextUtils.TruncateAt.END + } + + binding.mangaGenresTags.toggle() } /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewExtensions.kt index 41bbfa24f4..f3102d49ef 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewExtensions.kt @@ -80,6 +80,10 @@ inline fun View.visibleIf(block: () -> Boolean) { visibility = if (block()) View.VISIBLE else View.GONE } +inline fun View.toggle() { + visibleIf { visibility == View.GONE } +} + /** * Sets a round TextDrawable into an ImageView determined by input. * diff --git a/app/src/main/res/layout/manga_info_controller.xml b/app/src/main/res/layout/manga_info_controller.xml index c612d94ef0..957b66949a 100644 --- a/app/src/main/res/layout/manga_info_controller.xml +++ b/app/src/main/res/layout/manga_info_controller.xml @@ -80,6 +80,7 @@ style="@style/TextAppearance.Medium.Title" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:paddingBottom="8dp" android:maxLines="2" android:text="@string/manga_info_full_title_label" android:textIsSelectable="false" @@ -190,7 +191,9 @@ android:layout_height="wrap_content" android:orientation="horizontal" android:paddingStart="16dp" + android:paddingTop="8dp" android:paddingEnd="16dp" + android:paddingBottom="8dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/guideline"> @@ -242,9 +245,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="16dp" - android:layout_marginTop="8dp" android:layout_marginEnd="16dp" - android:text="@string/pref_category_about" + android:text="@string/manga_info_about_label" android:textIsSelectable="false" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -257,6 +259,10 @@ android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginEnd="16dp" + android:clickable="true" + android:ellipsize="end" + android:focusable="true" + android:maxLines="3" android:textIsSelectable="false" app:layout_constraintBottom_toTopOf="@id/manga_genres_tags" app:layout_constraintEnd_toEndOf="parent" @@ -271,12 +277,25 @@ android:layout_marginTop="8dp" android:layout_marginEnd="16dp" android:layout_marginBottom="8dp" + android:visibility="gone" app:chipSpacingHorizontal="4dp" app:layout_constrainedHeight="true" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/manga_summary" /> +