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 -> {