android: show disappearing message timer on calls and group invitations (#4090)

* android: show disappearing message timer on calls and group invitations

* fix padding
This commit is contained in:
spaced4ndy
2024-04-25 15:15:52 +04:00
committed by GitHub
parent 3eb88ab896
commit fc6fa5315b
5 changed files with 95 additions and 66 deletions

View File

@@ -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(" ")

View File

@@ -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)
}
}

View File

@@ -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
)
}
}

View File

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

View File

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