Add rename history with undo

- New crates/renamr-core/src/history module: HistoryBatch/HistoryEntry
  records, revert_batch() moves files back to their original paths
  (skip-on-conflict, same policy as rename::execute_renames; recreates a
  deleted destination folder defensively), push_batch() maintains a
  most-recent-first log capped at 50 batches. A partial port of the idea
  behind net.filebot.HistoryDialog, as a flat undo stack rather than a full
  session/element log. 6 new tests.
- New src-tauri/src/history.rs: persists the log as history.json in the OS
  app-config directory (same location as settings.json). execute_rename now
  takes an AppHandle and calls history::record_batch after every rename,
  recording only the items that actually got renamed. Two new commands:
  list_rename_history and undo_rename_batch.
- Frontend: the History button (previously a no-op) now opens a panel
  listing past rename batches with a timestamp, file count, and the
  old-name/new-name pairs, each with an Undo button. Undoing reconciles any
  currently-loaded item back to its pre-rename path/name, same pattern as
  post-rename reconciliation.
- Verified via cargo test (45 total)/check + npm build + a full Playwright
  pass: loaded mocked files, renamed them, opened History, undid the batch,
  and confirmed both the UI and the (mocked) backend state matched at every
  step.
This commit is contained in:
Renamr Scaffold
2026-08-29 03:44:38 +00:00
parent 658a235e05
commit 93b5ac5e56
7 changed files with 643 additions and 28 deletions
+29 -20
View File
@@ -10,10 +10,11 @@ detection ("Match") is working, real online metadata lookups against TMDB ("Fetc
Data") are working — including fuzzy show-name disambiguation, so a search that
returns several similarly-named shows doesn't just take TMDB's top-ranked hit — and the
actual on-disk rename operation is wired up (skip-on-conflict, with a confirmation step
showing the full old-name/new-name plan before anything touches disk — there is no undo
yet). Rename can also organize files into subfolders — including ones that don't exist
yet — when the naming scheme includes a `/`. Full media-metadata bindings are not yet
ported. See "Porting roadmap" below.
showing the full old-path/new-path plan before anything touches disk). Rename can also
organize files into subfolders — including ones that don't exist yet — when the naming
scheme includes a `/`. Every completed rename is logged to a history panel that can
undo it, moving files back to their original paths. Full media-metadata bindings are
not yet ported. See "Porting roadmap" below.
The naming scheme is fully user-editable from the app (the "Naming Scheme" button next
to the New Names list) — the default is `{show name} - {season number}x{episode
@@ -110,23 +111,26 @@ crates/renamr-core/ Pure Rust core: naming-expression engine (ported), local
(`similarity/`, partial `EpisodeMetrics` port), a TMDB metadata
client (`web/tmdb.rs` — TV search + episode lookup, disambiguated
via `similarity/`, tested against a mocked HTTP server via
`mockito`), and the on-disk rename engine (`rename/`) —
`mockito`), the on-disk rename engine (`rename/`) —
skip-on-conflict, can also organize into (auto-created)
subfolders when the naming scheme includes `/`. Not yet ported:
full media metadata bindings, other web datasource clients
(TVDB/AniDB/etc).
subfolders when the naming scheme includes `/` — and a rename
history/undo log (`history/`, a partial `HistoryDialog` port).
Not yet ported: full media metadata bindings, other web
datasource clients (TVDB/AniDB/etc).
No Tauri dependency, so it builds and unit-tests standalone.
src-tauri/ Tauri app shell: exposes renamr-core as commands to the frontend
(naming-scheme rendering, filename matching, TMDB metadata fetch,
executing a rename plan, native file/folder dialogs, drag-and-drop
expansion), plus `settings.rs` (TMDB token, stored as JSON in the
OS app-config directory), app metadata/icons/window config
expansion), plus `settings.rs` (TMDB token) and `history.rs`
(rename history/undo log) — both stored as JSON in the OS
app-config directory — app metadata/icons/window config
(tauri.conf.json).
src/ React + TypeScript UI (Vite). Faithful recreation of the original
two-pane rename screen (Aurora theme) wired to real file loading,
drag-and-drop, live naming-scheme preview, local matching, TMDB
fetch (behind a Settings modal for the API token), and a
confirm-before-touching-disk modal for the actual rename.
fetch (behind a Settings modal for the API token), a
confirm-before-touching-disk modal for the actual rename, and a
History panel that can undo a past rename.
scripts/gen_icons.py Regenerates src-tauri/icons/ (placeholder branding — swap the
colors/glyph in the script, or replace the icons directly, to
change the look).
@@ -217,13 +221,18 @@ ported from, for anyone picking this up:
`--conflict` variants beyond skip (auto-number, override), and the CLI flag surface
itself.
7. **The rest of the UI** — the Rename panel (file loading, drag-drop, live preview,
local matching, confirmed rename) is built; the other five sidebar panels
(Episodes/Subtitles/SFV/Filter/List) are still stub screens, plus Align up/down
reordering, History, and Presets on the Rename panel itself are no-ops. There's also
no per-item exclude inside the rename confirmation modal yet (it's all-or-nothing —
use "Exclude Selected" on the file list beforehand to leave a file out entirely).
8. **Undo/history for renames** — there is no undo yet; the confirmation modal before
Rename executes is the only safety net right now. `net.filebot.HistoryDialog`/the
original's rename-history log is the reference for what a real undo would look like.
local matching, confirmed rename, rename history/undo) is built; the other five
sidebar panels (Episodes/Subtitles/SFV/Filter/List) are still stub screens, plus
Align up/down reordering and Presets on the Rename panel itself are still no-ops.
There's also no per-item exclude inside the rename confirmation modal yet (it's
all-or-nothing — use "Exclude Selected" on the file list beforehand to leave a file
out entirely).
8. **Undo/history for renames** — done, as a flat JSON-backed undo stack rather than a
full port of `net.filebot.HistoryDialog`'s session/element log
(`crates/renamr-core/src/history`, `src-tauri/src/history.rs`). Every successful
rename is recorded to a `history.json` in the OS app-config directory (same location
as `settings.json`); the History panel lists past batches and can revert one back to
its original paths, skipping (never overwriting) any file whose original path now
has something else at it. Capped at the 50 most recent batches.
9. **Packaging** — code signing, auto-update, installers per platform via
`npm run tauri build`.