diff --git a/interface/src/combatlog.rs b/interface/src/combatlog.rs index 21371c9..3cd490d 100644 --- a/interface/src/combatlog.rs +++ b/interface/src/combatlog.rs @@ -1,12 +1,10 @@ -use std::time::{Duration, SystemTime, UNIX_EPOCH}; +use std::{path::Path, time::{Duration, SystemTime, UNIX_EPOCH}}; use anyhow::Ok; use common::{ControlPacket, TelemetryPacket}; use serde::{Deserialize, Serialize}; use tokio::{fs::File, io::AsyncWriteExt, sync::mpsc::Receiver, time::Instant}; -use crate::storage_dir::storage; - #[derive(Serialize, Deserialize)] pub enum CombatData { @@ -16,8 +14,8 @@ pub enum CombatData { type CombatLogRow = (CombatData, u128); -pub async fn combat_logger(mut data: Receiver) -> anyhow::Result<()> { - let mut path = storage(); +pub async fn combat_logger(mut data: Receiver, path: &Path) -> anyhow::Result<()> { + let mut path = path.to_path_buf(); let time = chrono::offset::Utc::now(); let formatted = time.to_rfc3339_opts(chrono::SecondsFormat::Secs, false); path.push(format!("{formatted}.combatlog")); diff --git a/interface/src/gui.rs b/interface/src/gui.rs index 38baf4f..5d19bb7 100644 --- a/interface/src/gui.rs +++ b/interface/src/gui.rs @@ -6,7 +6,7 @@ use image::ImageFormat; use tokio::{runtime::Runtime, sync::{mpsc, watch::{self, Receiver}}}; use egui_toast::{Toast, Toasts}; -use crate::{auto::Configurable, storage::StorageManager, storage_dir::storage_dir, POWER_THRESHOLD}; +use crate::{auto::Configurable, storage::StorageManager, POWER_THRESHOLD}; pub const GUI: OnceCell = OnceCell::new(); diff --git a/interface/src/lib.rs b/interface/src/lib.rs index f6f0ebb..8f92088 100644 --- a/interface/src/lib.rs +++ b/interface/src/lib.rs @@ -4,7 +4,6 @@ use atomic_float::AtomicF32; use gui::DEFAULT_VOLUME_THRESHOLD; pub mod gui; -pub mod storage_dir; pub mod combatlog; pub mod auto; pub mod storage; diff --git a/interface/src/main.rs b/interface/src/main.rs index dc438ea..1a94b94 100644 --- a/interface/src/main.rs +++ b/interface/src/main.rs @@ -17,7 +17,7 @@ fn main() -> Result<()> { let directories = ProjectDirs::from("dev", "ank", "Cruise Control").context("no home")?; let auto = Auto::new("../auto/target/release/libauto.so")?; - let storage = StorageManager::new(dbg!(directories.config_dir().to_path_buf().join(Path::new("conf.dat"))))?; + let storage = StorageManager::new(directories.config_dir().to_path_buf().join(Path::new("conf.dat")))?; println!("name: {}", auto.name()); @@ -98,7 +98,7 @@ fn main() -> Result<()> { spawner.block_on(async { let log_toasts = toast_sender.clone(); tokio::spawn(async move { - if let Err(e) = combat_logger(combatlog).await { + if let Err(e) = combat_logger(combatlog, directories.data_dir()).await { let _ = log_toasts.clone().send(Toast::new().text(format!("logger crashed: {e:?}")).kind(ToastKind::Error)).await; } }); diff --git a/interface/src/storage_dir.rs b/interface/src/storage_dir.rs deleted file mode 100644 index d5e3649..0000000 --- a/interface/src/storage_dir.rs +++ /dev/null @@ -1,157 +0,0 @@ -// copied from eframe (private item) -// https://docs.rs/eframe/latest/src/eframe/native/file_storage.rs.html#17 - -use std::path::PathBuf; - -use eframe::egui; - -pub fn storage() -> PathBuf { - storage_dir("cruisecontrol").unwrap() -} - -pub fn storage_dir(app_id: &str) -> Option { - - use egui::os::OperatingSystem as OS; - - use std::env::var_os; - - match OS::from_target_os() { - - OS::Nix => var_os("XDG_DATA_HOME") - - .map(PathBuf::from) - - .filter(|p| p.is_absolute()) - - .or_else(|| home::home_dir().map(|p| p.join(".local").join("share"))) - - .map(|p| { - - p.join( - - app_id - - .to_lowercase() - - .replace(|c: char| c.is_ascii_whitespace(), ""), - - ) - - }), - - OS::Mac => home::home_dir().map(|p| { - - p.join("Library") - - .join("Application Support") - - .join(app_id.replace(|c: char| c.is_ascii_whitespace(), "-")) - - }), - - OS::Windows => roaming_appdata().map(|p| p.join(app_id).join("data")), - - OS::Unknown | OS::Android | OS::IOS => None, - - } - -} - -// Adapted from - -// https://github.com/rust-lang/cargo/blob/6e11c77384989726bb4f412a0e23b59c27222c34/crates/home/src/windows.rs#L19-L37 - -#[cfg(all(windows, not(target_vendor = "uwp")))] - -#[allow(unsafe_code)] - -fn roaming_appdata() -> Option { - - use std::ffi::OsString; - - use std::os::windows::ffi::OsStringExt; - - use std::ptr; - - use std::slice; - - - use windows_sys::Win32::Foundation::S_OK; - - use windows_sys::Win32::System::Com::CoTaskMemFree; - - use windows_sys::Win32::UI::Shell::{ - - FOLDERID_RoamingAppData, SHGetKnownFolderPath, KF_FLAG_DONT_VERIFY, - - }; - - - extern "C" { - - fn wcslen(buf: *const u16) -> usize; - - } - - let mut path_raw = ptr::null_mut(); - - - // SAFETY: SHGetKnownFolderPath allocates for us, we don't pass any pointers to it. - - // See https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath - - let result = unsafe { - - SHGetKnownFolderPath( - - &FOLDERID_RoamingAppData, - - KF_FLAG_DONT_VERIFY as u32, - - std::ptr::null_mut(), - - &mut path_raw, - - ) - - }; - - - let path = if result == S_OK { - - // SAFETY: SHGetKnownFolderPath indicated success and is supposed to allocate a nullterminated string for us. - - let path_slice = unsafe { slice::from_raw_parts(path_raw, wcslen(path_raw)) }; - - Some(PathBuf::from(OsString::from_wide(path_slice))) - - } else { - - None - - }; - - - // SAFETY: - - // This memory got allocated by SHGetKnownFolderPath, we didn't touch anything in the process. - - // A null ptr is a no-op for `CoTaskMemFree`, so in case this failed we're still good. - - // https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-cotaskmemfree - - unsafe { CoTaskMemFree(path_raw.cast()) }; - - - path - -} - - -#[cfg(any(not(windows), target_vendor = "uwp"))] - -fn roaming_appdata() -> Option { - - None - -}