import Foundation import SaplingCore @MainActor public final class MarkdownDocumentSession: Identifiable, ObservableObject { public let id: UUID public let documentURL: URL public let viewModel: HybridMarkdownEditorViewModel public init( id: UUID = UUID(), documentURL: URL, viewModel: HybridMarkdownEditorViewModel ) { self.id = id self.documentURL = documentURL self.viewModel = viewModel } } @MainActor public final class DocumentSessionStore: ObservableObject { @Published public private(set) var sessions: [MarkdownDocumentSession] @Published public private(set) var activeSession: MarkdownDocumentSession? public init(sessions: [MarkdownDocumentSession] = []) { self.sessions = sessions self.activeSession = sessions.first } @discardableResult public func openDocument( at url: URL, loadDocument: @MainActor (URL) throws -> MarkdownDocument = HybridMarkdownEditorViewModel.loadDocument(at:) ) throws -> MarkdownDocumentSession { let key = sessionKey(for: url) if let existingSession = sessions.first(where: { sessionKey(for: $0.documentURL) == key }) { activeSession = existingSession return existingSession } let document = try loadDocument(url) let session = MarkdownDocumentSession( documentURL: url, viewModel: HybridMarkdownEditorViewModel(document: document) ) sessions.append(session) activeSession = session return session } @discardableResult public func activateDocument(at url: URL) -> Bool { let key = sessionKey(for: url) guard let session = sessions.first(where: { sessionKey(for: $0.documentURL) == key }) else { return false } activeSession = session return true } public func updateActiveSessionFromViewModel() { guard let activeSession else { return } objectWillChange.send() activeSession.objectWillChange.send() } private func sessionKey(for url: URL) -> String { url.standardizedFileURL.path } }