mirror of
https://github.com/mihonapp/mihon.git
synced 2025-06-26 19:17:51 +02:00
Totally rewrote the all in one manga page, now is a recycler header
It works perfect, there is no lag it all
This commit is contained in:
@ -0,0 +1,81 @@
|
||||
package eu.kanade.tachiyomi.ui.manga
|
||||
|
||||
import android.content.Context
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Category
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.MangaAllInOneChapterItem
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import java.text.DateFormat
|
||||
import java.text.DecimalFormat
|
||||
import java.text.DecimalFormatSymbols
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
class MangaAllInOneAdapter(
|
||||
controller: MangaAllInOneController,
|
||||
context: Context
|
||||
) : FlexibleAdapter<IFlexible<*>>(null, controller, true) {
|
||||
|
||||
val delegate: MangaAllInOneInterface = controller
|
||||
|
||||
val preferences: PreferencesHelper by injectLazy()
|
||||
|
||||
var items: List<MangaAllInOneChapterItem> = emptyList()
|
||||
|
||||
val readColor = context.getResourceColor(R.attr.colorOnSurface, 0.38f)
|
||||
val unreadColor = context.getResourceColor(R.attr.colorOnSurface)
|
||||
|
||||
val bookmarkedColor = context.getResourceColor(R.attr.colorAccent)
|
||||
|
||||
val decimalFormat = DecimalFormat(
|
||||
"#.###",
|
||||
DecimalFormatSymbols()
|
||||
.apply { decimalSeparator = '.' }
|
||||
)
|
||||
|
||||
val dateFormat: DateFormat = preferences.dateFormat()
|
||||
|
||||
override fun updateDataSet(items: List<IFlexible<*>>?) {
|
||||
this.items = items as List<MangaAllInOneChapterItem>? ?: emptyList()
|
||||
super.updateDataSet(items)
|
||||
}
|
||||
|
||||
fun indexOf(item: MangaAllInOneChapterItem): Int {
|
||||
return items.indexOf(item)
|
||||
}
|
||||
|
||||
interface MangaAllInOneInterface : MangaHeaderInterface
|
||||
|
||||
interface MangaHeaderInterface {
|
||||
fun openSmartSearch()
|
||||
fun mangaPresenter(): MangaAllInOnePresenter
|
||||
fun openRecommends()
|
||||
fun onNextManga(manga: Manga, source: Source, chapters: List<MangaAllInOneChapterItem>)
|
||||
fun setMangaInfo(manga: Manga, source: Source?, chapters: List<MangaAllInOneChapterItem>)
|
||||
fun openInWebView()
|
||||
fun shareManga()
|
||||
fun fetchMangaFromSource(manualFetch: Boolean = false, fetchManga: Boolean = true, fetchChapters: Boolean = true)
|
||||
fun onFetchMangaDone()
|
||||
fun onFetchMangaError(error: Throwable)
|
||||
fun setRefreshing(value: Boolean)
|
||||
fun onFavoriteClick()
|
||||
fun onCategoriesClick()
|
||||
fun updateCategoriesForMangas(mangas: List<Manga>, categories: List<Category>)
|
||||
fun performGlobalSearch(query: String)
|
||||
fun wrapTag(namespace: String, tag: String): String
|
||||
fun isEHentaiBasedSource(): Boolean
|
||||
fun performSearch(query: String)
|
||||
fun openTracking()
|
||||
suspend fun mergeWithAnother()
|
||||
fun copyToClipboard(label: String, text: String)
|
||||
fun migrateManga()
|
||||
fun isInitialLoadAndFromSource(): Boolean
|
||||
fun removeInitialLoad()
|
||||
val controllerScope: CoroutineScope
|
||||
}
|
||||
}
|
@ -3,10 +3,8 @@ package eu.kanade.tachiyomi.ui.manga
|
||||
import android.animation.Animator
|
||||
import android.animation.AnimatorListenerAdapter
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
@ -15,11 +13,9 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.view.ActionMode
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
import androidx.recyclerview.widget.DividerItemDecoration
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.gson.Gson
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
@ -30,16 +26,11 @@ import eu.kanade.tachiyomi.data.database.models.Category
|
||||
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import eu.kanade.tachiyomi.data.glide.GlideApp
|
||||
import eu.kanade.tachiyomi.data.glide.toMangaThumbnail
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.databinding.MangaAllInOneControllerBinding
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.tachiyomi.source.online.all.MergedSource
|
||||
import eu.kanade.tachiyomi.ui.base.controller.NucleusController
|
||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||
import eu.kanade.tachiyomi.ui.browse.source.SourceController
|
||||
@ -49,12 +40,11 @@ import eu.kanade.tachiyomi.ui.library.ChangeMangaCategoriesDialog
|
||||
import eu.kanade.tachiyomi.ui.library.LibraryController
|
||||
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||
import eu.kanade.tachiyomi.ui.main.offsetAppbarHeight
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterHolder
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersAdapter
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersPresenter
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.DeleteChaptersDialog
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.DownloadCustomChaptersDialog
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.MangaAllInOneChapterHolder
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.MangaAllInOneChapterItem
|
||||
import eu.kanade.tachiyomi.ui.manga.track.TrackController
|
||||
import eu.kanade.tachiyomi.ui.migration.manga.design.PreMigrationController
|
||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
||||
@ -69,13 +59,9 @@ import eu.kanade.tachiyomi.util.view.gone
|
||||
import eu.kanade.tachiyomi.util.view.shrinkOnScroll
|
||||
import eu.kanade.tachiyomi.util.view.snack
|
||||
import eu.kanade.tachiyomi.util.view.visible
|
||||
import eu.kanade.tachiyomi.util.view.visibleIf
|
||||
import exh.EH_SOURCE_ID
|
||||
import exh.EXH_SOURCE_ID
|
||||
import exh.MERGED_SOURCE_ID
|
||||
import exh.util.setChipsExtended
|
||||
import java.text.DateFormat
|
||||
import java.text.DecimalFormat
|
||||
import java.util.Date
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlinx.coroutines.CancellationException
|
||||
@ -86,11 +72,8 @@ import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.NonCancellable
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import reactivecircus.flowbinding.android.view.clicks
|
||||
import reactivecircus.flowbinding.android.view.longClicks
|
||||
import reactivecircus.flowbinding.swiperefreshlayout.refreshes
|
||||
import timber.log.Timber
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
@ -110,7 +93,8 @@ class MangaAllInOneController :
|
||||
FlexibleAdapter.OnItemClickListener,
|
||||
FlexibleAdapter.OnItemLongClickListener,
|
||||
DownloadCustomChaptersDialog.Listener,
|
||||
DeleteChaptersDialog.Listener {
|
||||
DeleteChaptersDialog.Listener,
|
||||
MangaAllInOneAdapter.MangaAllInOneInterface {
|
||||
|
||||
constructor(manga: Manga?, fromSource: Boolean = false, smartSearchConfig: SourceController.SmartSearchConfig? = null, update: Boolean = false) : super(
|
||||
Bundle().apply {
|
||||
@ -158,7 +142,7 @@ class MangaAllInOneController :
|
||||
/**
|
||||
* Adapter containing a list of chapters.
|
||||
*/
|
||||
private var adapter: ChaptersAdapter? = null
|
||||
private var adapter: MangaAllInOneAdapter? = null
|
||||
|
||||
/**
|
||||
* Action mode for multiple selection.
|
||||
@ -168,7 +152,7 @@ class MangaAllInOneController :
|
||||
/**
|
||||
* Selected items. Used to restore selections after a rotation.
|
||||
*/
|
||||
private val selectedItems = mutableSetOf<ChapterItem>()
|
||||
private val selectedItems = mutableSetOf<MangaAllInOneChapterItem>()
|
||||
|
||||
private var lastClickPosition = -1
|
||||
|
||||
@ -192,6 +176,8 @@ class MangaAllInOneController :
|
||||
|
||||
var update = args.getBoolean(UPDATE_EXTRA, false)
|
||||
|
||||
override val controllerScope = scope
|
||||
|
||||
init {
|
||||
setHasOptionsMenu(true)
|
||||
}
|
||||
@ -214,178 +200,10 @@ class MangaAllInOneController :
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
// Setting this via XML doesn't work
|
||||
binding.mangaCover.clipToOutline = true
|
||||
|
||||
binding.btnFavorite.clicks()
|
||||
.onEach { onFavoriteClick() }
|
||||
.launchIn(scope)
|
||||
|
||||
if ((Injekt.get<TrackManager>().hasLoggedServices()) && presenter.manga.favorite) {
|
||||
binding.btnTracking.visible()
|
||||
}
|
||||
|
||||
scope.launch(Dispatchers.IO) {
|
||||
if (Injekt.get<DatabaseHelper>().getTracks(presenter.manga).executeAsBlocking().any {
|
||||
val status = Injekt.get<TrackManager>().getService(it.sync_id)?.getStatus(it.status)
|
||||
status != null
|
||||
}
|
||||
) {
|
||||
withContext(Dispatchers.Main) {
|
||||
binding.btnTracking.icon = resources!!.getDrawable(R.drawable.ic_cloud_white_24dp, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.btnTracking.clicks()
|
||||
.onEach { openTracking() }
|
||||
.launchIn(scope)
|
||||
|
||||
if (presenter.manga.favorite && presenter.getCategories().isNotEmpty()) {
|
||||
binding.btnCategories.visible()
|
||||
}
|
||||
binding.btnCategories.clicks()
|
||||
.onEach { onCategoriesClick() }
|
||||
.launchIn(scope)
|
||||
|
||||
if (presenter.source is HttpSource) {
|
||||
binding.btnWebview.visible()
|
||||
binding.btnShare.visible()
|
||||
|
||||
binding.btnWebview.clicks()
|
||||
.onEach { openInWebView() }
|
||||
.launchIn(scope)
|
||||
binding.btnShare.clicks()
|
||||
.onEach { shareManga() }
|
||||
.launchIn(scope)
|
||||
}
|
||||
|
||||
if (presenter.manga.favorite) {
|
||||
binding.btnMigrate.visible()
|
||||
binding.btnSmartSearch.visible()
|
||||
}
|
||||
|
||||
binding.btnMigrate.clicks()
|
||||
.onEach {
|
||||
PreMigrationController.navigateToMigration(
|
||||
preferences.skipPreMigration().get(),
|
||||
router,
|
||||
listOf(presenter.manga.id!!)
|
||||
)
|
||||
}
|
||||
.launchIn(scope)
|
||||
|
||||
binding.btnSmartSearch.clicks()
|
||||
.onEach { openSmartSearch() }
|
||||
.launchIn(scope)
|
||||
|
||||
// Set SwipeRefresh to refresh manga data.
|
||||
binding.swipeRefresh.refreshes()
|
||||
.onEach { fetchMangaFromSource(manualFetch = true) }
|
||||
.launchIn(scope)
|
||||
|
||||
binding.mangaFullTitle.longClicks()
|
||||
.onEach {
|
||||
activity?.copyToClipboard(view.context.getString(R.string.title), binding.mangaFullTitle.text.toString())
|
||||
}
|
||||
.launchIn(scope)
|
||||
|
||||
binding.mangaFullTitle.clicks()
|
||||
.onEach {
|
||||
performGlobalSearch(binding.mangaFullTitle.text.toString())
|
||||
}
|
||||
.launchIn(scope)
|
||||
|
||||
binding.mangaArtist.longClicks()
|
||||
.onEach {
|
||||
activity?.copyToClipboard(binding.mangaArtistLabel.text.toString(), binding.mangaArtist.text.toString())
|
||||
}
|
||||
.launchIn(scope)
|
||||
|
||||
binding.mangaArtist.clicks()
|
||||
.onEach {
|
||||
var text = binding.mangaArtist.text.toString()
|
||||
if (isEHentaiBasedSource()) {
|
||||
text = wrapTag("artist", text)
|
||||
}
|
||||
performGlobalSearch(text)
|
||||
}
|
||||
.launchIn(scope)
|
||||
|
||||
binding.mangaAuthor.longClicks()
|
||||
.onEach {
|
||||
// EXH Special case E-Hentai/ExHentai to ignore author field (unused)
|
||||
if (!isEHentaiBasedSource()) {
|
||||
activity?.copyToClipboard(binding.mangaAuthor.text.toString(), binding.mangaAuthor.text.toString())
|
||||
}
|
||||
}
|
||||
.launchIn(scope)
|
||||
|
||||
binding.mangaAuthor.clicks()
|
||||
.onEach {
|
||||
// EXH Special case E-Hentai/ExHentai to ignore author field (unused)
|
||||
if (!isEHentaiBasedSource()) {
|
||||
performGlobalSearch(binding.mangaAuthor.text.toString())
|
||||
}
|
||||
}
|
||||
.launchIn(scope)
|
||||
|
||||
binding.mangaSummary.longClicks()
|
||||
.onEach {
|
||||
activity?.copyToClipboard(view.context.getString(R.string.description), binding.mangaSummary.text.toString())
|
||||
}
|
||||
.launchIn(scope)
|
||||
|
||||
binding.mangaCover.longClicks()
|
||||
.onEach {
|
||||
activity?.copyToClipboard(view.context.getString(R.string.title), presenter.manga.title)
|
||||
}
|
||||
.launchIn(scope)
|
||||
|
||||
// EXH -->
|
||||
if (smartSearchConfig == null) {
|
||||
binding.recommendBtn.visible()
|
||||
binding.recommendBtn.clicks()
|
||||
.onEach { openRecommends() }
|
||||
.launchIn(scope)
|
||||
}
|
||||
smartSearchConfig?.let { smartSearchConfig ->
|
||||
if (smartSearchConfig.origMangaId != null) { binding.mergeBtn.visible() }
|
||||
binding.mergeBtn.clicks()
|
||||
.onEach {
|
||||
// Init presenter here to avoid threading issues
|
||||
presenter
|
||||
|
||||
launch {
|
||||
try {
|
||||
val mergedManga = withContext(Dispatchers.IO + NonCancellable) {
|
||||
presenter.smartSearchMerge(presenter.manga, smartSearchConfig.origMangaId!!)
|
||||
}
|
||||
|
||||
router?.pushController(
|
||||
MangaAllInOneController(
|
||||
mergedManga,
|
||||
true,
|
||||
update = true
|
||||
).withFadeTransaction()
|
||||
)
|
||||
applicationContext?.toast("Manga merged!")
|
||||
} catch (e: Exception) {
|
||||
if (e is CancellationException) throw e
|
||||
else {
|
||||
applicationContext?.toast("Failed to merge manga: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.launchIn(scope)
|
||||
}
|
||||
// EXH <--
|
||||
|
||||
if (manga == null || source == null) return
|
||||
|
||||
// Init RecyclerView and adapter
|
||||
adapter = ChaptersAdapter(this, view.context)
|
||||
adapter = MangaAllInOneAdapter(this, view.context)
|
||||
|
||||
binding.recycler.adapter = adapter
|
||||
binding.recycler.layoutManager = LinearLayoutManager(view.context)
|
||||
@ -421,8 +239,28 @@ class MangaAllInOneController :
|
||||
binding.fab.offsetAppbarHeight(activity!!)
|
||||
}
|
||||
|
||||
private fun getHeader(): MangaAllInOneHolder? {
|
||||
return binding.recycler.findViewHolderForAdapterPosition(0) as? MangaAllInOneHolder
|
||||
}
|
||||
|
||||
private fun addMangaHeader() {
|
||||
if (adapter?.scrollableHeaders?.isEmpty() == true) {
|
||||
adapter?.removeAllScrollableHeaders()
|
||||
adapter?.addScrollableHeader(presenter.headerItem)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateHeader() {
|
||||
// binding.swipeRefresh?.isRefreshing = presenter.isLoading
|
||||
adapter?.updateDataSet(presenter.chapters)
|
||||
addMangaHeader()
|
||||
activity?.invalidateOptionsMenu()
|
||||
}
|
||||
|
||||
fun refreshAdapter() = adapter?.notifyDataSetChanged()
|
||||
|
||||
// EXH -->
|
||||
private fun openSmartSearch() {
|
||||
override fun openSmartSearch() {
|
||||
val smartSearchConfig = SourceController.SmartSearchConfig(presenter.manga.title, presenter.manga.id!!)
|
||||
|
||||
router?.pushController(
|
||||
@ -433,10 +271,48 @@ class MangaAllInOneController :
|
||||
).withFadeTransaction()
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun mergeWithAnother() {
|
||||
try {
|
||||
val mergedManga = withContext(Dispatchers.IO + NonCancellable) {
|
||||
presenter.smartSearchMerge(presenter.manga, smartSearchConfig?.origMangaId!!)
|
||||
}
|
||||
|
||||
router?.pushController(
|
||||
MangaAllInOneController(
|
||||
mergedManga,
|
||||
true,
|
||||
update = true
|
||||
).withFadeTransaction()
|
||||
)
|
||||
applicationContext?.toast("Manga merged!")
|
||||
} catch (e: Exception) {
|
||||
if (e is CancellationException) throw e
|
||||
else {
|
||||
applicationContext?.toast("Failed to merge manga: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun copyToClipboard(label: String, text: String) {
|
||||
activity!!.copyToClipboard(label, text)
|
||||
}
|
||||
|
||||
override fun migrateManga() {
|
||||
PreMigrationController.navigateToMigration(
|
||||
preferences.skipPreMigration().get(),
|
||||
router,
|
||||
listOf(presenter.manga.id!!)
|
||||
)
|
||||
}
|
||||
|
||||
override fun mangaPresenter(): MangaAllInOnePresenter {
|
||||
return presenter
|
||||
}
|
||||
// EXH <--
|
||||
|
||||
// AZ -->
|
||||
private fun openRecommends() {
|
||||
override fun openRecommends() {
|
||||
val recommendsConfig = BrowseSourceController.RecommendsConfig(presenter.manga)
|
||||
|
||||
router?.pushController(
|
||||
@ -449,7 +325,7 @@ class MangaAllInOneController :
|
||||
}
|
||||
// AZ <--
|
||||
|
||||
private fun openTracking() {
|
||||
override fun openTracking() {
|
||||
router?.pushController(
|
||||
TrackController(fromAllInOne = true, manga = manga).withFadeTransaction()
|
||||
)
|
||||
@ -463,7 +339,7 @@ class MangaAllInOneController :
|
||||
* @param manga manga object containing information about manga.
|
||||
* @param source the source of the manga.
|
||||
*/
|
||||
fun onNextManga(manga: Manga, source: Source, chapters: List<ChapterItem>) {
|
||||
override fun onNextManga(manga: Manga, source: Source, chapters: List<MangaAllInOneChapterItem>) {
|
||||
if (manga.initialized) {
|
||||
// Update view.
|
||||
setMangaInfo(manga, source, chapters)
|
||||
@ -482,121 +358,9 @@ class MangaAllInOneController :
|
||||
* @param manga manga object containing information about manga.
|
||||
* @param source the source of the manga.
|
||||
*/
|
||||
private fun setMangaInfo(manga: Manga, source: Source?, chapters: List<ChapterItem>) {
|
||||
override fun setMangaInfo(manga: Manga, source: Source?, chapters: List<MangaAllInOneChapterItem>) {
|
||||
val view = view ?: return
|
||||
|
||||
// update full title TextView.
|
||||
binding.mangaFullTitle.text = if (manga.title.isBlank()) {
|
||||
view.context.getString(R.string.unknown)
|
||||
} else {
|
||||
manga.title
|
||||
}
|
||||
|
||||
// Update artist TextView.
|
||||
binding.mangaArtist.text = if (manga.artist.isNullOrBlank()) {
|
||||
view.context.getString(R.string.unknown)
|
||||
} else {
|
||||
manga.artist
|
||||
}
|
||||
|
||||
// Update author TextView.
|
||||
binding.mangaAuthor.text = if (manga.author.isNullOrBlank()) {
|
||||
view.context.getString(R.string.unknown)
|
||||
} else {
|
||||
manga.author
|
||||
}
|
||||
|
||||
// If manga source is known update source TextView.
|
||||
val mangaSource = source?.toString()
|
||||
with(binding.mangaSource) {
|
||||
// EXH -->
|
||||
if (mangaSource == null) {
|
||||
text = view.context.getString(R.string.unknown)
|
||||
} else if (source.id == MERGED_SOURCE_ID) {
|
||||
text = MergedSource.MangaConfig.readFromUrl(gson, manga.url).children.map {
|
||||
sourceManager.getOrStub(it.source).toString()
|
||||
}.distinct().joinToString()
|
||||
} else {
|
||||
text = mangaSource
|
||||
setOnClickListener {
|
||||
val sourceManager = Injekt.get<SourceManager>()
|
||||
performSearch(sourceManager.getOrStub(source.id).name)
|
||||
}
|
||||
}
|
||||
// EXH <--
|
||||
}
|
||||
|
||||
// EXH -->
|
||||
if (source?.id == MERGED_SOURCE_ID) {
|
||||
binding.mangaSourceLabel.text = "Sources"
|
||||
} else {
|
||||
binding.mangaSourceLabel.setText(R.string.manga_info_source_label)
|
||||
}
|
||||
// EXH <--
|
||||
|
||||
// Update status TextView.
|
||||
binding.mangaStatus.setText(
|
||||
when (manga.status) {
|
||||
SManga.ONGOING -> R.string.ongoing
|
||||
SManga.COMPLETED -> R.string.completed
|
||||
SManga.LICENSED -> R.string.licensed
|
||||
else -> R.string.unknown
|
||||
}
|
||||
)
|
||||
|
||||
// Set the favorite drawable to the correct one.
|
||||
setFavoriteButtonState(manga.favorite)
|
||||
|
||||
// Set cover if it wasn't already.
|
||||
val mangaThumbnail = manga.toMangaThumbnail()
|
||||
|
||||
GlideApp.with(view.context)
|
||||
.load(mangaThumbnail)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.centerCrop()
|
||||
.into(binding.mangaCover)
|
||||
|
||||
binding.backdrop?.let {
|
||||
GlideApp.with(view.context)
|
||||
.load(mangaThumbnail)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.centerCrop()
|
||||
.into(it)
|
||||
}
|
||||
|
||||
// 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.mangaGenresTagsCompactChips.setChipsExtended(manga.getGenres(), this::performSearch, this::performGlobalSearch, manga.source)
|
||||
binding.mangaGenresTagsFullChips.setChipsExtended(manga.getGenres(), this::performSearch, this::performGlobalSearch, manga.source)
|
||||
} else {
|
||||
binding.mangaGenresTagsWrapper.gone()
|
||||
}
|
||||
|
||||
// Handle showing more or less info
|
||||
binding.mangaSummary.clicks()
|
||||
.onEach { toggleMangaInfo(view.context) }
|
||||
.launchIn(scope)
|
||||
binding.mangaInfoToggle.clicks()
|
||||
.onEach { toggleMangaInfo(view.context) }
|
||||
.launchIn(scope)
|
||||
|
||||
// Expand manga info if navigated from source listing
|
||||
if (initialLoad && fromSource) {
|
||||
toggleMangaInfo(view.context)
|
||||
initialLoad = false
|
||||
}
|
||||
}
|
||||
if (update ||
|
||||
// Auto-update old format galleries
|
||||
(
|
||||
@ -610,6 +374,7 @@ class MangaAllInOneController :
|
||||
|
||||
val adapter = adapter ?: return
|
||||
adapter.updateDataSet(chapters)
|
||||
addMangaHeader()
|
||||
|
||||
if (selectedItems.isNotEmpty()) {
|
||||
adapter.clearSelection() // we need to start from a clean state, index may have changed
|
||||
@ -624,90 +389,7 @@ class MangaAllInOneController :
|
||||
}
|
||||
}
|
||||
|
||||
private fun hideMangaInfo() {
|
||||
binding.mangaSummaryLabel.gone()
|
||||
binding.mangaSummary.gone()
|
||||
binding.mangaGenresTagsWrapper.gone()
|
||||
binding.mangaInfoToggle.gone()
|
||||
}
|
||||
|
||||
private fun toggleMangaInfo(context: Context) {
|
||||
val isExpanded = binding.mangaInfoToggle.text == context.getString(R.string.manga_info_collapse)
|
||||
|
||||
binding.mangaInfoToggle.text =
|
||||
if (isExpanded) {
|
||||
context.getString(R.string.manga_info_expand)
|
||||
} else {
|
||||
context.getString(R.string.manga_info_collapse)
|
||||
}
|
||||
|
||||
with(binding.mangaSummary) {
|
||||
maxLines =
|
||||
if (isExpanded) {
|
||||
3
|
||||
} else {
|
||||
Int.MAX_VALUE
|
||||
}
|
||||
|
||||
ellipsize =
|
||||
if (isExpanded) {
|
||||
TextUtils.TruncateAt.END
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
binding.mangaGenresTagsCompact.visibleIf { isExpanded }
|
||||
binding.mangaGenresTagsFullChips.visibleIf { !isExpanded }
|
||||
}
|
||||
|
||||
/**
|
||||
* Update chapter count TextView.
|
||||
*
|
||||
* @param count number of chapters.
|
||||
*/
|
||||
fun setChapterCount(count: Float) {
|
||||
if (count > 0f) {
|
||||
binding.mangaChapters.text = DecimalFormat("#.#").format(count)
|
||||
} else {
|
||||
binding.mangaChapters.text = resources?.getString(R.string.unknown)
|
||||
}
|
||||
}
|
||||
|
||||
fun setLastUpdateDate(date: Date) {
|
||||
if (date.time != 0L) {
|
||||
binding.mangaLastUpdate.text = dateFormat.format(date)
|
||||
} else {
|
||||
binding.mangaLastUpdate.text = resources?.getString(R.string.unknown)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the favorite status and asks for confirmation to delete downloaded chapters.
|
||||
*/
|
||||
private fun toggleFavorite() {
|
||||
val view = view
|
||||
|
||||
val isNowFavorite = presenter.toggleFavorite()
|
||||
if (view != null && !isNowFavorite && presenter.hasDownloads()) {
|
||||
view.snack(view.context.getString(R.string.delete_downloads_for_manga)) {
|
||||
setAction(R.string.action_delete) {
|
||||
presenter.deleteDownloads()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.btnCategories.visibleIf { isNowFavorite && presenter.getCategories().isNotEmpty() }
|
||||
if (isNowFavorite) {
|
||||
binding.btnSmartSearch.visible()
|
||||
binding.btnMigrate.visible()
|
||||
} else {
|
||||
binding.btnSmartSearch.gone()
|
||||
binding.btnMigrate.gone()
|
||||
}
|
||||
}
|
||||
|
||||
private fun openInWebView() {
|
||||
override fun openInWebView() {
|
||||
val source = presenter.source as? HttpSource ?: return
|
||||
|
||||
val url = try {
|
||||
@ -724,7 +406,7 @@ class MangaAllInOneController :
|
||||
/**
|
||||
* Called to run Intent with [Intent.ACTION_SEND], which show share dialog.
|
||||
*/
|
||||
private fun shareManga() {
|
||||
override fun shareManga() {
|
||||
val context = view?.context ?: return
|
||||
|
||||
val source = presenter.source as? HttpSource ?: return
|
||||
@ -740,38 +422,23 @@ class MangaAllInOneController :
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update favorite button with correct drawable and text.
|
||||
*
|
||||
* @param isFavorite determines if manga is favorite or not.
|
||||
*/
|
||||
fun setFavoriteButtonState(isFavorite: Boolean) {
|
||||
// Set the Favorite drawable to the correct one.
|
||||
// Border drawable if false, filled drawable if true.
|
||||
binding.btnFavorite.apply {
|
||||
icon = ContextCompat.getDrawable(context, if (isFavorite) R.drawable.ic_favorite_24dp else R.drawable.ic_favorite_border_24dp)
|
||||
text = context.getString(if (isFavorite) R.string.in_library else R.string.add_to_library)
|
||||
isChecked = isFavorite
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start fetching manga information from source.
|
||||
*/
|
||||
private fun fetchMangaFromSource(manualFetch: Boolean = false, fetchManga: Boolean = true, fetchChapters: Boolean = true) {
|
||||
override fun fetchMangaFromSource(manualFetch: Boolean, fetchManga: Boolean, fetchChapters: Boolean) {
|
||||
setRefreshing(true)
|
||||
// Call presenter and start fetching manga information
|
||||
presenter.fetchMangaFromSource(manualFetch, fetchManga, fetchChapters)
|
||||
}
|
||||
|
||||
fun onFetchMangaDone() {
|
||||
override fun onFetchMangaDone() {
|
||||
setRefreshing(false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Update swipe refresh to start showing refresh in progress spinner.
|
||||
*/
|
||||
fun onFetchMangaError(error: Throwable) {
|
||||
override fun onFetchMangaError(error: Throwable) {
|
||||
setRefreshing(false)
|
||||
activity?.toast(error.message)
|
||||
}
|
||||
@ -781,15 +448,15 @@ class MangaAllInOneController :
|
||||
*
|
||||
* @param value whether it should be refreshing or not.
|
||||
*/
|
||||
fun setRefreshing(value: Boolean) {
|
||||
override fun setRefreshing(value: Boolean) {
|
||||
binding.swipeRefresh.isRefreshing = value
|
||||
}
|
||||
|
||||
private fun onFavoriteClick() {
|
||||
override fun onFavoriteClick() {
|
||||
val manga = presenter.manga
|
||||
|
||||
if (manga.favorite) {
|
||||
toggleFavorite()
|
||||
getHeader()?.toggleFavorite()
|
||||
activity?.toast(activity?.getString(R.string.manga_removed_library))
|
||||
} else {
|
||||
val categories = presenter.getCategories()
|
||||
@ -799,14 +466,14 @@ class MangaAllInOneController :
|
||||
when {
|
||||
// Default category set
|
||||
defaultCategory != null -> {
|
||||
toggleFavorite()
|
||||
getHeader()?.toggleFavorite()
|
||||
presenter.moveMangaToCategory(manga, defaultCategory)
|
||||
activity?.toast(activity?.getString(R.string.manga_added_library))
|
||||
}
|
||||
|
||||
// Automatic 'Default' or no categories
|
||||
defaultCategoryId == 0 || categories.isEmpty() -> {
|
||||
toggleFavorite()
|
||||
getHeader()?.toggleFavorite()
|
||||
presenter.moveMangaToCategory(manga, null)
|
||||
activity?.toast(activity?.getString(R.string.manga_added_library))
|
||||
}
|
||||
@ -825,7 +492,7 @@ class MangaAllInOneController :
|
||||
}
|
||||
}
|
||||
|
||||
private fun onCategoriesClick() {
|
||||
override fun onCategoriesClick() {
|
||||
val manga = presenter.manga
|
||||
val categories = presenter.getCategories()
|
||||
|
||||
@ -842,7 +509,7 @@ class MangaAllInOneController :
|
||||
val manga = mangas.firstOrNull() ?: return
|
||||
|
||||
if (!manga.favorite) {
|
||||
toggleFavorite()
|
||||
getHeader()?.toggleFavorite()
|
||||
activity?.toast(activity?.getString(R.string.manga_added_library))
|
||||
}
|
||||
|
||||
@ -854,13 +521,31 @@ class MangaAllInOneController :
|
||||
*
|
||||
* @param query the search query to pass to the search controller
|
||||
*/
|
||||
private fun performGlobalSearch(query: String) {
|
||||
override fun performGlobalSearch(query: String) {
|
||||
val router = router ?: return
|
||||
router.pushController(GlobalSearchController(query).withFadeTransaction())
|
||||
}
|
||||
|
||||
fun setChapterCount(count: Float) {
|
||||
getHeader()?.setChapterCount(count)
|
||||
}
|
||||
|
||||
fun setLastUpdateDate(date: Date) {
|
||||
getHeader()?.setLastUpdateDate(date)
|
||||
}
|
||||
|
||||
fun setFavoriteButtonState(isFavorite: Boolean) {
|
||||
getHeader()?.setFavoriteButtonState(isFavorite)
|
||||
}
|
||||
|
||||
override fun isInitialLoadAndFromSource() = fromSource && initialLoad
|
||||
|
||||
override fun removeInitialLoad() {
|
||||
initialLoad = false
|
||||
}
|
||||
|
||||
// --> EH
|
||||
private fun wrapTag(namespace: String, tag: String) =
|
||||
override fun wrapTag(namespace: String, tag: String) =
|
||||
if (tag.contains(' ')) {
|
||||
"$namespace:\"$tag$\""
|
||||
} else {
|
||||
@ -869,7 +554,7 @@ class MangaAllInOneController :
|
||||
|
||||
private fun parseTag(tag: String) = tag.substringBefore(':').trim() to tag.substringAfter(':').trim()
|
||||
|
||||
private fun isEHentaiBasedSource(): Boolean {
|
||||
override fun isEHentaiBasedSource(): Boolean {
|
||||
val sourceId = presenter.source.id
|
||||
return sourceId == EH_SOURCE_ID ||
|
||||
sourceId == EXH_SOURCE_ID
|
||||
@ -881,7 +566,7 @@ class MangaAllInOneController :
|
||||
*
|
||||
* @param query the search query to the previous controller
|
||||
*/
|
||||
private fun performSearch(query: String) {
|
||||
override fun performSearch(query: String) {
|
||||
val router = router ?: return
|
||||
|
||||
if (router.backstackSize < 2) {
|
||||
@ -1039,8 +724,8 @@ class MangaAllInOneController :
|
||||
getHolder(download.chapter)?.notifyStatus(download.status)
|
||||
}
|
||||
|
||||
private fun getHolder(chapter: Chapter): ChapterHolder? {
|
||||
return binding.recycler.findViewHolderForItemId(chapter.id!!) as? ChapterHolder
|
||||
private fun getHolder(chapter: Chapter): MangaAllInOneChapterHolder? {
|
||||
return binding.recycler.findViewHolderForItemId(chapter.id!!) as? MangaAllInOneChapterHolder
|
||||
}
|
||||
|
||||
fun openChapter(chapter: Chapter, hasAnimation: Boolean = false) {
|
||||
@ -1054,7 +739,7 @@ class MangaAllInOneController :
|
||||
|
||||
override fun onItemClick(view: View?, position: Int): Boolean {
|
||||
val adapter = adapter ?: return false
|
||||
val item = adapter.getItem(position) ?: return false
|
||||
val item = adapter.getItem(position) as MangaAllInOneChapterItem? ?: return false
|
||||
return if (actionMode != null && adapter.mode == SelectableAdapter.Mode.MULTI) {
|
||||
lastClickPosition = position
|
||||
toggleSelection(position)
|
||||
@ -1089,7 +774,7 @@ class MangaAllInOneController :
|
||||
adapter.toggleSelection(position)
|
||||
adapter.notifyDataSetChanged()
|
||||
if (adapter.isSelected(position)) {
|
||||
selectedItems.add(item)
|
||||
selectedItems.add(item as MangaAllInOneChapterItem)
|
||||
} else {
|
||||
selectedItems.remove(item)
|
||||
}
|
||||
@ -1101,14 +786,14 @@ class MangaAllInOneController :
|
||||
val item = adapter.getItem(position) ?: return
|
||||
if (!adapter.isSelected(position)) {
|
||||
adapter.toggleSelection(position)
|
||||
selectedItems.add(item)
|
||||
selectedItems.add(item as MangaAllInOneChapterItem)
|
||||
actionMode?.invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSelectedChapters(): List<ChapterItem> {
|
||||
private fun getSelectedChapters(): List<MangaAllInOneChapterItem> {
|
||||
val adapter = adapter ?: return emptyList()
|
||||
return adapter.selectedPositions.mapNotNull { adapter.getItem(it) }
|
||||
return adapter.selectedPositions.mapNotNull { adapter.getItem(it) as MangaAllInOneChapterItem }
|
||||
}
|
||||
|
||||
private fun createActionModeIfNeeded() {
|
||||
@ -1209,24 +894,24 @@ class MangaAllInOneController :
|
||||
for (i in 0..adapter.itemCount) {
|
||||
adapter.toggleSelection(i)
|
||||
}
|
||||
selectedItems.addAll(adapter.selectedPositions.mapNotNull { adapter.getItem(it) })
|
||||
selectedItems.addAll(adapter.selectedPositions.mapNotNull { adapter.getItem(it) as MangaAllInOneChapterItem })
|
||||
|
||||
actionMode?.invalidate()
|
||||
adapter.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
private fun markAsRead(chapters: List<ChapterItem>) {
|
||||
private fun markAsRead(chapters: List<MangaAllInOneChapterItem>) {
|
||||
presenter.markChaptersRead(chapters, true)
|
||||
if (presenter.preferences.removeAfterMarkedAsRead()) {
|
||||
deleteChapters(chapters)
|
||||
}
|
||||
}
|
||||
|
||||
private fun markAsUnread(chapters: List<ChapterItem>) {
|
||||
private fun markAsUnread(chapters: List<MangaAllInOneChapterItem>) {
|
||||
presenter.markChaptersRead(chapters, false)
|
||||
}
|
||||
|
||||
private fun downloadChapters(chapters: List<ChapterItem>) {
|
||||
private fun downloadChapters(chapters: List<MangaAllInOneChapterItem>) {
|
||||
val view = view
|
||||
presenter.downloadChapters(chapters)
|
||||
if (view != null && !presenter.manga.favorite) {
|
||||
@ -1246,7 +931,7 @@ class MangaAllInOneController :
|
||||
deleteChapters(getSelectedChapters())
|
||||
}
|
||||
|
||||
private fun markPreviousAsRead(chapters: List<ChapterItem>) {
|
||||
private fun markPreviousAsRead(chapters: List<MangaAllInOneChapterItem>) {
|
||||
val adapter = adapter ?: return
|
||||
val prevChapters = if (presenter.sortDescending()) adapter.items.reversed() else adapter.items
|
||||
val chapterPos = prevChapters.indexOf(chapters.last())
|
||||
@ -1255,17 +940,17 @@ class MangaAllInOneController :
|
||||
}
|
||||
}
|
||||
|
||||
private fun bookmarkChapters(chapters: List<ChapterItem>, bookmarked: Boolean) {
|
||||
private fun bookmarkChapters(chapters: List<MangaAllInOneChapterItem>, bookmarked: Boolean) {
|
||||
presenter.bookmarkChapters(chapters, bookmarked)
|
||||
}
|
||||
|
||||
fun deleteChapters(chapters: List<ChapterItem>) {
|
||||
fun deleteChapters(chapters: List<MangaAllInOneChapterItem>) {
|
||||
if (chapters.isEmpty()) return
|
||||
|
||||
presenter.deleteChapters(chapters)
|
||||
}
|
||||
|
||||
fun onChaptersDeleted(chapters: List<ChapterItem>) {
|
||||
fun onChaptersDeleted(chapters: List<MangaAllInOneChapterItem>) {
|
||||
// this is needed so the downloaded text gets removed from the item
|
||||
chapters.forEach {
|
||||
adapter?.updateItem(it)
|
||||
|
@ -0,0 +1,48 @@
|
||||
package eu.kanade.tachiyomi.ui.manga
|
||||
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.ui.browse.source.SourceController
|
||||
|
||||
class MangaAllInOneHeaderItem(val manga: Manga, val source: Source, var smartSearchConfig: SourceController.SmartSearchConfig? = null) :
|
||||
AbstractFlexibleItem<MangaAllInOneHolder>() {
|
||||
|
||||
override fun getLayoutRes(): Int {
|
||||
return R.layout.manga_all_in_one_header
|
||||
}
|
||||
|
||||
override fun isSelectable(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun isSwipeable(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): MangaAllInOneHolder {
|
||||
return MangaAllInOneHolder(view, adapter as MangaAllInOneAdapter, smartSearchConfig)
|
||||
}
|
||||
|
||||
override fun bindViewHolder(
|
||||
adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>,
|
||||
holder: MangaAllInOneHolder,
|
||||
position: Int,
|
||||
payloads: MutableList<Any?>?
|
||||
) {
|
||||
holder.bind(this, manga, source)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return (this === other)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return -(manga.id).hashCode()
|
||||
}
|
||||
}
|
@ -0,0 +1,440 @@
|
||||
package eu.kanade.tachiyomi.ui.manga
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.accessibility.AccessibilityEventCompat.setAction
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.google.gson.Gson
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.glide.GlideApp
|
||||
import eu.kanade.tachiyomi.data.glide.toMangaThumbnail
|
||||
import eu.kanade.tachiyomi.data.preference.PreferenceKeys.dateFormat
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
|
||||
import eu.kanade.tachiyomi.ui.browse.source.SourceController
|
||||
import eu.kanade.tachiyomi.util.view.gone
|
||||
import eu.kanade.tachiyomi.util.view.snack
|
||||
import eu.kanade.tachiyomi.util.view.visible
|
||||
import eu.kanade.tachiyomi.util.view.visibleIf
|
||||
import exh.MERGED_SOURCE_ID
|
||||
import exh.debug.DebugFunctions.sourceManager
|
||||
import exh.util.setChipsExtended
|
||||
import java.text.DecimalFormat
|
||||
import java.util.Date
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.backdrop
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.btn_categories
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.btn_favorite
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.btn_migrate
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.btn_share
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.btn_smart_search
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.btn_tracking
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.btn_webview
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.manga_artist
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.manga_artist_label
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.manga_author
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.manga_author_label
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.manga_chapters
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.manga_cover
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.manga_full_title
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.manga_genres_tags_compact
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.manga_genres_tags_compact_chips
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.manga_genres_tags_full_chips
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.manga_genres_tags_wrapper
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.manga_info_toggle
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.manga_last_update
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.manga_source
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.manga_source_label
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.manga_status
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.manga_summary
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.manga_summary_label
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.merge_btn
|
||||
import kotlinx.android.synthetic.main.manga_all_in_one_header.recommend_btn
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import reactivecircus.flowbinding.android.view.clicks
|
||||
import reactivecircus.flowbinding.android.view.longClicks
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
class MangaAllInOneHolder(
|
||||
view: View,
|
||||
private val adapter: MangaAllInOneAdapter,
|
||||
smartSearchConfig: SourceController.SmartSearchConfig? = null
|
||||
) : BaseFlexibleViewHolder(view, adapter) {
|
||||
|
||||
private val gson: Gson by injectLazy()
|
||||
|
||||
init {
|
||||
val presenter = adapter.delegate.mangaPresenter()
|
||||
|
||||
// Setting this via XML doesn't work
|
||||
manga_cover.clipToOutline = true
|
||||
|
||||
btn_favorite.clicks()
|
||||
.onEach { adapter.delegate.onFavoriteClick() }
|
||||
.launchIn(adapter.delegate.controllerScope)
|
||||
|
||||
if ((Injekt.get<TrackManager>().hasLoggedServices()) && presenter.manga.favorite) {
|
||||
btn_tracking.visible()
|
||||
}
|
||||
|
||||
adapter.delegate.controllerScope.launch(Dispatchers.IO) {
|
||||
if (Injekt.get<DatabaseHelper>().getTracks(presenter.manga).executeAsBlocking().any {
|
||||
val status = Injekt.get<TrackManager>().getService(it.sync_id)?.getStatus(it.status)
|
||||
status != null
|
||||
}
|
||||
) {
|
||||
withContext(Dispatchers.Main) {
|
||||
btn_tracking.icon = itemView.context.getDrawable(R.drawable.ic_cloud_white_24dp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
btn_tracking.clicks()
|
||||
.onEach { adapter.delegate.openTracking() }
|
||||
.launchIn(adapter.delegate.controllerScope)
|
||||
|
||||
if (presenter.manga.favorite && presenter.getCategories().isNotEmpty()) {
|
||||
btn_categories.visible()
|
||||
}
|
||||
btn_categories.clicks()
|
||||
.onEach { adapter.delegate.onCategoriesClick() }
|
||||
.launchIn(adapter.delegate.controllerScope)
|
||||
|
||||
if (presenter.source is HttpSource) {
|
||||
btn_webview.visible()
|
||||
btn_share.visible()
|
||||
|
||||
btn_webview.clicks()
|
||||
.onEach { adapter.delegate.openInWebView() }
|
||||
.launchIn(adapter.delegate.controllerScope)
|
||||
btn_share.clicks()
|
||||
.onEach { adapter.delegate.shareManga() }
|
||||
.launchIn(adapter.delegate.controllerScope)
|
||||
}
|
||||
|
||||
if (presenter.manga.favorite) {
|
||||
btn_migrate.visible()
|
||||
btn_smart_search.visible()
|
||||
}
|
||||
|
||||
btn_migrate.clicks()
|
||||
.onEach {
|
||||
adapter.delegate.migrateManga()
|
||||
}
|
||||
.launchIn(adapter.delegate.controllerScope)
|
||||
|
||||
btn_smart_search.clicks()
|
||||
.onEach { adapter.delegate.openSmartSearch() }
|
||||
.launchIn(adapter.delegate.controllerScope)
|
||||
|
||||
manga_full_title.longClicks()
|
||||
.onEach {
|
||||
adapter.delegate.copyToClipboard(view.context.getString(R.string.title), manga_full_title.text.toString())
|
||||
}
|
||||
.launchIn(adapter.delegate.controllerScope)
|
||||
|
||||
manga_full_title.clicks()
|
||||
.onEach {
|
||||
adapter.delegate.performGlobalSearch(manga_full_title.text.toString())
|
||||
}
|
||||
.launchIn(adapter.delegate.controllerScope)
|
||||
|
||||
manga_artist.longClicks()
|
||||
.onEach {
|
||||
adapter.delegate.copyToClipboard(manga_artist_label.text.toString(), manga_artist.text.toString())
|
||||
}
|
||||
.launchIn(adapter.delegate.controllerScope)
|
||||
|
||||
manga_artist.clicks()
|
||||
.onEach {
|
||||
var text = manga_artist.text.toString()
|
||||
if (adapter.delegate.isEHentaiBasedSource()) {
|
||||
text = adapter.delegate.wrapTag("artist", text)
|
||||
}
|
||||
adapter.delegate.performGlobalSearch(text)
|
||||
}
|
||||
.launchIn(adapter.delegate.controllerScope)
|
||||
|
||||
manga_author.longClicks()
|
||||
.onEach {
|
||||
// EXH Special case E-Hentai/ExHentai to ignore author field (unused)
|
||||
if (!adapter.delegate.isEHentaiBasedSource()) {
|
||||
adapter.delegate.copyToClipboard(manga_author_label.text.toString(), manga_author.text.toString())
|
||||
}
|
||||
}
|
||||
.launchIn(adapter.delegate.controllerScope)
|
||||
|
||||
manga_author.clicks()
|
||||
.onEach {
|
||||
// EXH Special case E-Hentai/ExHentai to ignore author field (unused)
|
||||
if (!adapter.delegate.isEHentaiBasedSource()) {
|
||||
adapter.delegate.performGlobalSearch(manga_author.text.toString())
|
||||
}
|
||||
}
|
||||
.launchIn(adapter.delegate.controllerScope)
|
||||
|
||||
manga_summary.longClicks()
|
||||
.onEach {
|
||||
adapter.delegate.copyToClipboard(view.context.getString(R.string.description), manga_summary.text.toString())
|
||||
}
|
||||
.launchIn(adapter.delegate.controllerScope)
|
||||
|
||||
manga_cover.longClicks()
|
||||
.onEach {
|
||||
adapter.delegate.copyToClipboard(view.context.getString(R.string.title), presenter.manga.title)
|
||||
}
|
||||
.launchIn(adapter.delegate.controllerScope)
|
||||
|
||||
// EXH -->
|
||||
if (smartSearchConfig == null) {
|
||||
recommend_btn.visible()
|
||||
recommend_btn.clicks()
|
||||
.onEach { adapter.delegate.openRecommends() }
|
||||
.launchIn(adapter.delegate.controllerScope)
|
||||
}
|
||||
smartSearchConfig?.let { smartSearchConfig ->
|
||||
if (smartSearchConfig.origMangaId != null) { merge_btn.visible() }
|
||||
merge_btn.clicks()
|
||||
.onEach {
|
||||
adapter.delegate.mergeWithAnother()
|
||||
}
|
||||
|
||||
.launchIn(adapter.delegate.controllerScope)
|
||||
}
|
||||
// EXH <--
|
||||
}
|
||||
|
||||
fun bind(item: MangaAllInOneHeaderItem, manga: Manga, source: Source?) {
|
||||
val presenter = adapter.delegate.mangaPresenter()
|
||||
|
||||
manga_full_title.text = if (manga.title.isBlank()) {
|
||||
itemView.context.getString(R.string.unknown)
|
||||
} else {
|
||||
manga.title
|
||||
}
|
||||
|
||||
// Update artist TextView.
|
||||
manga_artist.text = if (manga.artist.isNullOrBlank()) {
|
||||
itemView.context.getString(R.string.unknown)
|
||||
} else {
|
||||
manga.artist
|
||||
}
|
||||
|
||||
// Update author TextView.
|
||||
manga_author.text = if (manga.author.isNullOrBlank()) {
|
||||
itemView.context.getString(R.string.unknown)
|
||||
} else {
|
||||
manga.author
|
||||
}
|
||||
|
||||
// If manga source is known update source TextView.
|
||||
val mangaSource = source?.toString()
|
||||
with(manga_source) {
|
||||
// EXH -->
|
||||
if (mangaSource == null) {
|
||||
text = itemView.context.getString(R.string.unknown)
|
||||
} else if (source.id == MERGED_SOURCE_ID) {
|
||||
text = eu.kanade.tachiyomi.source.online.all.MergedSource.MangaConfig.readFromUrl(gson, manga.url).children.map {
|
||||
sourceManager.getOrStub(it.source).toString()
|
||||
}.distinct().joinToString()
|
||||
} else {
|
||||
text = mangaSource
|
||||
setOnClickListener {
|
||||
val sourceManager = Injekt.get<SourceManager>()
|
||||
adapter.delegate.performSearch(sourceManager.getOrStub(source.id).name)
|
||||
}
|
||||
}
|
||||
// EXH <--
|
||||
}
|
||||
|
||||
// EXH -->
|
||||
if (source?.id == MERGED_SOURCE_ID) {
|
||||
manga_source_label.text = "Sources"
|
||||
} else {
|
||||
manga_source_label.setText(R.string.manga_info_source_label)
|
||||
}
|
||||
// EXH <--
|
||||
|
||||
// Update status TextView.
|
||||
manga_status.setText(
|
||||
when (manga.status) {
|
||||
SManga.ONGOING -> R.string.ongoing
|
||||
SManga.COMPLETED -> R.string.completed
|
||||
SManga.LICENSED -> R.string.licensed
|
||||
else -> R.string.unknown
|
||||
}
|
||||
)
|
||||
|
||||
// Set the favorite drawable to the correct one.
|
||||
setFavoriteButtonState(manga.favorite)
|
||||
|
||||
// Set cover if it wasn't already.
|
||||
val mangaThumbnail = manga.toMangaThumbnail()
|
||||
|
||||
GlideApp.with(itemView.context)
|
||||
.load(mangaThumbnail)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.centerCrop()
|
||||
.into(manga_cover)
|
||||
|
||||
backdrop?.let {
|
||||
GlideApp.with(itemView.context)
|
||||
.load(mangaThumbnail)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.centerCrop()
|
||||
.into(it)
|
||||
}
|
||||
|
||||
// Manga info section
|
||||
if (manga.description.isNullOrBlank() && manga.genre.isNullOrBlank()) {
|
||||
hideMangaInfo()
|
||||
} else {
|
||||
// Update description TextView.
|
||||
manga_summary.text = if (manga.description.isNullOrBlank()) {
|
||||
itemView.context.getString(R.string.unknown)
|
||||
} else {
|
||||
manga.description
|
||||
}
|
||||
|
||||
// Update genres list
|
||||
if (!manga.genre.isNullOrBlank()) {
|
||||
manga_genres_tags_compact_chips.setChipsExtended(manga.getGenres(), this::performSearch, this::performGlobalSearch, manga.source)
|
||||
manga_genres_tags_full_chips.setChipsExtended(manga.getGenres(), this::performSearch, this::performGlobalSearch, manga.source)
|
||||
} else {
|
||||
manga_genres_tags_wrapper.gone()
|
||||
}
|
||||
|
||||
// Handle showing more or less info
|
||||
manga_summary.clicks()
|
||||
.onEach { toggleMangaInfo(itemView.context) }
|
||||
.launchIn(adapter.delegate.controllerScope)
|
||||
manga_info_toggle.clicks()
|
||||
.onEach { toggleMangaInfo(itemView.context) }
|
||||
.launchIn(adapter.delegate.controllerScope)
|
||||
|
||||
// Expand manga info if navigated from source listing
|
||||
if (adapter.delegate.isInitialLoadAndFromSource()) {
|
||||
adapter.delegate.removeInitialLoad()
|
||||
toggleMangaInfo(itemView.context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun hideMangaInfo() {
|
||||
manga_summary_label.gone()
|
||||
manga_summary.gone()
|
||||
manga_genres_tags_wrapper.gone()
|
||||
manga_info_toggle.gone()
|
||||
}
|
||||
|
||||
fun toggleMangaInfo(context: Context) {
|
||||
val isExpanded = manga_info_toggle.text == context.getString(R.string.manga_info_collapse)
|
||||
|
||||
manga_info_toggle.text =
|
||||
if (isExpanded) {
|
||||
context.getString(R.string.manga_info_expand)
|
||||
} else {
|
||||
context.getString(R.string.manga_info_collapse)
|
||||
}
|
||||
|
||||
with(manga_summary) {
|
||||
maxLines =
|
||||
if (isExpanded) {
|
||||
3
|
||||
} else {
|
||||
Int.MAX_VALUE
|
||||
}
|
||||
|
||||
ellipsize =
|
||||
if (isExpanded) {
|
||||
android.text.TextUtils.TruncateAt.END
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
manga_genres_tags_compact.visibleIf { isExpanded }
|
||||
manga_genres_tags_full_chips.visibleIf { !isExpanded }
|
||||
}
|
||||
|
||||
/**
|
||||
* Update chapter count TextView.
|
||||
*
|
||||
* @param count number of chapters.
|
||||
*/
|
||||
fun setChapterCount(count: Float) {
|
||||
if (count > 0f) {
|
||||
manga_chapters.text = DecimalFormat("#.#").format(count)
|
||||
} else {
|
||||
manga_chapters.text = itemView.context.getString(R.string.unknown)
|
||||
}
|
||||
}
|
||||
|
||||
fun setLastUpdateDate(date: Date) {
|
||||
if (date.time != 0L) {
|
||||
manga_last_update.text = dateFormat.format(date)
|
||||
} else {
|
||||
manga_last_update.text = itemView.context.getString(R.string.unknown)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the favorite status and asks for confirmation to delete downloaded chapters.
|
||||
*/
|
||||
fun toggleFavorite() {
|
||||
val presenter = adapter.delegate.mangaPresenter()
|
||||
|
||||
val isNowFavorite = presenter.toggleFavorite()
|
||||
if (itemView != null && !isNowFavorite && presenter.hasDownloads()) {
|
||||
itemView.snack(itemView.context.getString(R.string.delete_downloads_for_manga)) {
|
||||
setAction(R.string.action_delete) {
|
||||
presenter.deleteDownloads()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
btn_categories.visibleIf { isNowFavorite && presenter.getCategories().isNotEmpty() }
|
||||
if (isNowFavorite) {
|
||||
btn_smart_search.visible()
|
||||
btn_migrate.visible()
|
||||
} else {
|
||||
btn_smart_search.gone()
|
||||
btn_migrate.gone()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update favorite button with correct drawable and text.
|
||||
*
|
||||
* @param isFavorite determines if manga is favorite or not.
|
||||
*/
|
||||
fun setFavoriteButtonState(isFavorite: Boolean) {
|
||||
// Set the Favorite drawable to the correct one.
|
||||
// Border drawable if false, filled drawable if true.
|
||||
btn_favorite.apply {
|
||||
icon = ContextCompat.getDrawable(context, if (isFavorite) R.drawable.ic_favorite_24dp else R.drawable.ic_favorite_border_24dp)
|
||||
text = context.getString(if (isFavorite) R.string.in_library else R.string.add_to_library)
|
||||
isChecked = isFavorite
|
||||
}
|
||||
}
|
||||
|
||||
private fun performSearch(query: String) {
|
||||
adapter.delegate.performSearch(query)
|
||||
}
|
||||
|
||||
private fun performGlobalSearch(query: String) {
|
||||
adapter.delegate.performGlobalSearch(query)
|
||||
}
|
||||
}
|
@ -18,8 +18,8 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.online.all.MergedSource
|
||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||
import eu.kanade.tachiyomi.ui.browse.source.SourceController
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersPresenter
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.MangaAllInOneChapterItem
|
||||
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
|
||||
import eu.kanade.tachiyomi.util.prepUpdateCover
|
||||
import eu.kanade.tachiyomi.util.removeCovers
|
||||
@ -64,7 +64,7 @@ class MangaAllInOnePresenter(
|
||||
/**
|
||||
* List of chapters of the manga. It's always unfiltered and unsorted.
|
||||
*/
|
||||
var chapters: List<ChapterItem> = emptyList()
|
||||
var chapters: List<MangaAllInOneChapterItem> = emptyList()
|
||||
private set
|
||||
|
||||
private val scope = CoroutineScope(Job() + Dispatchers.Default)
|
||||
@ -86,6 +86,8 @@ class MangaAllInOnePresenter(
|
||||
private val redirectUserRelay = BehaviorRelay.create<ChaptersPresenter.EXHRedirect>()
|
||||
// EXH <--
|
||||
|
||||
var headerItem = MangaAllInOneHeaderItem(manga, source, smartSearchConfig)
|
||||
|
||||
override fun onCreate(savedState: Bundle?) {
|
||||
super.onCreate(savedState)
|
||||
|
||||
@ -385,9 +387,9 @@ class MangaAllInOnePresenter(
|
||||
/**
|
||||
* Converts a chapter from the database to an extended model, allowing to store new fields.
|
||||
*/
|
||||
private fun Chapter.toModel(): ChapterItem {
|
||||
private fun Chapter.toModel(): MangaAllInOneChapterItem {
|
||||
// Create the model object.
|
||||
val model = ChapterItem(this, manga)
|
||||
val model = MangaAllInOneChapterItem(this, manga)
|
||||
|
||||
// Find an active download for this chapter.
|
||||
val download = downloadManager.queue.find { it.chapter.id == id }
|
||||
@ -404,7 +406,7 @@ class MangaAllInOnePresenter(
|
||||
*
|
||||
* @param chapters the list of chapter from the database.
|
||||
*/
|
||||
private fun setDownloadedChapters(chapters: List<ChapterItem>) {
|
||||
private fun setDownloadedChapters(chapters: List<MangaAllInOneChapterItem>) {
|
||||
for (chapter in chapters) {
|
||||
if (downloadManager.isChapterDownloaded(chapter, manga)) {
|
||||
chapter.status = Download.DOWNLOADED
|
||||
@ -417,7 +419,7 @@ class MangaAllInOnePresenter(
|
||||
* @param chapters the list of chapters from the database
|
||||
* @return an observable of the list of chapters filtered and sorted.
|
||||
*/
|
||||
private fun applyChapterFilters(chapterList: List<ChapterItem>): List<ChapterItem> {
|
||||
private fun applyChapterFilters(chapterList: List<MangaAllInOneChapterItem>): List<MangaAllInOneChapterItem> {
|
||||
var chapters = chapterList
|
||||
if (onlyUnread()) {
|
||||
chapters = chapters.filter { !it.read }
|
||||
@ -468,7 +470,7 @@ class MangaAllInOnePresenter(
|
||||
/**
|
||||
* Returns the next unread chapter or null if everything is read.
|
||||
*/
|
||||
fun getNextUnreadChapter(): ChapterItem? {
|
||||
fun getNextUnreadChapter(): MangaAllInOneChapterItem? {
|
||||
return chapters.sortedByDescending { it.source_order }.find { !it.read }
|
||||
}
|
||||
|
||||
@ -477,7 +479,7 @@ class MangaAllInOnePresenter(
|
||||
* @param selectedChapters the list of selected chapters.
|
||||
* @param read whether to mark chapters as read or unread.
|
||||
*/
|
||||
fun markChaptersRead(selectedChapters: List<ChapterItem>, read: Boolean) {
|
||||
fun markChaptersRead(selectedChapters: List<MangaAllInOneChapterItem>, read: Boolean) {
|
||||
Observable.from(selectedChapters)
|
||||
.doOnNext { chapter ->
|
||||
chapter.read = read
|
||||
@ -498,7 +500,7 @@ class MangaAllInOnePresenter(
|
||||
* Downloads the given list of chapters with the manager.
|
||||
* @param chapters the list of chapters to download.
|
||||
*/
|
||||
fun downloadChapters(chapters: List<ChapterItem>) {
|
||||
fun downloadChapters(chapters: List<MangaAllInOneChapterItem>) {
|
||||
downloadManager.downloadChapters(manga, chapters)
|
||||
}
|
||||
|
||||
@ -506,7 +508,7 @@ class MangaAllInOnePresenter(
|
||||
* Bookmarks the given list of chapters.
|
||||
* @param selectedChapters the list of chapters to bookmark.
|
||||
*/
|
||||
fun bookmarkChapters(selectedChapters: List<ChapterItem>, bookmarked: Boolean) {
|
||||
fun bookmarkChapters(selectedChapters: List<MangaAllInOneChapterItem>, bookmarked: Boolean) {
|
||||
Observable.from(selectedChapters)
|
||||
.doOnNext { chapter ->
|
||||
chapter.bookmark = bookmarked
|
||||
@ -521,7 +523,7 @@ class MangaAllInOnePresenter(
|
||||
* Deletes the given list of chapter.
|
||||
* @param chapters the list of chapters to delete.
|
||||
*/
|
||||
fun deleteChapters(chapters: List<ChapterItem>) {
|
||||
fun deleteChapters(chapters: List<MangaAllInOneChapterItem>) {
|
||||
Observable.just(chapters)
|
||||
.doOnNext { deleteChaptersInternal(chapters) }
|
||||
.doOnNext { if (onlyDownloaded()) updateChaptersView() }
|
||||
@ -539,7 +541,7 @@ class MangaAllInOnePresenter(
|
||||
* Deletes a list of chapters from disk. This method is called in a background thread.
|
||||
* @param chapters the chapters to delete.
|
||||
*/
|
||||
private fun deleteChaptersInternal(chapters: List<ChapterItem>) {
|
||||
private fun deleteChaptersInternal(chapters: List<MangaAllInOneChapterItem>) {
|
||||
downloadManager.deleteChapters(chapters, manga, source)
|
||||
chapters.forEach {
|
||||
it.status = Download.NOT_DOWNLOADED
|
||||
|
@ -8,6 +8,7 @@ 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.ui.base.holder.BaseFlexibleViewHolder
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaAllInOneAdapter
|
||||
import eu.kanade.tachiyomi.util.view.visibleIf
|
||||
import java.util.Date
|
||||
import kotlinx.android.synthetic.main.chapters_item.bookmark_icon
|
||||
@ -76,3 +77,65 @@ class ChapterHolder(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MangaAllInOneChapterHolder(
|
||||
view: View,
|
||||
private val adapter: MangaAllInOneAdapter
|
||||
) : BaseFlexibleViewHolder(view, adapter) {
|
||||
|
||||
fun bind(item: MangaAllInOneChapterItem, manga: Manga) {
|
||||
val chapter = item.chapter
|
||||
|
||||
chapter_title.text = when (manga.displayMode) {
|
||||
Manga.DISPLAY_NUMBER -> {
|
||||
val number = adapter.decimalFormat.format(chapter.chapter_number.toDouble())
|
||||
itemView.context.getString(R.string.display_mode_chapter, number)
|
||||
}
|
||||
else -> chapter.name
|
||||
}
|
||||
|
||||
// Set correct text color
|
||||
val chapterColor = when {
|
||||
chapter.read -> adapter.readColor
|
||||
chapter.bookmark -> adapter.bookmarkedColor
|
||||
else -> adapter.unreadColor
|
||||
}
|
||||
chapter_title.setTextColor(chapterColor)
|
||||
chapter_description.setTextColor(chapterColor)
|
||||
|
||||
bookmark_icon.visibleIf { chapter.bookmark }
|
||||
|
||||
val descriptions = mutableListOf<CharSequence>()
|
||||
|
||||
if (chapter.date_upload > 0) {
|
||||
descriptions.add(adapter.dateFormat.format(Date(chapter.date_upload)))
|
||||
}
|
||||
if (!chapter.read && chapter.last_page_read > 0) {
|
||||
val lastPageRead = SpannableString(itemView.context.getString(R.string.chapter_progress, chapter.last_page_read + 1)).apply {
|
||||
setSpan(ForegroundColorSpan(adapter.readColor), 0, length, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
}
|
||||
descriptions.add(lastPageRead)
|
||||
}
|
||||
if (!chapter.scanlator.isNullOrBlank()) {
|
||||
descriptions.add(chapter.scanlator!!)
|
||||
}
|
||||
|
||||
if (descriptions.isNotEmpty()) {
|
||||
chapter_description.text = descriptions.joinTo(SpannableStringBuilder(), " • ")
|
||||
} else {
|
||||
chapter_description.text = ""
|
||||
}
|
||||
|
||||
notifyStatus(item.status)
|
||||
}
|
||||
|
||||
fun notifyStatus(status: Int) = with(download_text) {
|
||||
when (status) {
|
||||
Download.QUEUE -> setText(R.string.chapter_queued)
|
||||
Download.DOWNLOADING -> setText(R.string.chapter_downloading)
|
||||
Download.DOWNLOADED -> setText(R.string.chapter_downloaded)
|
||||
Download.ERROR -> setText(R.string.chapter_error)
|
||||
else -> text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaAllInOneAdapter
|
||||
|
||||
class ChapterItem(val chapter: Chapter, val manga: Manga) :
|
||||
AbstractFlexibleItem<ChapterHolder>(),
|
||||
@ -57,3 +58,51 @@ class ChapterItem(val chapter: Chapter, val manga: Manga) :
|
||||
return chapter.id!!.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
class MangaAllInOneChapterItem(val chapter: Chapter, val manga: Manga) :
|
||||
AbstractFlexibleItem<MangaAllInOneChapterHolder>(),
|
||||
Chapter by chapter {
|
||||
|
||||
private var _status: Int = 0
|
||||
|
||||
var status: Int
|
||||
get() = download?.status ?: _status
|
||||
set(value) {
|
||||
_status = value
|
||||
}
|
||||
|
||||
@Transient
|
||||
var download: Download? = null
|
||||
|
||||
val isDownloaded: Boolean
|
||||
get() = status == Download.DOWNLOADED
|
||||
|
||||
override fun getLayoutRes(): Int {
|
||||
return R.layout.chapters_item
|
||||
}
|
||||
|
||||
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): MangaAllInOneChapterHolder {
|
||||
return MangaAllInOneChapterHolder(view, adapter as MangaAllInOneAdapter)
|
||||
}
|
||||
|
||||
override fun bindViewHolder(
|
||||
adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>,
|
||||
holder: MangaAllInOneChapterHolder,
|
||||
position: Int,
|
||||
payloads: List<Any?>?
|
||||
) {
|
||||
holder.bind(this, manga)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other is MangaAllInOneChapterItem) {
|
||||
return chapter.id!! == other.chapter.id!!
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return chapter.id!!.hashCode()
|
||||
}
|
||||
}
|
||||
|
@ -14,425 +14,29 @@
|
||||
android:elevation="5dp"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<eu.kanade.tachiyomi.widget.ThemedSwipeRefreshLayout
|
||||
android:id="@id/swipe_refresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ui.browse.source.browse.BrowseSourceController">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
<eu.kanade.tachiyomi.widget.ThemedSwipeRefreshLayout
|
||||
android:id="@id/swipe_refresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ui.browse.source.browse.BrowseSourceController">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/manga_cover"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_margin="16dp"
|
||||
android:background="@drawable/rounded_rectangle"
|
||||
android:contentDescription="@string/description_cover"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintDimensionRatio="h,3:2"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.0" />
|
||||
<FrameLayout
|
||||
android:id="@+id/linear_recycler_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/info_scrollview"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_cover"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp">
|
||||
android:clipToPadding="false"
|
||||
android:descendantFocusability="blocksDescendants"
|
||||
android:paddingBottom="@dimen/fab_list_padding"
|
||||
tools:listitem="@layout/chapters_item" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_full_title"
|
||||
style="@style/TextAppearance.Medium.Title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="2"
|
||||
android:text="@string/manga_info_full_title_label"
|
||||
android:textIsSelectable="false"
|
||||
app:autoSizeMaxTextSize="20sp"
|
||||
app:autoSizeMinTextSize="12sp"
|
||||
app:autoSizeStepGranularity="2sp"
|
||||
app:autoSizeTextType="uniform"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_author_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_author_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_full_title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_author"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_author_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_author_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_artist_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_artist_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_author_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_artist"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_artist_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_artist_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_chapters_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_last_chapter_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_artist_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_chapters"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_chapters_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_chapters_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_last_update_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_latest_data_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_chapters_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_last_update"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_last_update_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_last_update_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_status_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_status_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_last_update_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_status"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_status_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_status_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_source_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_source_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_status_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_source"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_source_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_source_label" />
|
||||
|
||||
<HorizontalScrollView
|
||||
android:id="@+id/actions_bar_scroll_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:requiresFadingEdge="horizontal"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/manga_source" >
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/actions_bar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="parent">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_favorite"
|
||||
style="@style/Theme.Widget.Button.Icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/add_to_library"
|
||||
app:icon="@drawable/ic_favorite_border_24dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_tracking"
|
||||
style="@style/Theme.Widget.Button.Icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="@string/track"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
app:icon="@drawable/ic_cloud_off_24dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_categories"
|
||||
style="@style/Theme.Widget.Button.Icon.Textless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/action_edit_categories"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_label_24dp"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_share"
|
||||
style="@style/Theme.Widget.Button.Icon.Textless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/action_share"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_share_24dp"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_webview"
|
||||
style="@style/Theme.Widget.Button.Icon.Textless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/action_open_in_web_view"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_public_24dp"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_migrate"
|
||||
style="@style/Theme.Widget.Button.Icon.Textless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/migrate"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/baseline_swap_calls_24"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_smart_search"
|
||||
style="@style/Theme.Widget.Button.Icon.Textless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/eh_merge_with_another_source"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/eh_ic_find_replace_white_24dp"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</HorizontalScrollView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_summary_label"
|
||||
style="@style/TextAppearance.Regular.SubHeading"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:text="@string/manga_info_about_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/actions_bar_scroll_view" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_summary"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="true"
|
||||
android:ellipsize="end"
|
||||
android:focusable="true"
|
||||
android:maxLines="3"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBottom_toTopOf="@id/manga_genres_tags_wrapper"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/manga_summary_label" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/manga_genres_tags_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:layout_constrainedHeight="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/manga_summary">
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/manga_genres_tags_full_chips"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:chipSpacingHorizontal="4dp" />
|
||||
|
||||
<HorizontalScrollView
|
||||
android:id="@+id/manga_genres_tags_compact"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:requiresFadingEdge="horizontal">
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/manga_genres_tags_compact_chips"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:chipSpacingHorizontal="4dp"
|
||||
app:singleLine="true" />
|
||||
|
||||
</HorizontalScrollView>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/manga_info_toggle"
|
||||
style="@style/Theme.Widget.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="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_wrapper" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/merge_btn"
|
||||
style="@style/Theme.Widget.Button.FilledAccent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/merge"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_info_toggle"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/recommend_btn"
|
||||
style="@style/Theme.Widget.Button.FilledAccent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/az_recommends"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_info_toggle"
|
||||
tools:layout_constraintTop_toBottomOf="@+id/merge_btn"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/recommend_btn">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:clipToPadding="false"
|
||||
android:descendantFocusability="blocksDescendants"
|
||||
android:paddingBottom="@dimen/fab_list_padding"
|
||||
tools:listitem="@layout/chapters_item" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</eu.kanade.tachiyomi.widget.ThemedSwipeRefreshLayout>
|
||||
</eu.kanade.tachiyomi.widget.ThemedSwipeRefreshLayout>
|
||||
|
||||
<eu.kanade.tachiyomi.ui.library.MaterialFastScroll
|
||||
android:id="@+id/fast_scroller"
|
||||
|
381
app/src/main/res/layout-land/manga_all_in_one_header.xml
Normal file
381
app/src/main/res/layout-land/manga_all_in_one_header.xml
Normal file
@ -0,0 +1,381 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/manga_cover"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_margin="16dp"
|
||||
android:background="@drawable/rounded_rectangle"
|
||||
android:contentDescription="@string/description_cover"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintDimensionRatio="h,3:2"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.0" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp"
|
||||
app:layout_constraintStart_toEndOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_full_title"
|
||||
style="@style/TextAppearance.Medium.Title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="2"
|
||||
android:text="@string/manga_info_full_title_label"
|
||||
android:textIsSelectable="false"
|
||||
app:autoSizeMaxTextSize="20sp"
|
||||
app:autoSizeMinTextSize="12sp"
|
||||
app:autoSizeStepGranularity="2sp"
|
||||
app:autoSizeTextType="uniform"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_author_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_author_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_full_title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_author"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_author_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_author_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_artist_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_artist_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_author_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_artist"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_artist_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_artist_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_chapters_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_last_chapter_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_artist_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_chapters"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_chapters_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_chapters_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_last_update_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_latest_data_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_chapters_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_last_update"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_last_update_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_last_update_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_status_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_status_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_last_update_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_status"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_status_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_status_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_source_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_source_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_status_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_source"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_source_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_source_label" />
|
||||
|
||||
<HorizontalScrollView
|
||||
android:id="@+id/actions_bar_scroll_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:requiresFadingEdge="horizontal"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/manga_source" >
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/actions_bar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="parent">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_favorite"
|
||||
style="@style/Theme.Widget.Button.Icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/add_to_library"
|
||||
app:icon="@drawable/ic_favorite_border_24dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_tracking"
|
||||
style="@style/Theme.Widget.Button.Icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="@string/track"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
app:icon="@drawable/ic_cloud_off_24dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_categories"
|
||||
style="@style/Theme.Widget.Button.Icon.Textless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/action_edit_categories"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_label_24dp"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_share"
|
||||
style="@style/Theme.Widget.Button.Icon.Textless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/action_share"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_share_24dp"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_webview"
|
||||
style="@style/Theme.Widget.Button.Icon.Textless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/action_open_in_web_view"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_public_24dp"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_migrate"
|
||||
style="@style/Theme.Widget.Button.Icon.Textless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/migrate"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/baseline_swap_calls_24"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_smart_search"
|
||||
style="@style/Theme.Widget.Button.Icon.Textless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/eh_merge_with_another_source"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/eh_ic_find_replace_white_24dp"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</HorizontalScrollView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_summary_label"
|
||||
style="@style/TextAppearance.Regular.SubHeading"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:text="@string/manga_info_about_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/actions_bar_scroll_view" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_summary"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="true"
|
||||
android:ellipsize="end"
|
||||
android:focusable="true"
|
||||
android:maxLines="3"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBottom_toTopOf="@id/manga_genres_tags_wrapper"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/manga_summary_label" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/manga_genres_tags_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:layout_constrainedHeight="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/manga_summary">
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/manga_genres_tags_full_chips"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:chipSpacingHorizontal="4dp" />
|
||||
|
||||
<HorizontalScrollView
|
||||
android:id="@+id/manga_genres_tags_compact"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:requiresFadingEdge="horizontal">
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/manga_genres_tags_compact_chips"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:chipSpacingHorizontal="4dp"
|
||||
app:singleLine="true" />
|
||||
|
||||
</HorizontalScrollView>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/manga_info_toggle"
|
||||
style="@style/Theme.Widget.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="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_wrapper" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/merge_btn"
|
||||
style="@style/Theme.Widget.Button.FilledAccent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/merge"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_info_toggle"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/recommend_btn"
|
||||
style="@style/Theme.Widget.Button.FilledAccent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/az_recommends"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_info_toggle"
|
||||
tools:layout_constraintTop_toBottomOf="@+id/merge_btn"
|
||||
tools:visibility="visible" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -20,428 +20,22 @@
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ui.browse.source.browse.BrowseSourceController">
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/linear_recycler_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:descendantFocusability="blocksDescendants"
|
||||
android:paddingBottom="@dimen/fab_list_padding"
|
||||
tools:listitem="@layout/chapters_item" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/guideline2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_percent="0.38" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/backdrop"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:alpha="0.2"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:background="@color/material_grey_700" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/manga_cover"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_margin="16dp"
|
||||
android:background="@drawable/rounded_rectangle"
|
||||
android:contentDescription="@string/description_cover"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintDimensionRatio="h,2:3"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline2"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/manga_info_section"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="0dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@+id/guideline2"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_full_title"
|
||||
style="@style/TextAppearance.Medium.Title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="2"
|
||||
android:paddingBottom="8dp"
|
||||
android:text="@string/manga_info_full_title_label"
|
||||
android:textIsSelectable="false"
|
||||
app:autoSizeMaxTextSize="20sp"
|
||||
app:autoSizeMinTextSize="12sp"
|
||||
app:autoSizeStepGranularity="2sp"
|
||||
app:autoSizeTextType="uniform"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_author_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_author_label"
|
||||
android:textIsSelectable="false"
|
||||
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_full_title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_author"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_author_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_author_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_artist_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_artist_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_author_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_artist"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_artist_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_artist_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_chapters_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_last_chapter_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_artist_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_chapters"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_chapters_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_chapters_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_last_update_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_latest_data_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_chapters_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_last_update"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_last_update_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_last_update_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_status_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_status_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_last_update_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_status"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_status_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_status_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_source_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_source_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_status_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_source"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_source_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_source_label" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<HorizontalScrollView
|
||||
android:id="@+id/actions_bar_scroll_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:requiresFadingEdge="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/actions_bar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_favorite"
|
||||
style="@style/Theme.Widget.Button.Icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/add_to_library"
|
||||
app:icon="@drawable/ic_favorite_border_24dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_tracking"
|
||||
style="@style/Theme.Widget.Button.Icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="@string/track"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
app:icon="@drawable/ic_cloud_off_24dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_categories"
|
||||
style="@style/Theme.Widget.Button.Icon.Textless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/action_edit_categories"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_label_24dp"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_share"
|
||||
style="@style/Theme.Widget.Button.Icon.Textless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/action_share"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_share_24dp"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_webview"
|
||||
style="@style/Theme.Widget.Button.Icon.Textless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/action_open_in_web_view"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_public_24dp"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_migrate"
|
||||
style="@style/Theme.Widget.Button.Icon.Textless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/migrate"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/baseline_swap_calls_24"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_smart_search"
|
||||
style="@style/Theme.Widget.Button.Icon.Textless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/eh_merge_with_another_source"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/eh_ic_find_replace_white_24dp"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</LinearLayout>
|
||||
</HorizontalScrollView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_summary_label"
|
||||
style="@style/TextAppearance.Regular.SubHeading"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:text="@string/manga_info_about_label"
|
||||
android:textIsSelectable="false" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_summary"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="match_parent"
|
||||
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" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/manga_genres_tags_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/manga_genres_tags_full_chips"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:visibility="gone"
|
||||
app:chipSpacingHorizontal="4dp" />
|
||||
|
||||
<HorizontalScrollView
|
||||
android:id="@+id/manga_genres_tags_compact"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:requiresFadingEdge="horizontal">
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/manga_genres_tags_compact_chips"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
app:chipSpacingHorizontal="4dp"
|
||||
app:singleLine="true" />
|
||||
|
||||
</HorizontalScrollView>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/manga_info_toggle"
|
||||
style="@style/Theme.Widget.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:text="@string/manga_info_expand"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/merge_btn"
|
||||
style="@style/Theme.Widget.Button.FilledAccent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:text="@string/eh_merge_with_another_source"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/recommend_btn"
|
||||
style="@style/Theme.Widget.Button.FilledAccent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:text="@string/az_recommends"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:clipToPadding="false"
|
||||
android:descendantFocusability="blocksDescendants"
|
||||
android:paddingBottom="@dimen/fab_list_padding"
|
||||
tools:listitem="@layout/chapters_item" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
</FrameLayout>
|
||||
|
||||
</eu.kanade.tachiyomi.widget.ThemedSwipeRefreshLayout>
|
||||
|
||||
|
408
app/src/main/res/layout/manga_all_in_one_header.xml
Normal file
408
app/src/main/res/layout/manga_all_in_one_header.xml
Normal file
@ -0,0 +1,408 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:context=".ui.browse.source.browse.BrowseSourceController">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/guideline2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_percent="0.38" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/backdrop"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:alpha="0.2"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:background="@color/material_grey_700" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/manga_cover"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_margin="16dp"
|
||||
android:background="@drawable/rounded_rectangle"
|
||||
android:contentDescription="@string/description_cover"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintDimensionRatio="h,2:3"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline2"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/manga_info_section"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="0dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@+id/guideline2"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_full_title"
|
||||
style="@style/TextAppearance.Medium.Title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="2"
|
||||
android:paddingBottom="8dp"
|
||||
android:text="@string/manga_info_full_title_label"
|
||||
android:textIsSelectable="false"
|
||||
app:autoSizeMaxTextSize="20sp"
|
||||
app:autoSizeMinTextSize="12sp"
|
||||
app:autoSizeStepGranularity="2sp"
|
||||
app:autoSizeTextType="uniform"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_author_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_author_label"
|
||||
android:textIsSelectable="false"
|
||||
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_full_title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_author"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_author_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_author_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_artist_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_artist_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_author_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_artist"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_artist_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_artist_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_chapters_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_last_chapter_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_artist_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_chapters"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_chapters_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_chapters_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_last_update_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_latest_data_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_chapters_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_last_update"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_last_update_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_last_update_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_status_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_status_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_last_update_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_status"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_status_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_status_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_source_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_source_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_status_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_source"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_source_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_source_label" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<HorizontalScrollView
|
||||
android:id="@+id/actions_bar_scroll_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:requiresFadingEdge="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/actions_bar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_favorite"
|
||||
style="@style/Theme.Widget.Button.Icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/add_to_library"
|
||||
app:icon="@drawable/ic_favorite_border_24dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_tracking"
|
||||
style="@style/Theme.Widget.Button.Icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="@string/track"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
app:icon="@drawable/ic_cloud_off_24dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_categories"
|
||||
style="@style/Theme.Widget.Button.Icon.Textless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/action_edit_categories"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_label_24dp"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_share"
|
||||
style="@style/Theme.Widget.Button.Icon.Textless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/action_share"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_share_24dp"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_webview"
|
||||
style="@style/Theme.Widget.Button.Icon.Textless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/action_open_in_web_view"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_public_24dp"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_migrate"
|
||||
style="@style/Theme.Widget.Button.Icon.Textless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/migrate"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/baseline_swap_calls_24"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_smart_search"
|
||||
style="@style/Theme.Widget.Button.Icon.Textless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/eh_merge_with_another_source"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/eh_ic_find_replace_white_24dp"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</LinearLayout>
|
||||
</HorizontalScrollView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_summary_label"
|
||||
style="@style/TextAppearance.Regular.SubHeading"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:text="@string/manga_info_about_label"
|
||||
android:textIsSelectable="false" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_summary"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="match_parent"
|
||||
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" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/manga_genres_tags_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/manga_genres_tags_full_chips"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:visibility="gone"
|
||||
app:chipSpacingHorizontal="4dp" />
|
||||
|
||||
<HorizontalScrollView
|
||||
android:id="@+id/manga_genres_tags_compact"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:requiresFadingEdge="horizontal">
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/manga_genres_tags_compact_chips"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
app:chipSpacingHorizontal="4dp"
|
||||
app:singleLine="true" />
|
||||
|
||||
</HorizontalScrollView>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/manga_info_toggle"
|
||||
style="@style/Theme.Widget.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:text="@string/manga_info_expand"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/merge_btn"
|
||||
style="@style/Theme.Widget.Button.FilledAccent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:text="@string/eh_merge_with_another_source"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/recommend_btn"
|
||||
style="@style/Theme.Widget.Button.FilledAccent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:text="@string/az_recommends"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</LinearLayout>
|
Reference in New Issue
Block a user