Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 2024-05-18 - [Optimize Selection and Clipboard State Checks in FileList]
**Learning:** Checking state conditions using `.some()` iteratively over `selectedItems` and `clipboard.items` inside `.map()` array renders scales O(N*M), severely degrading application performance in directories with high file counts.
**Action:** Replace `.some()` inside loop checks with O(1) checks against a `Set` built utilizing `useMemo`. This prevents O(N*M) calculation complexity for item render attributes like `isSelected` and `isCut` when rendering children in large collections.
2 changes: 2 additions & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ignoredBuiltDependencies:
- esbuild
1 change: 1 addition & 0 deletions src-tauri/src/commands/permission_commands.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#[cfg(target_os = "macos")]
use std::process::Command;

#[tauri::command]
Expand Down
1 change: 1 addition & 0 deletions src-tauri/src/commands/volume_operations_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ pub fn get_system_volumes_information() -> Vec<VolumeInformation> {
#[cfg(test)]
mod tests {
use super::*;
use crate::log_info;

#[test]
fn test_get_volumes() {
Expand Down
11 changes: 8 additions & 3 deletions src-tauri/src/search_engine/search_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,7 @@ impl SearchCore {
path
);

#[allow(unused_assignments)]
#[allow(unused_variables)]
let mut removed_count = 1;

Expand Down Expand Up @@ -672,11 +673,13 @@ impl SearchCore {

self.remove_paths_recursive(&path_to_remove);

removed_count += 1;
#[allow(unused_assignments)]
{ removed_count += 1; }
} else {
self.remove_path(&path_to_remove);

removed_count += 1;
#[allow(unused_assignments)]
{ removed_count += 1; }
}
}

Expand Down Expand Up @@ -886,14 +889,16 @@ impl SearchCore {
}

let mut seen: HashSet<String> = self.results_buffer.iter().map(|(p, _)| p.clone()).collect();
#[allow(unused_assignments)]
#[allow(unused_variables)]
let mut added_fuzzy = 0;

for (p, s) in fuzzy_results {
if !seen.contains(&p) {
seen.insert(p.clone());
self.results_buffer.push((p, s));
added_fuzzy += 1;
#[allow(unused_assignments)]
{ added_fuzzy += 1; }
}
}

Expand Down
2 changes: 1 addition & 1 deletion src-tauri/src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use logging::Logger;
use crate::state::searchengine_data::SearchEngineState;
use meta_data::MetaDataState;
use std::sync::{Arc, Mutex};
use tauri::{Builder, Wry, Manager};
use tauri::{Builder, Wry};

pub fn setup_app_state(app: Builder<Wry>) -> Builder<Wry> {
// Create our shared state instances
Expand Down
17 changes: 13 additions & 4 deletions src/components/explorer/FileList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,16 @@ const FileList = ({ data, isLoading, viewMode = 'grid', isSearching = false, sea
handleItemClickRef.current(item, index, true);
}, []);

// ⚑ Bolt: O(1) lookups for selection and clipboard state to avoid O(N*M) complexity in rendering loop
const selectedPaths = useMemo(() => {
return new Set(selectedItems.map(item => item.path));
}, [selectedItems]);

const cutPaths = useMemo(() => {
if (clipboard?.operation !== 'cut' || !clipboard?.items) return new Set();
return new Set(clipboard.items.map(item => item.path));
}, [clipboard]);

return (
<div className="file-list-wrapper">
<div
Expand Down Expand Up @@ -632,18 +642,17 @@ const FileList = ({ data, isLoading, viewMode = 'grid', isSearching = false, sea
{/* File list content */}
<div className={`file-list view-mode-${viewMode.toLowerCase()} scrollable-content`}>
{sortedItems.map((item, index) => {
const isCut = clipboard?.operation === 'cut' &&
clipboard.items?.some(clipItem => clipItem.path === item.path);
const isCut = cutPaths.has(item.path);

return (
<FileItem
key={item.path}
item={item}
index={index}
viewMode={viewMode}
isSelected={selectedItems.some(selected => selected.path === item.path)}
isSelected={selectedPaths.has(item.path)}
isFocused={focusedItem && focusedItem.path === item.path}
isCut={!!isCut}
isCut={isCut}
onItemClick={stableOnItemClick}
onItemDoubleClick={stableOnItemDoubleClick}
/>
Expand Down
Loading