Several changes

- fixed `constants.paths.prefix.current` value
- made `Tray` class to manage tray features
- added tray icon
This commit is contained in:
Observer KRypt0n_ 2022-01-06 18:35:48 +02:00
parent 3904a86381
commit 7fafddffac
No known key found for this signature in database
GPG key ID: DC5D4EC1303465DA
6 changed files with 169 additions and 11 deletions

View file

@ -6,7 +6,7 @@
"scripts": { "scripts": {
"neu": "neu", "neu": "neu",
"dev": "vite build && neu run --disable-auto-reload", "dev": "vite build && neu run --disable-auto-reload",
"build": "vite build && rm -rf dist/an-anime-game-launcher/public && mkdir dist/an-anime-game-launcher/public && cp public/runners.json dist/an-anime-game-launcher/public && cp public/dxvks.json dist/an-anime-game-launcher/public && cp -r public/locales dist/an-anime-game-launcher/public/locales && cp -r public/shaders dist/an-anime-game-launcher/public/shaders && cp -r public/discord-rpc dist/an-anime-game-launcher/public/discord-rpc && neu build --release", "build": "vite build && rm -rf dist/an-anime-game-launcher/public && mkdir dist/an-anime-game-launcher/public && cp public dist/an-anime-game-launcher/public && neu build --release",
"bundle": "node scripts/bundle-appimage.cjs", "bundle": "node scripts/bundle-appimage.cjs",
"check": "svelte-check --tsconfig ./tsconfig.json" "check": "svelte-check --tsconfig ./tsconfig.json"
}, },

View file

