瀏覽代碼

Collapsable manga summary/genre section

arkon 5 年之前
父節點
當前提交
df69559b39

+ 6 - 6
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<Boolean> = 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

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersController.kt

@@ -269,7 +269,7 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
 
     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()
         }
     }

+ 76 - 23
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<MangaInfoPresenter>(),
-        ChangeMangaCategoriesDialog.Listener {
+class MangaInfoController(private val fromSource: Boolean = false) :
+    NucleusController<MangaInfoPresenter>(),
+    ChangeMangaCategoriesDialog.Listener {
 
     private val preferences: PreferencesHelper by injectLazy()
 
@@ -241,27 +245,6 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
             }
         }
 
-        // 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<MangaInfoPresenter>(),
                         .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()
     }
 
     /**

+ 4 - 0
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.
  *

+ 21 - 2
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" />
 
+            <Button
+                android:id="@+id/manga_info_toggle"
+                style="@style/Theme.Widget.Button"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_margin="4dp"
+                android:text="@string/manga_info_expand"
+                android:textSize="12sp"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toBottomOf="@id/manga_genres_tags" />
+
         </androidx.constraintlayout.widget.ConstraintLayout>
 
     </androidx.core.widget.NestedScrollView>

+ 3 - 0
app/src/main/res/values/strings.xml

@@ -418,6 +418,9 @@
     <string name="manga_info_status_label">Status</string>
     <string name="manga_info_source_label">Source</string>
     <string name="manga_info_genres_label">Genres</string>
+    <string name="manga_info_about_label">About</string>
+    <string name="manga_info_expand">Show more info</string>
+    <string name="manga_info_collapse">Show less info</string>
     <string name="circular_icon">Circular</string>
     <string name="rounded_icon">Rounded</string>
     <string name="square_icon">Square</string>