agent: code-atomiser-fix — Tauri commands for trash list + restore

Adds two `#[tauri::command]` wrappers around the soft-delete pair that
landed with migration v16 in commit 15b74db:

  - `list_trashed_transcripts(limit, offset)` mirrors the existing
    `list_transcripts` shape (default 50, clamp 1..=500, offset >= 0)
    so the Trash view can paginate the `deleted_at IS NOT NULL`
    partition with the same UX as the live history list.

  - `restore_transcript(id)` clears `deleted_at`. Idempotent on a live
    row, per the storage-layer contract. Audio at `audio_path` may
    already have been removed by `delete_transcript`'s best-effort
    filesystem cleanup; the text + metadata recovery is what
    restoration actually buys you.

Both are registered in the `tauri::generate_handler!` block in
`src-tauri/src/lib.rs`, alongside the existing transcripts surface.
Mirrors the signature shape of `delete_transcript` — no
`ensure_main_window` because the rest of the transcripts command
surface does not gate on it; introducing that here would be
inconsistent and out of scope for this fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-13 17:58:13 +01:00
parent ed449ccc1f
commit 99f4ecdecc
2 changed files with 37 additions and 0 deletions

View File

@@ -16,6 +16,8 @@ use serde::{Deserialize, Serialize};
use lumotia_storage::{
delete_transcript as db_delete_transcript, get_transcript as db_get_transcript,
insert_transcript as db_insert_transcript, list_transcripts_paged,
list_trashed_transcripts as db_list_trashed_transcripts,
restore_transcript as db_restore_transcript,
search_transcripts as db_search_transcripts, update_transcript as db_update_transcript,
update_transcript_meta as db_update_transcript_meta, InsertTranscriptParams, TranscriptRow,
};
@@ -181,6 +183,39 @@ pub async fn delete_transcript(
.map_err(|e| e.to_string())
}
/// List soft-deleted transcripts for the Trash view. Mirrors
/// `list_transcripts` shape (defaults, clamps) but reads the
/// `deleted_at IS NOT NULL` partition so the trash is the exact
/// complement of the regular history list.
#[tauri::command]
pub async fn list_trashed_transcripts(
state: tauri::State<'_, AppState>,
limit: Option<i64>,
offset: Option<i64>,
) -> Result<Vec<TranscriptDto>, String> {
let limit = limit.unwrap_or(50).clamp(1, 500);
let offset = offset.unwrap_or(0).max(0);
db_list_trashed_transcripts(&state.db, limit, offset)
.await
.map(|rows| rows.into_iter().map(TranscriptDto::from).collect())
.map_err(|e| e.to_string())
}
/// Restore a soft-deleted transcript by clearing its `deleted_at`
/// timestamp. Idempotent: restoring a live row is a no-op. Note that
/// the audio file at `audio_path` may already have been removed by
/// `delete_transcript`'s best-effort filesystem cleanup; restoring
/// recovers the text + metadata but the audio may be gone.
#[tauri::command]
pub async fn restore_transcript(
state: tauri::State<'_, AppState>,
id: String,
) -> Result<(), String> {
db_restore_transcript(&state.db, &id)
.await
.map_err(|e| e.to_string())
}
/// FTS5 search. Query syntax: bare words AND together; quote phrases;
/// supports `OR`, `NOT`, prefix `*`. Returns up to 50 best-rank matches.
#[tauri::command]

View File

@@ -719,6 +719,8 @@ pub fn run() {
commands::transcripts::update_transcript,
commands::transcripts::update_transcript_meta_cmd,
commands::transcripts::delete_transcript,
commands::transcripts::list_trashed_transcripts,
commands::transcripts::restore_transcript,
commands::transcripts::search_transcripts,
// Diagnostics (panic + error capture, manual report bundle)
commands::diagnostics::log_frontend_error,