Initial commit
3
src-tauri/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/target/
|
||||
/Cargo.lock
|
||||
/gen/schemas
|
||||
25
src-tauri/Cargo.toml
Normal file
@@ -0,0 +1,25 @@
|
||||
[package]
|
||||
name = "lncvrt-games-launcher-loader"
|
||||
version = "0.1.0"
|
||||
authors = ["Lncvrt"]
|
||||
edition = "2024"
|
||||
|
||||
[lib]
|
||||
name = "lncvrt_games_launcher_loader_lib"
|
||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2.5.1", features = [] }
|
||||
|
||||
[dependencies]
|
||||
tauri = { version = "2.9.2", features = [] }
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
serde_json = "1.0.145"
|
||||
tauri-plugin-fs = "2"
|
||||
tokio = "1.48.0"
|
||||
zip = "6.0.0"
|
||||
tauri-plugin-os = "2"
|
||||
reqwest = { version = "0.12.24", default-features = false, features = ["stream", "rustls-tls"] }
|
||||
tauri-plugin-opener = "2"
|
||||
tauri-plugin-dialog = "2"
|
||||
|
||||
3
src-tauri/build.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
tauri_build::build()
|
||||
}
|
||||
19
src-tauri/capabilities/default.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "default",
|
||||
"description": "Capability for the main window",
|
||||
"windows": [
|
||||
"main"
|
||||
],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"core:window:allow-start-dragging",
|
||||
"fs:default",
|
||||
"fs:allow-applocaldata-read",
|
||||
"fs:allow-applocaldata-write",
|
||||
"fs:allow-exists",
|
||||
"os:default",
|
||||
"opener:default",
|
||||
"dialog:default"
|
||||
]
|
||||
}
|
||||
BIN
src-tauri/icons/128x128.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
src-tauri/icons/128x128@2x.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
src-tauri/icons/32x32.png
Normal file
|
After Width: | Height: | Size: 974 B |
BIN
src-tauri/icons/Square107x107Logo.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
src-tauri/icons/Square142x142Logo.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
src-tauri/icons/Square150x150Logo.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
src-tauri/icons/Square284x284Logo.png
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
src-tauri/icons/Square30x30Logo.png
Normal file
|
After Width: | Height: | Size: 903 B |
BIN
src-tauri/icons/Square310x310Logo.png
Normal file
|
After Width: | Height: | Size: 8.4 KiB |
BIN
src-tauri/icons/Square44x44Logo.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src-tauri/icons/Square71x71Logo.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
src-tauri/icons/Square89x89Logo.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
src-tauri/icons/StoreLogo.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
src-tauri/icons/icon.icns
Normal file
BIN
src-tauri/icons/icon.ico
Normal file
|
After Width: | Height: | Size: 85 KiB |
BIN
src-tauri/icons/icon.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
168
src-tauri/src/lib.rs
Normal file
@@ -0,0 +1,168 @@
|
||||
use std::{
|
||||
fs::{File, create_dir_all},
|
||||
io::{BufReader, copy},
|
||||
path::PathBuf,
|
||||
process::Command,
|
||||
};
|
||||
use tauri::{AppHandle, Manager};
|
||||
use tauri_plugin_os::platform;
|
||||
use zip::ZipArchive;
|
||||
|
||||
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))?;
|
||||
|
||||
for i in 0..archive.len() {
|
||||
let mut file = archive.by_index(i)?;
|
||||
let outpath = out_dir.join(file.name());
|
||||
|
||||
if file.is_dir() {
|
||||
create_dir_all(&outpath)?;
|
||||
} else {
|
||||
if let Some(parent) = outpath.parent() {
|
||||
create_dir_all(parent)?;
|
||||
}
|
||||
let mut outfile = File::create(&outpath)?;
|
||||
copy(&mut file, &mut outfile)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok::<(), zip::result::ZipError>(())
|
||||
})
|
||||
.await;
|
||||
|
||||
match res {
|
||||
Ok(Ok(())) => "1".into(),
|
||||
_ => "-1".into(),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn check_latest_ver(app: AppHandle, version: String) -> String {
|
||||
let updates_path = app.path().app_local_data_dir().unwrap().join("updates");
|
||||
if updates_path.exists()
|
||||
&& updates_path.is_dir()
|
||||
&& updates_path.join(&version).exists()
|
||||
&& updates_path.join(&version).is_dir()
|
||||
{
|
||||
return "1".to_string();
|
||||
}
|
||||
return "-1".to_string();
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn download(app: AppHandle, url: String, name: String) -> String {
|
||||
let client = reqwest::Client::new();
|
||||
let resp = match client.get(&url).send().await {
|
||||
Ok(r) => r,
|
||||
Err(_) => return "-1".to_string(),
|
||||
};
|
||||
let bytes = match resp.bytes().await {
|
||||
Ok(b) => b,
|
||||
Err(_) => return "-1".to_string(),
|
||||
};
|
||||
|
||||
let downloads_path = app.path().app_local_data_dir().unwrap().join("downloads");
|
||||
let updates_path = app.path().app_local_data_dir().unwrap().join("updates");
|
||||
|
||||
let download_part_path = downloads_path.join(format!("{}.part", name));
|
||||
let download_zip_path = downloads_path.join(format!("{}.zip", name));
|
||||
|
||||
let _ = tokio::fs::create_dir_all(&downloads_path).await;
|
||||
if let Ok(true) = tokio::fs::try_exists(&updates_path.join(name.clone())).await {
|
||||
let _ = tokio::fs::remove_dir_all(&updates_path.join(name.clone())).await;
|
||||
}
|
||||
let _ = tokio::fs::create_dir_all(&updates_path.join(&name)).await;
|
||||
if download_part_path.exists() {
|
||||
let _ = tokio::fs::remove_file(&download_part_path).await;
|
||||
}
|
||||
|
||||
if tokio::fs::write(&download_part_path, bytes).await.is_err() {
|
||||
return "-1".to_string();
|
||||
}
|
||||
|
||||
if tokio::fs::rename(&download_part_path, &download_zip_path)
|
||||
.await
|
||||
.is_err()
|
||||
{
|
||||
return "-1".to_string();
|
||||
}
|
||||
|
||||
let unzip_res = unzip_to_dir(download_zip_path.clone(), updates_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")]
|
||||
{
|
||||
let executable_path = updates_path.join(&name).join("lncvrt-games-launcher");
|
||||
let mut perms = fs::metadata(&executable_path).unwrap().permissions();
|
||||
perms.set_mode(0o755);
|
||||
fs::set_permissions(executable_path, perms).unwrap();
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
use std::fs;
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
|
||||
let macos_app_path = updates_path
|
||||
.join(&name)
|
||||
.join("Lncvrt Games Launcher.app")
|
||||
.join("Contents")
|
||||
.join("MacOS")
|
||||
.join("lncvrt-games-launcher");
|
||||
|
||||
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)]
|
||||
#[tauri::command]
|
||||
fn load(app: AppHandle, name: String) {
|
||||
let update_path = app
|
||||
.path()
|
||||
.app_local_data_dir()
|
||||
.unwrap()
|
||||
.join("updates")
|
||||
.join(&name);
|
||||
if !update_path.exists() {
|
||||
return;
|
||||
}
|
||||
if platform() == "macos" {
|
||||
Command::new("open")
|
||||
.arg("Lncvrt Games Launcher.app")
|
||||
.current_dir(&update_path)
|
||||
.spawn()
|
||||
.unwrap();
|
||||
} else if platform() == "linux" {
|
||||
Command::new("./lncvrt-games-launcher")
|
||||
.current_dir(&update_path)
|
||||
.spawn()
|
||||
.unwrap();
|
||||
} else if platform() == "windows" {
|
||||
Command::new("lncvrt-games-launcher.exe")
|
||||
.current_dir(&update_path)
|
||||
.spawn()
|
||||
.unwrap();
|
||||
}
|
||||
app.exit(0);
|
||||
}
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_dialog::init())
|
||||
.plugin(tauri_plugin_opener::init())
|
||||
.plugin(tauri_plugin_os::init())
|
||||
.plugin(tauri_plugin_fs::init())
|
||||
.invoke_handler(tauri::generate_handler![check_latest_ver, download, load])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
5
src-tauri/src/main.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
fn main() {
|
||||
lncvrt_games_launcher_loader_lib::run()
|
||||
}
|
||||
29
src-tauri/tauri.conf.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "lncvrt-games-launcher-loader",
|
||||
"version": "1.0.0",
|
||||
"identifier": "xyz.lncvrt.lncvrt-games-launcher-loader",
|
||||
"build": {
|
||||
"beforeDevCommand": "next dev",
|
||||
"devUrl": "http://localhost:3000",
|
||||
"beforeBuildCommand": "next build",
|
||||
"frontendDist": "../out"
|
||||
},
|
||||
"app": {
|
||||
"withGlobalTauri": true,
|
||||
"windows": [
|
||||
{
|
||||
"width": 300,
|
||||
"height": 300,
|
||||
"resizable": false,
|
||||
"maximizable": false
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
"csp": null
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
"active": false
|
||||
}
|
||||
}
|
||||
31
src-tauri/tauri.macos.conf.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "lncvrt-games-launcher-loader",
|
||||
"version": "1.0.0",
|
||||
"identifier": "xyz.lncvrt.lncvrt-games-launcher-loader",
|
||||
"build": {
|
||||
"beforeDevCommand": "next dev",
|
||||
"devUrl": "http://localhost:3000",
|
||||
"beforeBuildCommand": "next build",
|
||||
"frontendDist": "../out"
|
||||
},
|
||||
"app": {
|
||||
"withGlobalTauri": true,
|
||||
"windows": [
|
||||
{
|
||||
"width": 300,
|
||||
"height": 300,
|
||||
"resizable": false,
|
||||
"maximizable": false,
|
||||
"titleBarStyle": "Overlay",
|
||||
"hiddenTitle": true
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
"csp": null
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
"active": false
|
||||
}
|
||||
}
|
||||