[feature] Add notifications for BS download

This commit is contained in:
MathieuG-P
2023-08-05 03:50:04 +02:00
parent a92c65be53
commit 1be3b7af31
10 changed files with 84 additions and 52 deletions
+2 -4
View File
@@ -232,7 +232,6 @@
"404": "Steam-Server können nicht kontaktiert werden.",
"Password": "Passwort ist ungültig.",
"InvalidCredentials": "Deine E-Mail oder Passwort ist ungültig 😴",
"InvalidPassword": "Dein Passwort ist ungültig 😕",
"NoManifest": "Es wurde keine Manifest gefunden",
"DirectoryCreate": "Die erforderlichen Ordner können nicht installiert werden.",
"NotAvailableApp": "Versuchst du, Beat Saber herunterzuladen, wenn Du es nicht hast? 🤣",
@@ -248,10 +247,9 @@
"SteamLib": "Wenn dieser Fehler auftritt, melde den Fehler auf Github mit Protokollen, bitte.",
"ConnectionError": "Kann nach 10 Versuchen keine Verbindung zu Steam herstellen 🤯",
"LicenceError": "Die Liste der Lizenzen kann nicht abgerufen werden.",
"verification-failed": "Verifikation fehlgeschlagen, versuche es später erneut.",
"RateLimitExceeded": "Du hast es zu oft versucht, warte eine Weile und versuche es später erneut.",
"AlreadyDownloading": "Ein Download ist bereits im Gange",
"no-internet": "Keine Internet Verbindung",
"TokenRejected": "BeatSaber kann nicht heruntergeladen werden 😥 versuche es später noch einmal 😕",
"AccessDenied": "Der Zugang zu Steam wurde verweigert.",
"dotnet-required": ".NET 6 Runtime muss installiert sein, um eine Version von BeatSaber herunterzuladen. Lade es herunter, indem Du auf die Schaltfläche unten klickst."
},
"actions": {
+2 -4
View File
@@ -232,7 +232,6 @@
"404": "Unable to contact Steam servers.",
"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 Beat Saber when you don't have it? 🤣",
@@ -248,10 +247,9 @@
"SteamLib": "If you have this error, report the bug on GitHub with the logs pls.",
"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.",
"AlreadyDownloading": "A download is already in progress",
"no-internet": "No internet connection.",
"TokenRejected": "Unable to download Beat Saber 😥 try again later 😕",
"AccessDenied": "Access to Steam has been denied.",
"dotnet-required": ".NET 6 Runtime must be installed in order to download a version of Beat Saber. Download it by clicking the button below."
},
"actions": {
+2 -4
View File
@@ -231,7 +231,6 @@
"404": "No se puede contactar con los servidores de Steam",
"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? 🤣",
@@ -247,10 +246,9 @@
"SteamLib": "Si tienes este error, reporta el bug en GitHub con los logs por favor.",
"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.",
"AlreadyDownloading": "La descarga ya está en curso",
"no-internet": "Sin conexión a Internet.",
"TokenRejected": "No se puede descargar BeatSaber 😥 inténtalo más tarde 😕",
"AccessDenied": "El acceso a Steam ha sido denegado.",
"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": {
+2 -7
View File
@@ -215,10 +215,7 @@
},
"warnings": {
"msg": {
"ManifestChecksum": "Le manifest téléchargé précédemment ne correspond pas au nouveau 🤔",
"ConnectionTimeout": "Ta connexion internet semble instable 🥶",
"ConnectionLost": "La connexion a été perdue, nouvelle tentative...",
"ConnectionError": "Impossible de se connecter à Steam, nouvelle tentative...",
"Unknown": "Quelque chose d'étrange s'est produit 🤔 Votre connexion est surement instable."
}
},
@@ -231,7 +228,6 @@
"404": "Impossible de contacter les serveurs de Steam.",
"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 Beat Saber alors que tu ne l'as pas ? 🤣",
@@ -247,10 +243,9 @@
"SteamLib": "Si tu as cette erreur, signale le bug sur GitHub avec les logs stp.",
"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 attends un peu et recommence plus tard.",
"AlreadyDownloading": "Un téléchargement est déjà en cours",
"no-internet": "Pas de connexion internet.",
"TokenRejected": "Impossible de télécharger Beat Saber 😥 réessaye plus tard 😕",
"AccessDenied": "L'accès à Steam a été refusé.",
"dotnet-required": ".NET 6 Runtime doit être installé pour pouvoir télécharger une version de Beat Saber. Télécharge-le en cliquant sur le bouton ci-dessous."
},
"actions": {
+2 -4
View File
@@ -232,7 +232,6 @@
"404": "Нет связи с серверами Steam.",
"Password": "Неверный пароль.",
"InvalidCredentials": "Ваша почта или пароль неверны 😴",
"InvalidPassword": "Ваш пароль неверен 😕",
"NoManifest": "Файл манифеста не найден",
"DirectoryCreate": "Не смогли создать нужные папки.",
"NotAvailableApp": "Вы пытаетесь скачать Beat Saber, не купив её? 🤣",
@@ -248,10 +247,9 @@
"SteamLib": "Если вы это видите, пожалуйста, сообщите о баге на GitHub с файлом логов.",
"ConnectionError": "Не удалось подключиться к Steam за 10 попыток 🤯",
"LicenceError": "Не удалось проверить наличие лицензии.",
"verification-failed": "Верификация провалена, повторите попытку позже.",
"RateLimitExceeded": "Слишком много попыток, вернитесь позже и попробуйте снова.",
"AlreadyDownloading": "Скачивание уже в процессе",
"no-internet": "Нет интернета.",
"TokenRejected": "Не удалось скачать Beat Saber 😥 повторите попытку позже 😕",
"AccessDenied": "Доступ к Steam был отклонен.",
"dotnet-required": "Среда запуска .NET 6 должна быть установлена, чтобы скачать Beat Saber. Скачайте её с помощью кнопки ниже."
},
"actions": {
+18 -4
View File
@@ -1,6 +1,7 @@
import { ChildProcessWithoutNullStreams, SpawnOptionsWithoutStdio, spawn } from "child_process";
import { Observable, ReplaySubject, Subscriber, filter, map, share } from "rxjs";
import { DepotDownloaderArgsOptions, DepotDownloaderEvent, DepotDownloaderEventType, DepotDownloaderEventTypes, DepotDownloaderSubTypeOfEventType } from "../../shared/models/depot-downloader.model";
import { DepotDownloaderArgsOptions, DepotDownloaderErrorEvent, DepotDownloaderEvent, DepotDownloaderEventType, DepotDownloaderEventTypes, DepotDownloaderInfoEvent, DepotDownloaderWarningEvent } from "../../shared/models/depot-downloader.model";
import { DownloadEvent } from "main/services/bs-installer.service";
export class DepotDownloader {
@@ -22,7 +23,11 @@ export class DepotDownloader {
subscriber.next(`[Info]|[Start]|${JSON.stringify(options.echoStartData) ?? ""}`);
this.process.stdout.on("data", data => subscriber.next(data.toString()));
this.process.stdout.on("data", data => {
const lines: string[] = data.toString().split("\n");
lines.forEach(line => subscriber.next(line));
});
this.process.stderr.on("error", error => subscriber.error(error));
this.process.on("exit", code => subscriber.complete());
@@ -36,9 +41,18 @@ export class DepotDownloader {
}
public $events(): Observable<DepotDownloaderEvent<unknown>>{
const eventTypesArr = Object.values(DepotDownloaderEventType);
const DepotDownloaderSubTypeOfEventType: {[key in DepotDownloaderEventType]: DepotDownloaderEventTypes[]} = {
[DepotDownloaderEventType.Error]: Object.values(DepotDownloaderErrorEvent),
[DepotDownloaderEventType.Warning]: Object.values(DepotDownloaderWarningEvent),
[DepotDownloaderEventType.Info]: Object.values(DepotDownloaderInfoEvent),
}
return this.processOut$.pipe(map(line => {
console.log(line.toString());
console.log(line);
const matched = (line.toString() as string).match(/(?:\[(.*?)\])\|(?:\[(.*?)\]\|)?(.*?)(?=$|\[)/gm)?.[0] ?? null;
@@ -46,7 +60,7 @@ export class DepotDownloader {
const splitedLine = matched.split("|").map(str => str.trim().replaceAll("[", "").replaceAll("]", "")) as [DepotDownloaderEventType, DepotDownloaderEventTypes, unknown];
if(!Object.values(DepotDownloaderEventType).includes(splitedLine[0]) || !Object.values(DepotDownloaderSubTypeOfEventType[splitedLine[0]]).includes(splitedLine[1])){
if(!eventTypesArr.includes(splitedLine[0] as DepotDownloaderEventType) || !DepotDownloaderSubTypeOfEventType[splitedLine[0]].includes(splitedLine[1])){
return null;
}
+10 -2
View File
@@ -35,6 +35,7 @@ import { useService } from "renderer/hooks/use-service.hook";
import { lastValueFrom } from "rxjs";
import { BsmException } from "shared/models/bsm-exception.model";
import { useObservable } from "renderer/hooks/use-observable.hook";
import { AuthUserService } from "renderer/services/auth-user.service";
export function SettingsPage() {
@@ -51,6 +52,7 @@ export function SettingsPage() {
const playlistsManager = useService(PlaylistsManagerService);
const modelsManager = useService(ModelsManagerService);
const versionLinker = useService(VersionFolderLinkerService);
const authService = useService(AuthUserService);
const { firstColor, secondColor } = useThemeColor();
@@ -67,6 +69,9 @@ export function SettingsPage() {
})
.sort((a, b) => a.text.localeCompare(b.text));
const nav = useNavigate();
const t = useTranslation();
const [themeIdSelected, setThemeIdSelected] = useState(themeItem.find(e => e.value === themeService.getTheme()).id);
const [languageSelected, setLanguageSelected] = useState(languagesItems.find(e => e.value === i18nService.currentLanguage).id);
const [installationFolder, setInstallationFolder] = useState(null);
@@ -75,8 +80,7 @@ export function SettingsPage() {
const [playlistsDeepLinkEnabled, setPlaylistsDeepLinkEnabled] = useState(false);
const [modelsDeepLinkEnabled, setModelsDeepLinkEnabled] = useState(false);
const appVersion = useObservable(ipcService.sendV2<string>("current-version"));
const nav = useNavigate();
const t = useTranslation();
const steamSessionExist = useObservable(authService.sessionExist$);
useEffect(() => {
loadInstallationFolder();
@@ -203,6 +207,10 @@ export function SettingsPage() {
<BsmButton className="inline-block grow-0 bg-transparent sticky h-full w-full top-20 right-20 !m-0 rounded-full p-1" onClick={() => nav(-1)} icon="close" withBar={false} />
</div>
<SettingContainer title="pages.settings.steam.title" description="pages.settings.steam.description">
<BsmButton onClick={() => authService.deleteSteamSession()} className="w-fit px-3 py-[2px] text-white rounded-md" withBar={false} text="pages.settings.steam.logout" typeColor="error" disabled={!steamSessionExist}/>
</SettingContainer>
<SettingContainer title="pages.settings.appearance.title" description="pages.settings.appearance.description">
<div className="relative w-full h-8 bg-light-main-color-1 dark:bg-main-color-1 flex justify-center rounded-md py-1">
<SettingColorChooser color={firstColor} onChange={setFirstColorSetting} />
@@ -43,7 +43,7 @@ export function VersionViewer() {
navigate(`/bs-version/${version.BSVersion}`, { state: version });
};
const openFolder = () => ipcService.sendLazy("bs-version.open-folder", { args: state });
const verifyFiles = () => bsDownloaderService.download(state, true);
const verifyFiles = () => bsDownloaderService.verifyBsVersionFiles(state);
const uninstall = async () => {
const modalCompleted = await modalService.openModal(UninstallModal, state);
+41 -15
View File
@@ -1,7 +1,6 @@
import { DownloadEvent, DownloadInfo } from "main/services/bs-installer.service";
import { BehaviorSubject, Observable, Subscription, identity, lastValueFrom, of, throwError } from "rxjs";
import { distinctUntilChanged, filter, map, take, tap, throttleTime } from "rxjs/operators";
import { IpcResponse } from "shared/models/ipc";
import { DownloadInfo } from "main/services/bs-installer.service";
import { BehaviorSubject, Observable, ReplaySubject, Subscription, lastValueFrom, throwError } from "rxjs";
import { distinctUntilChanged, filter, map, share, take, tap, throttleTime } from "rxjs/operators";
import { BSVersion } from "shared/bs-version.interface";
import { AuthUserService } from "./auth-user.service";
import { BSVersionManagerService } from "./bs-version-manager.service";
@@ -12,7 +11,7 @@ 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";
import { DepotDownloaderErrorEvent, DepotDownloaderEvent, DepotDownloaderEventType, DepotDownloaderInfoEvent, DepotDownloaderSubTypeOfEventType, DepotDownloaderWarningEvent } from "../../shared/models/depot-downloader.model";
import { DepotDownloaderErrorEvent, DepotDownloaderEvent, DepotDownloaderEventType, DepotDownloaderInfoEvent, DepotDownloaderWarningEvent } from "../../shared/models/depot-downloader.model";
import equal from "fast-deep-equal";
import { SteamMobileApproveModal } from "renderer/components/modal/modal-types/steam-mobile-approve-modal.component";
@@ -146,7 +145,10 @@ export class BsDownloaderService {
filter(event => event.subType === DepotDownloaderInfoEvent.Finished),
take(1),
).subscribe(() => {
console.log("show success notification");
if(this.isVerification){
return this.notificationService.notifySuccess({title: "notifications.bs-download.success.titles.verification-finished"});
}
return this.notificationService.notifySuccess({title: "notifications.bs-download.success.titles.download-success"});
}));
return subs;
@@ -154,24 +156,37 @@ export class BsDownloaderService {
private handleWarningEvents(events$: Observable<DepotDownloaderEvent>): Subscription[] {
const subs: Subscription[] = [];
const handledWarnings = Object.values(DepotDownloaderWarningEvent);
subs.push(events$.pipe(
filter(event => handledWarnings.includes(event.subType as DepotDownloaderWarningEvent)),
).subscribe(event => {
this.notificationService.notifyWarning({title: "notifications.types.warning", desc: `notifications.bs-download.warnings.msg.${event.subType}`});
}));
return subs;
}
private hanndleErrorEvents(events$: Observable<DepotDownloaderEvent>): Subscription[] {
const subs: Subscription[] = [];
return subs;
private hanndleErrorEvent(errorEvent: DepotDownloaderEvent) {
const handledErrors = Object.values(DepotDownloaderErrorEvent);
if(handledErrors.includes(errorEvent?.subType as DepotDownloaderErrorEvent)){
return this.notificationService.notifyError({title: "notifications.types.error", desc: `notifications.bs-download.errors.msg.${errorEvent.subType}`});
}
return this.notificationService.notifyError({title: "notifications.types.error", desc: `notifications.bs-download.errors.msg.${DepotDownloaderErrorEvent.Unknown}`});
}
private wrapDownload(download$: Observable<DepotDownloaderEvent>): Observable<DepotDownloaderEvent> {
private wrapDownload(download$: Observable<DepotDownloaderEvent>, silent?: boolean): Observable<DepotDownloaderEvent> {
return new Observable<DepotDownloaderEvent>(sub => {
const downloadSub = download$.subscribe(sub);
const downloadSub = download$.subscribe({next: n => sub.next(n), error: e => sub.error(e), complete: () => sub.complete()});
const subs = [
...this.handleInfoEvents(download$.pipe(filter(event => event.type === DepotDownloaderEventType.Info))),
...this.handleWarningEvents(download$.pipe(filter(event => event.type === DepotDownloaderEventType.Warning))),
...this.hanndleErrorEvents(download$.pipe(filter(event => event.type === DepotDownloaderEventType.Error)))
...this.handleWarningEvents(download$.pipe(filter(event => event.type === DepotDownloaderEventType.Warning), throttleTime(10_000))),
];
return () => {
@@ -180,7 +195,13 @@ export class BsDownloaderService {
}
}).pipe(
tap({error: () => this.authService.deleteSteamSession()})
tap({
error: (e) => {
this.authService.deleteSteamSession();
!silent && this.hanndleErrorEvent(e)
}
}),
share({connector: () => new ReplaySubject(1)})
);
}
@@ -193,7 +214,8 @@ export class BsDownloaderService {
const infos: DownloadInfo = {...downloadInfo, username: this.authService.getSteamUsername()}
return this.wrapDownload(
this.ipcService.sendV2<DepotDownloaderEvent>("auto-download-bs-version", { args: infos })
this.ipcService.sendV2<DepotDownloaderEvent>("auto-download-bs-version", { args: infos }),
true
);
}
@@ -272,6 +294,10 @@ export class BsDownloaderService {
return this.doDownloadBsVersion(version).then(() => version);
}
public verifyBsVersionFiles(version: BSVersion): Promise<BSVersion> {
return this.doDownloadBsVersion(version, true).then(() => version);
}
public verifyBsVersion(version: BSVersion): Promise<BSVersion> {
return this.doDownloadBsVersion(version, true).then(() => version);
}
+4 -7
View File
@@ -35,7 +35,7 @@ export enum DepotDownloaderErrorEvent {
DepotNotFound = "DepotNotFound",
NotCompleted = "NotCompleted",
InvalidManifest = "InvalidManifest",
NoValidKeys = "NoValidKeys",
NoValidKeys = "NoValidKey",
NoManifestCode = "NoManifestCode",
_401 = "401",
_404 = "404",
@@ -46,17 +46,14 @@ export enum DepotDownloaderErrorEvent {
ConnectionError = "ConnectionError",
TokenRejected = "TokenRejected",
LicenceError = "LicenceError",
AccessDenied = "AccessDenied",
Unknown = "Unknown",
}
export enum DepotDownloaderWarningEvent {
ManifestChecksum = "ManifestChecksum",
}
export const DepotDownloaderSubTypeOfEventType = {
[DepotDownloaderEventType.Error]: DepotDownloaderErrorEvent,
[DepotDownloaderEventType.Warning]: DepotDownloaderWarningEvent,
[DepotDownloaderEventType.Info]: DepotDownloaderInfoEvent,
ConnectionTimeout = "ConnectionTimeout",
Unknown = "Unknown",
}
export interface DepotDownloaderArgsOptions {