feat: scope Saved Queries panel to active connection + clean up on delete
Two changes that close the "everything lives in one global pool" gap.
UI: Saved Queries sidebar now defaults to "This connection" and lists
only entries with `connection_id == activeConnectionId` plus unattached
entries (legacy global saves before F2). A small toggle ("All") above
the search box brings the previous behavior back when copying queries
between databases. Each row in "All" mode shows a tag with the source
connection's name; legacy global entries show "unattached".
Backend: delete_connection now best-effort cleans persisted state for
that connection — removes `memory/<id>.md` (delete_memory_core in
memory.rs) and drops every entry in saved_queries.json with the
matching `connection_id` (delete_by_connection_core in
saved_queries.rs). Entries with `connection_id == None` are deliberately
preserved. Cleanup errors are logged but don't block the deletion since
connections.json is the source of truth.
Memory was already per-connection (F1); query history already filters
by connection. This commit makes saved queries behave the same and
stops orphan files from accumulating.
This commit is contained in:
@@ -118,6 +118,16 @@ pub async fn delete_connection(
|
||||
fs::write(&path, data)?;
|
||||
}
|
||||
close_connection(&state, &id).await;
|
||||
// Best-effort cleanup of per-connection persisted state; errors are logged
|
||||
// but don't block the deletion (the connections.json is the source of truth).
|
||||
if let Err(e) = crate::commands::memory::delete_memory_core(&app, &id) {
|
||||
log::warn!("failed to delete memory file for {}: {}", id, e);
|
||||
}
|
||||
if let Err(e) =
|
||||
crate::commands::saved_queries::delete_by_connection_core(&app, &id).await
|
||||
{
|
||||
log::warn!("failed to clean saved queries for {}: {}", id, e);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -146,6 +146,21 @@ pub(crate) fn enforce_size_cap(content: &str, cap: usize) -> String {
|
||||
out
|
||||
}
|
||||
|
||||
/// Best-effort delete of a connection's memory file. Returns Ok(()) when the
|
||||
/// file doesn't exist; only surfaces an error for actual filesystem failures.
|
||||
/// Used by delete_connection to keep memory/ from filling up with orphan files.
|
||||
pub(crate) fn delete_memory_core(
|
||||
app: &AppHandle,
|
||||
connection_id: &str,
|
||||
) -> TuskResult<()> {
|
||||
let path = get_memory_path(app, connection_id)?;
|
||||
if !path.exists() {
|
||||
return Ok(());
|
||||
}
|
||||
fs::remove_file(&path)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_memory(app: AppHandle, connection_id: String) -> TuskResult<String> {
|
||||
read_memory_core(&app, &connection_id)
|
||||
|
||||
@@ -54,6 +54,29 @@ pub(crate) async fn save_query_core(app: &AppHandle, query: SavedQuery) -> TuskR
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Drop every saved-query entry tied to a specific connection_id. Entries with
|
||||
/// `connection_id == None` (older "global" saves) are deliberately preserved
|
||||
/// so they remain visible across all connections.
|
||||
pub(crate) async fn delete_by_connection_core(
|
||||
app: &AppHandle,
|
||||
connection_id: &str,
|
||||
) -> TuskResult<()> {
|
||||
let path = get_saved_queries_path(app)?;
|
||||
if !path.exists() {
|
||||
return Ok(());
|
||||
}
|
||||
let data = fs::read_to_string(&path)?;
|
||||
let mut entries: Vec<SavedQuery> = serde_json::from_str(&data).unwrap_or_default();
|
||||
let before = entries.len();
|
||||
entries.retain(|e| e.connection_id.as_deref() != Some(connection_id));
|
||||
if entries.len() == before {
|
||||
return Ok(());
|
||||
}
|
||||
let data = serde_json::to_string_pretty(&entries)?;
|
||||
fs::write(&path, data)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn list_saved_queries(
|
||||
app: AppHandle,
|
||||
|
||||
Reference in New Issue
Block a user