use annotated string in tv

This commit is contained in:
2026-08-09 16:55:53 +03:00
parent 009e25b846
commit c17a0732ad
2 changed files with 26 additions and 21 deletions
+1 -1
View File
@@ -7,7 +7,7 @@ plugins {
alias(libs.plugins.convention.ktor.client) alias(libs.plugins.convention.ktor.client)
} }
val appVersion = "1.25.3" val appVersion = "1.25.4"
android { android {
buildFeatures { buildConfig = true } buildFeatures { buildConfig = true }
@@ -235,25 +235,24 @@ private fun MessageBubble(
val focusedColor = MaterialTheme.colorScheme.error val focusedColor = MaterialTheme.colorScheme.error
val isTv = isTv() val isTv = isTv()
val annotatedString = remember(tokens) { val annotatedString = remember(tokens) {
if (isTv) { buildText(isTv, tokens, primaryColor, focusedColor, onClickLink)
buildAnnotatedString { append(message.content) }
} else {
buildText(tokens, primaryColor, focusedColor, onClickLink)
}
} }
val itemFocusRequester = remember { FocusRequester() }
var dialog by remember { mutableStateOf(false) } var dialog by remember { mutableStateOf(false) }
var boxModifier = Modifier.widthIn(max = 280.dp) var boxModifier = Modifier.widthIn(max = 280.dp)
if (isTv) { if (isTv) {
boxModifier = boxModifier.focusBorder(false).onKeyEvent { boxModifier = boxModifier.focusRequester(itemFocusRequester)
if (it.type == KeyEventType.KeyDown) { .focusBorder(false)
when (it.key) { .onKeyEvent {
Key.Enter, if (it.type == KeyEventType.KeyDown) {
Key.DirectionCenter -> dialog = true when (it.key) {
else -> onKeyEvent(it) Key.Enter,
Key.DirectionCenter -> dialog = true
else -> onKeyEvent(it)
}
} }
false
} }
false
}
} }
Box( Box(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
@@ -275,8 +274,11 @@ private fun MessageBubble(
modifier = boxModifier modifier = boxModifier
) { ChatText(annotatedString) } ) { ChatText(annotatedString) }
} }
if (dialog && isTv) { if (dialog && isTv && !isUser) {
TextDialog(message.content, linkTokens, onClickLink) { dialog = false } TextDialog(annotatedString, linkTokens, onClickLink) {
dialog = false
itemFocusRequester.requestFocus()
}
} }
} }
@@ -294,7 +296,7 @@ private fun ChatText(annotatedString: AnnotatedString) {
@Composable @Composable
private fun TextDialog( private fun TextDialog(
text: String, annotatedString: AnnotatedString,
links: List<TextToken.Link>, links: List<TextToken.Link>,
onClickLink: (String) -> Unit, onClickLink: (String) -> Unit,
dismiss: () -> Unit dismiss: () -> Unit
@@ -306,7 +308,7 @@ private fun TextDialog(
Column { Column {
val focusRequester = remember { FocusRequester() } val focusRequester = remember { FocusRequester() }
if (!showLinks) { if (!showLinks) {
ScrollableMessage(focusRequester, text) { ScrollableMessage(focusRequester, annotatedString) {
if (links.isNotEmpty()) { if (links.isNotEmpty()) {
showLinks = true showLinks = true
} else { } else {
@@ -341,7 +343,7 @@ private fun TextDialog(
@Composable @Composable
private fun ScrollableMessage( private fun ScrollableMessage(
focusRequester: FocusRequester, focusRequester: FocusRequester,
text: String, annotatedString: AnnotatedString,
onEnter: () -> Unit onEnter: () -> Unit
) { ) {
val scrollStep = 250f val scrollStep = 250f
@@ -376,7 +378,7 @@ private fun ScrollableMessage(
} }
) { ) {
Text( Text(
text = text, text = annotatedString,
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
.verticalScroll(scrollState) .verticalScroll(scrollState)
) )
@@ -384,6 +386,7 @@ private fun ScrollableMessage(
} }
private fun buildText( private fun buildText(
isTv: Boolean,
tokens: List<TextToken>, tokens: List<TextToken>,
primaryColor: Color, primaryColor: Color,
focusedColor: Color, focusedColor: Color,
@@ -407,7 +410,9 @@ private fun buildText(
textDecoration = TextDecoration.Underline textDecoration = TextDecoration.Underline
) )
), ),
linkInteractionListener = { onClickLink(token.text) } linkInteractionListener = {
if (!isTv) onClickLink(token.text)
}
) )
withLink(linkAnnotation) { append(token.text) } withLink(linkAnnotation) { append(token.text) }
} }