Start preparing for Manga Info Compose

This commit is contained in:
Jobobby04 2022-06-04 14:08:39 -04:00
parent fef7808bb4
commit 706315625e
21 changed files with 661 additions and 13 deletions

View File

@ -1,5 +1,6 @@
package eu.kanade.tachiyomi.source.online package eu.kanade.tachiyomi.source.online
import androidx.compose.runtime.Composable
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
@ -113,6 +114,9 @@ interface MetadataSource<M : RaisedSearchMetadata, I> : CatalogueSource {
fun getDescriptionAdapter(controller: MangaController): RecyclerView.Adapter<*>? fun getDescriptionAdapter(controller: MangaController): RecyclerView.Adapter<*>?
@Composable
fun DescriptionComposable(controller: MangaController)
fun MangaInfo.id() = db.getManga(key, id).executeAsBlocking()?.id fun MangaInfo.id() = db.getManga(key, id).executeAsBlocking()?.id
val SManga.id get() = (this as? Manga)?.id val SManga.id get() = (this as? Manga)?.id
val SChapter.mangaId get() = (this as? Chapter)?.manga_id val SChapter.mangaId get() = (this as? Chapter)?.manga_id

View File

@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.source.online.all
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import androidx.compose.runtime.Composable
import androidx.core.net.toUri import androidx.core.net.toUri
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.preference.PreferencesHelper 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.RaisedSearchMetadata.Companion.toGenreString
import exh.metadata.metadata.base.RaisedTag import exh.metadata.metadata.base.RaisedTag
import exh.ui.login.EhLoginActivity import exh.ui.login.EhLoginActivity
import exh.ui.metadata.adapters.EHentaiDescription
import exh.ui.metadata.adapters.EHentaiDescriptionAdapter import exh.ui.metadata.adapters.EHentaiDescriptionAdapter
import exh.util.UriFilter import exh.util.UriFilter
import exh.util.UriGroup import exh.util.UriGroup
@ -1073,6 +1075,11 @@ class EHentai(
return EHentaiDescriptionAdapter(controller) return EHentaiDescriptionAdapter(controller)
} }
@Composable
override fun DescriptionComposable(controller: MangaController) {
EHentaiDescription(controller)
}
companion object { companion object {
private const val TR_SUFFIX = "TR" private const val TR_SUFFIX = "TR"
private const val REVERSE_PARAM = "TEH_REVERSE" private const val REVERSE_PARAM = "TEH_REVERSE"

View File

@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.source.online.all
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import androidx.compose.runtime.Composable
import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.toSManga 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.RaisedSearchMetadata
import exh.metadata.metadata.base.RaisedTag import exh.metadata.metadata.base.RaisedTag
import exh.source.DelegatedHttpSource import exh.source.DelegatedHttpSource
import exh.ui.metadata.adapters.HitomiDescription
import exh.ui.metadata.adapters.HitomiDescriptionAdapter import exh.ui.metadata.adapters.HitomiDescriptionAdapter
import exh.util.urlImportFetchSearchManga import exh.util.urlImportFetchSearchManga
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
@ -140,6 +142,11 @@ class Hitomi(delegate: HttpSource, val context: Context) :
return HitomiDescriptionAdapter(controller) return HitomiDescriptionAdapter(controller)
} }
@Composable
override fun DescriptionComposable(controller: MangaController) {
HitomiDescription(controller)
}
companion object { companion object {
const val otherId = 2703068117101782422L const val otherId = 2703068117101782422L
private val DATE_FORMAT by lazy { private val DATE_FORMAT by lazy {

View File

@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.source.online.all
import android.content.Context import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import android.net.Uri import android.net.Uri
import androidx.compose.runtime.Composable
import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.data.track.TrackManager
@ -48,6 +49,7 @@ import exh.md.utils.MdLang
import exh.md.utils.MdUtil import exh.md.utils.MdUtil
import exh.metadata.metadata.MangaDexSearchMetadata import exh.metadata.metadata.MangaDexSearchMetadata
import exh.source.DelegatedHttpSource import exh.source.DelegatedHttpSource
import exh.ui.metadata.adapters.MangaDexDescription
import exh.ui.metadata.adapters.MangaDexDescriptionAdapter import exh.ui.metadata.adapters.MangaDexDescriptionAdapter
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Response import okhttp3.Response
@ -219,6 +221,11 @@ class MangaDex(delegate: HttpSource, val context: Context) :
return MangaDexDescriptionAdapter(controller) return MangaDexDescriptionAdapter(controller)
} }
@Composable
override fun DescriptionComposable(controller: MangaController) {
MangaDexDescription(controller)
}
override suspend fun parseIntoMetadata(metadata: MangaDexSearchMetadata, input: Triple<MangaDto, List<String>, StatisticsMangaDto>) { override suspend fun parseIntoMetadata(metadata: MangaDexSearchMetadata, input: Triple<MangaDto, List<String>, StatisticsMangaDto>) {
apiMangaParser.parseIntoMetadata(metadata, input.first, input.second, input.third) apiMangaParser.parseIntoMetadata(metadata, input.first, input.second, input.third)
} }

View File

@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.source.online.all
import android.content.Context import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import android.net.Uri import android.net.Uri
import androidx.compose.runtime.Composable
import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.toSManga 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.RaisedSearchMetadata
import exh.metadata.metadata.base.RaisedTag import exh.metadata.metadata.base.RaisedTag
import exh.source.DelegatedHttpSource import exh.source.DelegatedHttpSource
import exh.ui.metadata.adapters.NHentaiDescription
import exh.ui.metadata.adapters.NHentaiDescriptionAdapter import exh.ui.metadata.adapters.NHentaiDescriptionAdapter
import exh.util.trimOrNull import exh.util.trimOrNull
import exh.util.urlImportFetchSearchManga import exh.util.urlImportFetchSearchManga
@ -172,6 +174,11 @@ class NHentai(delegate: HttpSource, val context: Context) :
return NHentaiDescriptionAdapter(controller) return NHentaiDescriptionAdapter(controller)
} }
@Composable
override fun DescriptionComposable(controller: MangaController) {
NHentaiDescription(controller)
}
companion object { companion object {
const val otherId = 7309872737163460316L const val otherId = 7309872737163460316L

View File

@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.source.online.all
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import androidx.compose.runtime.Composable
import androidx.core.net.toUri import androidx.core.net.toUri
import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.source.model.FilterList 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.RaisedSearchMetadata
import exh.metadata.metadata.base.RaisedTag import exh.metadata.metadata.base.RaisedTag
import exh.source.DelegatedHttpSource import exh.source.DelegatedHttpSource
import exh.ui.metadata.adapters.PervEdenDescription
import exh.ui.metadata.adapters.PervEdenDescriptionAdapter import exh.ui.metadata.adapters.PervEdenDescriptionAdapter
import exh.util.urlImportFetchSearchManga import exh.util.urlImportFetchSearchManga
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
@ -136,4 +138,9 @@ class PervEden(delegate: HttpSource, val context: Context) :
override fun getDescriptionAdapter(controller: MangaController): PervEdenDescriptionAdapter { override fun getDescriptionAdapter(controller: MangaController): PervEdenDescriptionAdapter {
return PervEdenDescriptionAdapter(controller) return PervEdenDescriptionAdapter(controller)
} }
@Composable
override fun DescriptionComposable(controller: MangaController) {
PervEdenDescription(controller)
}
} }

