Align Up/Down now swaps the selected file with its neighbor in the shared
item list (Original Files and New Names stay positionally paired, matching
the original FileBot's "align" buttons for manually lining up mismatched
lists).
Naming-scheme Presets: up to 9 saved expressions, one per digit slot,
persisted as presets.json (src-tauri/src/presets.rs, same load/save
pattern as settings.rs/history.rs). A new Presets panel lists all 9 slots
with Save Current / Apply / Clear, and a global 1-9 keydown handler applies
a slot instantly from anywhere in the app (ignored while a text field is
focused or a modal is open).
Match now also parses filename-only release-tag text - resolution, source
(BluRay/HDTV/WEB-DL/...), video/audio codec, and release group - via a new
guess_release_info() in renamr-core's matching module, wired through a new
guess_release_info Tauri command and called alongside the existing TV/movie
guess for every file. Naming schemes can now reference
{resolution}/{source}/{video codec}/{audio codec}/{release group}, or
FileBot's own short names ({vf}/{source}/{vc}/{ac}/{group}).
- renamr-core::rename: new RenameAction enum (Move/Copy/Symlink, default Move,
mirroring net.filebot.cli.CmdlineOperations's --action modes). execute_renames() now
takes an action applied to the whole batch. Copy uses fs::copy (source untouched);
Symlink uses std::os::unix::fs::symlink / std::os::windows::fs::symlink_file behind a
cfg(unix)/cfg(windows) split. Same conflict policy (skip, never overwrite) and
auto-created destination folders apply to all three actions. 8 new tests.
- renamr-core::history: HistoryBatch now records which action produced it
(#[serde(default)] so old history.json entries - all implicitly Move - still
deserialize). revert_one() branches on it: Move still moves the file back; Copy/
Symlink undo by deleting the copy/symlink (using symlink_metadata so a broken link is
still recognized as present and removable) - the original was never touched by those
actions, so there's nothing to move back. 3 new tests.
- src-tauri: execute_rename command takes the chosen action and threads it through to
both execute_renames and record_batch.
- Frontend: a Move/Copy/Symlink segmented selector in the "Confirm Rename" modal
(remembered across modal opens, defaults to Move), action-aware subtitle/button
copy, and a status message using the right verb (Renamed/Copied/Symlinked). Only Move
reconciles a loaded item's id/name/bindings to the new path afterward, since Copy/
Symlink leave the source file exactly where it was. History panel now shows a Copy/
Symlink badge on non-Move batches and explains what Undo does for each.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
- renamr-core::matching: guess_movie() extracts a movie title (and release year, if
present) from a filename using the same year/quality-token boundary heuristics real
release names follow, as a fallback when guess_episode() finds no season/episode
marker.
- renamr-core::web::tmdb: search_movie()/lookup_movie() mirror the TV client, reusing
the same Sorensen-Dice title-disambiguation as lookup_episode(), narrowed further by
TMDB's own primary_release_year filter when a year was locally guessed. Also exposed
search_tv_best_match() and fixed a latent gap where the real Fetch Data command path
(metadata.rs::fetch_season) bypassed the fuzzy show-name disambiguation entirely,
doing its own raw first-result selection instead of reusing it.
- src-tauri: new guess_movie command and fetch_movie_metadata command/types
(MovieFetchQuery/Outcome/Result), registered alongside the existing TV commands.
- Frontend: Item now tracks mediaKind ("tv"/"movie"/null); Match tries guess_episode
then falls back to guess_movie; Fetch Data resolves TV and movie targets via their
own commands concurrently and merges results. A single batch can mix TV and movie
files - each only fills in the fields that apply to it. Movie fields ({movie name},
{year}, reusing {airdate} for release date, matching FileBot's own unified binding)
are documented in the naming-scheme field reference.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
- 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.