mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-11-06 00:15:06 +00:00
fix(sidebar): let groups that arrive from elsewhere pull no tab into a folder
A window draws its first frames before its copy of the workspace's groups lands, so every tab's entry watch recorded "in no folder" — and the groups landing then read as each tab walking into its folder. A restored tab, or one dragged out of its folder group, was pulled back in on every launch. Groups adopted from a pull or from another window's `GroupsChanged` now start every tab's watch over from where it is; only this window's own pin gathers the tabs inside the folder, and says so tab by tab. A tab also goes up with the group it names even when the window does not know that group yet, so a sync in that same gap cannot send every kept tab back to auto grouping.
This commit is contained in:
+50
-2
@@ -63,7 +63,7 @@ mod row_metrics {
|
||||
pub(super) const BRANCH_ICON: f32 = 11.;
|
||||
/// `pl_2` + `pr_1p5` on a group header.
|
||||
pub(super) const HEADER_PAD: f32 = 8. + 6.;
|
||||
/// The chevron a header opens with, and the asterisk that marks a custom
|
||||
/// The chevron a header opens with, and the pin that marks a folder
|
||||
/// group: both `xsmall` icons, which resolve to 12px.
|
||||
pub(super) const HEADER_ICON: f32 = 12.;
|
||||
|
||||
@@ -94,7 +94,7 @@ const ROW_CWD_FLOOR: f32 = 24.;
|
||||
/// rows share. The branch takes what it wants up to half the line, and the
|
||||
/// heading keeps the rest — so a long branch can no longer crush the name
|
||||
/// (flex used to hand the overflow to them in proportion to what each asked
|
||||
/// for, which gave the longer string the smaller cut), and a long custom name
|
||||
/// for, which gave the longer string the smaller cut), and a long group name
|
||||
/// cannot crush the branch in return. `git_want` is `None` for a header with
|
||||
/// no shared branch on it, which then owns the whole line.
|
||||
fn header_name_avail(avail: f32, git_want: Option<f32>) -> f32 {
|
||||
@@ -2059,6 +2059,28 @@ impl Tty7App {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
/// Take the workspace's groups as another window, or the machine, has them.
|
||||
///
|
||||
/// Every tab's [`EntryWatch`](crate::core::group_key::EntryWatch) starts
|
||||
/// over from where it is. A folder that arrives from elsewhere is not one
|
||||
/// this window's tabs walked into — and in particular, a window that drew
|
||||
/// a frame before its copy of the groups landed saw no folders at all, so
|
||||
/// without this every tab sitting in a pinned folder at launch would read
|
||||
/// the groups landing as an entry, and a tab dragged out of its folder
|
||||
/// group would be pulled back in on every start. The window that pinned
|
||||
/// the folder gathers the tabs itself and says so tab by tab.
|
||||
pub(crate) fn adopt_sidebar_groups(&mut self, groups: WorkspaceGroups, cx: &mut Context<Self>) {
|
||||
if self.sidebar_groups == groups {
|
||||
return;
|
||||
}
|
||||
self.sidebar_groups = groups;
|
||||
for tab in &self.tabs {
|
||||
tab.folder_watch
|
||||
.set(crate::core::group_key::EntryWatch::baseline());
|
||||
}
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
/// Put the dragged tab where it was dropped.
|
||||
///
|
||||
/// By id rather than index: a drag is several frames long, and a tab
|
||||
@@ -3913,6 +3935,32 @@ mod fold_tests {
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// Groups that arrive from another window, or from the machine at launch,
|
||||
/// are not folders this window's tabs walked into. A tab sitting in one —
|
||||
/// here, one that was dragged out of it — stays where it is.
|
||||
#[gpui::test]
|
||||
fn groups_arriving_from_elsewhere_pull_no_tab_in(cx: &mut TestAppContext) {
|
||||
let (app, mut vcx, _streams) = harness_with_tabs(cx, 1);
|
||||
|
||||
app.update(&mut vcx, |app, cx| {
|
||||
plant_repo(app, 0, "/w/probed/sub", "/w/probed", cx);
|
||||
cx.notify();
|
||||
});
|
||||
vcx.run_until_parked();
|
||||
app.update(&mut vcx, |app, cx| {
|
||||
let mut groups = WorkspaceGroups::default();
|
||||
groups
|
||||
.pinned
|
||||
.push(PinnedGroup::folder(Path::new("/w/probed")));
|
||||
app.adopt_sidebar_groups(groups, cx);
|
||||
});
|
||||
vcx.run_until_parked();
|
||||
|
||||
app.update(&mut vcx, |app, _| {
|
||||
assert_eq!(app.tabs[0].group.get(), None);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
+7
-10
@@ -133,9 +133,11 @@ pub(crate) fn desired_tabs(
|
||||
out.push(DesiredTab {
|
||||
id,
|
||||
name: tab.name.clone(),
|
||||
// A tab still naming a group this window has deleted is an auto
|
||||
// tab, and goes up as one.
|
||||
group: tab.group.get().filter(|g| app.sidebar_groups.contains(*g)),
|
||||
// As the tab has it, even when this window does not know the
|
||||
// group: a window whose copy of the groups has not landed yet
|
||||
// would otherwise send every tab it holds back to auto grouping.
|
||||
// A group that really is gone was already cleared by the machine.
|
||||
group: tab.group.get(),
|
||||
root,
|
||||
});
|
||||
}
|
||||
@@ -1599,12 +1601,7 @@ fn adopt_groups(cx: &mut App, client_ws: WorkspaceId) {
|
||||
else {
|
||||
return;
|
||||
};
|
||||
app.update(cx, |app, cx| {
|
||||
if app.sidebar_groups != groups {
|
||||
app.sidebar_groups = groups;
|
||||
cx.notify();
|
||||
}
|
||||
});
|
||||
app.update(cx, |app, cx| app.adopt_sidebar_groups(groups, cx));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2777,7 +2774,7 @@ impl Tty7App {
|
||||
true
|
||||
}
|
||||
LayoutDelta::GroupsChanged { groups } => {
|
||||
self.sidebar_groups = groups.clone();
|
||||
self.adopt_sidebar_groups(groups.clone(), cx);
|
||||
true
|
||||
}
|
||||
LayoutDelta::TabMoved { tab, to } => {
|
||||
|
||||
Reference in New Issue
Block a user