Add List panel (session 9, fifteenth feature)

Renders a naming-scheme-style expression per loaded file via the same
render_expression engine the Rename panel's live preview uses, fed by
the same local guess_episode/guess_movie/guess_release_info matching
Filter already uses. Copy List and Export to File... (a new
export_text_list Tauri command - the only new backend surface this
feature needed) round it out. Closes out all six original sidebar
panels as real screens.
This commit is contained in:
Renamr Scaffold
2026-08-29 17:28:38 +00:00
parent bfcec9135a
commit 03768c398d
7 changed files with 526 additions and 6 deletions
+2
View File
@@ -2,6 +2,7 @@ mod cli;
mod episodes;
mod files;
mod history;
mod list;
mod metadata;
mod presets;
mod settings;
@@ -121,6 +122,7 @@ pub fn run() {
sfv::compute_checksums,
sfv::save_checksum_file,
sfv::verify_checksum_file,
list::export_text_list,
history::list_rename_history,
history::undo_rename_batch,
presets::list_presets,
+61
View File
@@ -0,0 +1,61 @@
//! The Tauri-facing side of the List panel: exports a set of already-rendered text
//! lines (one per loaded file) to a plain text file the user picks via a native
//! "Save File" dialog. This is the *only* new Tauri surface List needs - matching
//! each file against local metadata and rendering a naming-scheme-style expression
//! per file both reuse commands that already exist: `guess_episode`/`guess_movie`/
//! `guess_release_info` (the same local guessers the Rename panel's "Match" and the
//! Filter panel's scan already call) and `render_expression` (the same engine the
//! Rename panel's live preview already calls). The frontend builds the final,
//! newline-joined text; this module's only job is writing it to a file the user
//! chooses, the same async native-dialog pattern `sfv::save_checksum_file` uses.
use tauri::AppHandle;
use tauri_plugin_dialog::DialogExt;
/// The `.txt`-suffixed file name to default the Save dialog to.
fn default_export_filename(default_name: &str) -> String {
format!("{default_name}.txt")
}
/// Opens a native "Save File" dialog defaulted to `<default_name>.txt`, and if the
/// user doesn't cancel, writes `content` there verbatim (already newline-joined by
/// the frontend, one rendered line per loaded file). Returns the saved path, or
/// `None` if the user cancelled the dialog (not an error) - same shape as
/// `sfv::save_checksum_file`.
#[tauri::command]
pub async fn export_text_list(app: AppHandle, default_name: String, content: String) -> Result<Option<String>, String> {
let (tx, rx) = tokio::sync::oneshot::channel();
app.dialog()
.file()
.set_file_name(default_export_filename(&default_name))
.save_file(move |result| {
let _ = tx.send(result);
});
let chosen = rx.await.map_err(|e| e.to_string())?;
let Some(file_path) = chosen else {
return Ok(None);
};
let path = file_path.into_path().map_err(|e| e.to_string())?;
tauri::async_runtime::spawn_blocking({
let path = path.clone();
move || std::fs::write(&path, content)
})
.await
.map_err(|e| e.to_string())?
.map_err(|e| e.to_string())?;
Ok(Some(path.to_string_lossy().to_string()))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_export_filename_appends_txt_extension() {
assert_eq!(default_export_filename("my-list"), "my-list.txt");
assert_eq!(default_export_filename(""), ".txt");
}
}