View File

@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.source.online.english
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import androidx.compose.runtime.Composable
import androidx.core.net.toUri import androidx.core.net.toUri
import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.source.model.FilterList 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.EightMusesSearchMetadata
import exh.metadata.metadata.base.RaisedTag import exh.metadata.metadata.base.RaisedTag
import exh.source.DelegatedHttpSource import exh.source.DelegatedHttpSource
import exh.ui.metadata.adapters.EightMusesDescription
import exh.ui.metadata.adapters.EightMusesDescriptionAdapter import exh.ui.metadata.adapters.EightMusesDescriptionAdapter
import exh.util.urlImportFetchSearchManga import exh.util.urlImportFetchSearchManga
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
@ -100,4 +102,9 @@ class EightMuses(delegate: HttpSource, val context: Context) :
override fun getDescriptionAdapter(controller: MangaController): EightMusesDescriptionAdapter { override fun getDescriptionAdapter(controller: MangaController): EightMusesDescriptionAdapter {
return EightMusesDescriptionAdapter(controller) return EightMusesDescriptionAdapter(controller)
} }
@Composable
override fun DescriptionComposable(controller: MangaController) {
EightMusesDescription(controller)
}
} }

View File

@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.source.online.english
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import androidx.compose.runtime.Composable
import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.toSManga 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.HBrowseSearchMetadata
import exh.metadata.metadata.base.RaisedTag import exh.metadata.metadata.base.RaisedTag
import exh.source.DelegatedHttpSource import exh.source.DelegatedHttpSource
import exh.ui.metadata.adapters.HBrowseDescription
import exh.ui.metadata.adapters.HBrowseDescriptionAdapter import exh.ui.metadata.adapters.HBrowseDescriptionAdapter
import exh.util.urlImportFetchSearchManga import exh.util.urlImportFetchSearchManga
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
@ -88,4 +90,9 @@ class HBrowse(delegate: HttpSource, val context: Context) :
override fun getDescriptionAdapter(controller: MangaController): HBrowseDescriptionAdapter { override fun getDescriptionAdapter(controller: MangaController): HBrowseDescriptionAdapter {
return HBrowseDescriptionAdapter(controller) return HBrowseDescriptionAdapter(controller)
} }
@Composable
override fun DescriptionComposable(controller: MangaController) {
HBrowseDescription(controller)
}
} }

