feat(sync): auto-resync artifacts on edit (notes/summary/transcript/tags/action items) (FR-SYNC-5)
This commit is contained in:
@@ -1732,6 +1732,7 @@ pub async fn reprocess_transcript(
|
||||
template.as_ref(),
|
||||
);
|
||||
let _ = state.store.update_notes(&meeting_id, ¬es_md).await;
|
||||
spawn_auto_sync(&app, state.store.clone(), meeting_id.clone());
|
||||
|
||||
let _ = app.emit(
|
||||
"transcript://finalized",
|
||||
@@ -2044,6 +2045,7 @@ pub async fn list_meetings(
|
||||
/// Replaces a meeting's complete tag set (Phase 8, FR-SEARCH-2).
|
||||
#[tauri::command]
|
||||
pub async fn set_tags(
|
||||
app: AppHandle,
|
||||
state: State<'_, AppState>,
|
||||
meeting_id: MeetingId,
|
||||
tags: Vec<String>,
|
||||
@@ -2052,7 +2054,9 @@ pub async fn set_tags(
|
||||
.store
|
||||
.set_tags(&meeting_id, &tags)
|
||||
.await
|
||||
.map_err(|e| WaError::new("storage", e.to_string()))
|
||||
.map_err(|e| WaError::new("storage", e.to_string()))?;
|
||||
spawn_auto_sync(&app, state.store.clone(), meeting_id);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// All known tag names, sorted, for filter/autocomplete UI (Phase 8, FR-SEARCH-2).
|
||||
@@ -2250,6 +2254,7 @@ pub(crate) fn cleanup_playback_temp() {
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn update_notes(
|
||||
app: AppHandle,
|
||||
state: State<'_, AppState>,
|
||||
meeting_id: MeetingId,
|
||||
markdown: String,
|
||||
@@ -2258,7 +2263,9 @@ pub async fn update_notes(
|
||||
.store
|
||||
.update_notes(&meeting_id, &markdown)
|
||||
.await
|
||||
.map_err(|e| WaError::new("storage", e.to_string()))
|
||||
.map_err(|e| WaError::new("storage", e.to_string()))?;
|
||||
spawn_auto_sync(&app, state.store.clone(), meeting_id);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// `format` ∈ `md | pdf | docx | bundle`. `dest` is a file path for
|
||||
@@ -2710,6 +2717,7 @@ pub async fn generate_summary(
|
||||
if let Err(e) = state.store.reindex_fts(&meeting_id).await {
|
||||
tracing::warn!("failed to reindex search after summary generation: {e}");
|
||||
}
|
||||
spawn_auto_sync(&app, state.store.clone(), meeting_id.clone());
|
||||
|
||||
let _ = app.emit(
|
||||
"llm://done",
|
||||
@@ -2723,6 +2731,7 @@ pub async fn generate_summary(
|
||||
/// T8.6, FR-CAL-5).
|
||||
#[tauri::command]
|
||||
pub async fn confirm_action_items(
|
||||
app: AppHandle,
|
||||
state: State<'_, AppState>,
|
||||
meeting_id: MeetingId,
|
||||
items: Vec<ActionItem>,
|
||||
@@ -2758,6 +2767,7 @@ pub async fn confirm_action_items(
|
||||
_ => crate::reminders::cancel(id),
|
||||
}
|
||||
}
|
||||
spawn_auto_sync(&app, state.store.clone(), meeting_id);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -3689,6 +3699,33 @@ pub(crate) async fn enqueue_meeting_sync(
|
||||
Ok(queued)
|
||||
}
|
||||
|
||||
/// Re-sync a meeting's artifacts after an edit (notes / summary / transcript /
|
||||
/// tags / action items), mirroring sync-on-finalize (T9.5, FR-SYNC-5). A no-op
|
||||
/// unless sync is enabled; only finalize-trigger targets are touched and
|
||||
/// unchanged files are deduped by SHA-256, so a save that didn't alter an
|
||||
/// uploaded artifact queues (and uploads) nothing. Fire-and-forget so the edit
|
||||
/// command returns immediately.
|
||||
///
|
||||
/// ponytail: fires on every (debounced) save; if WebDAV PUT volume from live
|
||||
/// note-typing ever matters, coarsen the debounce or trigger on blur instead.
|
||||
pub(crate) fn spawn_auto_sync(
|
||||
app: &AppHandle,
|
||||
store: std::sync::Arc<dyn crate::storage::Store>,
|
||||
meeting_id: MeetingId,
|
||||
) {
|
||||
if !load_settings().sync_enabled {
|
||||
return;
|
||||
}
|
||||
let app = app.clone();
|
||||
tauri::async_runtime::spawn(async move {
|
||||
match enqueue_meeting_sync(store.as_ref(), &meeting_id, None, true).await {
|
||||
Ok(0) => {} // nothing changed
|
||||
Ok(_) => pump_sync(&app, store.as_ref()).await, // upload the changes
|
||||
Err(e) => tracing::warn!("auto-sync enqueue failed: {e:?}"),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Upload one job's file: ensure the remote dir, PUT, report bytes sent.
|
||||
async fn upload_job(
|
||||
target: &dyn crate::sync::SyncTarget,
|
||||
|
||||
Reference in New Issue
Block a user