From 0acad2fb35554aeae5ee8e7046f73e853726c823 Mon Sep 17 00:00:00 2001 From: AndroidBob Date: Tue, 23 Apr 2024 11:01:03 +0200 Subject: [PATCH] refactor: make learn more links clickable for automation [WPB-5888] (#2923) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michał Saleniuk <30429749+saleniuk@users.noreply.github.com> Co-authored-by: Michał Saleniuk --- .../ui/authentication/login/LoginScreen.kt | 51 ++++---- .../ui/common/PreviewTextWithLinkSuffix.kt | 89 ++++++++++++++ .../messages/item/SystemMessageItem.kt | 46 ++------ .../common/CreateGroupErrorDialog.kt | 62 ++++------ .../com/wire/android/util/CoreFailureUtil.kt | 5 +- .../android/ui/common/TextWithLinkSuffix.kt | 109 ++++++++++++++++++ .../com/wire/android/ui/common/WireDialog.kt | 23 ++-- 7 files changed, 267 insertions(+), 118 deletions(-) create mode 100644 app/src/main/kotlin/com/wire/android/ui/common/PreviewTextWithLinkSuffix.kt create mode 100644 core/ui-common/src/main/kotlin/com/wire/android/ui/common/TextWithLinkSuffix.kt diff --git a/app/src/main/kotlin/com/wire/android/ui/authentication/login/LoginScreen.kt b/app/src/main/kotlin/com/wire/android/ui/authentication/login/LoginScreen.kt index 61043e355f5..96327f343ec 100644 --- a/app/src/main/kotlin/com/wire/android/ui/authentication/login/LoginScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/authentication/login/LoginScreen.kt @@ -48,6 +48,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.window.DialogProperties import androidx.hilt.navigation.compose.hiltViewModel @@ -243,22 +244,22 @@ fun LoginErrorDialog( ) { val dialogErrorData: LoginDialogErrorData = when (error) { is LoginError.DialogError.InvalidCredentialsError -> LoginDialogErrorData( - stringResource(R.string.login_error_invalid_credentials_title), - stringResource(R.string.login_error_invalid_credentials_message), - onDialogDismiss + title = stringResource(R.string.login_error_invalid_credentials_title), + body = AnnotatedString(stringResource(R.string.login_error_invalid_credentials_message)), + onDismiss = onDialogDismiss ) is LoginError.DialogError.UserAlreadyExists -> LoginDialogErrorData( - stringResource(R.string.login_error_user_already_logged_in_title), - stringResource(R.string.login_error_user_already_logged_in_message), - onDialogDismiss + title = stringResource(R.string.login_error_user_already_logged_in_title), + body = AnnotatedString(stringResource(R.string.login_error_user_already_logged_in_message)), + onDismiss = onDialogDismiss ) is LoginError.DialogError.ProxyError -> { LoginDialogErrorData( - stringResource(R.string.error_socket_title), - stringResource(R.string.error_socket_message), - onDialogDismiss + title = stringResource(R.string.error_socket_title), + body = AnnotatedString(stringResource(R.string.error_socket_message)), + onDismiss = onDialogDismiss ) } @@ -266,36 +267,36 @@ fun LoginErrorDialog( val strings = error.coreFailure.dialogErrorStrings(LocalContext.current.resources) LoginDialogErrorData( strings.title, - strings.message, + strings.annotatedMessage, onDialogDismiss ) } is LoginError.DialogError.InvalidSSOCodeError -> LoginDialogErrorData( - stringResource(R.string.login_error_invalid_credentials_title), - stringResource(R.string.login_error_invalid_sso_code), - onDialogDismiss + title = stringResource(R.string.login_error_invalid_credentials_title), + body = AnnotatedString(stringResource(R.string.login_error_invalid_sso_code)), + onDismiss = onDialogDismiss ) is LoginError.DialogError.InvalidSSOCookie -> LoginDialogErrorData( - stringResource(R.string.login_sso_error_invalid_cookie_title), - stringResource(R.string.login_sso_error_invalid_cookie_message), - onDialogDismiss + title = stringResource(R.string.login_sso_error_invalid_cookie_title), + body = AnnotatedString(stringResource(R.string.login_sso_error_invalid_cookie_message)), + onDismiss = onDialogDismiss ) is LoginError.DialogError.SSOResultError -> { with(ssoLoginResult as DeepLinkResult.SSOLogin.Failure) { LoginDialogErrorData( - stringResource(R.string.sso_error_dialog_title), - stringResource(R.string.sso_error_dialog_message, this.ssoError.errorCode), - onDialogDismiss + title = stringResource(R.string.sso_error_dialog_title), + body = AnnotatedString(stringResource(R.string.sso_error_dialog_message, this.ssoError.errorCode)), + onDismiss = onDialogDismiss ) } } is LoginError.DialogError.ServerVersionNotSupported -> LoginDialogErrorData( title = stringResource(R.string.api_versioning_server_version_not_supported_title), - body = stringResource(R.string.api_versioning_server_version_not_supported_message), + body = AnnotatedString(stringResource(R.string.api_versioning_server_version_not_supported_message)), onDismiss = onDialogDismiss, actionTextId = R.string.label_close, dismissOnClickOutside = false @@ -303,7 +304,7 @@ fun LoginErrorDialog( is LoginError.DialogError.ClientUpdateRequired -> LoginDialogErrorData( title = stringResource(R.string.api_versioning_client_update_required_title), - body = stringResource(R.string.api_versioning_client_update_required_message), + body = AnnotatedString(stringResource(R.string.api_versioning_client_update_required_message)), onDismiss = onDialogDismiss, actionTextId = R.string.label_update, onAction = updateTheApp, @@ -313,9 +314,9 @@ fun LoginErrorDialog( LoginError.DialogError.PasswordNeededToRegisterClient -> TODO() else -> LoginDialogErrorData( - stringResource(R.string.error_unknown_title), - stringResource(R.string.error_unknown_message), - onDialogDismiss + title = stringResource(R.string.error_unknown_title), + body = AnnotatedString(stringResource(R.string.error_unknown_message)), + onDismiss = onDialogDismiss ) } @@ -338,7 +339,7 @@ fun LoginErrorDialog( data class LoginDialogErrorData( val title: String, - val body: String, + val body: AnnotatedString, val onDismiss: () -> Unit, @StringRes val actionTextId: Int = R.string.label_ok, val onAction: () -> Unit = onDismiss, diff --git a/app/src/main/kotlin/com/wire/android/ui/common/PreviewTextWithLinkSuffix.kt b/app/src/main/kotlin/com/wire/android/ui/common/PreviewTextWithLinkSuffix.kt new file mode 100644 index 00000000000..b293680821b --- /dev/null +++ b/app/src/main/kotlin/com/wire/android/ui/common/PreviewTextWithLinkSuffix.kt @@ -0,0 +1,89 @@ +/* + * Wire + * Copyright (C) 2024 Wire Swiss GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ +package com.wire.android.ui.common + +import androidx.compose.foundation.layout.width +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.rememberTextMeasurer +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.unit.Dp +import com.wire.android.ui.theme.WireTheme +import com.wire.android.ui.theme.wireTypography +import com.wire.android.util.ui.PreviewMultipleThemes + +@Composable +private fun PreviewTextWithLinkSuffixBuilder( + textLines: List = listOf("This is a text with a link"), + linkText: String = "link", + calculateWidth: (lastTextLineWidthDp: Dp, linkWidthDp: Dp) -> Dp +) { + val textStyle = MaterialTheme.wireTypography.body01 + val linkStyle = MaterialTheme.wireTypography.body02.copy(textDecoration = TextDecoration.Underline) + val textMeasurer = rememberTextMeasurer() + val lastTextLineLayoutResult = textMeasurer.measure(text = "${textLines.last()} ", style = textStyle) + val linkLayoutResult = textMeasurer.measure(text = linkText, style = linkStyle) + val density = LocalDensity.current + val lastTextLineWidthDp = with(density) { lastTextLineLayoutResult.size.width.toDp() } + val linkWidthDp = with(density) { linkLayoutResult.size.width.toDp() } + TextWithLinkSuffix( + text = AnnotatedString(textLines.joinToString(separator = "\n")), + linkText = linkText, + onLinkClick = {}, + modifier = Modifier.width(calculateWidth(lastTextLineWidthDp, linkWidthDp)) + ) +} + +@PreviewMultipleThemes +@Composable +fun PreviewTextWithLinkSuffixWithoutALink() = WireTheme { + TextWithLinkSuffix(text = AnnotatedString("This is a text without a link")) +} + +@PreviewMultipleThemes +@Composable +fun PreviewTextWithLinkSuffixFittingInSameLine() = WireTheme { + PreviewTextWithLinkSuffixBuilder { lastTextLineWidthDp, linkWidthDp -> lastTextLineWidthDp + linkWidthDp } +} + +@PreviewMultipleThemes +@Composable +fun PreviewTextWithLinkSuffixNotFittingInSameLine() = WireTheme { + PreviewTextWithLinkSuffixBuilder { lastTextLineWidthDp, linkWidthDp -> lastTextLineWidthDp + (linkWidthDp / 2) } +} + +@PreviewMultipleThemes +@Composable +fun PreviewTextWithLinkSuffixMultilineFittingInLastLine() = WireTheme { + PreviewTextWithLinkSuffixBuilder( + textLines = listOf("This is a text with a link", "This is a text with a"), + linkText = "link", + ) { lastTextLineWidthDp, linkWidthDp -> lastTextLineWidthDp + linkWidthDp } +} + +@PreviewMultipleThemes +@Composable +fun PreviewTextWithLinkSuffixMultilineNotFittingInLastLine() = WireTheme { + PreviewTextWithLinkSuffixBuilder( + textLines = listOf("This is a text with a", "This is a text with a"), + linkText = "link" + ) { lastTextLineWidthDp, linkWidthDp -> lastTextLineWidthDp + (linkWidthDp / 2) } +} diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/messages/item/SystemMessageItem.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/messages/item/SystemMessageItem.kt index 3f86f544e9a..2acb463ebce 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/messages/item/SystemMessageItem.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/messages/item/SystemMessageItem.kt @@ -29,7 +29,6 @@ import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.text.ClickableText import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -41,11 +40,9 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString -import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.buildAnnotatedString -import androidx.compose.ui.text.style.TextDecoration import com.wire.android.R +import com.wire.android.ui.common.TextWithLinkSuffix import com.wire.android.ui.common.button.WireSecondaryButton import com.wire.android.ui.common.dimensions import com.wire.android.ui.common.spacers.VerticalSpace @@ -104,40 +101,18 @@ fun SystemMessageItem( errorColor = MaterialTheme.wireColorScheme.error, isErrorString = message.addingFailed, ) - val learnMoreAnnotatedString = message.messageContent.learnMoreResId?.let { - val learnMoreLink = stringResource(id = message.messageContent.learnMoreResId) - val learnMoreText = stringResource(id = R.string.label_learn_more) - buildAnnotatedString { - append(learnMoreText) - addStyle( - style = SpanStyle( - color = MaterialTheme.colorScheme.primary, - textDecoration = TextDecoration.Underline - ), - start = 0, - end = learnMoreText.length - ) - addStringAnnotation(tag = TAG_LEARN_MORE, annotation = learnMoreLink, start = 0, end = learnMoreText.length) - } - } - val fullAnnotatedString = when { - learnMoreAnnotatedString == null -> annotatedString - message.messageContent.expandable && expanded -> annotatedString + AnnotatedString("\n") + learnMoreAnnotatedString - message.messageContent.expandable && !expanded -> annotatedString - else -> annotatedString + AnnotatedString(" ") + learnMoreAnnotatedString - } + val learnMoreLink = message.messageContent.learnMoreResId?.let { stringResource(id = it) } - ClickableText( - modifier = Modifier.defaultMinSize(minHeight = dimensions().spacing20x), - text = fullAnnotatedString, - onClick = { offset -> - fullAnnotatedString.getStringAnnotations(TAG_LEARN_MORE, offset, offset) - .firstOrNull()?.let { result -> CustomTabsHelper.launchUrl(context, result.item) } - }, - style = MaterialTheme.wireTypography.body02, + TextWithLinkSuffix( + text = annotatedString, + linkText = learnMoreLink?.let { stringResource(id = R.string.label_learn_more) }, + textColor = MaterialTheme.wireColorScheme.secondaryText, + linkColor = MaterialTheme.wireColorScheme.onBackground, + onLinkClick = { learnMoreLink?.let { CustomTabsHelper.launchUrl(context, it) } }, onTextLayout = { centerOfFirstLine = if (it.lineCount == 0) 0f else ((it.getLineTop(0) + it.getLineBottom(0)) / 2) - } + }, + modifier = Modifier.defaultMinSize(minHeight = dimensions().spacing20x), ) if (message.messageContent.expandable) { @@ -371,4 +346,3 @@ private fun SystemMessage.MemberFailedToAdd.toFailedToAddMarkdownText( private const val EXPANDABLE_THRESHOLD = 4 private const val SINGLE_EXPANDABLE_THRESHOLD = 1 -private const val TAG_LEARN_MORE = "tag_learn_more" diff --git a/app/src/main/kotlin/com/wire/android/ui/home/newconversation/common/CreateGroupErrorDialog.kt b/app/src/main/kotlin/com/wire/android/ui/home/newconversation/common/CreateGroupErrorDialog.kt index 6d9e206f16e..1e7caa2b4e9 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/newconversation/common/CreateGroupErrorDialog.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/newconversation/common/CreateGroupErrorDialog.kt @@ -19,18 +19,13 @@ package com.wire.android.ui.home.newconversation.common import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.SpanStyle -import androidx.compose.ui.text.buildAnnotatedString -import androidx.compose.ui.text.style.TextDecoration -import androidx.compose.ui.text.withStyle import com.wire.android.R +import com.wire.android.ui.common.DialogTextSuffixLink import com.wire.android.ui.common.WireDialog import com.wire.android.ui.common.WireDialogButtonProperties import com.wire.android.ui.common.WireDialogButtonType -import com.wire.android.ui.common.colorsScheme -import com.wire.android.ui.markdown.MarkdownConstants import com.wire.android.ui.theme.WireTheme -import com.wire.android.util.DialogAnnotatedErrorStrings +import com.wire.android.util.DialogErrorStrings import com.wire.android.util.ui.PreviewMultipleThemes @Composable @@ -40,51 +35,34 @@ fun CreateGroupErrorDialog( onAccept: () -> Unit, onCancel: () -> Unit ) { - val dialogStrings = when (error) { - is CreateGroupState.Error.LackingConnection -> DialogAnnotatedErrorStrings( - stringResource(R.string.error_no_network_title), - buildAnnotatedString { append(stringResource(R.string.error_no_network_message)) } - ) + val (dialogStrings, dialogSuffixLink) = when (error) { + is CreateGroupState.Error.LackingConnection -> DialogErrorStrings( + title = stringResource(R.string.error_no_network_title), + message = stringResource(R.string.error_no_network_message), + ) to null - is CreateGroupState.Error.Unknown -> DialogAnnotatedErrorStrings( - stringResource(R.string.error_unknown_title), - buildAnnotatedString { append(stringResource(R.string.error_unknown_message)) } - ) + is CreateGroupState.Error.Unknown -> DialogErrorStrings( + title = stringResource(R.string.error_unknown_title), + message = stringResource(R.string.error_unknown_message), + ) to null - is CreateGroupState.Error.ConflictedBackends -> DialogAnnotatedErrorStrings( + is CreateGroupState.Error.ConflictedBackends -> DialogErrorStrings( title = stringResource(id = R.string.group_can_not_be_created_title), - annotatedMessage = buildAnnotatedString { - val description = stringResource( + message = stringResource( id = R.string.group_can_not_be_created_federation_conflict_description, error.domains.dropLast(1).joinToString(", "), error.domains.last() - ) - val learnMore = stringResource(id = R.string.label_learn_more) - - append(description) - append(' ') - - withStyle( - style = SpanStyle( - color = colorsScheme().primary, - textDecoration = TextDecoration.Underline - ) - ) { - append(learnMore) - } - addStringAnnotation( - tag = MarkdownConstants.TAG_URL, - annotation = stringResource(id = R.string.url_message_details_offline_backends_learn_more), - start = description.length + 1, - end = description.length + 1 + learnMore.length - ) - } + ), + ) to DialogTextSuffixLink( + linkText = stringResource(id = R.string.label_learn_more), + linkUrl = stringResource(id = R.string.url_message_details_offline_backends_learn_more) ) } WireDialog( - dialogStrings.title, - dialogStrings.annotatedMessage, + title = dialogStrings.title, + text = dialogStrings.annotatedMessage, + textSuffixLink = dialogSuffixLink, onDismiss = onDismiss, buttonsHorizontalAlignment = false, optionButton1Properties = WireDialogButtonProperties( diff --git a/app/src/main/kotlin/com/wire/android/util/CoreFailureUtil.kt b/app/src/main/kotlin/com/wire/android/util/CoreFailureUtil.kt index 85717698ea0..ac3f60ae358 100644 --- a/app/src/main/kotlin/com/wire/android/util/CoreFailureUtil.kt +++ b/app/src/main/kotlin/com/wire/android/util/CoreFailureUtil.kt @@ -48,5 +48,6 @@ fun CoreFailure.uiText(): UIText = when (this) { else -> UIText.StringResource(R.string.error_unknown_message) } -data class DialogErrorStrings(val title: String, val message: String) -data class DialogAnnotatedErrorStrings(val title: String, val annotatedMessage: AnnotatedString) +data class DialogErrorStrings(val title: String, val annotatedMessage: AnnotatedString) { + constructor(title: String, message: String) : this(title, AnnotatedString(message)) +} diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/TextWithLinkSuffix.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/TextWithLinkSuffix.kt new file mode 100644 index 00000000000..95f2485413a --- /dev/null +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/TextWithLinkSuffix.kt @@ -0,0 +1,109 @@ +/* + * Wire + * Copyright (C) 2024 Wire Swiss GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ +package com.wire.android.ui.common + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.text.InlineTextContent +import androidx.compose.foundation.text.appendInlineContent +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.Placeholder +import androidx.compose.ui.text.PlaceholderVerticalAlign +import androidx.compose.ui.text.TextLayoutResult +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.rememberTextMeasurer +import androidx.compose.ui.text.style.TextDecoration +import com.wire.android.ui.theme.wireColorScheme +import com.wire.android.ui.theme.wireTypography + +@Composable +fun TextWithLinkSuffix( + text: AnnotatedString, + linkText: String? = null, + onLinkClick: () -> Unit = {}, + linkTag: String = "link", + textStyle: TextStyle = MaterialTheme.wireTypography.body01, + textColor: Color = MaterialTheme.wireColorScheme.onBackground, + linkStyle: TextStyle = MaterialTheme.wireTypography.body02, + linkColor: Color = MaterialTheme.wireColorScheme.primary, + linkDecoration: TextDecoration = TextDecoration.Underline, + onTextLayout: (TextLayoutResult) -> Unit = {}, + modifier: Modifier = Modifier, +) { + val textMeasurer = rememberTextMeasurer() + val linkId = "link" + val inlineText = linkText?.let { + text.plus( + buildAnnotatedString { + append(" ") + appendInlineContent(linkId, "[link]") + } + ) + } ?: text + val inlineContent = buildMap { + if (linkText != null) { + val textLayoutResult: TextLayoutResult = textMeasurer.measure( + text = linkText, + style = linkStyle.copy(textDecoration = linkDecoration), + ) + val textSize = textLayoutResult.size + val density = LocalDensity.current + val (linkWidthSp, linkHeightSp) = with(density) { + textSize.width.toSp() to textSize.height.toSp() + } + + put( + linkId, + InlineTextContent( + placeholder = Placeholder( + width = linkWidthSp, + height = linkHeightSp, + placeholderVerticalAlign = PlaceholderVerticalAlign.Bottom + ), + children = { + Text( + text = linkText, + style = linkStyle, + color = linkColor, + textDecoration = linkDecoration, + modifier = Modifier + .testTag(linkTag) + .clickable(onClick = onLinkClick) + ) + } + ) + ) + } + } + + Text( + text = inlineText, + style = textStyle, + color = textColor, + inlineContent = inlineContent, + onTextLayout = onTextLayout, + modifier = modifier, + ) +} diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/WireDialog.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/WireDialog.kt index 79abc2029a5..5e3f0b5e8ae 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/WireDialog.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/WireDialog.kt @@ -31,7 +31,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.text.ClickableText import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text @@ -72,6 +71,7 @@ fun wireDialogPropertiesBuilder( fun WireDialog( title: String, text: String, + textSuffixLink: DialogTextSuffixLink? = null, onDismiss: () -> Unit, optionButton1Properties: WireDialogButtonProperties? = null, optionButton2Properties: WireDialogButtonProperties? = null, @@ -107,6 +107,7 @@ fun WireDialog( ) withStyle(style) { append(text) } }, + textSuffixLink = textSuffixLink, centerContent = centerContent, content = content ) @@ -116,6 +117,7 @@ fun WireDialog( fun WireDialog( title: String, text: AnnotatedString? = null, + textSuffixLink: DialogTextSuffixLink? = null, onDismiss: () -> Unit, optionButton1Properties: WireDialogButtonProperties? = null, optionButton2Properties: WireDialogButtonProperties? = null, @@ -144,6 +146,7 @@ fun WireDialog( title = title, titleLoading = titleLoading, text = text, + textSuffixLink = textSuffixLink, centerContent = centerContent, content = content ) @@ -155,6 +158,7 @@ fun WireDialogContent( title: String, titleLoading: Boolean = false, text: AnnotatedString? = null, + textSuffixLink: DialogTextSuffixLink? = null, optionButton1Properties: WireDialogButtonProperties? = null, optionButton2Properties: WireDialogButtonProperties? = null, dismissButtonProperties: WireDialogButtonProperties? = null, @@ -194,17 +198,11 @@ fun WireDialogContent( ) { text?.let { item { - ClickableText( + TextWithLinkSuffix( text = text, - style = MaterialTheme.wireTypography.body01, - modifier = Modifier.padding(bottom = MaterialTheme.wireDimensions.dialogTextsSpacing), - onClick = { offset -> - text.getStringAnnotations( - tag = TAG_URL, - start = offset, - end = offset, - ).firstOrNull()?.let { result -> uriHandler.openUri(result.item) } - } + linkText = textSuffixLink?.linkText, + onLinkClick = { textSuffixLink?.linkUrl?.let { uriHandler.openUri(it) } }, + modifier = Modifier.padding(bottom = MaterialTheme.wireDimensions.dialogTextsSpacing) ) } } @@ -300,5 +298,4 @@ data class WireDialogButtonProperties( val loading: Boolean = false ) -// todo, replace when markdown is moved to commons -private const val TAG_URL = "linkTag" +data class DialogTextSuffixLink(val linkText: String, val linkUrl: String)