mirror of
https://github.com/an-anime-team/an-anime-game-launcher.git
synced 2025-03-17 13:40:02 +03:00
API improvements
- added `start` events for `Archive` and `Downloader` streams - fixed `Downloader.download` file size calculation - `Downloader.fileFromUri` is now public - fixed `Runners.get` output type - added `Runners.download` method
This commit is contained in:
parent
a1d1d9a3ca
commit
9dc5b47983
4 changed files with 246 additions and 11 deletions
|
@ -5,6 +5,7 @@ import Window from '../ts/neutralino/Window';
|
|||
import Downloader from '../ts/Downloader';
|
||||
import Archive from '../ts/Archive';
|
||||
import Configs from '../ts/Configs';
|
||||
import Runners from '../ts/Runners';
|
||||
|
||||
const app = Vue.createApp({
|
||||
data: () => ({
|
||||
|
@ -18,6 +19,21 @@ const app = Vue.createApp({
|
|||
mounted: () => {
|
||||
Window.current.show();
|
||||
|
||||
/*Downloader.download('https://github.com/GloriousEggroll/wine-ge-custom/releases/download/6.20-GE-1/wine-lutris-ge-6.20-1-x86_64.tar.xz', '123.tar.xz').then((stream) => {
|
||||
stream.start(() => console.log('Downloading started'));
|
||||
stream.finish(() => console.log('Downloading finished'));
|
||||
|
||||
stream.progress((current, total) => console.log(`${Math.round(current / total * 100)}%`));
|
||||
});*/
|
||||
|
||||
/*Runners.download('wine-lutris-ge-6.20-1-x86_64').then((stream) => {
|
||||
stream.downloadStart(() => console.log('Downloading started'));
|
||||
stream.downloadFinish(() => console.log('Downloading finished'));
|
||||
|
||||
stream.unpackStart(() => console.log('Unpacking started'));
|
||||
stream.unpackFinish(() => console.log('Unpacking finished'));
|
||||
});*/
|
||||
|
||||
/*Archive.unpack('Audio_English(US)_2.3.0.zip', 'tmp').then((stream) => {
|
||||
stream.progress((current, total) => {
|
||||
console.log(`${Math.round(current / total * 100)}%`);
|
||||
|
|
|
@ -18,10 +18,12 @@ class Stream
|
|||
|
||||
protected archive: ArchiveInfo;
|
||||
|
||||
protected onStart?: () => void;
|
||||
protected onProgress?: (current: number, total: number, difference: number) => void;
|
||||
protected onFinish?: () => void;
|
||||
protected onError?: () => void;
|
||||
|
||||
protected started: boolean = false;
|
||||
protected finished: boolean = false;
|
||||
protected throwedError: boolean = false;
|
||||
|
||||
|
@ -33,6 +35,10 @@ class Stream
|
|||
{
|
||||
this.path = path;
|
||||
this.unpackDir = unpackDir;
|
||||
this.started = true;
|
||||
|
||||
if (this.onStart)
|
||||
this.onStart();
|
||||
|
||||
Archive.getInfo(path).then((info) => {
|
||||
if (info === null)
|
||||
|
@ -102,6 +108,19 @@ class Stream
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify event that will be called when the unpacking will be started
|
||||
*
|
||||
* @param callback
|
||||
*/
|
||||
public start(callback: () => void)
|
||||
{
|
||||
this.onStart = callback;
|
||||
|
||||
if (this.started)
|
||||
callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify event that will be called every [this.progressInterval] ms during archive unpacking
|
||||
*
|
||||
|
|
|
@ -9,15 +9,21 @@ class Stream
|
|||
protected total: number;
|
||||
protected previous: number = 0;
|
||||
|
||||
protected onStart?: () => void;
|
||||
protected onProgress?: (current: number, total: number, difference: number) => void;
|
||||
protected onFinish?: () => void;
|
||||
|
||||
protected started: boolean = false;
|
||||
protected finished: boolean = false;
|
||||
|
||||
public constructor(uri: string, output: string, total: number)
|
||||
{
|
||||
this.uri = uri;
|
||||
this.total = total;
|
||||
this.started = true;
|
||||
|
||||
if (this.onStart)
|
||||
this.onStart();
|
||||
|
||||
// @ts-expect-error
|
||||
Neutralino.os.execCommand(`curl -s -L -N -o "${output}" "${uri}"`, {
|
||||
|
@ -51,6 +57,19 @@ class Stream
|
|||
setTimeout(updateProgress, this.progressInterval);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify event that will be called when the downloading will be started
|
||||
*
|
||||
* @param callback
|
||||
*/
|
||||
public start(callback: () => void)
|
||||
{
|
||||
this.onStart = callback;
|
||||
|
||||
if (this.started)
|
||||
callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify event that will be called every [this.progressInterval] ms during the file downloading
|
||||
*
|
||||
|
@ -96,13 +115,16 @@ export default class Downloader
|
|||
|
||||
else statsRaw = statsRaw.stdOut;
|
||||
|
||||
const length = parseInt(/content-length: ([\d]+)/i.exec(statsRaw)[1]);
|
||||
let length = 0;
|
||||
|
||||
for (const match of statsRaw.matchAll(/content-length: ([\d]+)/gi))
|
||||
length = match[1];
|
||||
|
||||
resolve(new Stream(uri, output ?? this.fileFromUri(uri), length));
|
||||
});
|
||||
}
|
||||
|
||||
protected static fileFromUri(uri: string): string
|
||||
public static fileFromUri(uri: string): string
|
||||
{
|
||||
const file = uri.split('/').pop().split('#')[0].split('?')[0];
|
||||
|
||||
|
|
|
@ -1,9 +1,168 @@
|
|||
import type {
|
||||
import {
|
||||
Runner,
|
||||
RunnerFamily
|
||||
} from './types/Runners';
|
||||
|
||||
import constants from './Constants';
|
||||
import Constants from './Constants';
|
||||
import Downloader from './Downloader';
|
||||
import Archive from './Archive';
|
||||
|
||||
class Stream
|
||||
{
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
|
||||
class Runners
|
||||
{
|
||||
|
@ -12,17 +171,17 @@ class Runners
|
|||
*
|
||||
* @returns Promise<Runner[]>
|
||||
*/
|
||||
public static get(): Promise<Runner[]>
|
||||
public static get(): Promise<RunnerFamily[]>
|
||||
{
|
||||
return new Promise((resolve) => {
|
||||
constants.paths.runners.then(async (runnersDir: string) => {
|
||||
Constants.paths.runners.then(async (runnersDir: string) => {
|
||||
// @ts-expect-error
|
||||
let list: RunnerFamily[] = JSON.parse(await Neutralino.filesystem.readFile(`${constants.dirs.app}/public/runners.json`));
|
||||
let list: RunnerFamily[] = JSON.parse(await Neutralino.filesystem.readFile(`${Constants.paths.app}/public/runners.json`));
|
||||
|
||||
// @ts-expect-error
|
||||
const installed: { entry: string, type: string }[] = await Neutralino.filesystem.readDirectory(runnersDir);
|
||||
|
||||
let runners = [];
|
||||
let runners: RunnerFamily[] = [];
|
||||
|
||||
list.forEach((family) => {
|
||||
let newFamily: RunnerFamily = {
|
||||
|
@ -51,16 +210,35 @@ class Runners
|
|||
});
|
||||
}
|
||||
|
||||
public static download(runner: Runner|Runner['name']): Promise<boolean>
|
||||
public static download(runner: Runner|Runner['name']): Promise<null|Stream>
|
||||
{
|
||||
return new Promise((resolve) => {
|
||||
|
||||
return new Promise(async (resolve) => {
|
||||
// If we provided runner property as a name of the runner
|
||||
// then we should find this runner and call this method from it
|
||||
if (typeof runner == 'string')
|
||||
{
|
||||
let foundRunner = null;
|
||||
|
||||
(await this.get()).forEach((family) => {
|
||||
family.runners.forEach((familyRunner) => {
|
||||
if (familyRunner.name == runner)
|
||||
foundRunner = familyRunner;
|
||||
});
|
||||
});
|
||||
|
||||
resolve(foundRunner === null ? null : new Stream(foundRunner));
|
||||
}
|
||||
|
||||
// Otherwise we can use runner.uri and so on to download runner
|
||||
else resolve(new Stream(runner));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default Runners;
|
||||
|
||||
export { Stream };
|
||||
|
||||
export type {
|
||||
Runner,
|
||||
RunnerFamily
|
||||
|
|
Loading…
Add table
Reference in a new issue