* fix(#391): resolve deprecation warnings - Icon: Icons.Filled.ArrowForward → Icons.AutoMirrored.Filled.ArrowForward (KanbanScreen) - Room: fallbackToDestructiveMigration() → fallbackToDestructiveMigration(false) (HermesDatabase) - Tab: ScrollableTabRow → PrimaryScrollableTabRow (SettingsScreen) - Clipboard: LocalClipboardManager → LocalClipboard + coroutine-scoped setText (ChatBubble: UserBubble, AssistantBubble, ToolBubble, CopyButton) - ClickableText: pushStringAnnotation → pushLink(LinkAnnotation.Url), ClickableText → Text with native link handling (ChatBubble: RichText) * fix(#392): replace deprecated setText with setClipEntry for new Clipboard API --------- Co-authored-by: M57 <hy4ri@users.noreply.github.com>
This commit is contained in:
1 parent
b1fca60511
commit
8d3d8a11e8
4 files changed
+30
-27
No files matched your search
@@ -39,7 +39,7 @@ abstract class HermesDatabase : RoomDatabase() {
|
||||
HermesDatabase::class.java,
|
||||
"hermes_control.db",
|
||||
).openHelperFactory(factory)
|
||||
.fallbackToDestructiveMigration()
|
||||
.fallbackToDestructiveMigration(false)
|
||||
.build()
|
||||
.also { instance = it }
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.m57.hermescontrol.ui.chat
|
||||
|
||||
import android.content.ClipData
|
||||
import android.text.format.DateFormat
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.animateContentSize
|
||||
@@ -27,7 +28,6 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.widthIn
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.ClickableText
|
||||
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Build
|
||||
@@ -47,6 +47,7 @@ import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -54,14 +55,15 @@ import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.luminance
|
||||
import androidx.compose.ui.platform.LocalClipboardManager
|
||||
import androidx.compose.ui.platform.ClipEntry
|
||||
import androidx.compose.ui.platform.LocalClipboard
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.LinkAnnotation
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
@@ -82,6 +84,7 @@ import com.m57.hermescontrol.theme.ToolChipColor
|
||||
import com.m57.hermescontrol.theme.ToolChipColorLight
|
||||
import com.m57.hermescontrol.theme.UserBubble
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import java.time.Instant
|
||||
import java.time.ZoneId
|
||||
import java.time.format.DateTimeFormatter
|
||||
@@ -141,7 +144,8 @@ private fun UserBubble(
|
||||
isCurrentMatch: Boolean = false,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val clipboardManager = LocalClipboardManager.current
|
||||
val clipboard = LocalClipboard.current
|
||||
val scope = rememberCoroutineScope()
|
||||
var showCopyButton by remember { mutableStateOf(false) }
|
||||
|
||||
// Auto-dismiss copy button after 4 seconds
|
||||
@@ -255,7 +259,9 @@ private fun UserBubble(
|
||||
) {
|
||||
IconButton(
|
||||
onClick = {
|
||||
clipboardManager.setText(AnnotatedString(message.content))
|
||||
scope.launch {
|
||||
clipboard.setClipEntry(ClipEntry(ClipData.newPlainText(null, message.content)))
|
||||
}
|
||||
showCopyButton = false
|
||||
},
|
||||
modifier = Modifier.size(32.dp),
|
||||
@@ -298,7 +304,8 @@ private fun AssistantBubble(
|
||||
Color(0xFFE8E6EE)
|
||||
}
|
||||
}
|
||||
val clipboardManager = LocalClipboardManager.current
|
||||
val clipboard = LocalClipboard.current
|
||||
val scope = rememberCoroutineScope()
|
||||
var showCopyButton by remember { mutableStateOf(false) }
|
||||
|
||||
// Auto-dismiss copy button after 4 seconds
|
||||
@@ -385,7 +392,9 @@ private fun AssistantBubble(
|
||||
) {
|
||||
IconButton(
|
||||
onClick = {
|
||||
clipboardManager.setText(AnnotatedString(message.content))
|
||||
scope.launch {
|
||||
clipboard.setClipEntry(ClipEntry(ClipData.newPlainText(null, message.content)))
|
||||
}
|
||||
showCopyButton = false
|
||||
},
|
||||
modifier = Modifier.size(32.dp),
|
||||
@@ -706,7 +715,8 @@ private fun ToolBubble(
|
||||
}
|
||||
val config = ToolSchemaRegistry.getDisplayConfig(message.toolName)
|
||||
|
||||
val clipboardManager = LocalClipboardManager.current
|
||||
val clipboard = LocalClipboard.current
|
||||
val scope = rememberCoroutineScope()
|
||||
var showCopyButton by remember { mutableStateOf(false) }
|
||||
|
||||
// Auto-dismiss copy button after 4 seconds
|
||||
@@ -775,7 +785,6 @@ private fun ToolBubble(
|
||||
CopyButton(
|
||||
visible = showCopyButton,
|
||||
textToCopy = message.content,
|
||||
clipboardManager = clipboardManager,
|
||||
onCopy = { showCopyButton = false },
|
||||
modifier =
|
||||
Modifier
|
||||
@@ -806,7 +815,6 @@ private fun ToolBubble(
|
||||
CopyButton(
|
||||
visible = showCopyButton,
|
||||
textToCopy = message.content,
|
||||
clipboardManager = clipboardManager,
|
||||
onCopy = { showCopyButton = false },
|
||||
modifier =
|
||||
Modifier
|
||||
@@ -845,7 +853,6 @@ private fun ToolBubble(
|
||||
CopyButton(
|
||||
visible = showCopyButton,
|
||||
textToCopy = message.content,
|
||||
clipboardManager = clipboardManager,
|
||||
onCopy = { showCopyButton = false },
|
||||
modifier =
|
||||
Modifier
|
||||
@@ -921,10 +928,11 @@ private fun HeaderRow(
|
||||
private fun CopyButton(
|
||||
visible: Boolean,
|
||||
textToCopy: String,
|
||||
clipboardManager: androidx.compose.ui.platform.ClipboardManager,
|
||||
onCopy: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val clipboard = LocalClipboard.current
|
||||
val scope = rememberCoroutineScope()
|
||||
AnimatedVisibility(
|
||||
visible = visible,
|
||||
enter = fadeIn() + scaleIn(),
|
||||
@@ -938,7 +946,9 @@ private fun CopyButton(
|
||||
) {
|
||||
IconButton(
|
||||
onClick = {
|
||||
clipboardManager.setText(AnnotatedString(textToCopy))
|
||||
scope.launch {
|
||||
clipboard.setClipEntry(ClipEntry(ClipData.newPlainText(null, textToCopy)))
|
||||
}
|
||||
onCopy()
|
||||
},
|
||||
modifier = Modifier.size(32.dp),
|
||||
@@ -964,7 +974,6 @@ private fun RichText(
|
||||
searchQuery: String = "",
|
||||
isCurrentMatch: Boolean = false,
|
||||
) {
|
||||
val uriHandler = LocalUriHandler.current
|
||||
val urlPattern = remember { Regex("""https?://[^\s)>\]\u0022\u0027]+""") }
|
||||
val linkColor = MaterialTheme.colorScheme.primary
|
||||
val searchHighlightColor = if (isCurrentMatch) Color(0xFFF57C00) else Color(0xFFFFF176).copy(alpha = 0.9f)
|
||||
@@ -1033,7 +1042,7 @@ private fun RichText(
|
||||
// URL: https://...
|
||||
urlPattern.matchAt(src, i) != null -> {
|
||||
val match = urlPattern.matchAt(src, i)!!
|
||||
pushStringAnnotation(tag = "URL", annotation = match.value)
|
||||
pushLink(LinkAnnotation.Url(match.value))
|
||||
withStyle(
|
||||
SpanStyle(
|
||||
color = linkColor,
|
||||
@@ -1064,15 +1073,9 @@ private fun RichText(
|
||||
}
|
||||
}
|
||||
|
||||
ClickableText(
|
||||
Text(
|
||||
text = annotated,
|
||||
style = MaterialTheme.typography.bodyMedium.copy(color = textColor),
|
||||
onClick = { offset: Int ->
|
||||
annotated
|
||||
.getStringAnnotations("URL", offset, offset)
|
||||
.firstOrNull()
|
||||
?.let { uriHandler.openUri(it.item) }
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.ArrowForward
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowForward
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
@@ -253,7 +253,7 @@ fun TaskCard(
|
||||
if (onMoveRight != null) {
|
||||
IconButton(onClick = onMoveRight) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.ArrowForward,
|
||||
imageVector = Icons.AutoMirrored.Filled.ArrowForward,
|
||||
contentDescription = stringResource(R.string.content_desc_move_right),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.OutlinedTextFieldDefaults
|
||||
import androidx.compose.material3.ScrollableTabRow
|
||||
import androidx.compose.material3.PrimaryScrollableTabRow
|
||||
import androidx.compose.material3.SegmentedButton
|
||||
import androidx.compose.material3.SegmentedButtonDefaults
|
||||
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
|
||||
@@ -101,7 +101,7 @@ fun SettingsScreen(
|
||||
Modifier
|
||||
.fillMaxSize(),
|
||||
) {
|
||||
ScrollableTabRow(
|
||||
PrimaryScrollableTabRow(
|
||||
selectedTabIndex = selectedTab.ordinal,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
edgePadding = 0.dp,
|
||||
|
||||
Reference in new issue
Block a user