diff --git a/src/main/services/mods/beat-mods-api.service.ts b/src/main/services/mods/beat-mods-api.service.ts index 90313751..40e1fb0f 100644 --- a/src/main/services/mods/beat-mods-api.service.ts +++ b/src/main/services/mods/beat-mods-api.service.ts @@ -14,6 +14,7 @@ export class BeatModsApiService { private readonly aliasesCache = new Map(); private readonly versionModsCache = new Map(); + private readonly modsHashCache = new Map(); private allModsCache: Mod[]; @@ -66,6 +67,29 @@ export class BeatModsApiService { return mod; } + private updateModsHashCache(mods: Mod[]): void { + + if(!Array.isArray(mods)){ + return; + } + + for (const mod of mods) { + for (const downloads of (mod.downloads ?? [])) { + for (const hashMd5 of (downloads.hashMd5 ?? [])) { + this.modsHashCache.set(hashMd5.hash, mod); + } + } + + for (const dep of (mod.dependencies ?? [])) { + for (const downloads of (dep.downloads ?? [])) { + for (const hashMd5 of (downloads.hashMd5 ?? [])) { + this.modsHashCache.set(hashMd5.hash, dep); + } + } + } + } + } + public async getVersionMods(version: BSVersion): Promise { if (this.versionModsCache.has(version.BSVersion)) { return this.versionModsCache.get(version.BSVersion); @@ -76,6 +100,9 @@ export class BeatModsApiService { return this.requestService.getJSON(this.getVersionModsUrl(alias)).then(mods => { mods = mods.map(mod => this.asignDependencies(mod, mods)); this.versionModsCache.set(version.BSVersion, mods); + + this.updateModsHashCache(mods); + return mods; }); } @@ -89,4 +116,15 @@ export class BeatModsApiService { return this.allModsCache; }); } + + public getModByHash(hash: string): Promise { + if (this.modsHashCache.has(hash)) { + return Promise.resolve(this.modsHashCache.get(hash)); + } + + return this.requestService.getJSON(`${this.BEAT_MODS_API_URL}mod?hash=${hash}`).then(mods => { + this.updateModsHashCache(mods); + return mods.at(0); + }); + } } diff --git a/src/main/services/mods/bs-mods-manager.service.ts b/src/main/services/mods/bs-mods-manager.service.ts index fb336d33..7d34f835 100644 --- a/src/main/services/mods/bs-mods-manager.service.ts +++ b/src/main/services/mods/bs-mods-manager.service.ts @@ -48,23 +48,14 @@ export class BsModsManagerService { } private async getModFromHash(hash: string): Promise { - const allMods = await this.beatModsApi.getAllMods(); - return allMods.find(mod => { - if (mod.name.toLowerCase() === "bsipa") { - return false; - } - return mod.downloads.some(download => download.hashMd5.some(md5 => md5.hash === hash)); - }); - } - private async getIpaFromHash(hash: string): Promise { - const allMods = await this.beatModsApi.getAllMods(); - return allMods.find(mod => { - if (mod.name.toLowerCase() !== "bsipa") { - return false; - } - return mod.downloads.some(download => download.hashMd5.some(md5 => md5.hash === hash)); - }); + const mod = await this.beatModsApi.getModByHash(hash); + + if(mod?.name?.toLowerCase() === "bsipa"){ + return undefined; + } + + return mod; } private async getModsInDir(version: BSVersion, modsDir: ModsInstallFolder): Promise { @@ -84,7 +75,6 @@ export class BsModsManagerService { return undefined; } const hash = await md5File(filePath); - const mod = await this.getModFromHash(hash); if (!mod) { @@ -107,7 +97,7 @@ export class BsModsManagerService { }); const mods = await Promise.all(promises); - return mods.filter(Boolean); + return mods.filter(Boolean); } private async getBsipaInstalled(version: BSVersion): Promise { @@ -117,7 +107,7 @@ export class BsModsManagerService { return undefined; } const injectorMd5 = await md5File(injectorPath); - return this.getIpaFromHash(injectorMd5); + return this.beatModsApi.getModByHash(injectorMd5); } private async downloadZip(zipUrl: string): Promise { @@ -322,8 +312,10 @@ export class BsModsManagerService { public async getInstalledMods(version: BSVersion): Promise { this.manifestMatches = []; - await this.beatModsApi.getAllMods(); + const bsipa = await this.getBsipaInstalled(version); + + return Promise.all([this.getModsInDir(version, ModsInstallFolder.PLUGINS_PENDING), this.getModsInDir(version, ModsInstallFolder.LIBS_PENDING), this.getModsInDir(version, ModsInstallFolder.PLUGINS), this.getModsInDir(version, ModsInstallFolder.LIBS)]).then(dirMods => { const modsDict = new Map(); diff --git a/src/renderer/components/version-viewer/slides/mods/mods-slide.component.tsx b/src/renderer/components/version-viewer/slides/mods/mods-slide.component.tsx index 29fb94d3..cc773abb 100644 --- a/src/renderer/components/version-viewer/slides/mods/mods-slide.component.tsx +++ b/src/renderer/components/version-viewer/slides/mods/mods-slide.component.tsx @@ -9,8 +9,8 @@ import { BsmButton } from "renderer/components/shared/bsm-button.component"; import BeatWaitingImg from "../../../../../../assets/images/apngs/beat-waiting.png"; import BeatConflictImg from "../../../../../../assets/images/apngs/beat-conflict.png"; import { useObservable } from "renderer/hooks/use-observable.hook"; -import { skip, filter, map } from "rxjs/operators"; -import { Observable, Subscription, combineLatest, lastValueFrom, noop } from "rxjs"; +import { skip, filter } from "rxjs/operators"; +import { Subscription, lastValueFrom, noop } from "rxjs"; import { useTranslation } from "renderer/hooks/use-translation.hook"; import { LinkOpenerService } from "renderer/services/link-opener.service"; import { useInView } from "framer-motion"; @@ -96,24 +96,27 @@ export function ModsSlide({ version, onDisclamerDecline }: { version: BSVersion; }); modsManager.installMods(modsToInstall, version).then(() => { - lastValueFrom(loadMods()); + loadMods(); }); }; - const loadMods = (): Observable => { + const loadMods = (): Promise => { if (os.isOffline) { - return new Observable(subscriber => subscriber.complete()); + return Promise.resolve(); } - return combineLatest([ - modsManager.getAvailableMods(version), - modsManager.getInstalledMods(version) - ]).pipe(map(([available, installed]) => { + const promise = async () => { + const available = await lastValueFrom(modsManager.getAvailableMods(version)); + const installed = await lastValueFrom(modsManager.getInstalledMods(version)); + return [available, installed]; + } + + return promise().then(([available, installed]) => { const defaultMods = configService.get("default_mods" as DefaultConfigKey); setModsAvailable(() => modsToCategoryMap(available)); setModsSelected(() => available.filter(m => m.required || defaultMods.some(d => m.name.toLowerCase() === d.toLowerCase()) || installed.some(i => m.name === i.name))); setModsInstalled(() => modsToCategoryMap(installed)); - })); + }); }; useEffect(() => { @@ -141,14 +144,14 @@ export function ModsSlide({ version, onDisclamerDecline }: { version: BSVersion; return onDisclamerDecline?.(); } - subs.push(loadMods().subscribe()); + loadMods(); subs.push( modsManager.isUninstalling$.pipe( skip(1), filter(uninstalling => !uninstalling) ).subscribe(() => { - subs.push(loadMods().subscribe()); + loadMods(); }) ); });