Skip to content

Commit 2b22bbe

Browse files
committed
Multi-installation discovery + switching
1 parent 7253510 commit 2b22bbe

5 files changed

Lines changed: 213 additions & 20 deletions

File tree

AppDelegate.swift

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@ class AppDelegate: NSObject, NSApplicationDelegate {
1919
// MARK: - Component Managers
2020
private let mistServerManager = MistServerManager.shared
2121

22+
/// Re-detect all installations and resolve active mode
23+
func redetectServerMode() {
24+
let installations = mistServerManager.detectAllInstallations()
25+
let preference = mistServerManager.loadPreferredInstallation()
26+
appState.discoveredInstallations = installations
27+
appState.serverMode = mistServerManager.resolveActiveMode(
28+
installations: installations, preference: preference)
29+
}
30+
2231
override init() {
2332
super.init()
2433
}
@@ -37,8 +46,12 @@ class AppDelegate: NSObject, NSApplicationDelegate {
3746
// 1) Create the menu bar icon
3847
setupStatusBarIcon()
3948

40-
// 2) Detect server mode and running state
41-
appState.serverMode = mistServerManager.detectServerMode()
49+
// 2) Detect server installations and resolve active mode
50+
let installations = mistServerManager.detectAllInstallations()
51+
let preference = mistServerManager.loadPreferredInstallation()
52+
appState.discoveredInstallations = installations
53+
appState.serverMode = mistServerManager.resolveActiveMode(
54+
installations: installations, preference: preference)
4255
appState.serverRunning = mistServerManager.isMistServerRunning(mode: appState.serverMode)
4356

4457
// 3) Initial data refresh with auth check (capabilities included in main fetch)
@@ -55,11 +68,15 @@ class AppDelegate: NSObject, NSApplicationDelegate {
5568
// 5) Schedule regular data updates (every 10 seconds)
5669
activeStreamsTimer = Timer.scheduledTimer(withTimeInterval: 10, repeats: true) { [weak self] _ in
5770
guard let self = self else { return }
58-
// Re-detect mode on background queue to avoid blocking main thread
71+
// Re-detect installations on background queue to avoid blocking main thread
5972
DispatchQueue.global(qos: .utility).async {
60-
let mode = self.mistServerManager.detectServerMode()
73+
let installations = self.mistServerManager.detectAllInstallations()
74+
let preference = self.mistServerManager.loadPreferredInstallation()
75+
let mode = self.mistServerManager.resolveActiveMode(
76+
installations: installations, preference: preference)
6177
let running = self.mistServerManager.isMistServerRunning(mode: mode)
6278
DispatchQueue.main.async {
79+
self.appState.discoveredInstallations = installations
6380
self.appState.serverMode = mode
6481
self.appState.serverRunning = running
6582
if running {
@@ -283,7 +300,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
283300
self?.appState.serverRunning = !success
284301
if success {
285302
// Re-detect mode after stopping
286-
self?.appState.serverMode = self?.mistServerManager.detectServerMode() ?? .notFound
303+
self?.redetectServerMode()
287304
}
288305
}
289306
}
@@ -302,7 +319,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
302319
DispatchQueue.main.async {
303320
self?.appState.serverRunning = success
304321
if success {
305-
self?.appState.serverMode = self?.mistServerManager.detectServerMode() ?? mode
322+
self?.redetectServerMode()
306323
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
307324
self?.checkAuthAndRefresh()
308325
}

AppState.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class AppState {
1313
var needsAuth = false
1414
var authError: String?
1515
var serverMode: ServerMode = .notFound
16+
var discoveredInstallations: [MistInstallation] = []
1617

1718
var serverURL: String = UserDefaults.standard.string(forKey: "ServerURL") ?? "http://localhost:4242" {
1819
didSet {

DashboardView.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,9 @@ struct DashboardView: View {
383383
appState.serverRunning = !success
384384
appState.isTogglingServer = false
385385
if success {
386-
appState.serverMode = manager.detectServerMode()
386+
if let appDelegate = NSApp.delegate as? AppDelegate {
387+
appDelegate.redetectServerMode()
388+
}
387389
}
388390
}
389391
}
@@ -404,7 +406,9 @@ struct DashboardView: View {
404406
appState.serverRunning = success
405407
appState.isTogglingServer = false
406408
if success {
407-
appState.serverMode = manager.detectServerMode()
409+
if let appDelegate = NSApp.delegate as? AppDelegate {
410+
appDelegate.redetectServerMode()
411+
}
408412
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
409413
refreshData()
410414
}

DetailViews.swift

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1623,14 +1623,40 @@ struct SettingsView: View {
16231623
.onChange(of: showNotifications) { hasChanges = true }
16241624
}
16251625

1626-
Section {
1627-
HStack {
1628-
Text("Mode:")
1629-
.foregroundStyle(.secondary)
1630-
Text(appState.serverMode.description)
1626+
if appState.discoveredInstallations.count > 1 {
1627+
Section("Server Installation") {
1628+
Picker("Active Installation", selection: Binding(
1629+
get: {
1630+
MistServerManager.shared.loadPreferredInstallation()
1631+
?? appState.discoveredInstallations.first?.key ?? ""
1632+
},
1633+
set: { newKey in
1634+
MistServerManager.shared.savePreferredInstallation(newKey)
1635+
let installations = MistServerManager.shared.detectAllInstallations()
1636+
appState.discoveredInstallations = installations
1637+
appState.serverMode = MistServerManager.shared.resolveActiveMode(
1638+
installations: installations, preference: newKey)
1639+
}
1640+
)) {
1641+
ForEach(appState.discoveredInstallations) { install in
1642+
Text(install.label).tag(install.key)
1643+
}
1644+
}
1645+
.pickerStyle(.inline)
1646+
.font(.caption)
16311647
}
1632-
.font(.caption)
1648+
} else {
1649+
Section("Server Installation") {
1650+
HStack {
1651+
Text("Mode:")
1652+
.foregroundStyle(.secondary)
1653+
Text(appState.serverMode.description)
1654+
}
1655+
.font(.caption)
1656+
}
1657+
}
16331658

1659+
Section {
16341660
VStack(alignment: .leading, spacing: 4) {
16351661
Text("Custom Binary Path")
16361662
.font(.caption.weight(.medium))
@@ -1746,8 +1772,12 @@ struct SettingsView: View {
17461772
UserDefaults.standard.set(customBinaryPath.trimmed, forKey: "CustomBinaryPath")
17471773
UserDefaults.standard.set(customConfigPath.trimmed, forKey: "CustomConfigPath")
17481774
hasChanges = false
1749-
// Re-detect mode after path changes
1750-
appState.serverMode = MistServerManager.shared.detectServerMode()
1775+
// Re-detect installations after path changes
1776+
let installations = MistServerManager.shared.detectAllInstallations()
1777+
let preference = MistServerManager.shared.loadPreferredInstallation()
1778+
appState.discoveredInstallations = installations
1779+
appState.serverMode = MistServerManager.shared.resolveActiveMode(
1780+
installations: installations, preference: preference)
17511781
}
17521782

17531783
private func browseForBinary() {

0 commit comments

Comments
 (0)