we can now download maps from bsaver

This commit is contained in:
MathieuG-P
2022-12-06 00:52:37 +01:00
parent 9dce72250e
commit 8930009398
16 changed files with 309 additions and 24 deletions
@@ -45,13 +45,19 @@ export class BeatSaverService {
return new Observable(observer => {
(async () => {
if(mapDetails.length > 0){
observer.next(mapDetails);
}
for(const hashs of chunkHash){
const res = await this.bsaverApi.getMapsDetailsByHashs(hashs);
if(res.status === 200){
mapDetails.push(...Object.values<BsvMapDetail>(res.data));
mapDetails.forEach(detail => this.cachedMapsDetails.set(detail.versions.at(0).hash.toLowerCase(), detail));
mapDetails.push(...Object.values<BsvMapDetail>(res.data).filter(detail => !!detail));
mapDetails.forEach(detail => {
this.cachedMapsDetails.set(detail.versions.at(0).hash.toLowerCase(), detail);
});
}
if(mapDetails.length > 0){
@@ -1,6 +1,18 @@
import { DownloadMapsModal } from "renderer/components/modal/modal-types/download-maps-modal.component";
import { map, filter } from "rxjs/operators";
import { BehaviorSubject } from "rxjs";
import { BSVersion } from "shared/bs-version.interface";
import { ModalResponse, ModalService } from "./modale.service";
import { Observable } from "rxjs";
import { ProgressBarService } from "./progress-bar.service";
import { ProgressionInterface } from "shared/models/progress-bar";
import { BsvMapDetail } from "shared/models/maps";
import { IpcService } from "./ipc.service";
import { getMapZipUrlFromMapDetails } from "renderer/helpers/maps-utils";
import { OsDiagnosticService } from "./os-diagnostic.service";
import { timer } from "rxjs";
import equal from "fast-deep-equal/es6";
import { CSSProperties } from "react";
export class MapsDownloaderService {
@@ -12,15 +24,111 @@ export class MapsDownloaderService {
}
private readonly modals: ModalService;
private readonly progressBar: ProgressBarService;
private readonly ipc: IpcService;
private readonly os: OsDiagnosticService;
private readonly mapsQueue$: BehaviorSubject<MapDownload[]> = new BehaviorSubject([]);
private readonly currentDownload$: BehaviorSubject<MapDownload> = new BehaviorSubject(null);
private queueMaxLenght = 0;
private downloadedListerners: ((map: BsvMapDetail, version: BSVersion) => void)[] = [];
public readonly progressBarStyle: CSSProperties = {zIndex: 100000, position: "fixed", bottom: "10px", right: 0};
private constructor(){
this.modals = ModalService.getInsance();
this.progressBar = ProgressBarService.getInstance();
this.ipc = IpcService.getInstance();
this.os = OsDiagnosticService.getInstance();
this.mapsQueue$.pipe(filter(queue => queue.length === 1 && !this.isDownloading)).subscribe(() => this.startDownloadMaps());
this.mapsQueue$.pipe(filter(queue => queue.length === 0)).subscribe(() => this.queueMaxLenght = 0);
}
public openDownloadMapModal(version?: BSVersion): Promise<ModalResponse<void>>{
private async startDownloadMaps(){
this.progressBar.show(this.downloadProgress$, true, this.progressBarStyle);
await timer(2000).toPromise();
while(this.mapsQueue$.value.at(0)){
const toDownload = this.mapsQueue$.value.at(0);
this.currentDownload$.next(toDownload);
const downloaded = await this.downloadMap(toDownload.map, toDownload.version);
if(downloaded){
this.downloadedListerners.forEach(func => func(toDownload.map, toDownload.version));
}
const newArr = [...this.mapsQueue$.value];
newArr.shift();
this.mapsQueue$.next(newArr);
}
await timer(500).toPromise();
return this.modals.openModal(DownloadMapsModal, version);
this.currentDownload$.next(null);
this.progressBar.hide(true);
}
private async downloadMap(map: BsvMapDetail, version: BSVersion): Promise<boolean>{
if(this.os.isOffline){ return false }
const res = await this.ipc.send("download-map", {args: {zipUrl: getMapZipUrlFromMapDetails(map), version}});
return res.success;
}
public async openDownloadMapModal(version?: BSVersion): Promise<ModalResponse<void>>{
const res = await this.modals.openModal(DownloadMapsModal, version);
this.progressBar.setStyle(null);
return res;
}
public addMapToDownload(downloadMap: MapDownload){
if(this.mapsQueue$.value.length === 0 && !this.progressBar.require()){ return; }
this.queueMaxLenght++;
this.mapsQueue$.next([...this.mapsQueue$.value, downloadMap]);
}
public removeMapToDownload(downloadMap: MapDownload){
const newArr = [...this.mapsQueue$.value];
const index = newArr.findIndex(toDownload => toDownload.map.id === downloadMap.map.id && equal(toDownload.version, downloadMap.version));
if(index < 0){ return; }
newArr.splice(index, 1);
this.mapsQueue$.next(newArr);
}
public get downloadProgress$(): Observable<ProgressionInterface> {
return this.mapsQueue$.pipe(map<MapDownload[], ProgressionInterface>(download => {
let progress = this.queueMaxLenght === 0 ? 100 : ((100 / this.queueMaxLenght) * (this.queueMaxLenght - download.length)) + .1;
progress = progress > 100 ? 100 : progress;
return {progression: (progress), label: download.at(0)?.map.name || ""};
}));
}
public get currentMapDownload$(): Observable<MapDownload> {
return this.currentDownload$.asObservable();
}
public get mapsInQueue$(): Observable<MapDownload[]>{
return this.mapsQueue$.asObservable();
}
public addOnMapDownloadedListener(func: (map: BsvMapDetail, version: BSVersion) => void){
this.downloadedListerners.push(func);
}
public removeOnMapDownloadedListene(func: (map: BsvMapDetail, version: BSVersion) => void){
const funcIndex = this.downloadedListerners.indexOf(func);
if(funcIndex < 0){ return; }
this.downloadedListerners.splice(funcIndex, 1);
}
public get isDownloading(): boolean{
return !!this.currentDownload$.value;
}
}
export interface MapDownload {
map: BsvMapDetail
version: BSVersion
}
@@ -34,12 +34,16 @@ export class MapsManagerService {
this.progressBar = ProgressBarService.getInstance();
}
public getMaps(version?: BSVersion): Observable<BsmLocalMap[]>{
public getMaps(version?: BSVersion, withDetails = true): Observable<BsmLocalMap[]>{
return new Observable(obs => {
this.ipcService.send<BsmLocalMap[], BSVersion>("get-version-maps", {args: version}).then(res => {
if(!res.success){ return obs.next(null);}
obs.next(res.data);
if(!withDetails){ return obs.complete(); }
console.log("GET DETAILS");
this.bsaver.getMapDetailsFromHashs(res.data.map(localMap => localMap.hash)).pipe(finalize(() => obs.complete())).subscribe(mapsDetails => {
mapsDetails.forEach(details => {
res.data.find(localMap => localMap.hash === details.versions.find(details => details?.hash === localMap.hash)?.hash).bsaverInfo = details
@@ -86,6 +86,11 @@ export class ProgressBarService{
return true;
}
public setStyle(style: CSSProperties){
console.log("SET STYLE", style);
this._style$.next(style);
}
public get progressData$(): Observable<ProgressionInterface>{ return this._progression$.asObservable(); }
public get progress$(): Observable<number>{ return this._progression$.pipe(map(data => data.progression)); }
public get progressLabel(): Observable<string>{ return this._progression$.pipe(map(data => data?.label)); }