mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2025-06-28 12:19:54 +00:00
ios: error handling
This commit is contained in:
parent
b97a031d70
commit
1b9298fcee
8 changed files with 155 additions and 139 deletions
|
@ -899,8 +899,7 @@ func apiConnectPlan(connLink: String) async -> ((CreatedConnLink, ConnectionPlan
|
|||
}
|
||||
let r: APIResult<ChatResponse1> = await chatApiSendCmd(.apiConnectPlan(userId: userId, connLink: connLink))
|
||||
if case let .result(.connectionPlan(_, connLink, connPlan)) = r { return ((connLink, connPlan), nil) }
|
||||
let alert = apiConnectResponseAlert(r.unexpected) ?? connectionErrorAlert(r)
|
||||
return (nil, alert)
|
||||
return (nil, apiConnectResponseAlert(r))
|
||||
}
|
||||
|
||||
func apiConnect(incognito: Bool, connLink: CreatedConnLink) async -> (ConnReqType, PendingContactConnection)? {
|
||||
|
@ -933,12 +932,11 @@ func apiConnect_(incognito: Bool, connLink: CreatedConnLink) async -> ((ConnReqT
|
|||
return (nil, alert)
|
||||
default: ()
|
||||
}
|
||||
let alert = apiConnectResponseAlert(r.unexpected) ?? connectionErrorAlert(r)
|
||||
return (nil, alert)
|
||||
return (nil, apiConnectResponseAlert(r))
|
||||
}
|
||||
|
||||
private func apiConnectResponseAlert(_ r: ChatError) -> Alert? {
|
||||
switch r {
|
||||
private func apiConnectResponseAlert<R>(_ r: APIResult<R>) -> Alert {
|
||||
switch r.unexpected {
|
||||
case .error(.invalidConnReq):
|
||||
mkAlert(
|
||||
title: "Invalid connection link",
|
||||
|
@ -974,12 +972,12 @@ private func apiConnectResponseAlert(_ r: ChatError) -> Alert? {
|
|||
if internalErr == "SEUniqueID" {
|
||||
mkAlert(
|
||||
title: "Already connected?",
|
||||
message: "It seems like you are already connected via this link. If it is not the case, there was an error (\(responseError(r)))."
|
||||
message: "It seems like you are already connected via this link. If it is not the case, there was an error (\(internalErr))."
|
||||
)
|
||||
} else {
|
||||
nil
|
||||
connectionErrorAlert(r)
|
||||
}
|
||||
default: nil
|
||||
default: connectionErrorAlert(r)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1027,16 +1025,18 @@ func apiChangePreparedGroupUser(groupId: Int64, newUserId: Int64) async throws -
|
|||
throw r.unexpected
|
||||
}
|
||||
|
||||
func apiConnectPreparedContact(contactId: Int64, incognito: Bool, msg: MsgContent?) async throws -> Contact {
|
||||
let r: ChatResponse1 = try await chatSendCmd(.apiConnectPreparedContact(contactId: contactId, incognito: incognito, msg: msg))
|
||||
if case let .startedConnectionToContact(_, contact) = r { return contact }
|
||||
throw r.unexpected
|
||||
func apiConnectPreparedContact(contactId: Int64, incognito: Bool, msg: MsgContent?) async -> Contact? {
|
||||
let r: APIResult<ChatResponse1> = await chatApiSendCmd(.apiConnectPreparedContact(contactId: contactId, incognito: incognito, msg: msg))
|
||||
if case let .result(.startedConnectionToContact(_, contact)) = r { return contact }
|
||||
AlertManager.shared.showAlert(apiConnectResponseAlert(r))
|
||||
return nil
|
||||
}
|
||||
|
||||
func apiConnectPreparedGroup(groupId: Int64, incognito: Bool, msg: MsgContent?) async throws -> GroupInfo {
|
||||
let r: ChatResponse1 = try await chatSendCmd(.apiConnectPreparedGroup(groupId: groupId, incognito: incognito, msg: msg))
|
||||
if case let .startedConnectionToGroup(_, groupInfo) = r { return groupInfo }
|
||||
throw r.unexpected
|
||||
func apiConnectPreparedGroup(groupId: Int64, incognito: Bool, msg: MsgContent?) async -> GroupInfo? {
|
||||
let r: APIResult<ChatResponse1> = await chatApiSendCmd(.apiConnectPreparedGroup(groupId: groupId, incognito: incognito, msg: msg))
|
||||
if case let .result(.startedConnectionToGroup(_, groupInfo)) = r { return groupInfo }
|
||||
AlertManager.shared.showAlert(apiConnectResponseAlert(r))
|
||||
return nil
|
||||
}
|
||||
|
||||
func apiConnectContactViaAddress(incognito: Bool, contactId: Int64) async -> (Contact?, Alert?) {
|
||||
|
|
|
@ -405,14 +405,15 @@ struct ComposeView: View {
|
|||
}
|
||||
|
||||
if chat.chatInfo.groupInfo?.nextConnectPrepared == true {
|
||||
Button(action: connectPreparedGroup) {
|
||||
if chat.chatInfo.groupInfo?.businessChat == nil {
|
||||
if chat.chatInfo.groupInfo?.businessChat == nil {
|
||||
Button(action: connectPreparedGroup) {
|
||||
Label("Join group", systemImage: "person.2.fill")
|
||||
} else {
|
||||
Label("Connect", systemImage: "briefcase.fill")
|
||||
}
|
||||
.frame(height: 60)
|
||||
.disabled(composeState.inProgress)
|
||||
} else {
|
||||
sendContactRequestView(disableSendButton, icon: "briefcase.fill", sendRequest: connectPreparedGroup)
|
||||
}
|
||||
.frame(height: 60)
|
||||
} else if contact?.nextSendGrpInv == true {
|
||||
contextSendMessageToConnect("Send direct message to connect")
|
||||
Divider()
|
||||
|
@ -428,24 +429,9 @@ struct ComposeView: View {
|
|||
Label("Connect", systemImage: "person.fill.badge.plus")
|
||||
}
|
||||
.frame(height: 60)
|
||||
.disabled(composeState.inProgress)
|
||||
case .con:
|
||||
HStack (alignment: .center) {
|
||||
sendMessageView(
|
||||
disableSendButton,
|
||||
placeholder: NSLocalizedString("Add message", comment: "placeholder for sending contact request"),
|
||||
sendToConnect: sendConnectPreparedContactRequest
|
||||
)
|
||||
if composeState.whitespaceOnly {
|
||||
Button(action: sendConnectPreparedContactRequest) {
|
||||
HStack {
|
||||
Text("Connect").fontWeight(.medium)
|
||||
Image(systemName: "person.fill.badge.plus")
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 8)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 12)
|
||||
sendContactRequestView(disableSendButton, icon: "person.fill.badge.plus", sendRequest: sendConnectPreparedContactRequest)
|
||||
}
|
||||
} else if contact?.nextAcceptContactRequest == true, let crId = contact?.contactRequestId {
|
||||
ContextContactRequestActionsView(contactRequestId: crId)
|
||||
|
@ -620,6 +606,27 @@ struct ComposeView: View {
|
|||
}
|
||||
}
|
||||
|
||||
private func sendContactRequestView(_ disableSendButton: Bool, icon: String, sendRequest: @escaping () -> Void) -> some View {
|
||||
HStack (alignment: .center) {
|
||||
sendMessageView(
|
||||
disableSendButton,
|
||||
placeholder: NSLocalizedString("Add message", comment: "placeholder for sending contact request"),
|
||||
sendToConnect: sendRequest
|
||||
)
|
||||
if composeState.whitespaceOnly {
|
||||
Button(action: sendRequest) {
|
||||
HStack {
|
||||
Text("Connect").fontWeight(.medium)
|
||||
Image(systemName: icon)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 8)
|
||||
.disabled(composeState.inProgress)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 12)
|
||||
}
|
||||
|
||||
private func sendMessageView(_ disableSendButton: Bool, placeholder: String? = nil, sendToConnect: (() -> Void)? = nil) -> some View {
|
||||
ZStack(alignment: .leading) {
|
||||
SendMessageView(
|
||||
|
@ -695,6 +702,7 @@ struct ComposeView: View {
|
|||
Task {
|
||||
do {
|
||||
if let mc = connectCheckLinkPreview() {
|
||||
await sending()
|
||||
let contact = try await apiSendMemberContactInvitation(chat.chatInfo.apiId, mc)
|
||||
await MainActor.run {
|
||||
self.chatModel.updateContact(contact)
|
||||
|
@ -704,6 +712,7 @@ struct ComposeView: View {
|
|||
AlertManager.shared.showAlertMsg(title: "Empty message!")
|
||||
}
|
||||
} catch {
|
||||
composeState.inProgress = false
|
||||
logger.error("ChatView.sendMemberContactInvitation error: \(error.localizedDescription)")
|
||||
AlertManager.shared.showAlertMsg(title: "Error sending member contact invitation", message: "Error: \(responseError(error))")
|
||||
}
|
||||
|
@ -730,32 +739,30 @@ struct ComposeView: View {
|
|||
|
||||
private func sendConnectPreparedContact() {
|
||||
Task {
|
||||
do {
|
||||
let mc = connectCheckLinkPreview()
|
||||
let contact = try await apiConnectPreparedContact(contactId: chat.chatInfo.apiId, incognito: incognitoGroupDefault.get(), msg: mc)
|
||||
await sending()
|
||||
let mc = connectCheckLinkPreview()
|
||||
if let contact = await apiConnectPreparedContact(contactId: chat.chatInfo.apiId, incognito: incognitoGroupDefault.get(), msg: mc) {
|
||||
await MainActor.run {
|
||||
self.chatModel.updateContact(contact)
|
||||
clearState()
|
||||
}
|
||||
} catch {
|
||||
logger.error("ChatView.sendConnectPreparedContact error: \(error.localizedDescription)")
|
||||
AlertManager.shared.showAlertMsg(title: "Error connecting with contact", message: "Error: \(responseError(error))")
|
||||
} else {
|
||||
composeState.inProgress = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func connectPreparedGroup() {
|
||||
Task {
|
||||
do {
|
||||
let mc = connectCheckLinkPreview()
|
||||
let groupInfo = try await apiConnectPreparedGroup(groupId: chat.chatInfo.apiId, incognito: incognitoGroupDefault.get(), msg: mc)
|
||||
await sending()
|
||||
let mc = connectCheckLinkPreview()
|
||||
if let groupInfo = await apiConnectPreparedGroup(groupId: chat.chatInfo.apiId, incognito: incognitoGroupDefault.get(), msg: mc) {
|
||||
await MainActor.run {
|
||||
self.chatModel.updateGroup(groupInfo)
|
||||
clearState()
|
||||
}
|
||||
} catch {
|
||||
logger.error("ChatView.connectPreparedGroup error: \(error.localizedDescription)")
|
||||
AlertManager.shared.showAlertMsg(title: "Error joining group", message: "Error: \(responseError(error))")
|
||||
} else {
|
||||
composeState.inProgress = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1094,10 +1101,6 @@ struct ComposeView: View {
|
|||
}
|
||||
}
|
||||
|
||||
func sending() async {
|
||||
await MainActor.run { composeState.inProgress = true }
|
||||
}
|
||||
|
||||
func updateMessage(_ ei: ChatItem, live: Bool) async -> ChatItem? {
|
||||
if let oldMsgContent = ei.content.msgContent {
|
||||
do {
|
||||
|
@ -1270,6 +1273,10 @@ struct ComposeView: View {
|
|||
}
|
||||
}
|
||||
|
||||
func sending() async {
|
||||
await MainActor.run { composeState.inProgress = true }
|
||||
}
|
||||
|
||||
private func startVoiceMessageRecording() async {
|
||||
startingRecording = true
|
||||
let fileName = generateNewFileName("voice", "m4a")
|
||||
|
|
|
@ -13,60 +13,66 @@ struct ContextContactRequestActionsView: View {
|
|||
@EnvironmentObject var theme: AppTheme
|
||||
var contactRequestId: Int64
|
||||
@UserDefault(DEFAULT_TOOLBAR_MATERIAL) private var toolbarMaterial = ToolbarMaterial.defaultMaterial
|
||||
@State private var inProgress = false
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: 0) {
|
||||
Label("Reject", systemImage: "multiply")
|
||||
.foregroundColor(.red)
|
||||
.frame(maxWidth: .infinity)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
showRejectRequestAlert(contactRequestId)
|
||||
Button(role: .destructive, action: showRejectRequestAlert) {
|
||||
Label("Reject", systemImage: "multiply")
|
||||
}
|
||||
.frame(maxWidth: .infinity, minHeight: 60)
|
||||
|
||||
Label("Accept", systemImage: "checkmark").foregroundColor(theme.colors.primary)
|
||||
.frame(maxWidth: .infinity)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
Button {
|
||||
if ChatModel.shared.addressShortLinkDataSet {
|
||||
Task { await acceptContactRequest(incognito: false, contactRequestId: contactRequestId) }
|
||||
acceptRequest()
|
||||
} else {
|
||||
showAcceptRequestAlert(contactRequestId)
|
||||
showAcceptRequestAlert()
|
||||
}
|
||||
} label: {
|
||||
Label("Accept", systemImage: "checkmark")
|
||||
}
|
||||
.frame(maxWidth: .infinity, minHeight: 60)
|
||||
}
|
||||
.frame(minHeight: 60)
|
||||
.disabled(inProgress)
|
||||
.frame(maxWidth: .infinity)
|
||||
.background(ToolbarMaterial.material(toolbarMaterial))
|
||||
}
|
||||
}
|
||||
|
||||
func showRejectRequestAlert(_ contactRequestId: Int64) {
|
||||
showAlert(
|
||||
NSLocalizedString("Reject contact request", comment: "alert title"),
|
||||
message: NSLocalizedString("The sender will NOT be notified", comment: "alert message"),
|
||||
actions: {[
|
||||
UIAlertAction(title: NSLocalizedString("Reject", comment: "alert action"), style: .destructive) { _ in
|
||||
Task { await rejectContactRequest(contactRequestId, dismissToChatList: true) }
|
||||
},
|
||||
cancelAlertAction
|
||||
]}
|
||||
)
|
||||
}
|
||||
private func showRejectRequestAlert() {
|
||||
showAlert(
|
||||
NSLocalizedString("Reject contact request", comment: "alert title"),
|
||||
message: NSLocalizedString("The sender will NOT be notified", comment: "alert message"),
|
||||
actions: {[
|
||||
UIAlertAction(title: NSLocalizedString("Reject", comment: "alert action"), style: .destructive) { _ in
|
||||
Task { await rejectContactRequest(contactRequestId, dismissToChatList: true) }
|
||||
},
|
||||
cancelAlertAction
|
||||
]}
|
||||
)
|
||||
}
|
||||
|
||||
func showAcceptRequestAlert(_ contactRequestId: Int64) {
|
||||
showAlert(
|
||||
NSLocalizedString("Accept contact request", comment: "alert title"),
|
||||
actions: {[
|
||||
UIAlertAction(title: NSLocalizedString("Accept", comment: "alert action"), style: .default) { _ in
|
||||
Task { await acceptContactRequest(incognito: false, contactRequestId: contactRequestId) }
|
||||
},
|
||||
UIAlertAction(title: NSLocalizedString("Accept incognito", comment: "alert action"), style: .default) { _ in
|
||||
Task { await acceptContactRequest(incognito: true, contactRequestId: contactRequestId) }
|
||||
},
|
||||
cancelAlertAction
|
||||
]}
|
||||
)
|
||||
private func showAcceptRequestAlert() {
|
||||
showAlert(
|
||||
NSLocalizedString("Accept contact request", comment: "alert title"),
|
||||
actions: {[
|
||||
UIAlertAction(title: NSLocalizedString("Accept", comment: "alert action"), style: .default) { _ in
|
||||
acceptRequest()
|
||||
},
|
||||
UIAlertAction(title: NSLocalizedString("Accept incognito", comment: "alert action"), style: .default) { _ in
|
||||
acceptRequest(incognito: true)
|
||||
},
|
||||
cancelAlertAction
|
||||
]}
|
||||
)
|
||||
}
|
||||
|
||||
private func acceptRequest(incognito: Bool = false) {
|
||||
inProgress = true
|
||||
Task {
|
||||
await acceptContactRequest(incognito: false, contactRequestId: contactRequestId)
|
||||
await MainActor.run { inProgress = false }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
|
|
|
@ -887,7 +887,6 @@ struct GroupPreferencesButton: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -178,8 +178,8 @@
|
|||
64C3B0212A0D359700E19930 /* CustomTimePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C3B0202A0D359700E19930 /* CustomTimePicker.swift */; };
|
||||
64C8299D2D54AEEE006B9E89 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C829982D54AEED006B9E89 /* libgmp.a */; };
|
||||
64C8299E2D54AEEE006B9E89 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C829992D54AEEE006B9E89 /* libffi.a */; };
|
||||
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.4-1Rh0qJZPahP19NRjkSYFiJ-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.4-1Rh0qJZPahP19NRjkSYFiJ-ghc9.6.3.a */; };
|
||||
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.4-1Rh0qJZPahP19NRjkSYFiJ.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.4-1Rh0qJZPahP19NRjkSYFiJ.a */; };
|
||||
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.4-DWeDI2Xa9F86P3Q5uUF2Wy-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.4-DWeDI2Xa9F86P3Q5uUF2Wy-ghc9.6.3.a */; };
|
||||
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.4-DWeDI2Xa9F86P3Q5uUF2Wy.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.4-DWeDI2Xa9F86P3Q5uUF2Wy.a */; };
|
||||
64C829A12D54AEEE006B9E89 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299C2D54AEEE006B9E89 /* libgmpxx.a */; };
|
||||
64D0C2C029F9688300B38D5F /* UserAddressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2BF29F9688300B38D5F /* UserAddressView.swift */; };
|
||||
64D0C2C229FA57AB00B38D5F /* UserAddressLearnMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */; };
|
||||
|
@ -543,8 +543,8 @@
|
|||
64C3B0202A0D359700E19930 /* CustomTimePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTimePicker.swift; sourceTree = "<group>"; };
|
||||
64C829982D54AEED006B9E89 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
|
||||
64C829992D54AEEE006B9E89 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
|
||||
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.4-1Rh0qJZPahP19NRjkSYFiJ-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.4.0.4-1Rh0qJZPahP19NRjkSYFiJ-ghc9.6.3.a"; sourceTree = "<group>"; };
|
||||
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.4-1Rh0qJZPahP19NRjkSYFiJ.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.4.0.4-1Rh0qJZPahP19NRjkSYFiJ.a"; sourceTree = "<group>"; };
|
||||
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.4-DWeDI2Xa9F86P3Q5uUF2Wy-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.4.0.4-DWeDI2Xa9F86P3Q5uUF2Wy-ghc9.6.3.a"; sourceTree = "<group>"; };
|
||||
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.4-DWeDI2Xa9F86P3Q5uUF2Wy.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.4.0.4-DWeDI2Xa9F86P3Q5uUF2Wy.a"; sourceTree = "<group>"; };
|
||||
64C8299C2D54AEEE006B9E89 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
|
||||
64D0C2BF29F9688300B38D5F /* UserAddressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressView.swift; sourceTree = "<group>"; };
|
||||
64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressLearnMore.swift; sourceTree = "<group>"; };
|
||||
|
@ -704,8 +704,8 @@
|
|||
64C8299D2D54AEEE006B9E89 /* libgmp.a in Frameworks */,
|
||||
64C8299E2D54AEEE006B9E89 /* libffi.a in Frameworks */,
|
||||
64C829A12D54AEEE006B9E89 /* libgmpxx.a in Frameworks */,
|
||||
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.4-1Rh0qJZPahP19NRjkSYFiJ-ghc9.6.3.a in Frameworks */,
|
||||
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.4-1Rh0qJZPahP19NRjkSYFiJ.a in Frameworks */,
|
||||
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.4-DWeDI2Xa9F86P3Q5uUF2Wy-ghc9.6.3.a in Frameworks */,
|
||||
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.4-DWeDI2Xa9F86P3Q5uUF2Wy.a in Frameworks */,
|
||||
CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -790,8 +790,8 @@
|
|||
64C829992D54AEEE006B9E89 /* libffi.a */,
|
||||
64C829982D54AEED006B9E89 /* libgmp.a */,
|
||||
64C8299C2D54AEEE006B9E89 /* libgmpxx.a */,
|
||||
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.4-1Rh0qJZPahP19NRjkSYFiJ-ghc9.6.3.a */,
|
||||
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.4-1Rh0qJZPahP19NRjkSYFiJ.a */,
|
||||
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.4-DWeDI2Xa9F86P3Q5uUF2Wy-ghc9.6.3.a */,
|
||||
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.4-DWeDI2Xa9F86P3Q5uUF2Wy.a */,
|
||||
);
|
||||
path = Libraries;
|
||||
sourceTree = "<group>";
|
||||
|
|
|
@ -819,7 +819,7 @@ public enum SQLiteError: Decodable, Hashable {
|
|||
|
||||
public enum AgentErrorType: Decodable, Hashable {
|
||||
case CMD(cmdErr: CommandErrorType, errContext: String)
|
||||
case CONN(connErr: ConnectionErrorType)
|
||||
case CONN(connErr: ConnectionErrorType, errContext: String)
|
||||
case SMP(serverAddress: String, smpErr: ProtocolErrorType)
|
||||
case NTF(ntfErr: ProtocolErrorType)
|
||||
case XFTP(xftpErr: XFTPErrorType)
|
||||
|
|
|
@ -1378,6 +1378,7 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat, Hashable {
|
|||
case .memGroupDeleted: return ("group is deleted", nil)
|
||||
case .memRemoved: return ("removed from group", nil)
|
||||
case .memLeft: return ("you left", nil)
|
||||
case .memUnknown: return groupInfo.businessChat == nil ? ("can't send messages", nil) : nil
|
||||
default: return ("can't send messages", nil)
|
||||
}
|
||||
}
|
||||
|
@ -1421,7 +1422,7 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat, Hashable {
|
|||
default: false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public var groupInfo: GroupInfo? {
|
||||
switch self {
|
||||
case let .group(groupInfo, _): return groupInfo
|
||||
|
@ -1531,7 +1532,7 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat, Hashable {
|
|||
public func ntfsEnabled(chatItem: ChatItem) -> Bool {
|
||||
ntfsEnabled(chatItem.meta.userMention)
|
||||
}
|
||||
|
||||
|
||||
public func ntfsEnabled(_ userMention: Bool) -> Bool {
|
||||
switch self.chatSettings?.enableNtfs {
|
||||
case .all: true
|
||||
|
@ -1547,7 +1548,7 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat, Hashable {
|
|||
default: return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public var nextNtfMode: MsgFilter? {
|
||||
self.chatSettings?.enableNtfs.nextMode(mentions: hasMentions)
|
||||
}
|
||||
|
@ -1596,7 +1597,7 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat, Hashable {
|
|||
case .invalidJSON: return .now
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public func ttl(_ globalTTL: ChatItemTTL) -> ChatTTL {
|
||||
switch self {
|
||||
case let .direct(contact):
|
||||
|
@ -1644,7 +1645,7 @@ public struct ChatData: Decodable, Identifiable, Hashable, ChatLike {
|
|||
self.chatItems = chatItems
|
||||
self.chatStats = chatStats
|
||||
}
|
||||
|
||||
|
||||
public static func invalidJSON(_ json: Data?) -> ChatData {
|
||||
ChatData(
|
||||
chatInfo: .invalidJSON(json: json),
|
||||
|
@ -2085,15 +2086,14 @@ public struct GroupInfo: Identifiable, Decodable, NamedChat, Hashable {
|
|||
var createdAt: Date
|
||||
var updatedAt: Date
|
||||
var chatTs: Date?
|
||||
public var connLinkToConnect: CreatedConnLink?
|
||||
public var connLinkStartedConnection: Bool
|
||||
public var preparedGroup: PreparedGroup?
|
||||
public var uiThemes: ThemeModeOverrides?
|
||||
public var membersRequireAttention: Int
|
||||
|
||||
public var id: ChatId { get { "#\(groupId)" } }
|
||||
public var apiId: Int64 { get { groupId } }
|
||||
public var ready: Bool { get { true } }
|
||||
public var nextConnectPrepared: Bool { connLinkToConnect != nil && !connLinkStartedConnection }
|
||||
public var nextConnectPrepared: Bool { if let preparedGroup { !preparedGroup.connLinkStartedConnection } else { false } }
|
||||
public var displayName: String { localAlias == "" ? groupProfile.displayName : localAlias }
|
||||
public var fullName: String { get { groupProfile.fullName } }
|
||||
public var image: String? { get { groupProfile.image } }
|
||||
|
@ -2134,13 +2134,17 @@ public struct GroupInfo: Identifiable, Decodable, NamedChat, Hashable {
|
|||
chatSettings: ChatSettings.defaults,
|
||||
createdAt: .now,
|
||||
updatedAt: .now,
|
||||
connLinkStartedConnection: false,
|
||||
membersRequireAttention: 0,
|
||||
chatTags: [],
|
||||
localAlias: ""
|
||||
)
|
||||
}
|
||||
|
||||
public struct PreparedGroup: Decodable, Hashable {
|
||||
public var connLinkToConnect: CreatedConnLink?
|
||||
public var connLinkStartedConnection: Bool
|
||||
}
|
||||
|
||||
public struct GroupRef: Decodable, Hashable {
|
||||
public var groupId: Int64
|
||||
var localDisplayName: GroupName
|
||||
|
@ -2298,7 +2302,7 @@ public struct GroupMember: Identifiable, Decodable, Hashable {
|
|||
? String.localizedStringWithFormat(NSLocalizedString("Past member %@", comment: "past/unknown group member"), name)
|
||||
: name
|
||||
}
|
||||
|
||||
|
||||
public var localAliasAndFullName: String {
|
||||
get {
|
||||
let p = memberProfile
|
||||
|
@ -2378,7 +2382,7 @@ public struct GroupMember: Identifiable, Decodable, Hashable {
|
|||
return memberStatus != .memRemoved && memberStatus != .memLeft && memberRole < .admin
|
||||
&& userRole >= .admin && userRole >= memberRole && groupInfo.membership.memberActive
|
||||
}
|
||||
|
||||
|
||||
public var canReceiveReports: Bool {
|
||||
memberRole >= .moderator && versionRange.maxVersion >= REPORTS_VERSION
|
||||
}
|
||||
|
@ -2390,7 +2394,7 @@ public struct GroupMember: Identifiable, Decodable, Hashable {
|
|||
memberChatVRange
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public var memberIncognito: Bool {
|
||||
memberProfile.profileId != memberContactProfileId
|
||||
}
|
||||
|
@ -2446,7 +2450,7 @@ public enum GroupMemberRole: String, Identifiable, CaseIterable, Comparable, Cod
|
|||
public var id: Self { self }
|
||||
|
||||
public static var supportedRoles: [GroupMemberRole] = [.observer, .member, .admin, .owner]
|
||||
|
||||
|
||||
public var text: String {
|
||||
switch self {
|
||||
case .observer: return NSLocalizedString("observer", comment: "member role")
|
||||
|
@ -2602,7 +2606,7 @@ public enum ConnectionEntity: Decodable, Hashable {
|
|||
nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// public var localDisplayName: String? {
|
||||
// switch self {
|
||||
// case let .rcvDirectMsgConnection(conn, contact):
|
||||
|
@ -2643,7 +2647,7 @@ public struct NtfMsgInfo: Decodable, Hashable {
|
|||
public enum RcvNtfMsgInfo: Decodable {
|
||||
case info(ntfMsgInfo: NtfMsgInfo?)
|
||||
case error(ntfMsgError: AgentErrorType)
|
||||
|
||||
|
||||
@inline(__always)
|
||||
public var noMsg: Bool {
|
||||
if case let .info(msg) = self { msg == nil } else { true }
|
||||
|
@ -2703,7 +2707,7 @@ public struct CIMentionMember: Decodable, Hashable {
|
|||
public struct CIMention: Decodable, Hashable {
|
||||
public var memberId: String
|
||||
public var memberRef: CIMentionMember?
|
||||
|
||||
|
||||
public init(groupMember m: GroupMember) {
|
||||
self.memberId = m.memberId
|
||||
self.memberRef = CIMentionMember(
|
||||
|
@ -2954,7 +2958,7 @@ public struct ChatItem: Identifiable, Decodable, Hashable {
|
|||
default: return true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public var isReport: Bool {
|
||||
switch content {
|
||||
case let .sndMsgContent(msgContent), let .rcvMsgContent(msgContent):
|
||||
|
@ -3054,14 +3058,14 @@ public struct ChatItem: Identifiable, Decodable, Hashable {
|
|||
file: nil
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
public static func getReportSample(text: String, reason: ReportReason, item: ChatItem, sender: GroupMember? = nil) -> ChatItem {
|
||||
let chatDir = if let sender = sender {
|
||||
CIDirection.groupRcv(groupMember: sender)
|
||||
} else {
|
||||
CIDirection.groupSnd
|
||||
}
|
||||
|
||||
|
||||
return ChatItem(
|
||||
chatDir: chatDir,
|
||||
meta: CIMeta(
|
||||
|
@ -3175,7 +3179,7 @@ public enum CIDirection: Decodable, Hashable {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public func sameDirection(_ dir: CIDirection) -> Bool {
|
||||
switch (self, dir) {
|
||||
case let (.groupRcv(m1), .groupRcv(m2)): m1.groupMemberId == m2.groupMemberId
|
||||
|
@ -3311,7 +3315,7 @@ public enum CIStatus: Decodable, Hashable {
|
|||
case .invalid: return "invalid"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public var sent: Bool {
|
||||
switch self {
|
||||
case .sndNew: true
|
||||
|
@ -4124,7 +4128,7 @@ public enum FileError: Decodable, Equatable, Hashable {
|
|||
case let .other(fileError): String.localizedStringWithFormat(NSLocalizedString("Error: %@", comment: "file error text"), fileError)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public var moreInfoButton: (label: LocalizedStringKey, link: URL)? {
|
||||
switch self {
|
||||
case .blocked: ("How it works", contentModerationPostLink)
|
||||
|
@ -4426,7 +4430,7 @@ public enum ReportReason: Hashable {
|
|||
case profile
|
||||
case other
|
||||
case unknown(type: String)
|
||||
|
||||
|
||||
public static var supportedReasons: [ReportReason] = [.spam, .illegal, .community, .profile, .other]
|
||||
|
||||
public var text: String {
|
||||
|
@ -4439,7 +4443,7 @@ public enum ReportReason: Hashable {
|
|||
case let .unknown(type): return type
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public var attrString: NSAttributedString {
|
||||
let descr = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .body)
|
||||
return NSAttributedString(string: text.isEmpty ? self.text : "\(self.text): ", attributes: [
|
||||
|
@ -4486,7 +4490,7 @@ public struct LinkPreview: Codable, Equatable, Hashable {
|
|||
self.description = description
|
||||
self.image = image
|
||||
}
|
||||
|
||||
|
||||
public var uri: URL
|
||||
public var title: String
|
||||
// TODO remove once optional in haskell
|
||||
|
@ -4535,7 +4539,7 @@ public enum NtfTknStatus: String, Decodable, Hashable {
|
|||
case .expired: NSLocalizedString("Expired", comment: "token status text")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public func info(register: Bool) -> String {
|
||||
switch self {
|
||||
case .new: return NSLocalizedString("Please wait for token to be registered.", comment: "token info")
|
||||
|
@ -4913,9 +4917,9 @@ public enum ChatItemTTL: Identifiable, Comparable, Hashable {
|
|||
public enum ChatTTL: Identifiable, Hashable {
|
||||
case userDefault(ChatItemTTL)
|
||||
case chat(ChatItemTTL)
|
||||
|
||||
|
||||
public var id: Self { self }
|
||||
|
||||
|
||||
public var text: String {
|
||||
switch self {
|
||||
case let .chat(ttl): return ttl.deleteAfterText
|
||||
|
@ -4924,21 +4928,21 @@ public enum ChatTTL: Identifiable, Hashable {
|
|||
ttl.deleteAfterText)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public var neverExpires: Bool {
|
||||
switch self {
|
||||
case let .chat(ttl): return ttl.seconds == 0
|
||||
case let .userDefault(ttl): return ttl.seconds == 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public var value: Int64? {
|
||||
switch self {
|
||||
case let .chat(ttl): return ttl.seconds
|
||||
case .userDefault: return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public var usingDefault: Bool {
|
||||
switch self {
|
||||
case .userDefault: return true
|
||||
|
@ -4951,9 +4955,9 @@ public struct ChatTag: Decodable, Hashable {
|
|||
public var chatTagId: Int64
|
||||
public var chatTagText: String
|
||||
public var chatTagEmoji: String?
|
||||
|
||||
|
||||
public var id: Int64 { chatTagId }
|
||||
|
||||
|
||||
public init(chatTagId: Int64, chatTagText: String, chatTagEmoji: String?) {
|
||||
self.chatTagId = chatTagId
|
||||
self.chatTagText = chatTagText
|
||||
|
|
|
@ -7055,7 +7055,7 @@ sealed class SQLiteError {
|
|||
sealed class AgentErrorType {
|
||||
val string: String get() = when (this) {
|
||||
is CMD -> "CMD ${cmdErr.string} $errContext"
|
||||
is CONN -> "CONN ${connErr.string}"
|
||||
is CONN -> "CONN ${connErr.string} $errContext"
|
||||
is SMP -> "SMP ${smpErr.string}"
|
||||
// is NTF -> "NTF ${ntfErr.string}"
|
||||
is XFTP -> "XFTP ${xftpErr.string}"
|
||||
|
@ -7068,7 +7068,7 @@ sealed class AgentErrorType {
|
|||
is INACTIVE -> "INACTIVE"
|
||||
}
|
||||
@Serializable @SerialName("CMD") class CMD(val cmdErr: CommandErrorType, val errContext: String): AgentErrorType()
|
||||
@Serializable @SerialName("CONN") class CONN(val connErr: ConnectionErrorType): AgentErrorType()
|
||||
@Serializable @SerialName("CONN") class CONN(val connErr: ConnectionErrorType, val errContext: String): AgentErrorType()
|
||||
@Serializable @SerialName("SMP") class SMP(val serverAddress: String, val smpErr: SMPErrorType): AgentErrorType()
|
||||
// @Serializable @SerialName("NTF") class NTF(val ntfErr: SMPErrorType): AgentErrorType()
|
||||
@Serializable @SerialName("XFTP") class XFTP(val xftpErr: XFTPErrorType): AgentErrorType()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue