conversations-classic-ios/ConversationsClassic/View/Main/Contacts/AddContactOrChannelScreen.swift

157 lines
4.9 KiB
Swift
Raw Normal View History

2024-08-11 14:02:18 +00:00
import SwiftUI
struct AddContactOrChannelScreen: View {
2024-08-11 15:10:58 +00:00
@Environment(\.router) var router
2024-08-11 17:07:02 +00:00
@EnvironmentObject var clientsStore: ClientsStore
@EnvironmentObject var rostersStore: RostersStore
2024-08-11 14:02:18 +00:00
2024-08-11 17:07:02 +00:00
enum Field {
case account
case contact
}
@FocusState private var focus: Field?
@State private var ownerCredentials: Credentials?
@State private var contactJID: String = ""
2024-08-11 14:02:18 +00:00
var body: some View {
ZStack {
// Background color
Color.Material.Background.light
.ignoresSafeArea()
// Content
VStack(spacing: 0) {
// Header
SharedNavigationBar(
leftButton: .init(
image: Image(systemName: "xmark"),
action: {
2024-08-11 15:10:58 +00:00
router.dismissScreen()
2024-08-11 14:02:18 +00:00
}
),
centerText: .init(text: L10n.Contacts.Add.title),
rightButton: .init(
image: Image(systemName: "plus.viewfinder"),
action: {
print("Scan QR-code")
}
)
)
2024-08-11 17:07:02 +00:00
// Content
VStack(spacing: 16) {
// Explanation text
Text(L10n.Contacts.Add.explanation)
.font(.body3)
.foregroundColor(.Material.Shape.separator)
.multilineTextAlignment(.center)
.padding(.top, 16)
// Account selector
HStack(spacing: 0) {
Text("Use account:")
.font(.body2)
.foregroundColor(.Material.Text.main)
.frame(alignment: .leading)
Spacer()
}
UniversalInputCollection.DropDownMenu(
prompt: "Use account",
elements: activeClientsCredentials,
selected: $ownerCredentials,
focus: $focus,
fieldType: .account
)
// Contact text input
HStack(spacing: 0) {
Text("Contact JID:")
.font(.body2)
.foregroundColor(.Material.Text.main)
.frame(alignment: .leading)
Spacer()
}
UniversalInputCollection.TextField(
prompt: "Contact or channel JID",
text: $contactJID,
focus: $focus,
fieldType: .contact,
contentType: .emailAddress,
keyboardType: .emailAddress,
submitLabel: .done,
action: {
focus = .account
}
)
// Save button
Button {
Task {
await save()
}
} label: {
Text(L10n.Global.save)
}
.buttonStyle(PrimaryButtonStyle())
.disabled(!inputValid)
.padding(.top)
Spacer()
}
2024-08-11 14:02:18 +00:00
.padding(.horizontal, 32)
}
}
2024-08-11 17:07:02 +00:00
.onAppear {
if let exists = activeClientsCredentials.first {
ownerCredentials = exists
}
}
}
private var activeClientsCredentials: [Credentials] {
clientsStore.clients
.filter { $0.state != .disabled }
.map { $0.credentials }
2024-08-11 14:02:18 +00:00
}
private var inputValid: Bool {
2024-08-11 17:07:02 +00:00
ownerCredentials != nil && !contactJID.isEmpty && UniversalInputCollection.Validators.isEmail(contactJID)
}
private func save() async {
guard let ownerCredentials = ownerCredentials else { return }
router.showModal {
LoadingScreen()
}
defer {
router.dismissModal()
}
let result = await rostersStore.addRoster(ownerJid: ownerCredentials.bareJid, contactJID: contactJID, name: nil, groups: [])
switch result {
case .success:
router.dismissScreen()
case .connectionError:
showErrorAlert(subtitle: L10n.Contacts.Add.connectionError)
case .serverError:
showErrorAlert(subtitle: L10n.Contacts.Add.serverError)
}
2024-08-11 14:02:18 +00:00
}
2024-08-11 17:07:02 +00:00
private func showErrorAlert(subtitle: String) {
router.showAlert(
.alert,
title: L10n.Global.Error.title,
subtitle: subtitle
) {
Button(L10n.Global.ok, role: .cancel) {}
}
}
2024-08-11 14:02:18 +00:00
}