Add conflict policy options: Skip / Auto-number / Override
New ConflictPolicy enum in rename/ (Skip = original/default behavior,
AutoNumber = save as "Name (1).ext" counting up to the first free slot,
Override = replace the conflicting file outright), threaded through
execute_renames/rename_one alongside RenameAction. Override never deletes
a conflicting directory (falls back to Skip for that case); AutoNumber
sidesteps directories the same way by just trying the next number.
execute_rename now takes a conflict argument; undo/history are
deliberately NOT conflict-aware and always use their own fixed
skip-on-conflict policy regardless of what the original rename used.
Frontend: a second segmented selector in the rename confirmation modal
("On conflict: Skip / Auto-number / Override"), with Override styled in
red and its warning copy calling out that it can't be undone.
This commit is contained in:
+16
-9
@@ -6,7 +6,7 @@ mod settings;
|
||||
|
||||
use renamr_core::format::ExpressionFormat;
|
||||
use renamr_core::matching::{self, EpisodeGuess, MovieGuess, ReleaseInfo};
|
||||
use renamr_core::rename::{self, RenameAction, RenamePlanItem, RenameResult};
|
||||
use renamr_core::rename::{self, ConflictPolicy, RenameAction, RenamePlanItem, RenameResult};
|
||||
use renamr_core::string_bindings;
|
||||
use std::collections::HashMap;
|
||||
use tauri::AppHandle;
|
||||
@@ -53,19 +53,26 @@ fn guess_release_info(filename: String) -> Option<ReleaseInfo> {
|
||||
}
|
||||
|
||||
/// Executes a batch of planned on-disk rename/copy/symlink operations (optionally
|
||||
/// moving/copying files into subfolders - see `renamr_core::rename`; conflicting
|
||||
/// targets are always skipped, never overwritten). `action` picks which of the three
|
||||
/// happens - the UI is expected to have already shown the user the full old-path/
|
||||
/// new-path plan, the chosen action, and gotten explicit confirmation before calling
|
||||
/// this. Runs off the main thread since real filesystem I/O shouldn't block the UI.
|
||||
/// moving/copying files into subfolders - see `renamr_core::rename`). `action` picks
|
||||
/// which of the three happens; `conflict` picks what happens when a computed target
|
||||
/// already exists (skip it, save alongside it with an auto-numbered name, or replace
|
||||
/// it) - the UI is expected to have already shown the user the full old-path/new-path
|
||||
/// plan and both choices, and gotten explicit confirmation before calling this. Runs
|
||||
/// off the main thread since real filesystem I/O shouldn't block the UI.
|
||||
///
|
||||
/// Every successfully-produced item is recorded to the rename history log afterward
|
||||
/// (see `history::record_batch`), tagged with `action`, so it can be undone later from
|
||||
/// the History panel - a Move undo moves the file back, a Copy/Symlink undo just
|
||||
/// removes what was created.
|
||||
/// removes what was created. `conflict` is NOT recorded - undoing always uses its own
|
||||
/// fixed skip-on-conflict policy regardless of what the original rename used.
|
||||
#[tauri::command]
|
||||
async fn execute_rename(app: AppHandle, items: Vec<RenamePlanItem>, action: RenameAction) -> Vec<RenameResult> {
|
||||
let results = tauri::async_runtime::spawn_blocking(move || rename::execute_renames(&items, action))
|
||||
async fn execute_rename(
|
||||
app: AppHandle,
|
||||
items: Vec<RenamePlanItem>,
|
||||
action: RenameAction,
|
||||
conflict: ConflictPolicy,
|
||||
) -> Vec<RenameResult> {
|
||||
let results = tauri::async_runtime::spawn_blocking(move || rename::execute_renames(&items, action, conflict))
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
history::record_batch(&app, &results, action);
|
||||
|
||||
Reference in New Issue
Block a user