Support images in manga description

This commit is contained in:
Koitharu
2022-07-06 13:12:58 +03:00
parent be67b36b6a
commit 9283f419ba
5 changed files with 55 additions and 4 deletions

View File

@@ -1,5 +1,6 @@
package org.koitharu.kotatsu.core.ui
import android.text.Html
import coil.ComponentRegistry
import coil.ImageLoader
import coil.disk.DiskCache
@@ -10,6 +11,7 @@ import org.koin.dsl.module
import org.koitharu.kotatsu.core.parser.FaviconMapper
import org.koitharu.kotatsu.local.data.CacheDir
import org.koitharu.kotatsu.local.data.CbzFetcher
import org.koitharu.kotatsu.utils.image.CoilImageGetter
val uiModule
get() = module {
@@ -40,4 +42,5 @@ val uiModule
.build()
).build()
}
factory<Html.ImageGetter> { CoilImageGetter(androidContext(), get()) }
}

View File

@@ -8,6 +8,6 @@ val detailsModule
get() = module {
viewModel { intent ->
DetailsViewModel(intent.get(), get(), get(), get(), get(), get(), get(), get(), get())
DetailsViewModel(intent.get(), get(), get(), get(), get(), get(), get(), get(), get(), get())
}
}

View File

@@ -21,6 +21,7 @@ import coil.size.Scale
import coil.util.CoilUtils
import com.google.android.material.chip.Chip
import kotlinx.coroutines.launch
import org.koin.android.ext.android.get
import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
import org.koitharu.kotatsu.R
@@ -80,6 +81,7 @@ class DetailsFragment :
viewModel.readingHistory.observe(viewLifecycleOwner, ::onHistoryChanged)
viewModel.bookmarks.observe(viewLifecycleOwner, ::onBookmarksChanged)
viewModel.scrobblingInfo.observe(viewLifecycleOwner, ::onScrobblingInfoChanged)
viewModel.description.observe(viewLifecycleOwner, ::onDescriptionChanged)
addMenuProvider(DetailsMenuProvider())
}
@@ -108,8 +110,6 @@ class DetailsFragment :
textViewTitle.text = manga.title
textViewSubtitle.textAndVisible = manga.altTitle
textViewAuthor.textAndVisible = manga.author
textViewDescription.text = manga.description?.parseAsHtml()?.takeUnless(Spanned::isBlank)
?: getString(R.string.no_description)
when (manga.state) {
MangaState.FINISHED -> {
textViewState.apply {
@@ -172,6 +172,14 @@ class DetailsFragment :
}
}
private fun onDescriptionChanged(description: CharSequence?) {
if (description.isNullOrBlank()) {
binding.textViewDescription.setText(R.string.no_description)
} else {
binding.textViewDescription.text = description
}
}
private fun onHistoryChanged(history: MangaHistory?) {
with(binding.buttonRead) {
if (history == null) {

View File

@@ -1,5 +1,7 @@
package org.koitharu.kotatsu.details.ui
import android.text.Html
import androidx.core.text.parseAsHtml
import androidx.lifecycle.LiveData
import androidx.lifecycle.asFlow
import androidx.lifecycle.asLiveData
@@ -43,6 +45,7 @@ class DetailsViewModel(
private val bookmarksRepository: BookmarksRepository,
private val settings: AppSettings,
private val scrobbler: Scrobbler,
private val imageGetter: Html.ImageGetter,
) : BaseViewModel() {
private val delegate = MangaDetailsDelegate(
@@ -79,7 +82,19 @@ class DetailsViewModel(
val bookmarks = delegate.manga.flatMapLatest {
if (it != null) bookmarksRepository.observeBookmarks(it) else flowOf(emptyList())
}.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default)
}.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default, emptyList())
val description = delegate.manga
.distinctUntilChangedBy { it?.description.orEmpty() }
.transformLatest {
val description = it?.description
if (description.isNullOrEmpty()) {
emit(null)
} else {
emit(description.parseAsHtml())
emit(description.parseAsHtml(imageGetter = imageGetter))
}
}.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default, null)
val onMangaRemoved = SingleLiveEvent<Manga>()
val isScrobblingAvailable: Boolean

View File

@@ -0,0 +1,25 @@
package org.koitharu.kotatsu.utils.image
import android.content.Context
import android.graphics.drawable.Drawable
import android.text.Html
import coil.ImageLoader
import coil.executeBlocking
import coil.request.ImageRequest
class CoilImageGetter(
private val context: Context,
private val coil: ImageLoader,
) : Html.ImageGetter {
override fun getDrawable(source: String?): Drawable? {
return coil.executeBlocking(
ImageRequest.Builder(context)
.data(source)
.allowHardware(false)
.build()
).drawable?.apply {
setBounds(0, 0, intrinsicHeight, intrinsicHeight)
}
}
}