Merge branch 'neutralino' of https://gitlab.com/KRypt0n_/an-anime-game-launcher into neutralino

This commit is contained in:
Maroxy 2021-12-23 17:48:26 +01:00
commit 65ab2a8be7
No known key found for this signature in database
GPG key ID: F4B27EADB21E3021
12 changed files with 232 additions and 95 deletions

View file

@ -9,24 +9,22 @@
<body>
<div id="app" theme="light">
<h1 id="progress"></h1>
<img class="background">
<img class="background" :src="backgroundUri">
<div id="downloader-panel" class="dark" style="display: none">
<div id="downloader-label">
<div class="downloader-panel" theme="dark">
<div class="downloader-label">
<span id="downloaded">Downloading</span>
<span id="speed"></span>
<span id="eta"></span>
</div>
<div class="progress-bar" id="downloader">
<div class="progress-bar">
<div class="progress"></div>
</div>
</div>
<div id="launcher-content">
<iframe id="social" scrolling="no" style="position: absolute; border: 0; top: 0; left: 0;" width="100%" height="100%"></iframe>
<iframe id="social" :src="socialUri" scrolling="no" style="position: absolute; border: 0; top: 0; left: 0;" width="100%" height="100%"></iframe>
</div>
<div id="settings">
@ -42,4 +40,4 @@
<script type="module" src="/src/entry.js"></script>
<script type="module" lang="ts" src="/src/pages/index.ts"></script>
</body>
</html>
</html>

View file

@ -1,6 +1,6 @@
{
"applicationId": "com.krypt0nn.an-anime-game-linux-launcher",
"version": "1.0.0",
"version": "3.0.0",
"defaultMode": "window",
"port": 0,
"documentRoot": "/bundle/",

View file

@ -14,6 +14,6 @@
"@neutralinojs/neu": "^8.0.0",
"@vitejs/plugin-vue": "^2.0.1",
"sass": "^1.45.1",
"vite": "^2.7.4"
"vite": "^2.7.6"
}
}

View file

