дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 19:25:54 +02:00
perf(vfs): list directories off the main thread (#973)
`fs_read_dir` was a synchronous Tauri command, so every directory listing ran on the main thread. On a slow file system such as a network share (`\\wsl.localhost\...`), each stat while expanding the project tree stalled the whole UI. The listing now runs on the blocking pool, as the other disk-heavy commands do, both for the desktop command and over RPC. Refs #916. Co-authored-by: ntbang0901 <[email protected]>
Цей коміт міститься в:
1 джерело
5e7ee5e081
коміт
22a5f21a90
3 files changed
+24
-20
No files matched your search
@@ -73,24 +73,28 @@ pub async fn copy_merge(
|
||||
/// Files of a deleted folder snapshotted in Local History.
|
||||
const DELETE_SNAPSHOT_LIMIT: usize = 2000;
|
||||
|
||||
pub fn read_dir(host: &Host, window: &str, path: PathBuf) -> IdeResult<Vec<FileEntry>> {
|
||||
let excludes = host
|
||||
.project(window)
|
||||
.map(|p| {
|
||||
let globs = p.exclude_globs();
|
||||
// `read_dir` matches relative to the enclosing repository: re-anchor
|
||||
// project-root patterns (`/build`) when the project is a repo subfolder.
|
||||
let repo = p.root.ancestors().find(|d| d.join(".git").exists());
|
||||
match repo.and_then(|r| p.root.strip_prefix(r).ok()).filter(|rel| !rel.as_os_str().is_empty()) {
|
||||
Some(rel) => {
|
||||
let rel = rel.to_string_lossy().replace('\\', "/");
|
||||
globs.into_iter().map(|g| if g.starts_with('/') { format!("/{rel}{g}") } else { g }).collect()
|
||||
/// Runs on the blocking pool: on a network share (`\\wsl.localhost`) every stat is slow.
|
||||
pub async fn read_dir(host: &Host, window: &str, path: PathBuf) -> IdeResult<Vec<FileEntry>> {
|
||||
let project = host.project(window);
|
||||
host.blocking(move || {
|
||||
let excludes = project
|
||||
.map(|p| {
|
||||
let globs = p.exclude_globs();
|
||||
// `read_dir` matches relative to the enclosing repository: re-anchor
|
||||
// project-root patterns (`/build`) when the project is a repo subfolder.
|
||||
let repo = p.root.ancestors().find(|d| d.join(".git").exists());
|
||||
match repo.and_then(|r| p.root.strip_prefix(r).ok()).filter(|rel| !rel.as_os_str().is_empty()) {
|
||||
Some(rel) => {
|
||||
let rel = rel.to_string_lossy().replace('\\', "/");
|
||||
globs.into_iter().map(|g| if g.starts_with('/') { format!("/{rel}{g}") } else { g }).collect()
|
||||
}
|
||||
None => globs,
|
||||
}
|
||||
None => globs,
|
||||
}
|
||||
})
|
||||
.unwrap_or_default();
|
||||
ide_vfs::read_dir(&path, &excludes)
|
||||
})
|
||||
.unwrap_or_default();
|
||||
ide_vfs::read_dir(&path, &excludes)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
/// Creates an empty file; inside a project, honours the EditorConfig
|
||||
|
||||
@@ -178,7 +178,7 @@ impl Dispatcher {
|
||||
Ok(())
|
||||
})
|
||||
.add("cancel_task", |c| async move { Ok(ide_core::task::cancel(c.arg::<TaskId>("id")?)) })
|
||||
.add("fs_read_dir", |c| async move { ops::fs::read_dir(&c.host, &c.window, c.arg("path")?) })
|
||||
.add("fs_read_dir", |c| async move { ops::fs::read_dir(&c.host, &c.window, c.arg("path")?).await })
|
||||
.add("fs_entry_kind", |c| async move { ops::fs::entry_kind(&c.host, c.arg("path")?).await })
|
||||
.add("fs_create_file", |c| async move { ops::fs::create_file(&c.host, &c.window, c.arg("path")?) })
|
||||
.add("fs_create_file_bytes", |c| async move {
|
||||
|
||||
@@ -39,8 +39,8 @@ pub async fn fs_copy_merge(
|
||||
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub fn fs_read_dir(window: Window, state: State<'_, AppState>, path: PathBuf) -> IdeResult<Vec<FileEntry>> {
|
||||
fs::read_dir(&state.host, window.label(), path)
|
||||
pub async fn fs_read_dir(window: Window, state: State<'_, AppState>, path: PathBuf) -> IdeResult<Vec<FileEntry>> {
|
||||
fs::read_dir(&state.host, window.label(), path).await
|
||||
}
|
||||
|
||||
/// Creates an empty file; inside a project, honours the EditorConfig
|
||||
|
||||
Reference in new issue
Заблокувати користувача