import SwiftUI import SFSafeSymbols struct InsertableRoute: View, InsertableCommandView { @Environment(\.language) var language final class Model: ObservableObject, InsertableCommandModel { @Published var caption: String? @Published var chartTitle: String? @Published var components: Set = Set(RouteStatisticType.allCases) @Published var mapTitle: String? @Published var selectedImage: FileResource? @Published var dataFile: FileResource? var isReady: Bool { selectedImage != nil && dataFile != nil } init() { } var command: String? { guard let selectedImage, let dataFile else { return nil } var result = ["```route"] result.append("\(RouteBlock.Key.image.rawValue): \(selectedImage.id)") result.append("\(RouteBlock.Key.file.rawValue): \(dataFile.id)") if components != Set(RouteStatisticType.allCases) { let list = components .map { $0.rawValue } .joined(separator: ", ") result.append("\(RouteBlock.Key.components.rawValue): \(list)") } if let caption { result.append("\(RouteBlock.Key.caption.rawValue): \(caption)") } if let chartTitle { result.append("\(RouteBlock.Key.chartTitle.rawValue): \(chartTitle)") } if let mapTitle { result.append("\(RouteBlock.Key.mapTitle.rawValue): \(mapTitle)") } result.append("\n```") return result.joined(separator: "\n") } } static let title = "Route" static let sheetTitle = "Insert route map and statistics" static let icon: SFSymbol = .map @ObservedObject private var model: Model init(model: Model) { self.model = model } var body: some View { VStack { FilePropertyView( title: "Map Image", footer: "Select the image to insert as the map", selectedFile: $model.selectedImage, allowedType: .image) FilePropertyView( title: "Data File", footer: "Select the file containing the statistics", selectedFile: $model.dataFile, allowedType: .text) OptionalStringPropertyView( title: "Map Title", text: $model.mapTitle, prompt: "Map title", footer: "The title to show above the map image") OptionalStringPropertyView( title: "Map Image Caption", text: $model.caption, prompt: "Image Caption", footer: "The caption to show below the fullscreen map") OptionalStringPropertyView( title: "Chart Title", text: $model.chartTitle, prompt: "Title", footer: "The title to show above the statistics") ForEach(RouteStatisticType.allCases.sorted(), id: \.rawValue) { type in Toggle(isOn: Binding( get: { model.components.contains(type) }, set: { isSelected in if isSelected { model.components.insert(type) } else { model.components.remove(type) } } )) { Text(type.displayText(in: language)) }.toggleStyle(.checkbox) } } } } #Preview { InsertableRoute(model: .init()) }