diff --git a/apps/ios/Shared/Model/SimpleXAPI.swift b/apps/ios/Shared/Model/SimpleXAPI.swift index bb01b631b5..80fe35e94a 100644 --- a/apps/ios/Shared/Model/SimpleXAPI.swift +++ b/apps/ios/Shared/Model/SimpleXAPI.swift @@ -580,15 +580,15 @@ func apiVerifyGroupMember(_ groupId: Int64, _ groupMemberId: Int64, connectionCo return nil } -func apiAddContact(incognito: Bool) async -> (String, PendingContactConnection)? { +func apiAddContact(incognito: Bool) async -> ((String, PendingContactConnection)?, Alert?) { guard let userId = ChatModel.shared.currentUser?.userId else { logger.error("apiAddContact: no current user") - return nil + return (nil, nil) } let r = await chatSendCmd(.apiAddContact(userId: userId, incognito: incognito), bgTask: false) - if case let .invitation(_, connReqInvitation, connection) = r { return (connReqInvitation, connection) } - AlertManager.shared.showAlert(connectionErrorAlert(r)) - return nil + if case let .invitation(_, connReqInvitation, connection) = r { return ((connReqInvitation, connection), nil) } + let alert = connectionErrorAlert(r) + return (nil, alert) } func apiSetConnectionIncognito(connId: Int64, incognito: Bool) async throws -> PendingContactConnection? { diff --git a/apps/ios/Shared/Views/ChatList/ChatHelp.swift b/apps/ios/Shared/Views/ChatList/ChatHelp.swift index 7741512432..0001d609c6 100644 --- a/apps/ios/Shared/Views/ChatList/ChatHelp.swift +++ b/apps/ios/Shared/Views/ChatList/ChatHelp.swift @@ -11,7 +11,7 @@ import SwiftUI struct ChatHelp: View { @EnvironmentObject var chatModel: ChatModel @Binding var showSettings: Bool - @State private var showAddChat = false + @State private var showNewChatSheet = false var body: some View { ScrollView { chatHelp() } @@ -39,7 +39,7 @@ struct ChatHelp: View { HStack(spacing: 8) { Text("Tap button ") - NewChatButton(showAddChat: $showAddChat) + NewChatSheetButton(showNewChatSheet: $showNewChatSheet) Text("above, then choose:") } diff --git a/apps/ios/Shared/Views/ChatList/ChatListView.swift b/apps/ios/Shared/Views/ChatList/ChatListView.swift index 00e4874d85..b536b5eb68 100644 --- a/apps/ios/Shared/Views/ChatList/ChatListView.swift +++ b/apps/ios/Shared/Views/ChatList/ChatListView.swift @@ -13,7 +13,7 @@ struct ChatListView: View { @EnvironmentObject var chatModel: ChatModel @Binding var showSettings: Bool @State private var searchText = "" - @State private var showAddChat = false + @State private var showNewChatSheet = false @State private var userPickerVisible = false @State private var showConnectDesktop = false @State private var showCreateGroupSheet = false @@ -125,11 +125,10 @@ struct ChatListView: View { } ToolbarItem(placement: .navigationBarTrailing) { switch chatModel.chatRunning { - // case .some(true): NewChatButton(showAddChat: $showAddChat) case .some(true): HStack { createGroupButton() - NewChatButton2() + NewChatSheetButton(showNewChatSheet: $showNewChatSheet) } case .some(false): chatStoppedIcon() case .none: EmptyView() @@ -207,7 +206,7 @@ struct ChatListView: View { .padding(.trailing, 12) connectButton("Tap to start a new chat") { - showAddChat = true + showNewChatSheet = true } Spacer() diff --git a/apps/ios/Shared/Views/NewChat/AddContactLearnMore.swift b/apps/ios/Shared/Views/NewChat/AddContactLearnMore.swift index 182149cbde..45eb783326 100644 --- a/apps/ios/Shared/Views/NewChat/AddContactLearnMore.swift +++ b/apps/ios/Shared/Views/NewChat/AddContactLearnMore.swift @@ -9,8 +9,20 @@ import SwiftUI struct AddContactLearnMore: View { + var showTitle: Bool + var body: some View { List { + if showTitle { + Text("One-time invitation link") + .font(.largeTitle) + .bold() + .fixedSize(horizontal: false, vertical: true) + .padding(.vertical) + .listRowBackground(Color.clear) + .listRowSeparator(.hidden) + .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) + } VStack(alignment: .leading, spacing: 18) { Text("To connect, your contact can scan QR code or use the link in the app.") Text("If you can't meet in person, show QR code in a video call, or share the link.") @@ -23,6 +35,6 @@ struct AddContactLearnMore: View { struct AddContactLearnMore_Previews: PreviewProvider { static var previews: some View { - AddContactLearnMore() + AddContactLearnMore(showTitle: true) } } diff --git a/apps/ios/Shared/Views/NewChat/AddContactView.swift b/apps/ios/Shared/Views/NewChat/AddContactView.swift index de8e35d2a6..a48d91b922 100644 --- a/apps/ios/Shared/Views/NewChat/AddContactView.swift +++ b/apps/ios/Shared/Views/NewChat/AddContactView.swift @@ -109,7 +109,7 @@ func shareLinkButton(_ connReqInvitation: String) -> some View { func oneTimeLinkLearnMoreButton() -> some View { NavigationLink { - AddContactLearnMore() + AddContactLearnMore(showTitle: false) .navigationTitle("One-time invitation link") .navigationBarTitleDisplayMode(.large) } label: { diff --git a/apps/ios/Shared/Views/NewChat/CreateLinkView.swift b/apps/ios/Shared/Views/NewChat/CreateLinkView.swift index 0b9cfe7a17..d488277b8f 100644 --- a/apps/ios/Shared/Views/NewChat/CreateLinkView.swift +++ b/apps/ios/Shared/Views/NewChat/CreateLinkView.swift @@ -71,7 +71,8 @@ struct CreateLinkView: View { private func createInvitation() { creatingConnReq = true Task { - if let (connReq, pcc) = await apiAddContact(incognito: incognitoGroupDefault.get()) { + let (r, _) = await apiAddContact(incognito: incognitoGroupDefault.get()) + if let (connReq, pcc) = r { await MainActor.run { connReqInvitation = connReq contactConnection = pcc diff --git a/apps/ios/Shared/Views/NewChat/NewChatButton.swift b/apps/ios/Shared/Views/NewChat/NewChatButton.swift index 637c010328..87c2135529 100644 --- a/apps/ios/Shared/Views/NewChat/NewChatButton.swift +++ b/apps/ios/Shared/Views/NewChat/NewChatButton.swift @@ -51,7 +51,8 @@ struct NewChatButton: View { func addContactAction() { Task { - if let (connReq, pcc) = await apiAddContact(incognito: incognitoGroupDefault.get()) { + let (r, _) = await apiAddContact(incognito: incognitoGroupDefault.get()) + if let (connReq, pcc) = r { actionSheet = .createLink(link: connReq, connection: pcc) } } diff --git a/apps/ios/Shared/Views/NewChat/NewChatButton2.swift b/apps/ios/Shared/Views/NewChat/NewChatButton2.swift deleted file mode 100644 index 3fde4c8e3f..0000000000 --- a/apps/ios/Shared/Views/NewChat/NewChatButton2.swift +++ /dev/null @@ -1,53 +0,0 @@ -// -// NewChatButton2.swift -// SimpleX (iOS) -// -// Created by spaced4ndy on 28.11.2023. -// Copyright © 2023 SimpleX Chat. All rights reserved. -// - -import SwiftUI -import SimpleXChat - -enum NewChatSheet: Identifiable { - case newChat(link: String, connection: PendingContactConnection) - - var id: String { - switch self { - case let .newChat(link, _): return "newChat \(link)" - } - } -} - -struct NewChatButton2: View { - @State private var actionSheet: NewChatSheet? - - var body: some View { - Button { - addContactAction() - } label: { - Image(systemName: "square.and.pencil") - .resizable() - .scaledToFit() - .frame(width: 24, height: 24) - } - .sheet(item: $actionSheet) { sheet in - switch sheet { - case let .newChat(link, pcc): - NewChatView(selection: .invite, connReqInvitation: link, contactConnection: pcc) - } - } - } - - func addContactAction() { - Task { - if let (connReq, pcc) = await apiAddContact(incognito: incognitoGroupDefault.get()) { - actionSheet = .newChat(link: connReq, connection: pcc) - } - } - } -} - -//#Preview { -// NewChatButton2() -//} diff --git a/apps/ios/Shared/Views/NewChat/NewChatSheetButton.swift b/apps/ios/Shared/Views/NewChat/NewChatSheetButton.swift new file mode 100644 index 0000000000..201326abc1 --- /dev/null +++ b/apps/ios/Shared/Views/NewChat/NewChatSheetButton.swift @@ -0,0 +1,32 @@ +// +// NewChatSheetButton.swift +// SimpleX (iOS) +// +// Created by spaced4ndy on 28.11.2023. +// Copyright © 2023 SimpleX Chat. All rights reserved. +// + +import SwiftUI +import SimpleXChat + +struct NewChatSheetButton: View { + @Binding var showNewChatSheet: Bool + + var body: some View { + Button { + showNewChatSheet = true + } label: { + Image(systemName: "square.and.pencil") + .resizable() + .scaledToFit() + .frame(width: 24, height: 24) + } + .sheet(isPresented: $showNewChatSheet) { + NewChatView(selection: .invite) + } + } +} + +//#Preview { +// NewChatSheetButton() +//} diff --git a/apps/ios/Shared/Views/NewChat/NewChatView.swift b/apps/ios/Shared/Views/NewChat/NewChatView.swift index 620f138b4e..f0f3525021 100644 --- a/apps/ios/Shared/Views/NewChat/NewChatView.swift +++ b/apps/ios/Shared/Views/NewChat/NewChatView.swift @@ -10,6 +10,16 @@ import SwiftUI import SimpleXChat import CodeScanner +enum SomeAlert: Identifiable { + case someAlert(alert: Alert, id: String) + + var id: String { + switch self { + case let .someAlert(_, id): return id + } + } +} + enum NewChatOption: Identifiable { case invite case connect @@ -21,175 +31,119 @@ struct NewChatView: View { @EnvironmentObject var m: ChatModel @State var selection: NewChatOption @State var showScanQRCodeSheet = false - @State var connReqInvitation: String = "" - @State var contactConnection: PendingContactConnection? = nil + @State private var connReqInvitation: String = "" + @State private var contactConnection: PendingContactConnection? = nil @State private var creatingConnReq = false + @State private var someAlert: SomeAlert? var body: some View { - NavigationView { - VStack(alignment: .leading) { - Text("Start a New Chat") - .font(.largeTitle) - .bold() - .fixedSize(horizontal: false, vertical: true) - .padding(.vertical) + List { + Group { + HStack { + Text("New chat") + .font(.largeTitle) + .bold() + .fixedSize(horizontal: false, vertical: true) + .padding(.vertical) + Spacer() + InfoSheetButton { + AddContactLearnMore(showTitle: true) + } + } Picker("New chat", selection: $selection) { - Label("Invite", systemImage: "link") + Label("Share link", systemImage: "link") .tag(NewChatOption.invite) - Label("Connect", systemImage: "qrcode") + Label("Connect via link", systemImage: "qrcode") .tag(NewChatOption.connect) } .pickerStyle(.segmented) + } + .listRowBackground(Color.clear) + .listRowSeparator(.hidden) + .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) - switch selection { - case .invite: InviteView( - contactConnection: $contactConnection, - connReqInvitation: connReqInvitation - ) - case .connect: ConnectView(showScanQRCodeSheet: showScanQRCodeSheet) + switch selection { + case .invite: + if connReqInvitation != "" { + InviteView(contactConnection: $contactConnection, connReqInvitation: connReqInvitation) + } else if creatingConnReq { + creatingLinkProgressView() + } else { + retryButton() } + case .connect: + ConnectView(showScanQRCodeSheet: showScanQRCodeSheet) } - .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) - .padding() - .background(Color(.systemGroupedBackground)) - .onChange(of: selection) { sel in - if case .invite = sel, - connReqInvitation == "" && contactConnection == nil && !creatingConnReq { - createInvitation() - } + } + .onChange(of: selection) { sel in + createInvitation(sel) + } + .onAppear { + createInvitation(selection) + } + .onDisappear { m.connReqInv = nil } + .alert(item: $someAlert) { a in + switch a { + case let .someAlert(alert, _): alert } - .onAppear { m.connReqInv = connReqInvitation } - .onDisappear { m.connReqInv = nil } } } - private func createInvitation() { - creatingConnReq = true - Task { - if let (connReq, pcc) = await apiAddContact(incognito: incognitoGroupDefault.get()) { - await MainActor.run { - connReqInvitation = connReq - contactConnection = pcc - m.connReqInv = connReq - } - } else { - await MainActor.run { - creatingConnReq = false + private func createInvitation(_ selection: NewChatOption) { + if case .invite = selection, + connReqInvitation == "" && contactConnection == nil && !creatingConnReq { + creatingConnReq = true + Task { + let (r, alert) = await apiAddContact(incognito: incognitoGroupDefault.get()) + if let (connReq, pcc) = r { + await MainActor.run { + connReqInvitation = connReq + contactConnection = pcc + m.connReqInv = connReq + } + } else { + await MainActor.run { + creatingConnReq = false + if let alert = alert { + someAlert = .someAlert(alert: alert, id: "createInvitation error") + } + } } } } } + + private func creatingLinkProgressView() -> some View { + ProgressView("Creating link…") + .progressViewStyle(.circular) + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) + .padding(.top) + .listRowBackground(Color.clear) + .listRowSeparator(.hidden) + } + + private func retryButton() -> some View { + Button { + createInvitation(selection) + } label: { + Text("Retry") + } + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) + .padding(.top) + .listRowBackground(Color.clear) + .listRowSeparator(.hidden) + } } -struct InviteView: View { - @EnvironmentObject private var chatModel: ChatModel +private struct InviteView: View { + @EnvironmentObject var chatModel: ChatModel @Binding var contactConnection: PendingContactConnection? var connReqInvitation: String @AppStorage(GROUP_DEFAULT_INCOGNITO, store: groupDefaults) private var incognitoDefault = false var body: some View { - GeometryReader { geo in - ScrollView { - VStack(alignment: .leading, spacing: 8) { - if connReqInvitation != "" { - HStack { - Text("Share this unique invite link") - .textCase(.uppercase) - .font(.footnote) - .foregroundColor(.secondary) - Spacer() - Button { - copyLink() - } label: { - Text("Copy") - .font(.footnote) - } - } - .padding(.horizontal) - - Text(simplexChatLink(connReqInvitation)) - .lineLimit(2) - .font(.callout) - .padding(.horizontal) - .padding(.vertical, 8) - .background( - RoundedRectangle(cornerRadius: 12, style: .continuous) - .fill(Color(uiColor: .systemBackground)) - ) - - Text("Or show this code") - .textCase(.uppercase) - .font(.footnote) - .foregroundColor(.secondary) - .padding(.horizontal) - .padding(.top, 8) - - VStack(alignment: .center) { - SimpleXLinkQRCode(uri: connReqInvitation) - .padding(.horizontal) - .padding(.vertical, 10) - .frame(width: geo.size.width * 0.8) - } - .frame(maxWidth: .infinity, alignment: .center) - .background( - RoundedRectangle(cornerRadius: 12, style: .continuous) - .fill(Color(uiColor: .systemBackground)) - ) - - VStack(alignment: .leading) { - IncognitoToggle(incognitoEnabled: $incognitoDefault) - Divider() - shareLinkButton2(connReqInvitation) - } - .padding(.horizontal) - .padding(.vertical, 8) - .frame(maxWidth: .infinity) - .background( - RoundedRectangle(cornerRadius: 12, style: .continuous) - .fill(Color(uiColor: .systemBackground)) - ) - .padding(.top) - - VStack(alignment: .center) { - oneTimeLinkLearnMoreButton2() - } - .frame(maxWidth: .infinity, alignment: .center) - .padding(.top) - } else { - VStack(alignment: .center, spacing: 4) { - ProgressView() - .progressViewStyle(.circular) - Text("Creating link…") - .foregroundColor(.secondary) - } - .frame(maxWidth: .infinity, alignment: .center) - .padding(.top) - -// Text("Creating link…") -// .textCase(.uppercase) -// .font(.footnote) -// .foregroundColor(.secondary) -// .padding(.horizontal) -// -// VStack(alignment: .center) { -// ProgressView() -// .progressViewStyle(.circular) -// .scaleEffect(2) -// .frame(maxWidth: .infinity) -// .padding(.horizontal) -// .padding(.vertical, 14) -// } -// .frame(maxWidth: .infinity, alignment: .center) -// .background( -// RoundedRectangle(cornerRadius: 12, style: .continuous) -// .fill(Color(uiColor: .systemBackground)) -// ) - } - } - } - .padding(.vertical) - .onAppear { chatModel.connReqInv = connReqInvitation } + viewBody() .onChange(of: incognitoDefault) { incognito in Task { do { @@ -205,15 +159,54 @@ struct InviteView: View { } } } + } + + @ViewBuilder private func viewBody() -> some View { + Section("Share this 1-time invite link") { + shareLinkView() + } + + qrCodeView() + + Section { + IncognitoToggle(incognitoEnabled: $incognitoDefault) + } footer: { + sharedProfileInfo(incognitoDefault) } } - private func copyLink() { - UIPasteboard.general.string = simplexChatLink(connReqInvitation) + private func shareLinkView() -> some View { + HStack { + let link = simplexChatLink(connReqInvitation) + Text(link) + .lineLimit(1) + .font(.caption) + .truncationMode(.middle) + Button { + showShareSheet(items: [link]) + } label: { + Image(systemName: "square.and.arrow.up") + } + } + } + + private func qrCodeView() -> some View { + Section("Or show this code") { + SimpleXLinkQRCode(uri: connReqInvitation) + .padding() + .background( + RoundedRectangle(cornerRadius: 12, style: .continuous) + .fill(Color(uiColor: .systemBackground)) + ) + .padding(.horizontal) + .listRowBackground(Color.clear) + .listRowSeparator(.hidden) + .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) + } } } -struct ConnectView: View { +private struct ConnectView: View { @Environment(\.dismiss) var dismiss: DismissAction @State var showScanQRCodeSheet = false @State private var connectionLink: String = "" @@ -222,130 +215,55 @@ struct ConnectView: View { @State private var scannedLink: String = "" var body: some View { - ScrollView { - VStack(alignment: .leading, spacing: 8) { - ( - Text("Paste the URL your received from your contact.") - + Text("\n\n") - + Text("You'll be connected to begin a private conversation with them.") - ) - .font(.footnote) - .foregroundColor(.secondary) - .padding(.horizontal) - - HStack { - Text("Unique invite link") - .textCase(.uppercase) - .font(.footnote) - .foregroundColor(.secondary) - Spacer() - if (connectionLink != "") { - Button { - clearLink() - } label: { - Text("Clear") - .font(.footnote) - } - } + viewBody() + .alert(item: $alert) { a in planAndConnectAlert(a, dismiss: true) } + .actionSheet(item: $sheet) { s in planAndConnectActionSheet(s, dismiss: true) } + .sheet(isPresented: $showScanQRCodeSheet) { + if #available(iOS 16.0, *) { + ScanConnectionCodeView(scannedLink: $scannedLink) + .presentationDetents([.fraction(0.8)]) + } else { + ScanConnectionCodeView(scannedLink: $scannedLink) } - .padding(.horizontal) - .padding(.top) - - pasteLinkView() - - Text("Or scan QR code") - .textCase(.uppercase) - .font(.footnote) - .foregroundColor(.secondary) - .padding(.horizontal) - .padding(.top, 8) - - VStack(alignment: .center) { - scanQRCodeButton() - } - .padding(.horizontal) - .padding(.vertical, 8) - .frame(maxWidth: .infinity, alignment: .center) - .background( - RoundedRectangle(cornerRadius: 12, style: .continuous) - .fill(Color(uiColor: .systemBackground)) - ) - - VStack(alignment: .center) { - oneTimeLinkLearnMoreButton2() - } - .frame(maxWidth: .infinity, alignment: .center) - .padding(.top) } - } - .padding(.vertical) - .alert(item: $alert) { a in planAndConnectAlert(a, dismiss: true) } - .actionSheet(item: $sheet) { s in planAndConnectActionSheet(s, dismiss: true) } - .sheet(isPresented: $showScanQRCodeSheet) { - if #available(iOS 16.0, *) { - ScanConnectionCodeView(scannedLink: $scannedLink) - .presentationDetents([.fraction(0.8)]) - } else { - ScanConnectionCodeView(scannedLink: $scannedLink) + .onChange(of: scannedLink) { link in + connect(link) } - } - .onChange(of: scannedLink) { link in - connect(link) - } } - private func clearLink() { - connectionLink = "" + @ViewBuilder private func viewBody() -> some View { + Section { + // TODO clear link button + pasteLinkView() + } header: { + Text("Paste the link you received") + } + + Section { + scanQRCodeButton() + } header: { + Text("Or scan QR code") + } } @ViewBuilder private func pasteLinkView() -> some View { if connectionLink == "" { - VStack(alignment: .center) { - ZStack { - Text("\n") - .font(.callout) - .padding(.horizontal) - .padding(.vertical, 8) - .opacity(0) - Button { - if let link = UIPasteboard.general.string { - // TODO test pasted text is a link, alert if not - connectionLink = link.trimmingCharacters(in: .whitespaces) - connect(connectionLink) - } - } label: { - Text("Click Here to Paste Link") - .foregroundColor(.accentColor) - .padding(.horizontal) - .padding(.vertical, 8) - } + Button { + if let link = UIPasteboard.general.string { + // TODO test pasted text is a link, alert if not + connectionLink = link.trimmingCharacters(in: .whitespaces) + connect(connectionLink) + } + } label: { + settingsRow("doc.plaintext") { + Text("Tap to paste link") } } - .frame(maxWidth: .infinity, alignment: .center) - .background( - RoundedRectangle(cornerRadius: 12, style: .continuous) - .fill(Color(uiColor: .systemBackground)) - ) } else { - VStack() { - ZStack { - Text("\n") - .font(.callout) - .padding(.horizontal) - .padding(.vertical, 8) - .opacity(0) - Text(connectionLink) - .lineLimit(2) - .font(.callout) - .padding(.horizontal) - .padding(.vertical, 8) - } - } - .frame(maxWidth: .infinity) - .background( - RoundedRectangle(cornerRadius: 12, style: .continuous) - .fill(Color(uiColor: .systemBackground)) - ) + Text(connectionLink) + .lineLimit(1) + .font(.caption) + .truncationMode(.middle) } } @@ -370,7 +288,7 @@ struct ConnectView: View { } } -struct ScanConnectionCodeView: View { +private struct ScanConnectionCodeView: View { @Environment(\.dismiss) var dismiss: DismissAction @Binding var scannedLink: String @@ -407,35 +325,33 @@ struct ScanConnectionCodeView: View { } } +struct InfoSheetButton: View { + @ViewBuilder let content: Content + @State private var showInfoSheet = false + + var body: some View { + Button { + showInfoSheet = true + } label: { + Image(systemName: "info.circle") + .resizable() + .scaledToFit() + .frame(width: 20, height: 20) + } + .sheet(isPresented: $showInfoSheet) { + content + } + } +} + // TODO move IncognitoToggle here -// TODO move shareLinkButton here -func shareLinkButton2(_ connReqInvitation: String) -> some View { - Button { - showShareSheet(items: [simplexChatLink(connReqInvitation)]) - } label: { - settingsRow("square.and.arrow.up") { - Text("Share link") - } - } -} - -// TODO move oneTimeLinkLearnMoreButton here -func oneTimeLinkLearnMoreButton2() -> some View { - NavigationLink { - AddContactLearnMore() - .navigationTitle("One-time invitation link") - .navigationBarTitleDisplayMode(.large) - } label: { - settingsRow("info.circle") { - Text("Need Guidance?") - .underline() - } - } -} +// TODO move shareLinkButton to connection details // TODO move planAndConnect here +// TODO delete NewChatButton, CreateLinkView, ScanToConnectView, PasteToConnectView, AddContactView + //#Preview { // NewChatView() //} diff --git a/apps/ios/Shared/Views/UserSettings/IncognitoHelp.swift b/apps/ios/Shared/Views/UserSettings/IncognitoHelp.swift index 20dadb7954..fc478596a9 100644 --- a/apps/ios/Shared/Views/UserSettings/IncognitoHelp.swift +++ b/apps/ios/Shared/Views/UserSettings/IncognitoHelp.swift @@ -10,24 +10,23 @@ import SwiftUI struct IncognitoHelp: View { var body: some View { - VStack(alignment: .leading) { + List { Text("Incognito mode") .font(.largeTitle) .bold() + .fixedSize(horizontal: false, vertical: true) .padding(.vertical) - ScrollView { - VStack(alignment: .leading) { - Group { - Text("Incognito mode protects your privacy by using a new random profile for each contact.") - Text("It allows having many anonymous connections without any shared data between them in a single chat profile.") - Text("When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.") - } - .padding(.bottom) - } + .listRowBackground(Color.clear) + .listRowSeparator(.hidden) + .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) + VStack(alignment: .leading, spacing: 18) { + Text("Incognito mode protects your privacy by using a new random profile for each contact.") + Text("It allows having many anonymous connections without any shared data between them in a single chat profile.") + Text("When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.") + Text("Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).") } + .listRowBackground(Color.clear) } - .frame(maxWidth: .infinity) - .padding() } } diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index 558adae4f8..9b14004229 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -179,7 +179,7 @@ 64AA1C6927EE10C800AC7277 /* ContextItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64AA1C6827EE10C800AC7277 /* ContextItemView.swift */; }; 64AA1C6C27F3537400AC7277 /* DeletedItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64AA1C6B27F3537400AC7277 /* DeletedItemView.swift */; }; 64AEA4ED2B15D2A400334292 /* NewChatView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64AEA4EC2B15D2A400334292 /* NewChatView.swift */; }; - 64AEA4EF2B15FEE100334292 /* NewChatButton2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64AEA4EE2B15FEE100334292 /* NewChatButton2.swift */; }; + 64AEA4EF2B15FEE100334292 /* NewChatSheetButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64AEA4EE2B15FEE100334292 /* NewChatSheetButton.swift */; }; 64C06EB52A0A4A7C00792D4D /* ChatItemInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C06EB42A0A4A7C00792D4D /* ChatItemInfoView.swift */; }; 64C3B0212A0D359700E19930 /* CustomTimePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C3B0202A0D359700E19930 /* CustomTimePicker.swift */; }; 64D0C2C029F9688300B38D5F /* UserAddressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2BF29F9688300B38D5F /* UserAddressView.swift */; }; @@ -465,7 +465,7 @@ 64AA1C6827EE10C800AC7277 /* ContextItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextItemView.swift; sourceTree = ""; }; 64AA1C6B27F3537400AC7277 /* DeletedItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeletedItemView.swift; sourceTree = ""; }; 64AEA4EC2B15D2A400334292 /* NewChatView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewChatView.swift; sourceTree = ""; }; - 64AEA4EE2B15FEE100334292 /* NewChatButton2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewChatButton2.swift; sourceTree = ""; }; + 64AEA4EE2B15FEE100334292 /* NewChatSheetButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewChatSheetButton.swift; sourceTree = ""; }; 64C06EB42A0A4A7C00792D4D /* ChatItemInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatItemInfoView.swift; sourceTree = ""; }; 64C3B0202A0D359700E19930 /* CustomTimePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTimePicker.swift; sourceTree = ""; }; 64D0C2BF29F9688300B38D5F /* UserAddressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressView.swift; sourceTree = ""; }; @@ -741,7 +741,7 @@ 5CB2085228DB7CAF00D024EC /* ConnectViaLinkView.swift */, 64D0C2C529FAC1EC00B38D5F /* AddContactLearnMore.swift */, 64AEA4EC2B15D2A400334292 /* NewChatView.swift */, - 64AEA4EE2B15FEE100334292 /* NewChatButton2.swift */, + 64AEA4EE2B15FEE100334292 /* NewChatSheetButton.swift */, ); path = NewChat; sourceTree = ""; @@ -1121,7 +1121,7 @@ 5C13730B28156D2700F43030 /* ContactConnectionView.swift in Sources */, 644EFFE0292CFD7F00525D5B /* CIVoiceView.swift in Sources */, 6432857C2925443C00FBE5C8 /* GroupPreferencesView.swift in Sources */, - 64AEA4EF2B15FEE100334292 /* NewChatButton2.swift in Sources */, + 64AEA4EF2B15FEE100334292 /* NewChatSheetButton.swift in Sources */, 5C93293129239BED0090FFF9 /* ProtocolServerView.swift in Sources */, 5C9CC7AD28C55D7800BEF955 /* DatabaseEncryptionView.swift in Sources */, 5CBD285A295711D700EC2CF4 /* ImageUtils.swift in Sources */,