aboutsummaryrefslogtreecommitdiff
path: root/src/app/api.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/api.rs')
-rw-r--r--src/app/api.rs136
1 files changed, 79 insertions, 57 deletions
diff --git a/src/app/api.rs b/src/app/api.rs
index 166ea789..76d9c537 100644
--- a/src/app/api.rs
+++ b/src/app/api.rs
@@ -67,6 +67,12 @@ impl App {
}
if let AppEvent::PaneDied { pane_id } = &ev {
+ let previous_toast = self.state.toast.clone();
+ if let Some(update) = self.state.publish_pane_process_exit_if_agent(*pane_id) {
+ self.refresh_new_herdr_toast_context_for_update(&update, &previous_toast);
+ self.emit_pane_state_update(&update);
+ self.emit_terminal_or_system_agent_notifications(std::slice::from_ref(&update));
+ }
if self.runtime_exit_action(*pane_id) == RuntimeExitAction::RespawnShell
&& self.respawn_shell_for_launch_pane(*pane_id)
{
@@ -161,57 +167,7 @@ impl App {
let instruction = crate::update::update_install_instruction(&install_command);
let _ = notify(&format!("v{version} available"), Some(&instruction));
} else if self.state.toast_config.delay_seconds == 0 {
- for update in &pane_updates {
- let is_active_tab = self
- .state
- .pane_is_in_active_tab(update.ws_idx, update.pane_id);
- let suppress_active_tab_notifications =
- crate::app::actions::active_tab_suppresses_notifications(
- is_active_tab,
- self.state.outer_terminal_focus,
- );
- let Some(kind) = crate::app::actions::notification_toast_for_state_change(
- suppress_active_tab_notifications,
- update.previous_state,
- update.state,
- ) else {
- continue;
- };
- let Some(ws) = self.state.workspaces.get(update.ws_idx) else {
- continue;
- };
- let Some(pane) = ws
- .tabs
- .iter()
- .find_map(|tab| tab.panes.get(&update.pane_id))
- else {
- continue;
- };
- let Some(agent_label) = self
- .state
- .terminals
- .get(&pane.attached_terminal_id)
- .and_then(|terminal| terminal.effective_agent_label())
- else {
- continue;
- };
- let event_text = match kind {
- ToastKind::NeedsAttention => "needs attention",
- ToastKind::Finished => "finished",
- ToastKind::UpdateInstalled => "updated",
- };
- let workspace_label =
- ws.display_name_from(&self.state.terminals, &self.terminal_runtimes);
- let _ = notify(
- &format!("{} {}", agent_label, event_text),
- Some(&crate::app::actions::notification_context(
- ws,
- &workspace_label,
- update.ws_idx,
- update.pane_id,
- )),
- );
- }
+ self.emit_terminal_or_system_agent_notifications(&pane_updates);
}
}
@@ -407,6 +363,78 @@ impl App {
}
}
+ fn emit_terminal_or_system_agent_notifications(
+ &self,
+ pane_updates: &[crate::app::actions::PaneStateUpdate],
+ ) {
+ if !self.local_terminal_notifications
+ || self.state.toast_config.delay_seconds != 0
+ || !matches!(
+ self.state.toast_config.delivery,
+ crate::config::ToastDelivery::Terminal | crate::config::ToastDelivery::System
+ )
+ {
+ return;
+ }
+
+ let notify = match self.state.toast_config.delivery {
+ crate::config::ToastDelivery::Terminal => crate::terminal_notify::show_notification,
+ crate::config::ToastDelivery::System => crate::platform::show_desktop_notification,
+ _ => return,
+ };
+
+ for update in pane_updates {
+ let is_active_tab = self
+ .state
+ .pane_is_in_active_tab(update.ws_idx, update.pane_id);
+ let suppress_active_tab_notifications =
+ crate::app::actions::active_tab_suppresses_notifications(
+ is_active_tab,
+ self.state.outer_terminal_focus,
+ );
+ let Some(kind) = crate::app::actions::notification_toast_for_pane_state_update(
+ suppress_active_tab_notifications,
+ update,
+ ) else {
+ continue;
+ };
+ let Some(ws) = self.state.workspaces.get(update.ws_idx) else {
+ continue;
+ };
+ let Some(pane) = ws
+ .tabs
+ .iter()
+ .find_map(|tab| tab.panes.get(&update.pane_id))
+ else {
+ continue;
+ };
+ let Some(agent_label) = self
+ .state
+ .terminals
+ .get(&pane.attached_terminal_id)
+ .and_then(|terminal| terminal.effective_agent_label())
+ else {
+ continue;
+ };
+ let event_text = match kind {
+ ToastKind::NeedsAttention => "needs attention",
+ ToastKind::Finished => "finished",
+ ToastKind::UpdateInstalled => "updated",
+ };
+ let workspace_label =
+ ws.display_name_from(&self.state.terminals, &self.terminal_runtimes);
+ let _ = notify(
+ &format!("{} {}", agent_label, event_text),
+ Some(&crate::app::actions::notification_context(
+ ws,
+ &workspace_label,
+ update.ws_idx,
+ update.pane_id,
+ )),
+ );
+ }
+ }
+
pub(crate) fn sync_toast_deadline(
&mut self,
previous_toast: Option<crate::app::state::ToastNotification>,
@@ -891,7 +919,6 @@ mod tests {
agent: Some(Agent::Codex),
state: AgentState::Working,
visible_blocker: false,
- visible_idle: false,
visible_working: false,
process_exited: false,
observed_at: std::time::Instant::now(),
@@ -901,7 +928,6 @@ mod tests {
agent: Some(Agent::Codex),
state: AgentState::Idle,
visible_blocker: false,
- visible_idle: false,
visible_working: false,
process_exited: false,
observed_at: std::time::Instant::now(),
@@ -984,7 +1010,6 @@ mod tests {
agent: Some(Agent::Codex),
state: AgentState::Working,
visible_blocker: false,
- visible_idle: false,
visible_working: false,
process_exited: false,
observed_at: std::time::Instant::now(),
@@ -994,7 +1019,6 @@ mod tests {
agent: Some(Agent::Codex),
state: AgentState::Idle,
visible_blocker: false,
- visible_idle: false,
visible_working: false,
process_exited: false,
observed_at: std::time::Instant::now(),
@@ -1096,7 +1120,6 @@ mod tests {
agent: Some(Agent::Codex),
state: AgentState::Working,
visible_blocker: false,
- visible_idle: false,
visible_working: false,
process_exited: false,
observed_at: std::time::Instant::now(),
@@ -1117,7 +1140,6 @@ mod tests {
agent: Some(Agent::Codex),
state: AgentState::Idle,
visible_blocker: false,
- visible_idle: false,
visible_working: false,
process_exited: false,
observed_at: std::time::Instant::now(),