import SwiftUI import AppKit @MainActor final class ComposeModel: ObservableObject { @Published var projectName = "" @Published var projectURL: URL? @Published var services: [ComposeService] = [] @Published var selectedService: String? @Published var status = "Ready" @Published var busy = false @Published var output = "Open a compose.yaml file to begin.\n" func openProject() { let panel = NSOpenPanel() panel.allowedContentTypes = [.yaml, .init(filenameExtension: "yml")!] panel.canChooseDirectories = false if panel.runModal() == .OK, let url = panel.url { load(url) } } func load(_ url: URL) { do { let project = try ComposeProject(file: url) projectName = project.name projectURL = url; services = project.services selectedService = services.first?.id output += "Loaded \(url.path) (\(services.count) services)\n" } catch { output += "ERROR: \(error)\n" } } func clearLog() { output = "" } func checkRuntime() { guard let url = projectURL else { output += "Open a Compose project first.\n"; return } run(url: url, action: "doctor") } func perform(_ action: String) { guard let url = projectURL else { return } run(url: url, action: action) } private func run(url: URL, action: String) { guard !busy else { return } guard !CommandLine.arguments.contains("--demo") else { output += "Demo mode is read-only. Relaunch normally to run Compose actions.\n"; return } busy = true; status = "Running \(action)…"; output += "\n$ container-compose \(action)\n" Task.detached { let result: String do { result = try ComposeEngine(ComposeProject(file: url)).execute(action) } catch { result = "ERROR: \(error)\n" } await MainActor.run { self.output += result + "\n" self.busy = false; self.status = "Ready" } } } }