From 748b197984b3c054546132497a065731532e05e2 Mon Sep 17 00:00:00 2001 From: Observer KRypt0n_ Date: Tue, 21 Dec 2021 23:28:46 +0200 Subject: [PATCH] API improvements - changed dxvk fields - added abstract `Installer` class to simplify `Stream` classes - added `DXVK` class - updated comments --- public/dxvks.json | 22 ++--- src/pages/index.ts | 11 +-- src/ts/AbstractInstaller.ts | 165 +++++++++++++++++++++++++++++++++++ src/ts/Archive.ts | 4 +- src/ts/Configs.ts | 4 +- src/ts/Constants.ts | 24 ++---- src/ts/DXVK.ts | 78 +++++++++++++++++ src/ts/Downloader.ts | 2 +- src/ts/Runners.ts | 166 ++---------------------------------- src/ts/types/DXVK.d.ts | 8 ++ src/ts/types/Runners.d.ts | 2 +- 11 files changed, 283 insertions(+), 203 deletions(-) create mode 100644 src/ts/AbstractInstaller.ts create mode 100644 src/ts/types/DXVK.d.ts diff --git a/public/dxvks.json b/public/dxvks.json index 303a3f6..d3e5471 100644 --- a/public/dxvks.json +++ b/public/dxvks.json @@ -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 } ] \ No newline at end of file diff --git a/src/pages/index.ts b/src/pages/index.ts index 84e73b5..b78fc13 100644 --- a/src/pages/index.ts +++ b/src/pages/index.ts @@ -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'); - }); - });*/ } }); diff --git a/src/ts/AbstractInstaller.ts b/src/ts/AbstractInstaller.ts new file mode 100644 index 0000000..d09d507 --- /dev/null +++ b/src/ts/AbstractInstaller.ts @@ -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) + { + 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(); + } +} diff --git a/src/ts/Archive.ts b/src/ts/Archive.ts index 417bb06..cd5348f 100644 --- a/src/ts/Archive.ts +++ b/src/ts/Archive.ts @@ -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 + * @returns null if the archive has unsupported type. Otherwise - archive info */ public static getInfo(path: string): Promise { diff --git a/src/ts/Configs.ts b/src/ts/Configs.ts index 65f7417..75f1580 100644 --- a/src/ts/Configs.ts +++ b/src/ts/Configs.ts @@ -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 + * @returns undefined if config is not exists. Otherwise - config value */ public static get(name: string = ''): Promise { @@ -67,6 +68,7 @@ export default class Configs * Set default values * * @param configs object of default values + * @returns Promise indicates when the default settings was applied */ public static defaults(configs: scalar): Promise { diff --git a/src/ts/Constants.ts b/src/ts/Constants.ts index 961e4fa..8ec8d14 100644 --- a/src/ts/Constants.ts +++ b/src/ts/Constants.ts @@ -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 + * @defaultValue "~/.local/share/anime-game-launcher" */ public static get launcher(): Promise { @@ -34,9 +28,7 @@ class Paths /** * Runners directory * - * Default is ~/.local/share/anime-game-launcher/runners - * - * @returns Promise + * @defaultValue "~/.local/share/anime-game-launcher/runners" */ public static get runners(): Promise { @@ -46,9 +38,7 @@ class Paths /** * DXVKs directory * - * Default is ~/.local/share/anime-game-launcher/dxvks - * - * @returns Promise + * @defaultValue "~/.local/share/anime-game-launcher/dxvks" */ public static get dxvks(): Promise { @@ -58,9 +48,7 @@ class Paths /** * Config file * - * Default is ~/.local/share/anime-game-launcher/config.json - * - * @returns Promise + * @defaultValue "~/.local/share/anime-game-launcher/config.json" */ public static get config(): Promise { diff --git a/src/ts/DXVK.ts b/src/ts/DXVK.ts index e69de29..f85f5b9 100644 --- a/src/ts/DXVK.ts +++ b/src/ts/DXVK.ts @@ -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 + { + 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 + { + 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 }; diff --git a/src/ts/Downloader.ts b/src/ts/Downloader.ts index a82584d..8ed816a 100644 --- a/src/ts/Downloader.ts +++ b/src/ts/Downloader.ts @@ -103,7 +103,7 @@ export default class Downloader * @param uri * @param output * - * @returns Promise + * @returns downloading stream */ public static async download(uri: string, output: string|null = null): Promise { diff --git a/src/ts/Runners.ts b/src/ts/Runners.ts index 3d904af..39f343b 100644 --- a/src/ts/Runners.ts +++ b/src/ts/Runners.ts @@ -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 */ public static get(): Promise { @@ -213,8 +61,8 @@ class Runners /** * Download runner to the [Constants.paths.runners] directory * - * @param runner Runner object or name - * @returns Promise + * @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 { diff --git a/src/ts/types/DXVK.d.ts b/src/ts/types/DXVK.d.ts new file mode 100644 index 0000000..ca0d93d --- /dev/null +++ b/src/ts/types/DXVK.d.ts @@ -0,0 +1,8 @@ +type DXVK = { + version: string; + uri: string; + recommended: boolean; + installed: boolean; +}; + +export type { DXVK }; diff --git a/src/ts/types/Runners.d.ts b/src/ts/types/Runners.d.ts index fdedddb..9cff05c 100644 --- a/src/ts/types/Runners.d.ts +++ b/src/ts/types/Runners.d.ts @@ -2,7 +2,7 @@ type Runner = { /** * e.g. proton-ge */ - family: string; + family: string; /** * e.g. Proton-6.20-GE-1