Almost finished with new launcher

This commit is contained in:
2025-10-31 09:33:41 -07:00
parent 3b5bd13b1c
commit df951d90c6
64 changed files with 994 additions and 1424 deletions

View File

@@ -1,8 +0,0 @@
pub struct Keys;
impl Keys {
pub const SERVER_RECEIVE_TRANSFER_KEY: &str = "";
pub const SERVER_SEND_TRANSFER_KEY: &str = "";
pub const CONFIG_ENCRYPTION_KEY: &str = "";
pub const VERSIONS_ENCRYPTION_KEY: &str = "";
}

View File

@@ -1,10 +1,7 @@
mod keys;
use futures_util::stream::StreamExt;
use keys::Keys;
use std::{
fs::{File, create_dir_all},
io::{BufReader, Write, copy},
io::{BufReader, copy},
path::PathBuf,
process::Command,
time::Duration,
@@ -14,7 +11,7 @@ use tauri::{AppHandle, Emitter, Manager};
use tauri_plugin_dialog::{DialogExt, MessageDialogKind};
use tauri_plugin_opener::OpenerExt;
use tauri_plugin_os::platform;
use tokio::{io::AsyncWriteExt, task::spawn_blocking, time::timeout};
use tokio::{io::AsyncWriteExt, time::timeout};
use zip::ZipArchive;
#[cfg(target_os = "linux")]
@@ -22,8 +19,19 @@ use std::{fs, os::unix::fs::PermissionsExt};
#[cfg(target_os = "windows")]
use tauri_plugin_decorum::WebviewWindowExt;
pub async fn unzip_to_dir(zip_path: PathBuf, out_dir: PathBuf) -> zip::result::ZipResult<()> {
spawn_blocking(move || {
fn is_running_by_path(path: &PathBuf) -> bool {
let sys = System::new_all();
sys.processes().values().any(|proc| {
if let Some(exe) = proc.exe() {
exe == path
} else {
false
}
})
}
async fn unzip_to_dir(zip_path: PathBuf, out_dir: PathBuf) -> String {
let res = tauri::async_runtime::spawn_blocking(move || {
let file = File::open(zip_path)?;
let mut archive = ZipArchive::new(BufReader::new(file))?;
@@ -42,39 +50,23 @@ pub async fn unzip_to_dir(zip_path: PathBuf, out_dir: PathBuf) -> zip::result::Z
}
}
Ok(())
Ok::<(), zip::result::ZipError>(())
})
.await
.map_err(|e| zip::result::ZipError::Io(std::io::Error::new(std::io::ErrorKind::Other, e)))?
.await;
match res {
Ok(Ok(())) => "1".into(),
_ => "-1".into(),
}
}
fn is_running_by_path(path: &PathBuf) -> bool {
let sys = System::new_all();
sys.processes().values().any(|proc| {
if let Some(exe) = proc.exe() {
exe == path
} else {
false
}
})
}
#[allow(unused_variables)]
#[tauri::command]
async fn download(
app: AppHandle,
url: String,
name: String,
executable: String,
) -> Result<(), String> {
app.emit("download-started", &name).unwrap();
async fn download(app: AppHandle, url: String, name: String, executable: String) -> String {
let client = reqwest::Client::new();
let resp = match client.get(&url).send().await {
Ok(r) => r,
Err(e) => {
app.emit("download-failed", &name).unwrap();
return Err(e.to_string());
Err(_) => {
return "-1".to_string();
}
};
let total_size = resp.content_length().unwrap_or(0);
@@ -102,15 +94,13 @@ async fn download(
while let Ok(Some(chunk_result)) = timeout(Duration::from_secs(5), stream.next()).await {
let chunk = match chunk_result {
Ok(c) => c,
Err(e) => {
app.emit("download-failed", &name).unwrap();
return Err(e.to_string());
Err(_) => {
return "-1".to_string();
}
};
if let Err(e) = file.write_all(&chunk).await {
app.emit("download-failed", &name).unwrap();
return Err(e.to_string());
if let Err(_) = file.write_all(&chunk).await {
return "-1".to_string();
}
downloaded += chunk.len() as u64;
@@ -126,8 +116,7 @@ async fn download(
}
if total_size > 0 && downloaded < total_size {
app.emit("download-failed", &name).unwrap();
return Err("Download incomplete".into());
return "-1".to_string();
}
tokio::fs::rename(
@@ -136,12 +125,13 @@ async fn download(
)
.await
.unwrap();
unzip_to_dir(download_zip_path.clone(), game_path.join(&name))
.await
.map_err(|e| e.to_string())?;
let unzip_res = unzip_to_dir(download_zip_path.clone(), game_path.join(&name)).await;
tokio::fs::remove_file(download_zip_path.clone())
.await
.unwrap();
if unzip_res == "-1" {
return "-1".to_string();
}
#[cfg(target_os = "linux")]
{
@@ -152,7 +142,10 @@ async fn download(
}
#[cfg(target_os = "macos")]
{
let macos_app_path = &game_path
use std::fs;
use std::os::unix::fs::PermissionsExt;
let macos_app_path = game_path
.join(&name)
.join(&executable)
.join("Contents")
@@ -160,21 +153,15 @@ async fn download(
.join(
&executable
.chars()
.take(&executable.chars().count() - 4)
.take(executable.chars().count() - 4)
.collect::<String>(),
);
let _ = Command::new("osascript")
.arg("-e")
.arg(format!(
"do shell script \"chmod 755 \\\"{}\\\"\" with prompt \"Administrator is required to make Berry Dash v{} executable\" with administrator privileges",
macos_app_path.to_string_lossy(),
name
))
.spawn();
}
app.emit("download-done", &name).unwrap();
Ok(())
let mut perms = fs::metadata(&macos_app_path).unwrap().permissions();
perms.set_mode(0o755);
fs::set_permissions(&macos_app_path, perms).unwrap();
}
return "1".to_string();
}
#[allow(unused_variables)]
@@ -246,58 +233,6 @@ fn launch_game(app: AppHandle, name: String, executable: String, wine: bool, win
}
}
#[tauri::command]
fn download_leaderboard(app: AppHandle, content: String) {
app.dialog().file().save_file(move |file_path| {
if let Some(path) = file_path {
let mut path_buf = PathBuf::from(path.to_string());
if path_buf.extension().map(|ext| ext != "csv").unwrap_or(true) {
path_buf.set_extension("csv");
}
let path_str = path_buf.to_string_lossy().to_string();
if path_str.is_empty() {
app.dialog()
.message("No file selected.")
.kind(MessageDialogKind::Error)
.title("Error")
.show(|_| {});
return;
}
let mut file = match File::create(&path_buf) {
Ok(f) => f,
Err(e) => {
app.dialog()
.message(format!("Failed to create file: {}", e))
.kind(MessageDialogKind::Error)
.title("Error")
.show(|_| {});
return;
}
};
if let Err(e) = file.write_all(content.as_bytes()) {
app.dialog()
.message(format!("Failed to write to file: {}", e))
.kind(MessageDialogKind::Error)
.title("Error")
.show(|_| {});
} else {
let _ = app.opener().open_path(path.to_string(), None::<&str>);
}
}
})
}
#[tauri::command]
fn get_keys_config(key: i8) -> String {
match key {
0 => Keys::SERVER_RECEIVE_TRANSFER_KEY.to_string(),
1 => Keys::SERVER_SEND_TRANSFER_KEY.to_string(),
2 => Keys::CONFIG_ENCRYPTION_KEY.to_string(),
3 => Keys::VERSIONS_ENCRYPTION_KEY.to_string(),
_ => "".to_string(),
}
}
#[tauri::command]
async fn uninstall_version(app: AppHandle, name: String) {
let game_path = app
@@ -341,37 +276,6 @@ async fn open_folder(app: AppHandle, name: String) {
}
}
#[allow(unused_variables)]
#[tauri::command]
fn fix_mac_permissions(app: AppHandle, name: String, executable: String) {
#[cfg(target_os = "macos")]
{
let macos_app_path = app
.path()
.app_local_data_dir()
.unwrap()
.join("game")
.join(&name)
.join(&executable)
.join("Contents")
.join("MacOS")
.join(
&executable
.chars()
.take(&executable.chars().count() - 4)
.collect::<String>(),
);
let _ = Command::new("osascript")
.arg("-e")
.arg(format!(
"do shell script \"chmod 755 \\\"{}\\\"\" with prompt \"Administrator is required to make Berry Dash v{} executable\" with administrator privileges",
macos_app_path.to_string_lossy(),
name
))
.spawn();
}
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
#[allow(unused_variables)]
@@ -391,11 +295,8 @@ pub fn run() {
.invoke_handler(tauri::generate_handler![
download,
launch_game,
download_leaderboard,
get_keys_config,
uninstall_version,
open_folder,
fix_mac_permissions,
open_folder
])
.setup(|app| {
#[cfg(target_os = "windows")]