set auto update AND fix download version errors

This commit is contained in:
MathieuG-P
2022-09-19 01:04:50 +02:00
parent 5d0e5f03ee
commit b91e1a3567
38 changed files with 500 additions and 220 deletions
@@ -164,6 +164,20 @@ const configuration: webpack.Configuration = {
isDevelopment: process.env.NODE_ENV !== 'production',
nodeModules: webpackPaths.appNodeModulesPath,
}),
new HtmlWebpackPlugin({
filename: path.join('launcher.html'),
template: path.join(webpackPaths.srcRendererPath, 'launcher.ejs'),
minify: {
collapseWhitespace: true,
removeAttributeQuotes: true,
removeComments: true,
},
isBrowser: false,
env: process.env.NODE_ENV,
isDevelopment: process.env.NODE_ENV !== 'production',
nodeModules: webpackPaths.appNodeModulesPath,
})
],
node: {
@@ -143,6 +143,18 @@ const configuration: webpack.Configuration = {
isBrowser: false,
isDevelopment: process.env.NODE_ENV !== 'production',
}),
new HtmlWebpackPlugin({
filename: 'launcher.html',
template: path.join(webpackPaths.srcRendererPath, 'launcher.ejs'),
minify: {
collapseWhitespace: true,
removeAttributeQuotes: true,
removeComments: true,
},
isBrowser: false,
isDevelopment: process.env.NODE_ENV !== 'production',
})
],
};
+8 -6
View File
@@ -108,14 +108,10 @@
}
},
"errors":{
"titles":{
"already-downloading": "A download is already in progress",
"verification-failed":"The verification failed.",
"no-internet": "No internet connection."
},
"msg":{
"Password": "Password is invalid.",
"InvalidCredentials": "Your e-mail or password is invalid 😴",
"InvalidPassword": "Your password is invalid 😕",
"NoManifest": "No manifest was found",
"DirectoryCreate": "Unable to install the necessary folders.",
"NotAvailableApp": "Are you trying to download BeatSaber when you don't have it ? 🤣",
@@ -134,7 +130,9 @@
"ConnectionError": "Unable to connect to Steam after 10 tries 🤯",
"LicenceError": "Unable to get the list of licenses.",
"verification-failed": "Verification failed, try again later.",
"RateLimitExceeded": "You've tried too many times, wait a while and try again later."
"RateLimitExceeded": "You've tried too many times, wait a while and try again later.",
"AlreadyDownloading": "A download is already in progress",
"no-internet": "No internet connection."
}
}
},
@@ -260,6 +258,10 @@
}
}
},
"auto-update":{
"checking": "Checking for updates",
"downloading": "Downloading updates"
},
"dateformat":{
"dayNames": [
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+8 -6
View File
@@ -108,14 +108,10 @@
}
},
"errors":{
"titles":{
"already-downloading": "La descarga ya está en curso",
"verification-failed":"La verificación falló.",
"no-internet": "Sin conexión a Internet."
},
"msg":{
"Password": "La contraseña es inválida.",
"InvalidCredentials": "Su correo electrónico o contraseña no son válidos 😴",
"InvalidPassword": "Su contraseña no es válida 😕",
"NoManifest": "No se ha encontrado el manifiesto",
"DirectoryCreate": "No se pueden instalar las carpetas necesarias.",
"NotAvailableApp": "¿Intentas descargar BeatSaber cuando no lo tienes? 🤣",
@@ -134,7 +130,9 @@
"ConnectionError": "No se puede conectar a Steam después de 10 intentos 🤯",
"LicenceError": "No se puede obtener la lista de licencias.",
"verification-failed": "Verificación fallida, inténtelo más tarde.",
"RateLimitExceeded": "Lo has intentado demasiadas veces, espera un poco y vuelve a intentarlo más tarde."
"RateLimitExceeded": "Lo has intentado demasiadas veces, espera un poco y vuelve a intentarlo más tarde.",
"AlreadyDownloading": "La descarga ya está en curso",
"no-internet": "Sin conexión a Internet."
}
}
},
@@ -260,6 +258,10 @@
}
}
},
"auto-update":{
"checking": "Comprobar las actualizaciones",
"downloading": "Descargar actualizaciones"
},
"dateformat":{
"dayNames": [
"Dom", "Lun", "Mar", "Mié", "Jue", "Vie", "Sáb",
+8 -6
View File
@@ -108,14 +108,10 @@
}
},
"errors":{
"titles":{
"already-downloading": "Un téléchargement est déjà en cours",
"verification-failed": "La vérification a échoué.",
"no-internet": "Pas de connexion internet."
},
"msg":{
"Password": "Le mot de passe est invalide.",
"InvalidCredentials": "Ton e-mail ou mot de passe est invalide 😴",
"InvalidPassword": "Ton mot de passe est invalide 😕",
"NoManifest": "Aucun manifest n'a été trouvé.",
"DirectoryCreate": "Impossible d'installer les dossiers nécessaires.",
"NotAvailableApp": "Tu essayes de télécharger BeatSaber alors que tu ne l'as pas ? 🤣",
@@ -134,7 +130,9 @@
"ConnectionError": "Impossible de se connecter à Steam après 10 essais 🤯",
"LicenceError": "Impossible d'obtenir la liste des licences.",
"verification-failed": "La vérification a échoué, réessaye plus tard.",
"RateLimitExceeded": "Tu as essayé trop de fois attend un peu et recommence plus tard."
"RateLimitExceeded": "Tu as essayé trop de fois attend un peu et recommence plus tard.",
"AlreadyDownloading": "Un téléchargement est déjà en cours",
"no-internet": "Pas de connexion internet."
}
}
},
@@ -260,6 +258,10 @@
}
}
},
"auto-update":{
"checking": "Vérification des mises à jour",
"downloading": "Téléchargement des mises à jour"
},
"dateformat":{
"dayNames": [
"Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam",
+14 -4
View File
@@ -3249,6 +3249,7 @@
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.0.3.tgz",
"integrity": "sha512-SfG2wnyjpUbbdtpnqDpWwklujofC6GarGpvdWrEkg9p5AD/xJmTF2buTNaqs3qtsNBEVQDDjZz9xc2GGpVyMfA==",
"dev": true,
"requires": {
"debug": "^4.3.4",
"sax": "^1.2.4"
@@ -5180,12 +5181,12 @@
"dev": true
},
"electron-updater": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-5.2.1.tgz",
"integrity": "sha512-OQZVIvqcK8j03HjT07uVPgvguP/r8RY2wZcwCM26+fcDOjtrm01Dfz3G8Eru+69znbrR+F9pDzr98ewMavBrWQ==",
"version": "5.2.4",
"resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-5.2.4.tgz",
"integrity": "sha512-AE+I4cEagOJvHvtkBvJCp+hu1mrpinCt7PMmEOsDcpfayrPvWLuxeFVR9BzRvZVbz0eAqpRQjcEuR8gK80K7lQ==",
"requires": {
"@types/semver": "^7.3.6",
"builder-util-runtime": "9.0.3",
"builder-util-runtime": "9.1.1",
"fs-extra": "^10.0.0",
"js-yaml": "^4.1.0",
"lazy-val": "^1.0.5",
@@ -5195,6 +5196,15 @@
"typed-emitter": "^2.1.0"
},
"dependencies": {
"builder-util-runtime": {
"version": "9.1.1",
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.1.1.tgz",
"integrity": "sha512-azRhYLEoDvRDR8Dhis4JatELC/jUvYjm4cVSj7n9dauGTOM2eeNn9KS0z6YA6oDsjI1xphjNbY6PZZeHPzzqaw==",
"requires": {
"debug": "^4.3.4",
"sax": "^1.2.4"
}
},
"fs-extra": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+4 -4
View File
@@ -13,7 +13,8 @@
"start:main": "cross-env NODE_ENV=development electronmon -r ts-node/register/transpile-only ./src/main/main.ts",
"start:preload": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.preload.dev.ts",
"start:renderer": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack serve --config ./.erb/configs/webpack.config.renderer.dev.ts",
"test": "jest"
"test": "jest",
"publish": "npm run build && electron-builder --publish always --win --x64"
},
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
@@ -90,8 +91,7 @@
},
"publish": {
"provider": "github",
"owner": "Zagrios",
"repo": "bs-manager"
"owner": "Zagrios"
}
},
"repository": {
@@ -228,7 +228,7 @@
"electron-debug": "^3.2.0",
"electron-log": "^4.4.8",
"electron-store": "^8.1.0",
"electron-updater": "^5.2.1",
"electron-updater": "^5.2.4",
"framer-motion": "^7.2.1",
"history": "^5.3.0",
"is-online": "^9.0.1",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "BSManager",
"version": "0.1.0",
"version": "0.0.8",
"description": "A foundation for scalable desktop apps",
"main": "./dist/main/main.js",
"author": {
-2
View File
@@ -49,10 +49,8 @@ ipcMain.on('bs-download.installation-folder', async (event, request: IpcRequest<
ipcMain.on('bs-download.set-installation-folder', (event, request: IpcRequest<string>) => {
const installerService = InstallationLocationService.getInstance();
installerService.setInstallationDirectory(request.args).then(res => {
console.log("déplacement terminer");
UtilsService.getInstance().ipcSend(request.responceChannel, {success: true, data: res});
}).catch((err: BsmException) => {
console.log(err);
UtilsService.getInstance().ipcSend(request.responceChannel, {success: false, error: err});
});
})
+1
View File
@@ -10,6 +10,7 @@ ipcMain.on('bs-launch.launch', (event, request: IpcRequest<LauchOption>) => {
const utilsService = UtilsService.getInstance();
launcherService.launch(request.args).then(res => {
console.log("BEAT SABER LANCER");
utilsService.ipcSend(request.responceChannel, {success: true, data: res});
}).catch((err: BsmException) => {
utilsService.ipcSend(request.responceChannel, {success: false, error: err});
-4
View File
@@ -35,20 +35,16 @@ ipcMain.on("bs-version.open-folder", async (event, req: IpcRequest<BSVersion>) =
ipcMain.on("bs-version.edit", async (event, req: IpcRequest<{version: BSVersion, name: string, color: string}>) => {
BSLocalVersionService.getInstance().editVersion(req.args.version, req.args.name, req.args.color).then(res => {
console.log(res);
UtilsService.getInstance().ipcSend(req.responceChannel, {success: !!res, data: res});
}).catch((error: BsmException) => {
UtilsService.getInstance().ipcSend(req.responceChannel, {success: false, error});
console.log(error);
});
});
ipcMain.on("bs-version.clone", async (event, req: IpcRequest<{version: BSVersion, name: string, color: string}>) => {
BSLocalVersionService.getInstance().cloneVersion(req.args.version, req.args.name, req.args.color).then(res => {
console.log(res);
UtilsService.getInstance().ipcSend(req.responceChannel, {success: !!res, data: res});
}).catch((error: BsmException) => {
UtilsService.getInstance().ipcSend(req.responceChannel, {success: false, error});
console.log(error);
});
});
+2
View File
@@ -5,3 +5,5 @@ import './bs-version-ipcs';
import './bs-uninstall-ipcs';
import './map-ipcs';
import './supporters-ipcs';
import './launcher-ipcs';
import './window-manager-ipcs';
+31
View File
@@ -0,0 +1,31 @@
import { ipcMain } from "electron";
import { AutoUpdaterService } from "../services/auto-updater.service";
import { IpcRequest } from "shared/models/ipc";
import { UtilsService } from "../services/utils.service";
ipcMain.on("download-update", async (event, request: IpcRequest<void>) => {
const updaterService = AutoUpdaterService.getInstance();
const utilsService = UtilsService.getInstance();
updaterService.downloadUpdate().then(res => utilsService.ipcSend(request.responceChannel, {success: res}))
.catch(() => utilsService.ipcSend(request.responceChannel, {success: false}));
});
ipcMain.on("check-update", async (event, request: IpcRequest<void>) => {
const updaterService = AutoUpdaterService.getInstance();
const utilsService = UtilsService.getInstance();
updaterService.isUpdateAvailable().then(updateAvailable => {
utilsService.ipcSend(request.responceChannel, {success: true, data: updateAvailable});
})
.catch(() => utilsService.ipcSend(request.responceChannel, {success: false}));
});
ipcMain.on("install-update", async (event, request: IpcRequest<void>) => {
const updaterService = AutoUpdaterService.getInstance();
updaterService.quitAndInstall();
});
+11 -7
View File
@@ -1,26 +1,29 @@
import { ipcMain, shell, dialog, app } from 'electron';
import { UtilsService } from '../services/utils.service';
import { IpcRequest } from 'shared/models/ipc';
import { getMainWindow } from '../main';
ipcMain.on('window.close', async () => {
getMainWindow()?.close();
const utils = UtilsService.getInstance();
utils.getMainWindow()?.close();
});
ipcMain.on('window.maximize', async () => {
getMainWindow()?.maximize();
const utils = UtilsService.getInstance();
utils.getMainWindow()?.maximize();
});
ipcMain.on('window.minimize', async () => {
getMainWindow()?.minimize();
const utils = UtilsService.getInstance();
utils.getMainWindow()?.minimize();
});
ipcMain.on('window.reset', async () => {
getMainWindow()?.restore();
const utils = UtilsService.getInstance();
utils.getMainWindow()?.restore();
});
ipcMain.on('new-window', async (event, request: IpcRequest<string>) => {
shell.openExternal(request.args);
shell.openExternal(request.args);
});
ipcMain.on('choose-folder', async (event, request: IpcRequest<void>) => {
@@ -30,7 +33,8 @@ ipcMain.on('choose-folder', async (event, request: IpcRequest<void>) => {
});
ipcMain.on("window.progression", async (event, request: IpcRequest<number>) => {
getMainWindow().setProgressBar(request.args / 100);
const utils = UtilsService.getInstance();
utils.getMainWindow().setProgressBar(request.args / 100);
});
ipcMain.on('save-file', async (event, request: IpcRequest<{filename?: string, filters?: Electron.FileFilter[]}>) => {
+12
View File
@@ -0,0 +1,12 @@
import { ipcMain } from "electron";
import { WindowManagerService } from "../services/window-manager.service";
import { IpcRequest } from "shared/models/ipc";
import { AppWindow } from "shared/models/window-manager/app-window.model";
ipcMain.on("open-window-then-close-all", async (event, request: IpcRequest<AppWindow>) => {
const windowManager = WindowManagerService.getInstance();
windowManager.openWindow(request.args).then(window => {
windowManager.closeAllWindows(request.args);
});
});
+20 -103
View File
@@ -9,19 +9,15 @@
* `./src/main.js` using webpack. This gives us some performance wins.
*/
import path from 'path';
import { app, BrowserWindow, shell } from 'electron';
import { autoUpdater } from 'electron-updater';
import { app } from 'electron';
import log from 'electron-log';
import { resolveHtmlPath } from './util';
import './ipcs';
import { UtilsService } from './services/utils.service';
import { WindowManagerService } from './services/window-manager.service';
export default class AppUpdater {
constructor() {
autoUpdater.logger = log;
//autoUpdater.checkForUpdatesAndNotify();
}
}
export const PRELOAD_PATH = app.isPackaged ? path.join(__dirname, 'preload.js') : path.join(__dirname, '../../.erb/dll/preload.js')
const isDebug = process.env.NODE_ENV === 'development' || process.env.DEBUG_PROD === 'true';
log.transports.file.level = 'info';
log.transports.file.resolvePath = (() => {
@@ -31,11 +27,8 @@ log.transports.file.resolvePath = (() => {
log.catchErrors();
let mainWindow: BrowserWindow = null;
export function getMainWindow(): BrowserWindow{
return mainWindow;
}
const utilsService = UtilsService.getInstance();
utilsService.setAssetsPath(app.isPackaged ? path.join(process.resourcesPath, 'assets') : path.join(__dirname, '../../assets'));
if (process.env.NODE_ENV === 'production') {
@@ -43,107 +36,31 @@ if (process.env.NODE_ENV === 'production') {
sourceMapSupport.install();
}
const isDebug = process.env.NODE_ENV === 'development' || process.env.DEBUG_PROD === 'true';
if (isDebug) {
require('electron-debug')();
}
const installExtensions = async () => {
const installer = require('electron-devtools-installer');
const forceDownload = !!process.env.UPGRADE_EXTENSIONS;
const extensions = ['REACT_DEVELOPER_TOOLS'];
const installer = require('electron-devtools-installer');
const forceDownload = !!process.env.UPGRADE_EXTENSIONS;
const extensions = ['REACT_DEVELOPER_TOOLS'];
return installer
.default(
extensions.map((name) => installer[name]),
forceDownload
)
.catch(console.log);
return installer.default(extensions.map((name) => installer[name]), forceDownload).catch(console.log);
};
const createWindow = async () => {
if (isDebug) {
await installExtensions();
}
const RESOURCES_PATH = app.isPackaged ? path.join(process.resourcesPath, 'assets') : path.join(__dirname, '../../assets');
UtilsService.getInstance().setAssetsPath(RESOURCES_PATH);
const getAssetPath = (...paths: string[]): string => {
return path.join(RESOURCES_PATH, ...paths);
};
mainWindow = new BrowserWindow({
show: false,
width: 1080,
height: 720,
minWidth: 900,
minHeight: 500,
frame: false,
titleBarOverlay: false,
icon: getAssetPath('favicon.ico'),
webPreferences: {
preload: app.isPackaged
? path.join(__dirname, 'preload.js')
: path.join(__dirname, '../../.erb/dll/preload.js'),
},
});
UtilsService.getInstance().setMainWindow(mainWindow);
mainWindow.loadURL(resolveHtmlPath('index.html'));
mainWindow.on('ready-to-show', () => {
if (!mainWindow) {
throw new Error('"mainWindow" is not defined');
}
if (process.env.START_MINIMIZED) {
mainWindow.minimize();
} else {
mainWindow.show();
}
});
mainWindow.on('closed', () => {
mainWindow = null;
});
mainWindow.removeMenu();
mainWindow.setMenu(null);
// Open urls in the user's browser
mainWindow.webContents.setWindowOpenHandler((edata) => {
shell.openExternal(edata.url);
return { action: 'deny' };
});
// Remove this if your app does not use auto updates
// eslint-disable-next-line
new AppUpdater();
if(isDebug){ await installExtensions(); }
WindowManagerService.getInstance().openWindow("launcher.html");
};
/**
* Add event listeners...
*/
app.on('window-all-closed', () => {
// Respect the OSX convention of having the application in memory even
// after all windows have been closed
if (process.platform !== 'darwin') {
app.quit();
}
// Respect the OSX convention of having the application in memory even
// after all windows have been closed
if (process.platform !== 'darwin') {
app.quit();
}
});
app
.whenReady()
.then(() => {
app.whenReady().then(() => {
createWindow();
app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) createWindow();
});
})
.catch(console.log);
}).catch(console.log);
+55
View File
@@ -0,0 +1,55 @@
import { autoUpdater } from 'electron-updater';
import log from 'electron-log';
import { UtilsService } from './utils.service';
export class AutoUpdaterService {
private static instance: AutoUpdaterService;
private readonly utilsService: UtilsService;
public static getInstance(): AutoUpdaterService{
if(!AutoUpdaterService.instance){ AutoUpdaterService.instance = new AutoUpdaterService(); }
return AutoUpdaterService.instance;
}
constructor(){
autoUpdater.logger = log;
autoUpdater.autoDownload = false;
this.utilsService = UtilsService.getInstance();
}
public isUpdateAvailable(): Promise<boolean>{
return new Promise(resolve => {
autoUpdater.checkForUpdates().then(info => {
const needUpdate = (() => {
if(!info || !info.updateInfo){ return false; }
if(autoUpdater.currentVersion.version === info.updateInfo.version){ return false; }
return true;
})();
resolve(needUpdate)}
).catch(() => resolve(false));
});
}
public downloadUpdate(): Promise<boolean>{
autoUpdater.removeAllListeners("download-progress");
autoUpdater.addListener("download-progress", info => {
this.utilsService.ipcSend("update-download-progress", {success: true, data: info.percent});
});
// const promise = new Promise<boolean>((resolve, reject) => {
// autoUpdater.addListener("update-downloaded", () => resolve(true));
// autoUpdater.addListener("error", () => reject(false))
// });
return autoUpdater.downloadUpdate().then(res => !!res && !!res.length);
}
public quitAndInstall(){
autoUpdater.quitAndInstall();
}
}
+23 -22
View File
@@ -7,7 +7,6 @@ import log from "electron-log";
import { InstallationLocationService } from "./installation-location.service";
import { ctrlc } from "ctrlc-windows";
import { BSLocalVersionService } from "./bs-local-version.service";
import { getMainWindow } from "../main";
import isOnline from 'is-online';
export class BSInstallerService{
@@ -25,7 +24,7 @@ export class BSInstallerService{
this.installLocationService = InstallationLocationService.getInstance();
this.localVersionService = BSLocalVersionService.getInstance();
getMainWindow().on("close", () => {
this.utils.getMainWindow().on("close", () => {
this.killDownloadProcess();
});
}
@@ -35,14 +34,16 @@ export class BSInstallerService{
return BSInstallerService.instance;
}
private getDepotDownloaderExePath(): string{
return path.join(this.utils.getAssetsScriptsPath(), 'depot-downloader', 'DepotDownloader.exe');
}
private getDepotDownloaderExePath(): string{
return path.join(this.utils.getAssetsScriptsPath(), 'depot-downloader', 'DepotDownloader.exe');
}
private sendDownloadEvent(event: DownloadEventType, data?: string|number, success = true): void{
if(typeof data === "string"){ data = data.replaceAll(/\[|\]/g, ""); }
this.utils.ipcSend(`bs-download.${event}`, { success, data });
}
private removeSpecialSchar(txt: string): string{ return txt.replaceAll(/\[|\]/g, ""); }
private sendDownloadEvent(event: DownloadEventType, data?: string|number, success = true): void{
if(typeof data === "string"){ data = this.removeSpecialSchar(data); }
this.utils.ipcSend(`bs-download.${event}`, { success, data });
}
public sendInputProcess(input: string){
if(this.downloadProcess.stdin.writable){
@@ -54,16 +55,16 @@ export class BSInstallerService{
return new Promise(resolve => {
if(this.downloadProcess?.killed && !this.downloadProcess?.pid){ return resolve(false); }
this.downloadProcess.on('close', () => resolve(true));
this.downloadProcess.once('exit', () => resolve(true));
ctrlc(this.downloadProcess.pid);
if(!this.downloadProcess.kill()){ return resolve(false); }
setTimeout(() => resolve(false), 2000);
setTimeout(() => resolve(false), 3000);
});
}
public async downloadBsVersion(downloadInfos: DownloadInfo): Promise<DownloadEvent>{
if(this.downloadProcess && !this.downloadProcess?.killed){ return {type: "[AlreadyDownloading]"}; }
if(this.downloadProcess && this.downloadProcess.connected){ throw "AlreadyDownloading"; }
const {bsVersion} = downloadInfos;
if(!bsVersion){ return {type: "[Error]"}; }
if(!(await isOnline({timeout: 1500}))){ throw "no-internet"; }
@@ -86,9 +87,10 @@ export class BSInstallerService{
this.downloadProcess.stdout.on('data', data => {
const matched = (data.toString() as string).match(/(?:\[(.*?)\])\|(?:\[(.*?)\]\|)?(.*?)(?=$|\[)/gm) ?? [];
console.log(data.toString());
matched.forEach(match => {
const out = match.split("|");
if(out[0] !== "[Progress]" && out[0] !== "[Validated]"){ log.info(data.toString()); }
if(out[0] === "[Password]" as DownloadEventType && downloadInfos.password){
this.sendInputProcess(downloadInfos.password);
@@ -114,8 +116,7 @@ export class BSInstallerService{
this.sendDownloadEvent("[Warning]", out[1]);
}
else if(out[0] === "[Error]" as DownloadEventType){
reject(out[1]);
this.sendDownloadEvent("[Error]", out[1], false);
reject(this.removeSpecialSchar(out[1]));
this.killDownloadProcess();
log.error("Download Event, Error", data.toString());
}
@@ -125,18 +126,18 @@ export class BSInstallerService{
this.downloadProcess.stdout.on('error', (err) => {
log.error("BS-DOWNLOAD ERROR", err.toString());
this.downloadProcess.kill();
reject(err);
this.killDownloadProcess();
reject();
});
this.downloadProcess.stderr.on('data', (err) => {
log.error("BS-DOWNLOAD ERROR", err.toString());
this.downloadProcess.kill();
reject(err);
this.killDownloadProcess();
reject();
});
this.downloadProcess.stderr.on('error', (err) => {
log.error("BS-DOWNLOAD ERROR", err.toString());
this.downloadProcess.kill();
reject(err);
this.killDownloadProcess();
reject();
});
this.downloadProcess.on('close', () => reject());
+2
View File
@@ -38,6 +38,8 @@ export class BSLauncherService{
const cwd = await this.localVersionService.getVersionPath(launchOptions.version);
const exePath = path.join(cwd, BS_EXECUTABLE);
console.log(exePath);
if(!this.utilsService.pathExist(exePath)){ return "EXE_NOT_FINDED"; }
const launchMods = [launchOptions.oculus && "-vrmode oculus", launchOptions.desktop && "fpfc", launchOptions.debug && "--verbose"];
-2
View File
@@ -30,8 +30,6 @@ export class MapService{
const versionPath = await this.localVersionService.getVersionPath(version);
const mapsPath = this.getMapsPath(versionPath);
console.log(outputZip);
const output = createWriteStream(outputZip);
const archive = archiver("zip", {zlib: {level: 9}});
+4 -3
View File
@@ -23,12 +23,13 @@ export class UtilsService{
}
public setAssetsPath(path: string): void{ this.assetsPath = path; }
public getAssetsPath(): string{ return this.assetsPath; }
public getAssetsPath(pathToFile: string): string{ return path.join(this.assetsPath, pathToFile); }
public getAssetsScriptsPath(): string { return path.join(this.getAssetsPath(), 'scripts'); }
public getAssestsJsonsPath(): string { return path.join(this.getAssetsPath(), 'jsons'); }
public getAssetsScriptsPath(): string { return this.getAssetsPath("scripts") }
public getAssestsJsonsPath(): string { return this.getAssetsPath("jsons"); }
public setMainWindow(win: BrowserWindow){ this.mainWindow = win; }
public getMainWindow(){ return this.mainWindow; }
public pathExist(path: string): boolean{ return existsSync(path); }
@@ -0,0 +1,68 @@
import { app, BrowserWindow, BrowserWindowConstructorOptions } from "electron";
import { resolveHtmlPath } from "../util";
import { UtilsService } from "./utils.service";
import { AppWindow } from "shared/models/window-manager/app-window.model";
import { PRELOAD_PATH } from "../main";
export class WindowManagerService{
private static instance: WindowManagerService;
private readonly utilsService: UtilsService = UtilsService.getInstance();
private readonly appWindowsOptions: Record<AppWindow, BrowserWindowConstructorOptions> = {
"launcher.html": {width: 380, height: 500, minWidth: 380, minHeight: 500, resizable: false},
"index.html": {width: 1080, height: 720, minWidth: 900, minHeight: 500}
}
private readonly baseWindowOption: BrowserWindowConstructorOptions = {
icon: this.utilsService.getAssetsPath("favicon.ico"),
show: false,
frame: false,
titleBarOverlay: false,
webPreferences: { preload: PRELOAD_PATH }
}
private readonly windows: Map<AppWindow, BrowserWindow> = new Map<AppWindow, BrowserWindow>();
public static getInstance(): WindowManagerService{
if(!WindowManagerService.instance){ WindowManagerService.instance = new WindowManagerService(); }
return WindowManagerService.instance;
}
private constructor(){}
public openWindow(windowType: AppWindow): Promise<BrowserWindow>{
const window = new BrowserWindow({...this.appWindowsOptions[windowType], ...this.baseWindowOption});
const promise = window.loadURL(resolveHtmlPath(windowType));
window.removeMenu();
window.setMenu(null);
window.once("ready-to-show", () => {
if (!window) { throw new Error('"window" is not defined'); }
return window.show();
});
window.once("closed", () => {
this.windows.delete(windowType);
if(!this.windows.size){ app.quit(); }
});
this.windows.set(windowType, window);
this.utilsService.setMainWindow(window);
return promise.then(() => window);
}
public closeWindow(window: AppWindow){
this.windows.get(window).close();
}
public closeAllWindows(except?: AppWindow){
this.windows.forEach((window, key) => {
if(key === except){ return; }
window.close();
})
}
}
+53
View File
@@ -0,0 +1,53 @@
import { motion } from "framer-motion";
import { useEffect, useRef, useState } from "react";
import { BsManagerIcon } from "./components/nav-bar/bsmanager-icon.component";
import { BsmProgressBar } from "./components/progress-bar/bsm-progress-bar.component";
import TitleBar from "./components/title-bar/title-bar.component";
import { useTranslation } from "./hooks/use-translation.hook";
import { AutoUpdaterService } from "./services/auto-updater.service";
import { ThemeService } from "./services/theme.service";
import { WindowManagerService } from "./services/window-manager.service";
export default function Launcher() {
const themeService = ThemeService.getInstance();
const updaterService = AutoUpdaterService.getInstance();
const windowService = WindowManagerService.getInstance();
const constraintsRef = useRef(null);
const [text, setText] = useState("auto-update.checking");
const t = useTranslation();
useEffect(() => {
const sub = themeService.theme$.subscribe(() => {
if(themeService.isDark || (themeService.isOS && window.matchMedia('(prefers-color-scheme: dark)').matches)){ document.documentElement.classList.add('dark'); }
else { document.documentElement.classList.remove('dark'); }
});
updaterService.isUpdateAvailable().then(available => {
if(!available){ return windowService.openThenCloseAll("index.html"); }
setText("auto-update.downloading");
updaterService.downloadUpdate().then(installed => installed && updaterService.quitAndInstall());
});
return () => sub.unsubscribe();
}, []);
return (
<div className="w-full h-full">
<TitleBar template="update"/>
<div className="relative flex flex-col items-center justify-center pt-10">
<motion.div ref={constraintsRef}>
<motion.div drag dragConstraints={constraintsRef} animate={{rotate: [0, 10, 0]}} transition={{ duration: .6, repeat: Infinity, repeatDelay: 1.6 }}>
<BsManagerIcon className={"w-52 cursor-pointer"}/>
</motion.div>
</motion.div>
<span className="relative text-lg mt-16 mb-24 uppercase italic text-main-color-1 dark:text-gray-200">{t(text)}</span>
<BsmProgressBar/>
</div>
</div>
)
}
@@ -10,9 +10,6 @@ export function AvailableVersionsSlide(props: {year: string}) {
const versionsService = BSVersionManagerService.getInstance();
console.log("*** AVAILABLE VERISON");
console.log(availableVersions);
useEffect(() => {
versionsService.availableVersions$.pipe(filter(versions => !!versions?.length), take(1)).subscribe(() => {
setAvailableVersions(versionsService.getAvaibleVersionsOfYear(props.year));
@@ -17,7 +17,6 @@ export function AvailableVersionsSlider() {
useEffect(() => {
versionManagerService.availableVersions$.pipe(filter(versions => !!versions?.length), take(1)).subscribe(() => {
console.log("ouiiii");
setAvailableYears(versionManagerService.getAvailableYears());
});
}, [])
@@ -21,7 +21,7 @@ export function EditVersionModal({resolver, clone = false}: {resolver: (x: Modal
const rename = () => {
if(!name){ return; }
resolver({exitCode: ModalExitCode.COMPLETED, data: {name, color}})
resolver({exitCode: ModalExitCode.COMPLETED, data: {name: name.trim(), color}})
}
const resetColor = () => {
@@ -1,24 +1,32 @@
import { memo } from "react"
import { useThemeColor } from "renderer/hooks/use-theme-color.hook";
import { motion } from "framer-motion";
export const BsManagerIcon = memo(({className}: {className?: string}) => {
const {firstColor, secondColor} = useThemeColor();
export const BsManagerIcon = memo(({className, color1, color2}: {className: string, color1: string, color2: string}) => {
return (
<svg className={className} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000">
<g fill={color1}>
<path d="M626.75,485.91l20.82,351.94a35.21,35.21,0,0,1-15.49,31.36L487.37,965.35l-.06,0A35.56,35.56,0,0,1,476,970.12a34.85,34.85,0,0,1-23.51-2.87L136.58,809.9a115.45,115.45,0,0,1-63.75-96.49L52,361.46a35.26,35.26,0,0,1,15.23-31.21l145.05-96.36a35.72,35.72,0,0,1,11.27-4.7,34.87,34.87,0,0,1,23.51,2.87L563,389.42a115.41,115.41,0,0,1,63.75,96.49Z"/>
<path filter="brightness(30%)" d="M613.78,486.67l20.82,352a22.34,22.34,0,0,1-32.26,21.31L286.4,702.57A102.43,102.43,0,0,1,229.83,617L209,265a22.35,22.35,0,0,1,32.26-21.32L557.2,401.05A102.42,102.42,0,0,1,613.78,486.67Z"/>
</g>
<g fill="#fff">
<path d="M718.29,776.48,700,804.18c-40.63,39.5-87.06,67.25-133.81,90.75-87.32,43.9-203.67,77.19-249,90.34a48,48,0,0,1-26.17.16c-64-17.72-188.62-72-236.28-125.49a4.23,4.23,0,0,1,5.3-6.45c35.64,20.87,111.22,57.64,156.37,74.22,49.18,18.06,81.29,8.74,92.28-3.26a4.77,4.77,0,0,1,7.24.21c19.51,24,107.26,4.6,166.64-13C546.91,892.66,668.42,835.1,718.29,776.48Z"/>
<path d="M522.09,933.81,374.64,989.49a3.92,3.92,0,0,0,1.44,7.58l54.62-.77a35.63,35.63,0,0,0,19-5.79l76-49.55A4,4,0,0,0,522.09,933.81Z"/>
<path d="M218.92,195.56c-21.14.07-33.55,35.86-33.16,89.08.2,28,2.58,92.74,4.79,147.73.23,5.71-8.18,6.48-9,.81L143.13,162.47a4.38,4.38,0,0,1,7.12-4,63.63,63.63,0,0,0,21.93,11.85,4.61,4.61,0,0,0,5.9-3.72c4.2-27.7,16.63-58.74,37.35-88.74a4.36,4.36,0,0,1,7.56.69c10.86,23.87,49,103.8,93.34,152.79a4.65,4.65,0,0,1-5.62,7.22C274.14,219.18,227.7,195.54,218.92,195.56Z"/>
<path d="M203.45,580.36a4.51,4.51,0,0,1-4.46-3.92L185.17,469.15A4.5,4.5,0,0,1,194.1,468l13.82,107.29a4.5,4.5,0,0,1-3.89,5A3.86,3.86,0,0,1,203.45,580.36Z"/>
<path d="M577.08,54.58c-46.79,15.85-115.45,40.56-158.73,62.79a35.5,35.5,0,0,0-18.57,24.53c-3.95,19.49-11,56.09-19,107.26-.7,4.48-7.36,3.78-7.11-.75L384.33,53.68a3.78,3.78,0,0,1,7.46-.66l3.49,14.85a2.57,2.57,0,0,0,4.69.77c6.18-10,22.37-32.79,57.32-65a4.13,4.13,0,0,1,6.56,4.72L431.31,81.25s78.78-19.37,144-33.09C579.42,47.29,581,53.24,577.08,54.58Z"/>
</g>
<g fill={color2}>
<path filter="brightness(60%) saturate(120%)" d="M947.07,410.35,889.32,758.14a35.18,35.18,0,0,1-22.06,27.15L704.83,846.94l-.06,0a35.52,35.52,0,0,1-12.06,2.11,34.83,34.83,0,0,1-22.29-8L397.25,617.55a115.43,115.43,0,0,1-40.76-108.22l57.75-347.8A35.25,35.25,0,0,1,436,134.47L598.83,72.68a35.51,35.51,0,0,1,12-2.08,34.83,34.83,0,0,1,22.29,8L906.31,302.12a115.38,115.38,0,0,1,40.76,108.23Z"/>
<path d="M934.25,408.22,876.5,756a22.34,22.34,0,0,1-36.18,13.63L567.15,546.13a102.42,102.42,0,0,1-36.17-96L588.73,102.3a22.34,22.34,0,0,1,36.18-13.63L898.08,312.18A102.42,102.42,0,0,1,934.25,408.22Z"/>
</g>
<ellipse fill="#fff" cx="732.61" cy="429.16" rx="62.83" ry="110.73" transform="translate(-87.86 210.7) rotate(-15.45)"/>
</svg>
<motion.div className="cursor-pointer" whileTap={{rotate: -10}}>
<svg className={className} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000">
<g fill={firstColor}>
<path d="M626.75,485.91l20.82,351.94a35.21,35.21,0,0,1-15.49,31.36L487.37,965.35l-.06,0A35.56,35.56,0,0,1,476,970.12a34.85,34.85,0,0,1-23.51-2.87L136.58,809.9a115.45,115.45,0,0,1-63.75-96.49L52,361.46a35.26,35.26,0,0,1,15.23-31.21l145.05-96.36a35.72,35.72,0,0,1,11.27-4.7,34.87,34.87,0,0,1,23.51,2.87L563,389.42a115.41,115.41,0,0,1,63.75,96.49Z"/>
<path filter="brightness(30%)" d="M613.78,486.67l20.82,352a22.34,22.34,0,0,1-32.26,21.31L286.4,702.57A102.43,102.43,0,0,1,229.83,617L209,265a22.35,22.35,0,0,1,32.26-21.32L557.2,401.05A102.42,102.42,0,0,1,613.78,486.67Z"/>
</g>
<g fill="#fff">
<path d="M718.29,776.48,700,804.18c-40.63,39.5-87.06,67.25-133.81,90.75-87.32,43.9-203.67,77.19-249,90.34a48,48,0,0,1-26.17.16c-64-17.72-188.62-72-236.28-125.49a4.23,4.23,0,0,1,5.3-6.45c35.64,20.87,111.22,57.64,156.37,74.22,49.18,18.06,81.29,8.74,92.28-3.26a4.77,4.77,0,0,1,7.24.21c19.51,24,107.26,4.6,166.64-13C546.91,892.66,668.42,835.1,718.29,776.48Z"/>
<path d="M522.09,933.81,374.64,989.49a3.92,3.92,0,0,0,1.44,7.58l54.62-.77a35.63,35.63,0,0,0,19-5.79l76-49.55A4,4,0,0,0,522.09,933.81Z"/>
<path d="M218.92,195.56c-21.14.07-33.55,35.86-33.16,89.08.2,28,2.58,92.74,4.79,147.73.23,5.71-8.18,6.48-9,.81L143.13,162.47a4.38,4.38,0,0,1,7.12-4,63.63,63.63,0,0,0,21.93,11.85,4.61,4.61,0,0,0,5.9-3.72c4.2-27.7,16.63-58.74,37.35-88.74a4.36,4.36,0,0,1,7.56.69c10.86,23.87,49,103.8,93.34,152.79a4.65,4.65,0,0,1-5.62,7.22C274.14,219.18,227.7,195.54,218.92,195.56Z"/>
<path d="M203.45,580.36a4.51,4.51,0,0,1-4.46-3.92L185.17,469.15A4.5,4.5,0,0,1,194.1,468l13.82,107.29a4.5,4.5,0,0,1-3.89,5A3.86,3.86,0,0,1,203.45,580.36Z"/>
<path d="M577.08,54.58c-46.79,15.85-115.45,40.56-158.73,62.79a35.5,35.5,0,0,0-18.57,24.53c-3.95,19.49-11,56.09-19,107.26-.7,4.48-7.36,3.78-7.11-.75L384.33,53.68a3.78,3.78,0,0,1,7.46-.66l3.49,14.85a2.57,2.57,0,0,0,4.69.77c6.18-10,22.37-32.79,57.32-65a4.13,4.13,0,0,1,6.56,4.72L431.31,81.25s78.78-19.37,144-33.09C579.42,47.29,581,53.24,577.08,54.58Z"/>
</g>
<g fill={secondColor}>
<path filter="brightness(60%) saturate(120%)" d="M947.07,410.35,889.32,758.14a35.18,35.18,0,0,1-22.06,27.15L704.83,846.94l-.06,0a35.52,35.52,0,0,1-12.06,2.11,34.83,34.83,0,0,1-22.29-8L397.25,617.55a115.43,115.43,0,0,1-40.76-108.22l57.75-347.8A35.25,35.25,0,0,1,436,134.47L598.83,72.68a35.51,35.51,0,0,1,12-2.08,34.83,34.83,0,0,1,22.29,8L906.31,302.12a115.38,115.38,0,0,1,40.76,108.23Z"/>
<path d="M934.25,408.22,876.5,756a22.34,22.34,0,0,1-36.18,13.63L567.15,546.13a102.42,102.42,0,0,1-36.17-96L588.73,102.3a22.34,22.34,0,0,1,36.18-13.63L898.08,312.18A102.42,102.42,0,0,1,934.25,408.22Z"/>
</g>
<ellipse fill="#fff" cx="732.61" cy="429.16" rx="62.83" ry="110.73" transform="translate(-87.86 210.7) rotate(-15.45)"/>
</svg>
</motion.div>
)
})
@@ -4,7 +4,6 @@ import { BSVersionManagerService } from '../../services/bs-version-manager.servi
import { Link } from 'react-router-dom';
import { BsmIcon } from '../svgs/bsm-icon.component';
import { useObservable } from 'renderer/hooks/use-observable.hook';
import { useThemeColor } from 'renderer/hooks/use-theme-color.hook';
import { BsManagerIcon } from './bsmanager-icon.component';
export function NavBar() {
@@ -12,12 +11,11 @@ export function NavBar() {
const bsVersionServoce = BSVersionManagerService.getInstance();
const installedVersions = useObservable(bsVersionServoce.installedVersions$);
const {firstColor, secondColor} = useThemeColor();
return (
<div id='nav-bar' className='z-10 flex flex-col h-full max-h-full items-center p-1 bg-light-main-color-1 dark:bg-main-color-1'>
<div className='w-full flex items-start content-start justify-center relative mb-3'>
<BsManagerIcon className='relative aspect-square w-16 h-16' color1={firstColor} color2={secondColor}/>
<BsManagerIcon className='relative aspect-square w-16 h-16'/>
</div>
<div id='versions' className='w-fit max-w-[120px] relative left-[2px] grow overflow-y-hidden scrollbar-track-transparent scrollbar-thin scrollbar-thumb-neutral-900 hover:overflow-y-scroll'>
{installedVersions && installedVersions.map((version) => <BsVersionItem key={JSON.stringify(version)} version={version}/>)}
@@ -2,7 +2,7 @@ import { useState } from 'react';
import { IpcService } from 'renderer/services/ipc.service';
import './title-bar.component.css'
export default function TitleBar() {
export default function TitleBar({template = "main"} : {template?: "update"|"main"}) {
const ipcService = IpcService.getInstance();
@@ -31,23 +31,23 @@ export default function TitleBar() {
}
return (
<header id="titlebar" className="min-h-[22px] bg-light-main-color-1 dark:bg-main-color-1 w-screen h-10 flex content-center items-center justify-start z-10">
<div id="drag-region" className='grow basis-0'>
<div id="window-title" className='pl-1'>
<span className='text-gray-800 dark:text-gray-100 font-bold text-xs italic'>BSManager</span>
</div>
</div>
<div id="window-controls" className=''>
<header id="titlebar" className="min-h-[22px] bg-light-main-color-1 dark:bg-main-color-1 w-screen h-[22px] flex content-center items-center justify-start z-10">
<div id="drag-region" className='grow basis-0 h-full'>
{template !== "update" && (<div id="window-title" className='pl-1'>
<span className='text-gray-800 dark:text-gray-100 font-bold text-xs italic'>BSManager</span>
</div>)}
</div>
{template !== "update" && (<div id="window-controls">
<div onClick={minimizeWindow} className="button button text-gray-800 dark:text-gray-200 hover:bg-gray-300 dark:hover:bg-[#4F545C] cursor-pointer" id="min-button" >
<svg aria-hidden="false" width="12" height="12" viewBox="0 0 12 12"><rect fill="currentColor" width="10" height="1" x="1" y="6"> </rect></svg>
<svg aria-hidden="false" width="12" height="12" viewBox="0 0 12 12"><rect fill="currentColor" width="10" height="1" x="1" y="6"> </rect></svg>
</div>
<div onClick={toogleMaximize} className="button text-gray-800 dark:text-gray-200 hover:bg-gray-300 dark:hover:bg-[#4F545C] cursor-pointer" id="max-button">
<svg aria-hidden="false" width="12" height="12" viewBox="0 0 12 12"><rect width="9" height="9" x="1.5" y="1.5" fill="none" stroke="currentColor"> </rect></svg>
<svg aria-hidden="false" width="12" height="12" viewBox="0 0 12 12"><rect width="9" height="9" x="1.5" y="1.5" fill="none" stroke="currentColor"> </rect></svg>
</div>
<div onClick={closeWindow} className="button text-gray-800 dark:text-gray-200 cursor-pointer" id="close-button" draggable="false">
<svg aria-hidden="false" width="12" height="12" viewBox="0 0 12 12"><polygon fill="currentColor" fillRule="evenodd" points="11 1.576 6.583 6 11 10.424 10.424 11 6 6.583 1.576 11 1 10.424 5.417 6 1 1.576 1.576 1 6 5.417 10.424 1"> </polygon></svg>
<svg aria-hidden="false" width="12" height="12" viewBox="0 0 12 12"><polygon fill="currentColor" fillRule="evenodd" points="11 1.576 6.583 6 11 10.424 10.424 11 6 6.583 1.576 11 1 10.424 5.417 6 1 1.576 1.576 1 6 5.417 10.424 1"> </polygon></svg>
</div>
</div>
</div>)}
</header>
)
}
+14 -7
View File
@@ -1,14 +1,21 @@
//@ts-ignore
import { createRoot } from 'react-dom/client';
import { HashRouter } from 'react-router-dom';
import App from './App';
import Launcher from './Launcher';
import 'tailwindcss/tailwind.css';
import './index.css'
const container = document.getElementById('root')!;
const root = createRoot(container);
const launcherContainer = document.getElementById('launcher');
root.render(
<HashRouter>
<App />
</HashRouter>
);
if(!!launcherContainer){
createRoot(launcherContainer).render(<Launcher/>)
}
else{
const root = document.getElementById('root');
createRoot(root).render(
<HashRouter>
<App />
</HashRouter>
);
}
+15
View File
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://use.typekit.net/okr8ven.css">
<meta charset="utf-8" />
<meta
http-equiv="Content-Security-Policy"
content="script-src 'self' 'unsafe-inline'"
/>
</head>
<body>
<div id="launcher"></div>
</body>
</html>
@@ -78,7 +78,6 @@ export function VersionViewer() {
const newVersionPage = bsVersionManagerService.getInstalledVersions()[0];
navigateToVersion(newVersionPage);
})
.catch((e) => {console.log("*** ", e)})
}
}
@@ -0,0 +1,49 @@
import { Observable } from "rxjs";
import { map } from "rxjs/operators";
import { IpcService } from "./ipc.service";
import { ProgressBarService } from "./progress-bar.service";
export class AutoUpdaterService{
private static instance: AutoUpdaterService;
private progressService: ProgressBarService;
private ipcService: IpcService;
private downloadProgress$: Observable<number>;
public static getInstance(): AutoUpdaterService{
if(!AutoUpdaterService.instance){ AutoUpdaterService.instance = new AutoUpdaterService(); }
return AutoUpdaterService.instance;
}
private constructor(){
this.progressService = ProgressBarService.getInstance();
this.ipcService = IpcService.getInstance();
this.downloadProgress$ = this.ipcService.watch<number>("update-download-progress").pipe(map(res => res.success ? res.data : 0));
}
public isUpdateAvailable(): Promise<boolean>{
return this.ipcService.send<boolean>("check-update").then(res => {
if(!res.success){ return false; }
return res.data;
})
}
public downloadUpdate(): Promise<boolean>{
const promise = this.ipcService.send<boolean>("download-update").then(res => {
return res.success;
});
this.progressService.show(this.downloadProgress$, true);
return promise;
}
public quitAndInstall(){
this.ipcService.sendLazy("install-update");
}
}
@@ -113,8 +113,8 @@ export class BsDownloaderService{
this.progressBarService.hide(true);
this.resetDownload();
if(res.success){ this.notificationService.notifySuccess({title: `notifications.bs-download.success.titles.${isVerification ? "verification-finished" : "download-success"}`, duration: 3000}); }
else if(res.data){ this.notificationService.notifyError({title: `notifications.bs-download.errors.titles.${res.data}`, duration: 3000}); }
if(res.success && isFirstCall){ this.notificationService.notifySuccess({title: `notifications.bs-download.success.titles.${isVerification ? "verification-finished" : "download-success"}`, duration: 3000}); }
else if(res.data && isFirstCall){ console.log("aaaa"); this.notificationService.notifyError({title: `notifications.types.error`, desc: `notifications.bs-download.errors.msg.${res.data}`, duration: 3000}); }
return res;
}
+1
View File
@@ -53,6 +53,7 @@ export class I18nService {
public translate(translationKey: string, args?: Record<string, string>): string{
let translated = this.cache.get(translationKey);
if(!translated){
console.log(translationKey);
translated = getProperty(this.dictionary, translationKey);
translated ? this.cache.set(translated, translationKey) : translated = translationKey;
}
+1 -1
View File
@@ -29,7 +29,7 @@ export class IpcService {
return promise;
}
public sendLazy(channel: string, request?: IpcRequest<any>): void{
public sendLazy<T = any>(channel: string, request?: IpcRequest<T>): void{
window.electron.ipcRenderer.sendMessage(channel, request);
}
@@ -0,0 +1,25 @@
import { AppWindow } from "shared/models/window-manager/app-window.model";
import { IpcService } from "./ipc.service";
export class WindowManagerService{
private static instance: WindowManagerService;
private readonly ipcService: IpcService;
public static getInstance(): WindowManagerService{
if(!WindowManagerService.instance){ WindowManagerService.instance = new WindowManagerService(); }
return WindowManagerService.instance;
}
private constructor(){
this.ipcService = IpcService.getInstance();
}
public openThenCloseAll(window: AppWindow){
this.ipcService.sendLazy<AppWindow>("open-window-then-close-all", {args: window});
}
}
@@ -0,0 +1 @@
export type AppWindow = "index.html" | "launcher.html";