MangaController overhaul (#7244)
(cherry picked from commit 33a778873a)
# Conflicts:
# app/build.gradle.kts
# app/src/main/java/eu/kanade/tachiyomi/data/database/models/LibraryManga.kt
# app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SearchController.kt
# app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt
# app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt
# app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterHolder.kt
# app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersAdapter.kt
# app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersSettingsSheet.kt
# app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt
# app/src/main/java/eu/kanade/tachiyomi/widget/MangaSummaryView.kt
# app/src/main/res/layout-sw720dp/manga_info_header.xml
# app/src/main/res/layout/manga_controller.xml
# app/src/main/res/layout/manga_info_header.xml
# app/src/main/res/layout/manga_summary.xml
# app/src/main/res/menu/manga.xml
This commit is contained in:
@@ -3,8 +3,8 @@ package exh.md.similar
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import androidx.core.os.bundleOf
|
||||
import eu.kanade.domain.manga.model.Manga
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceController
|
||||
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter
|
||||
@@ -16,7 +16,7 @@ class MangaDexSimilarController(bundle: Bundle) : BrowseSourceController(bundle)
|
||||
|
||||
constructor(manga: Manga, source: CatalogueSource) : this(
|
||||
bundleOf(
|
||||
MANGA_ID to manga.id!!,
|
||||
MANGA_ID to manga.id,
|
||||
MANGA_TITLE to manga.title,
|
||||
SOURCE_ID_KEY to source.id,
|
||||
),
|
||||
|
||||
@@ -4,8 +4,8 @@ import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.View
|
||||
import androidx.core.os.bundleOf
|
||||
import eu.kanade.domain.manga.model.Manga
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||
import eu.kanade.tachiyomi.ui.base.controller.pushController
|
||||
import eu.kanade.tachiyomi.ui.browse.source.SourcesController
|
||||
@@ -19,7 +19,7 @@ class RecommendsController(bundle: Bundle) : BrowseSourceController(bundle) {
|
||||
|
||||
constructor(manga: Manga, source: CatalogueSource) : this(
|
||||
bundleOf(
|
||||
MANGA_ID to manga.id!!,
|
||||
MANGA_ID to manga.id,
|
||||
SOURCE_ID_KEY to source.id,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package exh.ui.base
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.annotation.CallSuper
|
||||
import eu.kanade.tachiyomi.util.lang.launchUI
|
||||
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||
@@ -7,26 +8,36 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.isActive
|
||||
import nucleus.presenter.Presenter
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
|
||||
@Suppress("DEPRECATION", "unused")
|
||||
open class CoroutinePresenter<V>(
|
||||
scope: CoroutineScope = MainScope(),
|
||||
) : Presenter<V>(), CoroutineScope by scope {
|
||||
private val scope: () -> CoroutineScope = ::MainScope,
|
||||
) : Presenter<V>() {
|
||||
var presenterScope: CoroutineScope = scope()
|
||||
|
||||
@CallSuper
|
||||
override fun onCreate(savedState: Bundle?) {
|
||||
super.onCreate(savedState)
|
||||
if (!presenterScope.isActive) {
|
||||
presenterScope = scope()
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DeprecatedCallableAddReplaceWith")
|
||||
@Deprecated("Use launchInView, Flow.inView, Flow.mapView")
|
||||
override fun getView(): V? {
|
||||
return super.getView()
|
||||
}
|
||||
|
||||
fun launchInView(block: (CoroutineScope, V) -> Unit) = launchUI {
|
||||
fun launchInView(block: (CoroutineScope, V) -> Unit) = presenterScope.launchUI {
|
||||
view?.let { block.invoke(this, it) }
|
||||
}
|
||||
|
||||
@@ -44,14 +55,14 @@ open class CoroutinePresenter<V>(
|
||||
}
|
||||
}
|
||||
|
||||
fun Flow<*>.launchUnderContext(context: CoroutineContext = EmptyCoroutineContext) =
|
||||
launch(context) { this@launchUnderContext.collect() }
|
||||
fun Flow<*>.launchUnderContext(context: CoroutineContext = EmptyCoroutineContext) = flowOn(context)
|
||||
.launch()
|
||||
|
||||
fun Flow<*>.launch() = launchIn(this@CoroutinePresenter)
|
||||
fun Flow<*>.launch() = launchIn(presenterScope)
|
||||
|
||||
@CallSuper
|
||||
override fun destroy() {
|
||||
super.destroy()
|
||||
cancel()
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
presenterScope.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,31 +6,30 @@ import android.view.View
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import dev.chrisbanes.insetter.applyInsetter
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.domain.manga.interactor.GetMangaById
|
||||
import eu.kanade.domain.manga.model.Manga
|
||||
import eu.kanade.tachiyomi.databinding.MetadataViewControllerBinding
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.ui.base.controller.NucleusController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class MetadataViewController : NucleusController<MetadataViewControllerBinding, MetadataViewPresenter> {
|
||||
constructor(manga: Manga?) : super(
|
||||
constructor(manga: Manga) : super(
|
||||
bundleOf(
|
||||
MangaController.MANGA_EXTRA to (manga?.id ?: 0),
|
||||
MangaController.MANGA_EXTRA to manga.id,
|
||||
),
|
||||
) {
|
||||
this.manga = manga
|
||||
if (manga != null) {
|
||||
source = Injekt.get<SourceManager>().getOrStub(manga.source)
|
||||
}
|
||||
source = Injekt.get<SourceManager>().getOrStub(manga.source)
|
||||
}
|
||||
|
||||
constructor(mangaId: Long) : this(
|
||||
Injekt.get<DatabaseHelper>().getManga(mangaId).executeAsBlocking(),
|
||||
runBlocking { Injekt.get<GetMangaById>().await(mangaId)!! },
|
||||
)
|
||||
|
||||
@Suppress("unused")
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
package exh.ui.metadata
|
||||
|
||||
import android.os.Bundle
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.domain.manga.model.Manga
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.online.MetadataSource
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||
import exh.metadata.metadata.base.getFlatMetadataForManga
|
||||
import exh.metadata.metadata.base.awaitFlatMetadataForManga
|
||||
import exh.source.getMainSource
|
||||
import exh.ui.base.CoroutinePresenter
|
||||
import exh.util.executeOnIO
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
@@ -20,7 +19,7 @@ class MetadataViewPresenter(
|
||||
val manga: Manga,
|
||||
val source: Source,
|
||||
val preferences: PreferencesHelper = Injekt.get(),
|
||||
private val db: DatabaseHelper = Injekt.get(),
|
||||
private val db: DatabaseHandler = Injekt.get(),
|
||||
) : CoroutinePresenter<MetadataViewController>() {
|
||||
|
||||
val meta = MutableStateFlow<RaisedSearchMetadata?>(null)
|
||||
@@ -29,7 +28,7 @@ class MetadataViewPresenter(
|
||||
super.onCreate(savedState)
|
||||
|
||||
launchIO {
|
||||
val flatMetadata = db.getFlatMetadataForManga(manga.id!!).executeOnIO() ?: return@launchIO
|
||||
val flatMetadata = db.awaitFlatMetadataForManga(manga.id) ?: return@launchIO
|
||||
val mainSource = source.getMainSource<MetadataSource<*, *>>()
|
||||
if (mainSource != null) {
|
||||
meta.value = flatMetadata.raise(mainSource.metaClass)
|
||||
|
||||
@@ -2,132 +2,29 @@ package exh.ui.metadata.adapters
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
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
|
||||
import eu.kanade.tachiyomi.ui.base.controller.pushController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaScreenState
|
||||
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(
|
||||
private val controller: MangaController,
|
||||
) :
|
||||
RecyclerView.Adapter<EHentaiDescriptionAdapter.EHentaiDescriptionViewHolder>() {
|
||||
|
||||
private lateinit var binding: DescriptionAdapterEhBinding
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EHentaiDescriptionViewHolder {
|
||||
binding = DescriptionAdapterEhBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return EHentaiDescriptionViewHolder(binding.root)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = 1
|
||||
|
||||
override fun onBindViewHolder(holder: EHentaiDescriptionViewHolder, position: Int) {
|
||||
holder.bind()
|
||||
}
|
||||
|
||||
inner class EHentaiDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||
fun bind() {
|
||||
val meta = controller.presenter.meta.value
|
||||
if (meta == null || meta !is EHentaiSearchMetadata) return
|
||||
|
||||
binding.genre.text =
|
||||
meta.genre?.let { MetadataUtil.getGenreAndColour(itemView.context, it) }
|
||||
?.let {
|
||||
binding.genre.setBackgroundColor(it.first)
|
||||
it.second
|
||||
}
|
||||
?: meta.genre
|
||||
?: itemView.context.getString(R.string.unknown)
|
||||
|
||||
binding.visible.text = itemView.context.getString(R.string.is_visible, meta.visible ?: itemView.context.getString(R.string.unknown))
|
||||
|
||||
binding.favorites.text = (meta.favorites ?: 0).toString()
|
||||
binding.favorites.bindDrawable(itemView.context, R.drawable.ic_book_24dp)
|
||||
|
||||
binding.uploader.text = meta.uploader ?: itemView.context.getString(R.string.unknown)
|
||||
|
||||
binding.size.text = MetadataUtil.humanReadableByteCount(meta.size ?: 0, true)
|
||||
binding.size.bindDrawable(itemView.context, R.drawable.ic_outline_sd_card_24)
|
||||
|
||||
val length = meta.length ?: 0
|
||||
binding.pages.text = itemView.resources.getQuantityString(R.plurals.num_pages, length, length)
|
||||
binding.pages.bindDrawable(itemView.context, R.drawable.ic_baseline_menu_book_24)
|
||||
|
||||
val language = meta.language ?: itemView.context.getString(R.string.unknown)
|
||||
binding.language.text = if (meta.translated == true) {
|
||||
itemView.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(itemView.context, ratingFloat?.times(2))
|
||||
|
||||
binding.moreInfo.bindDrawable(itemView.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 {
|
||||
itemView.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,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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?) {
|
||||
fun EHentaiDescription(state: MangaScreenState.Success, openMetadataViewer: () -> Unit, search: (String) -> Unit) {
|
||||
val context = LocalContext.current
|
||||
AndroidView(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
factory = { factoryContext ->
|
||||
DescriptionAdapterEhBinding.inflate(LayoutInflater.from(factoryContext)).root
|
||||
},
|
||||
update = {
|
||||
val meta = state.meta
|
||||
if (meta == null || meta !is EHentaiSearchMetadata) return@AndroidView
|
||||
val binding = DescriptionAdapterEhBinding.bind(it)
|
||||
|
||||
@@ -187,15 +84,11 @@ private fun EHentaiDescription(controller: MangaController, meta: RaisedSearchMe
|
||||
}
|
||||
|
||||
binding.uploader.setOnClickListener {
|
||||
meta.uploader?.let { controller.performSearch("uploader:\"$it\"") }
|
||||
meta.uploader?.let { search("uploader:\"$it\"") }
|
||||
}
|
||||
|
||||
binding.moreInfo.setOnClickListener {
|
||||
controller.router?.pushController(
|
||||
MetadataViewController(
|
||||
controller.manga,
|
||||
),
|
||||
)
|
||||
openMetadataViewer()
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@@ -1,84 +1,28 @@
|
||||
package exh.ui.metadata.adapters
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
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
|
||||
import eu.kanade.tachiyomi.ui.base.controller.pushController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaScreenState
|
||||
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(
|
||||
private val controller: MangaController,
|
||||
) :
|
||||
RecyclerView.Adapter<EightMusesDescriptionAdapter.EightMusesDescriptionViewHolder>() {
|
||||
|
||||
private lateinit var binding: DescriptionAdapter8mBinding
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EightMusesDescriptionViewHolder {
|
||||
binding = DescriptionAdapter8mBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return EightMusesDescriptionViewHolder(binding.root)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = 1
|
||||
|
||||
override fun onBindViewHolder(holder: EightMusesDescriptionViewHolder, position: Int) {
|
||||
holder.bind()
|
||||
}
|
||||
|
||||
inner class EightMusesDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||
fun bind() {
|
||||
val meta = controller.presenter.meta.value
|
||||
if (meta == null || meta !is EightMusesSearchMetadata) return
|
||||
|
||||
binding.title.text = meta.title ?: itemView.context.getString(R.string.unknown)
|
||||
|
||||
binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp)
|
||||
|
||||
binding.title.setOnLongClickListener {
|
||||
itemView.context.copyToClipboard(
|
||||
binding.title.text.toString(),
|
||||
binding.title.text.toString(),
|
||||
)
|
||||
true
|
||||
}
|
||||
|
||||
binding.moreInfo.setOnClickListener {
|
||||
controller.router?.pushController(
|
||||
MetadataViewController(
|
||||
controller.manga,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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?) {
|
||||
fun EightMusesDescription(state: MangaScreenState.Success, openMetadataViewer: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
AndroidView(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
factory = { factoryContext ->
|
||||
DescriptionAdapter8mBinding.inflate(LayoutInflater.from(factoryContext)).root
|
||||
},
|
||||
update = {
|
||||
val meta = state.meta
|
||||
if (meta == null || meta !is EightMusesSearchMetadata) return@AndroidView
|
||||
val binding = DescriptionAdapter8mBinding.bind(it)
|
||||
|
||||
@@ -95,11 +39,7 @@ private fun EightMusesDescription(controller: MangaController, meta: RaisedSearc
|
||||
}
|
||||
|
||||
binding.moreInfo.setOnClickListener {
|
||||
controller.router?.pushController(
|
||||
MetadataViewController(
|
||||
controller.manga,
|
||||
),
|
||||
)
|
||||
openMetadataViewer()
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@@ -1,85 +1,28 @@
|
||||
package exh.ui.metadata.adapters
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
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
|
||||
import eu.kanade.tachiyomi.ui.base.controller.pushController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaScreenState
|
||||
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(
|
||||
private val controller: MangaController,
|
||||
) :
|
||||
RecyclerView.Adapter<HBrowseDescriptionAdapter.HBrowseDescriptionViewHolder>() {
|
||||
|
||||
private lateinit var binding: DescriptionAdapterHbBinding
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HBrowseDescriptionViewHolder {
|
||||
binding = DescriptionAdapterHbBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return HBrowseDescriptionViewHolder(binding.root)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = 1
|
||||
|
||||
override fun onBindViewHolder(holder: HBrowseDescriptionViewHolder, position: Int) {
|
||||
holder.bind()
|
||||
}
|
||||
|
||||
inner class HBrowseDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||
fun bind() {
|
||||
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)
|
||||
binding.pages.bindDrawable(itemView.context, R.drawable.ic_baseline_menu_book_24)
|
||||
|
||||
binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp)
|
||||
|
||||
binding.pages.setOnLongClickListener {
|
||||
itemView.context.copyToClipboard(
|
||||
binding.pages.text.toString(),
|
||||
binding.pages.text.toString(),
|
||||
)
|
||||
true
|
||||
}
|
||||
|
||||
binding.moreInfo.setOnClickListener {
|
||||
controller.router?.pushController(
|
||||
MetadataViewController(
|
||||
controller.manga,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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?) {
|
||||
fun HBrowseDescription(state: MangaScreenState.Success, openMetadataViewer: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
AndroidView(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
factory = { factoryContext ->
|
||||
DescriptionAdapterHbBinding.inflate(LayoutInflater.from(factoryContext)).root
|
||||
},
|
||||
update = {
|
||||
val meta = state.meta
|
||||
if (meta == null || meta !is HBrowseSearchMetadata) return@AndroidView
|
||||
val binding = DescriptionAdapterHbBinding.bind(it)
|
||||
|
||||
@@ -97,11 +40,7 @@ private fun HBrowseDescription(controller: MangaController, meta: RaisedSearchMe
|
||||
}
|
||||
|
||||
binding.moreInfo.setOnClickListener {
|
||||
controller.router?.pushController(
|
||||
MetadataViewController(
|
||||
controller.manga,
|
||||
),
|
||||
)
|
||||
openMetadataViewer()
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@@ -1,98 +1,30 @@
|
||||
package exh.ui.metadata.adapters
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
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
|
||||
import eu.kanade.tachiyomi.ui.base.controller.pushController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaScreenState
|
||||
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
|
||||
|
||||
class HitomiDescriptionAdapter(
|
||||
private val controller: MangaController,
|
||||
) :
|
||||
RecyclerView.Adapter<HitomiDescriptionAdapter.HitomiDescriptionViewHolder>() {
|
||||
|
||||
private lateinit var binding: DescriptionAdapterHiBinding
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HitomiDescriptionViewHolder {
|
||||
binding = DescriptionAdapterHiBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return HitomiDescriptionViewHolder(binding.root)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = 1
|
||||
|
||||
override fun onBindViewHolder(holder: HitomiDescriptionViewHolder, position: Int) {
|
||||
holder.bind()
|
||||
}
|
||||
|
||||
inner class HitomiDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||
fun bind() {
|
||||
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 {
|
||||
binding.genre.setBackgroundColor(it.first)
|
||||
it.second
|
||||
} ?: meta.genre ?: itemView.context.getString(R.string.unknown)
|
||||
|
||||
binding.whenPosted.text = MetadataUtil.EX_DATE_FORMAT.format(Date(meta.uploadDate ?: 0))
|
||||
binding.language.text = meta.language ?: itemView.context.getString(R.string.unknown)
|
||||
|
||||
binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp)
|
||||
|
||||
listOf(
|
||||
binding.genre,
|
||||
binding.language,
|
||||
binding.whenPosted,
|
||||
).forEach { textView ->
|
||||
textView.setOnLongClickListener {
|
||||
itemView.context.copyToClipboard(
|
||||
textView.text.toString(),
|
||||
textView.text.toString(),
|
||||
)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
binding.moreInfo.setOnClickListener {
|
||||
controller.router?.pushController(
|
||||
MetadataViewController(
|
||||
controller.manga,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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?) {
|
||||
fun HitomiDescription(state: MangaScreenState.Success, openMetadataViewer: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
AndroidView(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
factory = { factoryContext ->
|
||||
DescriptionAdapterHiBinding.inflate(LayoutInflater.from(factoryContext)).root
|
||||
},
|
||||
update = {
|
||||
val meta = state.meta
|
||||
if (meta == null || meta !is HitomiSearchMetadata) return@AndroidView
|
||||
val binding = DescriptionAdapterHiBinding.bind(it)
|
||||
|
||||
@@ -121,11 +53,7 @@ private fun HitomiDescription(controller: MangaController, meta: RaisedSearchMet
|
||||
}
|
||||
|
||||
binding.moreInfo.setOnClickListener {
|
||||
controller.router?.pushController(
|
||||
MetadataViewController(
|
||||
controller.manga,
|
||||
),
|
||||
)
|
||||
openMetadataViewer()
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@@ -2,94 +2,31 @@ package exh.ui.metadata.adapters
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
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
|
||||
import eu.kanade.tachiyomi.databinding.DescriptionAdapterMdBinding
|
||||
import eu.kanade.tachiyomi.ui.base.controller.pushController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaScreenState
|
||||
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
|
||||
|
||||
class MangaDexDescriptionAdapter(
|
||||
private val controller: MangaController,
|
||||
) :
|
||||
RecyclerView.Adapter<MangaDexDescriptionAdapter.MangaDexDescriptionViewHolder>() {
|
||||
|
||||
private lateinit var binding: DescriptionAdapterMdBinding
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MangaDexDescriptionViewHolder {
|
||||
binding = DescriptionAdapterMdBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return MangaDexDescriptionViewHolder(binding.root)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = 1
|
||||
|
||||
override fun onBindViewHolder(holder: MangaDexDescriptionViewHolder, position: Int) {
|
||||
holder.bind()
|
||||
}
|
||||
|
||||
inner class MangaDexDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||
|
||||
fun bind() {
|
||||
val meta = controller.presenter.meta.value
|
||||
if (meta == null || meta !is MangaDexSearchMetadata) return
|
||||
|
||||
// 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(itemView.context, ratingFloat)
|
||||
binding.rating.isVisible = ratingFloat != null
|
||||
binding.ratingBar.isVisible = ratingFloat != null
|
||||
|
||||
binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp)
|
||||
|
||||
binding.rating.setOnLongClickListener {
|
||||
itemView.context.copyToClipboard(
|
||||
binding.rating.text.toString(),
|
||||
binding.rating.text.toString(),
|
||||
)
|
||||
true
|
||||
}
|
||||
|
||||
binding.moreInfo.setOnClickListener {
|
||||
controller.router?.pushController(
|
||||
MetadataViewController(
|
||||
controller.manga,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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?) {
|
||||
fun MangaDexDescription(state: MangaScreenState.Success, openMetadataViewer: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
AndroidView(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
factory = { factoryContext ->
|
||||
DescriptionAdapterMdBinding.inflate(LayoutInflater.from(factoryContext)).root
|
||||
},
|
||||
update = {
|
||||
val meta = state.meta
|
||||
if (meta == null || meta !is MangaDexSearchMetadata) return@AndroidView
|
||||
val binding = DescriptionAdapterMdBinding.bind(it)
|
||||
|
||||
@@ -112,11 +49,7 @@ private fun MangaDexDescription(controller: MangaController, meta: RaisedSearchM
|
||||
}
|
||||
|
||||
binding.moreInfo.setOnClickListener {
|
||||
controller.router?.pushController(
|
||||
MetadataViewController(
|
||||
controller.manga,
|
||||
),
|
||||
)
|
||||
openMetadataViewer()
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@@ -2,116 +2,30 @@ package exh.ui.metadata.adapters
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
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
|
||||
import eu.kanade.tachiyomi.ui.base.controller.pushController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaScreenState
|
||||
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
|
||||
|
||||
class NHentaiDescriptionAdapter(
|
||||
private val controller: MangaController,
|
||||
) :
|
||||
RecyclerView.Adapter<NHentaiDescriptionAdapter.NHentaiDescriptionViewHolder>() {
|
||||
|
||||
private lateinit var binding: DescriptionAdapterNhBinding
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NHentaiDescriptionViewHolder {
|
||||
binding = DescriptionAdapterNhBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return NHentaiDescriptionViewHolder(binding.root)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = 1
|
||||
|
||||
override fun onBindViewHolder(holder: NHentaiDescriptionViewHolder, position: Int) {
|
||||
holder.bind()
|
||||
}
|
||||
|
||||
inner class NHentaiDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||
|
||||
fun bind() {
|
||||
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 ->
|
||||
if (tags.isNotEmpty()) tags.joinToString(transform = { it.name }) else null
|
||||
}.let { categoriesString ->
|
||||
categoriesString?.let { MetadataUtil.getGenreAndColour(itemView.context, it) }?.let {
|
||||
binding.genre.setBackgroundColor(it.first)
|
||||
it.second
|
||||
} ?: categoriesString ?: itemView.context.getString(R.string.unknown)
|
||||
}
|
||||
|
||||
meta.favoritesCount?.let {
|
||||
if (it == 0L) return@let
|
||||
binding.favorites.text = it.toString()
|
||||
binding.favorites.bindDrawable(itemView.context, R.drawable.ic_book_24dp)
|
||||
}
|
||||
|
||||
binding.whenPosted.text = MetadataUtil.EX_DATE_FORMAT.format(Date((meta.uploadDate ?: 0) * 1000))
|
||||
|
||||
binding.pages.text = itemView.resources.getQuantityString(R.plurals.num_pages, meta.pageImageTypes.size, meta.pageImageTypes.size)
|
||||
binding.pages.bindDrawable(itemView.context, R.drawable.ic_baseline_menu_book_24)
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
binding.id.text = "#" + (meta.nhId ?: 0)
|
||||
|
||||
binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp)
|
||||
|
||||
listOf(
|
||||
binding.favorites,
|
||||
binding.genre,
|
||||
binding.id,
|
||||
binding.pages,
|
||||
binding.whenPosted,
|
||||
).forEach { textView ->
|
||||
textView.setOnLongClickListener {
|
||||
itemView.context.copyToClipboard(
|
||||
textView.text.toString(),
|
||||
textView.text.toString(),
|
||||
)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
binding.moreInfo.setOnClickListener {
|
||||
controller.router?.pushController(
|
||||
MetadataViewController(
|
||||
controller.manga,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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?) {
|
||||
fun NHentaiDescription(state: MangaScreenState.Success, openMetadataViewer: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
AndroidView(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
factory = { factoryContext ->
|
||||
DescriptionAdapterNhBinding.inflate(LayoutInflater.from(factoryContext)).root
|
||||
},
|
||||
update = {
|
||||
val meta = state.meta
|
||||
if (meta == null || meta !is NHentaiSearchMetadata) return@AndroidView
|
||||
val binding = DescriptionAdapterNhBinding.bind(it)
|
||||
|
||||
@@ -157,11 +71,7 @@ private fun NHentaiDescription(controller: MangaController, meta: RaisedSearchMe
|
||||
}
|
||||
|
||||
binding.moreInfo.setOnClickListener {
|
||||
controller.router?.pushController(
|
||||
MetadataViewController(
|
||||
controller.manga,
|
||||
),
|
||||
)
|
||||
openMetadataViewer()
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@@ -2,106 +2,31 @@ package exh.ui.metadata.adapters
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
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
|
||||
import eu.kanade.tachiyomi.ui.base.controller.pushController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaScreenState
|
||||
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
|
||||
|
||||
class PervEdenDescriptionAdapter(
|
||||
private val controller: MangaController,
|
||||
) :
|
||||
RecyclerView.Adapter<PervEdenDescriptionAdapter.PervEdenDescriptionViewHolder>() {
|
||||
|
||||
private lateinit var binding: DescriptionAdapterPeBinding
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PervEdenDescriptionViewHolder {
|
||||
binding = DescriptionAdapterPeBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return PervEdenDescriptionViewHolder(binding.root)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = 1
|
||||
|
||||
override fun onBindViewHolder(holder: PervEdenDescriptionViewHolder, position: Int) {
|
||||
holder.bind()
|
||||
}
|
||||
|
||||
inner class PervEdenDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||
fun bind() {
|
||||
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 {
|
||||
binding.genre.setBackgroundColor(it.first)
|
||||
it.second
|
||||
} ?: meta.genre ?: itemView.context.getString(R.string.unknown)
|
||||
|
||||
val language = meta.lang
|
||||
binding.language.text = if (language != null) {
|
||||
val local = Locale(language)
|
||||
local.displayName
|
||||
} else itemView.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(itemView.context, meta.rating?.times(2))
|
||||
|
||||
binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp)
|
||||
|
||||
listOf(
|
||||
binding.genre,
|
||||
binding.language,
|
||||
binding.rating,
|
||||
).forEach { textView ->
|
||||
textView.setOnLongClickListener {
|
||||
itemView.context.copyToClipboard(
|
||||
textView.text.toString(),
|
||||
textView.text.toString(),
|
||||
)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
binding.moreInfo.setOnClickListener {
|
||||
controller.router?.pushController(
|
||||
MetadataViewController(
|
||||
controller.manga,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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?) {
|
||||
fun PervEdenDescription(state: MangaScreenState.Success, openMetadataViewer: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
AndroidView(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
factory = { factoryContext ->
|
||||
DescriptionAdapterPeBinding.inflate(LayoutInflater.from(factoryContext)).root
|
||||
},
|
||||
update = {
|
||||
val meta = state.meta
|
||||
if (meta == null || meta !is PervEdenSearchMetadata) return@AndroidView
|
||||
val binding = DescriptionAdapterPeBinding.bind(it)
|
||||
|
||||
@@ -137,11 +62,7 @@ private fun PervEdenDescription(controller: MangaController, meta: RaisedSearchM
|
||||
}
|
||||
|
||||
binding.moreInfo.setOnClickListener {
|
||||
controller.router?.pushController(
|
||||
MetadataViewController(
|
||||
controller.manga,
|
||||
),
|
||||
)
|
||||
openMetadataViewer()
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@@ -2,112 +2,30 @@ package exh.ui.metadata.adapters
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
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
|
||||
import eu.kanade.tachiyomi.ui.base.controller.pushController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaScreenState
|
||||
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
|
||||
|
||||
class PururinDescriptionAdapter(
|
||||
private val controller: MangaController,
|
||||
) :
|
||||
RecyclerView.Adapter<PururinDescriptionAdapter.PururinDescriptionViewHolder>() {
|
||||
|
||||
private lateinit var binding: DescriptionAdapterPuBinding
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PururinDescriptionViewHolder {
|
||||
binding = DescriptionAdapterPuBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return PururinDescriptionViewHolder(binding.root)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = 1
|
||||
|
||||
override fun onBindViewHolder(holder: PururinDescriptionViewHolder, position: Int) {
|
||||
holder.bind()
|
||||
}
|
||||
|
||||
inner class PururinDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||
fun bind() {
|
||||
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 ->
|
||||
genre?.let { MetadataUtil.getGenreAndColour(itemView.context, it.name) }?.let {
|
||||
binding.genre.setBackgroundColor(it.first)
|
||||
it.second
|
||||
} ?: genre?.name ?: itemView.context.getString(R.string.unknown)
|
||||
}
|
||||
|
||||
binding.uploader.text = meta.uploaderDisp ?: meta.uploader.orEmpty()
|
||||
|
||||
binding.size.text = meta.fileSize ?: itemView.context.getString(R.string.unknown)
|
||||
binding.size.bindDrawable(itemView.context, R.drawable.ic_outline_sd_card_24)
|
||||
|
||||
binding.pages.text = itemView.resources.getQuantityString(R.plurals.num_pages, meta.pages ?: 0, meta.pages ?: 0)
|
||||
binding.pages.bindDrawable(itemView.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(itemView.context, ratingFloat?.times(2))
|
||||
|
||||
binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp)
|
||||
|
||||
listOf(
|
||||
binding.genre,
|
||||
binding.pages,
|
||||
binding.rating,
|
||||
binding.size,
|
||||
binding.uploader,
|
||||
).forEach { textView ->
|
||||
textView.setOnLongClickListener {
|
||||
itemView.context.copyToClipboard(
|
||||
textView.text.toString(),
|
||||
textView.text.toString(),
|
||||
)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
binding.moreInfo.setOnClickListener {
|
||||
controller.router?.pushController(
|
||||
MetadataViewController(
|
||||
controller.manga,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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?) {
|
||||
fun PururinDescription(state: MangaScreenState.Success, openMetadataViewer: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
AndroidView(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
factory = { factoryContext ->
|
||||
DescriptionAdapterPuBinding.inflate(LayoutInflater.from(factoryContext)).root
|
||||
},
|
||||
update = {
|
||||
val meta = state.meta
|
||||
if (meta == null || meta !is PururinSearchMetadata) return@AndroidView
|
||||
val binding = DescriptionAdapterPuBinding.bind(it)
|
||||
|
||||
@@ -150,11 +68,7 @@ private fun PururinDescription(controller: MangaController, meta: RaisedSearchMe
|
||||
}
|
||||
|
||||
binding.moreInfo.setOnClickListener {
|
||||
controller.router?.pushController(
|
||||
MetadataViewController(
|
||||
controller.manga,
|
||||
),
|
||||
)
|
||||
openMetadataViewer()
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@@ -2,113 +2,31 @@ package exh.ui.metadata.adapters
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
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
|
||||
import eu.kanade.tachiyomi.ui.base.controller.pushController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaScreenState
|
||||
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
|
||||
|
||||
class TsuminoDescriptionAdapter(
|
||||
private val controller: MangaController,
|
||||
) :
|
||||
RecyclerView.Adapter<TsuminoDescriptionAdapter.TsuminoDescriptionViewHolder>() {
|
||||
|
||||
private lateinit var binding: DescriptionAdapterTsBinding
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TsuminoDescriptionViewHolder {
|
||||
binding = DescriptionAdapterTsBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return TsuminoDescriptionViewHolder(binding.root)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = 1
|
||||
|
||||
override fun onBindViewHolder(holder: TsuminoDescriptionViewHolder, position: Int) {
|
||||
holder.bind()
|
||||
}
|
||||
|
||||
inner class TsuminoDescriptionViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||
fun bind() {
|
||||
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 {
|
||||
binding.genre.setBackgroundColor(it.first)
|
||||
it.second
|
||||
} ?: meta.category ?: itemView.context.getString(R.string.unknown)
|
||||
|
||||
binding.favorites.text = (meta.favorites ?: 0).toString()
|
||||
binding.favorites.bindDrawable(itemView.context, R.drawable.ic_book_24dp)
|
||||
|
||||
binding.whenPosted.text = TsuminoSearchMetadata.TSUMINO_DATE_FORMAT.format(Date(meta.uploadDate ?: 0))
|
||||
|
||||
binding.uploader.text = meta.uploader ?: itemView.context.getString(R.string.unknown)
|
||||
|
||||
binding.pages.text = itemView.resources.getQuantityString(R.plurals.num_pages, meta.length ?: 0, meta.length ?: 0)
|
||||
binding.pages.bindDrawable(itemView.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(itemView.context, meta.averageRating?.times(2))
|
||||
|
||||
binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp)
|
||||
|
||||
listOf(
|
||||
binding.favorites,
|
||||
binding.genre,
|
||||
binding.pages,
|
||||
binding.rating,
|
||||
binding.uploader,
|
||||
binding.whenPosted,
|
||||
).forEach { textView ->
|
||||
textView.setOnLongClickListener {
|
||||
itemView.context.copyToClipboard(
|
||||
textView.text.toString(),
|
||||
textView.text.toString(),
|
||||
)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
binding.moreInfo.setOnClickListener {
|
||||
controller.router?.pushController(
|
||||
MetadataViewController(
|
||||
controller.manga,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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?) {
|
||||
fun TsuminoDescription(state: MangaScreenState.Success, openMetadataViewer: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
AndroidView(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
factory = { factoryContext ->
|
||||
DescriptionAdapterTsBinding.inflate(LayoutInflater.from(factoryContext)).root
|
||||
},
|
||||
update = {
|
||||
val meta = state.meta
|
||||
if (meta == null || meta !is TsuminoSearchMetadata) return@AndroidView
|
||||
val binding = DescriptionAdapterTsBinding.bind(it)
|
||||
|
||||
@@ -151,11 +69,7 @@ private fun TsuminoDescription(controller: MangaController, meta: RaisedSearchMe
|
||||
}
|
||||
|
||||
binding.moreInfo.setOnClickListener {
|
||||
controller.router?.pushController(
|
||||
MetadataViewController(
|
||||
controller.manga,
|
||||
),
|
||||
)
|
||||
openMetadataViewer()
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@@ -22,7 +22,7 @@ class SmartSearchPresenter(private val source: CatalogueSource, private val conf
|
||||
override fun onCreate(savedState: Bundle?) {
|
||||
super.onCreate(savedState)
|
||||
|
||||
launchIO {
|
||||
presenterScope.launchIO {
|
||||
val result = try {
|
||||
val resultManga = smartSearchEngine.smartSearch(source, config.origTitle)
|
||||
if (resultManga != null) {
|
||||
|
||||
Reference in New Issue
Block a user