API improvements

- added `Game.update()` method
- added `Voice.update()` method
- fixed `ProgressBar.update()` types errors
- added languages to the `Voice.current` field
- updated `package.json` and `tsconfig.json`
- updated roadmap goals
This commit is contained in:
Observer KRypt0n_ 2021-12-23 22:19:32 +02:00
parent f85acba926
commit 6e38611900
No known key found for this signature in database
GPG key ID: DC5D4EC1303465DA
9 changed files with 107 additions and 35 deletions

View file

@ -122,14 +122,14 @@ This is our current roadmap goals. You can find older ones [here](ROADMAP.md)
* <s>Make `DXVK` class to manage DXVK installations</s>
* <s>Make `Runners` class to manage wines installations</s>
* <s>Make `Configs` class to manage launcher's configs</s>
* Make `Game` class to control game-related features
* <s>Make `Game` class to control game-related features</s>
* <s>Ability to parse current installed version</s>
* <s>Ability to get latest available version</s>
* Ability to download and install updates
* Make `Voice` class to control voice packages-related features
* <s>Ability to download and install updates</s>
* <s>Make `Voice` class to control voice packages-related features</s>
* <s>Ability to parse current installed voice packs and get selected one</s>
* <s>Ability to get latest available voice packs</s>
* Ability to download and install updates
* <s>Ability to download and install updates</s>
* Make `Patch` class to control patch-related features
* <s>Ability to get current installed patch</s>
* <s>Ability to get latest available patch</s>
@ -140,9 +140,9 @@ This is our current roadmap goals. You can find older ones [here](ROADMAP.md)
#### Launcher functions
* Make `Launcher` class to manage launcher-related features
* <s>Downloading progress</s>
* Launcher state functionality
* Make Vue components
* Progress bar for the main window
* Checkbox
* Selection
* SelectionList

View file

@ -24,7 +24,7 @@
</div>
<div id="launcher-content">
<iframe :src="uri.social" scrolling="no" style="position: absolute; border: 0; top: 0; left: 0;" width="100%" height="100%"></iframe>
<iframe id="launcher-content-frame" :src="uri.social" scrolling="no" style="position: absolute; border: 0; top: 0; left: 0;" width="100%" height="100%"></iframe>
</div>
<div id="settings">

View file

