Improve explore screen

pull/605/head
Koitharu 2 years ago
parent 4c9989da78
commit b878f358ff
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

@ -1,12 +1,21 @@
package org.koitharu.kotatsu.core.model package org.koitharu.kotatsu.core.model
import android.content.Context import android.content.Context
import android.graphics.Color
import android.text.SpannableStringBuilder
import android.text.style.ForegroundColorSpan
import android.text.style.RelativeSizeSpan
import android.text.style.SuperscriptSpan
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.core.text.buildSpannedString
import androidx.core.text.inSpans
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.util.ext.getThemeColor
import org.koitharu.kotatsu.parsers.model.ContentType import org.koitharu.kotatsu.parsers.model.ContentType
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.util.toTitleCase import org.koitharu.kotatsu.parsers.util.toTitleCase
import java.util.Locale import java.util.Locale
import com.google.android.material.R as materialR
fun MangaSource.getLocaleTitle(): String? { fun MangaSource.getLocaleTitle(): String? {
val lc = Locale(locale ?: return null) val lc = Locale(locale ?: return null)
@ -36,3 +45,21 @@ fun MangaSource.getSummary(context: Context): String {
val locale = getLocaleTitle() ?: context.getString(R.string.various_languages) val locale = getLocaleTitle() ?: context.getString(R.string.various_languages)
return context.getString(R.string.source_summary_pattern, type, locale) return context.getString(R.string.source_summary_pattern, type, locale)
} }
fun MangaSource.getTitle(context: Context): CharSequence = if (isNsfw()) {
buildSpannedString {
append(title)
append(' ')
appendNsfwLabel(context)
}
} else {
title
}
private fun SpannableStringBuilder.appendNsfwLabel(context: Context) = inSpans(
ForegroundColorSpan(context.getThemeColor(materialR.attr.colorError, Color.RED)),
RelativeSizeSpan(0.74f),
SuperscriptSpan(),
) {
append(context.getString(R.string.nsfw))
}

@ -111,7 +111,7 @@ class ExploreFragment :
} }
override fun onListHeaderClick(item: ListHeader, view: View) { override fun onListHeaderClick(item: ListHeader, view: View) {
startActivity(Intent(view.context, SourcesCatalogActivity::class.java)) startActivity(SettingsActivity.newManageSourcesIntent(view.context))
} }
override fun onPrimaryButtonClick(tipView: TipView) { override fun onPrimaryButtonClick(tipView: TipView) {
@ -160,7 +160,7 @@ class ExploreFragment :
override fun onRetryClick(error: Throwable) = Unit override fun onRetryClick(error: Throwable) = Unit
override fun onEmptyActionClick() { override fun onEmptyActionClick() {
startActivity(SettingsActivity.newManageSourcesIntent(context ?: return)) startActivity(Intent(context ?: return, SourcesCatalogActivity::class.java))
} }
private fun onOpenManga(manga: Manga) { private fun onOpenManga(manga: Manga) {

@ -21,7 +21,6 @@ import org.koitharu.kotatsu.core.ui.util.ReversibleAction
import org.koitharu.kotatsu.core.util.ext.MutableEventFlow import org.koitharu.kotatsu.core.util.ext.MutableEventFlow
import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.core.util.ext.call
import org.koitharu.kotatsu.explore.data.MangaSourcesRepository import org.koitharu.kotatsu.explore.data.MangaSourcesRepository
import org.koitharu.kotatsu.explore.data.SourcesSortOrder
import org.koitharu.kotatsu.explore.domain.ExploreRepository import org.koitharu.kotatsu.explore.domain.ExploreRepository
import org.koitharu.kotatsu.explore.ui.model.ExploreButtons import org.koitharu.kotatsu.explore.ui.model.ExploreButtons
import org.koitharu.kotatsu.explore.ui.model.MangaSourceItem import org.koitharu.kotatsu.explore.ui.model.MangaSourceItem
@ -56,8 +55,6 @@ class ExploreViewModel @Inject constructor(
valueProducer = { isSuggestionsEnabled }, valueProducer = { isSuggestionsEnabled },
) )
val sortOrder = MutableStateFlow(SourcesSortOrder.MANUAL) // TODO
val onOpenManga = MutableEventFlow<Manga>() val onOpenManga = MutableEventFlow<Manga>()
val onActionDone = MutableEventFlow<ReversibleAction>() val onActionDone = MutableEventFlow<ReversibleAction>()
val onShowSuggestionsTip = MutableEventFlow<Unit>() val onShowSuggestionsTip = MutableEventFlow<Unit>()
@ -136,7 +133,7 @@ class ExploreViewModel @Inject constructor(
result += RecommendationsItem(recommendation) result += RecommendationsItem(recommendation)
} }
if (sources.isNotEmpty()) { if (sources.isNotEmpty()) {
result += ListHeader(R.string.remote_sources, R.string.catalog) result += ListHeader(R.string.remote_sources, R.string.manage)
if (newSources.isNotEmpty()) { if (newSources.isNotEmpty()) {
result += TipModel( result += TipModel(
key = TIP_NEW_SOURCES, key = TIP_NEW_SOURCES,
@ -153,7 +150,7 @@ class ExploreViewModel @Inject constructor(
icon = R.drawable.ic_empty_common, icon = R.drawable.ic_empty_common,
textPrimary = R.string.no_manga_sources, textPrimary = R.string.no_manga_sources,
textSecondary = R.string.no_manga_sources_text, textSecondary = R.string.no_manga_sources_text,
actionStringRes = R.string.manage, actionStringRes = R.string.catalog,
) )
} }
return result return result

@ -8,6 +8,7 @@ import coil.ImageLoader
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.getSummary import org.koitharu.kotatsu.core.model.getSummary
import org.koitharu.kotatsu.core.model.getTitle
import org.koitharu.kotatsu.core.parser.favicon.faviconUri import org.koitharu.kotatsu.core.parser.favicon.faviconUri
import org.koitharu.kotatsu.core.ui.image.FaviconDrawable import org.koitharu.kotatsu.core.ui.image.FaviconDrawable
import org.koitharu.kotatsu.core.ui.image.TrimTransformation import org.koitharu.kotatsu.core.ui.image.TrimTransformation
@ -112,7 +113,7 @@ fun exploreSourceListItemAD(
binding.root.setOnContextClickListenerCompat(eventListener) binding.root.setOnContextClickListenerCompat(eventListener)
bind { bind {
binding.textViewTitle.text = item.source.title binding.textViewTitle.text = item.source.getTitle(context)
binding.textViewSubtitle.text = item.source.getSummary(context) binding.textViewSubtitle.text = item.source.getSummary(context)
val fallbackIcon = FaviconDrawable(context, R.style.FaviconDrawable_Small, item.source.name) val fallbackIcon = FaviconDrawable(context, R.style.FaviconDrawable_Small, item.source.name)
binding.imageViewIcon.newImageRequest(lifecycleOwner, item.source.faviconUri())?.run { binding.imageViewIcon.newImageRequest(lifecycleOwner, item.source.faviconUri())?.run {
@ -147,7 +148,7 @@ fun exploreSourceGridItemAD(
binding.root.setOnContextClickListenerCompat(eventListener) binding.root.setOnContextClickListenerCompat(eventListener)
bind { bind {
binding.textViewTitle.text = item.source.title binding.textViewTitle.text = item.source.getTitle(context)
val fallbackIcon = FaviconDrawable(context, R.style.FaviconDrawable_Large, item.source.name) val fallbackIcon = FaviconDrawable(context, R.style.FaviconDrawable_Large, item.source.name)
binding.imageViewIcon.newImageRequest(lifecycleOwner, item.source.faviconUri())?.run { binding.imageViewIcon.newImageRequest(lifecycleOwner, item.source.faviconUri())?.run {
fallback(fallbackIcon) fallback(fallbackIcon)

@ -1,11 +1,11 @@
package org.koitharu.kotatsu.search.ui.suggestion.adapter package org.koitharu.kotatsu.search.ui.suggestion.adapter
import androidx.core.text.buildSpannedString
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import coil.ImageLoader import coil.ImageLoader
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.getSummary import org.koitharu.kotatsu.core.model.getSummary
import org.koitharu.kotatsu.core.model.getTitle
import org.koitharu.kotatsu.core.parser.favicon.faviconUri import org.koitharu.kotatsu.core.parser.favicon.faviconUri
import org.koitharu.kotatsu.core.ui.image.FaviconDrawable import org.koitharu.kotatsu.core.ui.image.FaviconDrawable
import org.koitharu.kotatsu.core.util.ext.enqueueWith import org.koitharu.kotatsu.core.util.ext.enqueueWith
@ -14,7 +14,6 @@ import org.koitharu.kotatsu.core.util.ext.source
import org.koitharu.kotatsu.databinding.ItemSearchSuggestionSourceBinding import org.koitharu.kotatsu.databinding.ItemSearchSuggestionSourceBinding
import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionListener import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionListener
import org.koitharu.kotatsu.search.ui.suggestion.model.SearchSuggestionItem import org.koitharu.kotatsu.search.ui.suggestion.model.SearchSuggestionItem
import org.koitharu.kotatsu.settings.sources.adapter.appendNsfwLabel
fun searchSuggestionSourceAD( fun searchSuggestionSourceAD(
coil: ImageLoader, coil: ImageLoader,
@ -32,15 +31,7 @@ fun searchSuggestionSourceAD(
} }
bind { bind {
binding.textViewTitle.text = if (item.isNsfw) { binding.textViewTitle.text = item.source.getTitle(context)
buildSpannedString {
append(item.source.title)
append(' ')
appendNsfwLabel(context)
}
} else {
item.source.title
}
binding.textViewSubtitle.text = item.source.getSummary(context) binding.textViewSubtitle.text = item.source.getSummary(context)
binding.switchLocal.isChecked = item.isEnabled binding.switchLocal.isChecked = item.isEnabled
val fallbackIcon = FaviconDrawable(context, R.style.FaviconDrawable_Small, item.source.name) val fallbackIcon = FaviconDrawable(context, R.style.FaviconDrawable_Small, item.source.name)

@ -1,16 +1,8 @@
package org.koitharu.kotatsu.settings.sources.adapter package org.koitharu.kotatsu.settings.sources.adapter
import android.content.Context
import android.graphics.Color
import android.text.SpannableStringBuilder
import android.text.style.ForegroundColorSpan
import android.text.style.RelativeSizeSpan
import android.text.style.SuperscriptSpan
import android.view.View import android.view.View
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.core.content.pm.ShortcutManagerCompat import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.text.buildSpannedString
import androidx.core.text.inSpans
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
@ -19,12 +11,12 @@ import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegate
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.getSummary import org.koitharu.kotatsu.core.model.getSummary
import org.koitharu.kotatsu.core.model.getTitle
import org.koitharu.kotatsu.core.parser.favicon.faviconUri import org.koitharu.kotatsu.core.parser.favicon.faviconUri
import org.koitharu.kotatsu.core.ui.image.FaviconDrawable import org.koitharu.kotatsu.core.ui.image.FaviconDrawable
import org.koitharu.kotatsu.core.ui.list.OnTipCloseListener import org.koitharu.kotatsu.core.ui.list.OnTipCloseListener
import org.koitharu.kotatsu.core.util.ext.crossfade import org.koitharu.kotatsu.core.util.ext.crossfade
import org.koitharu.kotatsu.core.util.ext.enqueueWith import org.koitharu.kotatsu.core.util.ext.enqueueWith
import org.koitharu.kotatsu.core.util.ext.getThemeColor
import org.koitharu.kotatsu.core.util.ext.newImageRequest import org.koitharu.kotatsu.core.util.ext.newImageRequest
import org.koitharu.kotatsu.core.util.ext.source import org.koitharu.kotatsu.core.util.ext.source
import org.koitharu.kotatsu.databinding.ItemSourceConfigBinding import org.koitharu.kotatsu.databinding.ItemSourceConfigBinding
@ -51,15 +43,7 @@ fun sourceConfigItemCheckableDelegate(
} }
bind { bind {
binding.textViewTitle.text = if (item.isNsfw) { binding.textViewTitle.text = item.source.getTitle(context)
buildSpannedString {
append(item.source.title)
append(' ')
appendNsfwLabel(context)
}
} else {
item.source.title
}
binding.switchToggle.isChecked = item.isEnabled binding.switchToggle.isChecked = item.isEnabled
binding.switchToggle.isEnabled = item.isAvailable binding.switchToggle.isEnabled = item.isAvailable
binding.textViewDescription.text = item.source.getSummary(context) binding.textViewDescription.text = item.source.getSummary(context)
@ -101,15 +85,7 @@ fun sourceConfigItemDelegate2(
binding.imageViewMenu.setOnClickListener(eventListener) binding.imageViewMenu.setOnClickListener(eventListener)
bind { bind {
binding.textViewTitle.text = if (item.isNsfw) { binding.textViewTitle.text = item.source.getTitle(context)
buildSpannedString {
append(item.source.title)
append(' ')
appendNsfwLabel(context)
}
} else {
item.source.title
}
binding.imageViewAdd.isGone = item.isEnabled || !item.isAvailable binding.imageViewAdd.isGone = item.isEnabled || !item.isAvailable
binding.imageViewRemove.isVisible = item.isEnabled binding.imageViewRemove.isVisible = item.isEnabled
binding.imageViewMenu.isVisible = item.isEnabled binding.imageViewMenu.isVisible = item.isEnabled
@ -147,19 +123,6 @@ fun sourceConfigEmptySearchDelegate() =
R.layout.item_sources_empty, R.layout.item_sources_empty,
) { } ) { }
fun SpannableStringBuilder.appendNsfwLabel(context: Context) = inSpans(
ForegroundColorSpan(
context.getThemeColor(
com.google.android.material.R.attr.colorError,
Color.RED,
),
),
RelativeSizeSpan(0.74f),
SuperscriptSpan(),
) {
append(context.getString(R.string.nsfw))
}
private fun showSourceMenu( private fun showSourceMenu(
anchor: View, anchor: View,
item: SourceConfigItem.SourceItem, item: SourceConfigItem.SourceItem,

@ -1,13 +1,12 @@
package org.koitharu.kotatsu.settings.sources.catalog package org.koitharu.kotatsu.settings.sources.catalog
import androidx.core.text.buildSpannedString
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import coil.ImageLoader import coil.ImageLoader
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.getSummary import org.koitharu.kotatsu.core.model.getSummary
import org.koitharu.kotatsu.core.model.isNsfw import org.koitharu.kotatsu.core.model.getTitle
import org.koitharu.kotatsu.core.parser.favicon.faviconUri import org.koitharu.kotatsu.core.parser.favicon.faviconUri
import org.koitharu.kotatsu.core.ui.image.FaviconDrawable import org.koitharu.kotatsu.core.ui.image.FaviconDrawable
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
@ -18,7 +17,6 @@ import org.koitharu.kotatsu.core.util.ext.setTextAndVisible
import org.koitharu.kotatsu.core.util.ext.source import org.koitharu.kotatsu.core.util.ext.source
import org.koitharu.kotatsu.databinding.ItemEmptyHintBinding import org.koitharu.kotatsu.databinding.ItemEmptyHintBinding
import org.koitharu.kotatsu.databinding.ItemSourceCatalogBinding import org.koitharu.kotatsu.databinding.ItemSourceCatalogBinding
import org.koitharu.kotatsu.settings.sources.adapter.appendNsfwLabel
fun sourceCatalogItemSourceAD( fun sourceCatalogItemSourceAD(
coil: ImageLoader, coil: ImageLoader,
@ -35,15 +33,7 @@ fun sourceCatalogItemSourceAD(
} }
bind { bind {
binding.textViewTitle.text = if (item.source.isNsfw()) { binding.textViewTitle.text = item.source.getTitle(context)
buildSpannedString {
append(item.source.title)
append(' ')
appendNsfwLabel(context)
}
} else {
item.source.title
}
if (item.showSummary) { if (item.showSummary) {
binding.textViewDescription.text = item.source.getSummary(context) binding.textViewDescription.text = item.source.getSummary(context)
binding.textViewDescription.isVisible = true binding.textViewDescription.isVisible = true

Loading…
Cancel
Save