Collapsable manga summary/genre section

This commit is contained in:
arkon 2020-04-18 12:40:47 -04:00
parent e388f0d563
commit df69559b39
6 changed files with 111 additions and 32 deletions

View File

@ -35,9 +35,9 @@ import uy.kohesive.injekt.api.get
class MangaController : RxController, TabbedController { 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) putLong(MANGA_EXTRA, manga?.id ?: 0)
putBoolean(FROM_CATALOGUE_EXTRA, fromCatalogue) putBoolean(FROM_SOURCE_EXTRA, fromSource)
}) { }) {
this.manga = manga this.manga = manga
if (manga != null) { if (manga != null) {
@ -59,7 +59,7 @@ class MangaController : RxController, TabbedController {
private var adapter: MangaDetailAdapter? = null 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() val mangaFavoriteRelay: PublishRelay<Boolean> = PublishRelay.create()
@ -89,7 +89,7 @@ class MangaController : RxController, TabbedController {
binding.mangaPager.offscreenPageLimit = 3 binding.mangaPager.offscreenPageLimit = 3
binding.mangaPager.adapter = adapter binding.mangaPager.adapter = adapter
if (!fromCatalogue) if (!fromSource)
binding.mangaPager.currentItem = CHAPTERS_CONTROLLER binding.mangaPager.currentItem = CHAPTERS_CONTROLLER
} }
@ -156,7 +156,7 @@ class MangaController : RxController, TabbedController {
override fun configureRouter(router: Router, position: Int) { override fun configureRouter(router: Router, position: Int) {
if (!router.hasRootController()) { if (!router.hasRootController()) {
val controller = when (position) { val controller = when (position) {
INFO_CONTROLLER -> MangaInfoController() INFO_CONTROLLER -> MangaInfoController(fromSource)
CHAPTERS_CONTROLLER -> ChaptersController() CHAPTERS_CONTROLLER -> ChaptersController()
TRACK_CONTROLLER -> TrackController() TRACK_CONTROLLER -> TrackController()
else -> error("Wrong position $position") else -> error("Wrong position $position")
@ -171,7 +171,7 @@ class MangaController : RxController, TabbedController {
} }
companion object { companion object {
const val FROM_CATALOGUE_EXTRA = "from_catalogue" const val FROM_SOURCE_EXTRA = "from_source"
const val MANGA_EXTRA = "manga" const val MANGA_EXTRA = "manga"
const val INFO_CONTROLLER = 0 const val INFO_CONTROLLER = 0

View File

@ -269,7 +269,7 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
private fun initialFetchChapters() { private fun initialFetchChapters() {
// Only fetch if this view is from the catalog and it hasn't requested previously // 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() fetchChaptersFromSource()
} }
} }

View File

@ -10,6 +10,7 @@ import android.graphics.Bitmap
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.text.TextUtils
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.Menu import android.view.Menu
import android.view.MenuInflater 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.launchInUI
import eu.kanade.tachiyomi.util.lang.truncateCenter import eu.kanade.tachiyomi.util.lang.truncateCenter
import eu.kanade.tachiyomi.util.system.toast 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.snack
import eu.kanade.tachiyomi.util.view.toggle
import eu.kanade.tachiyomi.util.view.visible import eu.kanade.tachiyomi.util.view.visible
import jp.wasabeef.glide.transformations.CropSquareTransformation import jp.wasabeef.glide.transformations.CropSquareTransformation
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
@ -67,8 +70,9 @@ import uy.kohesive.injekt.injectLazy
* Uses R.layout.manga_info_controller. * Uses R.layout.manga_info_controller.
* UI related actions should be called from here. * UI related actions should be called from here.
*/ */
class MangaInfoController : NucleusController<MangaInfoPresenter>(), class MangaInfoController(private val fromSource: Boolean = false) :
ChangeMangaCategoriesDialog.Listener { NucleusController<MangaInfoPresenter>(),
ChangeMangaCategoriesDialog.Listener {
private val preferences: PreferencesHelper by injectLazy() 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. // Update status TextView.
binding.mangaStatus.setText(when (manga.status) { binding.mangaStatus.setText(when (manga.status) {
SManga.ONGOING -> R.string.ongoing SManga.ONGOING -> R.string.ongoing
@ -289,6 +272,76 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
.into(binding.backdrop!!) .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()
} }
/** /**

View File

@ -80,6 +80,10 @@ inline fun View.visibleIf(block: () -> Boolean) {
visibility = if (block()) View.VISIBLE else View.GONE 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. * Sets a round TextDrawable into an ImageView determined by input.
* *

View File

@ -80,6 +80,7 @@
style="@style/TextAppearance.Medium.Title" style="@style/TextAppearance.Medium.Title"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingBottom="8dp"
android:maxLines="2" android:maxLines="2"
android:text="@string/manga_info_full_title_label" android:text="@string/manga_info_full_title_label"
android:textIsSelectable="false" android:textIsSelectable="false"
@ -190,7 +191,9 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
android:paddingStart="16dp" android:paddingStart="16dp"
android:paddingTop="8dp"
android:paddingEnd="16dp" android:paddingEnd="16dp"
android:paddingBottom="8dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/guideline"> app:layout_constraintTop_toBottomOf="@id/guideline">
@ -242,9 +245,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:text="@string/pref_category_about" android:text="@string/manga_info_about_label"
android:textIsSelectable="false" android:textIsSelectable="false"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@ -257,6 +259,10 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:clickable="true"
android:ellipsize="end"
android:focusable="true"
android:maxLines="3"
android:textIsSelectable="false" android:textIsSelectable="false"
app:layout_constraintBottom_toTopOf="@id/manga_genres_tags" app:layout_constraintBottom_toTopOf="@id/manga_genres_tags"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
@ -271,12 +277,25 @@
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:visibility="gone"
app:chipSpacingHorizontal="4dp" app:chipSpacingHorizontal="4dp"
app:layout_constrainedHeight="true" app:layout_constrainedHeight="true"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/manga_summary" /> 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.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>

View File

@ -418,6 +418,9 @@
<string name="manga_info_status_label">Status</string> <string name="manga_info_status_label">Status</string>
<string name="manga_info_source_label">Source</string> <string name="manga_info_source_label">Source</string>
<string name="manga_info_genres_label">Genres</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="circular_icon">Circular</string>
<string name="rounded_icon">Rounded</string> <string name="rounded_icon">Rounded</string>
<string name="square_icon">Square</string> <string name="square_icon">Square</string>