From 9c9c9dad93b16781ec2fc40bd7582db62240171c Mon Sep 17 00:00:00 2001 From: Igor Soarez Date: Fri, 23 Oct 2026 13:59:59 +0300 Subject: restore, step 3: offer it in the panel, menu, and status line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit when tmux stops (and its sessions are missing from the running server, or no server runs), the daemon publishes the restore offer: offer.json for the menu bar app and @dingger_restore for the status line, withdrawn once restored or dismissed. - panel: a first row "↺ Restore 9 sessions · 22 agents" with when it was saved and how many agents were mid-turn; clicking restores, "Not now" dismisses. an offer shows the panel like a waiting agent; off stays off. - menu: the offer on top; restore all, one session, or not now. - status line: a clickable blue ↺N before the clock. - restore runs through the user's login shell, as a terminal starts tmux, so restored panes get a real environment, not launchd's; --report writes restore.log and notifies a summary. restore --dismiss. - commands log only warnings by default; SIGPIPE ends them quietly. e2e: the offer through the real menu bar binary, the summary notification, the offer clearing, a restore with no tmux running, and not now staying dismissed when a terminal starts tmux. the second test daemon is started directly (it leaked through a function's $! before, and dozens of leaked daemons fought over the test socket and loaded the machine); each run uses its own socket and checks its daemons stop. --- crates/dinggerd/src/notify.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'crates/dinggerd/src/notify.rs') diff --git a/crates/dinggerd/src/notify.rs b/crates/dinggerd/src/notify.rs index e619d6d..555299d 100644 --- a/crates/dinggerd/src/notify.rs +++ b/crates/dinggerd/src/notify.rs @@ -63,6 +63,19 @@ pub fn play_sound(kind: &NotificationKind) { } } +/// Deliver a notification and wait for it: for short-lived commands, whose +/// exit would cut a background delivery short. +pub fn send_message_blocking(title: &str, body: &str) { + info!(title, body, "notifying"); + if let Ok(command) = std::env::var("DINGGER_NOTIFIER") { + let _ = std::process::Command::new("sh").args(["-c", &command, title, body]).status(); + return; + } + if let Err(err) = mac_notification_sys::Notification::new().title(title).message(body).send() { + warn!(%err, "failed to deliver macOS notification"); + } +} + /// Deliver a macOS notification without blocking the caller: the delivery /// call waits on Notification Center for seconds, and the watcher must keep /// updating the UI meanwhile. -- cgit v1.2.3