diff --git a/Cargo.lock b/Cargo.lock index 6b35ab98..e5f42879 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -181,6 +181,12 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.6.0" @@ -369,6 +375,27 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "directories" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "either" version = "1.11.0" @@ -531,6 +558,15 @@ dependencies = [ "slab", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -838,6 +874,16 @@ dependencies = [ "windows-targets 0.52.5", ] +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.5.0", + "libc", +] + [[package]] name = "libsqlite3-sys" version = "0.28.0" @@ -893,7 +939,7 @@ dependencies = [ [[package]] name = "makepad-derive-live" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" dependencies = [ "makepad-live-id", "makepad-micro-proc-macro", @@ -902,7 +948,7 @@ dependencies = [ [[package]] name = "makepad-derive-wasm-bridge" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" dependencies = [ "makepad-micro-proc-macro", ] @@ -910,7 +956,7 @@ dependencies = [ [[package]] name = "makepad-derive-widget" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" dependencies = [ "makepad-live-id", "makepad-micro-proc-macro", @@ -919,9 +965,10 @@ dependencies = [ [[package]] name = "makepad-draw" version = "0.6.0" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" dependencies = [ "ab_glyph_rasterizer", + "fxhash", "makepad-html", "makepad-platform", "makepad-rustybuzz", @@ -933,17 +980,17 @@ dependencies = [ [[package]] name = "makepad-futures" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" [[package]] name = "makepad-futures-legacy" version = "0.7.0" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" [[package]] name = "makepad-html" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" dependencies = [ "makepad-live-id", ] @@ -951,7 +998,7 @@ dependencies = [ [[package]] name = "makepad-http" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" [[package]] name = "makepad-jni-sys" @@ -962,7 +1009,7 @@ checksum = "9775cbec5fa0647500c3e5de7c850280a88335d1d2d770e5aa2332b801ba7064" [[package]] name = "makepad-live-compiler" version = "0.5.0" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" dependencies = [ "makepad-derive-live", "makepad-live-tokenizer", @@ -972,7 +1019,7 @@ dependencies = [ [[package]] name = "makepad-live-id" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" dependencies = [ "makepad-live-id-macros", ] @@ -980,7 +1027,7 @@ dependencies = [ [[package]] name = "makepad-live-id-macros" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" dependencies = [ "makepad-micro-proc-macro", ] @@ -988,7 +1035,7 @@ dependencies = [ [[package]] name = "makepad-live-tokenizer" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" dependencies = [ "makepad-live-id", "makepad-math", @@ -998,7 +1045,7 @@ dependencies = [ [[package]] name = "makepad-markdown" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" dependencies = [ "makepad-live-id", ] @@ -1006,17 +1053,17 @@ dependencies = [ [[package]] name = "makepad-math" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" [[package]] name = "makepad-micro-proc-macro" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" [[package]] name = "makepad-micro-serde" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" dependencies = [ "makepad-micro-serde-derive", ] @@ -1024,7 +1071,7 @@ dependencies = [ [[package]] name = "makepad-micro-serde-derive" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" dependencies = [ "makepad-micro-proc-macro", ] @@ -1032,12 +1079,12 @@ dependencies = [ [[package]] name = "makepad-objc-sys" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" [[package]] name = "makepad-platform" version = "0.6.0" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" dependencies = [ "makepad-android-state", "makepad-futures", @@ -1055,7 +1102,7 @@ dependencies = [ [[package]] name = "makepad-rustybuzz" version = "0.8.0" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" dependencies = [ "bitflags 1.3.2", "bytemuck", @@ -1070,7 +1117,7 @@ dependencies = [ [[package]] name = "makepad-shader-compiler" version = "0.5.0" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" dependencies = [ "makepad-live-compiler", ] @@ -1078,7 +1125,7 @@ dependencies = [ [[package]] name = "makepad-vector" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" dependencies = [ "ttf-parser", ] @@ -1086,7 +1133,7 @@ dependencies = [ [[package]] name = "makepad-wasm-bridge" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" dependencies = [ "makepad-derive-wasm-bridge", "makepad-live-id", @@ -1095,7 +1142,7 @@ dependencies = [ [[package]] name = "makepad-widgets" version = "0.6.0" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" dependencies = [ "makepad-derive-widget", "makepad-draw", @@ -1108,7 +1155,7 @@ dependencies = [ [[package]] name = "makepad-windows" version = "0.51.1" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" dependencies = [ "windows-core 0.51.1", "windows-targets 0.48.5", @@ -1117,7 +1164,7 @@ dependencies = [ [[package]] name = "makepad-zune-core" version = "0.2.14" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" dependencies = [ "bitflags 2.5.0", ] @@ -1125,7 +1172,7 @@ dependencies = [ [[package]] name = "makepad-zune-inflate" version = "0.2.54" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" dependencies = [ "simd-adler32", ] @@ -1133,7 +1180,7 @@ dependencies = [ [[package]] name = "makepad-zune-jpeg" version = "0.3.17" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" dependencies = [ "makepad-zune-core", ] @@ -1141,7 +1188,7 @@ dependencies = [ [[package]] name = "makepad-zune-png" version = "0.2.1" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" dependencies = [ "makepad-zune-core", "makepad-zune-inflate", @@ -1191,6 +1238,7 @@ version = "0.1.0" dependencies = [ "anyhow", "chrono", + "directories", "lipsum", "makepad-widgets", "moxin-backend", @@ -1210,6 +1258,7 @@ dependencies = [ "anyhow", "chrono", "crossbeam", + "directories", "futures-util", "log", "moxin-protocol", @@ -1378,6 +1427,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "parking_lot" version = "0.12.2" @@ -1545,6 +1600,17 @@ dependencies = [ "bitflags 2.5.0", ] +[[package]] +name = "redox_users" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + [[package]] name = "regex" version = "1.10.4" @@ -2139,9 +2205,8 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "ttf-parser" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49d64318d8311fc2668e48b63969f4343e0a85c4a109aa8460d6672e364b8bd1" +version = "0.19.0" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" [[package]] name = "typenum" @@ -2473,7 +2538,7 @@ dependencies = [ [[package]] name = "windows-core" version = "0.51.1" -source = "git+https://github.com/makepad/makepad?branch=rik#bd972c6d386e839b3cf885f36099583420cbec01" +source = "git+https://github.com/makepad/makepad?branch=rik#867b756da30a7ebf6b600307dc7fd778c649a05d" dependencies = [ "windows-targets 0.48.5", ] diff --git a/Cargo.toml b/Cargo.toml index c7c13f9e..c58b500f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ makepad-widgets = { git = "https://github.com/makepad/makepad", branch = "rik" } robius-open = { git = "https://github.com/project-robius/robius-open", rev = "b901523667d4a8bbb0bba3cd1ebcc0b94d33534e" } chrono = "0.4" +directories = "5.0.1" unicode-segmentation = "1.10.1" anyhow = "1.0" serde_json = "1.0" diff --git a/moxin-backend/Cargo.toml b/moxin-backend/Cargo.toml index 5ce218e0..05e3ae0a 100644 --- a/moxin-backend/Cargo.toml +++ b/moxin-backend/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" [dependencies] moxin-protocol = { path = "../moxin-protocol" } chrono = "0.4" +directories = "5.0.1" wasmedge-sdk = { version = "=0.13.5-newapi", default-features = false, features = [ "wasi_nn", ] } diff --git a/moxin-backend/src/backend_impls.rs b/moxin-backend/src/backend_impls.rs index b5d388d9..b18fd46c 100644 --- a/moxin-backend/src/backend_impls.rs +++ b/moxin-backend/src/backend_impls.rs @@ -1,6 +1,6 @@ -use std::sync::{ - mpsc::{Receiver, Sender}, - Arc, Mutex, +use std::{ + path::{Path, PathBuf}, + sync::{mpsc::{Receiver, Sender}, Arc, Mutex}, }; use chrono::Utc; @@ -825,8 +825,8 @@ pub enum DownloadControlCommand { pub struct BackendImpl { sql_conn: Arc>, #[allow(unused)] - home_dir: String, - models_dir: String, + app_data_dir: PathBuf, + models_dir: PathBuf, pub rx: Receiver, download_tx: tokio::sync::mpsc::UnboundedSender<( store::models::Model, @@ -841,19 +841,21 @@ pub struct BackendImpl { } impl BackendImpl { - /// # Argument - /// - /// * `home_dir` - The home directory of the application. - /// * `models_dir` - The download path of the model. + /// # Arguments + /// * `app_data_dir` - The directory where application data should be stored. + /// * `models_dir` - The directory where models should be downloaded. /// * `max_download_threads` - Maximum limit on simultaneous file downloads. - pub fn build_command_sender( - home_dir: String, - models_dir: String, + pub fn build_command_sender, M: AsRef>( + app_data_dir: A, + models_dir: M, max_download_threads: usize, ) -> Sender { + let app_data_dir = app_data_dir.as_ref().to_path_buf(); wasmedge_sdk::plugin::PluginManager::load(None).unwrap(); - - let sql_conn = rusqlite::Connection::open(format!("{home_dir}/data.sqlite")).unwrap(); + std::fs::create_dir_all(&app_data_dir).unwrap_or_else(|_| + panic!("Failed to create the Moxin app data directory at {:?}", app_data_dir) + ); + let sql_conn = rusqlite::Connection::open(app_data_dir.join("data.sqlite")).unwrap(); // TODO Reorganize these bunch of functions, needs a little more of thought let _ = store::models::create_table_models(&sql_conn).unwrap(); @@ -883,8 +885,8 @@ impl BackendImpl { let mut backend = Self { sql_conn, - home_dir, - models_dir, + app_data_dir, + models_dir: models_dir.as_ref().into(), rx, download_tx, model: None, @@ -978,7 +980,7 @@ impl BackendImpl { reverse_prompt: remote_model.reverse_prompt, downloaded: false, file_size: 0, - download_dir: self.models_dir.clone(), + download_dir: self.models_dir.to_string_lossy().to_string(), downloaded_at: Utc::now(), tags:remote_file.tags, featured: false, @@ -1011,7 +1013,7 @@ impl BackendImpl { let conn = self.sql_conn.lock().unwrap(); let _ = store::download_files::DownloadedFile::remove(&file_id, &conn); } - let _ = store::remove_downloaded_file(self.models_dir.clone(), file_id); + let _ = store::remove_downloaded_file(self.models_dir.to_string_lossy().to_string(), file_id); let _ = tx.send(Ok(())); } @@ -1022,7 +1024,7 @@ impl BackendImpl { let _ = store::download_files::DownloadedFile::remove(&file_id, &conn); } - let _ = store::remove_downloaded_file(self.models_dir.clone(), file_id); + let _ = store::remove_downloaded_file(self.models_dir.to_string_lossy().to_string(), file_id); let _ = tx.send(Ok(())); } diff --git a/moxin-backend/src/lib.rs b/moxin-backend/src/lib.rs index 4da9e6ce..1cc88147 100644 --- a/moxin-backend/src/lib.rs +++ b/moxin-backend/src/lib.rs @@ -2,7 +2,8 @@ mod backend_impls; mod store; use moxin_protocol::protocol::Command; -use std::sync::mpsc; +use std::{path::Path, sync::{mpsc, OnceLock}}; +use directories::ProjectDirs; pub struct Backend { pub command_sender: mpsc::Sender, @@ -10,24 +11,44 @@ pub struct Backend { impl Default for Backend { fn default() -> Self { - // TODO: FIXME: use directories::ProjectDirs::data_dir() instead. - // - let home_dir = std::env::var("HOME") // Unix-like systems - .or_else(|_| std::env::var("USERPROFILE")) // Windows - .unwrap_or_else(|_| ".".to_string()); - Backend::new(home_dir.clone(), home_dir, 3) + // TODO: FIXME: this has been copied from , + // but should be deduplicated into a separate file shared between + // the frontend and backend (perhaps in moxin-protocol?).. + pub const APP_QUALIFIER: &str = "com"; + pub const APP_ORGANIZATION: &str = "moxin-org"; + pub const APP_NAME: &str = "moxin"; + + pub fn project_dirs() -> &'static ProjectDirs { + // This can be redesigned once std::sync::LazyLock is stabilized. + static MOXIN_PROJECT_DIRS: OnceLock = OnceLock::new(); + + MOXIN_PROJECT_DIRS.get_or_init(|| { + ProjectDirs::from(APP_QUALIFIER, APP_ORGANIZATION, APP_NAME) + .expect("Failed to obtain Moxin project directories") + }) + } + + pub const MODEL_DOWNLOADS_DIR_NAME: &str = "model_downloads"; + // end of copied code from + + let app_data_dir = project_dirs().data_dir(); + let models_dir = app_data_dir.join(MODEL_DOWNLOADS_DIR_NAME); + Backend::new(app_data_dir, models_dir, 3) } } impl Backend { - /// # Argument - /// - /// * `home_dir` - The home directory of the application. - /// * `models_dir` - The download path of the model. + /// # Arguments + /// * `app_data_dir` - The directory where application data should be stored. + /// * `models_dir` - The directory where models should be downloaded. /// * `max_download_threads` - Maximum limit on simultaneous file downloads. - pub fn new(home_dir: String, models_dir: String, max_download_threads: usize) -> Backend { + pub fn new, M: AsRef>( + app_data_dir: A, + models_dir: M, + max_download_threads: usize, + ) -> Backend { let command_sender = backend_impls::BackendImpl::build_command_sender( - home_dir, + app_data_dir, models_dir, max_download_threads, ); diff --git a/src/data/filesystem.rs b/src/data/filesystem.rs index 28c31b65..da329f1a 100644 --- a/src/data/filesystem.rs +++ b/src/data/filesystem.rs @@ -1,35 +1,29 @@ -use std::path::PathBuf; -use std::{env, fs}; +use std::{path::PathBuf, sync::OnceLock}; +use directories::ProjectDirs; -// Note that .moxin will create a hidden folder in unix-like systems. -// However in Windows the folder will be visible by default. -pub const DEFAULT_DOWNLOADS_DIR: &str = ".moxin/model_downloads"; -pub const MOXIN_HOME_DIR: &str = ".moxin"; +pub const APP_QUALIFIER: &str = "com"; +pub const APP_ORGANIZATION: &str = "moxin-org"; +pub const APP_NAME: &str = "moxin"; -pub fn setup_model_downloads_folder() -> String { - let home_dir = home_dir(); - let downloads_dir = PathBuf::from(home_dir).join(DEFAULT_DOWNLOADS_DIR); +pub fn project_dirs() -> &'static ProjectDirs { + // This can be redesigned once std::sync::LazyLock is stabilized. + static MOXIN_PROJECT_DIRS: OnceLock = OnceLock::new(); - if fs::create_dir_all(&downloads_dir).is_err() { - eprintln!( - "Failed to create the model downloads directory at '{}'. Using current directory as fallback.", - downloads_dir.display() - ); - ".".to_string() - } else { - downloads_dir.to_string_lossy().to_string() - } + MOXIN_PROJECT_DIRS.get_or_init(|| { + ProjectDirs::from(APP_QUALIFIER, APP_ORGANIZATION, APP_NAME) + .expect("Failed to obtain Moxin project directories") + }) } -fn home_dir() -> String { - // TODO: FIXME: use directories::ProjectDirs::data_dir() instead. - // - env::var("HOME") // Unix-like systems - .or_else(|_| env::var("USERPROFILE")) // Windows - .unwrap_or_else(|_| ".".to_string()) -} +pub const MODEL_DOWNLOADS_DIR_NAME: &str = "model_downloads"; + +pub fn setup_model_downloads_folder() -> PathBuf { + let downloads_dir = project_dirs() + .data_dir() + .join(MODEL_DOWNLOADS_DIR_NAME); -pub fn moxin_home_dir() -> PathBuf { - let home_dir = home_dir(); - PathBuf::from(home_dir).join(MOXIN_HOME_DIR) + std::fs::create_dir_all(&downloads_dir).unwrap_or_else(|_| + panic!("Failed to create the model downloads directory at {:?}", downloads_dir) + ); + downloads_dir } diff --git a/src/data/preferences.rs b/src/data/preferences.rs index 1c4b9048..075c60e5 100644 --- a/src/data/preferences.rs +++ b/src/data/preferences.rs @@ -7,8 +7,8 @@ use std::{ use moxin_protocol::data::FileID; use serde::{Deserialize, Serialize}; -use super::filesystem::moxin_home_dir; -const PREFERENCES_FILE: &str = "preferences.json"; +use super::filesystem::project_dirs; +const PREFERENCES_FILENAME: &str = "preferences.json"; #[derive(Serialize, Deserialize, Debug, Clone, Default)] pub struct Preferences { @@ -71,7 +71,11 @@ fn write_to_file(json: &str) -> Result<(), std::io::Error> { } fn preferences_path() -> PathBuf { - let home_dir = moxin_home_dir(); - let preferences_path = PathBuf::from(home_dir).join(PREFERENCES_FILE); - preferences_path + let preference_dir = project_dirs().preference_dir(); + // TODO: this is overkill to create the directory every time. + // This should be done somewhere during init, but I'm not sure where. + std::fs::create_dir_all(&preference_dir).unwrap_or_else(|_| + panic!("Failed to create the preference directory at {:?}", preference_dir) + ); + preference_dir.join(PREFERENCES_FILENAME) } diff --git a/src/data/store.rs b/src/data/store.rs index 1283ff3e..38187fc2 100644 --- a/src/data/store.rs +++ b/src/data/store.rs @@ -1,6 +1,6 @@ use super::chat::ChatID; use super::download::DownloadState; -use super::filesystem::{moxin_home_dir, setup_model_downloads_folder}; +use super::filesystem::{project_dirs, setup_model_downloads_folder}; use super::preferences::Preferences; use super::{chat::Chat, download::Download, search::Search}; use anyhow::{Context, Result}; @@ -11,9 +11,12 @@ use moxin_protocol::data::{ DownloadedFile, File, FileID, Model, PendingDownload, PendingDownloadsStatus, }; use moxin_protocol::protocol::{Command, LoadModelOptions, LoadModelResponse}; -use std::cell::RefCell; -use std::collections::HashMap; -use std::sync::mpsc::channel; +use std::{ + cell::RefCell, + collections::HashMap, + path::PathBuf, + sync::mpsc::channel, +}; pub const DEFAULT_MAX_DOWNLOAD_THREADS: usize = 3; @@ -84,16 +87,16 @@ pub struct Store { pub current_downloads: HashMap, pub preferences: Preferences, - pub downloaded_files_dir: String, + pub downloaded_files_dir: PathBuf, } impl Store { pub fn new() -> Self { let downloaded_files_dir = setup_model_downloads_folder(); - let moxin_home_dir = moxin_home_dir().to_string_lossy().to_string(); + let app_data_dir = project_dirs().data_dir(); let backend = Backend::new( - moxin_home_dir, + app_data_dir, downloaded_files_dir.clone(), DEFAULT_MAX_DOWNLOAD_THREADS, ); diff --git a/src/my_models/my_models_screen.rs b/src/my_models/my_models_screen.rs index dcc9db77..75a314bf 100644 --- a/src/my_models/my_models_screen.rs +++ b/src/my_models/my_models_screen.rs @@ -213,7 +213,7 @@ impl WidgetMatchEvent for MyModelsScreen { fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions, scope: &mut Scope) { if self.button(id!(show_in_files)).clicked(actions) { let models_dir = &scope.data.get::().unwrap().downloaded_files_dir; - let models_uri = &format!("file:///.{}", models_dir); + let models_uri = &format!("file:///{}", models_dir.display()); robius_open::Uri::new(models_uri) .open() .unwrap_or_else(|_| {