diff options
Diffstat (limited to 'menubar')
| -rw-r--r-- | menubar/main.swift | 24 | ||||
| -rw-r--r-- | menubar/model.swift | 31 |
2 files changed, 55 insertions, 0 deletions
diff --git a/menubar/main.swift b/menubar/main.swift index 2230817..82931ab 100644 --- a/menubar/main.swift +++ b/menubar/main.swift @@ -236,6 +236,16 @@ final class Menubar: NSObject, NSApplicationDelegate, NSMenuDelegate { refresh() } + /// Reload the agents on an old extension: those that can now, the + /// others as they become idle and leave the screen (the daemon's job). + @objc private func reloadOutdated() { + log("reload agents: requested") + DispatchQueue.global().async { + let result = runReporting(dinggerBinary, ["reload-agents"]) + log("reload agents: \(result.ok ? "" : "failed: ")\(result.output.replacingOccurrences(of: "\n", with: "; "))") + } + } + @objc private func restoreFromMenu(_ sender: NSMenuItem) { restore(sessions: (sender.representedObject as? String).map { [$0] } ?? []) } @@ -304,6 +314,16 @@ final class Menubar: NSObject, NSApplicationDelegate, NSMenuDelegate { menu.addItem(item) menu.addItem(.separator()) } + let outdated = fetchOutdated() + if !outdated.isEmpty { + let item = NSMenuItem(title: "⟳ \(outdated.title)", action: outdated.canReload ? #selector(reloadOutdated) : nil, + keyEquivalent: "") + item.target = self + item.isEnabled = outdated.canReload + item.subtitle = outdated.detail + menu.addItem(item) + menu.addItem(.separator()) + } if rows.isEmpty { let none = NSMenuItem(title: "No agents", action: nil, keyEquivalent: "") none.isEnabled = false @@ -443,6 +463,10 @@ if arguments.contains("--selftest") { if arguments.contains("--print") { let rows = fetchRows() print("title: \(plainTitle(for: rows))") + let outdated = fetchOutdated() + if !outdated.isEmpty { + print("⟳ \(outdated.title)\t\(outdated.detail)\(outdated.canReload ? "" : "\t(disabled)")") + } for row in rows { print("\(row.status.symbol) \(row.status.rawValue)\t\(row.markedLabel)\t\(row.subtitle)") } diff --git a/menubar/model.swift b/menubar/model.swift index f0f977e..e4d179c 100644 --- a/menubar/model.swift +++ b/menubar/model.swift @@ -230,6 +230,37 @@ func fetchRestoreOffer() -> RestoreOffer? { return try? JSONDecoder().decode(RestoreOffer.self, from: data) } +// MARK: agents on an old extension + +/// pi agents on an old dingger extension, as the daemon counts them: +/// `@dingger_outdated` it can reload, `@dingger_outdated_by_hand` it cannot +/// (an extension from before reloads). +struct OutdatedAgents: Equatable { + let reloadable: Int + let byHand: Int + + var isEmpty: Bool { reloadable == 0 && byHand == 0 } + var canReload: Bool { reloadable > 0 } + + private func agents(_ n: Int) -> String { "\(n) \(n == 1 ? "Agent" : "Agents")" } + + /// "Reload 3 Agents on an Old Extension", or "2 Agents Need /reload". + var title: String { + canReload ? "Reload \(agents(reloadable)) on an Old Extension" : "\(agents(byHand)) \(byHand == 1 ? "Needs" : "Need") /reload" + } + + var detail: String { + guard canReload else { return "their dingger extension is too old to reload them" } + let when = "each when idle and off screen" + return byHand > 0 ? "\(when) · \(byHand) more need /reload" : when + } +} + +func fetchOutdated() -> OutdatedAgents { + let count = { (name: String) in Int(tmux(["show-options", "-gv", name])?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "") ?? 0 } + return OutdatedAgents(reloadable: count("@dingger_outdated"), byHand: count("@dingger_outdated_by_hand")) +} + /// Run `dingger <args>` through the user's login shell, the way a terminal /// starts tmux: restored panes inherit this environment (PATH, LANG), and /// launchd's is bare. DINGGER_RESTORE_DIRECT runs it directly (tests). |
