import AppKit import LChatCore import SwiftUI // ๐Ÿค– "Media, links and docs" as a real window, one per chat โ€” the spec's // "window-pushed view on Mac" (docs/superpowers/specs/ // 2026-08-05-media-links-docs-design.md ยง Native). A sheet was the first // shape and it was wrong: macOS sheets can't be resized, and this surface is // exactly the one you want to make big โ€” a screenshot full of small text is // unreadable at any fixed size. A window resizes, zooms, and goes full // screen, and the collection viewer inside it grows to match. // // LChatMacApp deliberately uses `Window` (not `WindowGroup`), so `openWindow` // isn't available: hand-rolled NSWindow + NSHostingController is the // sanctioned pattern here, same as ThreadDebugWindows. @MainActor enum MediaWindows { private static var windows: [String: NSWindow] = [:] private static var closeObservers: [String: NSObjectProtocol] = [:] static func show(instance: SavedInstance, thread: ChatThread, store: ThreadStore, model: ChatFeedModel, onJump: @escaping (Int64) -> Void) { let key = "\(instance.origin)|\(thread.id)" if let w = windows[key] { w.makeKeyAndOrderFront(nil) return } let view = MediaLinksDocsSheet(instance: instance, thread: thread, store: store, model: model, onJump: { sid in close(key) onJump(sid) }) let w = NSWindow(contentViewController: NSHostingController(rootView: view)) w.title = "Media, links and docs" w.subtitle = thread.title w.setContentSize(NSSize(width: 820, height: 660)) // The dict keeps the window alive; releasedWhenClosed would have // AppKit deallocate it under us on close. w.isReleasedWhenClosed = false windows[key] = w closeObservers[key] = NotificationCenter.default.addObserver( forName: NSWindow.willCloseNotification, object: w, queue: .main ) { _ in Task { @MainActor in windows[key] = nil if let o = closeObservers.removeValue(forKey: key) { NotificationCenter.default.removeObserver(o) } } } w.center() w.makeKeyAndOrderFront(nil) } private static func close(_ key: String) { windows[key]?.close() } }