summaryrefslogtreecommitdiff
path: root/Rune/Views/Domains/ForwardAddView.swift
blob: 222ab869bef786fa74cc5c944af5e8437a1174b2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import SwiftUI

struct ForwardAddView: View {
    let domainName: String
    @ObservedObject var viewModel: DomainViewModel
    let client: NjallaClient

    @Environment(\.dismiss) private var dismiss

    @State private var from = ""
    @State private var to = ""

    var body: some View {
        Form {
            Section {
                TextField("From", text: $from)
                    .textInputAutocapitalization(.never)
                    .autocorrectionDisabled()
                TextField("To", text: $to)
                    .textInputAutocapitalization(.never)
                    .keyboardType(.emailAddress)
                    .autocorrectionDisabled()
            } header: {
                Text("Forward")
            } footer: {
                Text("Creates \(trimmedFrom)@\(domainName) -> \(trimmedTo)")
            }

            Section {
                Button("Save") {
                    Task {
                        await save()
                    }
                }
                .disabled(viewModel.isSaving || !canSubmit)
            }
        }
        .navigationTitle("Add Forward")
        .navigationBarTitleDisplayMode(.inline)
        .overlay {
            if viewModel.isSaving {
                ProgressView()
                    .controlSize(.large)
            }
        }
        .toolbar {
            ToolbarItem(placement: .cancellationAction) {
                Button("Cancel", role: .cancel) {
                    dismiss()
                }
                .disabled(viewModel.isSaving)
            }
        }
        .interactiveDismissDisabled(viewModel.isSaving)
        .alert("Request Failed", isPresented: mutationErrorBinding) {
            Button("OK", role: .cancel) {}
        } message: {
            Text(viewModel.mutationErrorMessage ?? "")
        }
    }

    private var trimmedFrom: String {
        from.trimmingCharacters(in: .whitespacesAndNewlines)
    }

    private var trimmedTo: String {
        to.trimmingCharacters(in: .whitespacesAndNewlines)
    }

    private var canSubmit: Bool {
        !trimmedFrom.isEmpty && !trimmedTo.isEmpty
    }

    private func save() async {
        guard !viewModel.isSaving, canSubmit else {
            return
        }

        let forward = EmailForward(domain: domainName, from: trimmedFrom, to: trimmedTo)

        debugLog("Creating forward \(forward.from)@\(forward.domain) -> \(forward.to)")
        do {
            try await viewModel.addForward(forward, client: client)
            debugLog("Created forward \(forward.from)@\(forward.domain) -> \(forward.to)")
            dismiss()
        } catch is CancellationError {
            debugLog("Create cancelled for \(forward.from)@\(forward.domain) -> \(forward.to)")
            return
        } catch {
            debugLog("Create failed for \(forward.from)@\(forward.domain) -> \(forward.to): \(error.localizedDescription)")
            return
        }
    }

    private var mutationErrorBinding: Binding<Bool> {
        Binding(
            get: { viewModel.mutationErrorMessage != nil },
            set: { newValue in
                if !newValue {
                    viewModel.dismissMutationError()
                }
            }
        )
    }

    private func debugLog(_ message: String) {
        #if DEBUG
        debugPrint("[ForwardAddView]", message)
        #endif
    }
}