improve scanning speed

This commit is contained in:
Lncvrt committed 2026-04-14 23:08:12 -07:00
1 parent 10caf9d56e
commit f98706ed85
2 files changed
+49 -36

No files matched your search

+33 -27
View File
@@ -1,6 +1,6 @@
use serde::{Deserialize, Serialize};
use sysinfo::Disks;
use tauri::{WebviewUrl, WebviewWindowBuilder};
use tauri::{Emitter, WebviewUrl, WebviewWindowBuilder};
use tauri_plugin_shell::ShellExt;
#[cfg(target_os = "macos")]
@@ -53,7 +53,7 @@ async fn get_file_info_from_dirs(
app: tauri::AppHandle,
path: String,
min_ratio: String,
) -> Result<DirScanResult, String> {
) -> Result<(), String> {
let cmd = app
.shell()
.sidecar("pdu")
@@ -70,58 +70,64 @@ async fn get_file_info_from_dirs(
let output = cmd.output().await.map_err(|e| e.to_string())?;
if !output.status.success() {
return Err(format!(
"pdu failed: {}",
String::from_utf8_lossy(&output.stderr)
));
return Err(String::from_utf8_lossy(&output.stderr).to_string());
}
let stdout = String::from_utf8_lossy(&output.stdout);
let json: serde_json::Value =
serde_json::from_str(&stdout).map_err(|e| format!("JSON parse failed: {}", e))?;
let json: serde_json::Value = serde_json::from_str(&stdout).map_err(|e| e.to_string())?;
let mut items = Vec::new();
if let Some(tree) = json.get("tree") {
extract_files(tree, "", &mut items);
let mut batch: Vec<FileInfo> = Vec::new();
stream_extract(tree, "", &mut batch, &app);
}
let total_size = items.iter().map(|i| i.size).sum();
Ok(DirScanResult {
items,
total_size,
error: None,
})
Ok(())
}
fn extract_files(node: &serde_json::Value, parent_path: &str, items: &mut Vec<FileInfo>) {
if let Some(name) = node.get("name").and_then(|v| v.as_str()) {
fn stream_extract(
node: &serde_json::Value,
parent_path: &str,
batch: &mut Vec<FileInfo>,
app: &tauri::AppHandle,
) {
let name = match node.get("name").and_then(|v| v.as_str()) {
Some(n) => n,
None => return,
};
let size = node.get("size").and_then(|v| v.as_u64()).unwrap_or(0);
let children = node.get("children").and_then(|v| v.as_array());
let is_dir = children.as_ref().map(|c| !c.is_empty()).unwrap_or(false);
let path = if parent_path.is_empty() {
name.to_string()
} else {
format!("{}/{}", parent_path, name)
};
items.push(FileInfo {
let is_dir = children.is_some();
batch.push(FileInfo {
name: name.to_string(),
path: path.clone(),
size,
is_dir,
});
if let Some(children_array) = children {
if !children_array.is_empty() {
for child in children_array {
extract_files(child, &path, items);
}
if batch.len() >= 200 {
let _ = app.emit("scan-batch", batch.clone());
batch.clear();
}
if let Some(children) = children {
for child in children {
stream_extract(child, &path, batch, app);
}
}
if parent_path.is_empty() && !batch.is_empty() {
let _ = app.emit("scan-batch", batch.clone());
}
}
+16 -9
View File
@@ -7,6 +7,7 @@ import { v5 as uuidv5 } from 'uuid'
import prettyBytes from 'pretty-bytes'
import { FileInfo, scanDir } from './scanlib'
import { message, open } from '@tauri-apps/plugin-dialog'
import { listen } from '@tauri-apps/api/event'
interface Disk {
name: string
@@ -31,19 +32,25 @@ export default function App () {
const handleFolderSelect = async (path: string) => {
setSelectedFolder(path)
setScanning(true)
console.log('scanning', path)
const scanResult = await scanDir(path)
console.log('done', scanResult)
if (scanResult.error) {
await message(`Error: ${scanResult.error}`, {
title: 'Tauri',
kind: 'error'
setFiles([])
const unlisten = await listen<FileInfo[]>('scan-batch', event => {
const batch = event.payload
setFiles(prev => [...prev, ...batch])
})
try {
await invoke('get_file_info_from_dirs', {
path,
minRatio: '0'
})
} catch (e: any) {
await message(`Error: ${e}`, { title: 'Error', kind: 'error' })
setSelectedFolder(null)
} else {
setFiles(scanResult.items)
}
setScanning(false)
unlisten()
}
return !selectedFolder ? (