rework invite
This commit is contained in:
parent
ab45ec5e8e
commit
0b7b43cc4b
@ -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? {
|
||||
|
@ -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:")
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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: {
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
//}
|
32
apps/ios/Shared/Views/NewChat/NewChatSheetButton.swift
Normal file
32
apps/ios/Shared/Views/NewChat/NewChatSheetButton.swift
Normal file
@ -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()
|
||||
//}
|
@ -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<Content: View>: 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()
|
||||
//}
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 = "<group>"; };
|
||||
64AA1C6B27F3537400AC7277 /* DeletedItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeletedItemView.swift; sourceTree = "<group>"; };
|
||||
64AEA4EC2B15D2A400334292 /* NewChatView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewChatView.swift; sourceTree = "<group>"; };
|
||||
64AEA4EE2B15FEE100334292 /* NewChatButton2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewChatButton2.swift; sourceTree = "<group>"; };
|
||||
64AEA4EE2B15FEE100334292 /* NewChatSheetButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewChatSheetButton.swift; sourceTree = "<group>"; };
|
||||
64C06EB42A0A4A7C00792D4D /* ChatItemInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatItemInfoView.swift; sourceTree = "<group>"; };
|
||||
64C3B0202A0D359700E19930 /* CustomTimePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTimePicker.swift; sourceTree = "<group>"; };
|
||||
64D0C2BF29F9688300B38D5F /* UserAddressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressView.swift; sourceTree = "<group>"; };
|
||||
@ -741,7 +741,7 @@
|
||||
5CB2085228DB7CAF00D024EC /* ConnectViaLinkView.swift */,
|
||||
64D0C2C529FAC1EC00B38D5F /* AddContactLearnMore.swift */,
|
||||
64AEA4EC2B15D2A400334292 /* NewChatView.swift */,
|
||||
64AEA4EE2B15FEE100334292 /* NewChatButton2.swift */,
|
||||
64AEA4EE2B15FEE100334292 /* NewChatSheetButton.swift */,
|
||||
);
|
||||
path = NewChat;
|
||||
sourceTree = "<group>";
|
||||
@ -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 */,
|
||||
|
Loading…
Reference in New Issue
Block a user