1.1.2
This commit is contained in:
8
bun.lock
8
bun.lock
@@ -71,9 +71,9 @@
|
|||||||
|
|
||||||
"@babel/types": ["@babel/types@7.28.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="],
|
"@babel/types": ["@babel/types@7.28.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="],
|
||||||
|
|
||||||
"@emnapi/core": ["@emnapi/core@1.6.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-zq/ay+9fNIJJtJiZxdTnXS20PllcYMX3OE23ESc4HK/bdYu3cOWYVhsOhVnXALfU/uqJIxn5NBPd9z4v+SfoSg=="],
|
"@emnapi/core": ["@emnapi/core@1.7.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-pJdKGq/1iquWYtv1RRSljZklxHCOCAJFJrImO5ZLKPJVJlVUcs8yFwNQlqS0Lo8xT1VAXXTCZocF9n26FWEKsw=="],
|
||||||
|
|
||||||
"@emnapi/runtime": ["@emnapi/runtime@1.6.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-obtUmAHTMjll499P+D9A3axeJFlhdjOWdKUNs/U6QIGT7V5RjcUW1xToAzjvmgTSQhDbYn/NwfTRoJcQ2rNBxA=="],
|
"@emnapi/runtime": ["@emnapi/runtime@1.7.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q=="],
|
||||||
|
|
||||||
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
|
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
|
||||||
|
|
||||||
@@ -927,9 +927,9 @@
|
|||||||
|
|
||||||
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.6.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-zq/ay+9fNIJJtJiZxdTnXS20PllcYMX3OE23ESc4HK/bdYu3cOWYVhsOhVnXALfU/uqJIxn5NBPd9z4v+SfoSg=="],
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.7.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-pJdKGq/1iquWYtv1RRSljZklxHCOCAJFJrImO5ZLKPJVJlVUcs8yFwNQlqS0Lo8xT1VAXXTCZocF9n26FWEKsw=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.6.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-obtUmAHTMjll499P+D9A3axeJFlhdjOWdKUNs/U6QIGT7V5RjcUW1xToAzjvmgTSQhDbYn/NwfTRoJcQ2rNBxA=="],
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.7.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "lncvrt-games-launcher",
|
"name": "lncvrt-games-launcher",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.1.1",
|
"version": "1.1.2",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "lncvrt-games-launcher"
|
name = "lncvrt-games-launcher"
|
||||||
version = "1.1.1"
|
version = "1.1.2"
|
||||||
authors = ["Lncvrt"]
|
authors = ["Lncvrt"]
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
@@ -27,6 +27,7 @@ libc = "0.2.177"
|
|||||||
tauri-plugin-dialog = "2.4.2"
|
tauri-plugin-dialog = "2.4.2"
|
||||||
tauri-plugin-notification = "2.3.3"
|
tauri-plugin-notification = "2.3.3"
|
||||||
sysinfo = "0.37.2"
|
sysinfo = "0.37.2"
|
||||||
|
sha2 = "0.10.9"
|
||||||
|
|
||||||
[target.'cfg(target_os = "linux")'.dependencies]
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
shlex = "1.3.0"
|
shlex = "1.3.0"
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use futures_util::stream::StreamExt;
|
use futures_util::stream::StreamExt;
|
||||||
|
use sha2::{Digest, Sha512};
|
||||||
use std::{
|
use std::{
|
||||||
fs::{File, create_dir_all},
|
fs::{File, create_dir_all},
|
||||||
io::{BufReader, copy},
|
io::{BufReader, copy},
|
||||||
@@ -62,7 +63,13 @@ async fn unzip_to_dir(zip_path: PathBuf, out_dir: PathBuf) -> String {
|
|||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
async fn download(app: AppHandle, url: String, name: String, executable: String) -> String {
|
async fn download(
|
||||||
|
app: AppHandle,
|
||||||
|
url: String,
|
||||||
|
name: String,
|
||||||
|
executable: String,
|
||||||
|
hash: String,
|
||||||
|
) -> String {
|
||||||
let client = reqwest::Client::new();
|
let client = reqwest::Client::new();
|
||||||
let resp = match client.get(&url).send().await {
|
let resp = match client.get(&url).send().await {
|
||||||
Ok(r) => r,
|
Ok(r) => r,
|
||||||
@@ -90,7 +97,9 @@ async fn download(app: AppHandle, url: String, name: String, executable: String)
|
|||||||
let _ = tokio::fs::remove_dir_all(&game_path.join(name.clone())).await;
|
let _ = tokio::fs::remove_dir_all(&game_path.join(name.clone())).await;
|
||||||
}
|
}
|
||||||
let _ = tokio::fs::create_dir_all(&game_path.join(&name)).await;
|
let _ = tokio::fs::create_dir_all(&game_path.join(&name)).await;
|
||||||
let mut file = tokio::fs::File::create(download_part_path).await.unwrap();
|
let mut file = tokio::fs::File::create(download_part_path.clone())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
while let Ok(Some(chunk_result)) = timeout(Duration::from_secs(5), stream.next()).await {
|
while let Ok(Some(chunk_result)) = timeout(Duration::from_secs(5), stream.next()).await {
|
||||||
let chunk = match chunk_result {
|
let chunk = match chunk_result {
|
||||||
@@ -120,10 +129,21 @@ async fn download(app: AppHandle, url: String, name: String, executable: String)
|
|||||||
return "-1".to_string();
|
return "-1".to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
tokio::fs::rename(
|
app.emit("download-hash-checking", format!("{}", &name))
|
||||||
downloads_path.join(format!("{}.part", name)),
|
.unwrap();
|
||||||
download_zip_path.clone(),
|
let mut hasher = Sha512::new();
|
||||||
)
|
hasher.update(&tokio::fs::read(download_part_path.clone()).await.unwrap());
|
||||||
|
let download_hash = format!("{:x}", hasher.finalize());
|
||||||
|
if hash != download_hash {
|
||||||
|
tokio::fs::remove_file(download_part_path.clone())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
return "-1".to_string();
|
||||||
|
}
|
||||||
|
app.emit("download-finishing", format!("{}", &name))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
tokio::fs::rename(download_part_path.clone(), download_zip_path.clone())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let unzip_res = unzip_to_dir(download_zip_path.clone(), game_path.join(&name)).await;
|
let unzip_res = unzip_to_dir(download_zip_path.clone(), game_path.join(&name)).await;
|
||||||
@@ -167,7 +187,7 @@ async fn download(app: AppHandle, url: String, name: String, executable: String)
|
|||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
fn launch_game(app: AppHandle, name: String, executable: String, wine: bool, wine_command: String) {
|
fn launch_game(app: AppHandle, name: String, executable: String) {
|
||||||
let game_folder = app
|
let game_folder = app
|
||||||
.path()
|
.path()
|
||||||
.app_local_data_dir()
|
.app_local_data_dir()
|
||||||
@@ -183,27 +203,6 @@ fn launch_game(app: AppHandle, name: String, executable: String, wine: bool, win
|
|||||||
.show(|_| {});
|
.show(|_| {});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let result = if wine && platform() == "linux" {
|
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
{
|
|
||||||
let wine_cmd_to_use =
|
|
||||||
wine_command.replace("%path%", &format!("\"{}\"", game_path.to_string_lossy()));
|
|
||||||
|
|
||||||
let parts = shlex::split(&wine_cmd_to_use).expect("failed to split command");
|
|
||||||
let exe = &parts[0];
|
|
||||||
let args = &parts[1..];
|
|
||||||
|
|
||||||
Command::new(exe)
|
|
||||||
.args(args)
|
|
||||||
.current_dir(&game_folder)
|
|
||||||
.spawn()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(target_os = "linux"))]
|
|
||||||
{
|
|
||||||
Err(std::io::Error::new(std::io::ErrorKind::Other, "not linux"))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if is_running_by_path(&game_path) {
|
if is_running_by_path(&game_path) {
|
||||||
app.dialog()
|
app.dialog()
|
||||||
.message(format!("The version {} is already running.", name))
|
.message(format!("The version {} is already running.", name))
|
||||||
@@ -212,25 +211,18 @@ fn launch_game(app: AppHandle, name: String, executable: String, wine: bool, win
|
|||||||
.show(|_| {});
|
.show(|_| {});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if platform() == "macos" {
|
if platform() == "macos" {
|
||||||
Command::new("open")
|
Command::new("open")
|
||||||
.arg(&game_path)
|
.arg(&game_path)
|
||||||
.current_dir(&game_folder)
|
.current_dir(&game_folder)
|
||||||
.spawn()
|
.spawn()
|
||||||
|
.unwrap();
|
||||||
} else {
|
} else {
|
||||||
Command::new(&game_path).current_dir(&game_folder).spawn()
|
Command::new(&game_path)
|
||||||
}
|
.current_dir(&game_folder)
|
||||||
};
|
.spawn()
|
||||||
|
.unwrap();
|
||||||
match result {
|
|
||||||
Ok(_) => println!("Game launched successfully."),
|
|
||||||
Err(e) => {
|
|
||||||
app.dialog()
|
|
||||||
.message(format!("Failed to load game:\n{}\n\nTry reinstalling the game or make a support request in the Community link on the sidebar.", e))
|
|
||||||
.kind(MessageDialogKind::Error)
|
|
||||||
.title("Failed to launch game")
|
|
||||||
.show(|_| {});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "Lncvrt Games Launcher",
|
"productName": "Lncvrt Games Launcher",
|
||||||
"version": "1.1.1",
|
"version": "1.1.2",
|
||||||
"identifier": "xyz.lncvrt.games-launcher",
|
"identifier": "xyz.lncvrt.games-launcher",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "next dev",
|
"beforeDevCommand": "next dev",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "Lncvrt Games Launcher",
|
"productName": "Lncvrt Games Launcher",
|
||||||
"version": "1.1.1",
|
"version": "1.1.2",
|
||||||
"identifier": "xyz.lncvrt.games-launcher",
|
"identifier": "xyz.lncvrt.games-launcher",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "next dev",
|
"beforeDevCommand": "next dev",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "Lncvrt Games Launcher",
|
"productName": "Lncvrt Games Launcher",
|
||||||
"version": "1.1.1",
|
"version": "1.1.2",
|
||||||
"identifier": "xyz.lncvrt.games-launcher",
|
"identifier": "xyz.lncvrt.games-launcher",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "next dev",
|
"beforeDevCommand": "next dev",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "Lncvrt Games Launcher",
|
"productName": "Lncvrt Games Launcher",
|
||||||
"version": "1.1.1",
|
"version": "1.1.2",
|
||||||
"identifier": "xyz.lncvrt.games-launcher",
|
"identifier": "xyz.lncvrt.games-launcher",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "next dev",
|
"beforeDevCommand": "next dev",
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import { platform } from '@tauri-apps/plugin-os'
|
|
||||||
import '../Installs.css'
|
import '../Installs.css'
|
||||||
import { format } from 'date-fns'
|
import { format } from 'date-fns'
|
||||||
import { invoke } from '@tauri-apps/api/core'
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
import { message } from '@tauri-apps/plugin-dialog'
|
|
||||||
import { useGlobal } from '../GlobalProvider'
|
import { useGlobal } from '../GlobalProvider'
|
||||||
import { useSearchParams } from 'next/navigation'
|
import { useSearchParams } from 'next/navigation'
|
||||||
|
|
||||||
@@ -100,43 +98,9 @@ export default function Installs () {
|
|||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
const verInfo = getVersionInfo(entry)
|
const verInfo = getVersionInfo(entry)
|
||||||
if (verInfo == undefined) return
|
if (verInfo == undefined) return
|
||||||
let plat = platform()
|
|
||||||
let willUseWine = false
|
|
||||||
let cfg = null
|
|
||||||
while (normalConfig != null) {
|
|
||||||
cfg = normalConfig
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if (plat === 'macos' || plat === 'linux') {
|
|
||||||
if (
|
|
||||||
!verInfo.platforms.includes(plat) &&
|
|
||||||
verInfo.platforms.includes('windows')
|
|
||||||
) {
|
|
||||||
if (
|
|
||||||
cfg != null &&
|
|
||||||
!cfg.settings.useWineOnUnixWhenNeeded
|
|
||||||
) {
|
|
||||||
await message(
|
|
||||||
'Wine support is disabled in settings and this version requires wine',
|
|
||||||
{
|
|
||||||
title: 'Wine is needed to load this version',
|
|
||||||
kind: 'error'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
plat = 'windows'
|
|
||||||
willUseWine = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
invoke('launch_game', {
|
invoke('launch_game', {
|
||||||
name: verInfo.id,
|
name: verInfo.id,
|
||||||
executable:
|
executable: verInfo.executable
|
||||||
verInfo.executables[
|
|
||||||
verInfo.platforms.indexOf(plat)
|
|
||||||
],
|
|
||||||
wine: willUseWine,
|
|
||||||
wineCommand: cfg?.settings.wineOnUnixCommand
|
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { useCallback, useEffect, useState } from 'react'
|
|||||||
import Sidebar from './componets/Sidebar'
|
import Sidebar from './componets/Sidebar'
|
||||||
import './Globals.css'
|
import './Globals.css'
|
||||||
import { DownloadProgress } from './types/DownloadProgress'
|
import { DownloadProgress } from './types/DownloadProgress'
|
||||||
import { arch, platform } from '@tauri-apps/plugin-os'
|
|
||||||
import { invoke } from '@tauri-apps/api/core'
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
import {
|
import {
|
||||||
@@ -40,6 +39,7 @@ import { GameVersion } from './types/GameVersion'
|
|||||||
import { Game } from './types/Game'
|
import { Game } from './types/Game'
|
||||||
import { listen } from '@tauri-apps/api/event'
|
import { listen } from '@tauri-apps/api/event'
|
||||||
import { usePathname } from 'next/navigation'
|
import { usePathname } from 'next/navigation'
|
||||||
|
import { arch, platform } from '@tauri-apps/plugin-os'
|
||||||
|
|
||||||
const roboto = Roboto({
|
const roboto = Roboto({
|
||||||
subsets: ['latin']
|
subsets: ['latin']
|
||||||
@@ -114,6 +114,28 @@ export default function RootLayout ({
|
|||||||
})
|
})
|
||||||
}).then(f => (unlistenProgress = f))
|
}).then(f => (unlistenProgress = f))
|
||||||
|
|
||||||
|
listen<string>('download-hash-checking', event => {
|
||||||
|
const versionName = event.payload
|
||||||
|
setDownloadProgress(prev => {
|
||||||
|
const i = prev.findIndex(d => d.version === versionName)
|
||||||
|
if (i === -1) return prev
|
||||||
|
const copy = [...prev]
|
||||||
|
copy[i] = { ...copy[i], hash_checking: true }
|
||||||
|
return copy
|
||||||
|
})
|
||||||
|
}).then(f => (unlistenProgress = f))
|
||||||
|
|
||||||
|
listen<string>('download-finishing', event => {
|
||||||
|
const versionName = event.payload
|
||||||
|
setDownloadProgress(prev => {
|
||||||
|
const i = prev.findIndex(d => d.version === versionName)
|
||||||
|
if (i === -1) return prev
|
||||||
|
const copy = [...prev]
|
||||||
|
copy[i] = { ...copy[i], hash_checking: false, finishing: true }
|
||||||
|
return copy
|
||||||
|
})
|
||||||
|
}).then(f => (unlistenProgress = f))
|
||||||
|
|
||||||
listen<string>('version-uninstalled', event => {
|
listen<string>('version-uninstalled', event => {
|
||||||
const versionName = event.payload
|
const versionName = event.payload
|
||||||
setDownloadedVersionsConfig(prev => {
|
setDownloadedVersionsConfig(prev => {
|
||||||
@@ -162,7 +184,7 @@ export default function RootLayout ({
|
|||||||
setLoadingText('Downloading version list...')
|
setLoadingText('Downloading version list...')
|
||||||
try {
|
try {
|
||||||
const res = await axios.get(
|
const res = await axios.get(
|
||||||
'https://games.lncvrt.xyz/api/launcher/versions'
|
`http://localhost:3342/launcher/versions?platform=${platform()}&arch=${arch()}`
|
||||||
)
|
)
|
||||||
setServerVersionList(res.data)
|
setServerVersionList(res.data)
|
||||||
} catch {
|
} catch {
|
||||||
@@ -193,92 +215,18 @@ export default function RootLayout ({
|
|||||||
function getSpecialVersionsList (game?: number): GameVersion[] {
|
function getSpecialVersionsList (game?: number): GameVersion[] {
|
||||||
if (!normalConfig || !serverVersionList) return []
|
if (!normalConfig || !serverVersionList) return []
|
||||||
|
|
||||||
const useWine = normalConfig.settings.useWineOnUnixWhenNeeded
|
|
||||||
const p = platform()
|
|
||||||
const a = arch()
|
|
||||||
|
|
||||||
return serverVersionList.versions
|
return serverVersionList.versions
|
||||||
.filter(v => !downloadedVersionsConfig?.list.includes(v.id))
|
.filter(v => !downloadedVersionsConfig?.list.includes(v.id))
|
||||||
.filter(v => {
|
.filter(v => {
|
||||||
if (game && v.game != game) return false
|
if (game && v.game != game) return false
|
||||||
if (p === 'macos' || p === 'linux') {
|
return true
|
||||||
if (useWine) {
|
|
||||||
return (
|
|
||||||
v.platforms.includes('windows-x86') ||
|
|
||||||
v.platforms.includes('windows-x64') ||
|
|
||||||
v.platforms.includes(p)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return v.platforms.includes(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p === 'windows') {
|
|
||||||
if (a === 'x86_64')
|
|
||||||
return (
|
|
||||||
v.platforms.includes('windows-x86') ||
|
|
||||||
v.platforms.includes('windows-x64')
|
|
||||||
)
|
|
||||||
if (a === 'aarch64') return v.platforms.includes('windows-arm64')
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
})
|
})
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
if (b.game !== a.game) return a.game - b.game
|
if (b.game !== a.game) return a.game - b.game
|
||||||
return b.place - a.place
|
return 0
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDownloadLink (version: GameVersion): string | undefined {
|
|
||||||
const p = platform()
|
|
||||||
const a = arch()
|
|
||||||
|
|
||||||
const findUrl = (plat: string) => {
|
|
||||||
const i = version.platforms.indexOf(plat)
|
|
||||||
return i >= 0 ? version.downloadUrls[i] : undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p === 'windows') {
|
|
||||||
if (a === 'x86_64')
|
|
||||||
return findUrl('windows-x64') || findUrl('windows-x86')
|
|
||||||
if (a === 'aarch64') return findUrl('windows-arm64')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p === 'macos' || p === 'linux') {
|
|
||||||
if (normalConfig?.settings.useWineOnUnixWhenNeeded) {
|
|
||||||
return findUrl('windows-x86') || findUrl('windows-x64') || findUrl(p)
|
|
||||||
}
|
|
||||||
return findUrl(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
function getExecutableName (version: GameVersion): string | undefined {
|
|
||||||
const p = platform()
|
|
||||||
const a = arch()
|
|
||||||
|
|
||||||
const findUrl = (plat: string) => {
|
|
||||||
const i = version.platforms.indexOf(plat)
|
|
||||||
return i >= 0 ? version.executables[i] : undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p === 'windows') {
|
|
||||||
if (a === 'x86_64')
|
|
||||||
return findUrl('windows-x64') || findUrl('windows-x86')
|
|
||||||
if (a === 'aarch64') return findUrl('windows-arm64')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p === 'macos' || p === 'linux') {
|
|
||||||
if (normalConfig?.settings.useWineOnUnixWhenNeeded) {
|
|
||||||
return findUrl('windows-x86') || findUrl('windows-x64') || findUrl(p)
|
|
||||||
}
|
|
||||||
return findUrl(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
function getVersionInfo (id: string | undefined): GameVersion | undefined {
|
function getVersionInfo (id: string | undefined): GameVersion | undefined {
|
||||||
if (!id) return undefined
|
if (!id) return undefined
|
||||||
return serverVersionList?.versions.find(v => v.id === id)
|
return serverVersionList?.versions.find(v => v.id === id)
|
||||||
@@ -310,7 +258,7 @@ export default function RootLayout ({
|
|||||||
setSelectedVersionList([])
|
setSelectedVersionList([])
|
||||||
|
|
||||||
const newDownloads = list.map(
|
const newDownloads = list.map(
|
||||||
version => new DownloadProgress(version, 0, false, true)
|
version => new DownloadProgress(version, 0, false, true, false, false)
|
||||||
)
|
)
|
||||||
|
|
||||||
setDownloadProgress(newDownloads)
|
setDownloadProgress(newDownloads)
|
||||||
@@ -330,29 +278,16 @@ export default function RootLayout ({
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const downloadLink = getDownloadLink(info)
|
|
||||||
if (!downloadLink) {
|
|
||||||
setDownloadProgress(prev =>
|
|
||||||
prev.filter(d => d.version !== download.version)
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const executableName = getExecutableName(info)
|
|
||||||
if (!executableName) {
|
|
||||||
setDownloadProgress(prev =>
|
|
||||||
prev.filter(d => d.version !== download.version)
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
setDownloadProgress(prev =>
|
setDownloadProgress(prev =>
|
||||||
prev.map(d =>
|
prev.map(d =>
|
||||||
d.version === download.version ? { ...d, queued: false } : d
|
d.version === download.version ? { ...d, queued: false } : d
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
const res = await invoke<string>('download', {
|
const res = await invoke<string>('download', {
|
||||||
url: downloadLink,
|
url: info.downloadUrl,
|
||||||
name: info.id,
|
name: info.id,
|
||||||
executable: executableName
|
executable: info.executable,
|
||||||
|
hash: info.sha512sum
|
||||||
})
|
})
|
||||||
if (res == '1') {
|
if (res == '1') {
|
||||||
setDownloadProgress(prev =>
|
setDownloadProgress(prev =>
|
||||||
@@ -394,38 +329,13 @@ export default function RootLayout ({
|
|||||||
} | null {
|
} | null {
|
||||||
if (!downloadedVersionsConfig || !serverVersionList) return null
|
if (!downloadedVersionsConfig || !serverVersionList) return null
|
||||||
|
|
||||||
const p = platform()
|
|
||||||
const a = arch()
|
|
||||||
|
|
||||||
const installed = downloadedVersionsConfig.list.filter(
|
const installed = downloadedVersionsConfig.list.filter(
|
||||||
v => getVersionGame(getVersionInfo(v)?.game)?.id === gameId
|
v => getVersionGame(getVersionInfo(v)?.game)?.id === gameId
|
||||||
).length
|
).length
|
||||||
|
|
||||||
const total = serverVersionList.versions
|
const total = serverVersionList.versions.filter(
|
||||||
.filter(v => {
|
v => getVersionGame(v?.game)?.id === gameId
|
||||||
if (p === 'macos' || p === 'linux') {
|
).length
|
||||||
if (normalConfig?.settings.useWineOnUnixWhenNeeded) {
|
|
||||||
return (
|
|
||||||
v.platforms.includes('windows-x86') ||
|
|
||||||
v.platforms.includes('windows-x64') ||
|
|
||||||
v.platforms.includes(p)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return v.platforms.includes(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p === 'windows') {
|
|
||||||
if (a === 'x86_64')
|
|
||||||
return (
|
|
||||||
v.platforms.includes('windows-x86') ||
|
|
||||||
v.platforms.includes('windows-x64')
|
|
||||||
)
|
|
||||||
if (a === 'aarch64') return v.platforms.includes('windows-arm64')
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
.filter(v => getVersionGame(v?.game)?.id === gameId).length
|
|
||||||
|
|
||||||
return { installed, total }
|
return { installed, total }
|
||||||
}
|
}
|
||||||
@@ -690,6 +600,18 @@ export default function RootLayout ({
|
|||||||
<span className='text-yellow-500'>
|
<span className='text-yellow-500'>
|
||||||
Queued…
|
Queued…
|
||||||
</span>
|
</span>
|
||||||
|
) : v.queued ? (
|
||||||
|
<span className='text-yellow-500'>
|
||||||
|
Queued…
|
||||||
|
</span>
|
||||||
|
) : v.hash_checking ? (
|
||||||
|
<span className='text-blue-500'>
|
||||||
|
Checking hash...
|
||||||
|
</span>
|
||||||
|
) : v.finishing ? (
|
||||||
|
<span className='text-green-500'>
|
||||||
|
Finishing...
|
||||||
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<span>
|
<span>
|
||||||
Downloading: {v.progress}% done
|
Downloading: {v.progress}% done
|
||||||
|
|||||||
@@ -3,25 +3,18 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { Setting } from '../componets/Setting'
|
import { Setting } from '../componets/Setting'
|
||||||
import { writeNormalConfig } from '../util/BazookaManager'
|
import { writeNormalConfig } from '../util/BazookaManager'
|
||||||
import { platform } from '@tauri-apps/plugin-os'
|
|
||||||
import { useGlobal } from '../GlobalProvider'
|
import { useGlobal } from '../GlobalProvider'
|
||||||
|
|
||||||
export default function Settings () {
|
export default function Settings () {
|
||||||
const [allowNotifications, setAllowNotifications] = useState(false)
|
const [allowNotifications, setAllowNotifications] = useState(false)
|
||||||
const [alwaysShowGamesInSidebar, setAlwaysShowGamesInSidebar] =
|
const [alwaysShowGamesInSidebar, setAlwaysShowGamesInSidebar] =
|
||||||
useState(false)
|
useState(false)
|
||||||
const [useWineOnUnixWhenNeeded, setUseWineOnUnixWhenNeeded] = useState(false)
|
|
||||||
const [wineOnUnixCommand, setWineOnUnixCommand] = useState('wine %path%')
|
|
||||||
const [loaded, setLoaded] = useState(false)
|
const [loaded, setLoaded] = useState(false)
|
||||||
const { normalConfig, setNormalConfig } = useGlobal()
|
const { normalConfig, setNormalConfig } = useGlobal()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
;(async () => {
|
;(async () => {
|
||||||
while (normalConfig != null) {
|
while (normalConfig != null) {
|
||||||
setUseWineOnUnixWhenNeeded(
|
|
||||||
normalConfig.settings.useWineOnUnixWhenNeeded
|
|
||||||
)
|
|
||||||
setWineOnUnixCommand(normalConfig.settings.wineOnUnixCommand)
|
|
||||||
setAllowNotifications(normalConfig.settings.allowNotifications)
|
setAllowNotifications(normalConfig.settings.allowNotifications)
|
||||||
setAlwaysShowGamesInSidebar(
|
setAlwaysShowGamesInSidebar(
|
||||||
normalConfig.settings.alwaysShowGamesInSidebar
|
normalConfig.settings.alwaysShowGamesInSidebar
|
||||||
@@ -73,35 +66,6 @@ export default function Settings () {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Setting
|
|
||||||
label='Use wine to launch Berry Dash when needed'
|
|
||||||
value={useWineOnUnixWhenNeeded}
|
|
||||||
onChange={async () => {
|
|
||||||
while (normalConfig != null) {
|
|
||||||
setUseWineOnUnixWhenNeeded(!useWineOnUnixWhenNeeded)
|
|
||||||
normalConfig.settings.useWineOnUnixWhenNeeded =
|
|
||||||
!useWineOnUnixWhenNeeded
|
|
||||||
await writeNormalConfig(normalConfig)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
className={platform() == 'linux' ? '' : 'hidden'}
|
|
||||||
/>
|
|
||||||
<input
|
|
||||||
type='text'
|
|
||||||
value={wineOnUnixCommand}
|
|
||||||
onChange={async e => {
|
|
||||||
while (normalConfig != null) {
|
|
||||||
setWineOnUnixCommand(e.target.value)
|
|
||||||
normalConfig.settings.wineOnUnixCommand = e.target.value
|
|
||||||
await writeNormalConfig(normalConfig)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
className={`input-field ${
|
|
||||||
platform() == 'linux' && useWineOnUnixWhenNeeded ? '' : 'hidden'
|
|
||||||
}`}
|
|
||||||
></input>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ export class DownloadProgress {
|
|||||||
public version: string,
|
public version: string,
|
||||||
public progress: number,
|
public progress: number,
|
||||||
public failed: boolean,
|
public failed: boolean,
|
||||||
public queued: boolean
|
public queued: boolean,
|
||||||
|
public hash_checking: boolean,
|
||||||
|
public finishing: boolean
|
||||||
) { }
|
) { }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,8 @@ export interface GameVersion {
|
|||||||
id: string
|
id: string
|
||||||
versionName: string
|
versionName: string
|
||||||
releaseDate: number
|
releaseDate: number
|
||||||
downloadUrls: string[]
|
|
||||||
platforms: string[]
|
|
||||||
executables: string[]
|
|
||||||
game: number
|
game: number
|
||||||
place: number
|
downloadUrl: string
|
||||||
|
executable: string
|
||||||
|
sha512sum: string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
export class SettingsType {
|
export class SettingsType {
|
||||||
constructor(
|
constructor(
|
||||||
public allowNotifications: boolean = true,
|
public allowNotifications: boolean = true,
|
||||||
public alwaysShowGamesInSidebar: boolean = true,
|
public alwaysShowGamesInSidebar: boolean = true
|
||||||
public useWineOnUnixWhenNeeded: boolean = false,
|
|
||||||
public wineOnUnixCommand: string = 'wine %path%'
|
|
||||||
) { }
|
) { }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user