From 57113014ecaa26f779451a9526fb4f1ccd349f71 Mon Sep 17 00:00:00 2001 From: 0x7673 <123292609+0x7673@users.noreply.github.com> Date: Tue, 14 Feb 2023 09:22:10 +0530 Subject: [PATCH] Add copy tags to clipboard feature (#9063) (cherry picked from commit d02b0ca2db744b0eca48dfca86811d653fd3bdaf) # Conflicts: # app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt # app/src/main/java/eu/kanade/presentation/manga/components/MangaInfoHeader.kt --- .../kanade/presentation/manga/MangaScreen.kt | 37 +++++++++--- .../manga/components/MangaInfoHeader.kt | 57 +++++++++++++++---- .../manga/components/NamespaceTags.kt | 5 +- .../source/browse/BrowseSourceScreenModel.kt | 2 +- .../kanade/tachiyomi/ui/manga/MangaScreen.kt | 2 +- i18n/src/main/res/values/strings.xml | 1 + 6 files changed, 80 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt b/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt index 56396c2c0..81b96ab6d 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt @@ -85,6 +85,7 @@ import eu.kanade.tachiyomi.ui.manga.MangaScreenState import eu.kanade.tachiyomi.ui.manga.PagePreviewState import eu.kanade.tachiyomi.ui.manga.chapterDecimalFormat import eu.kanade.tachiyomi.util.lang.toRelativeString +import eu.kanade.tachiyomi.util.system.copyToClipboard import exh.metadata.MetadataUtil import exh.source.MERGED_SOURCE_ID import exh.source.getMainSource @@ -115,7 +116,10 @@ fun MangaScreen( onWebViewClicked: (() -> Unit)?, onWebViewLongClicked: (() -> Unit)?, onTrackingClicked: (() -> Unit)?, - onTagClicked: (String) -> Unit, + + // For tags menu + onTagSearch: (String) -> Unit, + onFilterButtonClicked: () -> Unit, onRefresh: () -> Unit, onContinueReading: () -> Unit, @@ -151,6 +155,13 @@ fun MangaScreen( onAllChapterSelected: (Boolean) -> Unit, onInvertSelection: () -> Unit, ) { + val context = LocalContext.current + val onCopyTagToClipboard: (tag: String) -> Unit = { + if (it.isNotEmpty()) { + context.copyToClipboard(it, it) + } + } + if (!isTabletUi) { MangaScreenSmallImpl( state = state, @@ -164,7 +175,8 @@ fun MangaScreen( onWebViewClicked = onWebViewClicked, onWebViewLongClicked = onWebViewLongClicked, onTrackingClicked = onTrackingClicked, - onTagClicked = onTagClicked, + onTagSearch = onTagSearch, + onCopyTagToClipboard = onCopyTagToClipboard, onFilterClicked = onFilterButtonClicked, onRefresh = onRefresh, onContinueReading = onContinueReading, @@ -205,7 +217,8 @@ fun MangaScreen( onWebViewClicked = onWebViewClicked, onWebViewLongClicked = onWebViewLongClicked, onTrackingClicked = onTrackingClicked, - onTagClicked = onTagClicked, + onTagSearch = onTagSearch, + onCopyTagToClipboard = onCopyTagToClipboard, onFilterButtonClicked = onFilterButtonClicked, onRefresh = onRefresh, onContinueReading = onContinueReading, @@ -249,7 +262,11 @@ private fun MangaScreenSmallImpl( onWebViewClicked: (() -> Unit)?, onWebViewLongClicked: (() -> Unit)?, onTrackingClicked: (() -> Unit)?, - onTagClicked: (String) -> Unit, + + // For tags menu + onTagSearch: (String) -> Unit, + onCopyTagToClipboard: (tag: String) -> Unit, + onFilterClicked: () -> Unit, onRefresh: () -> Unit, onContinueReading: () -> Unit, @@ -454,7 +471,8 @@ private fun MangaScreenSmallImpl( defaultExpandState = state.isFromSource, description = state.manga.description, tagsProvider = { state.manga.genre }, - onTagClicked = onTagClicked, + onTagSearch = onTagSearch, + onCopyTagToClipboard = onCopyTagToClipboard, // SY --> doSearch = onSearch, searchMetadataChips = remember(state.meta, state.source.id, state.manga.genre) { @@ -535,7 +553,11 @@ fun MangaScreenLargeImpl( onWebViewClicked: (() -> Unit)?, onWebViewLongClicked: (() -> Unit)?, onTrackingClicked: (() -> Unit)?, - onTagClicked: (String) -> Unit, + + // For tags menu + onTagSearch: (String) -> Unit, + onCopyTagToClipboard: (tag: String) -> Unit, + onFilterButtonClicked: () -> Unit, onRefresh: () -> Unit, onContinueReading: () -> Unit, @@ -714,7 +736,8 @@ fun MangaScreenLargeImpl( defaultExpandState = true, description = state.manga.description, tagsProvider = { state.manga.genre }, - onTagClicked = onTagClicked, + onTagSearch = onTagSearch, + onCopyTagToClipboard = onCopyTagToClipboard, // SY --> doSearch = onSearch, searchMetadataChips = remember(state.meta, state.source.id, state.manga.genre) { diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/MangaInfoHeader.kt b/app/src/main/java/eu/kanade/presentation/manga/components/MangaInfoHeader.kt index 749af69ae..1cf537c4f 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/components/MangaInfoHeader.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/components/MangaInfoHeader.kt @@ -36,6 +36,7 @@ import androidx.compose.material.icons.outlined.Pause import androidx.compose.material.icons.outlined.Public import androidx.compose.material.icons.outlined.Schedule import androidx.compose.material.icons.outlined.Sync +import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.Icon import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme @@ -70,6 +71,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import coil.compose.AsyncImage import com.google.accompanist.flowlayout.FlowRow +import eu.kanade.presentation.components.DropdownMenu import eu.kanade.presentation.components.MangaCover import eu.kanade.presentation.components.TextButton import eu.kanade.presentation.util.clickableNoIndication @@ -221,7 +223,8 @@ fun ExpandableMangaDescription( defaultExpandState: Boolean, description: String?, tagsProvider: () -> List?, - onTagClicked: (String) -> Unit, + onTagSearch: (String) -> Unit, + onCopyTagToClipboard: (tag: String) -> Unit, // SY --> searchMetadataChips: SearchMetadataChips?, doSearch: (query: String, global: Boolean) -> Unit, @@ -255,13 +258,45 @@ fun ExpandableMangaDescription( .padding(vertical = 12.dp) .animateContentSize(), ) { + var showMenu by remember { mutableStateOf(false) } + var tagSelected by remember { mutableStateOf("") } + DropdownMenu( + expanded = showMenu, + onDismissRequest = { showMenu = false }, + ) { + DropdownMenuItem( + text = { Text(text = stringResource(R.string.action_search)) }, + onClick = { + onTagSearch(tagSelected) + showMenu = false + }, + ) + // SY --> + DropdownMenuItem( + text = { Text(text = stringResource(R.string.action_global_search)) }, + onClick = { + doSearch(tagSelected, true) + showMenu = false + }, + ) + // SY <-- + DropdownMenuItem( + text = { Text(text = stringResource(R.string.action_copy_to_clipboard)) }, + onClick = { + onCopyTagToClipboard(tagSelected) + showMenu = false + }, + ) + } if (expanded) { // SY --> if (searchMetadataChips != null) { NamespaceTags( tags = searchMetadataChips, - onClick = onTagClicked, - onLongClick = { doSearch(it, true) }, + onClick = { + tagSelected = it + showMenu = true + }, ) } else { // SY <-- @@ -273,10 +308,10 @@ fun ExpandableMangaDescription( tags.forEach { TagsChip( text = it, - onClick = { onTagClicked(it) }, - // SY --> - onLongClick = { doSearch(it, true) }, - // SY <-- + onClick = { + tagSelected = it + showMenu = true + }, ) } } @@ -289,10 +324,10 @@ fun ExpandableMangaDescription( items(items = tags) { TagsChip( text = it, - onClick = { onTagClicked(it) }, - // SY --> - onLongClick = { doSearch(it, true) }, - // SY <-- + onClick = { + tagSelected = it + showMenu = true + }, ) } } diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/NamespaceTags.kt b/app/src/main/java/eu/kanade/presentation/manga/components/NamespaceTags.kt index be1112f1a..6135310de 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/components/NamespaceTags.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/components/NamespaceTags.kt @@ -98,7 +98,6 @@ value class SearchMetadataChips( fun NamespaceTags( tags: SearchMetadataChips, onClick: (item: String) -> Unit, - onLongClick: (item: String) -> Unit, ) { Column(Modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(4.dp)) { tags.tags.forEach { (namespace, tags) -> @@ -116,7 +115,6 @@ fun NamespaceTags( TagsChip( text = text, onClick = { onClick(search) }, - onLongClick = { onLongClick(search) }, border = borderDp?.let { SuggestionChipDefaults.suggestionChipBorder(borderWidth = it) }, @@ -135,7 +133,7 @@ fun NamespaceTags( fun TagsChip( text: String, onClick: (() -> Unit)?, - onLongClick: (() -> Unit)?, + onLongClick: (() -> Unit)? = null, border: ChipBorder? = null, borderM3: ChipBorderM3? = null, ) { @@ -243,7 +241,6 @@ fun NamespaceTagsPreview() { }.let { SearchMetadataChips(it, EHentai(EXH_SOURCE_ID, true, context), emptyList()) }!! }, onClick = {}, - onLongClick = {}, ) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt index 93dab5c51..c848d11c6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt @@ -225,7 +225,7 @@ open class BrowseSourceScreenModel( .combineMetadata(dbManga, metadata) // SY <-- .stateIn(coroutineScope) - } + } } .cachedIn(coroutineScope) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt index 4f024bcfe..c49f83ff6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt @@ -161,7 +161,7 @@ class MangaScreen( // SY <-- onWebViewLongClicked = { copyMangaUrl(context, screenModel.manga, screenModel.source) }.takeIf { isHttpSource }, onTrackingClicked = screenModel::showTrackDialog.takeIf { successState.trackingAvailable }, - onTagClicked = { scope.launch { performGenreSearch(navigator, it, screenModel.source!!) } }, + onTagSearch = { scope.launch { performGenreSearch(navigator, it, screenModel.source!!) } }, onFilterButtonClicked = screenModel::showSettingsDialog, onRefresh = screenModel::fetchAllFromSource, onContinueReading = { continueReading(context, screenModel.getNextUnreadChapter()) }, diff --git a/i18n/src/main/res/values/strings.xml b/i18n/src/main/res/values/strings.xml index 5baf806a0..53cc42fcb 100755 --- a/i18n/src/main/res/values/strings.xml +++ b/i18n/src/main/res/values/strings.xml @@ -96,6 +96,7 @@ Resume Open in browser Show entry + Copy to clipboard Open in WebView WebView