[feature-107] Advancement on playlists feature

This commit is contained in:
MathieuG-P
2024-03-27 21:33:19 +01:00
parent 0460a0dab3
commit b98e1ccdfa
15 changed files with 210 additions and 94 deletions
+11 -3
View File
@@ -1,10 +1,11 @@
import { LocalBPList } from "shared/models/playlists/local-playlist.models";
import { LocalPlaylistsManagerService } from "../services/additional-content/local-playlists-manager.service";
import { IpcService } from "../services/ipc.service";
import { of } from "rxjs";
import { mergeMap, of } from "rxjs";
import { BPList } from "shared/models/playlists/playlist.interface";
import path from "path";
import { pathToFileURL } from "url";
import { LocalMapsManagerService } from "../services/additional-content/maps/local-maps-manager.service";
import { Progression } from "main/helpers/fs.helpers";
const ipc = IpcService.getInstance();
@@ -61,5 +62,12 @@ ipc.on("get-version-playlists-details", (args, reply) => {
ipc.on("delete-playlist", (args, reply) => {
const playlists = LocalPlaylistsManagerService.getInstance();
reply(playlists.deletePlaylist(args));
const maps = LocalMapsManagerService.getInstance();
reply(playlists.deletePlaylistFile(args.bpList).pipe(mergeMap(() => {
if(args.deleteMaps){
console.log("ALALALZELALZELAZELA");
return maps.deleteMapsFromHashs(args.version, args.bpList.songs.map(s => s.hash));
}
return of({ current: 0, total: 0 } as Progression);
})));
});
@@ -20,6 +20,7 @@ import { SongCacheService } from "./maps/song-cache.service";
import { InstallationLocationService } from "../installation-location.service";
import sanitize from "sanitize-filename";
import { isValidUrl } from "shared/helpers/url.helpers";
import { allSettled } from "shared/helpers/promise.helpers";
export class LocalPlaylistsManagerService {
private static instance: LocalPlaylistsManagerService;
@@ -284,34 +285,8 @@ export class LocalPlaylistsManagerService {
}
public deletePlaylist(opt: {path: string, deleteMaps?: boolean}): Observable<Progression>{
return new Observable<Progression>(obs => {
(async () => {
const bpList = await this.readPlaylistFromSource(opt.path);
const progress: Progression = { current: 0, total: opt.deleteMaps ? bpList.songs.length + 1 : 1};
if(opt.deleteMaps){
const mapsHashs = bpList.songs.map(s => ({ hash: s.hash }));
await lastValueFrom(this.maps.deleteMaps(mapsHashs).pipe(
tap({
next: () => {
progress.current += 1
obs.next(progress);
},
}),
));
}
await unlinkPath(opt.path);
progress.current += 1;
obs.next(progress);
})()
.catch(err => obs.error(err))
.finally(() => obs.complete());
});
public deletePlaylistFile(bpList: LocalBPList): Observable<void>{
return from(unlinkPath(bpList.path));
}
public oneClickInstallPlaylist(bpListUrl: string): Observable<Progression<DownloadPlaylistProgressionData>> {
@@ -26,6 +26,7 @@ import { SongCacheService } from "./song-cache.service";
import { IpcService } from "../../ipc.service";
import { pathToFileURL } from "url";
import { sToMs } from "../../../../shared/helpers/time.helpers";
import { FieldRequired } from "shared/helpers/type.helpers";
export class LocalMapsManagerService {
private static instance: LocalMapsManagerService;
@@ -236,7 +237,7 @@ export class LocalMapsManagerService {
return this.linker.unlinkFolder(versionMapsPath, { keepContents: keepMaps, intermediateFolder: LocalMapsManagerService.SHARED_MAPS_FOLDER });
}
public deleteMaps(maps: Partial<BsmLocalMap>[]): Observable<DeleteMapsProgress> {
public deleteMaps(maps: FieldRequired<BsmLocalMap, "path">[]): Observable<DeleteMapsProgress> {
return new Observable<DeleteMapsProgress>(observer => {
const progress: DeleteMapsProgress = { total: maps.length, deleted: 0 };
@@ -244,17 +245,13 @@ export class LocalMapsManagerService {
for (const map of maps) {
let mapPath = map.path;
if (!mapPath) {
const mapInfo = map.hash ? this.songCache.getMapInfoFromHash(map.hash) : null;
mapPath = mapInfo?.path;
}
if (mapPath && pathExistsSync(mapPath)) {
if (pathExistsSync(mapPath)) {
await deleteFolder(mapPath);
this.songCache.deleteMapInfoFromDirname(path.basename(mapPath));
progress.deleted++;
observer.next(progress);
}
observer.next(progress);
}
})()
.catch(e => observer.error(e))
@@ -262,6 +259,53 @@ export class LocalMapsManagerService {
});
}
public deleteMapsFromHashs(version: BSVersion, hashs: string[]): Observable<Progression> {
return new Observable<Progression>(observer => {
const progress: Progression = { total: hashs.length, current: 0 };
(async () => {
const versionMapsPath = await this.getMapsFolderPath(version);
const mapsPaths = await getFoldersInFolder(versionMapsPath);
for (const mapPath of mapsPaths) {
const mapInfo = await this.loadMapInfoFromPath(mapPath);
if (hashs.includes(mapInfo.hash)) {
await deleteFolder(mapPath);
this.songCache.deleteMapInfoFromDirname(path.basename(mapPath));
progress.current++;
}
observer.next(progress);
}
})()
.catch(e => observer.error(e))
.finally(() => observer.complete());
});
}
public async getMapInfoFromHash(hash: string, version: BSVersion): Promise<BsmLocalMap> {
const versionMapsPath = await this.getMapsFolderPath(version);
const mapInfo = this.songCache.getMapInfoFromHash(hash);
const cachedMapPath = path.join(versionMapsPath, mapInfo.dirname);
if(pathExistsSync(cachedMapPath)){
return this.loadMapInfoFromPath(cachedMapPath);
}
// if not in cache, search in the folder
const mapsPaths = await getFoldersInFolder(versionMapsPath);
for (const mapPath of mapsPaths) {
const mapInfo = await this.loadMapInfoFromPath(mapPath);
if (mapInfo.hash === hash) {
return mapInfo;
}
}
return null;
}
public async downloadMap(map: BsvMapDetail, version?: BSVersion): Promise<BsmLocalMap> {
if (!map.versions.at(0).hash) {
@@ -26,9 +26,9 @@ export class SongCacheService {
return this.rawInfosCache.get(dirname);
}
public getMapInfoFromHash(hash: string): { path: string, info: CachedRawInfoWithHash } | undefined {
public getMapInfoFromHash(hash: string): { dirname: string, info: CachedRawInfoWithHash } | undefined {
const res = Object.entries(this.rawInfosCache.cache).find(([, info]) => info.hash === hash);
return res ? { path: res[0], info: res[1] } : undefined;
return res ? { dirname: res[0], info: res[1] } : undefined;
}
public setMapInfoFromDirname(dirname: string, info: CachedRawInfoWithHash): void {