V1 of laucher

This commit is contained in:
Kelorastus
2026-09-18 14:42:28 +02:00
parent 3fdfde7043
commit d5da361952
8 changed files with 338 additions and 32 deletions
+55 -3
View File
@@ -41,11 +41,58 @@ fn settings_path(app: &AppHandle) -> Result<PathBuf, String> {
Ok(dir.join("settings.json"))
}
/// Is this drive a disk built into the PC, rather than a USB key or a card?
///
/// A key plugged into a laptop takes D:, and ODIAN would install itself onto it: the
/// database restore then stalls on the key's write speed until it gives up, and the
/// install would vanish the moment someone unplugs it.
#[cfg(windows)]
fn is_fixed_drive(root: &str) -> bool {
use std::os::windows::ffi::OsStrExt;
use windows_sys::Win32::Storage::FileSystem::GetDriveTypeW;
/// GetDriveType's answer for a disk built into the PC (windows-sys does not export it).
const DRIVE_FIXED: u32 = 3;
let wide: Vec<u16> = std::ffi::OsStr::new(root).encode_wide().chain(std::iter::once(0)).collect();
unsafe { GetDriveTypeW(wide.as_ptr()) == DRIVE_FIXED }
}
#[cfg(not(windows))]
fn is_fixed_drive(_root: &str) -> bool {
false
}
/// Does this path sit on a USB key or a card? Choosing one by hand is allowed, but it is
/// worth saying out loud before an install spends half an hour failing on it.
#[cfg(windows)]
pub fn is_removable_path(path: &Path) -> bool {
use std::os::windows::ffi::OsStrExt;
use windows_sys::Win32::Storage::FileSystem::GetDriveTypeW;
/// GetDriveType's answer for a USB key or a card reader.
const DRIVE_REMOVABLE: u32 = 2;
let Some(std::path::Component::Prefix(prefix)) = path.components().next() else {
return false;
};
let root = format!("{}\\", prefix.as_os_str().to_string_lossy());
let wide: Vec<u16> = std::ffi::OsStr::new(&root).encode_wide().chain(std::iter::once(0)).collect();
unsafe { GetDriveTypeW(wide.as_ptr()) == DRIVE_REMOVABLE }
}
#[cfg(not(windows))]
pub fn is_removable_path(_path: &Path) -> bool {
false
}
fn default_install_dir() -> String {
// Operator PCs keep the ~1 TB of data off the system drive when a D: exists.
// Not %LOCALAPPDATA%\ODIAN: on the release PC that folder holds the release
// signing key, and deleting a test install must never be able to take it along.
if Path::new("D:\\").is_dir() {
if Path::new("D:\\").is_dir() && is_fixed_drive("D:\\") {
"D:\\ODIAN".to_string()
} else {
"C:\\ODIAN".to_string()
@@ -56,8 +103,13 @@ fn read_site_file() -> SiteFile {
let Some(dir) = std::env::current_exe().ok().and_then(|exe| exe.parent().map(Path::to_path_buf)) else {
return SiteFile::default();
};
std::fs::read(dir.join("site.json"))
.ok()
// Beside the exe is how a launcher copied onto a USB key is handed out, and where
// the NSIS installer puts the site it was built for. Tauri has moved bundled
// resources under `resources/` between versions, so look there too rather than
// silently starting with no site and asking the operator for an address.
["site.json", "resources/site.json"]
.iter()
.find_map(|name| std::fs::read(dir.join(name)).ok())
.and_then(|bytes| serde_json::from_slice(&bytes).ok())
.unwrap_or_default()
}