Sources/Orgstar/ExportSheet.swift
57 lines · 2345 bytes
2 symbols in this file
1import AppKit
2import SwiftUI
3
4/// Export… (`app.export-dialog`): the format, where the file goes, and whether to open it after.
5struct ExportSheet: View {
6 let source: URL
7 let export: (_ format: String, _ destination: URL, _ open: Bool) -> Void
8 @AppStorage("exportFormat") private var format = "html"
9 @AppStorage("exportOpenAfter") private var openAfter = false
10 @State private var destination: URL?
11 @Environment(\.dismiss) private var dismiss
12
13 static let formats: [(id: String, title: String, ext: String)] = [
14 ("html", "HTML", "html"), ("markdown", "Markdown", "md"), ("pdf", "PDF (Emacs)", "pdf"),
15 ("odt", "ODT (Emacs)", "odt"), ("latex", "LaTeX (Emacs)", "tex"), ("text", "Plain text (Emacs)", "txt"),
16 ]
17
18 private var ext: String { Self.formats.first { $0.id == format }?.ext ?? "html" }
19 private var target: URL { destination ?? source.deletingPathExtension().appendingPathExtension(ext) }
20
21 var body: some View {
22 Form {
23 Picker("Format", selection: $format) {
24 ForEach(Self.formats, id: \.id) { Text($0.title).tag($0.id) }
25 }
26 .onChange(of: format) { destination = destination.map { $0.deletingPathExtension().appendingPathExtension(ext) } }
27 LabeledContent("Destination") {
28 HStack {
29 Text(target.path(percentEncoded: false)).lineLimit(1).truncationMode(.middle).foregroundStyle(.secondary)
30 Button("Choose…") { choose() }
31 }
32 }
33 Toggle("Open after export", isOn: $openAfter)
34 }
35 .formStyle(.grouped)
36 .safeAreaInset(edge: .bottom) {
37 HStack {
38 Spacer()
39 Button("Cancel") { dismiss() }.keyboardShortcut(.cancelAction)
40 Button("Export") {
41 export(format, target, openAfter)
42 dismiss()
43 }
44 .keyboardShortcut(.defaultAction)
45 }
46 .padding()
47 }
48 .frame(width: 520)
49 }
50
51 private func choose() {
52 let panel = NSSavePanel()
53 panel.directoryURL = target.deletingLastPathComponent()
54 panel.nameFieldStringValue = target.lastPathComponent
55 if panel.runModal() == .OK, let url = panel.url { destination = url }
56 }
57}