Fix updating of page commands

This commit is contained in:
Christoph Hagen
2025-01-27 22:30:27 +01:00
parent e02bfd17d2
commit 89062f153c
7 changed files with 201 additions and 67 deletions

View File

@ -1,7 +1,34 @@
import SwiftUI
import SFSafeSymbols
struct InsertableImage: View, InsertableCommand {
struct InsertableImage: View, InsertableCommandView {
final class Model: ObservableObject, InsertableCommandModel {
@Published
var caption: String?
@Published
var selectedImage: FileResource?
var isReady: Bool {
selectedImage != nil
}
init() {
}
var command: String? {
guard let selectedImage else {
return nil
}
guard let caption else {
return "![image](\(selectedImage.id))"
}
return "![image](\(selectedImage.id);\(caption))"
}
}
static let title = "Image"
@ -9,17 +36,11 @@ struct InsertableImage: View, InsertableCommand {
static let icon: SFSymbol = .photo
@State
private var selectedImage: FileResource?
@ObservedObject
private var model: Model
@State
private var caption: String? = ""
@Binding
private var command: String?
init(command: Binding<String?>) {
self._command = command
init(model: Model) {
self.model = model
}
var body: some View {
@ -27,29 +48,13 @@ struct InsertableImage: View, InsertableCommand {
FilePropertyView(
title: "Image",
footer: "Select the image to insert",
selectedFile: $selectedImage,
selectedFile: $model.selectedImage,
allowedType: .image)
OptionalStringPropertyView(
title: "Caption",
text: $caption,
text: $model.caption,
prompt: "Image Caption",
footer: "The caption to show on the fullscreen image")
}
.onChange(of: caption) { updateCommand() }
.onChange(of: selectedImage) { updateCommand() }
}
func updateCommand() {
command = currentCommand
}
private var currentCommand: String? {
guard let selectedImage else {
return nil
}
guard let caption else {
return "![image](\(selectedImage.id))"
}
return "![image](\(selectedImage.id);\(caption))"
}
}

View File

@ -0,0 +1,81 @@
import SwiftUI
import SFSafeSymbols
struct InsertableLabels: View, InsertableCommandView {
static let title = "Labels"
static let sheetTitle = "Insert labels"
static let icon: SFSymbol = .squaresBelowRectangle
final class Model: InsertableCommandModel {
@Published
var labels: [ContentLabel] = []
var isReady: Bool {
!labels.isEmpty
}
init() {
}
var command: String? {
guard !labels.isEmpty else {
return nil
}
var result = "```labels"
for label in labels {
result += "\n\(label.icon.rawValue): \(label.value)"
}
result += "\n```"
return result
}
}
@Environment(\.colorScheme)
private var colorScheme
@ObservedObject
private var model: Model
init(model: Model) {
self.model = model
}
var body: some View {
VStack(spacing: 2) {
ForEach(model.labels, id: \.icon) { label in
HStack {
Button(action: { remove(label) }) {
Image(systemSymbol: .minusCircleFill)
.foregroundStyle(.red)
}
.buttonStyle(.plain)
LabelEditingView(label: label)
}
.padding(.vertical, 2)
.padding(.horizontal, 8)
.background(colorScheme == .light ? Color.white : Color.black)
.cornerRadius(8)
}
Button("Add", action: addLabel)
.padding(.vertical, 2)
}
}
private func addLabel() {
model.labels.append(.init(icon: .clockFill, value: "Value"))
}
private func remove(_ label: ContentLabel) {
guard let index = model.labels.firstIndex(of: label) else {
return
}
model.labels.remove(at: index)
}
}

View File

@ -0,0 +1,25 @@
import SwiftUI
import SFSafeSymbols
protocol InsertableCommandView: View {
associatedtype Model: InsertableCommandModel
static var title: String { get }
static var sheetTitle: String { get }
static var icon: SFSymbol { get }
init(model: Model)
}
protocol InsertableCommandModel: ObservableObject {
var isReady: Bool { get }
var command: String? { get }
init()
}

View File

@ -1,18 +1,7 @@
import SwiftUI
import SFSafeSymbols
protocol InsertableCommand: View {
static var title: String { get }
static var sheetTitle: String { get }
static var icon: SFSymbol { get }
init(command: Binding<String?>)
}
struct InsertableCommandSheet<Presented>: View where Presented: InsertableCommand {
struct InsertableCommandSheet<Command>: View where Command: InsertableCommandView {
@Environment(\.dismiss)
var dismiss
@ -21,15 +10,19 @@ struct InsertableCommandSheet<Presented>: View where Presented: InsertableComman
private var error: String? = nil
@State
private var command: String?
private var isReady = false
init() { }
let model: Command.Model
init() {
model = .init()
}
var body: some View {
VStack {
Text(Presented.sheetTitle)
Text(Command.sheetTitle)
.font(.title)
Presented(command: $command)
Command(model: model)
if let error {
Text(error)
.foregroundStyle(.red)
@ -37,6 +30,7 @@ struct InsertableCommandSheet<Presented>: View where Presented: InsertableComman
HStack {
Button("Copy to clipboard", action: copyToClipboard)
.padding()
.disabled(!model.isReady)
Button("Cancel") {
dismiss()
}.padding()
@ -46,7 +40,7 @@ struct InsertableCommandSheet<Presented>: View where Presented: InsertableComman
}
func copyToClipboard() {
guard let command else {
guard let command = model.command else {
error = "Not all fields set"
return
}

View File

@ -1,21 +1,4 @@
import SwiftUI
import SFSafeSymbols
private struct InsertableView<Command>: View where Command: InsertableCommand {
@State
private var showSheet: Bool = false
var body: some View {
Button(action: { showSheet = true }) {
Label(Command.title, systemSymbol: Command.icon)
}
.sheet(isPresented: $showSheet) {
InsertableCommandSheet<Command>()
}
}
}
struct InsertableItemsView: View {
@ -24,6 +7,7 @@ struct InsertableItemsView: View {
Text("Commands")
.font(.headline)
InsertableView<InsertableImage>()
InsertableView<InsertableLabels>()
}
}
}

View File

@ -0,0 +1,17 @@
import SwiftUI
import SFSafeSymbols
struct InsertableView<Command>: View where Command: InsertableCommandView {
@State
private var showSheet: Bool = false
var body: some View {
Button(action: { showSheet = true }) {
Label(Command.title, systemSymbol: Command.icon)
}
.sheet(isPresented: $showSheet) {
InsertableCommandSheet<Command>()
}
}
}