From 97090a4dc60adc908cb7792ced8dd7a100cb4978 Mon Sep 17 00:00:00 2001 From: tarsin Date: Sun, 2 Jul 2023 12:01:21 +0800 Subject: [PATCH] Refactor out GalleryTag --- .../hippo/ehviewer/client/EhTagDatabase.kt | 8 +- .../com/hippo/ehviewer/ui/main/GalleryTag.kt | 94 ++++++++++++++++ .../ehviewer/ui/scene/GalleryDetailScene.kt | 104 +++--------------- .../hippo/ehviewer/ui/scene/SearchBarScene.kt | 2 +- 4 files changed, 113 insertions(+), 95 deletions(-) create mode 100644 app/src/main/java/com/hippo/ehviewer/ui/main/GalleryTag.kt diff --git a/app/src/main/java/com/hippo/ehviewer/client/EhTagDatabase.kt b/app/src/main/java/com/hippo/ehviewer/client/EhTagDatabase.kt index e292f61c7..3cd933b7b 100644 --- a/app/src/main/java/com/hippo/ehviewer/client/EhTagDatabase.kt +++ b/app/src/main/java/com/hippo/ehviewer/client/EhTagDatabase.kt @@ -16,6 +16,9 @@ package com.hippo.ehviewer.client import android.content.Context +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue import com.hippo.ehviewer.AppConfig import com.hippo.ehviewer.EhApplication.Companion.nonCacheOkHttpClient import com.hippo.ehviewer.R @@ -58,9 +61,7 @@ object EhTagDatabase : CoroutineScope { private val dbLock = Mutex() override val coroutineContext = Dispatchers.IO + Job() - fun isInitialized(): Boolean { - return this::tagGroups.isInitialized - } + var initialized by mutableStateOf(false) private fun JSONObject.toTagGroups(): TagGroups = keys().asSequence().associateWith { getJSONObject(it).toTagGroup() } @@ -220,6 +221,7 @@ object EhTagDatabase : CoroutineScope { tagGroups = JSONObject( dataFile.source().buffer().readString(StandardCharsets.UTF_8), ).toTagGroups() + initialized = true }.onFailure { it.printStackTrace() } diff --git a/app/src/main/java/com/hippo/ehviewer/ui/main/GalleryTag.kt b/app/src/main/java/com/hippo/ehviewer/ui/main/GalleryTag.kt new file mode 100644 index 000000000..1fab6a7b4 --- /dev/null +++ b/app/src/main/java/com/hippo/ehviewer/ui/main/GalleryTag.kt @@ -0,0 +1,94 @@ +package com.hippo.ehviewer.ui.main + +import androidx.compose.foundation.combinedClickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.FlowRow +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.hapticfeedback.HapticFeedbackType +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalHapticFeedback +import androidx.compose.ui.unit.dp +import com.hippo.ehviewer.Settings +import com.hippo.ehviewer.client.EhTagDatabase +import com.hippo.ehviewer.client.data.GalleryTagGroup +import com.hippo.ehviewer.ui.tools.includeFontPadding + +@Composable +fun GalleryTags( + tags: Array, + onTagClick: (String) -> Unit, + onTagLongClick: (String, String) -> Unit, + modifier: Modifier = Modifier, +) { + val context = LocalContext.current + val canTranslate = Settings.showTagTranslations && EhTagDatabase.isTranslatable(context) && EhTagDatabase.initialized + val ehTags = EhTagDatabase.takeIf { canTranslate } + fun String.translate() = ehTags?.takeIf { it.initialized }?.getTranslation(tag = this) ?: this + fun String.translate(prefix: String?) = ehTags?.takeIf { it.initialized }?.getTranslation(prefix = prefix, tag = this) ?: this + Column(modifier) { + tags.forEach { + Row { + it.groupName?.run { + BaseRoundText( + text = translate(), + isGroup = true, + ) + val prefix = EhTagDatabase.namespaceToPrefix(this) + FlowRow { + it.forEach { + val weak = it.startsWith('_') + val real = it.removePrefix("_") + val translated = real.translate(prefix) + val tag = this@run + ":" + real + val hapticFeedback = LocalHapticFeedback.current + BaseRoundText( + text = translated, + weak = weak, + modifier = Modifier.combinedClickable( + onClick = { onTagClick(tag) }, + onLongClick = { + hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) + onTagLongClick(translated, tag) + }, + ), + ) + } + } + } + } + } + } +} + +@Composable +private fun BaseRoundText( + text: String, + modifier: Modifier = Modifier, + weak: Boolean = false, + isGroup: Boolean = false, +) { + val bgColor = if (isGroup) { + MaterialTheme.colorScheme.primaryContainer + } else { + MaterialTheme.colorScheme.tertiaryContainer + } + Surface( + modifier = Modifier.padding(4.dp), + color = bgColor, + shape = RoundedCornerShape(64.dp), + ) { + Text( + text = text, + modifier = modifier.padding(horizontal = 12.dp, vertical = 4.dp), + color = MaterialTheme.colorScheme.onSurface.let { if (weak) it.copy(0.5F) else it }, + style = MaterialTheme.typography.labelLarge.includeFontPadding, + ) + } +} diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.kt b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.kt index 41ae31f29..d25ae883d 100755 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.kt +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.kt @@ -34,7 +34,6 @@ import android.widget.AdapterView import android.widget.ArrayAdapter import androidx.activity.result.contract.ActivityResultContracts import androidx.annotation.StringRes -import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -53,7 +52,6 @@ import androidx.compose.foundation.lazy.grid.GridItemSpan import androidx.compose.foundation.lazy.grid.LazyGridScope import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.items -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.CloudDone @@ -72,7 +70,6 @@ import androidx.compose.material3.FilledTonalButton import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.LargeTopAppBar -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.material3.Text @@ -90,11 +87,9 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.layout.LocalPinnableContainer import androidx.compose.ui.platform.ComposeView -import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp @@ -113,9 +108,6 @@ import com.hippo.ehviewer.Settings import com.hippo.ehviewer.client.EhCookieStore import com.hippo.ehviewer.client.EhEngine import com.hippo.ehviewer.client.EhFilter.remember -import com.hippo.ehviewer.client.EhTagDatabase -import com.hippo.ehviewer.client.EhTagDatabase.isTranslatable -import com.hippo.ehviewer.client.EhTagDatabase.namespaceToPrefix import com.hippo.ehviewer.client.EhUrl import com.hippo.ehviewer.client.EhUtils import com.hippo.ehviewer.client.data.GalleryComment @@ -155,6 +147,7 @@ import com.hippo.ehviewer.ui.legacy.calculateSuitableSpanCount import com.hippo.ehviewer.ui.main.EhPreviewItem import com.hippo.ehviewer.ui.main.GalleryDetailErrorTip import com.hippo.ehviewer.ui.main.GalleryDetailHeaderCard +import com.hippo.ehviewer.ui.main.GalleryTags import com.hippo.ehviewer.ui.navToReader import com.hippo.ehviewer.ui.openBrowser import com.hippo.ehviewer.ui.removeFromFavorites @@ -164,7 +157,6 @@ import com.hippo.ehviewer.ui.tools.CrystalCard import com.hippo.ehviewer.ui.tools.FilledTertiaryIconButton import com.hippo.ehviewer.ui.tools.FilledTertiaryIconToggleButton import com.hippo.ehviewer.ui.tools.GalleryDetailRating -import com.hippo.ehviewer.ui.tools.includeFontPadding import com.hippo.ehviewer.util.AppHelper import com.hippo.ehviewer.util.ExceptionUtils import com.hippo.ehviewer.util.ReadableTime @@ -744,7 +736,18 @@ class GalleryDetailScene : BaseScene(), DownloadInfoListener { Text(text = stringResource(id = R.string.no_tags)) } } else { - GalleryDetailTags(tags) + GalleryTags( + tags = tags, + onTagClick = { + val lub = ListUrlBuilder() + lub.mode = ListUrlBuilder.MODE_TAG + lub.keyword = it + navAnimated(R.id.galleryListScene, lub.toStartArgs(), true) + }, + onTagLongClick = { translation, realTag -> + showTagDialog(translation, realTag) + }, + ) } Spacer(modifier = Modifier.size(dimensionResource(id = R.dimen.keyline_margin))) if (Settings.showComments) { @@ -967,87 +970,6 @@ class GalleryDetailScene : BaseScene(), DownloadInfoListener { torrentText = resources.getString(R.string.torrent_count, gd.torrentCount) } - @Composable - private fun GalleryDetailTags(tagGroups: Array) { - @Composable - fun baseRoundText( - text: String, - weak: Boolean = false, - isGroup: Boolean = false, - modifier: Modifier = Modifier, - ) { - val bgColor = if (isGroup) { - MaterialTheme.colorScheme.primaryContainer - } else { - MaterialTheme.colorScheme.tertiaryContainer - } - Surface( - modifier = Modifier.padding(4.dp), - color = bgColor, - shape = RoundedCornerShape(64.dp), - ) { - Text( - text = text, - modifier = modifier.padding(horizontal = 12.dp, vertical = 4.dp), - color = MaterialTheme.colorScheme.onSurface.let { if (weak) it.copy(0.5F) else it }, - style = MaterialTheme.typography.labelLarge.includeFontPadding, - ) - } - } - - val canTranslate = Settings.showTagTranslations && isTranslatable(requireContext()) - val ehTags = EhTagDatabase.takeIf { canTranslate } - fun String.translate(): String { - return ehTags?.takeIf { it.isInitialized() }?.getTranslation(tag = this) ?: this - } - - fun String.translate(prefix: String?): String { - return ehTags?.takeIf { it.isInitialized() } - ?.getTranslation(prefix = prefix, tag = this) ?: this - } - - tagGroups.forEach { - Row { - it.groupName?.run { - baseRoundText( - text = translate(), - isGroup = true, - ) - val prefix = namespaceToPrefix(this) - FlowRow { - it.forEach { - val weak = it.startsWith('_') - val real = it.removePrefix("_") - val translated = real.translate(prefix) - val tag = this@run + ":" + real - fun onClick() { - val lub = ListUrlBuilder() - lub.mode = ListUrlBuilder.MODE_TAG - lub.keyword = tag - navAnimated(R.id.galleryListScene, lub.toStartArgs(), true) - } - - val hapticFeedback = LocalHapticFeedback.current - - fun onLongClick() { - hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) - showTagDialog(translated, tag) - } - baseRoundText( - text = translated, - weak = weak, - modifier = Modifier.combinedClickable( - onClick = ::onClick, - onLongClick = ::onLongClick, - ), - ) - } - } - } - } - } - } - private fun onNavigateToCommentScene() { val galleryDetail = composeBindingGD ?: return val args = Bundle() diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/SearchBarScene.kt b/app/src/main/java/com/hippo/ehviewer/ui/scene/SearchBarScene.kt index 9b5b84d48..ea33c649e 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/SearchBarScene.kt +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/SearchBarScene.kt @@ -329,7 +329,7 @@ abstract class SearchBarScene : BaseScene(), ToolBarScene { binding.searchview.editText.text?.toString()?.let { text -> mSuggestionProvider?.run { providerSuggestions(text)?.forEach { emit(it) } } mSearchDatabase.suggestions(text, 128).forEach { emit(KeywordSuggestion(it)) } - EhTagDatabase.takeIf { it.isInitialized() }?.run { + EhTagDatabase.takeIf { it.initialized }?.run { if (text.isNotEmpty() && !text.endsWith(' ')) { val keyword = text.substringAfterLast(' ') val translate = Settings.showTagTranslations && isTranslatable(requireContext())