SFTP 文件列表点列名即可排序,换目录后列宽和排序箭头不再复位

gpui-kit 只给列标题右边的箭头挂了排序,标题本身的点击用来选列,而文件列表关掉了选列,
所以只能点箭头。现在点列名和点箭头一样:降序、升序、恢复按名称。

表格每次 refresh(每读一次目录)都从委托重新取列,原来拖宽的列会弹回默认宽度,箭头也回到
「未排序」而行仍按原列排着。现在 FileListing 记下拖动后的列宽(ColumnWidthsChanged)和
当前排序,refresh 后照旧。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
XuzandClaude Opus 5.5 committed 2026-10-10 13:46:54 +08:00
1 parent e1600ce05c
commit 27822e7315
5 files changed
+191 -11

No files matched your search

+133
View File
@@ -1558,6 +1558,139 @@ async fn sftp_dragging_outside_the_names_selects_the_rows_crossed(cx: &mut TestA
cx.update(|cx| assert_eq!(pane_selection(&workspace, true, cx), ["目录", "链接目录"]));
}
/// A click on a column title sorts by the column, as one on its arrow does:
/// descending, ascending, then back to by name. The order outlives a
/// refresh, after which the next click carries on from it.
#[gpui_kit::test]
async fn sftp_clicking_a_column_title_sorts_by_it(cx: &mut TestAppContext) {
use shellrs::app::{ExplorerAction, ExplorerCommand};
let provider = Arc::new(FakeSftpProvider::default());
let (handle, workspace) = open_workspace_with_sftp(cx, provider);
open_test_explorer(cx, handle).await;
let pane = ("local-pane", SFTP_TAB);
let names = |cx: &mut TestAppContext| {
cx.run_until_parked();
cx.update(|cx| {
let explorer = workspace.read(cx).explorer(ExplorerId(SFTP_TAB)).unwrap();
let entries = explorer.read(cx).local().read(cx).entries(cx);
entries
.into_iter()
.map(|entry| entry.name.to_string())
.collect::<Vec<_>>()
})
};
let click_size = |cx: &mut TestAppContext| {
cx.update_window(handle.into(), |_, window, cx| {
window.render_frame(cx);
window.within(pane).click("column:size", cx);
})
.unwrap();
};
let by_name = ["..", "目录", "链接目录", "文件 乙.txt", "文件 甲.txt"];
assert_eq!(names(cx), by_name);
// Folders stay ahead of files whichever way.
click_size(cx);
let descending = ["..", "链接目录", "目录", "文件 乙.txt", "文件 甲.txt"];
assert_eq!(names(cx), descending);
cx.update_window(handle.into(), |_, window, cx| {
window.dispatch_action(
Box::new(ExplorerAction::new(
ExplorerId(SFTP_TAB),
ExplorerCommand::Refresh { remote: false },
)),
cx,
);
})
.unwrap();
assert_eq!(names(cx), descending);
click_size(cx);
assert_eq!(
names(cx),
["..", "目录", "链接目录", "文件 甲.txt", "文件 乙.txt"]
);
click_size(cx);
assert_eq!(names(cx), by_name);
}
/// A column dragged wider stays so with the next listing, which gives the
/// table its columns again.
#[gpui_kit::test]
async fn sftp_column_widths_outlive_a_refresh(cx: &mut TestAppContext) {
use gpui_kit::{Modifiers, MouseDownEvent, MouseUpEvent};
use shellrs::app::{ExplorerAction, ExplorerCommand};
let provider = Arc::new(FakeSftpProvider::default());
let (handle, _workspace) = open_workspace_with_sftp(cx, provider);
open_test_explorer(cx, handle).await;
let pane = ("local-pane", SFTP_TAB);
let width = |cx: &mut TestAppContext| {
cx.run_until_parked();
cx.update_window(handle.into(), |_, window, cx| {
window.render_frame(cx);
window
.within(pane)
.find(("col-header", 1usize))
.bounds()
.size
.width
})
.unwrap()
};
let before = width(cx);
// Drag the boundary right of 大小 by 60 pixels.
cx.update_window(handle.into(), |_, window, cx| {
window.render_frame(cx);
let bounds = window.within(pane).find(("col-header", 1usize)).bounds();
let start = point(bounds.right() - px(1.), bounds.center().y);
let event = |x: f32| MouseMoveEvent {
position: point(start.x + px(x), start.y),
pressed_button: Some(MouseButton::Left),
modifiers: Modifiers::default(),
};
window.dispatch_event(
MouseDownEvent {
button: MouseButton::Left,
position: start,
modifiers: Modifiers::default(),
click_count: 1,
first_mouse: false,
}
.to_platform_input(),
cx,
);
for x in [10., 30., 60.] {
window.dispatch_event(event(x).to_platform_input(), cx);
window.render_frame(cx);
}
window.dispatch_event(
MouseUpEvent {
button: MouseButton::Left,
position: point(start.x + px(60.), start.y),
modifiers: Modifiers::default(),
click_count: 1,
}
.to_platform_input(),
cx,
);
})
.unwrap();
let dragged = width(cx);
assert!(dragged > before + px(40.), "{before:?} -> {dragged:?}");
cx.update_window(handle.into(), |_, window, cx| {
window.dispatch_action(
Box::new(ExplorerAction::new(
ExplorerId(SFTP_TAB),
ExplorerCommand::Refresh { remote: false },
)),
cx,
);
})
.unwrap();
assert_eq!(width(cx), dragged);
}
/// As in WinSCP without full row select, only the name cell is the item: a
/// click on the rest of a row, or below the rows, is a click on empty space
/// and clears the selection. A ⌘ click there, or a click on a column title,