@ -12,7 +12,7 @@ class Prefix
*/ */
public static get current(): Promise<string> public static get current(): Promise<string>
{ {
return new Promise(async (resolve) => resolve(await Configs.get('prefix') as string)); return new Promise(async (resolve) => resolve(await Configs.get('folders.prefix') as string));
} }
/** /**

View file

@ -1,25 +1,30 @@
import Window from './neutralino/Window'; import Window from './neutralino/Window';
import Process from './neutralino/Process'; import Process from './neutralino/Process';
import Tray from './neutralino/Tray';
import constants from './Constants'; import constants from './Constants';
import Configs from './Configs'; import Configs from './Configs';
import ProgressBar from './launcher/ProgressBar';
import State from './launcher/State';
import Debug from './core/Debug'; import Debug from './core/Debug';
import IPC from './core/IPC'; import IPC from './core/IPC';
import DiscordRPC from './core/DiscordRPC'; import DiscordRPC from './core/DiscordRPC';
import ProgressBar from './launcher/ProgressBar';
import State from './launcher/State';
export default class Launcher export default class Launcher
{ {
public state?: State; public state?: State;
public progressBar?: ProgressBar; public progressBar?: ProgressBar;
public rpc?: DiscordRPC; public rpc?: DiscordRPC;
public tray: Tray;
protected settingsMenu?: Process; protected settingsMenu?: Process;
public constructor(onMount) public constructor(onMount)
{ {
this.tray = new Tray('/public/icons/256x256.png');
this.tray.update();
this.updateDiscordRPC('in-launcher'); this.updateDiscordRPC('in-launcher');
onMount(() => { onMount(() => {

View file

@ -39,6 +39,10 @@ export default (launcher: Launcher): Promise<void> => {
launcher.updateDiscordRPC('in-game'); launcher.updateDiscordRPC('in-game');
launcher.tray.update([
{ text: 'Starting the game...', disabled: true }
]);
/** /**
* Selecting wine executable * Selecting wine executable
*/ */
@ -131,15 +135,45 @@ export default (launcher: Launcher): Promise<void> => {
}); });
// Game was started by the launcher.bat file // Game was started by the launcher.bat file
// so we just need to wait until GenshinImpact process // so we just need to wait until AnimeGame.e process
// will be closed // will be closed
process.finish(() => { process.finish(() => {
const processName = `${constants.placeholders.uppercase.first + constants.placeholders.uppercase.second}.e`;
let closeGameCounter = 0;
const waiter = async () => { const waiter = async () => {
const processes: string = (await Neutralino.os.execCommand('ps -A')).stdOut; const processes: string = (await Neutralino.os.execCommand('ps -A')).stdOut;
// Game is still running // Game is still running
if (processes.includes('GenshinImpact')) if (processes.includes(processName))
{
const playtime = Math.round((Date.now() - startTime) / 1000);
let hours: string|number = Math.floor(playtime / 3600);
let minutes: string|number = Math.floor((playtime - hours * 3600) / 60);
let seconds: string|number = playtime - hours * 3600 - minutes * 60;
if (hours < 10)
hours = `0${hours}`;
if (minutes < 10)
minutes = `0${minutes}`;
if (seconds < 10)
seconds = `0${seconds}`;
launcher.tray.update([
{ text: `Playing for ${hours}:${minutes}:${seconds}`, disabled: true },
{
text: `Close game${closeGameCounter > 0 ? ` (${closeGameCounter})` : ''}`,
click: () => Neutralino.os.execCommand(`kill ${++closeGameCounter < 3 ? '-15' : '-9'} $(pidof ${processName})`)
}
]);
setTimeout(waiter, 3000); setTimeout(waiter, 3000);
}
// Game was closed // Game was closed
else else
@ -147,8 +181,10 @@ export default (launcher: Launcher): Promise<void> => {
const stopTime = Date.now(); const stopTime = Date.now();
Window.current.show(); Window.current.show();
Window.current.center(1280, 700);
launcher.updateDiscordRPC('in-launcher'); launcher.updateDiscordRPC('in-launcher');
launcher.tray.hide();
// TODO // TODO

View file

@ -199,11 +199,8 @@ class Process
// Set env variables // Set env variables
if (options.env) if (options.env)
{ for (const key of Object.keys(options.env))
Object.keys(options.env).forEach((key) => {
command = `${key}="${this.addSlashes(options.env![key].toString())}" ${command}`; command = `${key}="${this.addSlashes(options.env![key].toString())}" ${command}`;
});
}
// Set output redirection to the temp file // Set output redirection to the temp file
command = `${command} > "${this.addSlashes(tmpFile)}" 2>&1`; command = `${command} > "${this.addSlashes(tmpFile)}" 2>&1`;

120
src/ts/neutralino/Tray.ts Normal file
View file

@ -0,0 +1,120 @@
declare const Neutralino;
type Item = {
/**
* Item text
*/
text: string;
/**
* Item id
*/
id?: string;
/**
* Whether the item disabled or not
*
* If yes, then it will be a string
*/
disabled?: boolean;
/**
* Is this item a checkbox or not
*/
checked?: boolean;
/**
* Event on click
*
* If specified, then will generate random
* item id if it is not specified
*/
click?: (item: Item) => void;
};
Neutralino.events.on('trayMenuItemClicked', (item) => {
for (const tray of Tray.trays)
for (const trayItem of tray.items)
if (trayItem.id === item.detail.id)
{
if (trayItem.click)
{
trayItem.click({
id: item.detail.id,
text: item.detail.text,
disabled: item.detail['isDisabled'],
checked: item.detail['isChecked'],
click: trayItem.click
});
}
return;
}
});
export default class Tray
{
public static trays: Tray[] = [];
public icon: string;
protected _items: Item[] = [];
public get items(): Item[]
{
return this._items.map((item) => {
return {
id: item.id,
text: item.text,
disabled: item['isDisabled'],
checked: item['isChecked'],
click: item.click
};
});
}
public set items(items: Item[])
{
this._items = items.map((item) => {
if (item.id === undefined && item.click !== undefined)
item.id = 'click:' + Math.random().toString().substring(2);
return {
id: item.id,
text: item.text,
isDisabled: item.disabled,
isChecked: item.checked,
click: item.click
};
});
}
public constructor(icon: string, items: Item[] = [])
{
this.icon = icon;
this.items = items;
Tray.trays.push(this);
}
public update(items: Item[]|null = null): Promise<void>
{
if (items !== null)
this.items = items;
return Neutralino.os.setTray({
icon: this.icon,
menuItems: this._items
});
}
public hide(): Promise<void>
{
return Neutralino.os.setTray({
icon: this.icon,
menuItems: []
});
}
};
export type { Item };