From 868f0abaaf8a3c7a62bc9f55ac7279f2e1aa0de2 Mon Sep 17 00:00:00 2001
From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
Date: Thu, 6 Oct 2022 15:02:58 +0100
Subject: [PATCH] ios: connection information/alias sheet (#1178)
* ios: connection information/alias sheet
* add swipe button
* add localizations
* fix padding
* fix intermittent bug with multiple edits
---
.../Chat/Group/AddGroupMembersView.swift | 14 +-
.../Chat/Group/GroupMemberInfoView.swift | 19 +--
.../Views/ChatList/ChatListNavLink.swift | 105 ++++++------
.../ChatList/ContactConnectionInfo.swift | 150 +++++++++++++-----
.../ChatList/ContactConnectionView.swift | 118 +++-----------
.../Shared/Views/NewChat/AddContactView.swift | 4 +-
.../Views/UserSettings/UserAddress.swift | 10 +-
.../de.xcloc/Localized Contents/de.xliff | 22 ++-
.../en.xcloc/Localized Contents/en.xliff | 22 ++-
.../ru.xcloc/Localized Contents/ru.xliff | 22 ++-
apps/ios/SimpleX.xcodeproj/project.pbxproj | 8 +-
apps/ios/SimpleXChat/ChatTypes.swift | 4 +-
apps/ios/de.lproj/Localizable.strings | 14 +-
apps/ios/ru.lproj/Localizable.strings | 14 +-
14 files changed, 305 insertions(+), 221 deletions(-)
diff --git a/apps/ios/Shared/Views/Chat/Group/AddGroupMembersView.swift b/apps/ios/Shared/Views/Chat/Group/AddGroupMembersView.swift
index 0e7d37cf77..5e68e13672 100644
--- a/apps/ios/Shared/Views/Chat/Group/AddGroupMembersView.swift
+++ b/apps/ios/Shared/Views/Chat/Group/AddGroupMembersView.swift
@@ -23,7 +23,7 @@ struct AddGroupMembersView: View {
private enum AddGroupMembersAlert: Identifiable {
case prohibitedToInviteIncognito
- case error(title: LocalizedStringKey, error: String = "")
+ case error(title: LocalizedStringKey, error: LocalizedStringKey = "")
var id: String {
switch self {
@@ -101,7 +101,7 @@ struct AddGroupMembersView: View {
message: Text("You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile")
)
case let .error(title, error):
- return Alert(title: Text(title), message: Text("\(error)"))
+ return Alert(title: Text(title), message: Text(error))
}
}
}
@@ -128,14 +128,8 @@ struct AddGroupMembersView: View {
await MainActor.run { dismiss() }
if let cb = addedMembersCb { cb(selectedContacts) }
} catch {
- switch error as? ChatResponse {
- case .chatCmdError(.errorAgent(.BROKER(.TIMEOUT))):
- alert = .error(title: "Connection timeout", error: NSLocalizedString("Please check your network connection and try again.", comment: "alert message"))
- case .chatCmdError(.errorAgent(.BROKER(.NETWORK))):
- alert = .error(title: "Connection error", error: NSLocalizedString("Please check your network connection and try again.", comment: "alert message"))
- default:
- alert = .error(title: "Error adding member(s)", error: responseError(error))
- }
+ let a = getErrorAlert(error, "Error adding member(s)")
+ alert = .error(title: a.title, error: a.message)
}
}
}
diff --git a/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift b/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift
index 4040cb844b..2dc7554fb0 100644
--- a/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift
+++ b/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift
@@ -22,7 +22,7 @@ struct GroupMemberInfoView: View {
enum GroupMemberInfoViewAlert: Identifiable {
case removeMemberAlert
case changeMemberRoleAlert(role: GroupMemberRole)
- case error(title: LocalizedStringKey, error: String)
+ case error(title: LocalizedStringKey, error: LocalizedStringKey)
var id: String {
switch self {
@@ -176,7 +176,8 @@ struct GroupMemberInfoView: View {
}
} catch let error {
logger.error("apiRemoveMember error: \(responseError(error))")
- alert = errorAlert(error, "Error removing member")
+ let a = getErrorAlert(error, "Error removing member")
+ alert = .error(title: a.title, error: a.message)
}
}
},
@@ -199,7 +200,8 @@ struct GroupMemberInfoView: View {
} catch let error {
newRole = member.memberRole
logger.error("apiMemberRole error: \(responseError(error))")
- alert = errorAlert(error, "Error changing role")
+ let a = getErrorAlert(error, "Error changing role")
+ alert = .error(title: a.title, error: a.message)
}
}
},
@@ -208,17 +210,6 @@ struct GroupMemberInfoView: View {
}
)
}
-
- private func errorAlert(_ error: Error, _ title: LocalizedStringKey) -> GroupMemberInfoViewAlert {
- switch error as? ChatResponse {
- case .chatCmdError(.errorAgent(.BROKER(.TIMEOUT))):
- return .error(title: "Connection timeout", error: NSLocalizedString("Please check your network connection and try again.", comment: "alert message"))
- case .chatCmdError(.errorAgent(.BROKER(.NETWORK))):
- return .error(title: "Connection error", error: NSLocalizedString("Please check your network connection and try again.", comment: "alert message"))
- default:
- return .error(title: title, error: responseError(error))
- }
- }
}
struct GroupMemberInfoView_Previews: PreviewProvider {
diff --git a/apps/ios/Shared/Views/ChatList/ChatListNavLink.swift b/apps/ios/Shared/Views/ChatList/ChatListNavLink.swift
index c4d82252c3..672a279cc6 100644
--- a/apps/ios/Shared/Views/ChatList/ChatListNavLink.swift
+++ b/apps/ios/Shared/Views/ChatList/ChatListNavLink.swift
@@ -30,6 +30,7 @@ struct ChatListNavLink: View {
@State var chat: Chat
@State private var showContactRequestDialog = false
@State private var showJoinGroupDialog = false
+ @State private var showContactConnectionInfo = false
var body: some View {
switch chat.chatInfo {
@@ -199,24 +200,32 @@ struct ChatListNavLink: View {
}
private func contactConnectionNavLink(_ contactConnection: PendingContactConnection) -> some View {
- ContactConnectionView(contactConnection: contactConnection)
+ ContactConnectionView(chat: chat)
.swipeActions(edge: .trailing, allowsFullSwipe: true) {
Button {
- AlertManager.shared.showAlert(deleteContactConnectionAlert(contactConnection))
+ AlertManager.shared.showAlert(deleteContactConnectionAlert(contactConnection) { a in
+ AlertManager.shared.showAlertMsg(title: a.title, message: a.message)
+ })
} label: {
Label("Delete", systemImage: "trash")
}
.tint(.red)
+
+ Button {
+ showContactConnectionInfo = true
+ } label: {
+ Label("Name", systemImage: "pencil")
+ }
+ .tint(.accentColor)
}
.frame(height: rowHeights[dynamicTypeSize])
+ .sheet(isPresented: $showContactConnectionInfo) {
+ if case let .contactConnection(contactConnection) = chat.chatInfo {
+ ContactConnectionInfo(contactConnection: contactConnection)
+ }
+ }
.onTapGesture {
- AlertManager.shared.showAlertMsg(
- title: contactConnection.initiated
- ? "You invited your contact"
- : "You accepted connection",
- // below are the same messages that are shown in alert
- message: contactConnectionText(contactConnection)
- )
+ showContactConnectionInfo = true
}
}
@@ -279,29 +288,6 @@ struct ChatListNavLink: View {
)
}
- private func deleteContactConnectionAlert(_ contactConnection: PendingContactConnection) -> Alert {
- Alert(
- title: Text("Delete pending connection?"),
- message:
- contactConnection.initiated
- ? Text("The contact you shared this link with will NOT be able to connect!")
- : Text("The connection you accepted will be cancelled!"),
- primaryButton: .destructive(Text("Delete")) {
- Task {
- do {
- try await apiDeleteChat(type: .contactConnection, id: contactConnection.apiId)
- DispatchQueue.main.async {
- chatModel.removeChat(contactConnection.id)
- }
- } catch let error {
- logger.error("ChatListNavLink.deleteContactConnectionAlert apiDeleteChat error: \(responseError(error))")
- }
- }
- },
- secondaryButton: .cancel()
- )
- }
-
private func pendingContactAlert(_ chat: Chat, _ contact: Contact) -> Alert {
Alert(
title: Text("Contact is not connected yet!"),
@@ -345,6 +331,32 @@ struct ChatListNavLink: View {
}
}
+func deleteContactConnectionAlert(_ contactConnection: PendingContactConnection, showError: @escaping (ErrorAlert) -> Void, success: @escaping () -> Void = {}) -> Alert {
+ Alert(
+ title: Text("Delete pending connection?"),
+ message:
+ contactConnection.initiated
+ ? Text("The contact you shared this link with will NOT be able to connect!")
+ : Text("The connection you accepted will be cancelled!"),
+ primaryButton: .destructive(Text("Delete")) {
+ Task {
+ do {
+ try await apiDeleteChat(type: .contactConnection, id: contactConnection.apiId)
+ await MainActor.run {
+ ChatModel.shared.removeChat(contactConnection.id)
+ success()
+ }
+ } catch let error {
+ await MainActor.run {
+ showError(getErrorAlert(error, "Error deleting connection"))
+ }
+ }
+ }
+ },
+ secondaryButton: .cancel()
+ )
+}
+
func joinGroup(_ groupId: Int64) {
Task {
logger.debug("joinGroup")
@@ -361,15 +373,8 @@ func joinGroup(_ groupId: Int64) {
await deleteGroup()
}
} catch let error {
- switch error as? ChatResponse {
- case .chatCmdError(.errorAgent(.BROKER(.TIMEOUT))):
- AlertManager.shared.showAlertMsg(title: "Connection timeout", message: "Please check your network connection and try again.")
- case .chatCmdError(.errorAgent(.BROKER(.NETWORK))):
- AlertManager.shared.showAlertMsg(title: "Connection error", message: "Please check your network connection and try again.")
- default:
- logger.error("apiJoinGroup error: \(responseError(error))")
- AlertManager.shared.showAlertMsg(title: "Error joining group", message: "\(responseError(error))")
- }
+ let a = getErrorAlert(error, "Error joining group")
+ AlertManager.shared.showAlertMsg(title: a.title, message: a.message)
}
func deleteGroup() async {
@@ -384,10 +389,20 @@ func joinGroup(_ groupId: Int64) {
}
}
-func contactConnectionText(_ contactConnection: PendingContactConnection) -> LocalizedStringKey {
- contactConnection.viaContactUri
- ? "You will be connected when your connection request is accepted, please wait or check later!"
- : "You will be connected when your contact's device is online, please wait or check later!"
+struct ErrorAlert {
+ var title: LocalizedStringKey
+ var message: LocalizedStringKey
+}
+
+func getErrorAlert(_ error: Error, _ title: LocalizedStringKey) -> ErrorAlert {
+ switch error as? ChatResponse {
+ case .chatCmdError(.errorAgent(.BROKER(.TIMEOUT))):
+ return ErrorAlert(title: "Connection timeout", message: "Please check your network connection and try again.")
+ case .chatCmdError(.errorAgent(.BROKER(.NETWORK))):
+ return ErrorAlert(title: "Connection error", message: "Please check your network connection and try again.")
+ default:
+ return ErrorAlert(title: title, message: "Error: \(responseError(error))")
+ }
}
struct ChatListNavLink_Previews: PreviewProvider {
diff --git a/apps/ios/Shared/Views/ChatList/ContactConnectionInfo.swift b/apps/ios/Shared/Views/ChatList/ContactConnectionInfo.swift
index 3b7b899bf6..8a6e2141df 100644
--- a/apps/ios/Shared/Views/ChatList/ContactConnectionInfo.swift
+++ b/apps/ios/Shared/Views/ChatList/ContactConnectionInfo.swift
@@ -2,7 +2,7 @@
// ContactConnectionInfo.swift
// SimpleX (iOS)
//
-// Created by Evgeny on 30/09/2022.
+// Created by Evgeny on 06/10/2022.
// Copyright © 2022 SimpleX Chat. All rights reserved.
//
@@ -11,54 +11,128 @@ import SimpleXChat
struct ContactConnectionInfo: View {
@EnvironmentObject var m: ChatModel
- var contactConnection: PendingContactConnection
- var connReqInvitation: String
+ @Environment(\.dismiss) var dismiss: DismissAction
+ @State var contactConnection: PendingContactConnection
+ @State private var alert: CCInfoAlert?
+ @State private var showQRCodeView = false
+ @State private var localAlias = ""
+ @FocusState private var aliasTextFieldFocused: Bool
+
+ enum CCInfoAlert: Identifiable {
+ case deleteInvitationAlert
+ case error(title: LocalizedStringKey, error: LocalizedStringKey)
+
+ var id: String {
+ switch self {
+ case .deleteInvitationAlert: return "deleteInvitationAlert"
+ case let .error(title, _): return "error \(title)"
+ }
+ }
+ }
var body: some View {
- ScrollView {
- VStack(alignment: .leading) {
- Text("Shared one-time link")
- .font(.largeTitle)
- .bold()
- .padding(.vertical)
+ NavigationView {
+ List {
+ Group {
+ Text(contactConnection.initiated ? "You invited your contact" : "You accepted connection")
+ .font(.largeTitle)
+ .bold()
+ .padding(.bottom, 16)
- HStack {
- if contactConnection.incognito {
- Image(systemName: "theatermasks").foregroundColor(.indigo).font(.footnote)
- Spacer().frame(width: 8)
- Text("A random profile will be sent to your contact").font(.footnote)
- } else {
- Image(systemName: "info.circle").foregroundColor(.secondary).font(.footnote)
- Spacer().frame(width: 8)
- Text("Your chat profile will be sent to your contact").font(.footnote)
+ Text(contactConnectionText(contactConnection))
+ }
+ .listRowBackground(Color.clear)
+ .listRowSeparator(.hidden)
+ .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
+ .onTapGesture { aliasTextFieldFocused = false }
+
+ Section {
+ HStack(spacing: 20) {
+ Image(systemName: "pencil")
+ .foregroundColor(.secondary)
+ .padding(.leading, 6)
+ .onTapGesture { aliasTextFieldFocused = true }
+ TextField("Set contact name…", text: $localAlias)
+ .autocapitalization(.none)
+ .autocorrectionDisabled(true)
+ .focused($aliasTextFieldFocused)
+ .submitLabel(.done)
+ .onSubmit(setConnectionAlias)
+ }
+
+ if contactConnection.initiated && contactConnection.connReqInv != nil {
+ Button {
+ showQRCodeView = true
+ } label: {
+ Label("Show QR code", systemImage: "qrcode")
+ .foregroundColor(contactConnection.incognito ? .indigo : .accentColor)
+ }
+ }
+
+ Button(role: .destructive) {
+ alert = .deleteInvitationAlert
+ } label: {
+ Label("Delete connection", systemImage: "trash")
+ .foregroundColor(Color.red)
}
}
-
- Text(contactConnectionText(contactConnection))
- .padding(.top, 4)
- .padding(.bottom, 8)
-
- QRCode(uri: connReqInvitation).padding(.bottom)
-
- Text("If you can't meet in person, **show QR code in the video call**, or share the link.")
- .padding(.bottom)
- Button {
- showShareSheet(items: [connReqInvitation])
- } label: {
- Label("Share invitation link", systemImage: "square.and.arrow.up")
- }
- .frame(maxWidth: .infinity, alignment: .center)
}
- .padding()
- .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
- .onAppear { m.connReqInv = connReqInvitation }
- .onDisappear { m.connReqInv = nil }
+ .listStyle(.insetGrouped)
}
+ .sheet(isPresented: $showQRCodeView) {
+ if let connReqInv = contactConnection.connReqInv {
+ AddContactView(contactConnection: contactConnection, connReqInvitation: connReqInv)
+ }
+ }
+ .alert(item: $alert) { _alert in
+ switch _alert {
+ case .deleteInvitationAlert:
+ return deleteContactConnectionAlert(contactConnection) { a in
+ alert = .error(title: a.title, error: a.message)
+ } success: {
+ dismiss()
+ }
+ case let .error(title, error): return Alert(title: Text(title), message: Text(error))
+ }
+ }
+ .onAppear {
+ localAlias = contactConnection.localAlias
+ aliasTextFieldFocused = true
+ }
+ }
+
+ private func setConnectionAlias() {
+ if localAlias == contactConnection.localAlias {
+ aliasTextFieldFocused = false
+ return
+ }
+ Task {
+ let prevAlias = contactConnection.localAlias
+ contactConnection.localAlias = localAlias
+ do {
+ if let conn = try await apiSetConnectionAlias(connId: contactConnection.pccConnId, localAlias: localAlias) {
+ await MainActor.run {
+ contactConnection = conn
+ ChatModel.shared.updateContactConnection(conn)
+ dismiss()
+ }
+ }
+ } catch {
+ logger.error("setContactAlias error: \(responseError(error))")
+ contactConnection.localAlias = prevAlias
+ }
+ }
+ }
+
+ private func contactConnectionText(_ contactConnection: PendingContactConnection) -> LocalizedStringKey {
+ contactConnection.viaContactUri
+ ? "You will be connected when your connection request is accepted, please wait or check later!"
+ : "You will be connected when your contact's device is online, please wait or check later!"
}
}
struct ContactConnectionInfo_Previews: PreviewProvider {
static var previews: some View {
- ContactConnectionInfo(contactConnection: PendingContactConnection.getSampleData(), connReqInvitation: "")
+ ContactConnectionInfo(contactConnection: PendingContactConnection.getSampleData())
}
}
diff --git a/apps/ios/Shared/Views/ChatList/ContactConnectionView.swift b/apps/ios/Shared/Views/ChatList/ContactConnectionView.swift
index 59d8c5f401..a49789aeaa 100644
--- a/apps/ios/Shared/Views/ChatList/ContactConnectionView.swift
+++ b/apps/ios/Shared/Views/ChatList/ContactConnectionView.swift
@@ -11,80 +11,41 @@ import SimpleXChat
struct ContactConnectionView: View {
@EnvironmentObject var m: ChatModel
- @State var contactConnection: PendingContactConnection
- @State private var editLocalAlias = false
+ @ObservedObject var chat: Chat
@State private var localAlias = ""
@FocusState private var aliasTextFieldFocused: Bool
@State private var showContactConnectionInfo = false
var body: some View {
+ if case let .contactConnection(conn) = chat.chatInfo {
+ contactConnectionView(conn)
+ }
+ }
+
+ func contactConnectionView(_ contactConnection: PendingContactConnection) -> some View {
HStack(spacing: 8) {
Group {
- if contactConnection.initiated {
- let v = Image(systemName: "qrcode")
- .resizable()
- .scaledToFill()
- .frame(width: 40, height: 40)
- if contactConnection.connReqInv == nil {
- v.foregroundColor(Color(uiColor: .secondarySystemBackground))
- } else {
- v.foregroundColor(contactConnection.incognito ? .indigo : .accentColor)
- .onTapGesture { showContactConnectionInfo = true }
- }
- } else {
- Image(systemName: "link")
- .resizable()
- .scaledToFill()
- .frame(width: 48, height: 48)
- .foregroundColor(Color(uiColor: .secondarySystemBackground))
- }
+ Image(systemName: contactConnection.initiated ? "link.badge.plus" : "link")
+ .resizable()
+ .scaledToFill()
+ .frame(width: 48, height: 48)
+ .foregroundColor(Color(uiColor: .secondarySystemBackground))
+ .onTapGesture { showContactConnectionInfo = true }
}
.frame(width: 63, height: 63)
.padding(.leading, 4)
VStack(alignment: .leading, spacing: 0) {
HStack(alignment: .top) {
- Image(systemName: "pencil")
- .resizable()
- .scaledToFill()
- .frame(width: 16, height: 16)
+ Text(contactConnection.chatViewName)
+ .font(.title3)
+ .bold()
+ .allowsTightening(false)
.foregroundColor(.secondary)
- .padding(.leading, 8)
- .padding(.top, 8)
- .onTapGesture(perform: enableEditing)
-
- if editLocalAlias {
- let v = TextField("Set contact name…", text: $localAlias)
- .font(.title3)
- .disableAutocorrection(true)
- .focused($aliasTextFieldFocused)
- .submitLabel(.done)
- .onSubmit(setConnectionAlias)
- .foregroundColor(.secondary)
- .padding(.trailing, 8)
- .onTapGesture {}
- .onChange(of: aliasTextFieldFocused) { focussed in
- if !focussed {
- editLocalAlias = false
- }
- }
- if #available(iOS 16.0, *) {
- v.bold()
- } else {
- v
- }
- } else {
- Text(contactConnection.chatViewName)
- .font(.title3)
- .bold()
- .allowsTightening(false)
- .foregroundColor(.secondary)
- .padding(.trailing, 8)
- .padding(.top, 1)
- .padding(.bottom, 0.5)
- .frame(alignment: .topLeading)
- .onTapGesture(perform: enableEditing)
- }
+ .padding(.horizontal, 8)
+ .padding(.top, 1)
+ .padding(.bottom, 0.5)
+ .frame(alignment: .topLeading)
Spacer()
@@ -106,40 +67,7 @@ struct ContactConnectionView: View {
}
.frame(maxHeight: .infinity)
.sheet(isPresented: $showContactConnectionInfo) {
- if let connReqInv = contactConnection.connReqInv {
- ContactConnectionInfo(contactConnection: contactConnection, connReqInvitation: connReqInv)
- }
- }
- }
- }
-
- private func enableEditing() {
- editLocalAlias = true
- aliasTextFieldFocused = true
- localAlias = contactConnection.localAlias
- }
-
- private func setConnectionAlias() {
- if localAlias == contactConnection.localAlias {
- aliasTextFieldFocused = false
- editLocalAlias = false
- return
- }
- Task {
- let prevAlias = contactConnection.localAlias
- contactConnection.localAlias = localAlias
- do {
- if let conn = try await apiSetConnectionAlias(connId: contactConnection.pccConnId, localAlias: localAlias) {
- await MainActor.run {
- contactConnection = conn
- ChatModel.shared.updateContactConnection(conn)
- aliasTextFieldFocused = false
- editLocalAlias = false
- }
- }
- } catch {
- logger.error("setContactAlias error: \(responseError(error))")
- contactConnection.localAlias = prevAlias
+ ContactConnectionInfo(contactConnection: contactConnection)
}
}
}
@@ -147,7 +75,7 @@ struct ContactConnectionView: View {
struct ContactConnectionView_Previews: PreviewProvider {
static var previews: some View {
- ContactConnectionView(contactConnection: PendingContactConnection.getSampleData())
+ ContactConnectionView(chat: Chat(chatInfo: ChatInfo.sampleData.contactConnection))
.previewLayout(.fixed(width: 360, height: 80))
}
}
diff --git a/apps/ios/Shared/Views/NewChat/AddContactView.swift b/apps/ios/Shared/Views/NewChat/AddContactView.swift
index 031e1d9114..d6a1c128a7 100644
--- a/apps/ios/Shared/Views/NewChat/AddContactView.swift
+++ b/apps/ios/Shared/Views/NewChat/AddContactView.swift
@@ -8,9 +8,11 @@
import SwiftUI
import CoreImage.CIFilterBuiltins
+import SimpleXChat
struct AddContactView: View {
@EnvironmentObject private var chatModel: ChatModel
+ var contactConnection: PendingContactConnection? = nil
var connReqInvitation: String
var viaSettings = false
@@ -23,7 +25,7 @@ struct AddContactView: View {
.padding(viaSettings ? .bottom : .vertical)
Text("Your contact can scan it from the app.")
.padding(.bottom, 4)
- if (chatModel.incognito) {
+ if (contactConnection?.incognito ?? chatModel.incognito) {
HStack {
Image(systemName: "theatermasks").foregroundColor(.indigo).font(.footnote)
Spacer().frame(width: 8)
diff --git a/apps/ios/Shared/Views/UserSettings/UserAddress.swift b/apps/ios/Shared/Views/UserSettings/UserAddress.swift
index a522553111..89b8a93b01 100644
--- a/apps/ios/Shared/Views/UserSettings/UserAddress.swift
+++ b/apps/ios/Shared/Views/UserSettings/UserAddress.swift
@@ -61,14 +61,8 @@ struct UserAddress: View {
}
} catch let error {
logger.error("UserAddress apiCreateUserAddress: \(error.localizedDescription)")
- switch error as? ChatResponse {
- case .chatCmdError(.errorAgent(.BROKER(.TIMEOUT))):
- alert = .error(title: "Connection timeout", error: "Please check your network connection and try again.")
- case .chatCmdError(.errorAgent(.BROKER(.NETWORK))):
- alert = .error(title: "Connection error", error: "Please check your network connection and try again.")
- default:
- alert = .error(title: "Error creating address", error: "Error: \(responseError(error))")
- }
+ let a = getErrorAlert(error, "Error creating address")
+ alert = .error(title: a.title, error: "\(a.message)")
}
}
} label: { Label("Create address", systemImage: "qrcode") }
diff --git a/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff b/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff
index 32f5766596..608ce90185 100644
--- a/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff
+++ b/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff
@@ -746,6 +746,11 @@
Chat-Profil löschen?
No comment provided by engineer.
+
+ Delete connection
+ *** Delete connection
+ No comment provided by engineer.
+
Delete contact
Kontakt löschen
@@ -1021,6 +1026,11 @@
Fehler beim Löschen des Chats!
No comment provided by engineer.
+
+ Error deleting connection
+ *** Error deleting connection
+ No comment provided by engineer.
+
Error deleting database
Fehler beim Löschen der Datenbank
@@ -1573,6 +1583,11 @@ Wir werden Serverredundanzen hinzufügen, um verloren gegangene Nachrichten zu v
Stummschalten
No comment provided by engineer.
+
+ Name
+ *** Name
+ No comment provided by engineer.
+
Network & servers
Netzwerk & Server
@@ -1766,7 +1781,7 @@ Wir werden Serverredundanzen hinzufügen, um verloren gegangene Nachrichten zu v
Please check your network connection and try again.
Bitte überprüfen Sie Ihre Netzwerkverbindung und versuchen Sie es erneut.
- alert message
+ No comment provided by engineer.
Please enter correct current passphrase.
@@ -2103,6 +2118,11 @@ Wir werden Serverredundanzen hinzufügen, um verloren gegangene Nachrichten zu v
*** Shared one-time link
No comment provided by engineer.
+
+ Show QR code
+ *** Show QR code
+ No comment provided by engineer.
+
Show preview
Vorschau anzeigen
diff --git a/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff b/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff
index 45d0a0807e..6864c9435f 100644
--- a/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff
+++ b/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff
@@ -746,6 +746,11 @@
Delete chat profile?
No comment provided by engineer.
+
+ Delete connection
+ Delete connection
+ No comment provided by engineer.
+
Delete contact
Delete contact
@@ -1021,6 +1026,11 @@
Error deleting chat!
No comment provided by engineer.
+
+ Error deleting connection
+ Error deleting connection
+ No comment provided by engineer.
+
Error deleting database
Error deleting database
@@ -1573,6 +1583,11 @@ We will be adding server redundancy to prevent lost messages.
Mute
No comment provided by engineer.
+
+ Name
+ Name
+ No comment provided by engineer.
+
Network & servers
Network & servers
@@ -1766,7 +1781,7 @@ We will be adding server redundancy to prevent lost messages.
Please check your network connection and try again.
Please check your network connection and try again.
- alert message
+ No comment provided by engineer.
Please enter correct current passphrase.
@@ -2103,6 +2118,11 @@ We will be adding server redundancy to prevent lost messages.
Shared one-time link
No comment provided by engineer.
+
+ Show QR code
+ Show QR code
+ No comment provided by engineer.
+
Show preview
Show preview
diff --git a/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff b/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff
index 3dd48e40d1..bb7ab7a06e 100644
--- a/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff
+++ b/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff
@@ -746,6 +746,11 @@
Удалить профиль?
No comment provided by engineer.
+
+ Delete connection
+ Удалить соединение
+ No comment provided by engineer.
+
Delete contact
Удалить контакт
@@ -1021,6 +1026,11 @@
Ошибка при удалении чата!
No comment provided by engineer.
+
+ Error deleting connection
+ Ошибка при удалении соединения
+ No comment provided by engineer.
+
Error deleting database
Ошибка при удалении данных чата
@@ -1573,6 +1583,11 @@ We will be adding server redundancy to prevent lost messages.
Без звука
No comment provided by engineer.
+
+ Name
+ Имя
+ No comment provided by engineer.
+
Network & servers
Сеть & серверы
@@ -1766,7 +1781,7 @@ We will be adding server redundancy to prevent lost messages.
Please check your network connection and try again.
Пожалуйста, проверьте ваше соединение с сетью и попробуйте еще раз.
- alert message
+ No comment provided by engineer.
Please enter correct current passphrase.
@@ -2103,6 +2118,11 @@ We will be adding server redundancy to prevent lost messages.
Одноразовая ссылка-приглашение
No comment provided by engineer.
+
+ Show QR code
+ Показать QR код
+ No comment provided by engineer.
+
Show preview
Показывать уведомления
diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj
index 011fa6a75c..48175c85ff 100644
--- a/apps/ios/SimpleX.xcodeproj/project.pbxproj
+++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj
@@ -18,6 +18,7 @@
5C029EAA283942EA004A9677 /* CallController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C029EA9283942EA004A9677 /* CallController.swift */; };
5C05DF532840AA1D00C683F9 /* CallSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C05DF522840AA1D00C683F9 /* CallSettings.swift */; };
5C063D2727A4564100AEC577 /* ChatPreviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C063D2627A4564100AEC577 /* ChatPreviewView.swift */; };
+ 5C10D88828EED12E00E58BF0 /* ContactConnectionInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C10D88728EED12E00E58BF0 /* ContactConnectionInfo.swift */; };
5C116CDC27AABE0400E66D01 /* ContactRequestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C116CDB27AABE0400E66D01 /* ContactRequestView.swift */; };
5C13730B28156D2700F43030 /* ContactConnectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C13730A28156D2700F43030 /* ContactConnectionView.swift */; };
5C1A4C1E27A715B700EAD5AD /* ChatItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C1A4C1D27A715B700EAD5AD /* ChatItemView.swift */; };
@@ -90,7 +91,6 @@
5CCD403427A5F6DF00368C90 /* AddContactView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCD403327A5F6DF00368C90 /* AddContactView.swift */; };
5CCD403727A5F9A200368C90 /* ScanToConnectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCD403627A5F9A200368C90 /* ScanToConnectView.swift */; };
5CDCAD482818589900503DA2 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CDCAD472818589900503DA2 /* NotificationService.swift */; };
- 5CE1331028E7391000FFFD8C /* ContactConnectionInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CE1330F28E7391000FFFD8C /* ContactConnectionInfo.swift */; };
5CE2BA702845308900EC33A6 /* SimpleXChat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE2BA682845308900EC33A6 /* SimpleXChat.framework */; };
5CE2BA712845308900EC33A6 /* SimpleXChat.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE2BA682845308900EC33A6 /* SimpleXChat.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
5CE2BA77284530BF00EC33A6 /* SimpleXChat.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CE2BA76284530BF00EC33A6 /* SimpleXChat.h */; };
@@ -208,6 +208,7 @@
5C029EA9283942EA004A9677 /* CallController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallController.swift; sourceTree = ""; };
5C05DF522840AA1D00C683F9 /* CallSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallSettings.swift; sourceTree = ""; };
5C063D2627A4564100AEC577 /* ChatPreviewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatPreviewView.swift; sourceTree = ""; };
+ 5C10D88728EED12E00E58BF0 /* ContactConnectionInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactConnectionInfo.swift; sourceTree = ""; };
5C116CDB27AABE0400E66D01 /* ContactRequestView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactRequestView.swift; sourceTree = ""; };
5C13730A28156D2700F43030 /* ContactConnectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactConnectionView.swift; sourceTree = ""; };
5C13730C2815740A00F43030 /* DebugJSON.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = DebugJSON.playground; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
@@ -300,7 +301,6 @@
5CDCAD80281A7E2700503DA2 /* Notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notifications.swift; sourceTree = ""; };
5CE1330328E118CC00FFFD8C /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = "de.lproj/SimpleX--iOS--InfoPlist.strings"; sourceTree = ""; };
5CE1330428E118CC00FFFD8C /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = ""; };
- 5CE1330F28E7391000FFFD8C /* ContactConnectionInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactConnectionInfo.swift; sourceTree = ""; };
5CE2BA682845308900EC33A6 /* SimpleXChat.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SimpleXChat.framework; sourceTree = BUILT_PRODUCTS_DIR; };
5CE2BA76284530BF00EC33A6 /* SimpleXChat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleXChat.h; sourceTree = ""; };
5CE2BA78284530CC00EC33A6 /* SimpleXChat.docc */ = {isa = PBXFileReference; lastKnownFileType = folder.documentationcatalog; path = SimpleXChat.docc; sourceTree = ""; };
@@ -588,7 +588,7 @@
5C063D2627A4564100AEC577 /* ChatPreviewView.swift */,
5C116CDB27AABE0400E66D01 /* ContactRequestView.swift */,
5C13730A28156D2700F43030 /* ContactConnectionView.swift */,
- 5CE1330F28E7391000FFFD8C /* ContactConnectionInfo.swift */,
+ 5C10D88728EED12E00E58BF0 /* ContactConnectionInfo.swift */,
);
path = ChatList;
sourceTree = "";
@@ -891,6 +891,7 @@
648010AB281ADD15009009B9 /* CIFileView.swift in Sources */,
5C4B3B0A285FB130003915F2 /* DatabaseView.swift in Sources */,
5CB2084F28DA4B4800D024EC /* RTCServers.swift in Sources */,
+ 5C10D88828EED12E00E58BF0 /* ContactConnectionInfo.swift in Sources */,
3CDBCF4227FAE51000354CDD /* ComposeLinkView.swift in Sources */,
3CDBCF4827FF621E00354CDD /* CILinkView.swift in Sources */,
5C7505A827B6D34800BE3227 /* ChatInfoToolbar.swift in Sources */,
@@ -908,7 +909,6 @@
5CB0BA8E2827126500B3292C /* OnboardingView.swift in Sources */,
6442E0BE2880182D00CEC0F9 /* GroupChatInfoView.swift in Sources */,
5C2E261227A30FEA00F70299 /* TerminalView.swift in Sources */,
- 5CE1331028E7391000FFFD8C /* ContactConnectionInfo.swift in Sources */,
5CB2085128DB64CA00D024EC /* CreateLinkView.swift in Sources */,
5C9FD96E27A5D6ED0075386C /* SendMessageView.swift in Sources */,
64E972072881BB22008DBC02 /* CIGroupInvitationView.swift in Sources */,
diff --git a/apps/ios/SimpleXChat/ChatTypes.swift b/apps/ios/SimpleXChat/ChatTypes.swift
index 5f758adccb..58c4fc6f2f 100644
--- a/apps/ios/SimpleXChat/ChatTypes.swift
+++ b/apps/ios/SimpleXChat/ChatTypes.swift
@@ -283,12 +283,14 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat {
public var direct: ChatInfo
public var group: ChatInfo
public var contactRequest: ChatInfo
+ public var contactConnection: ChatInfo
}
public static var sampleData: ChatInfo.SampleData = SampleData(
direct: ChatInfo.direct(contact: Contact.sampleData),
group: ChatInfo.group(groupInfo: GroupInfo.sampleData),
- contactRequest: ChatInfo.contactRequest(contactRequest: UserContactRequest.sampleData)
+ contactRequest: ChatInfo.contactRequest(contactRequest: UserContactRequest.sampleData),
+ contactConnection: ChatInfo.contactConnection(contactConnection: PendingContactConnection.getSampleData())
)
}
diff --git a/apps/ios/de.lproj/Localizable.strings b/apps/ios/de.lproj/Localizable.strings
index 2d7c2776e5..e7b35f5d99 100644
--- a/apps/ios/de.lproj/Localizable.strings
+++ b/apps/ios/de.lproj/Localizable.strings
@@ -524,6 +524,9 @@
/* No comment provided by engineer. */
"Delete chat profile?" = "Chat-Profil löschen?";
+/* No comment provided by engineer. */
+"Delete connection" = "*** Delete connection";
+
/* No comment provided by engineer. */
"Delete contact" = "Kontakt löschen";
@@ -716,6 +719,9 @@
/* No comment provided by engineer. */
"Error deleting chat!" = "Fehler beim Löschen des Chats!";
+/* No comment provided by engineer. */
+"Error deleting connection" = "*** Error deleting connection";
+
/* No comment provided by engineer. */
"Error deleting database" = "Fehler beim Löschen der Datenbank";
@@ -1098,6 +1104,9 @@
/* No comment provided by engineer. */
"Mute" = "Stummschalten";
+/* No comment provided by engineer. */
+"Name" = "*** Name";
+
/* No comment provided by engineer. */
"Network & servers" = "Netzwerk & Server";
@@ -1230,7 +1239,7 @@
/* No comment provided by engineer. */
"Please check that you used the correct link or ask your contact to send you another one." = "Überprüfen Sie bitte, ob Sie den richtigen Link genutzt haben oder bitten Sie Ihren Kontakt nochmal darum, Ihnen einen Link zuzusenden.";
-/* alert message */
+/* No comment provided by engineer. */
"Please check your network connection and try again." = "Bitte überprüfen Sie Ihre Netzwerkverbindung und versuchen Sie es erneut.";
/* No comment provided by engineer. */
@@ -1455,6 +1464,9 @@
/* No comment provided by engineer. */
"Show preview" = "Vorschau anzeigen";
+/* No comment provided by engineer. */
+"Show QR code" = "*** Show QR code";
+
/* notification */
"SimpleX encrypted message or connection event" = "SimpleX verschlüsselte Nachricht oder Verbindungs-Ereignis";
diff --git a/apps/ios/ru.lproj/Localizable.strings b/apps/ios/ru.lproj/Localizable.strings
index 6bae21eea9..cfac100095 100644
--- a/apps/ios/ru.lproj/Localizable.strings
+++ b/apps/ios/ru.lproj/Localizable.strings
@@ -524,6 +524,9 @@
/* No comment provided by engineer. */
"Delete chat profile?" = "Удалить профиль?";
+/* No comment provided by engineer. */
+"Delete connection" = "Удалить соединение";
+
/* No comment provided by engineer. */
"Delete contact" = "Удалить контакт";
@@ -716,6 +719,9 @@
/* No comment provided by engineer. */
"Error deleting chat!" = "Ошибка при удалении чата!";
+/* No comment provided by engineer. */
+"Error deleting connection" = "Ошибка при удалении соединения";
+
/* No comment provided by engineer. */
"Error deleting database" = "Ошибка при удалении данных чата";
@@ -1098,6 +1104,9 @@
/* No comment provided by engineer. */
"Mute" = "Без звука";
+/* No comment provided by engineer. */
+"Name" = "Имя";
+
/* No comment provided by engineer. */
"Network & servers" = "Сеть & серверы";
@@ -1230,7 +1239,7 @@
/* No comment provided by engineer. */
"Please check that you used the correct link or ask your contact to send you another one." = "Пожалуйста, проверьте, что вы использовали правильную ссылку или попросите, чтобы ваш контакт отправил вам другую ссылку.";
-/* alert message */
+/* No comment provided by engineer. */
"Please check your network connection and try again." = "Пожалуйста, проверьте ваше соединение с сетью и попробуйте еще раз.";
/* No comment provided by engineer. */
@@ -1455,6 +1464,9 @@
/* No comment provided by engineer. */
"Show preview" = "Показывать уведомления";
+/* No comment provided by engineer. */
+"Show QR code" = "Показать QR код";
+
/* notification */
"SimpleX encrypted message or connection event" = "SimpleX: зашифрованное сообщение или соединение контакта";