// Copyright (C) 2024 Rubén Beltrán del Río // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see https://map.tranquil.systems. import SwiftUI struct StagesPreferencesView: View { @AppStorage("customStages") private var customStagesData: Data = UserPreferences.Defaults .customStages @State private var customStages: [CustomStage] = [] @State private var showingHelpPopover = false var body: some View { VStack(alignment: .leading, spacing: Dimensions.Spacing.regular) { Table(customStages) { TableColumn("preferences.stages.column.name") { customStage in TextField( "preferences.stages.placeholder.name", text: Binding( get: { customStage.name }, set: { newValue in updateStageName(customStage.id, newValue) } ) ) .textFieldStyle(.plain) } .width(120) TableColumn("preferences.stages.column.stage_i") { customStage in TextField( "preferences.stages.placeholder.stage_i", text: Binding( get: { customStage.stage.i }, set: { newValue in updateStageValue(customStage.id, \.i, newValue) } ) ) .textFieldStyle(.plain) } TableColumn("preferences.stages.column.stage_ii") { customStage in TextField( "preferences.stages.placeholder.stage_ii", text: Binding( get: { customStage.stage.ii }, set: { newValue in updateStageValue(customStage.id, \.ii, newValue) } ) ) .textFieldStyle(.plain) } TableColumn("preferences.stages.column.stage_iii") { customStage in TextField( "preferences.stages.placeholder.stage_iii", text: Binding( get: { customStage.stage.iii }, set: { newValue in updateStageValue(customStage.id, \.iii, newValue) } ) ) .textFieldStyle(.plain) } TableColumn("preferences.stages.column.stage_iv") { customStage in TextField( "preferences.stages.placeholder.stage_iv", text: Binding( get: { customStage.stage.iv }, set: { newValue in updateStageValue(customStage.id, \.iv, newValue) } ) ) .textFieldStyle(.plain) } TableColumn("") { customStage in Button(action: { removeStage(customStage.id) }) { Image(systemName: "minus") } .buttonStyle(.borderless) } .width(30) } .tableStyle(.bordered(alternatesRowBackgrounds: true)) HStack(spacing: Dimensions.Spacing.regular) { Spacer() Button(action: { showingHelpPopover = true }) { Image(systemName: "questionmark.circle") } .buttonStyle(.borderless) .popover(isPresented: $showingHelpPopover, arrowEdge: .bottom) { Text("preferences.stages.explanation") .font(.Theme.Body.regular) .kerning(Dimensions.Kerning.body) .lineSpacing(Dimensions.LineHeight.body - Dimensions.FontSize.body) .frame(width: 300) .padding(Dimensions.Spacing.regular) } Button(action: addStage) { Image(systemName: "plus") } } } .padding(.vertical, Dimensions.Spacing.loose) .padding(.horizontal, Dimensions.Spacing.indulgent) .onAppear { loadStages() } } private func loadStages() { if let decoded = try? JSONDecoder().decode([CustomStage].self, from: customStagesData) { customStages = decoded } } private func saveStages() { if let encoded = try? JSONEncoder().encode(customStages) { customStagesData = encoded } } private func addStage() { customStages.append(CustomStage.placeholderDefault()) saveStages() } private func removeStage(_ id: UUID) { customStages.removeAll { $0.id == id } saveStages() } private func updateStageName(_ id: UUID, _ newName: String) { if let index = customStages.firstIndex(where: { $0.id == id }) { customStages[index].name = newName saveStages() } } private func updateStageValue( _ id: UUID, _ keyPath: WritableKeyPath, _ value: String ) { if let index = customStages.firstIndex(where: { $0.id == id }) { customStages[index].stage[keyPath: keyPath] = value saveStages() } } } #Preview { StagesPreferencesView() }