diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/MetadataSource.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/MetadataSource.kt index 3f83de66c..e900180b9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/MetadataSource.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/MetadataSource.kt @@ -1,5 +1,6 @@ package eu.kanade.tachiyomi.source.online +import androidx.compose.runtime.Composable import androidx.recyclerview.widget.RecyclerView import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Chapter @@ -113,6 +114,9 @@ interface MetadataSource : CatalogueSource { fun getDescriptionAdapter(controller: MangaController): RecyclerView.Adapter<*>? + @Composable + fun DescriptionComposable(controller: MangaController) + fun MangaInfo.id() = db.getManga(key, id).executeAsBlocking()?.id val SManga.id get() = (this as? Manga)?.id val SChapter.mangaId get() = (this as? Chapter)?.manga_id diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/EHentai.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/EHentai.kt index 717d7659a..22ba67f4e 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/EHentai.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/EHentai.kt @@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.source.online.all import android.content.Context import android.net.Uri +import androidx.compose.runtime.Composable import androidx.core.net.toUri import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.preference.PreferencesHelper @@ -44,6 +45,7 @@ import exh.metadata.metadata.base.RaisedSearchMetadata.Companion.TAG_TYPE_VIRTUA import exh.metadata.metadata.base.RaisedSearchMetadata.Companion.toGenreString import exh.metadata.metadata.base.RaisedTag import exh.ui.login.EhLoginActivity +import exh.ui.metadata.adapters.EHentaiDescription import exh.ui.metadata.adapters.EHentaiDescriptionAdapter import exh.util.UriFilter import exh.util.UriGroup @@ -1073,6 +1075,11 @@ class EHentai( return EHentaiDescriptionAdapter(controller) } + @Composable + override fun DescriptionComposable(controller: MangaController) { + EHentaiDescription(controller) + } + companion object { private const val TR_SUFFIX = "TR" private const val REVERSE_PARAM = "TEH_REVERSE" diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/Hitomi.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/Hitomi.kt index d73985c25..5b6377934 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/Hitomi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/Hitomi.kt @@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.source.online.all import android.content.Context import android.net.Uri import android.os.Build +import androidx.compose.runtime.Composable import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.toSManga @@ -16,6 +17,7 @@ import exh.metadata.metadata.HitomiSearchMetadata import exh.metadata.metadata.base.RaisedSearchMetadata import exh.metadata.metadata.base.RaisedTag import exh.source.DelegatedHttpSource +import exh.ui.metadata.adapters.HitomiDescription import exh.ui.metadata.adapters.HitomiDescriptionAdapter import exh.util.urlImportFetchSearchManga import org.jsoup.nodes.Document @@ -140,6 +142,11 @@ class Hitomi(delegate: HttpSource, val context: Context) : return HitomiDescriptionAdapter(controller) } + @Composable + override fun DescriptionComposable(controller: MangaController) { + HitomiDescription(controller) + } + companion object { const val otherId = 2703068117101782422L private val DATE_FORMAT by lazy { diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MangaDex.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MangaDex.kt index 36ed09e5b..5ab3d8858 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MangaDex.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MangaDex.kt @@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.source.online.all import android.content.Context import android.content.SharedPreferences import android.net.Uri +import androidx.compose.runtime.Composable import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.track.TrackManager @@ -48,6 +49,7 @@ import exh.md.utils.MdLang import exh.md.utils.MdUtil import exh.metadata.metadata.MangaDexSearchMetadata import exh.source.DelegatedHttpSource +import exh.ui.metadata.adapters.MangaDexDescription import exh.ui.metadata.adapters.MangaDexDescriptionAdapter import okhttp3.OkHttpClient import okhttp3.Response @@ -219,6 +221,11 @@ class MangaDex(delegate: HttpSource, val context: Context) : return MangaDexDescriptionAdapter(controller) } + @Composable + override fun DescriptionComposable(controller: MangaController) { + MangaDexDescription(controller) + } + override suspend fun parseIntoMetadata(metadata: MangaDexSearchMetadata, input: Triple, StatisticsMangaDto>) { apiMangaParser.parseIntoMetadata(metadata, input.first, input.second, input.third) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/NHentai.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/NHentai.kt index 2c35454f7..fcc242640 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/NHentai.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/NHentai.kt @@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.source.online.all import android.content.Context import android.content.SharedPreferences import android.net.Uri +import androidx.compose.runtime.Composable import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.toSManga @@ -15,6 +16,7 @@ import exh.metadata.metadata.NHentaiSearchMetadata import exh.metadata.metadata.base.RaisedSearchMetadata import exh.metadata.metadata.base.RaisedTag import exh.source.DelegatedHttpSource +import exh.ui.metadata.adapters.NHentaiDescription import exh.ui.metadata.adapters.NHentaiDescriptionAdapter import exh.util.trimOrNull import exh.util.urlImportFetchSearchManga @@ -172,6 +174,11 @@ class NHentai(delegate: HttpSource, val context: Context) : return NHentaiDescriptionAdapter(controller) } + @Composable + override fun DescriptionComposable(controller: MangaController) { + NHentaiDescription(controller) + } + companion object { const val otherId = 7309872737163460316L diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/PervEden.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/PervEden.kt index 4b610d79e..c7f195084 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/PervEden.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/PervEden.kt @@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.source.online.all import android.content.Context import android.net.Uri +import androidx.compose.runtime.Composable import androidx.core.net.toUri import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.source.model.FilterList @@ -15,6 +16,7 @@ import exh.metadata.metadata.PervEdenSearchMetadata import exh.metadata.metadata.base.RaisedSearchMetadata import exh.metadata.metadata.base.RaisedTag import exh.source.DelegatedHttpSource +import exh.ui.metadata.adapters.PervEdenDescription import exh.ui.metadata.adapters.PervEdenDescriptionAdapter import exh.util.urlImportFetchSearchManga import org.jsoup.nodes.Document @@ -136,4 +138,9 @@ class PervEden(delegate: HttpSource, val context: Context) : override fun getDescriptionAdapter(controller: MangaController): PervEdenDescriptionAdapter { return PervEdenDescriptionAdapter(controller) } + + @Composable + override fun DescriptionComposable(controller: MangaController) { + PervEdenDescription(controller) + } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/EightMuses.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/EightMuses.kt index c753cb411..443facffb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/EightMuses.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/EightMuses.kt @@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.source.online.english import android.content.Context import android.net.Uri +import androidx.compose.runtime.Composable import androidx.core.net.toUri import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.source.model.FilterList @@ -15,6 +16,7 @@ import eu.kanade.tachiyomi.util.asJsoup import exh.metadata.metadata.EightMusesSearchMetadata import exh.metadata.metadata.base.RaisedTag import exh.source.DelegatedHttpSource +import exh.ui.metadata.adapters.EightMusesDescription import exh.ui.metadata.adapters.EightMusesDescriptionAdapter import exh.util.urlImportFetchSearchManga import org.jsoup.nodes.Document @@ -100,4 +102,9 @@ class EightMuses(delegate: HttpSource, val context: Context) : override fun getDescriptionAdapter(controller: MangaController): EightMusesDescriptionAdapter { return EightMusesDescriptionAdapter(controller) } + + @Composable + override fun DescriptionComposable(controller: MangaController) { + EightMusesDescription(controller) + } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/HBrowse.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/HBrowse.kt index 1e8cd8621..8e6259d4e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/HBrowse.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/HBrowse.kt @@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.source.online.english import android.content.Context import android.net.Uri +import androidx.compose.runtime.Composable import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.toSManga @@ -14,6 +15,7 @@ import eu.kanade.tachiyomi.util.asJsoup import exh.metadata.metadata.HBrowseSearchMetadata import exh.metadata.metadata.base.RaisedTag import exh.source.DelegatedHttpSource +import exh.ui.metadata.adapters.HBrowseDescription import exh.ui.metadata.adapters.HBrowseDescriptionAdapter import exh.util.urlImportFetchSearchManga import org.jsoup.nodes.Document @@ -88,4 +90,9 @@ class HBrowse(delegate: HttpSource, val context: Context) : override fun getDescriptionAdapter(controller: MangaController): HBrowseDescriptionAdapter { return HBrowseDescriptionAdapter(controller) } + + @Composable + override fun DescriptionComposable(controller: MangaController) { + HBrowseDescription(controller) + } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Pururin.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Pururin.kt index 46807a8f2..12797cd82 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Pururin.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Pururin.kt @@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.source.online.english import android.content.Context import android.net.Uri +import androidx.compose.runtime.Composable import androidx.core.net.toUri import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.source.model.FilterList @@ -17,6 +18,7 @@ import exh.metadata.metadata.PururinSearchMetadata import exh.metadata.metadata.base.RaisedSearchMetadata import exh.metadata.metadata.base.RaisedTag import exh.source.DelegatedHttpSource +import exh.ui.metadata.adapters.PururinDescription import exh.ui.metadata.adapters.PururinDescriptionAdapter import exh.util.dropBlank import exh.util.trimAll @@ -118,4 +120,9 @@ class Pururin(delegate: HttpSource, val context: Context) : override fun getDescriptionAdapter(controller: MangaController): PururinDescriptionAdapter { return PururinDescriptionAdapter(controller) } + + @Composable + override fun DescriptionComposable(controller: MangaController) { + PururinDescription(controller) + } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Tsumino.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Tsumino.kt index 6f611c1ce..07cc12f3c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Tsumino.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Tsumino.kt @@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.source.online.english import android.content.Context import android.net.Uri +import androidx.compose.runtime.Composable import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.MangasPage @@ -17,6 +18,7 @@ import exh.metadata.metadata.TsuminoSearchMetadata.Companion.TAG_TYPE_DEFAULT import exh.metadata.metadata.base.RaisedSearchMetadata.Companion.TAG_TYPE_VIRTUAL import exh.metadata.metadata.base.RaisedTag import exh.source.DelegatedHttpSource +import exh.ui.metadata.adapters.TsuminoDescription import exh.ui.metadata.adapters.TsuminoDescriptionAdapter import exh.util.dropBlank import exh.util.trimAll @@ -145,4 +147,9 @@ class Tsumino(delegate: HttpSource, val context: Context) : override fun getDescriptionAdapter(controller: MangaController): TsuminoDescriptionAdapter { return TsuminoDescriptionAdapter(controller) } + + @Composable + override fun DescriptionComposable(controller: MangaController) { + TsuminoDescription(controller) + } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt index 7d87efad0..beb054980 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt @@ -66,6 +66,7 @@ import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.supervisorScope @@ -146,7 +147,7 @@ class MangaPresenter( data class EXHRedirect(val manga: Manga, val update: Boolean) - var meta: RaisedSearchMetadata? = null + val meta: MutableStateFlow = MutableStateFlow(null) var mergedManga = emptyMap() private set @@ -191,7 +192,7 @@ class MangaPresenter( val meta = if (mainSource != null) { flatMetadata?.raise(mainSource.metaClass) } else null - this.meta = meta + this.meta.value = meta // SY <-- view.onNextMangaInfo(manga, source, meta) },) @@ -394,7 +395,7 @@ class MangaPresenter( .observeOn(AndroidSchedulers.mainThread()) .subscribeLatestCache( { view, _ -> - view.onNextMangaInfo(manga, source, meta) + view.onNextMangaInfo(manga, source, meta.value) }, ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt index e545e8271..81b218224 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt @@ -48,7 +48,7 @@ class MangaInfoHeaderAdapter( private var source: Source = controller.presenter.source // SY --> - private var meta: RaisedSearchMetadata? = controller.presenter.meta + private var meta: RaisedSearchMetadata? = controller.presenter.meta.value private var mergedMangaReferences: List = controller.presenter.mergedMangaReferences // SY <-- diff --git a/app/src/main/java/exh/ui/metadata/adapters/EHentaiDescriptionAdapter.kt b/app/src/main/java/exh/ui/metadata/adapters/EHentaiDescriptionAdapter.kt index 7bd5cd7b4..4bacfd735 100644 --- a/app/src/main/java/exh/ui/metadata/adapters/EHentaiDescriptionAdapter.kt +++ b/app/src/main/java/exh/ui/metadata/adapters/EHentaiDescriptionAdapter.kt @@ -4,6 +4,11 @@ import android.annotation.SuppressLint import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.viewinterop.AndroidView import androidx.recyclerview.widget.RecyclerView import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.databinding.DescriptionAdapterEhBinding @@ -13,6 +18,7 @@ import eu.kanade.tachiyomi.util.system.copyToClipboard import exh.metadata.MetadataUtil import exh.metadata.bindDrawable import exh.metadata.metadata.EHentaiSearchMetadata +import exh.metadata.metadata.base.RaisedSearchMetadata import exh.ui.metadata.MetadataViewController class EHentaiDescriptionAdapter( @@ -35,7 +41,7 @@ class EHentaiDescriptionAdapter( inner class EHentaiDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) { fun bind() { - val meta = controller.presenter.meta + val meta = controller.presenter.meta.value if (meta == null || meta !is EHentaiSearchMetadata) return binding.genre.text = @@ -107,3 +113,90 @@ class EHentaiDescriptionAdapter( } } } + +@Composable +fun EHentaiDescription(controller: MangaController) { + val meta by controller.presenter.meta.collectAsState() + EHentaiDescription(controller = controller, meta = meta) +} + +@Composable +private fun EHentaiDescription(controller: MangaController, meta: RaisedSearchMetadata?) { + val context = LocalContext.current + AndroidView( + factory = { factoryContext -> + DescriptionAdapterEhBinding.inflate(LayoutInflater.from(factoryContext)).root + }, + update = { + if (meta == null || meta !is EHentaiSearchMetadata) return@AndroidView + val binding = DescriptionAdapterEhBinding.bind(it) + + binding.genre.text = + meta.genre?.let { MetadataUtil.getGenreAndColour(context, it) } + ?.let { + binding.genre.setBackgroundColor(it.first) + it.second + } + ?: meta.genre + ?: context.getString(R.string.unknown) + + binding.visible.text = context.getString(R.string.is_visible, meta.visible ?: context.getString(R.string.unknown)) + + binding.favorites.text = (meta.favorites ?: 0).toString() + binding.favorites.bindDrawable(context, R.drawable.ic_book_24dp) + + binding.uploader.text = meta.uploader ?: context.getString(R.string.unknown) + + binding.size.text = MetadataUtil.humanReadableByteCount(meta.size ?: 0, true) + binding.size.bindDrawable(context, R.drawable.ic_outline_sd_card_24) + + val length = meta.length ?: 0 + binding.pages.text = context.resources.getQuantityString(R.plurals.num_pages, length, length) + binding.pages.bindDrawable(context, R.drawable.ic_baseline_menu_book_24) + + val language = meta.language ?: context.getString(R.string.unknown) + binding.language.text = if (meta.translated == true) { + context.getString(R.string.language_translated, language) + } else { + language + } + + val ratingFloat = meta.averageRating?.toFloat() + binding.ratingBar.rating = ratingFloat ?: 0F + @SuppressLint("SetTextI18n") + binding.rating.text = (ratingFloat ?: 0F).toString() + " - " + MetadataUtil.getRatingString(context, ratingFloat?.times(2)) + + binding.moreInfo.bindDrawable(context, R.drawable.ic_info_24dp) + + listOf( + binding.favorites, + binding.genre, + binding.language, + binding.pages, + binding.rating, + binding.uploader, + binding.visible, + ).forEach { textView -> + textView.setOnLongClickListener { + context.copyToClipboard( + textView.text.toString(), + textView.text.toString(), + ) + true + } + } + + binding.uploader.setOnClickListener { + meta.uploader?.let { controller.performSearch("uploader:\"$it\"") } + } + + binding.moreInfo.setOnClickListener { + controller.router?.pushController( + MetadataViewController( + controller.manga, + ), + ) + } + }, + ) +} diff --git a/app/src/main/java/exh/ui/metadata/adapters/EightMusesDescriptionAdapter.kt b/app/src/main/java/exh/ui/metadata/adapters/EightMusesDescriptionAdapter.kt index 273eff9d0..0f87c3e51 100644 --- a/app/src/main/java/exh/ui/metadata/adapters/EightMusesDescriptionAdapter.kt +++ b/app/src/main/java/exh/ui/metadata/adapters/EightMusesDescriptionAdapter.kt @@ -3,6 +3,11 @@ package exh.ui.metadata.adapters import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.viewinterop.AndroidView import androidx.recyclerview.widget.RecyclerView import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.databinding.DescriptionAdapter8mBinding @@ -11,6 +16,7 @@ import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.util.system.copyToClipboard import exh.metadata.bindDrawable import exh.metadata.metadata.EightMusesSearchMetadata +import exh.metadata.metadata.base.RaisedSearchMetadata import exh.ui.metadata.MetadataViewController class EightMusesDescriptionAdapter( @@ -33,7 +39,7 @@ class EightMusesDescriptionAdapter( inner class EightMusesDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) { fun bind() { - val meta = controller.presenter.meta + val meta = controller.presenter.meta.value if (meta == null || meta !is EightMusesSearchMetadata) return binding.title.text = meta.title ?: itemView.context.getString(R.string.unknown) @@ -58,3 +64,43 @@ class EightMusesDescriptionAdapter( } } } + +@Composable +fun EightMusesDescription(controller: MangaController) { + val meta by controller.presenter.meta.collectAsState() + EightMusesDescription(controller = controller, meta = meta) +} + +@Composable +private fun EightMusesDescription(controller: MangaController, meta: RaisedSearchMetadata?) { + val context = LocalContext.current + AndroidView( + factory = { factoryContext -> + DescriptionAdapter8mBinding.inflate(LayoutInflater.from(factoryContext)).root + }, + update = { + if (meta == null || meta !is EightMusesSearchMetadata) return@AndroidView + val binding = DescriptionAdapter8mBinding.bind(it) + + binding.title.text = meta.title ?: context.getString(R.string.unknown) + + binding.moreInfo.bindDrawable(context, R.drawable.ic_info_24dp) + + binding.title.setOnLongClickListener { + context.copyToClipboard( + binding.title.text.toString(), + binding.title.text.toString(), + ) + true + } + + binding.moreInfo.setOnClickListener { + controller.router?.pushController( + MetadataViewController( + controller.manga, + ), + ) + } + }, + ) +} diff --git a/app/src/main/java/exh/ui/metadata/adapters/HBrowseDescriptionAdapter.kt b/app/src/main/java/exh/ui/metadata/adapters/HBrowseDescriptionAdapter.kt index 08c726ef8..3a435b9ff 100644 --- a/app/src/main/java/exh/ui/metadata/adapters/HBrowseDescriptionAdapter.kt +++ b/app/src/main/java/exh/ui/metadata/adapters/HBrowseDescriptionAdapter.kt @@ -3,6 +3,11 @@ package exh.ui.metadata.adapters import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.viewinterop.AndroidView import androidx.recyclerview.widget.RecyclerView import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.databinding.DescriptionAdapterHbBinding @@ -11,6 +16,7 @@ import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.util.system.copyToClipboard import exh.metadata.bindDrawable import exh.metadata.metadata.HBrowseSearchMetadata +import exh.metadata.metadata.base.RaisedSearchMetadata import exh.ui.metadata.MetadataViewController class HBrowseDescriptionAdapter( @@ -33,7 +39,7 @@ class HBrowseDescriptionAdapter( inner class HBrowseDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) { fun bind() { - val meta = controller.presenter.meta + val meta = controller.presenter.meta.value if (meta == null || meta !is HBrowseSearchMetadata) return binding.pages.text = itemView.resources.getQuantityString(R.plurals.num_pages, meta.length ?: 0, meta.length ?: 0) @@ -59,3 +65,44 @@ class HBrowseDescriptionAdapter( } } } + +@Composable +fun HBrowseDescription(controller: MangaController) { + val meta by controller.presenter.meta.collectAsState() + HBrowseDescription(controller = controller, meta = meta) +} + +@Composable +private fun HBrowseDescription(controller: MangaController, meta: RaisedSearchMetadata?) { + val context = LocalContext.current + AndroidView( + factory = { factoryContext -> + DescriptionAdapterHbBinding.inflate(LayoutInflater.from(factoryContext)).root + }, + update = { + if (meta == null || meta !is HBrowseSearchMetadata) return@AndroidView + val binding = DescriptionAdapterHbBinding.bind(it) + + binding.pages.text = context.resources.getQuantityString(R.plurals.num_pages, meta.length ?: 0, meta.length ?: 0) + binding.pages.bindDrawable(context, R.drawable.ic_baseline_menu_book_24) + + binding.moreInfo.bindDrawable(context, R.drawable.ic_info_24dp) + + binding.pages.setOnLongClickListener { + context.copyToClipboard( + binding.pages.text.toString(), + binding.pages.text.toString(), + ) + true + } + + binding.moreInfo.setOnClickListener { + controller.router?.pushController( + MetadataViewController( + controller.manga, + ), + ) + } + }, + ) +} diff --git a/app/src/main/java/exh/ui/metadata/adapters/HitomiDescriptionAdapter.kt b/app/src/main/java/exh/ui/metadata/adapters/HitomiDescriptionAdapter.kt index a9ac3202f..235c653ba 100644 --- a/app/src/main/java/exh/ui/metadata/adapters/HitomiDescriptionAdapter.kt +++ b/app/src/main/java/exh/ui/metadata/adapters/HitomiDescriptionAdapter.kt @@ -3,6 +3,11 @@ package exh.ui.metadata.adapters import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.viewinterop.AndroidView import androidx.recyclerview.widget.RecyclerView import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.databinding.DescriptionAdapterHiBinding @@ -12,6 +17,7 @@ import eu.kanade.tachiyomi.util.system.copyToClipboard import exh.metadata.MetadataUtil import exh.metadata.bindDrawable import exh.metadata.metadata.HitomiSearchMetadata +import exh.metadata.metadata.base.RaisedSearchMetadata import exh.ui.metadata.MetadataViewController import java.util.Date @@ -35,7 +41,7 @@ class HitomiDescriptionAdapter( inner class HitomiDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) { fun bind() { - val meta = controller.presenter.meta + val meta = controller.presenter.meta.value if (meta == null || meta !is HitomiSearchMetadata) return binding.genre.text = meta.genre?.let { MetadataUtil.getGenreAndColour(itemView.context, it) }?.let { @@ -72,3 +78,55 @@ class HitomiDescriptionAdapter( } } } + +@Composable +fun HitomiDescription(controller: MangaController) { + val meta by controller.presenter.meta.collectAsState() + HitomiDescription(controller = controller, meta = meta) +} + +@Composable +private fun HitomiDescription(controller: MangaController, meta: RaisedSearchMetadata?) { + val context = LocalContext.current + AndroidView( + factory = { factoryContext -> + DescriptionAdapterHiBinding.inflate(LayoutInflater.from(factoryContext)).root + }, + update = { + if (meta == null || meta !is HitomiSearchMetadata) return@AndroidView + val binding = DescriptionAdapterHiBinding.bind(it) + + binding.genre.text = meta.genre?.let { MetadataUtil.getGenreAndColour(context, it) }?.let { + binding.genre.setBackgroundColor(it.first) + it.second + } ?: meta.genre ?: context.getString(R.string.unknown) + + binding.whenPosted.text = MetadataUtil.EX_DATE_FORMAT.format(Date(meta.uploadDate ?: 0)) + binding.language.text = meta.language ?: context.getString(R.string.unknown) + + binding.moreInfo.bindDrawable(context, R.drawable.ic_info_24dp) + + listOf( + binding.genre, + binding.language, + binding.whenPosted, + ).forEach { textView -> + textView.setOnLongClickListener { + context.copyToClipboard( + textView.text.toString(), + textView.text.toString(), + ) + true + } + } + + binding.moreInfo.setOnClickListener { + controller.router?.pushController( + MetadataViewController( + controller.manga, + ), + ) + } + }, + ) +} diff --git a/app/src/main/java/exh/ui/metadata/adapters/MangaDexDescriptionAdapter.kt b/app/src/main/java/exh/ui/metadata/adapters/MangaDexDescriptionAdapter.kt index 9bd6f2482..3b49b30c0 100644 --- a/app/src/main/java/exh/ui/metadata/adapters/MangaDexDescriptionAdapter.kt +++ b/app/src/main/java/exh/ui/metadata/adapters/MangaDexDescriptionAdapter.kt @@ -4,6 +4,11 @@ import android.annotation.SuppressLint import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.viewinterop.AndroidView import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView import eu.kanade.tachiyomi.R @@ -14,6 +19,7 @@ import eu.kanade.tachiyomi.util.system.copyToClipboard import exh.metadata.MetadataUtil.getRatingString import exh.metadata.bindDrawable import exh.metadata.metadata.MangaDexSearchMetadata +import exh.metadata.metadata.base.RaisedSearchMetadata import exh.ui.metadata.MetadataViewController import kotlin.math.round @@ -38,7 +44,7 @@ class MangaDexDescriptionAdapter( inner class MangaDexDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) { fun bind() { - val meta = controller.presenter.meta + val meta = controller.presenter.meta.value if (meta == null || meta !is MangaDexSearchMetadata) return // todo @@ -69,3 +75,49 @@ class MangaDexDescriptionAdapter( } } } + +@Composable +fun MangaDexDescription(controller: MangaController) { + val meta by controller.presenter.meta.collectAsState() + MangaDexDescription(controller = controller, meta = meta) +} + +@Composable +private fun MangaDexDescription(controller: MangaController, meta: RaisedSearchMetadata?) { + val context = LocalContext.current + AndroidView( + factory = { factoryContext -> + DescriptionAdapterMdBinding.inflate(LayoutInflater.from(factoryContext)).root + }, + update = { + if (meta == null || meta !is MangaDexSearchMetadata) return@AndroidView + val binding = DescriptionAdapterMdBinding.bind(it) + + // todo + val ratingFloat = meta.rating + binding.ratingBar.rating = ratingFloat?.div(2F) ?: 0F + @SuppressLint("SetTextI18n") + binding.rating.text = (round((ratingFloat ?: 0F) * 100.0) / 100.0).toString() + " - " + getRatingString(context, ratingFloat) + binding.rating.isVisible = ratingFloat != null + binding.ratingBar.isVisible = ratingFloat != null + + binding.moreInfo.bindDrawable(context, R.drawable.ic_info_24dp) + + binding.rating.setOnLongClickListener { + context.copyToClipboard( + binding.rating.text.toString(), + binding.rating.text.toString(), + ) + true + } + + binding.moreInfo.setOnClickListener { + controller.router?.pushController( + MetadataViewController( + controller.manga, + ), + ) + } + }, + ) +} diff --git a/app/src/main/java/exh/ui/metadata/adapters/NHentaiDescriptionAdapter.kt b/app/src/main/java/exh/ui/metadata/adapters/NHentaiDescriptionAdapter.kt index c93476bad..b35b0a507 100644 --- a/app/src/main/java/exh/ui/metadata/adapters/NHentaiDescriptionAdapter.kt +++ b/app/src/main/java/exh/ui/metadata/adapters/NHentaiDescriptionAdapter.kt @@ -4,6 +4,11 @@ import android.annotation.SuppressLint import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.viewinterop.AndroidView import androidx.recyclerview.widget.RecyclerView import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.databinding.DescriptionAdapterNhBinding @@ -13,6 +18,7 @@ import eu.kanade.tachiyomi.util.system.copyToClipboard import exh.metadata.MetadataUtil import exh.metadata.bindDrawable import exh.metadata.metadata.NHentaiSearchMetadata +import exh.metadata.metadata.base.RaisedSearchMetadata import exh.ui.metadata.MetadataViewController import java.util.Date @@ -37,7 +43,7 @@ class NHentaiDescriptionAdapter( inner class NHentaiDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) { fun bind() { - val meta = controller.presenter.meta + val meta = controller.presenter.meta.value if (meta == null || meta !is NHentaiSearchMetadata) return binding.genre.text = meta.tags.filter { it.namespace == NHentaiSearchMetadata.NHENTAI_CATEGORIES_NAMESPACE }.let { tags -> @@ -91,3 +97,72 @@ class NHentaiDescriptionAdapter( } } } + +@Composable +fun NHentaiDescription(controller: MangaController) { + val meta by controller.presenter.meta.collectAsState() + NHentaiDescription(controller = controller, meta = meta) +} + +@Composable +private fun NHentaiDescription(controller: MangaController, meta: RaisedSearchMetadata?) { + val context = LocalContext.current + AndroidView( + factory = { factoryContext -> + DescriptionAdapterNhBinding.inflate(LayoutInflater.from(factoryContext)).root + }, + update = { + if (meta == null || meta !is NHentaiSearchMetadata) return@AndroidView + val binding = DescriptionAdapterNhBinding.bind(it) + + binding.genre.text = meta.tags.filter { it.namespace == NHentaiSearchMetadata.NHENTAI_CATEGORIES_NAMESPACE }.let { tags -> + if (tags.isNotEmpty()) tags.joinToString(transform = { it.name }) else null + }.let { categoriesString -> + categoriesString?.let { MetadataUtil.getGenreAndColour(context, it) }?.let { + binding.genre.setBackgroundColor(it.first) + it.second + } ?: categoriesString ?: context.getString(R.string.unknown) + } + + meta.favoritesCount?.let { + if (it == 0L) return@let + binding.favorites.text = it.toString() + binding.favorites.bindDrawable(context, R.drawable.ic_book_24dp) + } + + binding.whenPosted.text = MetadataUtil.EX_DATE_FORMAT.format(Date((meta.uploadDate ?: 0) * 1000)) + + binding.pages.text = context.resources.getQuantityString(R.plurals.num_pages, meta.pageImageTypes.size, meta.pageImageTypes.size) + binding.pages.bindDrawable(context, R.drawable.ic_baseline_menu_book_24) + + @SuppressLint("SetTextI18n") + binding.id.text = "#" + (meta.nhId ?: 0) + + binding.moreInfo.bindDrawable(context, R.drawable.ic_info_24dp) + + listOf( + binding.favorites, + binding.genre, + binding.id, + binding.pages, + binding.whenPosted, + ).forEach { textView -> + textView.setOnLongClickListener { + context.copyToClipboard( + textView.text.toString(), + textView.text.toString(), + ) + true + } + } + + binding.moreInfo.setOnClickListener { + controller.router?.pushController( + MetadataViewController( + controller.manga, + ), + ) + } + }, + ) +} diff --git a/app/src/main/java/exh/ui/metadata/adapters/PervEdenDescriptionAdapter.kt b/app/src/main/java/exh/ui/metadata/adapters/PervEdenDescriptionAdapter.kt index cd0d90a92..6da17c7ad 100644 --- a/app/src/main/java/exh/ui/metadata/adapters/PervEdenDescriptionAdapter.kt +++ b/app/src/main/java/exh/ui/metadata/adapters/PervEdenDescriptionAdapter.kt @@ -4,6 +4,11 @@ import android.annotation.SuppressLint import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.viewinterop.AndroidView import androidx.recyclerview.widget.RecyclerView import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.databinding.DescriptionAdapterPeBinding @@ -13,6 +18,7 @@ import eu.kanade.tachiyomi.util.system.copyToClipboard import exh.metadata.MetadataUtil import exh.metadata.bindDrawable import exh.metadata.metadata.PervEdenSearchMetadata +import exh.metadata.metadata.base.RaisedSearchMetadata import exh.ui.metadata.MetadataViewController import java.util.Locale import kotlin.math.round @@ -37,7 +43,7 @@ class PervEdenDescriptionAdapter( inner class PervEdenDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) { fun bind() { - val meta = controller.presenter.meta + val meta = controller.presenter.meta.value if (meta == null || meta !is PervEdenSearchMetadata) return binding.genre.text = meta.genre?.let { MetadataUtil.getGenreAndColour(itemView.context, it) }?.let { @@ -81,3 +87,62 @@ class PervEdenDescriptionAdapter( } } } + +@Composable +fun PervEdenDescription(controller: MangaController) { + val meta by controller.presenter.meta.collectAsState() + PervEdenDescription(controller = controller, meta = meta) +} + +@Composable +private fun PervEdenDescription(controller: MangaController, meta: RaisedSearchMetadata?) { + val context = LocalContext.current + AndroidView( + factory = { factoryContext -> + DescriptionAdapterPeBinding.inflate(LayoutInflater.from(factoryContext)).root + }, + update = { + if (meta == null || meta !is PervEdenSearchMetadata) return@AndroidView + val binding = DescriptionAdapterPeBinding.bind(it) + + binding.genre.text = meta.genre?.let { MetadataUtil.getGenreAndColour(context, it) }?.let { + binding.genre.setBackgroundColor(it.first) + it.second + } ?: meta.genre ?: context.getString(R.string.unknown) + + val language = meta.lang + binding.language.text = if (language != null) { + val local = Locale(language) + local.displayName + } else context.getString(R.string.unknown) + + binding.ratingBar.rating = meta.rating ?: 0F + @SuppressLint("SetTextI18n") + binding.rating.text = (round((meta.rating ?: 0F) * 100.0) / 100.0).toString() + " - " + MetadataUtil.getRatingString(context, meta.rating?.times(2)) + + binding.moreInfo.bindDrawable(context, R.drawable.ic_info_24dp) + + listOf( + binding.genre, + binding.language, + binding.rating, + ).forEach { textView -> + textView.setOnLongClickListener { + context.copyToClipboard( + textView.text.toString(), + textView.text.toString(), + ) + true + } + } + + binding.moreInfo.setOnClickListener { + controller.router?.pushController( + MetadataViewController( + controller.manga, + ), + ) + } + }, + ) +} diff --git a/app/src/main/java/exh/ui/metadata/adapters/PururinDescriptionAdapter.kt b/app/src/main/java/exh/ui/metadata/adapters/PururinDescriptionAdapter.kt index 8cc4d4bdf..0a6837517 100644 --- a/app/src/main/java/exh/ui/metadata/adapters/PururinDescriptionAdapter.kt +++ b/app/src/main/java/exh/ui/metadata/adapters/PururinDescriptionAdapter.kt @@ -4,6 +4,11 @@ import android.annotation.SuppressLint import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.viewinterop.AndroidView import androidx.recyclerview.widget.RecyclerView import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.databinding.DescriptionAdapterPuBinding @@ -13,6 +18,7 @@ import eu.kanade.tachiyomi.util.system.copyToClipboard import exh.metadata.MetadataUtil import exh.metadata.bindDrawable import exh.metadata.metadata.PururinSearchMetadata +import exh.metadata.metadata.base.RaisedSearchMetadata import exh.ui.metadata.MetadataViewController import kotlin.math.round @@ -36,7 +42,7 @@ class PururinDescriptionAdapter( inner class PururinDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) { fun bind() { - val meta = controller.presenter.meta + val meta = controller.presenter.meta.value if (meta == null || meta !is PururinSearchMetadata) return binding.genre.text = meta.tags.find { it.namespace == PururinSearchMetadata.TAG_NAMESPACE_CATEGORY }.let { genre -> @@ -87,3 +93,69 @@ class PururinDescriptionAdapter( } } } + +@Composable +fun PururinDescription(controller: MangaController) { + val meta by controller.presenter.meta.collectAsState() + PururinDescription(controller = controller, meta = meta) +} + +@Composable +private fun PururinDescription(controller: MangaController, meta: RaisedSearchMetadata?) { + val context = LocalContext.current + AndroidView( + factory = { factoryContext -> + DescriptionAdapterPuBinding.inflate(LayoutInflater.from(factoryContext)).root + }, + update = { + if (meta == null || meta !is PururinSearchMetadata) return@AndroidView + val binding = DescriptionAdapterPuBinding.bind(it) + + binding.genre.text = meta.tags.find { it.namespace == PururinSearchMetadata.TAG_NAMESPACE_CATEGORY }.let { genre -> + genre?.let { MetadataUtil.getGenreAndColour(context, it.name) }?.let { + binding.genre.setBackgroundColor(it.first) + it.second + } ?: genre?.name ?: context.getString(R.string.unknown) + } + + binding.uploader.text = meta.uploaderDisp ?: meta.uploader.orEmpty() + + binding.size.text = meta.fileSize ?: context.getString(R.string.unknown) + binding.size.bindDrawable(context, R.drawable.ic_outline_sd_card_24) + + binding.pages.text = context.resources.getQuantityString(R.plurals.num_pages, meta.pages ?: 0, meta.pages ?: 0) + binding.pages.bindDrawable(context, R.drawable.ic_baseline_menu_book_24) + + val ratingFloat = meta.averageRating?.toFloat() + binding.ratingBar.rating = ratingFloat ?: 0F + @SuppressLint("SetTextI18n") + binding.rating.text = (round((ratingFloat ?: 0F) * 100.0) / 100.0).toString() + " - " + MetadataUtil.getRatingString(context, ratingFloat?.times(2)) + + binding.moreInfo.bindDrawable(context, R.drawable.ic_info_24dp) + + listOf( + binding.genre, + binding.pages, + binding.rating, + binding.size, + binding.uploader, + ).forEach { textView -> + textView.setOnLongClickListener { + context.copyToClipboard( + textView.text.toString(), + textView.text.toString(), + ) + true + } + } + + binding.moreInfo.setOnClickListener { + controller.router?.pushController( + MetadataViewController( + controller.manga, + ), + ) + } + }, + ) +} diff --git a/app/src/main/java/exh/ui/metadata/adapters/TsuminoDescriptionAdapter.kt b/app/src/main/java/exh/ui/metadata/adapters/TsuminoDescriptionAdapter.kt index caa59e428..e3b8506b6 100644 --- a/app/src/main/java/exh/ui/metadata/adapters/TsuminoDescriptionAdapter.kt +++ b/app/src/main/java/exh/ui/metadata/adapters/TsuminoDescriptionAdapter.kt @@ -4,6 +4,11 @@ import android.annotation.SuppressLint import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.viewinterop.AndroidView import androidx.recyclerview.widget.RecyclerView import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.databinding.DescriptionAdapterTsBinding @@ -13,6 +18,7 @@ import eu.kanade.tachiyomi.util.system.copyToClipboard import exh.metadata.MetadataUtil import exh.metadata.bindDrawable import exh.metadata.metadata.TsuminoSearchMetadata +import exh.metadata.metadata.base.RaisedSearchMetadata import exh.ui.metadata.MetadataViewController import java.util.Date import kotlin.math.round @@ -37,7 +43,7 @@ class TsuminoDescriptionAdapter( inner class TsuminoDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) { fun bind() { - val meta = controller.presenter.meta + val meta = controller.presenter.meta.value if (meta == null || meta !is TsuminoSearchMetadata) return binding.genre.text = meta.category?.let { MetadataUtil.getGenreAndColour(itemView.context, it) }?.let { @@ -88,3 +94,69 @@ class TsuminoDescriptionAdapter( } } } + +@Composable +fun TsuminoDescription(controller: MangaController) { + val meta by controller.presenter.meta.collectAsState() + TsuminoDescription(controller = controller, meta = meta) +} + +@Composable +private fun TsuminoDescription(controller: MangaController, meta: RaisedSearchMetadata?) { + val context = LocalContext.current + AndroidView( + factory = { factoryContext -> + DescriptionAdapterTsBinding.inflate(LayoutInflater.from(factoryContext)).root + }, + update = { + if (meta == null || meta !is TsuminoSearchMetadata) return@AndroidView + val binding = DescriptionAdapterTsBinding.bind(it) + + binding.genre.text = meta.category?.let { MetadataUtil.getGenreAndColour(context, it) }?.let { + binding.genre.setBackgroundColor(it.first) + it.second + } ?: meta.category ?: context.getString(R.string.unknown) + + binding.favorites.text = (meta.favorites ?: 0).toString() + binding.favorites.bindDrawable(context, R.drawable.ic_book_24dp) + + binding.whenPosted.text = TsuminoSearchMetadata.TSUMINO_DATE_FORMAT.format(Date(meta.uploadDate ?: 0)) + + binding.uploader.text = meta.uploader ?: context.getString(R.string.unknown) + + binding.pages.text = context.resources.getQuantityString(R.plurals.num_pages, meta.length ?: 0, meta.length ?: 0) + binding.pages.bindDrawable(context, R.drawable.ic_baseline_menu_book_24) + + binding.ratingBar.rating = meta.averageRating ?: 0F + @SuppressLint("SetTextI18n") + binding.rating.text = (round((meta.averageRating ?: 0F) * 100.0) / 100.0).toString() + " - " + MetadataUtil.getRatingString(context, meta.averageRating?.times(2)) + + binding.moreInfo.bindDrawable(context, R.drawable.ic_info_24dp) + + listOf( + binding.favorites, + binding.genre, + binding.pages, + binding.rating, + binding.uploader, + binding.whenPosted, + ).forEach { textView -> + textView.setOnLongClickListener { + context.copyToClipboard( + textView.text.toString(), + textView.text.toString(), + ) + true + } + } + + binding.moreInfo.setOnClickListener { + controller.router?.pushController( + MetadataViewController( + controller.manga, + ), + ) + } + }, + ) +}