fix(app-settings): persist and prune pinned tree nodes
This commit is contained in:
1 parent
0e189ba0cc
commit
1ef09e8975
12 files changed
+237
-2
No files matched your search
@@ -340,6 +340,24 @@ impl Storage {
|
||||
.unwrap_or_else(|| DesktopSettings::default().show_tray_icon),
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn save_pinned_tree_node_ids(&self, ids: &[String]) -> Result<(), String> {
|
||||
let mut settings = self.load_app_settings_json().await?;
|
||||
let values = ids.iter().map(|id| serde_json::Value::String(id.clone())).collect::<Vec<serde_json::Value>>();
|
||||
settings.insert("pinned_tree_node_ids".to_string(), serde_json::Value::Array(values));
|
||||
self.save_app_settings_json(&settings).await
|
||||
}
|
||||
|
||||
pub async fn load_pinned_tree_node_ids(&self) -> Result<Vec<String>, String> {
|
||||
let settings = self.load_app_settings_json().await?;
|
||||
let Some(value) = settings.get("pinned_tree_node_ids") else {
|
||||
return Ok(Vec::new());
|
||||
};
|
||||
let Some(array) = value.as_array() else {
|
||||
return Ok(Vec::new());
|
||||
};
|
||||
Ok(array.iter().filter_map(|item| item.as_str().map(|value| value.to_string())).collect())
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -1041,4 +1059,27 @@ mod tests {
|
||||
assert_eq!(storage.load_password_hash().await.unwrap(), Some("hash-2".to_string()));
|
||||
assert_eq!(storage.load_desktop_settings().await.unwrap(), DesktopSettings { show_tray_icon: false });
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn pinned_tree_node_ids_default_to_empty() {
|
||||
let path = temp_db_path("pinned-tree-default");
|
||||
let storage = Storage::open(&path).await.unwrap();
|
||||
|
||||
assert_eq!(storage.load_pinned_tree_node_ids().await.unwrap(), Vec::<String>::new());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn pinned_tree_node_ids_roundtrip_and_preserve_password_hash() {
|
||||
let path = temp_db_path("pinned-tree-roundtrip");
|
||||
let storage = Storage::open(&path).await.unwrap();
|
||||
|
||||
storage.save_password_hash("hash-3").await.unwrap();
|
||||
storage.save_pinned_tree_node_ids(&["conn-1".to_string(), "conn-1:db:main".to_string()]).await.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
storage.load_pinned_tree_node_ids().await.unwrap(),
|
||||
vec!["conn-1".to_string(), "conn-1:db:main".to_string()]
|
||||
);
|
||||
assert_eq!(storage.load_password_hash().await.unwrap(), Some("hash-3".to_string()));
|
||||
}
|
||||
}
|
||||
@@ -195,6 +195,11 @@ async fn main() {
|
||||
.route("/update/check", get(routes::update::check_for_updates))
|
||||
// Layout
|
||||
.route("/layout/sidebar", post(routes::layout::save_sidebar_layout).get(routes::layout::load_sidebar_layout))
|
||||
// App settings
|
||||
.route(
|
||||
"/app-settings/pinned-tree-node-ids",
|
||||
get(routes::app_settings::load_pinned_tree_node_ids).post(routes::app_settings::save_pinned_tree_node_ids),
|
||||
)
|
||||
.layer(middleware::from_fn_with_state(web_state.clone(), auth::auth_middleware))
|
||||
.with_state(web_state.clone());
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use axum::extract::State;
|
||||
use axum::Json;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::error::AppError;
|
||||
use crate::state::WebState;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SavePinnedTreeNodeIdsRequest {
|
||||
pub ids: Vec<String>,
|
||||
}
|
||||
|
||||
pub async fn load_pinned_tree_node_ids(State(state): State<Arc<WebState>>) -> Result<Json<Vec<String>>, AppError> {
|
||||
let ids = state.app.storage.load_pinned_tree_node_ids().await.map_err(AppError)?;
|
||||
Ok(Json(ids))
|
||||
}
|
||||
|
||||
pub async fn save_pinned_tree_node_ids(
|
||||
State(state): State<Arc<WebState>>,
|
||||
Json(body): Json<SavePinnedTreeNodeIdsRequest>,
|
||||
) -> Result<Json<()>, AppError> {
|
||||
state.app.storage.save_pinned_tree_node_ids(&body.ids).await.map_err(AppError)?;
|
||||
Ok(Json(()))
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
pub mod agents;
|
||||
pub mod ai;
|
||||
pub mod app_settings;
|
||||
pub mod connection;
|
||||
pub mod database_export;
|
||||
pub mod history;
|
||||
|
||||
Reference in new issue
Block a user