diff --git a/entry.js b/entry.js index fa992b6..255db22 100644 --- a/entry.js +++ b/entry.js @@ -98,9 +98,7 @@ app.whenReady().then(() => { mainWindow.webContents.send('updateVP', { 'oldvp': args.oldvp }); }); - ipcMain.on('rpcstate', (event, args) => { - mainWindow.webContents.send('rpcstate', {}); - }); + ipcMain.on('rpc-toggle', () => mainWindow.webContents.send('rpc-toggle')); }); // Quit when all windows are closed, except on macOS. There, it's common diff --git a/public/locales/de.json b/public/locales/de.json index 3f6f4ca..9008b4d 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -13,7 +13,7 @@ "GameDownloaded": "Spiel würde erfolgreich heruntergeladen", "ApplyPatch": "Patch wird angewendet", "PatchRequired": "Patch nicht verfügbar", - "PatchRequiredHint": "Diese Spielversion hat noch kein anti-cheat patch, Bitte warten sie ein paar Tage bevor sie es erneut versuchen.", + "PatchRequiredHint": "Diese Spielversion hat noch kein anti-cheat patch, Bitte warten sie ein paar Tage bevor sie es erneut versuchen", "TestPatch": "Test Patch anwenden", - "TestPatchHint": "Diese Spielversion hat ein anti-cheat patch aber es befindet sich noch in der Testphase. Sie können noch ein paar Tage warten bis es Stabil ist oder auf eigenen Risiko den Testpatch anwenden." + "TestPatchHint": "Diese Spielversion hat ein anti-cheat patch aber es befindet sich noch in der Testphase. Sie können noch ein paar Tage warten bis es Stabil ist oder auf eigenen Risiko den Testpatch anwenden" } \ No newline at end of file diff --git a/public/locales/en-us.json b/public/locales/en-us.json index ef0cacf..32d568b 100644 --- a/public/locales/en-us.json +++ b/public/locales/en-us.json @@ -13,7 +13,7 @@ "GameDownloaded": "Game was successfully installed", "ApplyPatch": "Applying patch...", "PatchRequired": "Patch required", - "PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again.", + "PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again", "TestPatch": "Apply test patch", - "TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk." + "TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk" } \ No newline at end of file diff --git a/public/locales/en.json b/public/locales/en.json index cad7c8f..1fc64fc 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -13,7 +13,7 @@ "GameDownloaded": "Game was successfully installed", "ApplyPatch": "Applying patch...", "PatchRequired": "Patch required", - "PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again.", + "PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again", "TestPatch": "Apply test patch", - "TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk." + "TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk" } \ No newline at end of file diff --git a/public/locales/es.json b/public/locales/es.json index cad7c8f..1fc64fc 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -13,7 +13,7 @@ "GameDownloaded": "Game was successfully installed", "ApplyPatch": "Applying patch...", "PatchRequired": "Patch required", - "PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again.", + "PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again", "TestPatch": "Apply test patch", - "TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk." + "TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk" } \ No newline at end of file diff --git a/public/locales/fr.json b/public/locales/fr.json index cad7c8f..1fc64fc 100644 --- a/public/locales/fr.json +++ b/public/locales/fr.json @@ -13,7 +13,7 @@ "GameDownloaded": "Game was successfully installed", "ApplyPatch": "Applying patch...", "PatchRequired": "Patch required", - "PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again.", + "PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again", "TestPatch": "Apply test patch", - "TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk." + "TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk" } \ No newline at end of file diff --git a/public/locales/id.json b/public/locales/id.json index cad7c8f..1fc64fc 100644 --- a/public/locales/id.json +++ b/public/locales/id.json @@ -13,7 +13,7 @@ "GameDownloaded": "Game was successfully installed", "ApplyPatch": "Applying patch...", "PatchRequired": "Patch required", - "PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again.", + "PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again", "TestPatch": "Apply test patch", - "TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk." + "TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk" } \ No newline at end of file diff --git a/public/locales/ja.json b/public/locales/ja.json index a2a2d76..85f6215 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -13,7 +13,7 @@ "GameDownloaded": "ゲームのインストールに成功しました", "ApplyPatch": "パッチの適用...", "PatchRequired": "要パッチ", - "PatchRequiredHint": "このゲームバージョンにはアンチチートパッチがありません。数日待ってから再度お試しください。", + "PatchRequiredHint": "このゲームバージョンにはアンチチートパッチがありません。数日待ってから再度お試しください", "TestPatch": "テストパッチの適用", - "TestPatchHint": "このゲームバージョンにはアンチチートパッチがありますが、テスト段階にあります。安定するまで数日お待ちいただくか、ご自身の責任で適用してください。" + "TestPatchHint": "このゲームバージョンにはアンチチートパッチがありますが、テスト段階にあります。安定するまで数日お待ちいただくか、ご自身の責任で適用してください" } \ No newline at end of file diff --git a/public/locales/ko.json b/public/locales/ko.json index cad7c8f..1fc64fc 100644 --- a/public/locales/ko.json +++ b/public/locales/ko.json @@ -13,7 +13,7 @@ "GameDownloaded": "Game was successfully installed", "ApplyPatch": "Applying patch...", "PatchRequired": "Patch required", - "PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again.", + "PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again", "TestPatch": "Apply test patch", - "TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk." + "TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk" } \ No newline at end of file diff --git a/public/locales/pt.json b/public/locales/pt.json index cad7c8f..1fc64fc 100644 --- a/public/locales/pt.json +++ b/public/locales/pt.json @@ -13,7 +13,7 @@ "GameDownloaded": "Game was successfully installed", "ApplyPatch": "Applying patch...", "PatchRequired": "Patch required", - "PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again.", + "PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again", "TestPatch": "Apply test patch", - "TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk." + "TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk" } \ No newline at end of file diff --git a/public/locales/ru.json b/public/locales/ru.json index cad7c8f..cf04afb 100644 --- a/public/locales/ru.json +++ b/public/locales/ru.json @@ -1,19 +1,19 @@ { - "Install": "Install", - "Update": "Update", - "Launch": "Launch", - "Runners": "Runners", - "Langs": "Languages", - "Voice": "Voice Pack", - "SettingsTitle": "Settings", - "GeneralSettings": "General", - "WineVersion": "Wine version", - "Downloading": "Downloading", - "Unpack": "Unpacking", - "GameDownloaded": "Game was successfully installed", - "ApplyPatch": "Applying patch...", - "PatchRequired": "Patch required", - "PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again.", - "TestPatch": "Apply test patch", - "TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk." + "Install": "Установить", + "Update": "Обновить", + "Launch": "Запустить", + "Runners": "Версии Wine", + "Langs": "Языки", + "Voice": "Озвучка", + "SettingsTitle": "Настройки", + "GeneralSettings": "Общее", + "WineVersion": "Версии Wine", + "Downloading": "Загрузка", + "Unpack": "Распаковка", + "GameDownloaded": "Игра была успешно установлена", + "ApplyPatch": "Применение патча...", + "PatchRequired": "Необходим патч", + "PatchRequiredHint": "Эта версия игры не имеет патча античита. Пожалуйста, подождите несколько дней и попробуйте снова", + "TestPatch": "Применить тестовый патч", + "TestPatchHint": "Эта версия игры имеет лишь тестовый патч античита. Вы можете подождать пару дней до того, как он станет стабильным, либо применить его на свой страх и риск" } \ No newline at end of file diff --git a/public/locales/th.json b/public/locales/th.json index cad7c8f..1fc64fc 100644 --- a/public/locales/th.json +++ b/public/locales/th.json @@ -13,7 +13,7 @@ "GameDownloaded": "Game was successfully installed", "ApplyPatch": "Applying patch...", "PatchRequired": "Patch required", - "PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again.", + "PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again", "TestPatch": "Apply test patch", - "TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk." + "TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk" } \ No newline at end of file diff --git a/public/locales/vi.json b/public/locales/vi.json index cad7c8f..1fc64fc 100644 --- a/public/locales/vi.json +++ b/public/locales/vi.json @@ -13,7 +13,7 @@ "GameDownloaded": "Game was successfully installed", "ApplyPatch": "Applying patch...", "PatchRequired": "Patch required", - "PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again.", + "PatchRequiredHint": "This game version doesn't have an anti-cheat patch. Please, wait a few days and try again", "TestPatch": "Apply test patch", - "TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk." + "TestPatchHint": "This game version has an anti-cheat patch, but it is in the testing phase. You can wait a few days until it is stable or apply it at your own risk" } \ No newline at end of file diff --git a/public/locales/zh-cn.json b/public/locales/zh-cn.json index 3dc9fa9..be47c64 100644 --- a/public/locales/zh-cn.json +++ b/public/locales/zh-cn.json @@ -13,7 +13,7 @@ "GameDownloaded": "游戏安装成功", "ApplyPatch": "应用补丁...", "PatchRequired": "需要补丁", - "PatchRequiredHint": "此游戏版本没有防作弊补丁。请等待几天,然后重试。", + "PatchRequiredHint": "此游戏版本没有防作弊补丁。请等待几天,然后重试", "TestPatch": "应用测试补丁", - "TestPatchHint": "此游戏版本有防作弊补丁,但处于测试阶段。您可以等待几天直到它稳定或自担风险应用它。" + "TestPatchHint": "此游戏版本有防作弊补丁,但处于测试阶段。您可以等待几天直到它稳定或自担风险应用它" } \ No newline at end of file diff --git a/public/locales/zh-tw.json b/public/locales/zh-tw.json index dc1de1e..a05de05 100644 --- a/public/locales/zh-tw.json +++ b/public/locales/zh-tw.json @@ -13,7 +13,7 @@ "GameDownloaded": "遊戲安裝成功", "ApplyPatch": "Applying patch...", "PatchRequired": "需要補丁", - "PatchRequiredHint": "此遊戲版本沒有防作弊補丁。請等待幾天,然後重試。", + "PatchRequiredHint": "此遊戲版本沒有防作弊補丁。請等待幾天,然後重試", "TestPatch": "應用測試補丁", - "TestPatchHint": "該遊戲版本有一個反作弊補丁,但處於測試階段。您可以等待幾天直到它穩定或自擔風險應用它。" + "TestPatchHint": "該遊戲版本有一個反作弊補丁,但處於測試階段。您可以等待幾天直到它穩定或自擔風險應用它" } \ No newline at end of file diff --git a/src/ts/index.ts b/src/ts/index.ts index 7e20d6c..90ea0bc 100644 --- a/src/ts/index.ts +++ b/src/ts/index.ts @@ -1,12 +1,13 @@ const path = require('path'); const fs = require('fs'); -const discordrpc = require("discord-rpc"); const { exec } = require('child_process'); const { ipcRenderer } = require('electron'); import $ from 'cash-dom'; -import { Genshinlib } from './Genshinlib'; -import { LauncherUI } from './LauncherUI'; +import { Genshinlib } from './lib/Genshinlib'; +import { LauncherUI } from './lib/LauncherUI'; +import { Tools } from './lib/Tools'; +import { DiscordRPC } from './lib/DiscordRPC'; if (!fs.existsSync(Genshinlib.prefixDir)) fs.mkdirSync(Genshinlib.prefixDir, { recursive: true }); @@ -21,61 +22,24 @@ $(() => { if (Genshinlib.version !== null) document.title = 'Genshin Impact Linux Launcher - ' + Genshinlib.version; - ipcRenderer.on('change-lang', (event: void, data: any) => { - LauncherUI.updateBackground(); - LauncherUI.updateSocial(); - LauncherUI.updateLang(data.lang); - }); - LauncherUI.setState('game-launch-available'); + LauncherUI.updateBackground(); LauncherUI.updateSocial(); - let rpc: any; + ipcRenderer.on('change-lang', (event: void, data: any) => { + LauncherUI.updateLang(data.lang); + LauncherUI.updateBackground(); + LauncherUI.updateSocial(); + }); - // FIXME - if (Genshinlib.getConfig().rpc) - { - rpc = new discordrpc.Client({ transport: 'ipc' }); - rpc.login({ clientId: '901534333360304168' }).catch(console.error); + if (Genshinlib.getConfig('rpc')) + DiscordRPC.init(); - rpc.on('ready', () => { - rpc.setActivity({ - details: 'Preparing to launch', - largeImageKey: 'launcher', - largeImageText: 'An Anime Game Launcher', - instance: false, - }); - }); - } - - // FIXME - ipcRenderer.on('rpcstate', (event: void, data: any) => { - if(!rpc) { - rpc = new discordrpc.Client({ transport: "ipc" }); - rpc.login({ clientId: '901534333360304168' }).catch(console.error); - - rpc.on('ready', () => { - rpc.setActivity({ - details: `Preparing to launch`, - largeImageKey: `launcher`, - largeImageText: `An Anime Game Launcher`, - instance: false, - }); - }); - - if (!Genshinlib.getConfig().rpc) - Genshinlib.updateConfig({ - rpc: true - }); - } else { - rpc.clearActivity(); - rpc.destroy(); - rpc = false; - Genshinlib.updateConfig({ - rpc: false - }); - } + ipcRenderer.on('rpc-toggle', () => { + DiscordRPC.isActive() ? + DiscordRPC.init() : + DiscordRPC.close(); }); // FIXME @@ -113,14 +77,14 @@ $(() => { console.log(`%c> Downloading voice data...`, 'font-size: 16px'); // For some reason this keeps breaking and locking up most of the time. - Genshinlib.downloadFile(voicePack.path, path.join(Genshinlib.launcherDir, voicePack.name), (current: number, total: number, difference: number) => { + Tools.downloadFile(voicePack.path, path.join(Genshinlib.launcherDir, voicePack.name), (current: number, total: number, difference: number) => { LauncherUI.updateProgressBar(LauncherUI.i18n.translate('Downloading'), current, total, difference); }).then(() => { console.log(`%c> Unpacking voice data...`, 'font-size: 16px'); LauncherUI.initProgressBar(); - Genshinlib.unzip(path.join(Genshinlib.launcherDir, voicePack.name), Genshinlib.gameDir, (current: number, total: number, difference: number) => { + Tools.unzip(path.join(Genshinlib.launcherDir, voicePack.name), Genshinlib.gameDir, (current: number, total: number, difference: number) => { LauncherUI.updateProgressBar(LauncherUI.i18n.translate('Unpack'), current, total, difference); }).then(() => { fs.unlinkSync(path.join(Genshinlib.launcherDir, voicePack.name)); @@ -136,7 +100,7 @@ $(() => { LauncherUI.setState(Genshinlib.version === null ? 'game-installation-available' : 'game-update-available'); // Patch version is incorrect - else if (Genshinlib.getConfig().patch && Genshinlib.getConfig().patch.version != Genshinlib.getPatchInfo().version) + else if (Genshinlib.getConfig('patch') && Genshinlib.getConfig('patch.version') != Genshinlib.getPatchInfo().version) { // Patch is not available if (Genshinlib.getPatchInfo().version !== data.game.latest.version) @@ -164,7 +128,7 @@ $(() => { // Current patch is in testing phase, // but stable is available - else if (Genshinlib.getConfig().patch && Genshinlib.getConfig().patch.version == Genshinlib.getPatchInfo().version && Genshinlib.getConfig().patch.state == 'testing' && Genshinlib.getPatchInfo().state == 'stable') + else if (Genshinlib.getConfig('patch') && Genshinlib.getConfig('patch.version') == Genshinlib.getPatchInfo().version && Genshinlib.getConfig('patch.state') == 'testing' && Genshinlib.getPatchInfo().state == 'stable') { console.log(`%c> Applying patch...`, 'font-size: 16px'); @@ -219,12 +183,12 @@ $(() => { { let wineExeutable = 'wine'; - if (Genshinlib.getConfig().runner !== null) + if (Genshinlib.getConfig('runner') !== null) { wineExeutable = path.join( Genshinlib.runnersDir, - Genshinlib.getConfig().runner?.folder, - Genshinlib.getConfig().runner?.executable + Genshinlib.getConfig('runner.folder'), + Genshinlib.getConfig('runner.executable') ); if (!fs.existsSync(wineExeutable)) @@ -239,15 +203,12 @@ $(() => { console.log(`Wine executable: ${wineExeutable}`); - // FIXME - if (rpc) + if (DiscordRPC.isActive()) { - rpc.setActivity({ - details: `In-Game`, - largeImageKey: `game`, - largeImageText: `An Anime Game Launcher`, - startTimestamp: parseInt(new Date().setDate(new Date().getDate()).toString()), - instance: false, + DiscordRPC.setActivity({ + details: 'In-Game', + largeImageKey: 'game', + largeImageText: 'An Anime Game Launcher' }); } @@ -262,14 +223,12 @@ $(() => { ipcRenderer.invoke('show-window'); - // FIXME - if (rpc) + if (DiscordRPC.isActive()) { - rpc.setActivity({ - details: `Preparing to launch`, - largeImageKey: `launcher`, - largeImageText: `An Anime Game Launcher`, - instance: false, + DiscordRPC.setActivity({ + details: 'Preparing to launch', + largeImageKey: 'launcher', + largeImageText: 'An Anime Game Launcher' }); } @@ -322,7 +281,7 @@ $(() => { LauncherUI.initProgressBar(); - Genshinlib.downloadFile(diff.path, path.join(Genshinlib.launcherDir, diff.name), (current: number, total: number, difference: number) => { + Tools.downloadFile(diff.path, path.join(Genshinlib.launcherDir, diff.name), (current: number, total: number, difference: number) => { LauncherUI.updateProgressBar(LauncherUI.i18n.translate('Downloading'), current, total, difference); }).then(() => { /** @@ -336,7 +295,7 @@ $(() => { LauncherUI.initProgressBar(); - Genshinlib.unzip(path.join(Genshinlib.launcherDir, diff.name), Genshinlib.gameDir, (current: number, total: number, difference: number) => { + Tools.unzip(path.join(Genshinlib.launcherDir, diff.name), Genshinlib.gameDir, (current: number, total: number, difference: number) => { LauncherUI.updateProgressBar(LauncherUI.i18n.translate('Unpack'), current, total, difference); }).then(() => { /** @@ -359,7 +318,7 @@ $(() => { LauncherUI.initProgressBar(); - Genshinlib.downloadFile(voicePack.path, path.join(Genshinlib.launcherDir, voicePack.name), (current: number, total: number, difference: number) => { + Tools.downloadFile(voicePack.path, path.join(Genshinlib.launcherDir, voicePack.name), (current: number, total: number, difference: number) => { LauncherUI.updateProgressBar(LauncherUI.i18n.translate('Downloading'), current, total, difference); }).then(() => { /** @@ -370,7 +329,7 @@ $(() => { LauncherUI.initProgressBar(); - Genshinlib.unzip(path.join(Genshinlib.launcherDir, voicePack.name), Genshinlib.gameDir, (current: number, total: number, difference: number) => { + Tools.unzip(path.join(Genshinlib.launcherDir, voicePack.name), Genshinlib.gameDir, (current: number, total: number, difference: number) => { LauncherUI.updateProgressBar(LauncherUI.i18n.translate('Unpack'), current, total, difference); }).then(() => { fs.unlinkSync(path.join(Genshinlib.launcherDir, voicePack.name)); diff --git a/src/ts/lib/DiscordRPC.ts b/src/ts/lib/DiscordRPC.ts new file mode 100644 index 0000000..c43296b --- /dev/null +++ b/src/ts/lib/DiscordRPC.ts @@ -0,0 +1,46 @@ +const discordRpc = require('discord-rpc'); + +export class DiscordRPC +{ + protected static readonly clientId = '901534333360304168'; + + protected static rpc: any = null; + + public static init () + { + this.rpc = new discordRpc.Client({ transport: 'ipc' }); + + this.rpc.login({ clientId: this.clientId }).catch(console.error); + + this.rpc.on('ready', () => { + this.rpc.setActivity({ + details: 'Preparing to launch', + largeImageKey: 'launcher', + largeImageText: 'An Anime Game Launcher', + instance: false + }); + }); + } + + public static setActivity (activity: any): void + { + this.rpc?.setActivity({ + startTimestamp: parseInt(new Date().setDate(new Date().getDate()).toString()), + instance: false, + ...activity + }); + } + + public static isActive (): boolean + { + return this.rpc !== null; + } + + public static close (): void + { + this.rpc?.clearActivity(); + this.rpc?.destroy(); + + this.rpc = null; + } +} diff --git a/src/ts/GIJSON.d.ts b/src/ts/lib/GIJSON.d.ts similarity index 100% rename from src/ts/GIJSON.d.ts rename to src/ts/lib/GIJSON.d.ts diff --git a/src/ts/Genshinlib.ts b/src/ts/lib/Genshinlib.ts similarity index 63% rename from src/ts/Genshinlib.ts rename to src/ts/lib/Genshinlib.ts index d9407ea..9a8f6bb 100644 --- a/src/ts/Genshinlib.ts +++ b/src/ts/lib/Genshinlib.ts @@ -1,4 +1,5 @@ import GIJSON from './GIJSON'; +import { Tools } from './Tools'; const https = require('follow-redirects').https; @@ -42,13 +43,13 @@ type Config = { folder: string, executable: string }, - rpc: boolean, - dxvk: string|null + dxvk: string|null, + rpc: boolean }; export class Genshinlib { - public static readonly patchDir: string = path.join(path.dirname(__dirname), 'patch'); + public static readonly patchDir: string = path.join(path.dirname(__dirname), '..', 'patch'); public static readonly patchJson: string = path.join(this.patchDir, 'patch.json'); public static readonly patchSh = path.join(this.patchDir, 'patch.sh'); public static readonly patchAntiCrashSh = path.join(this.patchDir, 'patch_anti_logincrash.sh'); @@ -71,12 +72,12 @@ export class Genshinlib public static get version(): Config['version'] { - return this.getConfig().version; + return this.getConfig('version'); } public static get lang(): Config['lang'] { - return this.getConfig().lang; + return this.getConfig('lang'); } public static getRunners (): Promise<[{ title: string, runners: Runner[] }]> @@ -101,7 +102,7 @@ export class Genshinlib // return new Promise(resolve => resolve(JSON.parse(fs.readFileSync(path.join(__dirname, '..', '..', 'dxvks.json'))))); } - public static getConfig (): Config + public static getConfig (property: string|null = null, splitProperty: boolean = true): any { if (!fs.existsSync(this.launcherJson)) fs.writeFileSync(this.launcherJson, JSON.stringify({ @@ -119,7 +120,20 @@ export class Genshinlib rpc: false }, null, 4)); - return JSON.parse(fs.readFileSync(this.launcherJson)); + let config = JSON.parse(fs.readFileSync(this.launcherJson)); + + if (property === null) + return config; + + else + { + if (!splitProperty) + return config[property]; + + property.split('.').forEach(prop => config = config[prop]); + + return config; + } } public static setConfig (info: Config): Genshinlib @@ -158,12 +172,12 @@ export class Genshinlib { let background = ''; - if (!this.getConfig().background.time || new Date(new Date().setHours(0,0,0,0)).setDate(new Date(new Date().setHours(0,0,0,0)).getDate()).toString() >= this.getConfig().background.time!) + if (!this.getConfig('background.time') || new Date(new Date().setHours(0,0,0,0)).setDate(new Date(new Date().setHours(0,0,0,0)).getDate()).toString() >= this.getConfig('background.time')!) { await fetch(this.backgroundUri + this.lang.launcher) .then(res => res.json()) .then(async resdone => { - let prevBackground = this.getConfig().background.file; + let prevBackground = this.getConfig('background.file'); this.updateConfig({ background: { @@ -172,23 +186,23 @@ export class Genshinlib } }); - if (fs.existsSync(path.join(this.launcherDir, this.getConfig().background.file))) - background = path.join(this.launcherDir, this.getConfig().background.file); + if (fs.existsSync(path.join(this.launcherDir, this.getConfig('background.file')))) + background = path.join(this.launcherDir, this.getConfig('background.file')); else { - await this.downloadFile(resdone.data.adv.background, path.join(this.launcherDir, this.getConfig().background.file), (current: number, total: number, difference: number) => null).then(() => { + await Tools.downloadFile(resdone.data.adv.background, path.join(this.launcherDir, this.getConfig('background.file')), (current: number, total: number, difference: number) => null).then(() => { !prevBackground ? console.log('No old background found') : fs.unlinkSync(path.join(this.launcherDir, prevBackground)); - background = path.join(this.launcherDir, this.getConfig().background.file); + background = path.join(this.launcherDir, this.getConfig('background.file')); }); }; }); } - else background = path.join(this.launcherDir, this.getConfig().background.file); + else background = path.join(this.launcherDir, this.getConfig('background.file')); return background; } @@ -228,131 +242,6 @@ export class Genshinlib }); } - public static async downloadFile (uri: string, savePath: string, progress: (current: number, total: number, difference: number) => void): Promise - { - return new Promise((resolve, reject) => { - https.get(uri, (response: any) => { - let length = parseInt(response.headers['content-length'], 10), - total = 0; - - response.on('data', (chunk: any) => { - total += chunk.length; - - progress(total, length, chunk.length); - - fs.appendFileSync(savePath, chunk); - }); - - response.on('end', () => resolve()); - }).on('error', (err: Error) => reject(err)); - }); - } - - public static async unzip (zipPath: string, unpackedPath: string, progress: (current: number, total: number, difference: number) => void): Promise - { - return new Promise((resolve, reject) => { - let listenerProcess = spawn('unzip', ['-v', zipPath]), - filesList = ''; - - listenerProcess.stdout.on('data', (data: string) => filesList += data); - - listenerProcess.on('close', () => { - let files = filesList.split(/\r\n|\r|\n/).slice(3, -3).map(line => { - line = line.trim(); - - if (line.slice(-1) == '/') - line = line.slice(0, -1); - - let matches = /^(\d+) [a-zA-Z\:]+[ ]+(\d+)[ ]+[0-9\-]+% [0-9\-]+ [0-9\:]+ [a-f0-9]{8} (.+)/.exec(line); - - if (matches) - return { - path: matches[3], - compressedSize: parseInt(matches[2]), - uncompressedSize: parseInt(matches[1]) - }; - }); - - let total = fs.statSync(zipPath)['size'], current = 0; - let unpackerProcess = spawn('unzip', ['-o', zipPath, '-d', unpackedPath]); - - unpackerProcess.stdout.on('data', (data: string) => { - data.toString().split(/\r\n|\r|\n/).forEach(line => { - let items = line.split(': '); - - if (items[1] !== undefined) - { - items[1] = path.relative(unpackedPath, items[1].trim()); - - files.forEach(file => { - if (file?.path == items[1]) - { - current += file.compressedSize; - - progress(current, total, file.compressedSize); - } - }); - } - }); - }); - - unpackerProcess.on('close', () => resolve()); - }); - }); - } - - public static async untar (tarPath: string, unpackedPath: string, progress: (current: number, total: number, difference: number) => void): Promise - { - return new Promise((resolve, reject) => { - let listenerProcess = spawn('tar', ['-tvf', tarPath]), - filesList = '', total = 0; - - listenerProcess.stdout.on('data', (data: string) => filesList += data); - - listenerProcess.on('close', () => { - let files = filesList.split(/\r\n|\r|\n/).slice(3, -3).map(line => { - line = line.trim(); - - if (line.slice(-1) == '/') - line = line.slice(0, -1); - - let matches = /^[dwxr\-]+ [\w/]+[ ]+(\d+) [0-9\-]+ [0-9\:]+ (.+)/.exec(line); - - // TODO: compressedSize? - if (matches) - { - total += parseInt(matches[1]); - - return { - path: matches[2], - uncompressedSize: parseInt(matches[1]) - }; - } - }); - - let current = 0; - let unpackerProcess = spawn('tar', ['-xvf', tarPath, '-C', unpackedPath]); - - unpackerProcess.stdout.on('data', (data: string) => { - data.toString().split(/\r\n|\r|\n/).forEach(line => { - line = line.trim(); - - files.forEach(file => { - if (file?.path == line) - { - current += file.uncompressedSize; // compressedSize - - progress(current, total, file.uncompressedSize); // compressedSize - } - }); - }); - }); - - unpackerProcess.on('close', () => resolve()); - }); - }); - } - // WINEPREFIX='/home/observer/genshin-impact-launcher/wineprefix' winetricks corefonts usetakefocus=n public static async installPrefix (prefixpath: string, progress: (output: string, current: number, total: number) => void): Promise { @@ -377,13 +266,13 @@ export class Genshinlib let installationProgress = 0; let installerProcess; - if (this.getConfig().runner) + if (this.getConfig('runner')) { installerProcess = spawn('winetricks', ['corefonts', 'usetakefocus=n', 'dxvk191'], { env: { ...process.env, WINEPREFIX: prefixpath, - WINE: path.join(this.runnersDir, this.getConfig().runner?.folder, this.getConfig().runner?.executable) + WINE: path.join(this.runnersDir, this.getConfig('runner.folder'), this.getConfig('runner.executable')) } }); } @@ -421,8 +310,8 @@ export class Genshinlib public static patchGame (version: string, onFinish: () => void, onData: (data: string) => void) { - this.downloadFile(this.patchUri, path.join(this.launcherDir, 'krock.zip'), (current: number, total: number, difference: number) => null).then(() => { - this.unzip(path.join(this.launcherDir, 'krock.zip'), this.launcherDir, (current: number, total: number, difference: number) => null).then(() => { + Tools.downloadFile(this.patchUri, path.join(this.launcherDir, 'krock.zip'), (current: number, total: number, difference: number) => null).then(() => { + Tools.unzip(path.join(this.launcherDir, 'krock.zip'), this.launcherDir, (current: number, total: number, difference: number) => null).then(() => { // Delete zip file and assign patch directory. fs.unlinkSync(path.join(this.launcherDir, 'krock.zip')); @@ -476,38 +365,4 @@ export class Genshinlib }); }); } - - /*public static applyPatch (onFinish: () => void, onData: (data: string) => void) - { - let patcherProcess = spawn('bash', [Genshinlib.patchSh], { - cwd: Genshinlib.gameDir, - env: { - ...process.env, - WINEPREFIX: Genshinlib.prefixDir - } - }); - - patcherProcess.stdout.on('data', (data: string) => onData(data)); - - patcherProcess.on('close', () => { - let patcherAntiCrashProcess = spawn('bash', [Genshinlib.patchAntiCrashSh], { - cwd: Genshinlib.gameDir, - env: { - ...process.env, - WINEPREFIX: Genshinlib.prefixDir - } - }); - - patcherAntiCrashProcess.stdout.on('data', (data: string) => onData(data)); - - patcherAntiCrashProcess.on('close', () => { - Genshinlib.setConfig({ - ...Genshinlib.getConfig(), - patch: Genshinlib.getPatchInfo() - }); - - onFinish(); - }); - }); - }*/ } diff --git a/src/ts/LauncherUI.ts b/src/ts/lib/LauncherUI.ts similarity index 94% rename from src/ts/LauncherUI.ts rename to src/ts/lib/LauncherUI.ts index 9190928..56c4e91 100644 --- a/src/ts/LauncherUI.ts +++ b/src/ts/lib/LauncherUI.ts @@ -167,14 +167,14 @@ export class LauncherUI public static updateSocial (): void { fetch(`https://genshin.mihoyo.com/launcher/10/${Genshinlib.lang.launcher}?api_url=https%3A%2F%2Fapi-os-takumi.mihoyo.com%2Fhk4e_global&prev=false`) - .then(res => res.text()) - .then(body => { - $('#__layout').remove(); - $(body).find('#__layout').appendTo('#launchcontent'); + .then(res => res.text()) + .then(body => { + $('#__layout').remove(); + $(body).find('#__layout').appendTo('#launchcontent'); - $('#launchcontent .home__main .home-swiper-wrap').remove(); - $('#launchcontent .home__main .home-news').remove(); - }); + $('#launchcontent .home__main .home-swiper-wrap').remove(); + $('#launchcontent .home__main .home-news').remove(); + }); } public static updateLang (lang: string|null = null): void diff --git a/src/ts/lib/Tools.ts b/src/ts/lib/Tools.ts new file mode 100644 index 0000000..17f001f --- /dev/null +++ b/src/ts/lib/Tools.ts @@ -0,0 +1,133 @@ +const https = require('follow-redirects').https; + +const fs = require('fs'); +const path = require('path'); +const { spawn } = require('child_process'); + +export class Tools +{ + public static async downloadFile (uri: string, savePath: string, progress: (current: number, total: number, difference: number) => void): Promise + { + return new Promise((resolve, reject) => { + https.get(uri, (response: any) => { + let length = parseInt(response.headers['content-length'], 10), + total = 0; + + response.on('data', (chunk: any) => { + total += chunk.length; + + progress(total, length, chunk.length); + + fs.appendFileSync(savePath, chunk); + }); + + response.on('end', () => resolve()); + }).on('error', (err: Error) => reject(err)); + }); + } + + public static async unzip (zipPath: string, unpackedPath: string, progress: (current: number, total: number, difference: number) => void): Promise + { + return new Promise((resolve, reject) => { + let listenerProcess = spawn('unzip', ['-v', zipPath]), + filesList = ''; + + listenerProcess.stdout.on('data', (data: string) => filesList += data); + + listenerProcess.on('close', () => { + let files = filesList.split(/\r\n|\r|\n/).slice(3, -3).map(line => { + line = line.trim(); + + if (line.slice(-1) == '/') + line = line.slice(0, -1); + + let matches = /^(\d+) [a-zA-Z\:]+[ ]+(\d+)[ ]+[0-9\-]+% [0-9\-]+ [0-9\:]+ [a-f0-9]{8} (.+)/.exec(line); + + if (matches) + return { + path: matches[3], + compressedSize: parseInt(matches[2]), + uncompressedSize: parseInt(matches[1]) + }; + }); + + let total = fs.statSync(zipPath)['size'], current = 0; + let unpackerProcess = spawn('unzip', ['-o', zipPath, '-d', unpackedPath]); + + unpackerProcess.stdout.on('data', (data: string) => { + data.toString().split(/\r\n|\r|\n/).forEach(line => { + let items = line.split(': '); + + if (items[1] !== undefined) + { + items[1] = path.relative(unpackedPath, items[1].trim()); + + files.forEach(file => { + if (file?.path == items[1]) + { + current += file.compressedSize; + + progress(current, total, file.compressedSize); + } + }); + } + }); + }); + + unpackerProcess.on('close', () => resolve()); + }); + }); + } + + public static async untar (tarPath: string, unpackedPath: string, progress: (current: number, total: number, difference: number) => void): Promise + { + return new Promise((resolve, reject) => { + let listenerProcess = spawn('tar', ['-tvf', tarPath]), + filesList = '', total = 0; + + listenerProcess.stdout.on('data', (data: string) => filesList += data); + + listenerProcess.on('close', () => { + let files = filesList.split(/\r\n|\r|\n/).slice(3, -3).map(line => { + line = line.trim(); + + if (line.slice(-1) == '/') + line = line.slice(0, -1); + + let matches = /^[dwxr\-]+ [\w/]+[ ]+(\d+) [0-9\-]+ [0-9\:]+ (.+)/.exec(line); + + // TODO: compressedSize? + if (matches) + { + total += parseInt(matches[1]); + + return { + path: matches[2], + uncompressedSize: parseInt(matches[1]) + }; + } + }); + + let current = 0; + let unpackerProcess = spawn('tar', ['-xvf', tarPath, '-C', unpackedPath]); + + unpackerProcess.stdout.on('data', (data: string) => { + data.toString().split(/\r\n|\r|\n/).forEach(line => { + line = line.trim(); + + files.forEach(file => { + if (file?.path == line) + { + current += file.uncompressedSize; // compressedSize + + progress(current, total, file.uncompressedSize); // compressedSize + } + }); + }); + }); + + unpackerProcess.on('close', () => resolve()); + }); + }); + } +} diff --git a/src/ts/i18n.ts b/src/ts/lib/i18n.ts similarity index 84% rename from src/ts/i18n.ts rename to src/ts/lib/i18n.ts index 1f5fe02..d25caac 100644 --- a/src/ts/i18n.ts +++ b/src/ts/lib/i18n.ts @@ -3,6 +3,8 @@ const fs = require('fs'); export class i18n { + public static readonly localesDir = path.join(path.dirname(__dirname), '..', 'locales'); + public static loadedLanguage: any; public static translate (phrase: string) @@ -36,8 +38,8 @@ export class i18n break; } - i18n.loadedLanguage = JSON.parse(fs.readFileSync(path.join(path.dirname(__dirname), 'locales', - fs.existsSync(path.join(path.dirname(__dirname), 'locales', lang + '.json')) ? + i18n.loadedLanguage = JSON.parse(fs.readFileSync(path.join(this.localesDir, + fs.existsSync(path.join(this.localesDir, lang + '.json')) ? lang + '.json' : 'en.json' ))); } diff --git a/src/ts/settings.ts b/src/ts/settings.ts index 1622cff..4440b90 100644 --- a/src/ts/settings.ts +++ b/src/ts/settings.ts @@ -4,8 +4,10 @@ const { ipcRenderer } = require('electron'); const { exec } = require('child_process'); import $ from 'cash-dom'; -import { Genshinlib } from './Genshinlib'; -import { LauncherUI } from './LauncherUI'; +import { i18n } from './lib/i18n'; +import { Genshinlib } from './lib/Genshinlib'; +import { LauncherUI } from './lib/LauncherUI'; +import { Tools } from './lib/Tools'; $(() => { @@ -31,10 +33,16 @@ $(() => { $(`#voice-list option[value="${Genshinlib.lang.voice}"]`).prop('selected', true); $(`#language-list option[value="${Genshinlib.lang.launcher}"]`).prop('selected', true); - if (Genshinlib.getConfig().rpc) - $(`#drpc`).prop('checked', true); + if (Genshinlib.getConfig('rpc')) + $('#drpc').prop('checked', true); - $('#drpc').on('change', () => ipcRenderer.send('rpcstate', {})); + $('#drpc').on('change', () => { + Genshinlib.updateConfig({ + rpc: $('#drpc').prop('checked') + }); + + ipcRenderer.send('rpc-toggle'); + }); $('#voice-list').on('change', (e) => { let activeVP = Genshinlib.lang.voice; @@ -66,32 +74,27 @@ $(() => { lang: { launcher: e.target.value, voice: Genshinlib.lang.voice - } - }); + }, - // This is required as the file name changes on the API but since we don't call the API before checking - // if the time is null or expired we set time to null here. - Genshinlib.updateConfig({ + // This is required as the file name changes on the API but since we don't call the API before checking + // if the time is null or expired we set time to null here. background: { time: null, - file: Genshinlib.getConfig().background.file + file: Genshinlib.getConfig('background.file') } }); - // Send language updates LauncherUI.updateLang(e.target.value); - ipcRenderer.send('change-lang', { 'lang': e.target.value }); - /*$('*[i18id]').each((i, element) => { - element.innerText = i18n.translate(element.getAttribute('i18id')?.toString()!); - });*/ + // Send language updates + ipcRenderer.send('change-lang', { 'lang': e.target.value }); $(`#language-list option[value="${activeLang}"]`).removeProp('selected'); $(`#language-list option[value="${e.target.value}"]`).prop('selected', true); } }); - let activeRunner = Genshinlib.getConfig().runner; + let activeRunner = Genshinlib.getConfig('runner'); Genshinlib.getRunners().then(runners => { runners.forEach(category => { @@ -116,11 +119,11 @@ $(() => { let div = item.find('div'); - Genshinlib.downloadFile(runner.uri, path.join(Genshinlib.launcherDir, runner.name), (current: number, total: number, difference: number) => { + Tools.downloadFile(runner.uri, path.join(Genshinlib.launcherDir, runner.name), (current: number, total: number, difference: number) => { div.text(`${ Math.round(current / total * 100) }%`); }).then(() => { let unpacker = runner.archive === 'tar' ? - Genshinlib.untar : Genshinlib.unzip; + Tools.untar : Tools.unzip; unpacker( path.join(Genshinlib.launcherDir, runner.name), @@ -165,7 +168,7 @@ $(() => { }); }); - let activeDXVK = Genshinlib.getConfig().dxvk; + let activeDXVK = Genshinlib.getConfig('dxvk'); Genshinlib.getDXVKs().then(dxvks => { dxvks.forEach(dxvk => { @@ -187,10 +190,10 @@ $(() => { let div = item.find('div'); - Genshinlib.downloadFile(dxvk.uri, path.join(Genshinlib.launcherDir, 'dxvk-' + dxvk.version), (current: number, total: number, difference: number) => { + Tools.downloadFile(dxvk.uri, path.join(Genshinlib.launcherDir, 'dxvk-' + dxvk.version), (current: number, total: number, difference: number) => { div.text(`${ Math.round(current / total * 100) }%`); }).then(() => { - Genshinlib.untar( + Tools.untar( path.join(Genshinlib.launcherDir, 'dxvk-' + dxvk.version), Genshinlib.dxvksDir, (current: number, total: number, difference: number) => { diff --git a/tsconfig.json b/tsconfig.json index c94f9be..8becd53 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,6 +9,6 @@ "removeComments": true, "outDir": "public/js" }, - "include": ["src/ts/*"], + "include": ["src/ts/*", "src/ts/lib/*"], "exclude": ["node_modules", "**/*.spec.ts"] } \ No newline at end of file