summaryrefslogtreecommitdiff
path: root/Rune/Views/Domains/RecordEditView.swift
blob: e0c0fde7a697530953a0401b006e95793c836312 (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
import SwiftUI

struct RecordEditView: View {
    let domainName: String
    let record: DNSRecord
    @ObservedObject var viewModel: DomainViewModel
    let client: NjallaClient

    @Environment(\.dismiss) private var dismiss

    @State private var draft: DNSRecordDraft
    @State private var showingDeleteConfirmation = false
    @State private var localErrorMessage: String?

    init(domainName: String, record: DNSRecord, viewModel: DomainViewModel, client: NjallaClient) {
        self.domainName = domainName
        self.record = record
        self.viewModel = viewModel
        self.client = client
        _draft = State(initialValue: DNSRecordDraft(record: record))
    }

    var body: some View {
        Form {
            DNSRecordFormSections(draft: $draft)

            Section {
                Button("Save") {
                    Task {
                        await save()
                    }
                }
                .disabled(viewModel.isSaving || !draft.canSubmit)
            }

            Section {
                Button("Delete Record", role: .destructive) {
                    showingDeleteConfirmation = true
                }
                .foregroundStyle(.red)
            }
        }
        .navigationTitle(record.name)
        .navigationBarTitleDisplayMode(.inline)
        .onChange(of: draft.type) { oldValue, newValue in
            guard oldValue != newValue else { return }
            draft.resetTypeSpecificFields()
        }
        .confirmationDialog(
            "Delete \(record.type) record \(record.name)?",
            isPresented: $showingDeleteConfirmation,
            titleVisibility: .visible
        ) {
            Button("Delete Record", role: .destructive) {
                Task {
                    await deleteRecord()
                }
            }
        }
        .alert("API Error", isPresented: localErrorBinding) {
            Button("OK", role: .cancel) {}
        } message: {
            Text(localErrorMessage ?? "")
        }
    }

    private func save() async {
        do {
            try await viewModel.editRecord(for: domainName, recordID: record.id, draft: draft, client: client)
            dismiss()
        } catch is CancellationError {
            return
        } catch {
            if (error as? URLError)?.code == .cancelled {
                return
            }
            localErrorMessage = error.localizedDescription
        }
    }

    private func deleteRecord() async {
        do {
            try await viewModel.removeRecord(record, client: client)
            dismiss()
        } catch is CancellationError {
            return
        } catch {
            if (error as? URLError)?.code == .cancelled {
                return
            }
            localErrorMessage = error.localizedDescription
        }
    }

    private var localErrorBinding: Binding<Bool> {
        Binding(
            get: { localErrorMessage != nil },
            set: { newValue in
                if !newValue {
                    localErrorMessage = nil
                }
            }
        )
    }
}