SFTP 本地目录列表在 Windows 上列出各个驱动器
Windows 上每个盘是一个独立的根,目录列表原来只有当前路径的各级和主目录、桌面、文稿、下载, 离不开起始的盘(只能在「打开目录/书签」里手动输入 D:\)。现在「位置」里按 WinSCP 的样子 列出所有盘符:「C: 本地磁盘」「E: 可移动磁盘」「Z: 网络驱动器」「F: CD 驱动器」。 盘符用 GetLogicalDrives 和 GetDriveTypeW 取,不读卷标。位置改在后台随每次读本地目录 一起重新取,所以新插上的 U 盘刷新一下就出现,也不在 UI 线程上碰网络驱动器。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5be3f56b0c
commit
e1600ce05c
10 files changed
+184
-24
No files matched your search
@@ -1271,6 +1271,50 @@ async fn sftp_tab_reconnects_from_its_tab_bar_and_reports_at_the_bottom_left(
|
||||
cx.update(|cx| assert_eq!(workspace.read(cx).explorers_of(HostId(DB_01), cx).len(), 2));
|
||||
}
|
||||
|
||||
/// The 目录列表 select's places, Windows drives among them, are read again
|
||||
/// with each local listing: a drive plugged in shows up on the next refresh.
|
||||
#[gpui_kit::test]
|
||||
async fn local_places_are_read_again_with_each_listing(cx: &mut TestAppContext) {
|
||||
use shellrs::app::{ExplorerAction, ExplorerCommand};
|
||||
use shellrs::sftp::{DriveKind, Place};
|
||||
let local = FakeLocalDirectory::default();
|
||||
let system = (Place::Drive('C', DriveKind::Local), "/c".to_string());
|
||||
local
|
||||
.places
|
||||
.lock()
|
||||
.unwrap()
|
||||
.push((system.0, system.1.clone().into()));
|
||||
let (handle, workspace) =
|
||||
open_workspace_with_services(cx, Arc::new(FakeSftpProvider::default()), local.clone());
|
||||
open_test_explorer(cx, handle).await;
|
||||
let places = |cx: &mut TestAppContext| {
|
||||
cx.update(|cx| {
|
||||
let explorer = workspace.read(cx).explorer(ExplorerId(SFTP_TAB)).unwrap();
|
||||
explorer.read(cx).local().read(cx).places().to_vec()
|
||||
})
|
||||
};
|
||||
assert_eq!(places(cx), std::slice::from_ref(&system));
|
||||
|
||||
let stick = (Place::Drive('E', DriveKind::Removable), "/e".to_string());
|
||||
local
|
||||
.places
|
||||
.lock()
|
||||
.unwrap()
|
||||
.push((stick.0, stick.1.clone().into()));
|
||||
cx.update_window(handle.into(), |_, window, cx| {
|
||||
window.dispatch_action(
|
||||
Box::new(ExplorerAction::new(
|
||||
ExplorerId(SFTP_TAB),
|
||||
ExplorerCommand::Refresh { remote: false },
|
||||
)),
|
||||
cx,
|
||||
);
|
||||
})
|
||||
.unwrap();
|
||||
cx.run_until_parked();
|
||||
assert_eq!(places(cx), [system, stick]);
|
||||
}
|
||||
|
||||
#[gpui_kit::test]
|
||||
async fn sftp_file_commands_confirm_validate_and_send_one_operation(cx: &mut TestAppContext) {
|
||||
use shellrs::app::{ExplorerAction, ExplorerCommand};
|
||||
|
||||
@@ -271,6 +271,8 @@ pub struct FakeLocalDirectory {
|
||||
pub calls: Arc<Mutex<Vec<String>>>,
|
||||
/// The files the editor reads and writes, in memory.
|
||||
pub files: Arc<Mutex<std::collections::BTreeMap<std::path::PathBuf, Vec<u8>>>>,
|
||||
/// The places it offers, such as a drive plugged in.
|
||||
pub places: Arc<Mutex<Vec<(shellrs::sftp::Place, std::path::PathBuf)>>>,
|
||||
}
|
||||
|
||||
impl FakeLocalDirectory {
|
||||
@@ -287,6 +289,9 @@ impl LocalDirectoryProvider for FakeLocalDirectory {
|
||||
fn list(&self, path: &std::path::Path) -> anyhow::Result<DirectoryListing> {
|
||||
Ok(fake_listing(path.to_str().unwrap()))
|
||||
}
|
||||
fn places(&self) -> Vec<(shellrs::sftp::Place, std::path::PathBuf)> {
|
||||
self.places.lock().unwrap().clone()
|
||||
}
|
||||
fn trash(&self, paths: &[std::path::PathBuf]) -> anyhow::Result<()> {
|
||||
self.record(format!("trash {paths:?}"))
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user