mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2025-06-29 04:39:53 +00:00
* ios: disappearing messages * show ttl in meta if different * mark messages as disappearing when read * previews
165 lines
8.2 KiB
Swift
165 lines
8.2 KiB
Swift
//
|
|
// ChatItemView.swift
|
|
// SimpleX
|
|
//
|
|
// Created by Evgeny Poberezkin on 30/01/2022.
|
|
// Copyright © 2022 SimpleX Chat. All rights reserved.
|
|
//
|
|
|
|
import SwiftUI
|
|
import SimpleXChat
|
|
|
|
struct ChatItemView: View {
|
|
var chatInfo: ChatInfo
|
|
var chatItem: ChatItem
|
|
var showMember = false
|
|
var maxWidth: CGFloat = .infinity
|
|
@State var scrollProxy: ScrollViewProxy? = nil
|
|
@Binding var revealed: Bool
|
|
|
|
var body: some View {
|
|
let ci = chatItem
|
|
if chatItem.meta.itemDeleted && !revealed {
|
|
MarkedDeletedItemView(chatItem: chatItem, showMember: showMember)
|
|
} else if ci.quotedItem == nil && !ci.meta.itemDeleted && !ci.meta.isLive {
|
|
if let mc = ci.content.msgContent, mc.isText && isShortEmoji(ci.content.text) {
|
|
EmojiItemView(chatItem: ci)
|
|
} else if ci.content.text.isEmpty, case let .voice(_, duration) = ci.content.msgContent {
|
|
CIVoiceView(chatItem: ci, recordingFile: ci.file, duration: duration)
|
|
} else if ci.content.msgContent == nil {
|
|
ChatItemContentView(chatInfo: chatInfo, chatItem: chatItem, showMember: showMember, msgContentView: { Text(ci.text) }) // msgContent is unreachable branch in this case
|
|
} else {
|
|
framedItemView()
|
|
}
|
|
} else {
|
|
framedItemView()
|
|
}
|
|
}
|
|
|
|
private func framedItemView() -> some View {
|
|
FramedItemView(chatInfo: chatInfo, chatItem: chatItem, showMember: showMember, maxWidth: maxWidth, scrollProxy: scrollProxy)
|
|
}
|
|
}
|
|
|
|
struct ChatItemContentView<Content: View>: View {
|
|
var chatInfo: ChatInfo
|
|
var chatItem: ChatItem
|
|
var showMember: Bool
|
|
var msgContentView: () -> Content
|
|
|
|
var body: some View {
|
|
switch chatItem.content {
|
|
case .sndMsgContent: msgContentView()
|
|
case .rcvMsgContent: msgContentView()
|
|
case .sndDeleted: deletedItemView()
|
|
case .rcvDeleted: deletedItemView()
|
|
case let .sndCall(status, duration): callItemView(status, duration)
|
|
case let .rcvCall(status, duration): callItemView(status, duration)
|
|
case .rcvIntegrityError: IntegrityErrorItemView(chatItem: chatItem, showMember: showMember)
|
|
case let .rcvGroupInvitation(groupInvitation, memberRole): groupInvitationItemView(groupInvitation, memberRole)
|
|
case let .sndGroupInvitation(groupInvitation, memberRole): groupInvitationItemView(groupInvitation, memberRole)
|
|
case .rcvGroupEvent: eventItemView()
|
|
case .sndGroupEvent: eventItemView()
|
|
case .rcvConnEvent: eventItemView()
|
|
case .sndConnEvent: eventItemView()
|
|
case let .rcvChatFeature(feature, enabled, param): chatFeatureView(feature, enabled.iconColor, param)
|
|
case let .sndChatFeature(feature, enabled, param): chatFeatureView(feature, enabled.iconColor, param)
|
|
case let .rcvGroupFeature(feature, preference, param): chatFeatureView(feature, preference.enable.iconColor, param)
|
|
case let .sndGroupFeature(feature, preference, param): chatFeatureView(feature, preference.enable.iconColor, param)
|
|
case let .rcvChatFeatureRejected(feature): chatFeatureView(feature, .red)
|
|
case let .rcvGroupFeatureRejected(feature): chatFeatureView(feature, .red)
|
|
}
|
|
}
|
|
|
|
private func deletedItemView() -> some View {
|
|
DeletedItemView(chatItem: chatItem, showMember: showMember)
|
|
}
|
|
|
|
private func callItemView(_ status: CICallStatus, _ duration: Int) -> some View {
|
|
CICallItemView(chatInfo: chatInfo, chatItem: chatItem, status: status, duration: duration)
|
|
}
|
|
|
|
private func groupInvitationItemView(_ groupInvitation: CIGroupInvitation, _ memberRole: GroupMemberRole) -> some View {
|
|
CIGroupInvitationView(chatItem: chatItem, groupInvitation: groupInvitation, memberRole: memberRole, chatIncognito: chatInfo.incognito)
|
|
}
|
|
|
|
private func eventItemView() -> some View {
|
|
CIEventView(chatItem: chatItem)
|
|
}
|
|
|
|
private func chatFeatureView(_ feature: Feature, _ iconColor: Color, _ param: Int? = nil) -> some View {
|
|
CIChatFeatureView(chatItem: chatItem, feature: feature, iconColor: iconColor)
|
|
}
|
|
}
|
|
|
|
struct ChatItemView_Previews: PreviewProvider {
|
|
static var previews: some View {
|
|
Group{
|
|
ChatItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello"), revealed: Binding.constant(false))
|
|
ChatItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too"), revealed: Binding.constant(false))
|
|
ChatItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(1, .directSnd, .now, "🙂"), revealed: Binding.constant(false))
|
|
ChatItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directRcv, .now, "🙂🙂🙂🙂🙂"), revealed: Binding.constant(false))
|
|
ChatItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directRcv, .now, "🙂🙂🙂🙂🙂🙂"), revealed: Binding.constant(false))
|
|
ChatItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getDeletedContentSample(), revealed: Binding.constant(false))
|
|
ChatItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent, true, false), revealed: Binding.constant(false))
|
|
ChatItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(1, .directSnd, .now, "🙂", .sndSent, false, false, true), revealed: Binding.constant(true))
|
|
ChatItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent, false, false, true), revealed: Binding.constant(true))
|
|
}
|
|
.previewLayout(.fixed(width: 360, height: 70))
|
|
.environmentObject(Chat.sampleData)
|
|
}
|
|
}
|
|
|
|
struct ChatItemView_NonMsgContentDeleted_Previews: PreviewProvider {
|
|
static var previews: some View {
|
|
let ciFeatureContent = CIContent.rcvChatFeature(feature: .fullDelete, enabled: FeatureEnabled(forUser: false, forContact: false), param: nil)
|
|
Group{
|
|
ChatItemView(
|
|
chatInfo: ChatInfo.sampleData.direct,
|
|
chatItem: ChatItem(
|
|
chatDir: .directRcv,
|
|
meta: CIMeta.getSample(1, .now, "1 skipped message", .rcvRead, true, false, false),
|
|
content: .rcvIntegrityError(msgError: .msgSkipped(fromMsgId: 1, toMsgId: 2)),
|
|
quotedItem: nil,
|
|
file: nil
|
|
),
|
|
revealed: Binding.constant(true)
|
|
)
|
|
ChatItemView(
|
|
chatInfo: ChatInfo.sampleData.direct,
|
|
chatItem: ChatItem(
|
|
chatDir: .directRcv,
|
|
meta: CIMeta.getSample(1, .now, "received invitation to join group team as admin", .rcvRead, true, false, false),
|
|
content: .rcvGroupInvitation(groupInvitation: CIGroupInvitation.getSample(status: .pending), memberRole: .admin),
|
|
quotedItem: nil,
|
|
file: nil
|
|
),
|
|
revealed: Binding.constant(true)
|
|
)
|
|
ChatItemView(
|
|
chatInfo: ChatInfo.sampleData.direct,
|
|
chatItem: ChatItem(
|
|
chatDir: .directRcv,
|
|
meta: CIMeta.getSample(1, .now, "group event text", .rcvRead, true, false, false),
|
|
content: .rcvGroupEvent(rcvGroupEvent: .memberAdded(groupMemberId: 1, profile: Profile.sampleData)),
|
|
quotedItem: nil,
|
|
file: nil
|
|
),
|
|
revealed: Binding.constant(true)
|
|
)
|
|
ChatItemView(
|
|
chatInfo: ChatInfo.sampleData.direct,
|
|
chatItem: ChatItem(
|
|
chatDir: .directRcv,
|
|
meta: CIMeta.getSample(1, .now, ciFeatureContent.text, .rcvRead, true, false, false),
|
|
content: ciFeatureContent,
|
|
quotedItem: nil,
|
|
file: nil
|
|
),
|
|
revealed: Binding.constant(true)
|
|
)
|
|
}
|
|
.previewLayout(.fixed(width: 360, height: 70))
|
|
.environmentObject(Chat.sampleData)
|
|
}
|
|
}
|