View File

@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.source.online.english
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import androidx.compose.runtime.Composable
import androidx.core.net.toUri import androidx.core.net.toUri
import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.source.model.FilterList 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.RaisedSearchMetadata
import exh.metadata.metadata.base.RaisedTag import exh.metadata.metadata.base.RaisedTag
import exh.source.DelegatedHttpSource import exh.source.DelegatedHttpSource
import exh.ui.metadata.adapters.PururinDescription
import exh.ui.metadata.adapters.PururinDescriptionAdapter import exh.ui.metadata.adapters.PururinDescriptionAdapter
import exh.util.dropBlank import exh.util.dropBlank
import exh.util.trimAll import exh.util.trimAll
@ -118,4 +120,9 @@ class Pururin(delegate: HttpSource, val context: Context) :
override fun getDescriptionAdapter(controller: MangaController): PururinDescriptionAdapter { override fun getDescriptionAdapter(controller: MangaController): PururinDescriptionAdapter {
return PururinDescriptionAdapter(controller) return PururinDescriptionAdapter(controller)
} }
@Composable
override fun DescriptionComposable(controller: MangaController) {
PururinDescription(controller)
}
} }

View File

@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.source.online.english
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import androidx.compose.runtime.Composable
import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage 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.RaisedSearchMetadata.Companion.TAG_TYPE_VIRTUAL
import exh.metadata.metadata.base.RaisedTag import exh.metadata.metadata.base.RaisedTag
import exh.source.DelegatedHttpSource import exh.source.DelegatedHttpSource
import exh.ui.metadata.adapters.TsuminoDescription
import exh.ui.metadata.adapters.TsuminoDescriptionAdapter import exh.ui.metadata.adapters.TsuminoDescriptionAdapter
import exh.util.dropBlank import exh.util.dropBlank
import exh.util.trimAll import exh.util.trimAll
@ -145,4 +147,9 @@ class Tsumino(delegate: HttpSource, val context: Context) :
override fun getDescriptionAdapter(controller: MangaController): TsuminoDescriptionAdapter { override fun getDescriptionAdapter(controller: MangaController): TsuminoDescriptionAdapter {
return TsuminoDescriptionAdapter(controller) return TsuminoDescriptionAdapter(controller)
} }
@Composable
override fun DescriptionComposable(controller: MangaController) {
TsuminoDescription(controller)
}
} }

View File

@ -66,6 +66,7 @@ import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.supervisorScope import kotlinx.coroutines.supervisorScope
@ -146,7 +147,7 @@ class MangaPresenter(
data class EXHRedirect(val manga: Manga, val update: Boolean) data class EXHRedirect(val manga: Manga, val update: Boolean)
var meta: RaisedSearchMetadata? = null val meta: MutableStateFlow<RaisedSearchMetadata?> = MutableStateFlow(null)
var mergedManga = emptyMap<Long, Manga>() var mergedManga = emptyMap<Long, Manga>()
private set private set
@ -191,7 +192,7 @@ class MangaPresenter(
val meta = if (mainSource != null) { val meta = if (mainSource != null) {
flatMetadata?.raise(mainSource.metaClass) flatMetadata?.raise(mainSource.metaClass)
} else null } else null
this.meta = meta this.meta.value = meta
// SY <-- // SY <--
view.onNextMangaInfo(manga, source, meta) view.onNextMangaInfo(manga, source, meta)
},) },)
@ -394,7 +395,7 @@ class MangaPresenter(
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribeLatestCache( .subscribeLatestCache(
{ view, _ -> { view, _ ->
view.onNextMangaInfo(manga, source, meta) view.onNextMangaInfo(manga, source, meta.value)
}, },
) )
} }

