From fc6fa5315b222f31b0483480d6658ded34bbdcaf Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Thu, 25 Apr 2024 15:15:52 +0400 Subject: [PATCH 1/3] android: show disappearing message timer on calls and group invitations (#4090) * android: show disappearing message timer on calls and group invitations * fix padding --- .../Views/Chat/ChatItem/CIMetaView.swift | 26 +++++---- .../common/views/chat/item/CICallItemView.kt | 17 +++--- .../views/chat/item/CIGroupInvitationView.kt | 56 ++++++++++--------- .../common/views/chat/item/CIMetaView.kt | 56 +++++++++++++------ .../common/views/chat/item/ChatItemView.kt | 6 +- 5 files changed, 95 insertions(+), 66 deletions(-) diff --git a/apps/ios/Shared/Views/Chat/ChatItem/CIMetaView.swift b/apps/ios/Shared/Views/Chat/ChatItem/CIMetaView.swift index b0a3520fca..17b93930fe 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/CIMetaView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/CIMetaView.swift @@ -78,19 +78,21 @@ func ciMetaText( } r = r + Text(" ") } - if showStatus, let (icon, statusColor) = meta.statusIcon(color) { - let t = Text(Image(systemName: icon)).font(.caption2) - let gap = Text(" ").kerning(-1.25) - let t1 = t.foregroundColor(transparent ? .clear : statusColor.opacity(0.67)) - switch sent { - case nil: r = r + t1 - case .sent: r = r + t1 + gap - case .rcvd1: r = r + t.foregroundColor(transparent ? .clear : statusColor.opacity(0.67)) + gap - case .rcvd2: r = r + gap + t1 + if showStatus { + if let (icon, statusColor) = meta.statusIcon(color) { + let t = Text(Image(systemName: icon)).font(.caption2) + let gap = Text(" ").kerning(-1.25) + let t1 = t.foregroundColor(transparent ? .clear : statusColor.opacity(0.67)) + switch sent { + case nil: r = r + t1 + case .sent: r = r + t1 + gap + case .rcvd1: r = r + t.foregroundColor(transparent ? .clear : statusColor.opacity(0.67)) + gap + case .rcvd2: r = r + gap + t1 + } + r = r + Text(" ") + } else if !meta.disappearing { + r = r + statusIconText("circlebadge.fill", .clear) + Text(" ") } - r = r + Text(" ") - } else if !meta.disappearing { - r = r + statusIconText("circlebadge.fill", .clear) + Text(" ") } if let enc = encrypted { r = r + statusIconText(enc ? "lock" : "lock.open", color) + Text(" ") diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CICallItemView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CICallItemView.kt index 6f165515ec..5d3d5aa94a 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CICallItemView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CICallItemView.kt @@ -9,14 +9,20 @@ import androidx.compose.ui.graphics.Color import dev.icerock.moko.resources.compose.painterResource import dev.icerock.moko.resources.compose.stringResource import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import chat.simplex.common.ui.theme.* import chat.simplex.common.model.* import chat.simplex.common.views.helpers.SimpleButton import chat.simplex.res.MR @Composable -fun CICallItemView(cInfo: ChatInfo, cItem: ChatItem, status: CICallStatus, duration: Int, acceptCall: (Contact) -> Unit) { +fun CICallItemView( + cInfo: ChatInfo, + cItem: ChatItem, + status: CICallStatus, + duration: Int, + acceptCall: (Contact) -> Unit, + timedMessagesTTL: Int? +) { val sent = cItem.chatDir.sent Column( Modifier @@ -41,12 +47,7 @@ fun CICallItemView(cInfo: ChatInfo, cItem: ChatItem, status: CICallStatus, durat CICallStatus.Error -> {} } - Text( - cItem.timestampText, - color = MaterialTheme.colors.secondary, - fontSize = 14.sp, - modifier = Modifier.padding(start = 3.dp) - ) + CIMetaView(cItem, timedMessagesTTL, showStatus = false, showEdited = false) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIGroupInvitationView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIGroupInvitationView.kt index 911bbaf833..e3008f36b3 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIGroupInvitationView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIGroupInvitationView.kt @@ -9,11 +9,12 @@ import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.text.buildAnnotatedString import dev.icerock.moko.resources.compose.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import chat.simplex.common.ui.theme.* import chat.simplex.common.views.helpers.* import chat.simplex.common.model.* @@ -26,7 +27,8 @@ fun CIGroupInvitationView( groupInvitation: CIGroupInvitation, memberRole: GroupMemberRole, chatIncognito: Boolean = false, - joinGroup: (Long, () -> Unit) -> Unit + joinGroup: (Long, () -> Unit) -> Unit, + timedMessagesTTL: Int? ) { val sent = ci.chatDir.sent val action = !sent && groupInvitation.status == CIGroupInvitationStatus.Pending @@ -69,13 +71,15 @@ fun CIGroupInvitationView( } @Composable - fun groupInvitationText() { - when { - sent -> Text(stringResource(MR.strings.you_sent_group_invitation)) - !sent && groupInvitation.status == CIGroupInvitationStatus.Pending -> Text(stringResource(MR.strings.you_are_invited_to_group)) - !sent && groupInvitation.status == CIGroupInvitationStatus.Accepted -> Text(stringResource(MR.strings.you_joined_this_group)) - !sent && groupInvitation.status == CIGroupInvitationStatus.Rejected -> Text(stringResource(MR.strings.you_rejected_group_invitation)) - !sent && groupInvitation.status == CIGroupInvitationStatus.Expired -> Text(stringResource(MR.strings.group_invitation_expired)) + fun groupInvitationStr(): String { + return when { + sent -> stringResource(MR.strings.you_sent_group_invitation) + else -> when(groupInvitation.status) { + CIGroupInvitationStatus.Pending -> stringResource(MR.strings.you_are_invited_to_group) + CIGroupInvitationStatus.Accepted -> stringResource(MR.strings.you_joined_this_group) + CIGroupInvitationStatus.Rejected -> stringResource(MR.strings.you_rejected_group_invitation) + CIGroupInvitationStatus.Expired -> stringResource(MR.strings.group_invitation_expired) + } } } @@ -109,20 +113,24 @@ fun CIGroupInvitationView( Column(Modifier.padding(top = 2.dp, start = 5.dp)) { Divider(Modifier.fillMaxWidth().padding(bottom = 4.dp)) if (action) { - groupInvitationText() + Text(groupInvitationStr()) Text( - stringResource( - if (chatIncognito) MR.strings.group_invitation_tap_to_join_incognito else MR.strings.group_invitation_tap_to_join - ), + buildAnnotatedString { + append(generalGetString(if (chatIncognito) MR.strings.group_invitation_tap_to_join_incognito else MR.strings.group_invitation_tap_to_join)) + withStyle(reserveTimestampStyle) { append(reserveSpaceForMeta(ci.meta, timedMessagesTTL, encrypted = null, showStatus = false, showEdited = false)) } + }, color = if (inProgress.value) MaterialTheme.colors.secondary else if (chatIncognito) Indigo else MaterialTheme.colors.primary ) } else { - Box(Modifier.padding(end = 48.dp)) { - groupInvitationText() - } + Text( + buildAnnotatedString { + append(groupInvitationStr()) + withStyle(reserveTimestampStyle) { append(reserveSpaceForMeta(ci.meta, timedMessagesTTL, encrypted = null, showStatus = false, showEdited = false)) } + } + ) } } } @@ -136,12 +144,7 @@ fun CIGroupInvitationView( } } - Text( - ci.timestampText, - color = MaterialTheme.colors.secondary, - fontSize = 14.sp, - modifier = Modifier.padding(start = 3.dp) - ) + CIMetaView(ci, timedMessagesTTL, showStatus = false, showEdited = false) } } } @@ -157,7 +160,8 @@ fun PendingCIGroupInvitationViewPreview() { ci = ChatItem.getGroupInvitationSample(), groupInvitation = CIGroupInvitation.getSample(), memberRole = GroupMemberRole.Admin, - joinGroup = { _, _ -> } + joinGroup = { _, _ -> }, + timedMessagesTTL = null ) } } @@ -173,7 +177,8 @@ fun CIGroupInvitationViewAcceptedPreview() { ci = ChatItem.getGroupInvitationSample(), groupInvitation = CIGroupInvitation.getSample(status = CIGroupInvitationStatus.Accepted), memberRole = GroupMemberRole.Admin, - joinGroup = { _, _ -> } + joinGroup = { _, _ -> }, + timedMessagesTTL = null ) } } @@ -189,7 +194,8 @@ fun CIGroupInvitationViewLongNamePreview() { status = CIGroupInvitationStatus.Accepted ), memberRole = GroupMemberRole.Admin, - joinGroup = { _, _ -> } + joinGroup = { _, _ -> }, + timedMessagesTTL = null ) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIMetaView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIMetaView.kt index 72f7137b55..b40d8989e1 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIMetaView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIMetaView.kt @@ -33,7 +33,9 @@ fun CIMetaView( red = minOf(metaColor.red * 1.33F, 1F), green = minOf(metaColor.green * 1.33F, 1F), blue = minOf(metaColor.red * 1.33F, 1F)) - } + }, + showStatus: Boolean = true, + showEdited: Boolean = true ) { Row(Modifier.padding(start = 3.dp), verticalAlignment = Alignment.CenterVertically) { if (chatItem.isDeletedContent) { @@ -44,15 +46,31 @@ fun CIMetaView( modifier = Modifier.padding(start = 3.dp) ) } else { - CIMetaText(chatItem.meta, timedMessagesTTL, encrypted = chatItem.encryptedFile, metaColor, paleMetaColor) + CIMetaText( + chatItem.meta, + timedMessagesTTL, + encrypted = chatItem.encryptedFile, + metaColor, + paleMetaColor, + showStatus = showStatus, + showEdited = showEdited + ) } } } @Composable // changing this function requires updating reserveSpaceForMeta -private fun CIMetaText(meta: CIMeta, chatTTL: Int?, encrypted: Boolean?, color: Color, paleColor: Color) { - if (meta.itemEdited) { +private fun CIMetaText( + meta: CIMeta, + chatTTL: Int?, + encrypted: Boolean?, + color: Color, + paleColor: Color, + showStatus: Boolean = true, + showEdited: Boolean = true +) { + if (showEdited && meta.itemEdited) { StatusIconText(painterResource(MR.images.ic_edit), color) Spacer(Modifier.width(3.dp)) } @@ -64,18 +82,20 @@ private fun CIMetaText(meta: CIMeta, chatTTL: Int?, encrypted: Boolean?, color: } Spacer(Modifier.width(4.dp)) } - val statusIcon = meta.statusIcon(MaterialTheme.colors.primary, color, paleColor) - if (statusIcon != null) { - val (icon, statusColor) = statusIcon - if (meta.itemStatus is CIStatus.SndSent || meta.itemStatus is CIStatus.SndRcvd) { - Icon(painterResource(icon), null, Modifier.height(17.dp), tint = statusColor) - } else { - StatusIconText(painterResource(icon), statusColor) + if (showStatus) { + val statusIcon = meta.statusIcon(MaterialTheme.colors.primary, color, paleColor) + if (statusIcon != null) { + val (icon, statusColor) = statusIcon + if (meta.itemStatus is CIStatus.SndSent || meta.itemStatus is CIStatus.SndRcvd) { + Icon(painterResource(icon), null, Modifier.height(17.dp), tint = statusColor) + } else { + StatusIconText(painterResource(icon), statusColor) + } + Spacer(Modifier.width(4.dp)) + } else if (!meta.disappearing) { + StatusIconText(painterResource(MR.images.ic_circle_filled), Color.Transparent) + Spacer(Modifier.width(4.dp)) } - Spacer(Modifier.width(4.dp)) - } else if (!meta.disappearing) { - StatusIconText(painterResource(MR.images.ic_circle_filled), Color.Transparent) - Spacer(Modifier.width(4.dp)) } if (encrypted != null) { StatusIconText(painterResource(if (encrypted) MR.images.ic_lock else MR.images.ic_lock_open_right), color) @@ -85,10 +105,10 @@ private fun CIMetaText(meta: CIMeta, chatTTL: Int?, encrypted: Boolean?, color: } // the conditions in this function should match CIMetaText -fun reserveSpaceForMeta(meta: CIMeta, chatTTL: Int?, encrypted: Boolean?): String { +fun reserveSpaceForMeta(meta: CIMeta, chatTTL: Int?, encrypted: Boolean?, showStatus: Boolean = true, showEdited: Boolean = true): String { val iconSpace = " " var res = "" - if (meta.itemEdited) res += iconSpace + if (showEdited && meta.itemEdited) res += iconSpace if (meta.itemTimed != null) { res += iconSpace val ttl = meta.itemTimed.ttl @@ -96,7 +116,7 @@ fun reserveSpaceForMeta(meta: CIMeta, chatTTL: Int?, encrypted: Boolean?): Strin res += shortTimeText(ttl) } } - if (meta.statusIcon(CurrentColors.value.colors.secondary) != null || !meta.disappearing) { + if (showStatus && (meta.statusIcon(CurrentColors.value.colors.secondary) != null || !meta.disappearing)) { res += iconSpace } if (encrypted != null) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt index c9aea2c6dd..10078dc266 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt @@ -365,7 +365,7 @@ fun ChatItemView( } @Composable fun CallItem(status: CICallStatus, duration: Int) { - CICallItemView(cInfo, cItem, status, duration, acceptCall) + CICallItemView(cInfo, cItem, status, duration, acceptCall, cInfo.timedMessagesTTL) DeleteItemMenu() } @@ -459,11 +459,11 @@ fun ChatItemView( DeleteItemMenu() } is CIContent.RcvGroupInvitation -> { - CIGroupInvitationView(cItem, c.groupInvitation, c.memberRole, joinGroup = joinGroup, chatIncognito = cInfo.incognito) + CIGroupInvitationView(cItem, c.groupInvitation, c.memberRole, joinGroup = joinGroup, chatIncognito = cInfo.incognito, timedMessagesTTL = cInfo.timedMessagesTTL) DeleteItemMenu() } is CIContent.SndGroupInvitation -> { - CIGroupInvitationView(cItem, c.groupInvitation, c.memberRole, joinGroup = joinGroup, chatIncognito = cInfo.incognito) + CIGroupInvitationView(cItem, c.groupInvitation, c.memberRole, joinGroup = joinGroup, chatIncognito = cInfo.incognito, timedMessagesTTL = cInfo.timedMessagesTTL) DeleteItemMenu() } is CIContent.RcvDirectEventContent -> { From f712eb0d1f11130b7c3445c09e30cf55b290a5ec Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Thu, 25 Apr 2024 13:16:49 +0100 Subject: [PATCH 2/3] ui: add link to the release post --- apps/ios/Shared/Views/Onboarding/WhatsNewView.swift | 1 + .../simplex/common/views/onboarding/WhatsNewView.kt | 1 + ...ding-transparency-v5-7-better-user-experience.md | 13 +++++++++++++ 3 files changed, 15 insertions(+) create mode 100644 blog/20240426-simplex-legally-binding-transparency-v5-7-better-user-experience.md diff --git a/apps/ios/Shared/Views/Onboarding/WhatsNewView.swift b/apps/ios/Shared/Views/Onboarding/WhatsNewView.swift index 6886c18447..209c440b16 100644 --- a/apps/ios/Shared/Views/Onboarding/WhatsNewView.swift +++ b/apps/ios/Shared/Views/Onboarding/WhatsNewView.swift @@ -378,6 +378,7 @@ private let versionDescriptions: [VersionDescription] = [ ), VersionDescription( version: "v5.7", + post: URL(string: "https://simplex.chat/blog/20240426-simplex-legally-binding-transparency-v5-7-better-user-experience.html"), features: [ FeatureDescription( icon: "key", diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/WhatsNewView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/WhatsNewView.kt index 43c492a732..df6c66deb4 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/WhatsNewView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/WhatsNewView.kt @@ -523,6 +523,7 @@ private val versionDescriptions: List = listOf( ), VersionDescription( version = "v5.7", + post = "https://simplex.chat/blog/20240426-simplex-legally-binding-transparency-v5-7-better-user-experience.html", features = listOf( FeatureDescription( icon = MR.images.ic_vpn_key_filled, diff --git a/blog/20240426-simplex-legally-binding-transparency-v5-7-better-user-experience.md b/blog/20240426-simplex-legally-binding-transparency-v5-7-better-user-experience.md new file mode 100644 index 0000000000..77254bbbea --- /dev/null +++ b/blog/20240426-simplex-legally-binding-transparency-v5-7-better-user-experience.md @@ -0,0 +1,13 @@ + +--- +layout: layouts/article.html +title: "SimpleX network: legally binding transparency, v5.7 released with better user experience for calls and messages" +date: 2024-04-26 +preview: blog_previews/20240323.html +draft: true +permalink: "/blog/20240426-simplex-legally-binding-transparency-v5-7-better-user-experience.html" +--- + +# SimpleX network: legally binding transparency, v5.7 released with better user experience for calls and messages + +This is a permalink for the post From 5325b0a543bb9b82ce652161c054038802dc0dba Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Thu, 25 Apr 2024 13:40:06 +0100 Subject: [PATCH 3/3] core: update simplexmq to 5.7.0.3 --- cabal.project | 2 +- scripts/nix/sha256map.nix | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cabal.project b/cabal.project index 6c14023e17..04e92734c8 100644 --- a/cabal.project +++ b/cabal.project @@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd source-repository-package type: git location: https://github.com/simplex-chat/simplexmq.git - tag: b931c1be3721f002747742d1e100c566966523f7 + tag: 935d2e25df80eed7761c48a01529b6c0da0d3baa source-repository-package type: git diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix index 253326900d..badbf49541 100644 --- a/scripts/nix/sha256map.nix +++ b/scripts/nix/sha256map.nix @@ -1,5 +1,5 @@ { - "https://github.com/simplex-chat/simplexmq.git"."b931c1be3721f002747742d1e100c566966523f7" = "1wbbazc2a5dkjggwiha5b4bya34hf44wl15930h2mhsbj9xmzvig"; + "https://github.com/simplex-chat/simplexmq.git"."935d2e25df80eed7761c48a01529b6c0da0d3baa" = "1gyis2zvxm6352x3myaxdifr9sy4fkhygwqmzgxvn669gmf4gx2n"; "https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38"; "https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d"; "https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl";