Skip to content

Add Undo Delete and keyboard shortcuts#11

Open
Kryxzort wants to merge 10 commits into
sunwoo101:mainfrom
Kryxzort:pr/undo-delete
Open

Add Undo Delete and keyboard shortcuts#11
Kryxzort wants to merge 10 commits into
sunwoo101:mainfrom
Kryxzort:pr/undo-delete

Conversation

@Kryxzort

@Kryxzort Kryxzort commented May 4, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Del key deletes selected library card(s)
  • Esc key deselects all selected cards
  • Undo button appears in status bar after deletion — click to restore
  • Undo is session-scoped: deleted files are moved to a temp batch directory and purged on app close
  • Clear Library also purges any pending undo batches and stops playback first

How undo works

Deleted files are moved (not permanently deleted) to a temp batch directory under ~/.cache/livepaper/trash/<batch-id>/. The Undo button restores the entire batch. On app close, all batches are purged. No time window — undo is available until the session ends.

Test plan

  • Select a library card → press Del → card removed, Undo button appears in status bar
  • Click Undo → card restored to library
  • Delete multiple cards → Undo restores all of them
  • Close and reopen app → Undo button gone (purged on close)
  • Press Esc with cards selected → selection cleared
  • Clear Library → stops playback, clears undo history, removes all cards

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Soft delete functionality: deleted library items move to trash instead of permanent deletion
    • Undo deleted items with Ctrl+Z keyboard shortcut
    • Delete key triggers deletion of selected items
    • Trash automatically purges on app close and startup
    • Animated undo button added to status bar
  • Documentation

    • Updated UI and library management rules for soft delete and undo behavior

@coderabbitai

coderabbitai Bot commented May 4, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Rate limit exceeded

@Kryxzort has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 45 minutes and 46 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8a75cdd3-805a-4663-887f-5ce042421403

📥 Commits

Reviewing files that changed from the base of the PR and between 3d0e61b and 5c75ce1.

📒 Files selected for processing (3)
  • src/livepaper/Helpers/LibraryService.cs
  • src/livepaper/ViewModels/MainWindowViewModel.cs
  • src/livepaper/Views/MainWindow.axaml.cs
📝 Walkthrough

Walkthrough

This PR implements soft-delete with undo for library items. Deletions move items into trash batches instead of immediately removing them, allowing restoration via Ctrl+Z. Trash is automatically purged on window close and startup. The status bar shows an animated undo button when restore is available.

Changes

Soft Delete with Undo

Layer / File(s) Summary
Trash Service Contract
src/livepaper/Helpers/LibraryService.cs
LibraryService adds TrashPath property and methods: Trash() moves item sidecars into a batch directory; RestoreBatch() moves files back; PurgeBatch() recursively deletes a batch; CleanTrash() removes all trash subdirectories; MoveIfExists() helper selectively moves files.
Undo State Model
src/livepaper/ViewModels/MainWindowViewModel.cs
UndoBatch type records batch directory, deleted cards, and prior playlist membership. Internal _undoBatches list and _canUndo observable track undo availability.
Delete & Undo Commands
src/livepaper/ViewModels/MainWindowViewModel.cs
DeleteCards generates unique batch directory, trashes each item, records batch in undo list, and enables undo. UndoDelete restores latest batch and rehydrates library/playlist state. PurgeTrash() purges all undo batches.
Lifecycle Management
src/livepaper/ViewModels/MainWindowViewModel.cs, src/livepaper/Views/MainWindow.axaml.cs
Constructor calls CleanTrash() at startup. OnClosed override calls PurgeTrash() on window close. ConfirmClearLibrary purges all undo batches before clearing library.
UI & Keyboard Input
src/livepaper/Views/MainWindow.axaml, src/livepaper/Views/MainWindow.axaml.cs
Status bar wraps message in DockPanel and adds right-aligned undo button with visibility binding to CanUndo and animated border styling. Delete key executes DeleteSelectedCommand in library tab. Ctrl+Z executes UndoDeleteCommand when undo available. Escape closes preview or clears selection.
Documentation
.claude/rules/library.md, .claude/rules/ui.md
Rules document soft-delete behavior: items move to .trash/<batchId>/, trash purges on close/startup, and Ctrl+Z restores batches. UI rules document per-card delete, keyboard triggers, and status bar undo button.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 A trash bin born, with batches neat and tidy,
Where deleted dreams await their chance on Friday.
Ctrl+Z brings them back with grace,
A second chance in library space!
Undo magic, soft and kind.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add Undo Delete and keyboard shortcuts' accurately reflects the main changes: undo-delete functionality and keyboard shortcuts (Del, Esc, Ctrl+Z) are central to this PR's objectives.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Kryxzort and others added 9 commits May 8, 2026 04:14
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace mi:MaterialIcon (needs PR 4 package) with plain text.
Replace Stop() with PlayerHelper.Stop() (ViewModel method not yet present).
Remove _currentlyPlayingCard reference (added by per-video overrides PR).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/livepaper/Helpers/LibraryService.cs`:
- Around line 24-26: The current restore loop uses File.Move(file,
Path.Combine(DownloadHelper.LibraryPath, Path.GetFileName(file)), overwrite:
true) which can overwrite a newer file; modify the loop that iterates
Directory.GetFiles(batchDir) to first compute the target path using
Path.Combine(DownloadHelper.LibraryPath, Path.GetFileName(file)), then if
File.Exists(target) do not overwrite: instead generate a non-colliding name
(e.g., append a counter or GUID) or skip and log the conflict, and then move the
file without forcing overwrite; keep the existing try {
Directory.Delete(batchDir); } catch { } behavior unchanged.
- Line 10: The TrashPath property on LibraryService currently points at
DownloadHelper.LibraryPath (persisted library) but must point to the
cache-backed session trash location; update the TrashPath getter to build the
path under the cache directory (e.g. Path.Combine(DownloadHelper.CachePath,
"trash", sessionBatchId)) instead of DownloadHelper.LibraryPath, ensuring it
uses the session/batch identifier used by the undo-delete contract and creating
the subfolders if missing; modify or add a DownloadHelper.CachePath if one
doesn't exist and reference the session batch id variable used by the session
management code when constructing the path.

In `@src/livepaper/ViewModels/MainWindowViewModel.cs`:
- Around line 1205-1211: UndoDelete currently removes the last batch from
_undoBatches before calling LibraryService.RestoreBatch, which loses undo
metadata if restore fails; change the flow in the UndoDelete method (the block
referencing _undoBatches, batch, LibraryService.RestoreBatch, and CanUndo) to
first retrieve/peek the last batch (e.g., use _undoBatches[^1] without
RemoveAt), call LibraryService.RestoreBatch(batch.BatchDir) and only upon
successful completion remove the batch from _undoBatches and then update
CanUndo; if RestoreBatch fails, do not remove the batch and propagate or log the
error so the undo can be retried.
- Line 1198: The StatusMessage currently uses targets[0].Title for the
singular-delete message which can point to a failed target; instead, determine
the actual successfully deleted card and use its Title (e.g., use the
list/collection that records successful deletions or filter targets for those
that succeeded) when deleted == 1; if no successful Title can be found fall back
to a generic message. Update the code that sets StatusMessage (the StatusMessage
assignment) to reference that successful-deletion item (or a safe fallback)
rather than targets[0].Title.

In `@src/livepaper/Views/MainWindow.axaml.cs`:
- Around line 160-168: The global key handlers in MainWindow.axaml.cs are firing
even when focus is inside text-entry controls; update the Key event logic that
checks e.Key for Delete and Ctrl+Z (the block invoking Vm.DeleteSelectedCommand
and Vm.UndoDeleteCommand with MainTabControl.SelectedIndex == 1 and Vm?.CanUndo)
to first detect if the current focused control is a text input (e.g., TextBox,
TextArea, RichTextBox or any control deriving from TextBoxBase) or if e.Source
is a text-editing element, and if so skip handling; only execute
Vm.DeleteSelectedCommand.Execute(null) or Vm.UndoDeleteCommand.Execute(null) and
set e.Handled = true when focus is not inside a text-entry control.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 42ba49ee-3a2b-4258-97f1-d710745102b2

📥 Commits

Reviewing files that changed from the base of the PR and between e4828ba and 3d0e61b.

📒 Files selected for processing (6)
  • .claude/rules/library.md
  • .claude/rules/ui.md
  • src/livepaper/Helpers/LibraryService.cs
  • src/livepaper/ViewModels/MainWindowViewModel.cs
  • src/livepaper/Views/MainWindow.axaml
  • src/livepaper/Views/MainWindow.axaml.cs

Comment thread src/livepaper/Helpers/LibraryService.cs
Comment thread src/livepaper/Helpers/LibraryService.cs
Comment thread src/livepaper/ViewModels/MainWindowViewModel.cs Outdated
Comment thread src/livepaper/ViewModels/MainWindowViewModel.cs
Comment thread src/livepaper/Views/MainWindow.axaml.cs
- RestoreBatch: skip overwrite if target already re-downloaded
- DeleteCards status: use batchItems[0].Card.Title (not targets[0] which may include failed deletions)
- UndoDelete: restore files before removing batch from stack (atomic ordering)
- OnKeyDown: guard Delete/Ctrl+Z from firing inside TextBox

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Kryxzort added a commit to Kryxzort/livepaper-pro that referenced this pull request May 22, 2026
Both sides added documentation in the same regions. Preserved sidecar
table from PR sunwoo101#10 and soft-delete section from PR sunwoo101#11 in library.md.
Combined per-card delete description (PR sunwoo101#11) with preview modal line
(PR sunwoo101#10) in ui.md. No logic removed.
Kryxzort added a commit to Kryxzort/livepaper-pro that referenced this pull request May 22, 2026
…rge-fix branch)

Merges sunwoo101#11. Implements undo delete with 10-minute window
(session-scoped), keyboard shortcuts (Esc to deselect, Del to delete), and
double white flash animation on undo button.
Conflicts resolved in merge-fix/pr-11-undo-delete.
Kryxzort added a commit to Kryxzort/livepaper-pro that referenced this pull request May 22, 2026
ui.md: merged Browse tab — kept GIF hover note (PR sunwoo101#13) plus Auto-search
and Sort button lines (PR sunwoo101#14); merged Library tab — kept soft-delete/keyboard
shortcuts (PR sunwoo101#11) alongside workshop ID copy button (PR sunwoo101#14) in preview modal.
WallpaperResult: added AddedAt field from PR sunwoo101#14.
WallpaperEngineScraper: integrated scene detection and addedAt from PR sunwoo101#14;
added FindThumbnail sync helper (PR sunwoo101#14 had it, PR sunwoo101#13 replaced it with async);
kept AnimatedThumbnailUrl (PR sunwoo101#13) and added AddedAt to video results; added
sort cases 3-6; removed redundant post-loop query filter (already done inline).
WallpaperCardViewModel: kept all GIF animation code from PR sunwoo101#13 that PR sunwoo101#14
was unaware of; kept volume/speed fields from PR sunwoo101#10; PR sunwoo101#14 added WorkshopId
display only.
MainWindow.axaml: kept volume/speed slider rows at row 1/2 (PR sunwoo101#10) then
placed PR sunwoo101#14 title+WorkshopId header at row 3 (correct grid row offset).
Kryxzort added a commit to Kryxzort/livepaper-pro that referenced this pull request May 22, 2026
ui.md: kept soft-delete/keyboard shortcuts (PR sunwoo101#11) and added right-click
context menu lines (PR sunwoo101#15) to Library tab; kept GIF hover note (PR sunwoo101#13)
and added playlist right-click menu (PR sunwoo101#15); kept status bar line.
WallpaperCardViewModel: merged imports (System.Diagnostics from PR sunwoo101#15
alongside Avalonia.Threading from PR sunwoo101#13); kept GIF animation code (PR sunwoo101#13);
added IsLocalSource property (PR sunwoo101#15); removed ghost conflict marker.
MainWindowViewModel: kept volume/speed/GIF wiring (PR sunwoo101#10/PR sunwoo101#13) plus
added OnOpenSettings callback (PR sunwoo101#15) in MakeLibraryCard.
MainWindow.axaml: browse card and playlist card — kept PointerEntered/Exited
handlers (PR sunwoo101#13 GIF hover) AND added context menus (PR sunwoo101#15).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant