krz/rune
an ios client for njalla
clone: git clone https://gitbay.org/krz/rune.git
v1.0.0: Rune/Views/Domains/RecordEditView.swift · raw
1import SwiftUI
2
3struct RecordEditView: View {
4 let domainName: String
5 let record: DNSRecord
6 @ObservedObject var viewModel: DomainViewModel
7 let client: NjallaClient
8
9 @Environment(\.dismiss) private var dismiss
10
11 @State private var draft: DNSRecordDraft
12 @State private var showingDeleteConfirmation = false
13 @State private var localErrorMessage: String?
14
15 init(domainName: String, record: DNSRecord, viewModel: DomainViewModel, client: NjallaClient) {
16 self.domainName = domainName
17 self.record = record
18 self.viewModel = viewModel
19 self.client = client
20 _draft = State(initialValue: DNSRecordDraft(record: record))
21 }
22
23 var body: some View {
24 Form {
25 DNSRecordFormSections(draft: $draft)
26
27 Section {
28 Button("Save") {
29 Task {
30 await save()
31 }
32 }
33 .disabled(viewModel.isSaving || !draft.canSubmit)
34 }
35
36 Section {
37 Button("Delete Record", role: .destructive) {
38 showingDeleteConfirmation = true
39 }
40 .foregroundStyle(.red)
41 }
42 }
43 .navigationTitle(record.name)
44 .navigationBarTitleDisplayMode(.inline)
45 .onChange(of: draft.type) { oldValue, newValue in
46 guard oldValue != newValue else { return }
47 draft.resetTypeSpecificFields()
48 }
49 .confirmationDialog(
50 "Delete \(record.type) record \(record.name)?",
51 isPresented: $showingDeleteConfirmation,
52 titleVisibility: .visible
53 ) {
54 Button("Delete Record", role: .destructive) {
55 Task {
56 await deleteRecord()
57 }
58 }
59 }
60 .alert("API Error", isPresented: localErrorBinding) {
61 Button("OK", role: .cancel) {}
62 } message: {
63 Text(localErrorMessage ?? "")
64 }
65 }
66
67 private func save() async {
68 do {
69 try await viewModel.editRecord(for: domainName, recordID: record.id, draft: draft, client: client)
70 dismiss()
71 } catch is CancellationError {
72 return
73 } catch {
74 if (error as? URLError)?.code == .cancelled {
75 return
76 }
77 localErrorMessage = error.localizedDescription
78 }
79 }
80
81 private func deleteRecord() async {
82 do {
83 try await viewModel.removeRecord(record, client: client)
84 dismiss()
85 } catch is CancellationError {
86 return
87 } catch {
88 if (error as? URLError)?.code == .cancelled {
89 return
90 }
91 localErrorMessage = error.localizedDescription
92 }
93 }
94
95 private var localErrorBinding: Binding<Bool> {
96 Binding(
97 get: { localErrorMessage != nil },
98 set: { newValue in
99 if !newValue {
100 localErrorMessage = nil
101 }
102 }
103 )
104 }
105}