From eebd582b3e71baeed864fe4f8a9dd216efeb438c Mon Sep 17 00:00:00 2001 From: Andrew Blakeslee Moore Date: Wed, 8 Jul 2026 05:12:18 -0700 Subject: [PATCH] Add App Bundle Integration Nucleic-Session: 307EEE49-F1A9-4AF7-B2C1-72C8473CD6B4 Co-authored-by: Nucleic --- Sources/NucleicApp/SettingsView.swift | 30 ++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/Sources/NucleicApp/SettingsView.swift b/Sources/NucleicApp/SettingsView.swift index 2e5027f5..b9cae1a3 100644 --- a/Sources/NucleicApp/SettingsView.swift +++ b/Sources/NucleicApp/SettingsView.swift @@ -694,22 +694,38 @@ private struct MacVMSettingsTab: View { } isTargeted: { appDropTargeted = $0 } if let baseStatus, baseStatus.installed { - Text("Rebuild / re-provision the base image above to apply changes to the " - + "already-installed base — or copy them straight into any running VMs below.") + Button { + Task { await addAppsToBase() } + } label: { + HStack(spacing: 6) { + if addingToBase { ProgressView().controlSize(.small) } + Label("Add to base image", systemImage: "square.and.arrow.down.on.square") + } + } + .disabled(addingToBase || building || deleting || bundledApps.isEmpty) + Text("Adds the apps above to the existing base image without a full rebuild: boots " + + "the base briefly, copies them into its Applications folder, and powers it " + + "off. New session VMs then include them. (Takes a minute or two.)") .settingsCaption() + if let baseAddStatus { + Text(baseAddStatus).font(.caption).foregroundStyle(.secondary) + } } if !runningVMs.isEmpty { Button { Task { await pushAppsToRunningVMs() } } label: { - Label( - "Copy to \(runningVMs.count) running VM\(runningVMs.count == 1 ? "" : "s")", - systemImage: "arrow.down.app") + HStack(spacing: 6) { + if pushingApps { ProgressView().controlSize(.small) } + Label( + "Copy to \(runningVMs.count) running VM\(runningVMs.count == 1 ? "" : "s")", + systemImage: "arrow.down.app") + } } .disabled(pushingApps || bundledApps.isEmpty) - Text("Streams the apps above into each running VM's Applications folder over the " - + "guest agent (no rebuild, no restart). Existing copies are replaced.") + Text("Also streams the apps into each already-running VM's Applications folder over " + + "the guest agent (no restart). Existing copies are replaced.") .settingsCaption() if let appPushStatus { Text(appPushStatus).font(.caption).foregroundStyle(.secondary)