fix: keep workspace labels current without extra redraws

refs #1838
This commit is contained in:
Ogulcan Celik
2026-07-25 04:08:16 +03:00
parent 00ecb78155
commit 5886fe6bd2
5 changed files with 79 additions and 21 deletions
+2 -1
View File
@@ -3113,7 +3113,8 @@ impl AppState {
let sound = sound_for_toast_kind(kind, suppress_active_tab_notifications)
.filter(|_| self.sound.allows(known_agent));
let build_toast = || {
let workspace_label = self.workspaces[ws_idx].display_name();
let workspace_label =
self.workspaces[ws_idx].display_name_from_terminals(&self.terminals);
let context =
notification_context(&self.workspaces[ws_idx], &workspace_label, ws_idx, pane_id);
ToastNotification {
+15
View File
@@ -2412,6 +2412,21 @@ mod tests {
assert!(app.state.toast.is_none());
}
#[test]
fn unchanged_git_status_drain_has_no_render_impact() {
let mut app = test_app();
app.git_refresh_in_flight = true;
app.event_tx
.try_send(AppEvent::GitStatusRefreshed {
results: Vec::new(),
cache_updates: Vec::new(),
})
.unwrap();
assert!(!app.drain_internal_events());
assert!(!app.git_refresh_in_flight);
}
#[test]
fn internal_event_drain_limits_work_per_tick() {
let mut app = test_app();
+14 -7
View File
@@ -586,26 +586,33 @@ impl App {
pub(crate) fn drain_internal_events(&mut self) -> bool {
self.drain_internal_events_up_to(super::APP_EVENT_DRAIN_LIMIT)
.1
}
pub(crate) fn drain_all_internal_events(&mut self) -> bool {
let mut had_event = false;
while self.drain_internal_events_up_to(super::APP_EVENT_DRAIN_LIMIT) {
had_event = true;
let mut changed = false;
loop {
let (had_event, batch_changed) =
self.drain_internal_events_up_to(super::APP_EVENT_DRAIN_LIMIT);
changed |= batch_changed;
if !had_event {
break;
}
}
had_event
changed
}
fn drain_internal_events_up_to(&mut self, limit: usize) -> bool {
fn drain_internal_events_up_to(&mut self, limit: usize) -> (bool, bool) {
let mut had_event = false;
let mut changed = false;
for _ in 0..limit {
let Ok(ev) = self.event_rx.try_recv() else {
break;
};
had_event = true;
self.handle_internal_event_with_prefix_sync(ev);
changed |= self.handle_internal_event_with_prefix_sync(ev);
}
had_event
(had_event, changed)
}
}
+2 -2
View File
@@ -197,12 +197,12 @@ fn workspace_row_height(app: &AppState, ws: &crate::workspace::Workspace, indent
let (state, seen) = ws.aggregate_state(&app.terminals);
let label = if indented {
grouped_child_display_label(
&ws.display_name(),
&ws.display_name_from_terminals(&app.terminals),
ws.branch().as_deref(),
ws.custom_name.is_some(),
)
} else {
ws.display_name()
ws.display_name_from_terminals(&app.terminals)
};
let token_values = ws.metadata_tokens.values();
tokens::space_rows(
+46 -11
View File
@@ -1093,16 +1093,31 @@ impl Workspace {
.or_else(|| Some(self.identity_cwd.clone()))
}
#[cfg(test)]
pub fn display_name(&self) -> String {
if let Some(name) = &self.custom_name {
return name.clone();
}
if self.cached_identity_cwd == self.identity_cwd {
self.cached_auto_label.clone()
} else {
fallback_label_from_cwd(&self.identity_cwd)
self.automatic_display_name_for_cwd(&self.identity_cwd)
}
pub(crate) fn display_name_from_terminals(
&self,
terminals: &HashMap<TerminalId, TerminalState>,
) -> String {
if let Some(name) = &self.custom_name {
return name.clone();
}
let cwd = self
.tabs
.first()
.and_then(|tab| tab.terminal_id(tab.root_pane))
.and_then(|terminal_id| terminals.get(terminal_id))
.map(|terminal| &terminal.cwd)
.unwrap_or(&self.identity_cwd);
self.automatic_display_name_for_cwd(cwd)
}
pub fn display_name_from(
@@ -1115,16 +1130,18 @@ impl Workspace {
}
self.resolved_identity_cwd_from(terminals, terminal_runtimes)
.map(|cwd| {
if cwd == self.cached_identity_cwd {
self.cached_auto_label.clone()
} else {
fallback_label_from_cwd(&cwd)
}
})
.map(|cwd| self.automatic_display_name_for_cwd(&cwd))
.unwrap_or_else(|| "workspace".into())
}
fn automatic_display_name_for_cwd(&self, cwd: &std::path::Path) -> String {
if cwd == self.cached_identity_cwd {
self.cached_auto_label.clone()
} else {
fallback_label_from_cwd(cwd)
}
}
pub fn branch(&self) -> Option<String> {
self.cached_git_branch.clone()
}
@@ -1642,6 +1659,24 @@ mod tests {
assert_eq!(ws.display_name(), "cached-repo");
}
#[test]
fn terminal_aware_display_name_uses_latest_admitted_identity_cache() {
let mut ws = Workspace::test_new("ignored");
let root_pane = ws.tabs[0].root_pane;
let terminal_id = ws.tabs[0].terminal_id(root_pane).unwrap().clone();
ws.custom_name = None;
ws.identity_cwd = PathBuf::from("/old/workspace");
ws.cached_identity_cwd = PathBuf::from("/new/repo/deep");
ws.cached_auto_label = "repo".into();
let terminals = HashMap::from([(
terminal_id.clone(),
TerminalState::new(terminal_id, PathBuf::from("/new/repo/deep")),
)]);
assert_eq!(ws.display_name_from_terminals(&terminals), "repo");
assert_eq!(ws.display_name(), "workspace");
}
#[test]
fn workspace_identity_follows_first_tab_root_pane_cwd() {
let mut ws = Workspace::test_new("ignored");