From 666020c3dca3b093615705a2b4f78cf61b4d2b1b Mon Sep 17 00:00:00 2001 From: Clark Date: Thu, 30 Mar 2023 16:28:30 -0400 Subject: [PATCH] Add learn more link to export account data. --- .../export/ExportAccountDataFragment.kt | 25 ++++++++--- .../thoughtcrime/securesms/util/SpanUtil.java | 12 +++++ app/src/main/res/values/strings.xml | 1 + .../src/main/java/org/signal/core/ui/Texts.kt | 45 +++++++++++++++++++ 4 files changed, 78 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/account/export/ExportAccountDataFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/account/export/ExportAccountDataFragment.kt index d567a9b53e..d5808b8d91 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/account/export/ExportAccountDataFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/account/export/ExportAccountDataFragment.kt @@ -13,6 +13,7 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Card import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text @@ -36,10 +37,19 @@ import org.signal.core.ui.Buttons import org.signal.core.ui.Dialogs import org.signal.core.ui.Rows import org.signal.core.ui.Scaffolds +import org.signal.core.ui.Texts +import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.compose.ComposeFragment +import org.thoughtcrime.securesms.util.CommunicationActions +import org.thoughtcrime.securesms.util.SpanUtil class ExportAccountDataFragment : ComposeFragment() { + + companion object { + val TAG = Log.tag(ExportAccountDataFragment::class.java) + } + private val viewModel: ExportAccountDataViewModel by viewModels() private fun deleteReport() { @@ -105,10 +115,15 @@ class ExportAccountDataFragment : ComposeFragment() { } item { - Text( - text = stringResource(id = R.string.ExportAccountDataFragment__export_explanation, stringResource(id = R.string.ExportAccountDataFragment__learn_more)), - textAlign = TextAlign.Center, - modifier = Modifier.padding(top = 12.dp, start = 32.dp, end = 32.dp, bottom = 20.dp) + val learnMore = stringResource(R.string.ExportAccountDataFragment__learn_more) + val explanation = stringResource(R.string.ExportAccountDataFragment__export_explanation, learnMore) + Texts.LinkifiedText( + textWithUrlSpans = SpanUtil.urlSubsequence(explanation, learnMore, stringResource(R.string.export_account_data_url)), + onUrlClick = { url -> + CommunicationActions.openBrowserLink(requireContext(), url) + }, + modifier = Modifier.padding(top = 12.dp, start = 32.dp, end = 32.dp, bottom = 20.dp), + style = LocalTextStyle.current.copy(color = MaterialTheme.colorScheme.onSurface, textAlign = TextAlign.Center) ) } @@ -255,7 +270,7 @@ class ExportAccountDataFragment : ComposeFragment() { } Text( - text = stringResource(id = R.string.ExportAccountDataFragment__report_deletion_disclaimer, stringResource(id = R.string.ExportAccountDataFragment__learn_more)), + text = stringResource(id = R.string.ExportAccountDataFragment__report_deletion_disclaimer), style = MaterialTheme.typography.bodySmall, textAlign = TextAlign.Start, modifier = Modifier.padding(top = 16.dp, start = 24.dp, end = 28.dp, bottom = 20.dp) diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/SpanUtil.java b/app/src/main/java/org/thoughtcrime/securesms/util/SpanUtil.java index 2b2f53f06e..37873dc22d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/SpanUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/SpanUtil.java @@ -24,6 +24,7 @@ import android.text.style.RelativeSizeSpan; import android.text.style.StyleSpan; import android.text.style.TextAppearanceSpan; import android.text.style.TypefaceSpan; +import android.text.style.URLSpan; import android.view.View; import androidx.annotation.ColorInt; @@ -155,6 +156,17 @@ public final class SpanUtil { return clickSubstring(text, text, onLearnMoreClicked, color); } + public static Spanned urlSubsequence(@NonNull CharSequence fullString, @NonNull CharSequence substring, @NonNull String url) { + SpannableString spannable = new SpannableString(fullString); + int start = TextUtils.indexOf(fullString, substring); + int end = start + substring.length(); + + if (start >= 0 && end <= fullString.length()) { + spannable.setSpan(new URLSpan(url), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + return spannable; + } + /** * Takes two resources: * - one resource that has a single string placeholder diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0ebc67c1ec..0e54b07dec 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -15,6 +15,7 @@ https://signal.me/#u/%1$s signal.me/#u/%1$s https://support.signal.org/hc/articles/5389476324250 + https://support.signal.org/hc/articles/5538911756954 Yes No diff --git a/core-ui/src/main/java/org/signal/core/ui/Texts.kt b/core-ui/src/main/java/org/signal/core/ui/Texts.kt index 662abea6f2..0d5ee51028 100644 --- a/core-ui/src/main/java/org/signal/core/ui/Texts.kt +++ b/core-ui/src/main/java/org/signal/core/ui/Texts.kt @@ -1,13 +1,21 @@ package org.signal.core.ui +import android.text.Spanned +import android.text.style.URLSpan import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.text.ClickableText +import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.dimensionResource +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.TextStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.core.text.getSpans import org.signal.core.ui.theme.SignalTheme object Texts { @@ -29,6 +37,43 @@ object Texts { .padding(top = 16.dp, bottom = 12.dp) ) } + + @Composable + fun LinkifiedText( + textWithUrlSpans: Spanned, + onUrlClick: (String) -> Unit, + modifier: Modifier = Modifier, + style: TextStyle = LocalTextStyle.current + ) { + val annotatedText = annotatedStringFromUrlSpans(urlSpanText = textWithUrlSpans) + ClickableText( + text = annotatedText, + style = style, + modifier = modifier, + onClick = { offset -> + annotatedText.getStringAnnotations(tag = "URL", start = offset, end = offset).firstOrNull()?.let { annotation -> + onUrlClick(annotation.item) + } + } + ) + } + + @Composable + private fun annotatedStringFromUrlSpans(urlSpanText: Spanned): AnnotatedString { + val builder = AnnotatedString.Builder(urlSpanText.toString()) + val urlSpans = urlSpanText.getSpans() + for (urlSpan in urlSpans) { + val spanStart = urlSpanText.getSpanStart(urlSpan) + val spanEnd = urlSpanText.getSpanEnd(urlSpan) + builder.addStyle( + style = SpanStyle(color = MaterialTheme.colorScheme.primary), + start = spanStart, + end = spanEnd + ) + builder.addStringAnnotation("URL", urlSpan.url, spanStart, spanEnd) + } + return builder.toAnnotatedString() + } } @Preview