diff --git a/apps/ios/Shared/Views/Chat/ChatView.swift b/apps/ios/Shared/Views/Chat/ChatView.swift index 97ffd61116..5ec69412a6 100644 --- a/apps/ios/Shared/Views/Chat/ChatView.swift +++ b/apps/ios/Shared/Views/Chat/ChatView.swift @@ -827,6 +827,9 @@ struct ChatView: View { menu.append(deleteUIAction(ci)) } else if ci.mergeCategory != nil && ((range?.count ?? 0) > 1 || revealed) { menu.append(revealed ? shrinkUIAction() : expandUIAction()) + menu.append(deleteUIAction(ci)) + } else if ci.showLocalDelete { + menu.append(deleteUIAction(ci)) } return menu } @@ -1039,7 +1042,7 @@ struct ChatView: View { image: UIImage(systemName: "trash"), attributes: [.destructive] ) { _ in - if !revealed && ci.meta.itemDeleted != nil, + if !revealed, let currIndex = m.getChatItemIndex(ci), let ciCategory = ci.mergeCategory { let (prevHidden, _) = m.getPrevShownChatItem(currIndex, ciCategory) diff --git a/apps/ios/SimpleXChat/ChatTypes.swift b/apps/ios/SimpleXChat/ChatTypes.swift index d1f1fc06d1..24aca0dd18 100644 --- a/apps/ios/SimpleXChat/ChatTypes.swift +++ b/apps/ios/SimpleXChat/ChatTypes.swift @@ -2437,6 +2437,16 @@ public struct ChatItem: Identifiable, Decodable { } } + public var showLocalDelete: Bool { + switch content { + case .sndDirectE2EEInfo: return false + case .rcvDirectE2EEInfo: return false + case .sndGroupE2EEInfo: return false + case .rcvGroupE2EEInfo: return false + default: return true + } + } + public static func getSample (_ id: Int64, _ dir: CIDirection, _ ts: Date, _ text: String, _ status: CIStatus = .sndNew, quotedItem: CIQuote? = nil, file: CIFile? = nil, itemDeleted: CIDeleted? = nil, itemEdited: Bool = false, itemLive: Bool = false, deletable: Bool = true, editable: Bool = true) -> ChatItem { ChatItem( chatDir: dir, 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 427f34b2e5..c9aea2c6dd 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 @@ -175,6 +175,13 @@ fun ChatItemView( } } + @Composable + fun DeleteItemMenu() { + DefaultDropdownMenu(showMenu) { + DeleteItemAction(cItem, revealed, showMenu, questionText = deleteMessageQuestionText(), deleteMessage, deleteMessages) + } + } + @Composable fun MsgContentItemDropdownMenu() { val saveFileLauncher = rememberSaveFileLauncher(ciFile = cItem.file) @@ -305,10 +312,13 @@ fun ChatItemView( } else { ExpandItemAction(revealed, showMenu) } + DeleteItemAction(cItem, revealed, showMenu, questionText = deleteMessageQuestionText(), deleteMessage, deleteMessages) } } else -> { - showMenu.value = false + DefaultDropdownMenu(showMenu) { + DeleteItemAction(cItem, revealed, showMenu, questionText = deleteMessageQuestionText(), deleteMessage, deleteMessages) + } } } } @@ -356,6 +366,7 @@ fun ChatItemView( @Composable fun CallItem(status: CICallStatus, duration: Int) { CICallItemView(cInfo, cItem, status, duration, acceptCall) + DeleteItemMenu() } fun mergedGroupEventText(chatItem: ChatItem): String? { @@ -439,12 +450,22 @@ fun ChatItemView( is CIContent.RcvCall -> CallItem(c.status, c.duration) is CIContent.RcvIntegrityError -> if (developerTools) { IntegrityErrorItemView(c.msgError, cItem, cInfo.timedMessagesTTL) + DeleteItemMenu() } else { Box(Modifier.size(0.dp)) {} } - is CIContent.RcvDecryptionError -> CIRcvDecryptionError(c.msgDecryptError, c.msgCount, cInfo, cItem, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember) - is CIContent.RcvGroupInvitation -> CIGroupInvitationView(cItem, c.groupInvitation, c.memberRole, joinGroup = joinGroup, chatIncognito = cInfo.incognito) - is CIContent.SndGroupInvitation -> CIGroupInvitationView(cItem, c.groupInvitation, c.memberRole, joinGroup = joinGroup, chatIncognito = cInfo.incognito) + is CIContent.RcvDecryptionError -> { + CIRcvDecryptionError(c.msgDecryptError, c.msgCount, cInfo, cItem, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember) + DeleteItemMenu() + } + is CIContent.RcvGroupInvitation -> { + CIGroupInvitationView(cItem, c.groupInvitation, c.memberRole, joinGroup = joinGroup, chatIncognito = cInfo.incognito) + DeleteItemMenu() + } + is CIContent.SndGroupInvitation -> { + CIGroupInvitationView(cItem, c.groupInvitation, c.memberRole, joinGroup = joinGroup, chatIncognito = cInfo.incognito) + DeleteItemMenu() + } is CIContent.RcvDirectEventContent -> { EventItemView() MsgContentItemDropdownMenu() @@ -479,6 +500,7 @@ fun ChatItemView( is CIContent.RcvChatPreference -> { val ct = if (cInfo is ChatInfo.Direct) cInfo.contact else null CIFeaturePreferenceView(cItem, ct, c.feature, c.allowed, acceptFeature) + DeleteItemMenu() } is CIContent.SndChatPreference -> { CIChatFeatureView(cInfo, cItem, c.feature, MaterialTheme.colors.secondary, icon = c.feature.icon, revealed, showMenu = showMenu) @@ -507,7 +529,10 @@ fun ChatItemView( is CIContent.RcvDirectE2EEInfo -> DirectE2EEInfoText(c.e2eeInfo) is CIContent.SndGroupE2EEInfo -> E2EEInfoNoPQText() is CIContent.RcvGroupE2EEInfo -> E2EEInfoNoPQText() - is CIContent.InvalidJSON -> CIInvalidJSONView(c.json) + is CIContent.InvalidJSON -> { + CIInvalidJSONView(c.json) + DeleteItemMenu() + } } } @@ -574,7 +599,7 @@ fun DeleteItemAction( painterResource(MR.images.ic_delete), onClick = { showMenu.value = false - if (!revealed.value && cItem.meta.itemDeleted != null) { + if (!revealed.value) { val currIndex = chatModel.getChatItemIndexOrNull(cItem) val ciCategory = cItem.mergeCategory if (currIndex != null && ciCategory != null) {