krz/rune

an ios client for njalla

clone: git clone https://gitbay.org/krz/rune.git

v1.0.0: Rune/Views/Domains/DomainEditView.swift · raw

 1import SwiftUI
 2
 3struct DomainEditView: View {
 4    let domain: Domain
 5    @ObservedObject var viewModel: DomainViewModel
 6    let client: NjallaClient
 7
 8    @Environment(\.dismiss) private var dismiss
 9
10    @State private var autorenew: Bool
11    @State private var mailforwarding: Bool
12    @State private var dnssec: Bool
13    @State private var lock: Bool
14    @State private var nameserversText: String
15    @State private var localErrorMessage: String?
16
17    init(domain: Domain, viewModel: DomainViewModel, client: NjallaClient) {
18        self.domain = domain
19        self.viewModel = viewModel
20        self.client = client
21        _autorenew = State(initialValue: domain.autorenew ?? false)
22        _mailforwarding = State(initialValue: domain.mailforwarding ?? false)
23        _dnssec = State(initialValue: domain.dnssec ?? false)
24        _lock = State(initialValue: domain.lock ?? false)
25        _nameserversText = State(initialValue: (domain.nameservers ?? []).joined(separator: "\n"))
26    }
27
28    var body: some View {
29        Form {
30            Section("Settings") {
31                Toggle("Autorenew", isOn: $autorenew)
32                Toggle("Mail Forwarding", isOn: $mailforwarding)
33                Toggle("DNSSEC", isOn: $dnssec)
34                Toggle("Registrar Lock", isOn: $lock)
35            }
36
37            Section {
38                TextEditor(text: $nameserversText)
39                    .frame(minHeight: 120)
40            } header: {
41                Text("Nameservers")
42            } footer: {
43                Text("Enter one nameserver per line. Leave blank to use Njalla defaults.")
44            }
45
46            Section {
47                Button("Save") {
48                    Task {
49                        await save()
50                    }
51                }
52                .disabled(viewModel.isSaving)
53            }
54        }
55        .navigationTitle("Edit Domain")
56        .navigationBarTitleDisplayMode(.inline)
57        .alert("API Error", isPresented: localErrorBinding) {
58            Button("OK", role: .cancel) {}
59        } message: {
60            Text(localErrorMessage ?? "")
61        }
62    }
63
64    private func save() async {
65        let request = DomainUpdateRequest(
66            autorenew: autorenew,
67            mailforwarding: mailforwarding,
68            dnssec: dnssec,
69            lock: lock,
70            nameservers: nameserversText
71                .split(whereSeparator: \.isNewline)
72                .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
73                .filter { !$0.isEmpty }
74        )
75
76        do {
77            try await viewModel.updateDomain(named: domain.name, request: request, client: client)
78            dismiss()
79        } catch is CancellationError {
80            return
81        } catch {
82            if (error as? URLError)?.code == .cancelled {
83                return
84            }
85            localErrorMessage = error.localizedDescription
86        }
87    }
88
89    private var localErrorBinding: Binding<Bool> {
90        Binding(
91            get: { localErrorMessage != nil },
92            set: { newValue in
93                if !newValue {
94                    localErrorMessage = nil
95                }
96            }
97        )
98    }
99}