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