ui: show secrets on tap (#3628)

* ios: show secrets on tap

* android: show secrets on tap/click

* android: clickable links in group descriptions

* android: hide secrets one by one

* ios: clickable links in welcome message preview

* refactor

* refactor2
This commit is contained in:
Evgeny Poberezkin
2023-12-30 18:57:10 +00:00
committed by GitHub
parent 4ab078bd18
commit 809040c7bc
14 changed files with 91 additions and 43 deletions
@@ -53,6 +53,7 @@ fun ChatItemInfoView(chatModel: ChatModel, ci: ChatItem, ciInfo: ChatItemInfo, d
text, if (text.isEmpty()) emptyList() else formattedText,
sender = sender,
senderBold = true,
toggleSecrets = true,
linkMode = SimplexLinkMode.DESCRIPTION, uriHandler = uriHandler,
onLinkLongClick = { showMenu.value = true }
)
@@ -34,6 +34,7 @@ fun ContextItemView(
fun msgContentView(lines: Int) {
MarkdownText(
contextItem.text, contextItem.formattedText,
toggleSecrets = false,
maxLines = lines,
linkMode = SimplexLinkMode.DESCRIPTION,
modifier = Modifier.fillMaxWidth(),
@@ -15,6 +15,7 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.text.AnnotatedString
import dev.icerock.moko.resources.compose.painterResource
import dev.icerock.moko.resources.compose.stringResource
@@ -119,13 +120,15 @@ private fun GroupWelcomeLayout(
@Composable
private fun TextPreview(text: String, linkMode: SimplexLinkMode, markdown: Boolean = true) {
val uriHandler = LocalUriHandler.current
Column {
SelectionContainer(Modifier.fillMaxWidth()) {
MarkdownText(
text,
formattedText = if (markdown) remember(text) { parseToMarkdown(text) } else null,
toggleSecrets = false,
modifier = Modifier.fillMaxHeight().padding(horizontal = DEFAULT_PADDING),
linkMode = linkMode,
linkMode = linkMode, uriHandler = uriHandler,
style = MaterialTheme.typography.body1.copy(color = MaterialTheme.colors.onBackground, lineHeight = 22.sp)
)
}
@@ -54,6 +54,7 @@ fun FramedItemView(
MarkdownText(
qi.text,
qi.formattedText,
toggleSecrets = true,
maxLines = lines,
overflow = TextOverflow.Ellipsis,
style = TextStyle(fontSize = 15.sp, color = MaterialTheme.colors.onSurface),
@@ -288,7 +289,7 @@ fun CIMarkdownText(
Box(Modifier.padding(vertical = 6.dp, horizontal = 12.dp)) {
val text = if (ci.meta.isLive) ci.content.msgContent?.text ?: ci.text else ci.text
MarkdownText(
text, if (text.isEmpty()) emptyList() else ci.formattedText,
text, if (text.isEmpty()) emptyList() else ci.formattedText, toggleSecrets = true,
meta = ci.meta, chatTTL = chatTTL, linkMode = linkMode,
uriHandler = uriHandler, senderBold = true, onLinkLongClick = onLinkLongClick
)
@@ -60,6 +60,7 @@ fun MarkdownText (
sender: String? = null,
meta: CIMeta? = null,
chatTTL: Int? = null,
toggleSecrets: Boolean,
style: TextStyle = MaterialTheme.typography.body1.copy(color = MaterialTheme.colors.onSurface, lineHeight = 22.sp),
maxLines: Int = Int.MAX_VALUE,
overflow: TextOverflow = TextOverflow.Clip,
@@ -89,6 +90,7 @@ fun MarkdownText (
) {
var timer: Job? by remember { mutableStateOf(null) }
var typingIdx by rememberSaveable { mutableStateOf(0) }
val showSecrets = remember { mutableStateMapOf<String, Boolean>() }
fun stopTyping() {
timer?.cancel()
timer = null
@@ -127,15 +129,22 @@ fun MarkdownText (
}
Text(annotatedText, style = style, modifier = modifier, maxLines = maxLines, overflow = overflow, inlineContent = inlineContent ?: mapOf())
} else {
var hasLinks = false
var hasAnnotations = false
val annotatedText = buildAnnotatedString {
appendSender(this, sender, senderBold)
for (ft in formattedText) {
for ((i, ft) in formattedText.withIndex()) {
if (ft.format == null) append(ft.text)
else {
else if (toggleSecrets && ft.format is Format.Secret) {
val ftStyle = ft.format.style
hasAnnotations = true
val key = i.toString()
withAnnotation(tag = "SECRET", annotation = key) {
if (showSecrets[key] == true) append(ft.text) else withStyle(ftStyle) { append(ft.text) }
}
} else {
val link = ft.link(linkMode)
if (link != null) {
hasLinks = true
hasAnnotations = true
val ftStyle = ft.format.style
withAnnotation(tag = if (ft.format is Format.SimplexLink) "SIMPLEX_URL" else "URL", annotation = link) {
withStyle(ftStyle) { append(ft.viewText(linkMode)) }
@@ -153,7 +162,7 @@ fun MarkdownText (
withStyle(reserveTimestampStyle) { append("\n" + metaText) }
else */if (meta != null) withStyle(reserveTimestampStyle) { append(reserve) }
}
if (hasLinks && uriHandler != null) {
if (hasAnnotations && uriHandler != null) {
val icon = remember { mutableStateOf(PointerIcon.Default) }
ClickableText(annotatedText, style = style, modifier = modifier.pointerHoverIcon(icon.value), maxLines = maxLines, overflow = overflow,
onLongClick = { offset ->
@@ -177,12 +186,20 @@ fun MarkdownText (
.firstOrNull()?.let { annotation ->
uriHandler.openVerifiedSimplexUri(annotation.item)
}
annotatedText.getStringAnnotations(tag = "SECRET", start = offset, end = offset)
.firstOrNull()?.let { annotation ->
val key = annotation.item
showSecrets[key] = !(showSecrets[key] ?: false)
}
},
onHover = { offset ->
icon.value = annotatedText.getStringAnnotations(tag = "URL", start = offset, end = offset)
.firstOrNull()?.let {
PointerIcon.Hand
} ?: annotatedText.getStringAnnotations(tag = "SIMPLEX_URL", start = offset, end = offset)
.firstOrNull()?.let {
PointerIcon.Hand
} ?: annotatedText.getStringAnnotations(tag = "SECRET", start = offset, end = offset)
.firstOrNull()?.let {
PointerIcon.Hand
} ?: PointerIcon.Default
@@ -173,6 +173,7 @@ fun ChatPreviewView(
cInfo is ChatInfo.Group && !ci.chatDir.sent -> ci.memberDisplayName
else -> null
},
toggleSecrets = false,
linkMode = linkMode,
senderBold = true,
maxLines = 2,
@@ -78,17 +78,6 @@ fun ReadableText(text: String, textAlign: TextAlign = TextAlign.Start, padding:
Text(text, modifier = Modifier.padding(padding), textAlign = textAlign, lineHeight = 22.sp)
}
@Composable
fun ReadableMarkdownText(text: String, textAlign: TextAlign = TextAlign.Start, padding: PaddingValues = PaddingValues(bottom = 12.dp)) {
MarkdownText(
text,
formattedText = remember(text) { parseToMarkdown(text) },
modifier = Modifier.padding(padding),
style = TextStyle(textAlign = textAlign, lineHeight = 22.sp, fontSize = 16.sp),
linkMode = ChatController.appPrefs.simplexLinkMode.get(),
)
}
@Preview/*(
uiMode = Configuration.UI_MODE_NIGHT_YES,
showBackground = true,