Open multiple documents per markdown file

This commit is contained in:
0x8664b2
2025-06-20 09:58:53 -07:00
parent e17eba0a1b
commit a921131ea7
2 changed files with 102 additions and 71 deletions

View File

@@ -1,77 +1,34 @@
import SwiftUI import SwiftUI
import UniformTypeIdentifiers
import AppKit
struct ContentView: View { struct ContentView: View {
@State private var selectedFileURL: URL?
@State private var markdownContent: String = ""
var body: some View { var body: some View {
NavigationSplitView {
VStack {
Button("Open Markdown File") {
openFile()
}
.padding()
if let url = selectedFileURL {
Text("File: \(url.lastPathComponent)")
.foregroundColor(.secondary)
.font(.caption)
.truncationMode(.middle)
.padding(.horizontal)
}
Spacer()
}
.frame(minWidth: 200)
.navigationSplitViewColumnWidth(min: 200, ideal: 250)
} detail: {
if !markdownContent.isEmpty {
MarkdownRenderer(content: markdownContent)
.onAppear {
print("MarkdownRenderer appeared with content length: \(markdownContent.count)")
}
} else {
VStack { VStack {
Image(systemName: "doc.text") Image(systemName: "doc.text")
.font(.system(size: 60)) .font(.system(size: 80))
.foregroundColor(.secondary) .foregroundColor(.secondary)
Text("Select a markdown file to preview") Text("Markdown Viewer")
.font(.largeTitle)
.fontWeight(.medium)
Text("Open markdown files from the File menu")
.foregroundColor(.secondary) .foregroundColor(.secondary)
.padding() .padding(.top, 8)
Text("⌘O")
.foregroundColor(.secondary)
.font(.caption)
.padding(.top, 4)
} }
.frame(maxWidth: .infinity, maxHeight: .infinity) .frame(maxWidth: .infinity, maxHeight: .infinity)
} }
} }
.navigationTitle("Markdown Viewer")
}
private func openFile() { struct MarkdownDocumentView: View {
let panel = NSOpenPanel() let content: String
panel.allowsMultipleSelection = false let fileName: String
panel.canChooseDirectories = false
panel.canChooseFiles = true
panel.allowedContentTypes = [UTType.plainText, UTType(filenameExtension: "md")!]
if panel.runModal() == .OK { var body: some View {
if let url = panel.url { MarkdownRenderer(content: content)
selectedFileURL = url .navigationTitle(fileName)
loadMarkdownFile(from: url) .frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
}
private func loadMarkdownFile(from url: URL) {
do {
let content = try String(contentsOf: url, encoding: .utf8)
print("File loaded successfully, content length: \(content.count)")
print("First 100 characters: \(String(content.prefix(100)))")
markdownContent = content
} catch {
print("Error reading file: \(error)")
markdownContent = "Error loading file: \(error.localizedDescription)"
}
} }
} }

View File

@@ -1,10 +1,84 @@
import SwiftUI import SwiftUI
import UniformTypeIdentifiers
import AppKit
@main @main
struct MarkdownViewerApp: App { struct MarkdownViewerApp: App {
var body: some Scene { var body: some Scene {
WindowGroup { Settings {
ContentView() EmptyView()
}
.commands {
CommandGroup(replacing: .newItem) {
Button("Open Markdown File...") {
openMarkdownFile()
}
.keyboardShortcut("o", modifiers: .command)
}
}
}
private func openMarkdownFile() {
let panel = NSOpenPanel()
panel.allowsMultipleSelection = true
panel.canChooseDirectories = false
panel.canChooseFiles = true
panel.allowedContentTypes = [UTType.plainText, UTType(filenameExtension: "md")!]
if panel.runModal() == .OK {
for url in panel.urls {
openNewWindow(for: url)
}
}
}
private func openNewWindow(for url: URL) {
do {
let content = try String(contentsOf: url, encoding: .utf8)
let newWindow = NSWindow(
contentRect: NSRect(x: 0, y: 0, width: 800, height: 600),
styleMask: [.titled, .closable, .resizable, .miniaturizable],
backing: .buffered,
defer: false
)
newWindow.title = url.lastPathComponent
newWindow.contentView = NSHostingView(
rootView: MarkdownDocumentView(
content: content,
fileName: url.lastPathComponent
)
)
newWindow.center()
newWindow.makeKeyAndOrderFront(nil)
} catch {
print("Error reading file: \(error)")
// Show error in a new window
let newWindow = NSWindow(
contentRect: NSRect(x: 0, y: 0, width: 400, height: 200),
styleMask: [.titled, .closable],
backing: .buffered,
defer: false
)
newWindow.title = "Error"
newWindow.contentView = NSHostingView(
rootView: VStack {
Image(systemName: "exclamationmark.triangle")
.font(.system(size: 40))
.foregroundColor(.red)
Text("Error loading file")
.font(.headline)
Text(error.localizedDescription)
.font(.caption)
.foregroundColor(.secondary)
.multilineTextAlignment(.center)
}
.padding()
)
newWindow.center()
newWindow.makeKeyAndOrderFront(nil)
} }
} }
} }