import SwiftUI import UniformTypeIdentifiers import AppKit @main struct MarkdownViewerApp: App { @StateObject private var recentFilesManager = RecentFilesManager.shared var body: some Scene { Settings { EmptyView() } .commands { CommandGroup(replacing: .newItem) { Button("Open Markdown File...") { openMarkdownFile() } .keyboardShortcut("o", modifiers: .command) Divider() Menu("Recent Files") { if recentFilesManager.recentFiles.isEmpty { Text("No Recent Files") .disabled(true) } else { ForEach(recentFilesManager.recentFiles, id: \.self) { url in Button(action: { openRecentFile(url) }) { VStack(alignment: .leading) { Text(recentFilesManager.getDisplayName(for: url)) Text(recentFilesManager.getRelativePath(for: url)) .font(.caption) .foregroundColor(.secondary) } } } Divider() Button("Clear Recent Files") { recentFilesManager.clearRecentFiles() } } } } } } 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 openRecentFile(_ url: URL) { // Check if file still exists guard FileManager.default.fileExists(atPath: url.path) else { recentFilesManager.removeRecentFile(url) showErrorWindow(message: "File no longer exists", details: url.path) return } openNewWindow(for: url) } private func openNewWindow(for url: URL) { do { let content = try String(contentsOf: url, encoding: .utf8) // Add to recent files recentFilesManager.addRecentFile(url) 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)") showErrorWindow(message: "Error loading file", details: error.localizedDescription) } } private func showErrorWindow(message: String, details: String) { 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(message) .font(.headline) Text(details) .font(.caption) .foregroundColor(.secondary) .multilineTextAlignment(.center) } .padding() ) newWindow.center() newWindow.makeKeyAndOrderFront(nil) } }