2025-01-29 09:16:29 +01:00

201 lines
5.1 KiB
Swift

import SwiftUI
import SFSafeSymbols
final class InsertableFileButton: ObservableObject {
@Published
var label: ContentLabel = .init(icon: .buttonDownload, value: "Text")
@Published
var file: FileResource?
@Published
var downloadedFileName: String? = nil
var command: String? {
guard let file else {
return nil
}
let result =
"""
icon: \(label.icon.rawValue)
text: \(label.value)
file: \(file.id)
"""
guard let downloadedFileName else {
return result
}
return result + "\n" + "name: \(downloadedFileName)"
}
}
final class InsertableUrlButton: ObservableObject {
@Published
var label: ContentLabel = .init(icon: .buttonDownload, value: "Text")
@Published
var url: String = "Url"
var command: String? {
"""
icon: \(label.icon.rawValue)
text: \(label.value)
url: \(url)
"""
}
}
final class InsertableEventButton: ObservableObject {
@Published
var label: ContentLabel = .init(icon: .buttonDownload, value: "Text")
@Published
var event: String = "Javascript"
var command: String? {
"""
icon: \(label.icon.rawValue)
text: \(label.value)
event: \(event)
"""
}
}
struct InsertableButtons: View, InsertableCommandView {
final class Model: ObservableObject, InsertableCommandModel {
enum AnyButton: Identifiable {
case file(InsertableFileButton)
case url(InsertableUrlButton)
case event(InsertableEventButton)
var command: String? {
switch self {
case .file(let file):
return file.command
case .url(let url):
return url.command
case .event(let event):
return event.command
}
}
var id: String {
switch self {
case .file(let file):
return "file-\(file.file?.id ?? "none")"
case .url(let url):
return "url-\(url.url)"
case .event(let event):
return "event-\(event.event)"
}
}
}
@Published
var buttons: [AnyButton] = []
var isReady: Bool {
!buttons.isEmpty
}
var command: String? {
let result = buttons.compactMap { $0.command }
guard result.count == buttons.count else {
return nil
}
return result.map {
"```buttons\n\($0)\n```"
}.joined(separator: "\n\n")
}
}
static let title = "Buttons"
static let sheetTitle = "Insert buttons"
static let icon: SFSymbol = .rectangleAndHandPointUpLeft
@ObservedObject
private var model: Model
init(model: Model) {
self.model = model
}
var body: some View {
VStack(alignment: .leading) {
List(model.buttons) { button in
switch button {
case .file(let file):
FileButtonView(content: file)
case .url(let url):
UrlButtonView(content: url)
case .event(let event):
EventButtonView(content: event)
}
}
.frame(minHeight: 300)
HStack {
Spacer()
Button("File", action: { model.buttons.append(.file(.init())) })
Button("Url", action: { model.buttons.append(.url(.init())) })
Button("Event", action: { model.buttons.append(.event(.init())) })
Spacer()
}
}
}
}
private struct FileButtonView: View {
@ObservedObject
var content: InsertableFileButton
@State
private var showFileSelectionSheet = false
var body: some View {
HStack {
LabelEditingView(label: content.label)
Button("\(content.file?.id ?? "Select file")", action: { showFileSelectionSheet = true })
OptionalTextField("", text: $content.downloadedFileName, prompt: "Downloaded file name")
.textFieldStyle(.roundedBorder)
}
.sheet(isPresented: $showFileSelectionSheet) {
FileSelectionView(selectedFile: $content.file)
}
}
}
private struct UrlButtonView: View {
@ObservedObject
var content: InsertableUrlButton
var body: some View {
HStack {
LabelEditingView(label: content.label)
TextField("", text: $content.url, prompt: Text("URL"))
.textFieldStyle(.roundedBorder)
}
}
}
private struct EventButtonView: View {
@ObservedObject
var content: InsertableEventButton
var body: some View {
HStack {
LabelEditingView(label: content.label)
TextField("", text: $content.event, prompt: Text("Javascript"))
.textFieldStyle(.roundedBorder)
}
}
}