fix(delete): resolve Content paths, progress updates, DEL keybinds#3041
fix(delete): resolve Content paths, progress updates, DEL keybinds#3041jamiepine merged 5 commits intospacedriveapp:mainfrom
Conversation
DeleteJob now calls resolve_in_job() on each target path before strategy selection, converting SdPath::Content to SdPath::Physical via DB lookup. This follows the same pattern established by CopyJob (upstream). Also replaces unimplemented!() panic in PathResolver::resolve() for Content paths with a proper error return. Note: RemoteDeleteStrategy still uses deprecated device_id() — fixing this requires device_slug resolution infrastructure (separate concern). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Register explorer.delete (DEL / Cmd+Backspace) and explorer.permanentDelete (Shift+DEL / Cmd+Alt+Backspace) handlers in useExplorerKeyboard, using the same confirm + mutateAsync pattern as the context menu. Clears selection after successful delete. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
DeleteJob now emits GenericProgress at 4 phases: Preparing (validation), Preparing (path resolution), Deleting (strategy execution), and Complete (with final counts and timing). Fixes the UI showing 0% throughout delete operations. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Extract delete logic into useDeleteFiles hook (DRY: used by both useExplorerKeyboard and useFileContextMenu) - Add isPending guard to prevent double-deletion on rapid key presses - Remove dead DeleteProgress struct from delete job - Use Progress::Indeterminate for intermediate phases instead of misleading percentage values that get overridden by with_completion Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
core/src/domain/addressing.rs (1)
685-689: Consider moving imports to file scope.Placing
usestatements inside a match arm works but is unconventional. Moving these imports to the top of the file (grouped with othersea_ormand entity imports) would improve readability and align with the coding guideline to group imports with blank lines between standard library, external crates, and local modules.📦 Suggested import organization
Add these imports at the file's top-level import section (around line 7-13):
use sea_orm::{ColumnTrait, EntityTrait, ModelTrait, QueryFilter}; use crate::infra::db::entities::{ content_identity, device, location, ContentIdentity, Device, DirectoryPaths, Entry, Location, };Then remove lines 685-689 from inside the match arm.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@core/src/domain/addressing.rs` around lines 685 - 689, Move the in-match-arm imports into the file-level imports: take the use statements for sea_orm::{ColumnTrait, EntityTrait, ModelTrait, QueryFilter} and the crate::infra::db::entities::{content_identity, device, location, ContentIdentity, Device, DirectoryPaths, Entry, Location} out of the match arm and add them to the top of core/src/domain/addressing.rs grouped with the other external and local imports, then delete the duplicate use lines inside the match arm so only the file-scoped imports remain.packages/interface/src/routes/explorer/hooks/useDeleteFiles.ts (1)
25-25: Consider using a modal dialog instead ofconfirm().The native
confirm()blocks the main thread and has inconsistent styling across browsers/platforms. For better UX consistency with the rest of Spacedrive's UI, consider using a modal component. This is a minor enhancement that could be deferred.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/interface/src/routes/explorer/hooks/useDeleteFiles.ts` at line 25, The code in useDeleteFiles.ts uses the blocking native confirm(message) which should be replaced with the app's modal/confirmation component for consistent styling and non-blocking behavior; update the delete flow inside the useDeleteFiles hook to call the project's confirmation modal API (e.g., openConfirmation / useDialog / ConfirmModal) instead of confirm(message), make it return a Promise<boolean> (await the user's response) and proceed only if true, and import or inject the modal hook/component where useDeleteFiles is defined so the function that currently checks if (!confirm(message)) return false uses the modal result instead.core/src/ops/files/delete/job.rs (1)
159-170: Completion metrics may be misleading.The
with_completion(total_files as u64, total_files as u64)reports 100% completion even when some deletions failed. Consider usingdeleted_countfor the completed count to accurately reflect successful operations:📊 More accurate completion metrics
ctx.progress(Progress::Generic( GenericProgress::new( 1.0, "Complete", format!("{} deleted, {} failed", deleted_count, failed_count), ) - .with_completion(total_files as u64, total_files as u64) + .with_completion(deleted_count as u64, total_files as u64) .with_bytes(total_bytes, total_bytes) .with_performance(0.0, None, Some(self.started_at.elapsed())) .with_errors(failed_count as u64, 0), ));🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@core/src/ops/files/delete/job.rs` around lines 159 - 170, The completion metrics currently call with_completion(total_files as u64, total_files as u64) which reports 100% even if some deletes failed; update the Progress::Generic payload (the GenericProgress built in ctx.progress(...) inside the Complete phase) to call .with_completion(deleted_count as u64, total_files as u64) so the completed count reflects successful deletions (keep .with_errors(failed_count as u64, 0) as-is to report failures).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@core/src/domain/addressing.rs`:
- Around line 744-750: The current branch that constructs
PathBuf::from(filename) when entry.parent_id is None can produce relative paths
for non-directory entries; update the logic in the function handling
DirectoryPaths -> SdPath::Physical creation (the block using entry.parent_id,
entry.name, entry.extension) to validate entry.parent_id is present and return
an Err (or propagate a suitable error) instead of constructing a relative
PathBuf when parent_id is None; ensure callers that map entries to
SdPath::Physical (the code that uses entry.parent_id and creates the PathBuf
filename) handle that Result/Option accordingly so only absolute/anchored
physical paths are returned per the SdPath::Physical contract.
---
Nitpick comments:
In `@core/src/domain/addressing.rs`:
- Around line 685-689: Move the in-match-arm imports into the file-level
imports: take the use statements for sea_orm::{ColumnTrait, EntityTrait,
ModelTrait, QueryFilter} and the crate::infra::db::entities::{content_identity,
device, location, ContentIdentity, Device, DirectoryPaths, Entry, Location} out
of the match arm and add them to the top of core/src/domain/addressing.rs
grouped with the other external and local imports, then delete the duplicate use
lines inside the match arm so only the file-scoped imports remain.
In `@core/src/ops/files/delete/job.rs`:
- Around line 159-170: The completion metrics currently call
with_completion(total_files as u64, total_files as u64) which reports 100% even
if some deletes failed; update the Progress::Generic payload (the
GenericProgress built in ctx.progress(...) inside the Complete phase) to call
.with_completion(deleted_count as u64, total_files as u64) so the completed
count reflects successful deletions (keep .with_errors(failed_count as u64, 0)
as-is to report failures).
In `@packages/interface/src/routes/explorer/hooks/useDeleteFiles.ts`:
- Line 25: The code in useDeleteFiles.ts uses the blocking native
confirm(message) which should be replaced with the app's modal/confirmation
component for consistent styling and non-blocking behavior; update the delete
flow inside the useDeleteFiles hook to call the project's confirmation modal API
(e.g., openConfirmation / useDialog / ConfirmModal) instead of confirm(message),
make it return a Promise<boolean> (await the user's response) and proceed only
if true, and import or inject the modal hook/component where useDeleteFiles is
defined so the function that currently checks if (!confirm(message)) return
false uses the modal result instead.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: a40b9898-9af6-4e02-9da2-b24734cf2287
📒 Files selected for processing (6)
core/src/domain/addressing.rscore/src/ops/addressing.rscore/src/ops/files/delete/job.rspackages/interface/src/routes/explorer/hooks/useDeleteFiles.tspackages/interface/src/routes/explorer/hooks/useExplorerKeyboard.tspackages/interface/src/routes/explorer/hooks/useFileContextMenu.ts
…ive paths addressing.rs: when resolving SdPath::Physical, entries with parent_id=None produced a relative path like "file.txt" which violates the SdPath::Physical contract (must be absolute). Now returns an error instead. In practice this case shouldn't occur (root entries are directories), but it's correct to fail explicitly rather than silently produce invalid paths. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
DeleteJobnow callsresolve_in_job()on each target path before strategy selection, convertingSdPath::ContenttoSdPath::Physicalvia DB lookup. Follows the same pattern asCopyJob(upstream). Also replacesunimplemented!()panic inPathResolver::resolve()with a proper error.DeleteJobemits progress at each phase (Preparing, Resolving, Deleting, Complete) so the UI can display meaningful status.explorer.delete(trash) andexplorer.permanentDelete(permanent) keyboard shortcuts in the Explorer.useDeleteFileshook: Extracts delete logic (mutation, error handling,isPendingguard) into a reusable hook used by both keyboard shortcuts and context menu — removes ~53 lines of duplicated code.Related
useFileContextMenu.ts. If both are merged, the second will need a minor rebase (2-3 lines in the imports/hooks section). No functional conflict.Files changed (6 files, +196/-77)
core/src/domain/addressing.rsresolve_in_job()forSdPath::Contentvia DB lookupcore/src/ops/addressing.rsunimplemented!()with proper errorcore/src/ops/files/delete/job.rsDeleteProgressstructpackages/.../useDeleteFiles.tspackages/.../useExplorerKeyboard.tspackages/.../useFileContextMenu.tsTest plan
isPendingguard prevents duplicate operations