krz/rune
an ios client for njalla
clone: git clone https://gitbay.org/krz/rune.git
main: Rune/Views/Domains/ForwardAddView.swift · raw
1import SwiftUI
2
3struct ForwardAddView: View {
4 let domainName: String
5 @ObservedObject var viewModel: DomainViewModel
6 let client: NjallaClient
7
8 @Environment(\.dismiss) private var dismiss
9
10 @State private var from = ""
11 @State private var to = ""
12
13 var body: some View {
14 Form {
15 Section {
16 TextField("From", text: $from)
17 .textInputAutocapitalization(.never)
18 .autocorrectionDisabled()
19 TextField("To", text: $to)
20 .textInputAutocapitalization(.never)
21 .keyboardType(.emailAddress)
22 .autocorrectionDisabled()
23 } header: {
24 Text("Forward")
25 } footer: {
26 Text("Creates \(trimmedFrom)@\(domainName) -> \(trimmedTo)")
27 }
28
29 Section {
30 Button("Save") {
31 Task {
32 await save()
33 }
34 }
35 .disabled(viewModel.isSaving || !canSubmit)
36 }
37 }
38 .navigationTitle("Add Forward")
39 .navigationBarTitleDisplayMode(.inline)
40 .overlay {
41 if viewModel.isSaving {
42 ProgressView()
43 .controlSize(.large)
44 }
45 }
46 .toolbar {
47 ToolbarItem(placement: .cancellationAction) {
48 Button("Cancel", role: .cancel) {
49 dismiss()
50 }
51 .disabled(viewModel.isSaving)
52 }
53 }
54 .interactiveDismissDisabled(viewModel.isSaving)
55 .alert("Request Failed", isPresented: mutationErrorBinding) {
56 Button("OK", role: .cancel) {}
57 } message: {
58 Text(viewModel.mutationErrorMessage ?? "")
59 }
60 }
61
62 private var trimmedFrom: String {
63 from.trimmingCharacters(in: .whitespacesAndNewlines)
64 }
65
66 private var trimmedTo: String {
67 to.trimmingCharacters(in: .whitespacesAndNewlines)
68 }
69
70 private var canSubmit: Bool {
71 !trimmedFrom.isEmpty && !trimmedTo.isEmpty
72 }
73
74 private func save() async {
75 guard !viewModel.isSaving, canSubmit else {
76 return
77 }
78
79 let forward = EmailForward(domain: domainName, from: trimmedFrom, to: trimmedTo)
80
81 debugLog("Creating forward \(forward.from)@\(forward.domain) -> \(forward.to)")
82 do {
83 try await viewModel.addForward(forward, client: client)
84 debugLog("Created forward \(forward.from)@\(forward.domain) -> \(forward.to)")
85 dismiss()
86 } catch is CancellationError {
87 debugLog("Create cancelled for \(forward.from)@\(forward.domain) -> \(forward.to)")
88 return
89 } catch {
90 debugLog("Create failed for \(forward.from)@\(forward.domain) -> \(forward.to): \(error.localizedDescription)")
91 return
92 }
93 }
94
95 private var mutationErrorBinding: Binding<Bool> {
96 Binding(
97 get: { viewModel.mutationErrorMessage != nil },
98 set: { newValue in
99 if !newValue {
100 viewModel.dismissMutationError()
101 }
102 }
103 )
104 }
105
106 private func debugLog(_ message: String) {
107 #if DEBUG
108 debugPrint("[ForwardAddView]", message)
109 #endif
110 }
111}