|
@@ -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,
|