conversations-classic-ios/ConversationsClassic/View/Screens/Create/AddContactOrChannelScreen.swift

149 lines
5.2 KiB
Swift
Raw Normal View History

2024-06-19 15:15:27 +00:00
import SwiftUI
struct AddContactOrChannelScreen: View {
@EnvironmentObject var store: AppStore
enum Field {
case account
case contact
}
@FocusState private var focus: Field?
@Binding var isPresented: Bool
@State private var contactJID: String = ""
@State private var ownerAccount: Account?
@State private var isShowingLoader = false
@State private var isShowingAlert = false
@State private var errorMsg = ""
var body: some View {
ZStack {
// Background color
2024-07-04 08:21:12 +00:00
Color.Material.Background.light
2024-06-19 15:15:27 +00:00
.ignoresSafeArea()
// Content
VStack(spacing: 0) {
// Header
2024-08-07 09:19:53 +00:00
SharedNavigationBar(
leftButton: .init(
image: Image(systemName: "chevron.left"),
action: {
isPresented = false
}
),
centerText: .init(text: L10n.Contacts.Add.title),
rightButton: .init(
image: Image(systemName: "plus.viewfinder"),
action: {
print("Scan QR-code")
}
)
)
2024-06-19 15:15:27 +00:00
VStack(spacing: 16) {
// Explanation text
Text(L10n.Contacts.Add.explanation)
.font(.body3)
2024-07-04 08:21:12 +00:00
.foregroundColor(.Material.Shape.separator)
2024-06-19 15:15:27 +00:00
.multilineTextAlignment(.center)
.padding(.top, 16)
// Account selector
HStack(spacing: 0) {
Text("Use account:")
.font(.body2)
2024-07-04 08:21:12 +00:00
.foregroundColor(.Material.Text.main)
2024-06-19 15:15:27 +00:00
.frame(alignment: .leading)
Spacer()
}
UniversalInputCollection.DropDownMenu(
prompt: "Use account",
elements: store.state.accountsState.accounts,
selected: $ownerAccount,
focus: $focus,
fieldType: .account
)
// Contact text input
HStack(spacing: 0) {
Text("Contact JID:")
.font(.body2)
2024-07-04 08:21:12 +00:00
.foregroundColor(.Material.Text.main)
2024-06-19 15:15:27 +00:00
.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 {
save()
} label: {
Text(L10n.Global.save)
}
.buttonStyle(PrimaryButtonStyle())
.disabled(!inputValid)
.padding(.top)
Spacer()
}
.padding(.horizontal, 32)
}
}
.onAppear {
if let exists = store.state.accountsState.accounts.first, exists.isActive {
ownerAccount = exists
}
}
.loadingIndicator(isShowingLoader)
.alert(isPresented: $isShowingAlert) {
Alert(
title: Text(L10n.Global.Error.title),
message: Text(errorMsg),
dismissButton: .default(Text(L10n.Global.ok))
)
}
.onChange(of: store.state.rostersState.newAddedRosterJid) { jid in
2024-07-04 08:21:12 +00:00
if jid != nil, isShowingLoader {
2024-06-19 15:15:27 +00:00
isShowingLoader = false
isPresented = false
}
}
.onChange(of: store.state.rostersState.newAddedRosterError) { error in
if let error = error, isShowingLoader {
isShowingLoader = false
errorMsg = error
isShowingAlert = true
}
}
}
private var inputValid: Bool {
ownerAccount != nil && !contactJID.isEmpty && UniversalInputCollection.Validators.isEmail(contactJID)
}
private func save() {
guard let ownerAccount else { return }
if let exists = store.state.rostersState.rosters.first(where: { $0.bareJid == ownerAccount.bareJid && $0.contactBareJid == contactJID }), exists.locallyDeleted {
store.dispatch(.rostersAction(.unmarkRosterAsLocallyDeleted(ownerJID: ownerAccount.bareJid, contactJID: contactJID)))
isPresented = false
} else {
isShowingLoader = true
store.dispatch(.rostersAction(.addRoster(ownerJID: ownerAccount.bareJid, contactJID: contactJID, name: nil, groups: [])))
}
}
}