浏览代码

[track-search] Added context menu for copy and open-in-web (#10352)

Caleb Morris 1 年之前
父节点
当前提交
a8040cb21a
共有 1 个文件被更改,包括 69 次插入22 次删除
  1. 69 22
      app/src/main/java/eu/kanade/presentation/track/TrackerSearch.kt

+ 69 - 22
app/src/main/java/eu/kanade/presentation/track/TrackerSearch.kt

@@ -7,6 +7,7 @@ import androidx.compose.animation.slideInVertically
 import androidx.compose.animation.slideOutVertically
 import androidx.compose.foundation.background
 import androidx.compose.foundation.border
+import androidx.compose.foundation.combinedClickable
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
@@ -22,7 +23,6 @@ import androidx.compose.foundation.layout.paddingFromBaseline
 import androidx.compose.foundation.layout.width
 import androidx.compose.foundation.layout.windowInsetsPadding
 import androidx.compose.foundation.lazy.items
-import androidx.compose.foundation.selection.selectable
 import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.foundation.text.BasicTextField
 import androidx.compose.foundation.text.KeyboardActions
@@ -33,6 +33,7 @@ import androidx.compose.material.icons.filled.CheckCircle
 import androidx.compose.material.icons.filled.Close
 import androidx.compose.material3.Button
 import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.DropdownMenuItem
 import androidx.compose.material3.HorizontalDivider
 import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
@@ -40,7 +41,10 @@ import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
 import androidx.compose.material3.TopAppBar
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.clip
@@ -48,7 +52,11 @@ import androidx.compose.ui.focus.FocusRequester
 import androidx.compose.ui.focus.focusRequester
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.SolidColor
+import androidx.compose.ui.platform.ClipboardManager
+import androidx.compose.ui.platform.LocalClipboardManager
+import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.platform.LocalFocusManager
+import androidx.compose.ui.text.AnnotatedString
 import androidx.compose.ui.text.capitalize
 import androidx.compose.ui.text.input.ImeAction
 import androidx.compose.ui.text.input.TextFieldValue
@@ -58,9 +66,11 @@ import androidx.compose.ui.text.toLowerCase
 import androidx.compose.ui.tooling.preview.PreviewLightDark
 import androidx.compose.ui.tooling.preview.PreviewParameter
 import androidx.compose.ui.unit.dp
+import eu.kanade.presentation.components.DropdownMenu
 import eu.kanade.presentation.manga.components.MangaCover
 import eu.kanade.presentation.theme.TachiyomiTheme
 import eu.kanade.tachiyomi.data.track.model.TrackSearch
+import eu.kanade.tachiyomi.util.system.openInBrowser
 import tachiyomi.i18n.MR
 import tachiyomi.presentation.core.components.ScrollbarLazyColumn
 import tachiyomi.presentation.core.components.material.Scaffold
@@ -188,13 +198,7 @@ fun TrackerSearch(
                             key = { it.hashCode() },
                         ) {
                             SearchResultItem(
-                                title = it.title,
-                                coverUrl = it.cover_url,
-                                type = it.publishing_type.toLowerCase(Locale.current).capitalize(Locale.current),
-                                startDate = it.start_date,
-                                status = it.publishing_status.toLowerCase(Locale.current).capitalize(Locale.current),
-                                score = it.score,
-                                description = it.summary.trim(),
+                                trackSearch = it,
                                 selected = it == selected,
                                 onClick = { onSelectedChange(it) },
                             )
@@ -214,18 +218,18 @@ fun TrackerSearch(
 
 @Composable
 private fun SearchResultItem(
-    title: String,
-    coverUrl: String,
-    type: String,
-    startDate: String,
-    status: String,
-    score: Float,
-    description: String,
+    trackSearch: TrackSearch,
     selected: Boolean,
     onClick: () -> Unit,
 ) {
+    val context = LocalContext.current
+    val clipboardManager: ClipboardManager = LocalClipboardManager.current
+    val type = trackSearch.publishing_type.toLowerCase(Locale.current).capitalize(Locale.current)
+    val status = trackSearch.publishing_status.toLowerCase(Locale.current).capitalize(Locale.current)
+    val description = trackSearch.summary.trim()
     val shape = RoundedCornerShape(16.dp)
     val borderColor = if (selected) MaterialTheme.colorScheme.outline else Color.Transparent
+    var dropDownMenuExpanded by remember { mutableStateOf(false) }
     Box(
         modifier = Modifier
             .fillMaxWidth()
@@ -237,7 +241,10 @@ private fun SearchResultItem(
                 color = borderColor,
                 shape = shape,
             )
-            .selectable(selected = selected, onClick = onClick)
+            .combinedClickable(
+                onLongClick = { dropDownMenuExpanded = true },
+                onClick = onClick,
+            )
             .padding(12.dp),
     ) {
         if (selected) {
@@ -251,28 +258,41 @@ private fun SearchResultItem(
         Column {
             Row {
                 MangaCover.Book(
-                    data = coverUrl,
+                    data = trackSearch.cover_url,
                     modifier = Modifier.height(96.dp),
                 )
                 Spacer(modifier = Modifier.width(12.dp))
                 Column {
                     Text(
-                        text = title,
+                        text = trackSearch.title,
                         modifier = Modifier.padding(end = 28.dp),
                         maxLines = 2,
                         overflow = TextOverflow.Ellipsis,
                         style = MaterialTheme.typography.titleMedium,
                     )
+                    SearchResultItemDropDownMenu(
+                        expanded = dropDownMenuExpanded,
+                        onCollapseMenu = { dropDownMenuExpanded = false },
+                        onCopyName = {
+                            clipboardManager.setText(AnnotatedString(trackSearch.title))
+                        },
+                        onOpenInBrowser = {
+                            val url = trackSearch.tracking_url
+                            if (url.isNotBlank()) {
+                                context.openInBrowser(url)
+                            }
+                        },
+                    )
                     if (type.isNotBlank()) {
                         SearchResultItemDetails(
                             title = stringResource(MR.strings.track_type),
                             text = type,
                         )
                     }
-                    if (startDate.isNotBlank()) {
+                    if (trackSearch.start_date.isNotBlank()) {
                         SearchResultItemDetails(
                             title = stringResource(MR.strings.label_started),
-                            text = startDate,
+                            text = trackSearch.start_date,
                         )
                     }
                     if (status.isNotBlank()) {
@@ -281,10 +301,10 @@ private fun SearchResultItem(
                             text = status,
                         )
                     }
-                    if (score != -1f) {
+                    if (trackSearch.score != -1f) {
                         SearchResultItemDetails(
                             title = stringResource(MR.strings.score),
-                            text = score.toString(),
+                            text = trackSearch.score.toString(),
                         )
                     }
                 }
@@ -304,6 +324,33 @@ private fun SearchResultItem(
     }
 }
 
+@Composable
+private fun SearchResultItemDropDownMenu(
+    expanded: Boolean,
+    onCollapseMenu: () -> Unit,
+    onCopyName: () -> Unit,
+    onOpenInBrowser: () -> Unit,
+) {
+    DropdownMenu(
+        expanded = expanded,
+        onDismissRequest = onCollapseMenu,
+    ) {
+        DropdownMenuItem(
+            text = { Text(stringResource(MR.strings.action_copy_to_clipboard)) },
+            onClick = {
+                onCopyName()
+                onCollapseMenu()
+            },
+        )
+        DropdownMenuItem(
+            text = { Text(stringResource(MR.strings.action_open_in_browser)) },
+            onClick = {
+                onOpenInBrowser()
+            },
+        )
+    }
+}
+
 @Composable
 private fun SearchResultItemDetails(
     title: String,