mirror of
https://github.com/an-anime-team/an-anime-game-launcher.git
synced 2024-12-21 09:21:49 +03:00
API improvements
- changed dxvk fields - added abstract `Installer` class to simplify `Stream` classes - added `DXVK` class - updated comments
This commit is contained in:
parent
bde04d7a9a
commit
748b197984
11 changed files with 283 additions and 203 deletions
|
@ -2,56 +2,56 @@
|
|||
{
|
||||
"version": "1.9.2",
|
||||
"uri": "https://github.com/doitsujin/dxvk/releases/download/v1.9.2/dxvk-1.9.2.tar.gz",
|
||||
"recommendable": true
|
||||
"recommended": true
|
||||
},
|
||||
{
|
||||
"version": "1.9.1",
|
||||
"uri": "https://github.com/doitsujin/dxvk/releases/download/v1.9.1/dxvk-1.9.1.tar.gz",
|
||||
"recommendable": true
|
||||
"recommended": true
|
||||
},
|
||||
{
|
||||
"version": "1.9",
|
||||
"uri": "https://github.com/doitsujin/dxvk/releases/download/v1.9/dxvk-1.9.tar.gz",
|
||||
"recommendable": true
|
||||
"recommended": true
|
||||
},
|
||||
{
|
||||
"version": "1.8.1",
|
||||
"uri": "https://github.com/doitsujin/dxvk/releases/download/v1.8.1/dxvk-1.8.1.tar.gz",
|
||||
"recommendable": true
|
||||
"recommended": true
|
||||
},
|
||||
{
|
||||
"version": "1.8",
|
||||
"uri": "https://github.com/doitsujin/dxvk/releases/download/v1.8/dxvk-1.8.tar.gz",
|
||||
"recommendable": true
|
||||
"recommended": true
|
||||
},
|
||||
{
|
||||
"version": "1.7.3",
|
||||
"uri": "https://github.com/doitsujin/dxvk/releases/download/v1.7.3/dxvk-1.7.3.tar.gz",
|
||||
"recommendable": false
|
||||
"recommended": false
|
||||
},
|
||||
{
|
||||
"version": "1.7.2",
|
||||
"uri": "https://github.com/doitsujin/dxvk/releases/download/v1.7.2/dxvk-1.7.2.tar.gz",
|
||||
"recommendable": false
|
||||
"recommended": false
|
||||
},
|
||||
{
|
||||
"version": "1.7.1",
|
||||
"uri": "https://github.com/doitsujin/dxvk/releases/download/v1.7.1/dxvk-1.7.1.tar.gz",
|
||||
"recommendable": false
|
||||
"recommended": false
|
||||
},
|
||||
{
|
||||
"version": "1.7",
|
||||
"uri": "https://github.com/doitsujin/dxvk/releases/download/v1.7/dxvk-1.7.tar.gz",
|
||||
"recommendable": false
|
||||
"recommended": false
|
||||
},
|
||||
{
|
||||
"version": "1.6.1",
|
||||
"uri": "https://github.com/doitsujin/dxvk/releases/download/v1.6.1/dxvk-1.6.1.tar.gz",
|
||||
"recommendable": false
|
||||
"recommended": false
|
||||
},
|
||||
{
|
||||
"version": "1.6",
|
||||
"uri": "https://github.com/doitsujin/dxvk/releases/download/v1.6/dxvk-1.6.tar.gz",
|
||||
"recommendable": false
|
||||
"recommended": false
|
||||
}
|
||||
]
|
|
@ -6,6 +6,7 @@ import Downloader from '../ts/Downloader';
|
|||
import Archive from '../ts/Archive';
|
||||
import Configs from '../ts/Configs';
|
||||
import Runners from '../ts/Runners';
|
||||
import DXVK from '../ts/DXVK';
|
||||
|
||||
const app = Vue.createApp({
|
||||
data: () => ({
|
||||
|
@ -41,16 +42,6 @@ const app = Vue.createApp({
|
|||
|
||||
stream.finish(() => console.log('finished'));
|
||||
});*/
|
||||
|
||||
/*Downloader.download('https://autopatchhk.yuanshen.com/client_app/download/pc_zip/20211117173404_G0gLRnxvOd4PvSu9/Audio_English(US)_2.3.0.zip', '123.zip').then((stream) => {
|
||||
stream.progress((current: number, total: number) => {
|
||||
document.getElementById('progress').innerHTML = `${Math.round(current / total * 100)}%`;
|
||||
});
|
||||
|
||||
stream.finish(() => {
|
||||
console.log('finished');
|
||||
});
|
||||
});*/
|
||||
}
|
||||
});
|
||||
|
||||
|
|
165
src/ts/AbstractInstaller.ts
Normal file
165
src/ts/AbstractInstaller.ts
Normal file
|
@ -0,0 +1,165 @@
|
|||
import Constants from './Constants';
|
||||
import Downloader from './Downloader';
|
||||
import Archive from './Archive';
|
||||
|
||||
export default abstract class Installer
|
||||
{
|
||||
/**
|
||||
* The interval in ms between progress event calls
|
||||
*/
|
||||
public downloadProgressInterval: number = 200;
|
||||
|
||||
/**
|
||||
* The interval in ms between progress event calls
|
||||
*/
|
||||
public unpackProgressInterval: number = 500;
|
||||
|
||||
protected onDownloadStart?: () => void;
|
||||
protected onUnpackStart?: () => void;
|
||||
|
||||
protected onDownloadProgress?: (current: number, total: number, difference: number) => void;
|
||||
protected onUnpackProgress?: (current: number, total: number, difference: number) => void;
|
||||
|
||||
protected onDownloadFinish?: () => void;
|
||||
protected onUnpackFinish?: () => void;
|
||||
|
||||
protected downloadStarted: boolean = false;
|
||||
protected unpackStarted: boolean = false;
|
||||
|
||||
protected downloadFinished: boolean = false;
|
||||
protected unpackFinished: boolean = false;
|
||||
|
||||
public constructor(uri: string, unpackDir: string|Promise<string>)
|
||||
{
|
||||
Constants.paths.launcher.then((launcherDir) => {
|
||||
const archivePath = `${launcherDir}/${Downloader.fileFromUri(uri)}`;
|
||||
|
||||
// Download archive
|
||||
Downloader.download(uri, archivePath).then((stream) => {
|
||||
stream.progressInterval = this.downloadProgressInterval;
|
||||
|
||||
stream.start(() => {
|
||||
this.downloadStarted = true;
|
||||
|
||||
if (this.onDownloadStart)
|
||||
this.onDownloadStart();
|
||||
});
|
||||
|
||||
stream.progress((current, total, difference) => {
|
||||
if (this.onDownloadProgress)
|
||||
this.onDownloadProgress(current, total, difference);
|
||||
});
|
||||
|
||||
stream.finish(() => {
|
||||
this.downloadFinished = true;
|
||||
|
||||
if (this.onDownloadFinish)
|
||||
this.onDownloadFinish();
|
||||
|
||||
// And then unpack it
|
||||
const unpackArchive = (unpackDir: string) => {
|
||||
Archive.unpack(archivePath, unpackDir).then((stream) => {
|
||||
stream.progressInterval = this.unpackProgressInterval;
|
||||
|
||||
stream.start(() => {
|
||||
this.unpackStarted = true;
|
||||
|
||||
if (this.onUnpackStart)
|
||||
this.onUnpackStart();
|
||||
});
|
||||
|
||||
stream.progress((current, total, difference) => {
|
||||
if (this.onUnpackProgress)
|
||||
this.onUnpackProgress(current, total, difference);
|
||||
});
|
||||
|
||||
stream.finish(() => {
|
||||
this.unpackFinished = true;
|
||||
|
||||
if (this.onUnpackFinish)
|
||||
this.onUnpackFinish();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
if (typeof unpackDir === 'string')
|
||||
unpackArchive(unpackDir);
|
||||
|
||||
else unpackDir.then((unpackDir) => unpackArchive(unpackDir));
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify event that will be called after downloading will begin
|
||||
*
|
||||
* @param callback
|
||||
*/
|
||||
public downloadStart(callback: () => void)
|
||||
{
|
||||
this.onDownloadStart = callback;
|
||||
|
||||
if (this.downloadStarted)
|
||||
callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify event that will be called after unpacking will begin
|
||||
*
|
||||
* @param callback
|
||||
*/
|
||||
public unpackStart(callback: () => void)
|
||||
{
|
||||
this.onUnpackStart = callback;
|
||||
|
||||
if (this.unpackStarted)
|
||||
callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify event that will be called every [this.downloadProgressInterval] ms during downloading
|
||||
*
|
||||
* @param callback
|
||||
*/
|
||||
public downloadProgress(callback: (current: number, total: number, difference: number) => void)
|
||||
{
|
||||
this.onDownloadProgress = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify event that will be called every [this.unpackProgressInterval] ms during unpacking
|
||||
*
|
||||
* @param callback
|
||||
*/
|
||||
public unpackProgress(callback: (current: number, total: number, difference: number) => void)
|
||||
{
|
||||
this.onUnpackProgress = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify event that will be called after downloading will be finished
|
||||
*
|
||||
* @param callback
|
||||
*/
|
||||
public downloadFinish(callback: () => void)
|
||||
{
|
||||
this.onDownloadFinish = callback;
|
||||
|
||||
if (this.downloadFinished)
|
||||
callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify event that will be called after unpacking will be finished
|
||||
*
|
||||
* @param callback
|
||||
*/
|
||||
public unpackFinish(callback: () => void)
|
||||
{
|
||||
this.onUnpackFinish = callback;
|
||||
|
||||
if (this.unpackFinished)
|
||||
callback();
|
||||
}
|
||||
}
|
|
@ -164,7 +164,7 @@ export default class Archive
|
|||
* Get type of archive
|
||||
*
|
||||
* @param path path to archive
|
||||
* @returns ArchiveType|null
|
||||
* @returns supported archive type or null
|
||||
*/
|
||||
public static getType(path: string): ArchiveType|null
|
||||
{
|
||||
|
@ -181,7 +181,7 @@ export default class Archive
|
|||
* Get archive info
|
||||
*
|
||||
* @param path path to archive
|
||||
* @returns Promise<ArchiveInfo|null>
|
||||
* @returns null if the archive has unsupported type. Otherwise - archive info
|
||||
*/
|
||||
public static getInfo(path: string): Promise<ArchiveInfo|null>
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Constants from './Constants';
|
||||
|
||||
declare const Neutralino;
|
||||
declare const NL_CWD;
|
||||
|
||||
|
@ -12,7 +13,7 @@ export default class Configs
|
|||
* Get config value
|
||||
*
|
||||
* @param name config name, e.g. "lang.launcher"
|
||||
* @returns Promise<undefined|..>
|
||||
* @returns undefined if config is not exists. Otherwise - config value
|
||||
*/
|
||||
public static get(name: string = ''): Promise<undefined|scalar|scalar[]>
|
||||
{
|
||||
|
@ -67,6 +68,7 @@ export default class Configs
|
|||
* Set default values
|
||||
*
|
||||
* @param configs object of default values
|
||||
* @returns Promise<void> indicates when the default settings was applied
|
||||
*/
|
||||
public static defaults(configs: scalar): Promise<void>
|
||||
{
|
||||
|
|
|
@ -1,30 +1,24 @@
|
|||
declare const Neutralino;
|
||||
declare const NL_PATH;
|
||||
|
||||
class Paths
|
||||
{
|
||||
/**
|
||||
* Directory where the launcher's executable stored
|
||||
*
|
||||
* @returns string
|
||||
*/
|
||||
// @ts-expect-error
|
||||
public static readonly app: string = NL_PATH;
|
||||
|
||||
/**
|
||||
* Shaders directory
|
||||
*
|
||||
* Default is [constants.paths.app]/public/shaders
|
||||
*
|
||||
* @returns string
|
||||
* @defaultValue "[Constants.paths.app]/public/shaders"
|
||||
*/
|
||||
public static readonly shaders: string = `${this.app}/public/shaders`;
|
||||
|
||||
/**
|
||||
* Launcher data directory
|
||||
*
|
||||
* Default is ~/.local/share/anime-game-launcher
|
||||
*
|
||||
* @returns Promise<string>
|
||||
* @defaultValue "~/.local/share/anime-game-launcher"
|
||||
*/
|
||||
public static get launcher(): Promise<string>
|
||||
{
|
||||
|
@ -34,9 +28,7 @@ class Paths
|
|||
/**
|
||||
* Runners directory
|
||||
*
|
||||
* Default is ~/.local/share/anime-game-launcher/runners
|
||||
*
|
||||
* @returns Promise<string>
|
||||
* @defaultValue "~/.local/share/anime-game-launcher/runners"
|
||||
*/
|
||||
public static get runners(): Promise<string>
|
||||
{
|
||||
|
@ -46,9 +38,7 @@ class Paths
|
|||
/**
|
||||
* DXVKs directory
|
||||
*
|
||||
* Default is ~/.local/share/anime-game-launcher/dxvks
|
||||
*
|
||||
* @returns Promise<string>
|
||||
* @defaultValue "~/.local/share/anime-game-launcher/dxvks"
|
||||
*/
|
||||
public static get dxvks(): Promise<string>
|
||||
{
|
||||
|
@ -58,9 +48,7 @@ class Paths
|
|||
/**
|
||||
* Config file
|
||||
*
|
||||
* Default is ~/.local/share/anime-game-launcher/config.json
|
||||
*
|
||||
* @returns Promise<string>
|
||||
* @defaultValue "~/.local/share/anime-game-launcher/config.json"
|
||||
*/
|
||||
public static get config(): Promise<string>
|
||||
{
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
import type { DXVK as TDXVK } from './types/DXVK';
|
||||
|
||||
import Constants from './Constants';
|
||||
import AbstractInstaller from './AbstractInstaller';
|
||||
|
||||
declare const Neutralino;
|
||||
|
||||
class Stream extends AbstractInstaller
|
||||
{
|
||||
public constructor(dxvk: TDXVK)
|
||||
{
|
||||
super(dxvk.uri, Constants.paths.dxvks);
|
||||
}
|
||||
}
|
||||
|
||||
export default class DXVK
|
||||
{
|
||||
/**
|
||||
* Get DXVKs list
|
||||
*/
|
||||
public static get(): Promise<TDXVK[]>
|
||||
{
|
||||
return new Promise((resolve) => {
|
||||
Constants.paths.dxvks.then(async (dxvksDir: string) => {
|
||||
let list: TDXVK[] = JSON.parse(await Neutralino.filesystem.readFile(`${Constants.paths.app}/public/dxvks.json`));
|
||||
|
||||
const installed: { entry: string, type: string }[] = await Neutralino.filesystem.readDirectory(dxvksDir);
|
||||
|
||||
let dxvks: TDXVK[] = [];
|
||||
|
||||
list.forEach((dxvk) => {
|
||||
let inst = false;
|
||||
|
||||
for (let dir of installed)
|
||||
inst ||= dir.entry == `dxvk-${dxvk.version}`;
|
||||
|
||||
dxvks.push({
|
||||
...dxvk,
|
||||
|
||||
installed: inst
|
||||
});
|
||||
});
|
||||
|
||||
resolve(dxvks);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Download DXVK to the [Constants.paths.dxvks] directory
|
||||
*
|
||||
* @param dxvk DXVK object or version
|
||||
* @returns null if the DXVK with specified version is not exists. Otherwise - installation stream
|
||||
*/
|
||||
public static download(dxvk: TDXVK|TDXVK['version']): Promise<null|Stream>
|
||||
{
|
||||
return new Promise(async (resolve) => {
|
||||
// If we provided dxvk property as a version of the DXVK
|
||||
// then we should find this DXVK and call this method from it
|
||||
if (typeof dxvk == 'string')
|
||||
{
|
||||
let foundDXVK = null;
|
||||
|
||||
(await this.get()).forEach((currDxvk) => {
|
||||
if (currDxvk.version == dxvk)
|
||||
foundDXVK = currDxvk;
|
||||
});
|
||||
|
||||
resolve(foundDXVK === null ? null : new Stream(foundDXVK));
|
||||
}
|
||||
|
||||
// Otherwise we can use dxvk.uri and so on to download DXVK
|
||||
else resolve(new Stream(dxvk));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export type { TDXVK };
|
|
@ -103,7 +103,7 @@ export default class Downloader
|
|||
* @param uri
|
||||
* @param output
|
||||
*
|
||||
* @returns Promise<Stream>
|
||||
* @returns downloading stream
|
||||
*/
|
||||
public static async download(uri: string, output: string|null = null): Promise<Stream>
|
||||
{
|
||||
|
|
|
@ -3,166 +3,16 @@ import {
|
|||
RunnerFamily
|
||||
} from './types/Runners';
|
||||
|
||||
import Constants from './Constants';
|
||||
import AbstractInstaller from './AbstractInstaller';
|
||||
|
||||
declare const Neutralino;
|
||||
|
||||
import Constants from './Constants';
|
||||
import Downloader from './Downloader';
|
||||
import Archive from './Archive';
|
||||
|
||||
class Stream
|
||||
class Stream extends AbstractInstaller
|
||||
{
|
||||
/**
|
||||
* The interval in ms between progress event calls
|
||||
*/
|
||||
public downloadProgressInterval: number = 200;
|
||||
|
||||
/**
|
||||
* The interval in ms between progress event calls
|
||||
*/
|
||||
public unpackProgressInterval: number = 500;
|
||||
|
||||
protected onDownloadStart?: () => void;
|
||||
protected onUnpackStart?: () => void;
|
||||
|
||||
protected onDownloadProgress?: (current: number, total: number, difference: number) => void;
|
||||
protected onUnpackProgress?: (current: number, total: number, difference: number) => void;
|
||||
|
||||
protected onDownloadFinish?: () => void;
|
||||
protected onUnpackFinish?: () => void;
|
||||
|
||||
protected downloadStarted: boolean = false;
|
||||
protected unpackStarted: boolean = false;
|
||||
|
||||
protected downloadFinished: boolean = false;
|
||||
protected unpackFinished: boolean = false;
|
||||
|
||||
public constructor(runner: Runner)
|
||||
{
|
||||
Constants.paths.launcher.then((launcherDir) => {
|
||||
const archivePath = `${launcherDir}/${Downloader.fileFromUri(runner.uri)}`;
|
||||
|
||||
// Download archive
|
||||
Downloader.download(runner.uri, archivePath).then((stream) => {
|
||||
stream.progressInterval = this.downloadProgressInterval;
|
||||
|
||||
stream.start(() => {
|
||||
this.downloadStarted = true;
|
||||
|
||||
if (this.onDownloadStart)
|
||||
this.onDownloadStart();
|
||||
});
|
||||
|
||||
stream.progress((current, total, difference) => {
|
||||
if (this.onDownloadProgress)
|
||||
this.onDownloadProgress(current, total, difference);
|
||||
});
|
||||
|
||||
stream.finish(() => {
|
||||
this.downloadFinished = true;
|
||||
|
||||
if (this.onDownloadFinish)
|
||||
this.onDownloadFinish();
|
||||
|
||||
// And then unpack it
|
||||
Constants.paths.runners.then((runners) => {
|
||||
Archive.unpack(archivePath, runners).then((stream) => {
|
||||
stream.progressInterval = this.unpackProgressInterval;
|
||||
|
||||
stream.start(() => {
|
||||
this.unpackStarted = true;
|
||||
|
||||
if (this.onUnpackStart)
|
||||
this.onUnpackStart();
|
||||
});
|
||||
|
||||
stream.progress((current, total, difference) => {
|
||||
if (this.onUnpackProgress)
|
||||
this.onUnpackProgress(current, total, difference);
|
||||
});
|
||||
|
||||
stream.finish(() => {
|
||||
this.unpackFinished = true;
|
||||
|
||||
if (this.onUnpackFinish)
|
||||
this.onUnpackFinish();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify event that will be called after the runner will begin downloading
|
||||
*
|
||||
* @param callback
|
||||
*/
|
||||
public downloadStart(callback: () => void)
|
||||
{
|
||||
this.onDownloadStart = callback;
|
||||
|
||||
if (this.downloadStarted)
|
||||
callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify event that will be called after the runner will begin unpacking
|
||||
*
|
||||
* @param callback
|
||||
*/
|
||||
public unpackStart(callback: () => void)
|
||||
{
|
||||
this.onUnpackStart = callback;
|
||||
|
||||
if (this.unpackStarted)
|
||||
callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify event that will be called every [this.downloadProgressInterval] ms during the runner downloading
|
||||
*
|
||||
* @param callback
|
||||
*/
|
||||
public downloadProgress(callback: (current: number, total: number, difference: number) => void)
|
||||
{
|
||||
this.onDownloadProgress = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify event that will be called every [this.unpackProgressInterval] ms during the runner unpacking
|
||||
*
|
||||
* @param callback
|
||||
*/
|
||||
public unpackProgress(callback: (current: number, total: number, difference: number) => void)
|
||||
{
|
||||
this.onUnpackProgress = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify event that will be called after the runner will be downloaded
|
||||
*
|
||||
* @param callback
|
||||
*/
|
||||
public downloadFinish(callback: () => void)
|
||||
{
|
||||
this.onDownloadFinish = callback;
|
||||
|
||||
if (this.downloadFinished)
|
||||
callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify event that will be called after the runner will be unpacked
|
||||
*
|
||||
* @param callback
|
||||
*/
|
||||
public unpackFinish(callback: () => void)
|
||||
{
|
||||
this.onUnpackFinish = callback;
|
||||
|
||||
if (this.unpackFinished)
|
||||
callback();
|
||||
super(runner.uri, Constants.paths.runners);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,8 +20,6 @@ class Runners
|
|||
{
|
||||
/**
|
||||
* Get runners list
|
||||
*
|
||||
* @returns Promise<Runner[]>
|
||||
*/
|
||||
public static get(): Promise<RunnerFamily[]>
|
||||
{
|
||||
|
@ -213,8 +61,8 @@ class Runners
|
|||
/**
|
||||
* Download runner to the [Constants.paths.runners] directory
|
||||
*
|
||||
* @param runner Runner object or name
|
||||
* @returns Promise<null|Stream>
|
||||
* @param runner runner object or name
|
||||
* @returns null if the runner with specified name is not exists. Otherwise - installation stream
|
||||
*/
|
||||
public static download(runner: Runner|Runner['name']): Promise<null|Stream>
|
||||
{
|
||||
|
|
8
src/ts/types/DXVK.d.ts
vendored
Normal file
8
src/ts/types/DXVK.d.ts
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
type DXVK = {
|
||||
version: string;
|
||||
uri: string;
|
||||
recommended: boolean;
|
||||
installed: boolean;
|
||||
};
|
||||
|
||||
export type { DXVK };
|
2
src/ts/types/Runners.d.ts
vendored
2
src/ts/types/Runners.d.ts
vendored
|
@ -2,7 +2,7 @@ type Runner = {
|
|||
/**
|
||||
* e.g. proton-ge
|
||||
*/
|
||||
family: string;
|
||||
family: string;
|
||||
|
||||
/**
|
||||
* e.g. Proton-6.20-GE-1
|
||||
|
|
Loading…
Reference in a new issue