krz/rune
an ios client for njalla
clone: git clone https://gitbay.org/krz/rune.git
v1.2.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
14 init(domainName: String, record: DNSRecord, viewModel: DomainViewModel, client: NjallaClient) {
15 self.domainName = domainName
16 self.record = record
17 self.viewModel = viewModel
18 self.client = client
19 _draft = State(initialValue: DNSRecordDraft(record: record))
20 }
21
22 var body: some View {
23 Form {
24 DNSRecordFormSections(draft: $draft)
25
26 Section {
27 Button("Save") {
28 Task {
29 await save()
30 }
31 }
32 .disabled(viewModel.isSaving || !draft.canSubmit)
33 }
34
35 Section {
36 Button("Delete Record", role: .destructive) {
37 guard !viewModel.isSaving else { return }
38 showingDeleteConfirmation = true
39 }
40 .foregroundStyle(.red)
41 .disabled(viewModel.isSaving)
42 }
43 }
44 .navigationTitle(record.name)
45 .navigationBarTitleDisplayMode(.inline)
46 .overlay {
47 if viewModel.isSaving {
48 ProgressView()
49 .controlSize(.large)
50 }
51 }
52 .interactiveDismissDisabled(viewModel.isSaving)
53 .onChange(of: draft.type) { oldValue, newValue in
54 guard oldValue != newValue else { return }
55 draft.resetTypeSpecificFields()
56 }
57 .alert(deleteAlertTitle, isPresented: $showingDeleteConfirmation) {
58 Button("Delete Record", role: .destructive) {
59 Task {
60 await deleteRecord()
61 }
62 }
63 Button("Cancel", role: .cancel) {}
64 } message: {
65 Text("This action cannot be undone.")
66 }
67 .alert("Request Failed", isPresented: mutationErrorBinding) {
68 Button("OK", role: .cancel) {}
69 } message: {
70 Text(viewModel.mutationErrorMessage ?? "")
71 }
72 }
73
74 private func save() async {
75 guard !viewModel.isSaving else {
76 return
77 }
78
79 do {
80 try await viewModel.editRecord(for: domainName, recordID: record.id, draft: draft, client: client)
81 dismiss()
82 } catch is CancellationError {
83 return
84 } catch {
85 return
86 }
87 }
88
89 private func deleteRecord() async {
90 guard !viewModel.isSaving else {
91 return
92 }
93
94 do {
95 try await viewModel.removeRecord(record, client: client)
96 dismiss()
97 } catch is CancellationError {
98 return
99 } catch {
100 return
101 }
102 }
103
104 private var mutationErrorBinding: Binding<Bool> {
105 Binding(
106 get: { viewModel.mutationErrorMessage != nil },
107 set: { newValue in
108 if !newValue {
109 viewModel.dismissMutationError()
110 }
111 }
112 )
113 }
114
115 private var deleteAlertTitle: String {
116 "Delete \(record.type) record \(record.name)?"
117 }
118}