@ -1,62 +1,31 @@
import * as Vue from 'vue/dist/vue.esm-bundler';
import { createApp } from 'vue/dist/vue.esm-bundler';
import Window from '../ts/neutralino/Window';
import Patch from '../ts/Patch';
import Voice from '../ts/Voice';
import fetch from '../ts/core/Fetch';
import Downloader from '../ts/core/Downloader';
const app = Vue.createApp({
import Launcher from '../ts/Launcher';
let app = createApp({
data: () => ({
progress: '0%'
socialUri: '',
backgroundUri: ''
}),
methods: {
showAbout: () => Window.open('about')
},
mounted: () => {
Window.current.show();
mounted()
{
const launcher = new Launcher(this);
Patch.latest.then(console.log);
new Promise(async (resolve) => {
await launcher.updateSocial();
await launcher.updateBackground();
/*fetch('https://sdk-os-static.mihoyo.com/hk4e_global/mdk/launcher/api/resource?key=gcStgarh&launcher_id=10', 1000)
.then((response) => {
console.log(response);
response.body().then((body) => console.log(body.length));
});*/
/*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'));
});*/
/*DXVK.download('1.8').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)}%`);
});
stream.finish(() => console.log('finished'));
});*/
resolve(null);
}).then(() => {
Window.current.show();
});
}
});

View file

@ -75,33 +75,10 @@
.unactive
display: none
.progress-bar
padding: 0
background-color: rgba(0, 0, 0, .1)
border: 1px solid rgba(0, 0, 0, .2)
border-radius: 8px
.progress
width: 0
height: 100%
background-color: rgba(255, 255, 255, .7)
border-radius: 6px
#downloader-panel
.downloader-panel
user-select: none
#downloader
position: absolute
left: 48px
bottom: 68px
width: 720px
height: 36px
#downloader-label
.downloader-label
position: absolute
left: 48px
@ -120,11 +97,34 @@
color: #cccccc
font-weight: 100
#downloader-panel.dark
.progress-bar
position: absolute
padding: 0
left: 48px
bottom: 68px
width: 720px
height: 36px
background-color: rgba(0, 0, 0, .1)
border: 1px solid rgba(0, 0, 0, .2)
border-radius: 8px
.progress
width: 0
height: 100%
background-color: rgba(255, 255, 255, .7)
border-radius: 6px
/*#downloader-panel.dark
#downloader-label
#downloaded, #speed, #eta
color: rgba(0, 0, 0, .7)
#downloader
background-color: rgba(0,0,0,.3)
border: 1px solid rgba(0,0,0,.4)
border: 1px solid rgba(0,0,0,.4)

View file

@ -1,11 +1,10 @@
import constants from './Constants';
declare const Neutralino;
declare const NL_CWD;
// Ok yea, null and object aren't scalars
// Ok yea, null, object and boolean aren't scalars
// but I don't care
type scalar = null | string | number | object;
type scalar = null | string | number | boolean | object;
export default class Configs
{

View file

@ -90,6 +90,16 @@ class Paths
return new Promise(async (resolve) => resolve(`${await this.launcherDir}/config.json`));
}
/**
* Cache file
*
* @default "~/.local/share/anime-game-launcher/cache.json"
*/
public static get cache(): Promise<string>
{
return new Promise(async (resolve) => resolve(`${await this.launcherDir}/cache.json`));
}
public static readonly prefix = Prefix;
/**

95
src/ts/Launcher.ts Normal file
View file

@ -0,0 +1,95 @@
import constants from './Constants';
import Configs from './Configs';
import fetch from './core/Fetch';
export default class Launcher
{
public app;
public constructor(app)
{
this.app = app;
}
/**
* Get background image URI
*
* Neutralino is unnable to load local files
* so we sadly can't provide proper caching
*/
/*public getBackgroundUri(): Promise<string>
{
return new Promise((resolve, reject) => {
Cache.get('background').then(async (background) => {
const launcherDir = await constants.paths.launcherDir;
// If the background is not cached or
// the cache is expired
if (background === null || background.expired)
{
const header = await fetch(constants.backgroundUri + await Configs.get('lang.launcher'));
// Reject an error if background server is not available
if (!header.ok)
reject(new Error(`${constants.placeholders.uppercase.company}'s background server is not responding`));
else
{
header.body().then(async (body) => {
const json = JSON.parse(body);
// If the background wasn't loaded - then again reject an error
if (json.data.adv.background === undefined)
reject(new Error('Background property wasn\'t found'));
else
{
// Store some background info to the cache
await Cache.set('background', {
gameVersion: (await Game.latest).version,
cachedAt: Math.round(Date.now() / 1000)
}, 7 * 24 * 60 * 60);
console.log(json.data.adv.background);
// Download background picture and return path to it
Downloader.download(json.data.adv.background, `${launcherDir}/background.png`)
.then((stream) => {
stream.finish(() => resolve(`file://${launcherDir}/background.png`));
});
}
});
}
}
// Background is cached
// todo: add cache auto dropping when the banner is updated
else resolve(`file://${launcherDir}/background.png`);
});
});
}*/
public updateBackground(): Promise<void>
{
return new Promise(async (resolve) => {
fetch(constants.backgroundUri + await Configs.get('lang.launcher'))
.then((header) => header.body().then((body) => {
this.app.backgroundUri = JSON.parse(body).data.adv.background;
resolve();
}));
});
}
/**
* Update launcher social buttons
*/
public updateSocial(): Promise<void>
{
return new Promise(async (resolve) => {
this.app.socialUri = `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();
});
}
};

View file

@ -9,8 +9,6 @@ import constants from './Constants';
import Game from './Game';
import fetch from './core/Fetch';
declare const Neutralino;
export default class Patch
{
public static fetchTimeout: number = 3000;

70
src/ts/core/Cache.ts Normal file
View file

@ -0,0 +1,70 @@
import constants from '../Constants';
type Record = {
expired: boolean;
value: object|object[];
};
declare const Neutralino;
export default class Cache
{
/**
* Get cached value
*
* @returns null if this value is not cached
*/
public static get(name: string): Promise<Record|null>
{
return new Promise(async (resolve) => {
Neutralino.filesystem.readFile(await constants.paths.cache)
.then((cache) => {
cache = JSON.parse(cache);
if (cache[name] === undefined)
resolve(null);
else
{
resolve({
expired: cache[name].ttl !== null ? Date.now() > cache[name].ttl * 1000 : false,
value: JSON.parse(atob(cache[name].value))
});
}
})
.catch(() => resolve(null));
});
}
/**
* Cache value
*
* @param name name of the value to cache
* @param value value to cache
* @param ttl number of seconds to cache
*
* @returns promise that indicates when the value will be cached
*/
public static set(name: string, value: object|object[], ttl: number|null = null): Promise<void>
{
return new Promise((resolve) => {
constants.paths.cache.then((cacheFile) => {
let cache = {};
Neutralino.filesystem.readFile(cacheFile)
.then((cacheRaw) => cache = JSON.parse(cacheRaw))
.catch(() => {});
cache[name] = {
ttl: ttl !== null ? Math.round(Date.now() / 1000) + ttl : null,
value: btoa(JSON.stringify(value))
};
Neutralino.filesystem.writeFile(cacheFile, JSON.stringify(cache))
.then(() => resolve());
});
});
}
};
export type { Record };

View file

@ -101,8 +101,8 @@ export default class Downloader
/**
* Download file
*
* @param uri
* @param output
* @param uri file's uri to download
* @param output relative or absolute path to the file to save it as
*
* @returns downloading stream
*/

View file

@ -7,9 +7,7 @@ export default defineConfig({
server: {
port: 8080
},
plugins: [
vue()
],
plugins: [vue()],
base: '',
build: {
outDir: 'bundle',