diff --git a/README.md b/README.md index 2c9c5ad4..2f3e1155 100644 --- a/README.md +++ b/README.md @@ -20,9 +20,9 @@ - **Cross-platform support** | OS | Supported | |---------|-----------| - | Windows | ✔️ | - | Linux | ✔️ | - | macOS | ❌ | + | Windows | ✔️ | + | Linux | ✔️ | + | macOS | ✔️ | - **Support for every major Linux terminal emulator**
List of supported terminals diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index d6c36241..03b995b0 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -11,6 +11,7 @@ edition = "2021" tauri-build = { version = "2.0.0-rc.11", features = [] } [dependencies] +fix-path-env = { git = "https://github.com/tauri-apps/fix-path-env-rs" } tauri = { version = "2.0.0-rc.14", features = [] } tauri-plugin-shell = "2.0.0-rc.3" tauri-plugin-dialog = "2.0.0-rc.7" @@ -18,6 +19,9 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" derive-getters = "0.5.0" sha256 = "1.5.0" -reqwest = { version = "0.12.7" } +reqwest = { version = "0.12.7",features = ["blocking"] } zip = "2.2.0" async-process = "2.3.0" + +[profile.dev] +incremental = true diff --git a/src-tauri/src/depotdownloader.rs b/src-tauri/src/depotdownloader.rs index 8d4e224d..1c538652 100644 --- a/src-tauri/src/depotdownloader.rs +++ b/src-tauri/src/depotdownloader.rs @@ -3,9 +3,11 @@ use std::io::ErrorKind::AlreadyExists; use std::{fs, io}; use std::{io::Write, path::Path}; +use crate::get_os; use reqwest; use sha256; -use crate::get_os; + +pub static DEPOTDOWNLOADER_VERSION: &str = "2.7.2"; pub fn calc_checksum(path: &Path) -> io::Result { let bytes = fs::read(path)?; @@ -13,6 +15,20 @@ pub fn calc_checksum(path: &Path) -> io::Result { Ok(hash) } +/** +See: [`test_get_depotdownloader_url()`] +*/ +pub fn get_depotdownloader_url() -> String { + let arch = match std::env::consts::ARCH { + "x86_64" => "x64", + "aarch64" => "arm64", + "arm" => "arm", + _ => "x86_64", + }; + + format!("https://github.com/SteamRE/DepotDownloader/releases/download/DepotDownloader_{}/DepotDownloader-{}-{}.zip", DEPOTDOWNLOADER_VERSION, get_os(), arch) +} + /// Downloads a file. The file will be saved to the [`filename`] provided. pub async fn download_file(url: &str, filename: &Path) -> io::Result<()> { if filename.exists() { @@ -75,3 +91,25 @@ pub fn unzip(zip_file: &Path) -> io::Result<()> { } Ok(()) } + +#[cfg(test)] +mod tests { + use super::*; + use reqwest::blocking; + + #[test] + /// checks if all possible DepotDownloader URLs exist. + fn test_get_depotdownloader_url() { + for os in ["windows", "linux", "macos"].iter() { + for arch in ["x64", "arm64", "arm"].iter() { + if arch.eq(&"arm") && !os.eq(&"linux") { + continue; + } + let url = format!("https://github.com/SteamRE/DepotDownloader/releases/download/DepotDownloader_{}/DepotDownloader-{}-{}.zip", DEPOTDOWNLOADER_VERSION, os, arch); + println!("Testing DepotDownloader URL: {}", url); + + assert!(blocking::get(url).unwrap().status().is_success()); + } + } + } +} diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 08d17de1..ba78ebd2 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -1,37 +1,39 @@ // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] -use std::{env, io}; +use std::env; +use std::io; use std::path::Path; use std::sync::OnceLock; use std::time::Duration; +use crate::depotdownloader::{get_depotdownloader_url, DEPOTDOWNLOADER_VERSION}; +use crate::terminal::Terminal; use tauri::{AppHandle, Emitter}; -use crate::terminal::Terminal; - -mod steam; mod depotdownloader; +mod steam; mod terminal; -static DEPOTDOWNLOADER_VERSION: &str = "2.7.1"; -//TODO: arm -static DEPOTDOWNLOADER_LINUX_URL: &str = "https://github.com/SteamRE/DepotDownloader/releases/download/DepotDownloader_2.7.1/DepotDownloader-linux-x64.zip"; -static DEPOTDOWNLOADER_WIN_URL: &str = "https://github.com/SteamRE/DepotDownloader/releases/download/DepotDownloader_2.7.1/DepotDownloader-windows-x64.zip"; -static DEPOTDOWNLOADER_MAC_URL: &str = "https://github.com/SteamRE/DepotDownloader/releases/download/DepotDownloader_2.7.1/DepotDownloader-macos-x64.zip"; - - -// We create this variable now, and quickly populate it in preload_vectum(). Then we later access the data in start_download() -static TERMINAL: OnceLock> = OnceLock::new(); +/// The first terminal found. Used as default terminal. +static TERMINAL: OnceLock> = OnceLock::new(); // We create this variable now, and quickly populate it in preload_vectum(). we then later access the data in start_download() /// This function is called every time the app is reloaded/started. It quickly populates the [`TERMINAL`] variable with a working terminal. #[tauri::command] async fn preload_vectum(app: AppHandle) { // Only fill this variable once. - if TERMINAL.get().is_none() { TERMINAL.set(terminal::get_installed_terminals(true).await).expect("Failed to set available terminals") } + if TERMINAL.get().is_none() { + TERMINAL + .set(terminal::get_installed_terminals(true).await) + .expect("Failed to set available terminals") + } // Send the default terminal name to the frontend. - app.emit("default-terminal", Terminal::pretty_name(&TERMINAL.get().unwrap()[0])).unwrap(); + app.emit( + "default-terminal", + Terminal::pretty_name(&TERMINAL.get().unwrap()[0]), + ) + .unwrap(); } #[tauri::command] @@ -58,36 +60,30 @@ async fn start_download(steam_download: steam::SteamDownload) { terminal_to_use.create_command(&steam_download).spawn().ok(); } - /// Downloads the DepotDownloader zip file from the internet based on the OS. #[tauri::command] async fn download_depotdownloader() { - let url = match get_os() { - "linux" => DEPOTDOWNLOADER_LINUX_URL, - "macos" => DEPOTDOWNLOADER_MAC_URL, - "windows" => DEPOTDOWNLOADER_WIN_URL, - _ => DEPOTDOWNLOADER_LINUX_URL, - }; - + let url = get_depotdownloader_url(); + // Where we store the DepotDownloader zip. let zip_filename = format!("DepotDownloader-v{}-{}.zip", DEPOTDOWNLOADER_VERSION, env::consts::OS); let depotdownloader_zip = Path::new(&zip_filename); - println!("Downloading DepotDownloader for {} to .{}{}", env::consts::OS, std::path::MAIN_SEPARATOR, depotdownloader_zip.display()); + println!("Downloading DepotDownloader for {} to {}/{}", env::consts::OS, std::path::current_dir(), depotdownloader_zip.display()); - match depotdownloader::download_file(url, depotdownloader_zip).await { + match depotdownloader::download_file(url.as_str(), depotdownloader_zip).await { Err(e) => { if e.kind() == io::ErrorKind::AlreadyExists { println!("DepotDownloader already exists. Skipping download."); return; } - + println!("Failed to download DepotDownloader: {}", e); return; }, _ => {} } - + println!("Succesfully downloaded DepotDownloader from {}", url); depotdownloader::unzip(depotdownloader_zip).unwrap(); @@ -102,14 +98,13 @@ async fn internet_connection() -> bool { client.get("https://connectivitycheck.android.com/generate_204").send().await.is_ok() } - #[tauri::command] async fn get_all_terminals(app: AppHandle) { let terminals = terminal::get_installed_terminals(false).await; terminals.iter().for_each(|terminal| { println!("Terminal #{} ({}) is installed!", terminal.index().unwrap(), terminal.pretty_name()); - + // Sends: (terminal index aligned with dropdown; total terminals) app.emit("working-terminal", (terminal.index(), Terminal::total())).unwrap(); }); @@ -125,12 +120,31 @@ pub fn get_os() -> &'static str { } fn main() { + // macOS: change dir to documents because upon opening, our current dir by default is "/". + if get_os() == "macos" { + let _ = fix_path_env::fix(); // todo: does this actually do something useful + let documents_dir = format!( + "{}/Documents/SteamDepotDownloaderGUI", + std::env::var_os("HOME").unwrap().to_str().unwrap() + ); + let documents_dir = Path::new(&documents_dir); + // println!("{}", documents_dir.display()); + + std::fs::create_dir_all(documents_dir).unwrap(); + env::set_current_dir(documents_dir).unwrap(); + } + println!(); - tauri::Builder::default().plugin(tauri_plugin_dialog::init()).plugin(tauri_plugin_shell::init()).invoke_handler(tauri::generate_handler![ + tauri::Builder::default() + .plugin(tauri_plugin_dialog::init()) + .plugin(tauri_plugin_shell::init()) + .invoke_handler(tauri::generate_handler![ start_download, download_depotdownloader, internet_connection, preload_vectum, get_all_terminals - ]).run(tauri::generate_context!()).expect("error while running tauri application"); + ]) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); }