View File

@ -48,7 +48,7 @@ class MangaInfoHeaderAdapter(
private var source: Source = controller.presenter.source private var source: Source = controller.presenter.source
// SY --> // SY -->
private var meta: RaisedSearchMetadata? = controller.presenter.meta private var meta: RaisedSearchMetadata? = controller.presenter.meta.value
private var mergedMangaReferences: List<MergedMangaReference> = controller.presenter.mergedMangaReferences private var mergedMangaReferences: List<MergedMangaReference> = controller.presenter.mergedMangaReferences
// SY <-- // SY <--

View File

@ -4,6 +4,11 @@ import android.annotation.SuppressLint
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup 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 androidx.recyclerview.widget.RecyclerView
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.databinding.DescriptionAdapterEhBinding import eu.kanade.tachiyomi.databinding.DescriptionAdapterEhBinding
@ -13,6 +18,7 @@ import eu.kanade.tachiyomi.util.system.copyToClipboard
import exh.metadata.MetadataUtil import exh.metadata.MetadataUtil
import exh.metadata.bindDrawable import exh.metadata.bindDrawable
import exh.metadata.metadata.EHentaiSearchMetadata import exh.metadata.metadata.EHentaiSearchMetadata
import exh.metadata.metadata.base.RaisedSearchMetadata
import exh.ui.metadata.MetadataViewController import exh.ui.metadata.MetadataViewController
class EHentaiDescriptionAdapter( class EHentaiDescriptionAdapter(
@ -35,7 +41,7 @@ class EHentaiDescriptionAdapter(
inner class EHentaiDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) { inner class EHentaiDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind() { fun bind() {
val meta = controller.presenter.meta val meta = controller.presenter.meta.value
if (meta == null || meta !is EHentaiSearchMetadata) return if (meta == null || meta !is EHentaiSearchMetadata) return
binding.genre.text = 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,
),
)
}
},
)
}

View File

@ -3,6 +3,11 @@ package exh.ui.metadata.adapters
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup 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 androidx.recyclerview.widget.RecyclerView
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.databinding.DescriptionAdapter8mBinding 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 eu.kanade.tachiyomi.util.system.copyToClipboard
import exh.metadata.bindDrawable import exh.metadata.bindDrawable
import exh.metadata.metadata.EightMusesSearchMetadata import exh.metadata.metadata.EightMusesSearchMetadata
import exh.metadata.metadata.base.RaisedSearchMetadata
import exh.ui.metadata.MetadataViewController import exh.ui.metadata.MetadataViewController
class EightMusesDescriptionAdapter( class EightMusesDescriptionAdapter(
@ -33,7 +39,7 @@ class EightMusesDescriptionAdapter(
inner class EightMusesDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) { inner class EightMusesDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind() { fun bind() {
val meta = controller.presenter.meta val meta = controller.presenter.meta.value
if (meta == null || meta !is EightMusesSearchMetadata) return if (meta == null || meta !is EightMusesSearchMetadata) return
binding.title.text = meta.title ?: itemView.context.getString(R.string.unknown) 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,
),
)
}
},
)
}

View File

@ -3,6 +3,11 @@ package exh.ui.metadata.adapters
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup 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 androidx.recyclerview.widget.RecyclerView
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.databinding.DescriptionAdapterHbBinding 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 eu.kanade.tachiyomi.util.system.copyToClipboard
import exh.metadata.bindDrawable import exh.metadata.bindDrawable
import exh.metadata.metadata.HBrowseSearchMetadata import exh.metadata.metadata.HBrowseSearchMetadata
import exh.metadata.metadata.base.RaisedSearchMetadata
import exh.ui.metadata.MetadataViewController import exh.ui.metadata.MetadataViewController
class HBrowseDescriptionAdapter( class HBrowseDescriptionAdapter(
@ -33,7 +39,7 @@ class HBrowseDescriptionAdapter(
inner class HBrowseDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) { inner class HBrowseDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind() { fun bind() {
val meta = controller.presenter.meta val meta = controller.presenter.meta.value
if (meta == null || meta !is HBrowseSearchMetadata) return if (meta == null || meta !is HBrowseSearchMetadata) return
binding.pages.text = itemView.resources.getQuantityString(R.plurals.num_pages, meta.length ?: 0, meta.length ?: 0) 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,
),
)
}
},
)
}

