SimpleX-Chat/apps/ios/Shared/Views/Chat/ChatItem/CIGroupInvitationView.swift
Evgeny 4b42a19ccb
ios: fix XCode 16 regressions (tap not working on files, quotes, images, voice messages, etc.), open link previews on tap (#5880)
* ios: fix XCode 16 regressions (tap not working on files, quotes, images, voice messages, etc.), open link previews on tap

* fix voice recording

* fix video, accepting calls from chat, preference toggles in chat

* WIP message and meta

* handle links in attributed strings

* custom attribute for links to prevent race conditions with default tap handler
2025-05-10 14:37:45 +01:00

151 lines
5.8 KiB
Swift

//
// CIGroupInvitationView.swift
// SimpleX (iOS)
//
// Created by JRoberts on 15.07.2022.
// Copyright © 2022 SimpleX Chat. All rights reserved.
//
import SwiftUI
import SimpleXChat
struct CIGroupInvitationView: View {
@EnvironmentObject var chatModel: ChatModel
@EnvironmentObject var theme: AppTheme
@Environment(\.showTimestamp) var showTimestamp: Bool
@ObservedObject var chat: Chat
var chatItem: ChatItem
var groupInvitation: CIGroupInvitation
var memberRole: GroupMemberRole
var chatIncognito: Bool = false
@State private var frameWidth: CGFloat = 0
@State private var inProgress = false
@State private var progressByTimeout = false
@AppStorage(DEFAULT_SHOW_SENT_VIA_RPOXY) private var showSentViaProxy = false
var body: some View {
let action = !chatItem.chatDir.sent && groupInvitation.status == .pending
let v = ZStack(alignment: .bottomTrailing) {
ZStack {
VStack(alignment: .leading) {
groupInfoView(action)
.padding(.horizontal, 2)
.padding(.top, 8)
.padding(.bottom, 6)
.overlay(DetermineWidth())
Divider().frame(width: frameWidth)
if action {
VStack(alignment: .leading, spacing: 2) {
groupInvitationText()
.overlay(DetermineWidth())
(
Text(chatIncognito ? "Tap to join incognito" : "Tap to join")
.foregroundColor(inProgress ? theme.colors.secondary : chatIncognito ? .indigo : theme.colors.primary)
.font(.callout)
+ Text(verbatim: " ")
+ ciMetaText(chatItem.meta, chatTTL: nil, encrypted: nil, colorMode: .transparent, showStatus: false, showEdited: false, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp)
)
.overlay(DetermineWidth())
}
} else {
(
groupInvitationText()
+ Text(verbatim: " ")
+ ciMetaText(chatItem.meta, chatTTL: nil, encrypted: nil, colorMode: .transparent, showStatus: false, showEdited: false, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp)
)
.overlay(DetermineWidth())
}
}
.padding(.bottom, 2)
if progressByTimeout {
ProgressView().scaleEffect(2)
}
}
CIMetaView(chat: chat, chatItem: chatItem, metaColor: theme.colors.secondary, showStatus: false, showEdited: false)
}
.padding(.horizontal, 12)
.padding(.vertical, 6)
.background { chatItemFrameColor(chatItem, theme).modifier(ChatTailPadding()) }
.textSelection(.disabled)
.onPreferenceChange(DetermineWidth.Key.self) { frameWidth = $0 }
.onChange(of: inProgress) { inProgress in
if inProgress {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
progressByTimeout = inProgress
}
} else {
progressByTimeout = false
}
}
if action {
v.simultaneousGesture(TapGesture().onEnded {
inProgress = true
joinGroup(groupInvitation.groupId) {
await MainActor.run { inProgress = false }
}
})
.disabled(inProgress)
} else {
v
}
}
private func groupInfoView(_ action: Bool) -> some View {
var color: Color
if action && !inProgress {
color = chatIncognito ? .indigo : theme.colors.primary
} else {
color = Color(uiColor: .tertiaryLabel)
}
return HStack(alignment: .top) {
ProfileImage(
imageStr: groupInvitation.groupProfile.image,
iconName: "person.2.circle.fill",
size: 44,
color: color
)
.padding(.trailing, 4)
VStack(alignment: .leading) {
let p = groupInvitation.groupProfile
Text(p.displayName).font(.headline).lineLimit(2)
if p.fullName != "" && p.displayName != p.fullName {
Text(p.fullName).font(.subheadline).lineLimit(2)
}
}
.frame(minHeight: 44)
}
}
private func groupInvitationText() -> Text {
Text(groupInvitationStr())
.font(.callout)
}
private func groupInvitationStr() -> LocalizedStringKey {
if chatItem.chatDir.sent {
return "You sent group invitation"
} else {
switch groupInvitation.status {
case .pending: return "You are invited to group"
case .accepted: return "You joined this group"
case .rejected: return "You rejected group invitation"
case .expired: return "Group invitation expired"
}
}
}
}
struct CIGroupInvitationView_Previews: PreviewProvider {
static var previews: some View {
Group {
CIGroupInvitationView(chat: Chat.sampleData, chatItem: ChatItem.getGroupInvitationSample(), groupInvitation: CIGroupInvitation.getSample(groupProfile: GroupProfile(displayName: "team", fullName: "team")), memberRole: .admin)
CIGroupInvitationView(chat: Chat.sampleData, chatItem: ChatItem.getGroupInvitationSample(), groupInvitation: CIGroupInvitation.getSample(status: .accepted), memberRole: .admin)
}
}
}