#!/usr/bin/env python3 from pathlib import Path from datetime import datetime import shutil root = Path.cwd() controller = root / 'OrionToolbar/OrionVMController.swift' view = root / 'OrionToolbar/OrionMenuView.swift' if not controller.exists() or not view.exists(): raise SystemExit('Run from the OrionToolbar project root. No changes made.') c = controller.read_text() v = view.read_text() # Verify all expected anchors before writing anything. checks = [ (c, 'await discoverVMs()\n await refreshAll()', 1), (c, 'await self.discoverVMs(); await self.refreshAll()', 1), (c, 'func refreshServiceAvailability() async {', 1), (c, 'func openSSH(_ s: ServerDefinition) {', 1), (c, 'func openMailpit(_ s: ServerDefinition) { if let p = s.mailpitPort, let url = URL(string: "http://\\(s.host):\\(p)") { NSWorkspace.shared.open(url) } }', 1), (v, 'if !server.host.isEmpty && !server.sshUser.isEmpty {', 2), (v, 'if !server.host.isEmpty && server.mailpitPort != nil {', 2), ] for src, anchor, count in checks: if src.count(anchor) != count: raise SystemExit(f'Expected {count} occurrence(s) of {anchor!r}, found {src.count(anchor)}. No changes made.') c = c.replace('await discoverVMs()\n await refreshAll()', 'await discoverVMs()\n await refreshAll()\n await refreshServiceAvailability()', 1) c = c.replace('await self.discoverVMs(); await self.refreshAll()', 'await self.discoverVMs(); await self.refreshAll(); await self.refreshServiceAvailability()', 1) # Dismiss the menu bar panel before activating external apps. This must happen # at the click site; delayed activation alone leaves the panel in front. helper = ''' private func dismissMenuPanelAndActivate(_ application: NSRunningApplication?) { NSApp.keyWindow?.orderOut(nil) DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { application?.activate(options: [.activateAllWindows]) } } ''' if 'private func dismissMenuPanelAndActivate(' not in c: c = c.replace(' func openSSH(_ s: ServerDefinition) {', helper + ' func openSSH(_ s: ServerDefinition) {', 1) old = ''' NSWorkspace.shared.open([scriptURL], withApplicationAt: terminalURL, configuration: configuration) { _, error in Task { @MainActor in if let error { self.lastError = "Could not open Terminal: \\(error.localizedDescription)" } } }''' new = ''' NSApp.keyWindow?.orderOut(nil) NSWorkspace.shared.open([scriptURL], withApplicationAt: terminalURL, configuration: configuration) { app, error in Task { @MainActor in if let error { self.lastError = "Could not open Terminal: \\(error.localizedDescription)" } else { self.dismissMenuPanelAndActivate(app) } } }''' if c.count(old) != 1: raise SystemExit('SSH open completion differs from expected. No changes made.') c = c.replace(old, new, 1) old_mail = ' func openMailpit(_ s: ServerDefinition) { if let p = s.mailpitPort, let url = URL(string: "http://\\(s.host):\\(p)") { NSWorkspace.shared.open(url) } }' new_mail = ''' func openMailpit(_ s: ServerDefinition) { guard let port = s.mailpitPort, let url = URL(string: "http://\\(s.host):\\(port)") else { return } NSApp.keyWindow?.orderOut(nil) NSWorkspace.shared.open(url) DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) { if let browser = NSWorkspace.shared.frontmostApplication, browser.bundleIdentifier != Bundle.main.bundleIdentifier { browser.activate(options: [.activateAllWindows]) } } }''' c = c.replace(old_mail, new_mail, 1) v = v.replace('if !server.host.isEmpty && !server.sshUser.isEmpty {', 'if !server.host.isEmpty && !server.sshUser.isEmpty && vm.reachableSSH.contains(server.id) {') v = v.replace('if !server.host.isEmpty && server.mailpitPort != nil {', 'if !server.host.isEmpty && server.mailpitPort != nil && vm.reachableMailpit.contains(server.id) {') backup = root / 'backups' / ('service-foreground-' + datetime.now().strftime('%Y%m%d-%H%M%S')) for path, content in [(controller, c), (view, v)]: dest = backup / path.relative_to(root) dest.parent.mkdir(parents=True, exist_ok=True) shutil.copy2(path, dest) path.write_text(content) print('Updated:', path.relative_to(root)) print('Backup:', backup)