View File

@ -3,6 +3,11 @@ package exh.ui.metadata.adapters
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup 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 androidx.recyclerview.widget.RecyclerView
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.databinding.DescriptionAdapterHiBinding import eu.kanade.tachiyomi.databinding.DescriptionAdapterHiBinding
@ -12,6 +17,7 @@ import eu.kanade.tachiyomi.util.system.copyToClipboard
import exh.metadata.MetadataUtil import exh.metadata.MetadataUtil
import exh.metadata.bindDrawable import exh.metadata.bindDrawable
import exh.metadata.metadata.HitomiSearchMetadata import exh.metadata.metadata.HitomiSearchMetadata
import exh.metadata.metadata.base.RaisedSearchMetadata
import exh.ui.metadata.MetadataViewController import exh.ui.metadata.MetadataViewController
import java.util.Date import java.util.Date
@ -35,7 +41,7 @@ class HitomiDescriptionAdapter(
inner class HitomiDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) { inner class HitomiDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind() { fun bind() {
val meta = controller.presenter.meta val meta = controller.presenter.meta.value
if (meta == null || meta !is HitomiSearchMetadata) return if (meta == null || meta !is HitomiSearchMetadata) return
binding.genre.text = meta.genre?.let { MetadataUtil.getGenreAndColour(itemView.context, it) }?.let { 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,
),
)
}
},
)
}

View File

@ -4,6 +4,11 @@ import android.annotation.SuppressLint
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup 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.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
@ -14,6 +19,7 @@ import eu.kanade.tachiyomi.util.system.copyToClipboard
import exh.metadata.MetadataUtil.getRatingString import exh.metadata.MetadataUtil.getRatingString
import exh.metadata.bindDrawable import exh.metadata.bindDrawable
import exh.metadata.metadata.MangaDexSearchMetadata import exh.metadata.metadata.MangaDexSearchMetadata
import exh.metadata.metadata.base.RaisedSearchMetadata
import exh.ui.metadata.MetadataViewController import exh.ui.metadata.MetadataViewController
import kotlin.math.round import kotlin.math.round
@ -38,7 +44,7 @@ class MangaDexDescriptionAdapter(
inner class MangaDexDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) { inner class MangaDexDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind() { fun bind() {
val meta = controller.presenter.meta val meta = controller.presenter.meta.value
if (meta == null || meta !is MangaDexSearchMetadata) return if (meta == null || meta !is MangaDexSearchMetadata) return
// todo // 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,
),
)
}
},
)
}

View File

@ -4,6 +4,11 @@ import android.annotation.SuppressLint
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup 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 androidx.recyclerview.widget.RecyclerView
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.databinding.DescriptionAdapterNhBinding import eu.kanade.tachiyomi.databinding.DescriptionAdapterNhBinding
@ -13,6 +18,7 @@ import eu.kanade.tachiyomi.util.system.copyToClipboard
import exh.metadata.MetadataUtil import exh.metadata.MetadataUtil
import exh.metadata.bindDrawable import exh.metadata.bindDrawable
import exh.metadata.metadata.NHentaiSearchMetadata import exh.metadata.metadata.NHentaiSearchMetadata
import exh.metadata.metadata.base.RaisedSearchMetadata
import exh.ui.metadata.MetadataViewController import exh.ui.metadata.MetadataViewController
import java.util.Date import java.util.Date
@ -37,7 +43,7 @@ class NHentaiDescriptionAdapter(
inner class NHentaiDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) { inner class NHentaiDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind() { fun bind() {
val meta = controller.presenter.meta val meta = controller.presenter.meta.value
if (meta == null || meta !is NHentaiSearchMetadata) return if (meta == null || meta !is NHentaiSearchMetadata) return
binding.genre.text = meta.tags.filter { it.namespace == NHentaiSearchMetadata.NHENTAI_CATEGORIES_NAMESPACE }.let { tags -> 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,
),
)
}
},
)
}

