add preferences and macOS packaging

This commit is contained in:
Georg Bauer
2026-07-24 12:23:50 +02:00
parent 2e1de825ab
commit 579e1030b2
13 changed files with 591 additions and 79 deletions

View File

@@ -4,10 +4,39 @@ use std::collections::HashMap;
use std::fs;
use std::path::Path;
use crate::schema::{projects, sessions};
use crate::schema::{preferences, projects, sessions};
pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("migrations");
#[derive(Clone, Debug, Identifiable, Queryable, Selectable)]
#[diesel(table_name = preferences)]
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
pub struct AppPreferences {
pub id: i32,
pub selected_model: String,
pub dflash_enabled: bool,
pub idle_timeout_minutes: i32,
}
impl Default for AppPreferences {
fn default() -> Self {
Self {
id: 1,
selected_model: "deepseek-v4-flash".into(),
dflash_enabled: false,
idle_timeout_minutes: 10,
}
}
}
#[derive(AsChangeset)]
#[diesel(table_name = preferences)]
struct PreferenceChanges<'a> {
selected_model: &'a str,
dflash_enabled: bool,
idle_timeout_minutes: i32,
}
#[derive(Clone, Debug, Identifiable, Queryable, Selectable)]
#[diesel(table_name = projects)]
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
@@ -95,6 +124,31 @@ impl Database {
.collect())
}
pub fn load_preferences(&mut self) -> Result<AppPreferences, String> {
preferences::table
.find(1)
.select(AppPreferences::as_select())
.first(&mut self.connection)
.map_err(|error| error.to_string())
}
pub fn update_preferences(
&mut self,
selected_model: &str,
dflash_enabled: bool,
idle_timeout_minutes: i32,
) -> Result<AppPreferences, String> {
diesel::update(preferences::table.find(1))
.set(PreferenceChanges {
selected_model,
dflash_enabled,
idle_timeout_minutes,
})
.returning(AppPreferences::as_returning())
.get_result(&mut self.connection)
.map_err(|error| error.to_string())
}
pub fn create_project(&mut self, name: &str, path: &str) -> Result<Project, String> {
diesel::insert_into(projects::table)
.values(NewProject { name, path })
@@ -144,6 +198,18 @@ mod tests {
let path = std::env::temp_dir().join(format!("ds4-server-{id}.sqlite3"));
let mut database = Database::open(&path).unwrap();
let preferences = database.load_preferences().unwrap();
assert_eq!(preferences.selected_model, "deepseek-v4-flash");
assert!(!preferences.dflash_enabled);
assert_eq!(preferences.idle_timeout_minutes, 10);
assert!(database.update_preferences("glm-5.2", true, 30).is_err());
assert!(
database
.update_preferences("deepseek-v4-flash", false, 0)
.is_err()
);
database.update_preferences("glm-5.2", false, 30).unwrap();
let project = database.create_project("DS4", "/tmp/ds4").unwrap();
let first = database
.create_session(project.id, "First session")
@@ -158,6 +224,12 @@ mod tests {
database.delete_project(project.id).unwrap();
assert!(database.load_projects().unwrap().is_empty());
drop(database);
let mut reopened = Database::open(&path).unwrap();
let preferences = reopened.load_preferences().unwrap();
assert_eq!(preferences.selected_model, "glm-5.2");
assert_eq!(preferences.idle_timeout_minutes, 30);
drop(reopened);
fs::remove_file(path).unwrap();
}
}