diff --git a/assets/jsons/translations/en.json b/assets/jsons/translations/en.json index 72422ef0..e838d4e3 100644 --- a/assets/jsons/translations/en.json +++ b/assets/jsons/translations/en.json @@ -187,6 +187,9 @@ } }, "errors": { + "titles":{ + "dotnet-required": ".NET 6 Required" + }, "msg": { "401": "Steam doesn't seem to want to let us download BeatSaber 😢", "404": "Unable to contact Steam servers.", @@ -211,7 +214,11 @@ "verification-failed": "Verification failed, 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." + "no-internet": "No internet connection.", + "dotnet-required": ".NET 6 Runtime must be installed in order to download a version of BeatSaber. Download it by clicking the button below." + }, + "actions":{ + "download-dotnet": "Download .NET 6" } } }, diff --git a/assets/jsons/translations/es.json b/assets/jsons/translations/es.json index 8c453fd6..bb4209be 100644 --- a/assets/jsons/translations/es.json +++ b/assets/jsons/translations/es.json @@ -187,6 +187,9 @@ } }, "errors": { + "titles":{ + "dotnet-required": ".NET 6 Requerido" + }, "msg": { "401": "Parece que Steam no quiere dejarnos descargar BeatSaber 😢", "404": "No se puede contactar con los servidores de Steam", @@ -211,7 +214,11 @@ "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.", "AlreadyDownloading": "La descarga ya está en curso", - "no-internet": "Sin conexión a Internet." + "no-internet": "Sin conexión a Internet.", + "dotnet-required": "Se debe instalar el tiempo de ejecución de .NET 6 para descargar una versión de BeatSaber. Descárguelo haciendo clic en el botón de abajo." + }, + "actions":{ + "download-dotnet": "Descargar .NET 6" } } }, diff --git a/assets/jsons/translations/fr.json b/assets/jsons/translations/fr.json index 69801494..cdf58eb6 100644 --- a/assets/jsons/translations/fr.json +++ b/assets/jsons/translations/fr.json @@ -187,6 +187,9 @@ } }, "errors": { + "titles":{ + "dotnet-required": ".NET 6 Requis" + }, "msg": { "401": "Steam semble pas vouloir nous laisser télécharger BeatSaber 😢", "404": "Impossible de contacter les serveurs de Steam.", @@ -211,7 +214,11 @@ "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.", "AlreadyDownloading": "Un téléchargement est déjà en cours", - "no-internet": "Pas de connexion internet." + "no-internet": "Pas de connexion internet.", + "dotnet-required": ".NET 6 Runtime doit être installé pour pouvoir télécharger une version de BeatSaber. Télécharge-le en cliquant sur le bouton ci-dessous." + }, + "actions":{ + "download-dotnet": "Télécharger .NET 6" } } }, diff --git a/src/main/ipcs/bs-download-ipcs.ts b/src/main/ipcs/bs-download-ipcs.ts index d9e8b748..80acc27b 100644 --- a/src/main/ipcs/bs-download-ipcs.ts +++ b/src/main/ipcs/bs-download-ipcs.ts @@ -25,6 +25,14 @@ export interface DownloadInfo { stay?: boolean } +ipcMain.on('is-dotnet-6-installed', async (event, request: IpcRequest) => { + const installer = BSInstallerService.getInstance(); + const utils = UtilsService.getInstance(); + installer.isDotNet6Installed().then(installed => { + utils.ipcSend(request.responceChannel, {success: true, data: installed}); + }); +}); + ipcMain.on('bs-download.start', async (event, request: IpcRequest) => { BSInstallerService.getInstance().downloadBsVersion(request.args).then(async res => { await LocalMapsManagerService.getInstance().linkVersionMaps(request.args.bsVersion, true).catch(e => {}); diff --git a/src/main/services/bs-installer.service.ts b/src/main/services/bs-installer.service.ts index 6c412ac3..ffdfd5b4 100644 --- a/src/main/services/bs-installer.service.ts +++ b/src/main/services/bs-installer.service.ts @@ -2,7 +2,7 @@ import { BS_APP_ID, BS_DEPOT } from "../constants"; import path from "path"; import { BSVersion } from 'shared/bs-version.interface'; import { UtilsService } from "./utils.service"; -import { ChildProcessWithoutNullStreams, spawn } from "child_process"; +import { ChildProcessWithoutNullStreams, spawn, spawnSync } from "child_process"; import log from "electron-log"; import { InstallationLocationService } from "./installation-location.service"; import { ctrlc } from "ctrlc-windows"; @@ -27,7 +27,7 @@ export class BSInstallerService{ this.localVersionService = BSLocalVersionService.getInstance(); this.windows = WindowManagerService.getInstance(); - this.windows.getWindows("index.html").on("close", () => { + this.windows.getWindows("index.html")?.on("close", () => { this.killDownloadProcess(); }); } @@ -65,6 +65,18 @@ export class BSInstallerService{ }); } + public async isDotNet6Installed(): Promise{ + try{ + const process = spawnSync(this.getDepotDownloaderExePath()); + const out = process.output.toString(); + if(out.includes(".NET runtime can be found at")){ return false; } + return true; + } + catch(e){ + return false; + } + } + public async downloadBsVersion(downloadInfos: DownloadInfo): Promise{ if(this.downloadProcess && this.downloadProcess.connected){ throw "AlreadyDownloading"; } diff --git a/src/renderer/services/bs-downloader.service.ts b/src/renderer/services/bs-downloader.service.ts index 5cf32032..c7da6b2a 100644 --- a/src/renderer/services/bs-downloader.service.ts +++ b/src/renderer/services/bs-downloader.service.ts @@ -11,6 +11,7 @@ import { NotificationService } from './notification.service'; import { ProgressBarService } from './progress-bar.service'; import { LoginModal } from 'renderer/components/modal/modal-types/login-modal.component'; import { GuardModal } from 'renderer/components/modal/modal-types/guard-modal.component'; +import { LinkOpenerService } from './link-opener.service'; export class BsDownloaderService{ @@ -22,6 +23,7 @@ export class BsDownloaderService{ private readonly authService: AuthUserService; private readonly progressBarService: ProgressBarService; private readonly notificationService: NotificationService; + private readonly linkOpener: LinkOpenerService; private _isVerification: boolean = false; @@ -41,6 +43,7 @@ export class BsDownloaderService{ this.authService = AuthUserService.getInstance(); this.progressBarService = ProgressBarService.getInstance(); this.notificationService = NotificationService.getInstance(); + this.linkOpener = LinkOpenerService.getInstance(); this.asignListerners(); } @@ -49,7 +52,7 @@ export class BsDownloaderService{ this.ipcService.watch("bs-download.[SteamID]").pipe(filter(r => r.success && !!r.data)).subscribe(response => this.authService.setSteamID(response.data)); - this.ipcService.watch("bs-download.[Warning]").pipe(filter(v => !!v && !!v.data), distinctUntilChanged(), throttleTime(1000)).subscribe(warning => { + this.ipcService.watch("bs-download.[Warning]").pipe(filter(v => !!v && !!v.data), distinctUntilChanged(), throttleTime(10_000)).subscribe(warning => { this.notificationService.notifyWarning({title: "notifications.types.warning", desc: `notifications.bs-download.warnings.msg.${warning.data}`}); }); @@ -84,9 +87,29 @@ export class BsDownloaderService{ return this.ipcService.send("bs-download.kill"); } + public isDotNet6Installed(): Promise{ + return this.ipcService.send("is-dotnet-6-installed").then(res => res.success && res.data) + } + public async download(bsVersion: BSVersion, isVerification?: boolean, isFirstCall = true): Promise>{ if(isFirstCall && !this.progressBarService.require()){ return {success: false}; } + if(isFirstCall && !(await this.isDotNet6Installed())){ + + const choice = await this.notificationService.notifyError({ + duration: 11_000, + title: "notifications.bs-download.errors.titles.dotnet-required", + desc: "notifications.bs-download.errors.msg.dotnet-required", + actions: [{id: "0", title: "notifications.bs-download.errors.actions.download-dotnet"}] + }); + + if(choice === "0"){ + this.linkOpener.open("https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-6.0.12-windows-x64-installer"); + } + + return {success: false}; + } + this.progressBarService.show(this.downloadProgress$); this._isVerification = !!isVerification; diff --git a/src/renderer/windows/App.tsx b/src/renderer/windows/App.tsx index 1cd2e173..7a0b3e3a 100644 --- a/src/renderer/windows/App.tsx +++ b/src/renderer/windows/App.tsx @@ -48,7 +48,7 @@ export default function App() { if(config.get("not-remind-oneclick") === true){ return; } - await timer(2_000).toPromise(); + await timer(3_000).toPromise(); const oneClicks = await Promise.all([ maps.isDeepLinksEnabled(),