feat(transcripts): migration v5 meta — starred, tags, template, language, segments persisted

This commit is contained in:
2026-04-19 16:35:17 +01:00
parent 9378980639
commit e248923f5d
7 changed files with 360 additions and 24 deletions

View File

@@ -13,7 +13,8 @@ use kon_storage::{
delete_transcript as db_delete_transcript, get_transcript as db_get_transcript,
insert_transcript as db_insert_transcript, list_dictionary,
list_transcripts_paged, search_transcripts as db_search_transcripts,
update_transcript as db_update_transcript, DictionaryEntry, InsertTranscriptParams,
update_transcript as db_update_transcript,
update_transcript_meta as db_update_transcript_meta, DictionaryEntry, InsertTranscriptParams,
TranscriptRow,
};
@@ -22,6 +23,10 @@ use crate::AppState;
/// Frontend-facing shape of a stored transcript. Mirrors `TranscriptRow`
/// from the storage crate but drops fields the UI does not need yet
/// (sample_rate, audio_channels, format flags) and renames to camelCase.
///
/// Task 2.5 — `starred`, `manualTags`, `template`, `language`, `segmentsJson`
/// were added to back the viewer metadata that previously lived only in the
/// removed `kon_history` localStorage cache.
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TranscriptDto {
@@ -34,6 +39,11 @@ pub struct TranscriptDto {
pub engine: Option<String>,
pub model_id: Option<String>,
pub created_at: String,
pub starred: bool,
pub manual_tags: String,
pub template: String,
pub language: String,
pub segments_json: String,
}
impl From<TranscriptRow> for TranscriptDto {
@@ -48,6 +58,11 @@ impl From<TranscriptRow> for TranscriptDto {
engine: r.engine,
model_id: r.model_id,
created_at: r.created_at,
starred: r.starred,
manual_tags: r.manual_tags,
template: r.template,
language: r.language,
segments_json: r.segments_json,
}
}
}
@@ -179,6 +194,45 @@ pub async fn search_transcripts(
.map_err(|e| e.to_string())
}
/// Task 2.5 — patch-style update for the transcripts_meta columns. Each
/// field is optional: `Some` overwrites, omitted / `None` preserves via
/// COALESCE server-side. Separate from `update_transcript` (text / title)
/// so the existing command surface stays untouched.
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UpdateTranscriptMetaRequest {
#[serde(default)]
pub starred: Option<bool>,
#[serde(default)]
pub manual_tags: Option<String>,
#[serde(default)]
pub template: Option<String>,
#[serde(default)]
pub language: Option<String>,
#[serde(default)]
pub segments_json: Option<String>,
}
#[tauri::command]
pub async fn update_transcript_meta_cmd(
state: tauri::State<'_, AppState>,
id: String,
patch: UpdateTranscriptMetaRequest,
) -> Result<TranscriptDto, String> {
let row = db_update_transcript_meta(
&state.db,
&id,
patch.starred,
patch.manual_tags.as_deref(),
patch.template.as_deref(),
patch.language.as_deref(),
patch.segments_json.as_deref(),
)
.await
.map_err(|e| e.to_string())?;
Ok(TranscriptDto::from(row))
}
// --- Dictionary commands (custom vocabulary) ---
#[derive(Debug, Clone, Serialize)]

View File

@@ -271,6 +271,7 @@ pub fn run() {
commands::transcripts::count_transcripts_command,
commands::transcripts::get_transcript,
commands::transcripts::update_transcript,
commands::transcripts::update_transcript_meta_cmd,
commands::transcripts::delete_transcript,
commands::transcripts::search_transcripts,
commands::transcripts::list_dictionary_command,