From 8d3d8a11e821574114a700daef820f4324f37718 Mon Sep 17 00:00:00 2001 From: M57 <41645758+Hy4ri@users.noreply.github.com> Date: Fri, 26 Jun 2026 05:25:01 +0300 Subject: [PATCH] fix(#391): resolve 5 deprecation warnings (#392) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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 --- .../data/local/HermesDatabase.kt | 2 +- .../m57/hermescontrol/ui/chat/ChatBubble.kt | 47 ++++++++++--------- .../hermescontrol/ui/kanban/KanbanScreen.kt | 4 +- .../ui/settings/SettingsScreen.kt | 4 +- 4 files changed, 30 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/com/m57/hermescontrol/data/local/HermesDatabase.kt b/app/src/main/java/com/m57/hermescontrol/data/local/HermesDatabase.kt index 2ecf99ef..a86b1f5b 100644 --- a/app/src/main/java/com/m57/hermescontrol/data/local/HermesDatabase.kt +++ b/app/src/main/java/com/m57/hermescontrol/data/local/HermesDatabase.kt @@ -39,7 +39,7 @@ abstract class HermesDatabase : RoomDatabase() { HermesDatabase::class.java, "hermes_control.db", ).openHelperFactory(factory) - .fallbackToDestructiveMigration() + .fallbackToDestructiveMigration(false) .build() .also { instance = it } } diff --git a/app/src/main/java/com/m57/hermescontrol/ui/chat/ChatBubble.kt b/app/src/main/java/com/m57/hermescontrol/ui/chat/ChatBubble.kt index c66cbd2a..e2d9fb30 100644 --- a/app/src/main/java/com/m57/hermescontrol/ui/chat/ChatBubble.kt +++ b/app/src/main/java/com/m57/hermescontrol/ui/chat/ChatBubble.kt @@ -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) } - }, ) } diff --git a/app/src/main/java/com/m57/hermescontrol/ui/kanban/KanbanScreen.kt b/app/src/main/java/com/m57/hermescontrol/ui/kanban/KanbanScreen.kt index 28a9772d..e07a1716 100644 --- a/app/src/main/java/com/m57/hermescontrol/ui/kanban/KanbanScreen.kt +++ b/app/src/main/java/com/m57/hermescontrol/ui/kanban/KanbanScreen.kt @@ -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), ) } diff --git a/app/src/main/java/com/m57/hermescontrol/ui/settings/SettingsScreen.kt b/app/src/main/java/com/m57/hermescontrol/ui/settings/SettingsScreen.kt index cfae4e0f..39e2a2cf 100644 --- a/app/src/main/java/com/m57/hermescontrol/ui/settings/SettingsScreen.kt +++ b/app/src/main/java/com/m57/hermescontrol/ui/settings/SettingsScreen.kt @@ -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,