Initial commit

This commit is contained in:
2025-10-31 22:35:12 -07:00
commit 426fe66baa
38 changed files with 2239 additions and 0 deletions

3
src-tauri/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
/target/
/Cargo.lock
/gen/schemas

25
src-tauri/Cargo.toml Normal file
View 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
View File

@@ -0,0 +1,3 @@
fn main() {
tauri_build::build()
}

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
src-tauri/icons/32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 974 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 903 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
src-tauri/icons/icon.icns Normal file

Binary file not shown.

BIN
src-tauri/icons/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

BIN
src-tauri/icons/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

168
src-tauri/src/lib.rs Normal file
View 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
View 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
View 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
}
}

View 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
}
}