View File

@ -4,6 +4,11 @@ import android.annotation.SuppressLint
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup 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 androidx.recyclerview.widget.RecyclerView
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.databinding.DescriptionAdapterPeBinding import eu.kanade.tachiyomi.databinding.DescriptionAdapterPeBinding
@ -13,6 +18,7 @@ import eu.kanade.tachiyomi.util.system.copyToClipboard
import exh.metadata.MetadataUtil import exh.metadata.MetadataUtil
import exh.metadata.bindDrawable import exh.metadata.bindDrawable
import exh.metadata.metadata.PervEdenSearchMetadata import exh.metadata.metadata.PervEdenSearchMetadata
import exh.metadata.metadata.base.RaisedSearchMetadata
import exh.ui.metadata.MetadataViewController import exh.ui.metadata.MetadataViewController
import java.util.Locale import java.util.Locale
import kotlin.math.round import kotlin.math.round
@ -37,7 +43,7 @@ class PervEdenDescriptionAdapter(
inner class PervEdenDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) { inner class PervEdenDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind() { fun bind() {
val meta = controller.presenter.meta val meta = controller.presenter.meta.value
if (meta == null || meta !is PervEdenSearchMetadata) return if (meta == null || meta !is PervEdenSearchMetadata) return
binding.genre.text = meta.genre?.let { MetadataUtil.getGenreAndColour(itemView.context, it) }?.let { 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,
),
)
}
},
)
}

View File

@ -4,6 +4,11 @@ import android.annotation.SuppressLint
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup 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 androidx.recyclerview.widget.RecyclerView
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.databinding.DescriptionAdapterPuBinding import eu.kanade.tachiyomi.databinding.DescriptionAdapterPuBinding
@ -13,6 +18,7 @@ import eu.kanade.tachiyomi.util.system.copyToClipboard
import exh.metadata.MetadataUtil import exh.metadata.MetadataUtil
import exh.metadata.bindDrawable import exh.metadata.bindDrawable
import exh.metadata.metadata.PururinSearchMetadata import exh.metadata.metadata.PururinSearchMetadata
import exh.metadata.metadata.base.RaisedSearchMetadata
import exh.ui.metadata.MetadataViewController import exh.ui.metadata.MetadataViewController
import kotlin.math.round import kotlin.math.round
@ -36,7 +42,7 @@ class PururinDescriptionAdapter(
inner class PururinDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) { inner class PururinDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind() { fun bind() {
val meta = controller.presenter.meta val meta = controller.presenter.meta.value
if (meta == null || meta !is PururinSearchMetadata) return if (meta == null || meta !is PururinSearchMetadata) return
binding.genre.text = meta.tags.find { it.namespace == PururinSearchMetadata.TAG_NAMESPACE_CATEGORY }.let { genre -> 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,
),
)
}
},
)
}

View File

@ -4,6 +4,11 @@ import android.annotation.SuppressLint
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup 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 androidx.recyclerview.widget.RecyclerView
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.databinding.DescriptionAdapterTsBinding import eu.kanade.tachiyomi.databinding.DescriptionAdapterTsBinding
@ -13,6 +18,7 @@ import eu.kanade.tachiyomi.util.system.copyToClipboard
import exh.metadata.MetadataUtil import exh.metadata.MetadataUtil
import exh.metadata.bindDrawable import exh.metadata.bindDrawable
import exh.metadata.metadata.TsuminoSearchMetadata import exh.metadata.metadata.TsuminoSearchMetadata
import exh.metadata.metadata.base.RaisedSearchMetadata
import exh.ui.metadata.MetadataViewController import exh.ui.metadata.MetadataViewController
import java.util.Date import java.util.Date
import kotlin.math.round import kotlin.math.round
@ -37,7 +43,7 @@ class TsuminoDescriptionAdapter(
inner class TsuminoDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) { inner class TsuminoDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind() { fun bind() {
val meta = controller.presenter.meta val meta = controller.presenter.meta.value
if (meta == null || meta !is TsuminoSearchMetadata) return if (meta == null || meta !is TsuminoSearchMetadata) return
binding.genre.text = meta.category?.let { MetadataUtil.getGenreAndColour(itemView.context, it) }?.let { 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,
),
)
}
},
)
}