From 200fdc813d834d042b6c389e15f0275f76f4820b Mon Sep 17 00:00:00 2001 From: Christoph Hagen Date: Fri, 24 Jan 2025 22:47:54 +0100 Subject: [PATCH] First button with command shortcut --- CHDataManagement.xcodeproj/project.pbxproj | 20 +++++++ .../Views/Pages/Commands/Insert+Image.swift | 55 +++++++++++++++++ .../Commands/InsertableCommandSheet.swift | 59 +++++++++++++++++++ .../Pages/Commands/InsertableItemsView.swift | 29 +++++++++ .../Pages/LocalizedPageContentView.swift | 1 + 5 files changed, 164 insertions(+) create mode 100644 CHDataManagement/Views/Pages/Commands/Insert+Image.swift create mode 100644 CHDataManagement/Views/Pages/Commands/InsertableCommandSheet.swift create mode 100644 CHDataManagement/Views/Pages/Commands/InsertableItemsView.swift diff --git a/CHDataManagement.xcodeproj/project.pbxproj b/CHDataManagement.xcodeproj/project.pbxproj index f2c6647..8ffcf60 100644 --- a/CHDataManagement.xcodeproj/project.pbxproj +++ b/CHDataManagement.xcodeproj/project.pbxproj @@ -188,6 +188,9 @@ E2FD1D302D37196C00B48627 /* GeneralSettingsDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FD1D2F2D37196500B48627 /* GeneralSettingsDetailView.swift */; }; E2FD1D322D3AEB6300B48627 /* PostVideo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FD1D312D3AEB6000B48627 /* PostVideo.swift */; }; E2FD1D342D3BA2E700B48627 /* SelectedContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FD1D332D3BA2DE00B48627 /* SelectedContent.swift */; }; + E2FD1D372D3BBCCA00B48627 /* Insert+Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FD1D362D3BBCB500B48627 /* Insert+Image.swift */; }; + E2FD1D392D3BBED300B48627 /* InsertableItemsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FD1D382D3BBECA00B48627 /* InsertableItemsView.swift */; }; + E2FD1D3B2D3BC40500B48627 /* InsertableCommandSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FD1D3A2D3BC40500B48627 /* InsertableCommandSheet.swift */; }; E2FE0EE62D15A0B5002963B7 /* GenerationResults.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FE0EE52D15A0B1002963B7 /* GenerationResults.swift */; }; E2FE0EE82D16D4A3002963B7 /* ConvertThrowing.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FE0EE72D16D4A3002963B7 /* ConvertThrowing.swift */; }; E2FE0EEC2D1C1253002963B7 /* MultiFileSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FE0EEB2D1C124E002963B7 /* MultiFileSelectionView.swift */; }; @@ -422,6 +425,9 @@ E2FD1D2F2D37196500B48627 /* GeneralSettingsDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralSettingsDetailView.swift; sourceTree = ""; }; E2FD1D312D3AEB6000B48627 /* PostVideo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostVideo.swift; sourceTree = ""; }; E2FD1D332D3BA2DE00B48627 /* SelectedContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectedContent.swift; sourceTree = ""; }; + E2FD1D362D3BBCB500B48627 /* Insert+Image.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Insert+Image.swift"; sourceTree = ""; }; + E2FD1D382D3BBECA00B48627 /* InsertableItemsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InsertableItemsView.swift; sourceTree = ""; }; + E2FD1D3A2D3BC40500B48627 /* InsertableCommandSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InsertableCommandSheet.swift; sourceTree = ""; }; E2FE0EE52D15A0B1002963B7 /* GenerationResults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenerationResults.swift; sourceTree = ""; }; E2FE0EE72D16D4A3002963B7 /* ConvertThrowing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConvertThrowing.swift; sourceTree = ""; }; E2FE0EEB2D1C124E002963B7 /* MultiFileSelectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiFileSelectionView.swift; sourceTree = ""; }; @@ -629,6 +635,7 @@ E2A21C322CB5BCAC0060935B /* Pages */ = { isa = PBXGroup; children = ( + E2FD1D352D3BBCAF00B48627 /* Commands */, E29D31782D083DDA0051B7F4 /* PageContentResultsView.swift */, E2A37D242CEBD7A10000979F /* PageListView.swift */, E2A21C312CB5BCAC0060935B /* PageContentView.swift */, @@ -887,6 +894,16 @@ path = Loading; sourceTree = ""; }; + E2FD1D352D3BBCAF00B48627 /* Commands */ = { + isa = PBXGroup; + children = ( + E2FD1D3A2D3BC40500B48627 /* InsertableCommandSheet.swift */, + E2FD1D362D3BBCB500B48627 /* Insert+Image.swift */, + E2FD1D382D3BBECA00B48627 /* InsertableItemsView.swift */, + ); + path = Commands; + sourceTree = ""; + }; E2FE0F072D2689DC002963B7 /* Post Lists */ = { isa = PBXGroup; children = ( @@ -1183,6 +1200,7 @@ E2FE0F422D2B4821002963B7 /* OtherCodeBlock.swift in Sources */, E21850332CFAFA2F0090B18B /* Settings.swift in Sources */, E29D31892D0AED1F0051B7F4 /* ModelViewer.swift in Sources */, + E2FD1D392D3BBED300B48627 /* InsertableItemsView.swift in Sources */, E29D31412D04887F0051B7F4 /* SelectedDetailView.swift in Sources */, E29D31A32D0CC98C0051B7F4 /* Item.swift in Sources */, E25DA57A2D01C64400AEF16D /* PageContentGenerator.swift in Sources */, @@ -1221,6 +1239,7 @@ E2FE0F572D2BCFD4002963B7 /* BlockLineProcessor.swift in Sources */, E229904A2D10BB90009F8D77 /* SecurityScopeBookmark.swift in Sources */, E29D314B2D04FC950051B7F4 /* FileToAdd.swift in Sources */, + E2FD1D3B2D3BC40500B48627 /* InsertableCommandSheet.swift in Sources */, E2E06DFB2CA4A65E0019C2AF /* Content.swift in Sources */, E29D31B52D0DA8490051B7F4 /* PageIcon.swift in Sources */, E2FE0F332D2B2665002963B7 /* AudioBlock.swift in Sources */, @@ -1257,6 +1276,7 @@ E22990202D0ECBE5009F8D77 /* TagOverviewDetailView.swift in Sources */, E29D31C02D0DB9F20051B7F4 /* AudioPlayerContent.swift in Sources */, E22990192D0E3546009F8D77 /* ItemReference.swift in Sources */, + E2FD1D372D3BBCCA00B48627 /* Insert+Image.swift in Sources */, E25DA51F2CFF15C400AEF16D /* NavigationBar.swift in Sources */, E2FE0F0F2D268D4F002963B7 /* BoxCommand.swift in Sources */, E22990482D10B7B7009F8D77 /* StorageAccessError.swift in Sources */, diff --git a/CHDataManagement/Views/Pages/Commands/Insert+Image.swift b/CHDataManagement/Views/Pages/Commands/Insert+Image.swift new file mode 100644 index 0000000..b329da7 --- /dev/null +++ b/CHDataManagement/Views/Pages/Commands/Insert+Image.swift @@ -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) { + 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 "![image](\(selectedImage.id))" + } + return "![image](\(selectedImage.id);\(caption))" + } +} diff --git a/CHDataManagement/Views/Pages/Commands/InsertableCommandSheet.swift b/CHDataManagement/Views/Pages/Commands/InsertableCommandSheet.swift new file mode 100644 index 0000000..6e34a00 --- /dev/null +++ b/CHDataManagement/Views/Pages/Commands/InsertableCommandSheet.swift @@ -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) +} + +struct InsertableCommandSheet: 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) + } +} diff --git a/CHDataManagement/Views/Pages/Commands/InsertableItemsView.swift b/CHDataManagement/Views/Pages/Commands/InsertableItemsView.swift new file mode 100644 index 0000000..a70ef91 --- /dev/null +++ b/CHDataManagement/Views/Pages/Commands/InsertableItemsView.swift @@ -0,0 +1,29 @@ +import SwiftUI +import SFSafeSymbols + +private struct InsertableView: 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() + } + } + +} + +struct InsertableItemsView: View { + + var body: some View { + HStack { + Text("Commands") + .font(.headline) + InsertableView() + } + } +} diff --git a/CHDataManagement/Views/Pages/LocalizedPageContentView.swift b/CHDataManagement/Views/Pages/LocalizedPageContentView.swift index 49ad6db..3073be4 100644 --- a/CHDataManagement/Views/Pages/LocalizedPageContentView.swift +++ b/CHDataManagement/Views/Pages/LocalizedPageContentView.swift @@ -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)