diff --git a/src/renderer/services/beat-saver/beat-saver-api.service.ts b/src/renderer/services/beat-saver/beat-saver-api.service.ts index 7f15410b..2ac681bc 100644 --- a/src/renderer/services/beat-saver/beat-saver-api.service.ts +++ b/src/renderer/services/beat-saver/beat-saver-api.service.ts @@ -19,7 +19,6 @@ export class BeatSaverApiService { if(hashs.length > 50){ throw "too musch map hashs"; } const paramsHashs = hashs.join(","); - const resp = await fetch(`${this.bsaverApiUrl}/maps/hash/${paramsHashs}`); const data = await resp.json() as Record, BsvMapDetail> | BsvMapDetail; diff --git a/src/renderer/services/beat-saver/beat-saver.service.ts b/src/renderer/services/beat-saver/beat-saver.service.ts index 39bcca9b..b1ee2a37 100644 --- a/src/renderer/services/beat-saver/beat-saver.service.ts +++ b/src/renderer/services/beat-saver/beat-saver.service.ts @@ -1,6 +1,8 @@ import { splitIntoChunk } from "renderer/helpers/array-tools"; +import { of } from "rxjs"; import { Observable } from "rxjs"; import { BsvMapDetail } from "shared/models/maps"; +import { OsDiagnosticService } from "../os-diagnostic.service"; import { BeatSaverApiService } from "./beat-saver-api.service"; export class BeatSaverService { @@ -13,24 +15,45 @@ export class BeatSaverService { } private readonly bsaverApi: BeatSaverApiService; + private readonly os: OsDiagnosticService; + + private readonly cachedMapsDetails = new Map() private constructor(){ this.bsaverApi = BeatSaverApiService.getInstance(); + this.os = OsDiagnosticService.getInstance(); } public getMapDetailsFromHashs(hashs: string[]): Observable{ - const chunkHash = splitIntoChunk(hashs, 50); + + const filtredHashs = hashs.map(h => h.toLowerCase()).filter(hash => !Array.from(this.cachedMapsDetails.keys()).includes(hash)); + const chunkHash = splitIntoChunk(filtredHashs, 50); + + const mapDetails = Array.from(this.cachedMapsDetails.entries()).reduce((res , [hash, details]) => { + if(hashs.includes(hash)){ + res.push(details); + } + return res; + }, [] as BsvMapDetail[]); + + if(this.os.isOffline){ + return of(mapDetails); + } return new Observable(observer => { (async () => { - const mapDetails: BsvMapDetail[] = []; - for(const hashs of chunkHash){ + const res = await this.bsaverApi.getMapsDetailsByHashs(hashs); + if(res.status === 200){ mapDetails.push(...Object.values(res.data)); + mapDetails.forEach(detail => this.cachedMapsDetails.set(detail.versions.at(0).hash.toLowerCase(), detail)); + } + + if(mapDetails.length > 0){ observer.next(mapDetails); } diff --git a/src/renderer/services/os-diagnostic.service.ts b/src/renderer/services/os-diagnostic.service.ts new file mode 100644 index 00000000..a5b4fd1c --- /dev/null +++ b/src/renderer/services/os-diagnostic.service.ts @@ -0,0 +1,25 @@ +import { BehaviorSubject } from "rxjs"; + +export class OsDiagnosticService { + + private static instance: OsDiagnosticService; + + public static getInstance(): OsDiagnosticService{ + if(!OsDiagnosticService.instance){ OsDiagnosticService.instance = new OsDiagnosticService(); } + return OsDiagnosticService.instance; + } + + private _isOnline$ = new BehaviorSubject(true); + + private constructor(){ + + window.addEventListener("online", () => this._isOnline$.next(true)); + window.addEventListener("offline", () => this._isOnline$.next(false)); + + } + + public get isOnline(){ return this._isOnline$.value; } + public get isOffline(){ return !this._isOnline$.value; } + public get isOnline$(){ return this._isOnline$.asObservable(); } + +} \ No newline at end of file