First button with command shortcut
This commit is contained in:
55
CHDataManagement/Views/Pages/Commands/Insert+Image.swift
Normal file
55
CHDataManagement/Views/Pages/Commands/Insert+Image.swift
Normal file
@ -0,0 +1,55 @@
|
||||
import SwiftUI
|
||||
import SFSafeSymbols
|
||||
|
||||
struct InsertableImage: View, InsertableCommand {
|
||||
|
||||
static let title = "Image"
|
||||
|
||||
static let sheetTitle = "Insert image"
|
||||
|
||||
static let icon: SFSymbol = .photo
|
||||
|
||||
@State
|
||||
private var selectedImage: FileResource?
|
||||
|
||||
@State
|
||||
private var caption: String? = ""
|
||||
|
||||
@Binding
|
||||
private var command: String?
|
||||
|
||||
init(command: Binding<String?>) {
|
||||
self._command = command
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
FilePropertyView(
|
||||
title: "Image",
|
||||
footer: "Select the image to insert",
|
||||
selectedFile: $selectedImage,
|
||||
allowedType: .image)
|
||||
OptionalStringPropertyView(
|
||||
title: "Caption",
|
||||
text: $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 ")"
|
||||
}
|
||||
return ";\(caption))"
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
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 {
|
||||
|
||||
@Environment(\.dismiss)
|
||||
var dismiss
|
||||
|
||||
@State
|
||||
private var error: String? = nil
|
||||
|
||||
@State
|
||||
private var command: String?
|
||||
|
||||
init() { }
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
Text(Presented.sheetTitle)
|
||||
.font(.title)
|
||||
Presented(command: $command)
|
||||
if let error {
|
||||
Text(error)
|
||||
.foregroundStyle(.red)
|
||||
}
|
||||
HStack {
|
||||
Button("Copy to clipboard", action: copyToClipboard)
|
||||
.padding()
|
||||
Button("Cancel") {
|
||||
dismiss()
|
||||
}.padding()
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
|
||||
func copyToClipboard() {
|
||||
guard let command else {
|
||||
error = "Not all fields set"
|
||||
return
|
||||
}
|
||||
defer { dismiss() }
|
||||
|
||||
let pasteboard = NSPasteboard.general
|
||||
pasteboard.clearContents()
|
||||
pasteboard.setString(command, forType: .string)
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
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 {
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
Text("Commands")
|
||||
.font(.headline)
|
||||
InsertableView<InsertableImage>()
|
||||
}
|
||||
}
|
||||
}
|
@ -53,6 +53,7 @@ struct LocalizedPageContentView: View {
|
||||
text: "\(linkingPosts.count) linking posts",
|
||||
items: linkingPosts.map { $0.title(in: language) })
|
||||
}.foregroundStyle(.secondary)
|
||||
InsertableItemsView()
|
||||
HighlightedTextEditor(
|
||||
text: $pageContent,
|
||||
highlightRules: .markdown)
|
||||
|
Reference in New Issue
Block a user