@ -1,6 +1,7 @@
{
"name": "an-anime-game-launcher",
"version": "3.0.0",
"license": "GPL-3.0-or-later",
"scripts": {
"neu": "neu",
"dev": "vite build && neu run --disable-auto-reload",
@ -12,6 +13,7 @@
},
"devDependencies": {
"@neutralinojs/neu": "^8.0.0",
"@types/js-md5": "^0.4.3",
"@vitejs/plugin-vue": "^2.0.1",
"sass": "^1.45.1",
"vite": "^2.7.6"

View file

@ -1,4 +1,4 @@
import { createApp } from 'vue/dist/vue.esm-bundler';
import { createApp } from 'vue';
import Window from '../ts/neutralino/Window';

View file

@ -7,11 +7,18 @@ import type {
import constants from './Constants';
import fetch from './core/Fetch';
import Downloader, { Stream } from './core/Downloader';
import AbstractInstaller from './core/AbstractInstaller';
declare const Neutralino;
class Stream extends AbstractInstaller
{
public constructor(uri: string)
{
super(uri, constants.paths.gameDir);
}
}
export default class Game
{
/**
@ -122,10 +129,20 @@ export default class Game
});
}
public static update(version: string|null = null): Promise<Stream>
/**
* Get the game installation stream
*
* @returns null if the version can't be found
* @returns rejects Error object if company's servers are unreachable or they responded with an error
*/
public static update(version: string|null = null): Promise<Stream|null>
{
return new Promise((resolve) => {
return new Promise((resolve, reject) => {
(version === null ? this.latest : this.getDiff(version))
.then((data: Latest|Diff|null) => resolve(data === null ? null : new Stream(data.path)))
.catch((error) => reject(error));
});
}
}
export { Stream };

View file

@ -3,6 +3,8 @@ import Configs from './Configs';
import Background from './launcher/Background';
import ProgressBar from './launcher/ProgressBar';
declare const Neutralino;
export default class Launcher
{
public app;
@ -55,7 +57,24 @@ export default class Launcher
return new Promise(async (resolve) => {
this.app.uri.social = `https://${constants.placeholders.lowercase.first}.${constants.placeholders.lowercase.company}.com/launcher/10/${await Configs.get('lang.launcher')}?api_url=https%3A%2F%2Fapi-os-takumi.${constants.placeholders.lowercase.company}.com%2Fhk4e_global&key=gcStgarh&prev=false`;
resolve();
const iframe = <HTMLElement>document.getElementById('launcher-content')!.children[0];
iframe.onload = () => {
// Buttons are not working and we can't edit
// them inside iframe because of Neutralino restrictions
/*console.log(window.frames['launcher-content-frame']);
window.frames['launcher-content-frame'].document.querySelectorAll('a[href]').forEach((link) => {
console.log(link);
link.addEventListener('click', () => {
Neutralino.os.open(link.getAttribute('href'));
});
});*/
resolve();
};
});
}
};

View file

@ -3,9 +3,18 @@ import type { InstalledVoice } from './types/Voice';
import constants from './Constants';
import Game from './Game';
import AbstractInstaller from './core/AbstractInstaller';
declare const Neutralino;
class Stream extends AbstractInstaller
{
public constructor(uri: string)
{
super(uri, constants.paths.gameDir);
}
}
export default class Voice
{
/**
@ -16,10 +25,11 @@ export default class Voice
return new Promise(async (resolve) => {
const persistentPath = `${await constants.paths.gameDataDir}/Persistent/audio_lang_14`;
// TODO: more langs folders
const langs = {
'English(US)': 'en-us',
'Japanese': 'ja-jp'
'Japanese': 'ja-jp',
'Korean': 'ko-kr',
'Chinese': 'zn-cn'
};
let installedVoice: InstalledVoice = {
@ -78,4 +88,31 @@ export default class Voice
.catch((error) => reject(error));
});
}
/**
* Get the voice data installation stream
*
* @returns null if the language or the version can't be found
* @returns rejects Error object if company's servers are unreachable or they responded with an error
*/
public static update(lang: string|null = null, version: string|null = null): Promise<Stream|null>
{
return new Promise((resolve, reject) => {
(version === null ? this.latest : this.getDiff(version))
.then((data: VoicePack[]|null) => {
if (data === null)
resolve(null);
else
{
const voice = data.filter(voice => voice.language === lang);
resolve(voice.length === 1 ? new Stream(voice[0].path) : null);
}
})
.catch((error) => reject(error));
});
}
}
export { Stream };

View file

@ -23,7 +23,7 @@ export default class ProgressBar
public speedLabelElement: HTMLElement;
public etaLabelElement: HTMLElement;
public options: InitOptions;
public options?: InitOptions;
protected progress = {
beganAt: 0,
@ -87,23 +87,23 @@ export default class ProgressBar
public update(current: number, total: number, difference: number): void
{
// Update progress label if it is not a static text
if (typeof this.options.label === 'function')
this.downloadedLabelElement.textContent = this.options.label(current, total, difference);
if (typeof this.options!.label === 'function')
this.downloadedLabelElement.textContent = this.options!.label(current, total, difference);
// Otherwise update percents and totals if we should
else if (this.options.showPercents || this.options.showPercents)
else if (this.options!.showPercents || this.options!.showPercents)
{
this.downloadedLabelElement.textContent = `${this.options.label}:`;
this.downloadedLabelElement.textContent = `${this.options!.label}:`;
if (this.options.showPercents)
if (this.options!.showPercents)
this.downloadedLabelElement.textContent += ` ${Math.round(current / total * 100)}%`;
if (this.options.showTotals)
if (this.options!.showTotals)
this.downloadedLabelElement.textContent += ` (${ProgressBar.prettifyBytes(current)} / ${ProgressBar.prettifyBytes(total)})`;
}
// Update progress width
this.progressElement.style['width'] = `${(current / total * 100).toFixed(2)}%`;
this.progressElement.style['width'] = `${(current / total * 100).toFixed(3)}%`;
this.progress.temp += difference;
@ -111,11 +111,11 @@ export default class ProgressBar
if (Date.now() - this.progress.prevTime > 1000)
{
// Update speed if we need
if (this.options.showSpeed)
if (this.options!.showSpeed)
this.speedLabelElement.textContent = `${ProgressBar.prettifyBytes(this.progress.temp / (Date.now() - this.progress.prevTime) * 1000)}/s`;
// Update ETA if we need
if (this.options.showEta)
if (this.options!.showEta)
{
type etaType = string | number;
@ -143,11 +143,11 @@ export default class ProgressBar
}
// Call user-provided update callback
if (this.options.update)
this.options.update(current, total, difference);
if (this.options!.update)
this.options!.update(current, total, difference);
if (current === total && this.options.finish)
this.options.finish();
if (current === total && this.options!.finish)
this.options!.finish();
}
/**

View file

@ -11,10 +11,7 @@
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "es5", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
"lib": [ /* Specify a set of bundled library declaration files that describe the target runtime environment. */
"ES2021.String"
],
"target": "es2021", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
@ -26,9 +23,9 @@
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
/* Modules */
"module": "commonjs", /* Specify what module code is generated. */
"module": "es2020", /* Specify what module code is generated. */
// "rootDir": "./", /* Specify the root folder within your source files. */
// "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
"moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */