mirror of
https://github.com/Zagrios/bs-manager.git
synced 2026-07-03 14:08:25 +02:00
one click install playlist working
This commit is contained in:
@@ -5,15 +5,10 @@ import { UtilsService } from "../services/utils.service";
|
||||
|
||||
ipcMain.on("one-click-install-playlist", async (event, request: IpcRequest<string>) => {
|
||||
|
||||
console.log("OUI");
|
||||
|
||||
const utils = UtilsService.getInstance();
|
||||
const playlists = LocalPlaylistsManagerService.getInstance();
|
||||
|
||||
console.log(request.args);
|
||||
|
||||
playlists.oneClickInstallPlaylist(request.args).then(() => {
|
||||
console.log("C FINI");
|
||||
utils.ipcSend(request.responceChannel, {success: true});
|
||||
}).catch(e => {
|
||||
console.log(e);
|
||||
|
||||
+1
-1
@@ -89,7 +89,7 @@ else{
|
||||
|
||||
app.whenReady().then(() => {
|
||||
|
||||
process.argv.push("bsplaylist://playlist/https://api.beatsaver.com/playlists/id/11137/download/beatsaver-11137.bplist"); // to force deep-link (oneClick map)
|
||||
process.argv.push("bsplaylist://playlist/https://api.beatsaver.com/playlists/id/11199/download/beatsaver-11199.bplist"); // to force deep-link (oneClick map)
|
||||
|
||||
initServicesMustBeInitialized();
|
||||
|
||||
|
||||
@@ -202,8 +202,6 @@ export class LocalMapsManagerService {
|
||||
}
|
||||
|
||||
public async deleteMaps(maps: BsmLocalMap[], verion?: BSVersion){
|
||||
|
||||
console.log(verion);
|
||||
|
||||
const mapsFolders = await this.getAbsoluteFolderOfMaps(maps, verion);
|
||||
const mapsHashsToDelete = maps.map(map => map.hash);
|
||||
@@ -273,12 +271,8 @@ export class LocalMapsManagerService {
|
||||
|
||||
public async oneClickDownloadMap(map: BsvMapDetail): Promise<void>{
|
||||
|
||||
console.log("AALLLOO");
|
||||
|
||||
const downloadedMap = await this.downloadMap(map);
|
||||
|
||||
console.log(downloadedMap);
|
||||
|
||||
const versions = await this.localVersion.getInstalledVersions();
|
||||
|
||||
for(const version of versions){
|
||||
@@ -289,8 +283,6 @@ export class LocalMapsManagerService {
|
||||
|
||||
this.utils.createFolderIfNotExist(versionMapsPath);
|
||||
|
||||
console.log(downloadedMap, path.join(versionMapsPath, path.basename(downloadedMap)));
|
||||
|
||||
copySync(downloadedMap, path.join(versionMapsPath, path.basename(downloadedMap)), {overwrite: true});
|
||||
|
||||
}
|
||||
|
||||
@@ -91,13 +91,9 @@ export class LocalPlaylistsManagerService {
|
||||
|
||||
const playlistFolder = await this.getPlaylistsFolder(version);
|
||||
|
||||
const bpListDest = path.join(playlistFolder, path.basename(bpListUrlOrPath));
|
||||
|
||||
console.log("INSTALL BPLIST", bpListUrlOrPath, playlistFolder);
|
||||
const bpListDest = path.join(playlistFolder, path.basename(bpListUrlOrPath));
|
||||
|
||||
if(this.utils.pathExist(bpListUrlOrPath)){
|
||||
console.log("PATH EXIST", bpListUrlOrPath);
|
||||
console.log("COPY", bpListUrlOrPath, bpListDest);
|
||||
copyFileSync(bpListUrlOrPath, bpListDest);
|
||||
}
|
||||
else{
|
||||
@@ -131,12 +127,9 @@ export class LocalPlaylistsManagerService {
|
||||
|
||||
public downloadPlaylist(bpListUrl: string, version: BSVersion): Observable<DownloadPlaylistProgression>{
|
||||
|
||||
console.log("DOWNLOAD PLAYLIST");
|
||||
|
||||
const res = new BehaviorSubject<DownloadPlaylistProgression>({progression: 0, current: null, downloadedMaps: [], mapsPath: [], bpListPath: ""});
|
||||
|
||||
const sub = res.subscribe(process => {
|
||||
console.log("PROGRESS", process);
|
||||
this.utils.ipcSend("download-playlist-progress", {success: true, data: process});
|
||||
}, err => {
|
||||
this.utils.ipcSend("download-playlist-progress", {success: false, error: err});
|
||||
@@ -169,7 +162,8 @@ export class LocalPlaylistsManagerService {
|
||||
const progression = ((res.value.downloadedMaps.length + 1) / bpList.songs.length) * 100;
|
||||
|
||||
res.next({
|
||||
...res.value,
|
||||
...res.value,
|
||||
current: null,
|
||||
downloadedMaps: [...res.value.downloadedMaps, map],
|
||||
mapsPath: [...res.value.mapsPath, mapPath],
|
||||
progression
|
||||
@@ -195,8 +189,6 @@ export class LocalPlaylistsManagerService {
|
||||
|
||||
const versions = await this.versions.getInstalledVersions();
|
||||
|
||||
await timer(2);
|
||||
|
||||
const firstVersion = versions.shift();
|
||||
const fistVersionLinked = await this.maps.versionIsLinked(firstVersion);
|
||||
|
||||
@@ -214,8 +206,6 @@ export class LocalPlaylistsManagerService {
|
||||
const versionMapsFolder = await this.maps.getMapsFolderPath(version);
|
||||
const mapDest = path.join(versionMapsFolder, path.basename(mapPath));
|
||||
|
||||
console.log("COPY MAP", mapPath, mapDest);
|
||||
|
||||
copySync(mapPath, mapDest, {overwrite: true});
|
||||
}
|
||||
|
||||
|
||||
@@ -98,10 +98,8 @@ export class UtilsService{
|
||||
|
||||
public ipcSend<T = any>(channel: string, response: IpcResponse<T>): void{
|
||||
try {
|
||||
console.log(channel, ...Array.from(this.windows.keys()), response);
|
||||
Array.from(this.windows.values()).forEach(window => window.webContents.send(channel, response));
|
||||
} catch (error) {
|
||||
console.log("ERREUR", error);
|
||||
log.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ export default function TitleBar({template = "index.html"} : {template: AppWindo
|
||||
</header>
|
||||
)
|
||||
}
|
||||
if(template === "oneclick-download-map.html"){
|
||||
if(template === "oneclick-download-map.html" || template === "oneclick-download-playlist.html"){
|
||||
return (
|
||||
<header id="titlebar" className="min-h-[22px] bg-transparent w-screen h-[22px] flex content-center items-center justify-start z-10">
|
||||
<div id="drag-region" className='grow h-full'>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Observable } from "rxjs";
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
export function useObservable<T>(observable: Observable<T>): T{
|
||||
const [obsValue, setObsValue] = useState(null as T);
|
||||
export function useObservable<T>(observable: Observable<T>, defaultValue?: T): T{
|
||||
const [obsValue, setObsValue] = useState(defaultValue ?? null as T);
|
||||
|
||||
useEffect(() => {
|
||||
const sub = observable.subscribe(val => setObsValue(() => val));
|
||||
|
||||
@@ -34,17 +34,10 @@ export class IpcService {
|
||||
}
|
||||
|
||||
public watch<T>(channel: string): Observable<IpcResponse<T>>{
|
||||
console.log("watch", channel);
|
||||
if(this.channelObservables.has(channel)){ return this.channelObservables.get(channel) as Observable<IpcResponse<T>>; }
|
||||
console.log("allo");
|
||||
|
||||
window.electron.ipcRenderer.on(channel, (res: IpcResponse<T>) => {
|
||||
console.log("oui", res);
|
||||
});
|
||||
|
||||
const obs = new Observable<IpcResponse<T>>(observer => {
|
||||
window.electron.ipcRenderer.on(channel, (res: IpcResponse<T>) => {
|
||||
console.log("oui", res);
|
||||
observer.next(res);
|
||||
});
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { map, multicast, tap } from "rxjs/operators";
|
||||
import { map } from "rxjs/operators";
|
||||
import { Observable, Subject } from "rxjs";
|
||||
import { DownloadPlaylistProgression } from "shared/models/playlists/playlist.interface";
|
||||
import { IpcService } from "./ipc.service";
|
||||
@@ -34,18 +34,31 @@ export class PlaylistDownloaderService{
|
||||
}));
|
||||
}
|
||||
|
||||
public get progress$(): Observable<DownloadPlaylistProgression>{
|
||||
return this.progressWatcher$.asObservable();
|
||||
}
|
||||
|
||||
public oneClickInstallPlaylist(bpListUrl: string): Observable<DownloadPlaylistProgression>{
|
||||
|
||||
if(!this.progress.require()){ return null; }
|
||||
|
||||
this.progressWatcher$.next(null);
|
||||
|
||||
const res = new Subject<DownloadPlaylistProgression>();
|
||||
|
||||
this.progress.show(this.downloadProgression$, true);
|
||||
|
||||
const sub = this.progressWatcher$.subscribe(progress => {console.log("progress"); res.next(progress)})
|
||||
const sub = this.progressWatcher$.subscribe(progress => {
|
||||
res.next(progress);
|
||||
if(progress.progression === 100){
|
||||
this.progress.showFake(0.08);
|
||||
}
|
||||
})
|
||||
|
||||
this.ipc.send<void, string>("one-click-install-playlist", {args: bpListUrl}).then(oneClickRes => {
|
||||
sub.unsubscribe();
|
||||
this.progress.hide(true);
|
||||
this.progressWatcher$.next(null);
|
||||
if(!oneClickRes.success){
|
||||
return res.error(oneClickRes.error);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import { useEffect, useState } from "react"
|
||||
import { motion } from "framer-motion";
|
||||
import { useEffect, useRef, useState } from "react"
|
||||
import { BsmProgressBar } from "renderer/components/progress-bar/bsm-progress-bar.component";
|
||||
import { BsmImage } from "renderer/components/shared/bsm-image.component";
|
||||
import TitleBar from "renderer/components/title-bar/title-bar.component";
|
||||
import { useObservable } from "renderer/hooks/use-observable.hook";
|
||||
import { IpcService } from "renderer/services/ipc.service"
|
||||
import { PlaylistDownloaderService } from "renderer/services/playlist-downloader.service";
|
||||
import { ProgressBarService } from "renderer/services/progress-bar.service";
|
||||
import { ThemeService } from "renderer/services/theme.service";
|
||||
import { BeatSaverService } from "renderer/services/thrird-partys/beat-saver.service";
|
||||
import { WindowManagerService } from "renderer/services/window-manager.service";
|
||||
import { map, filter } from "rxjs/operators";
|
||||
import { BsvPlaylist } from "shared/models/maps/beat-saver.model";
|
||||
import defaultImage from '../../../../assets/images/default-version-img.jpg';
|
||||
|
||||
@@ -14,14 +17,16 @@ export default function OneClickDownloadPlaylist() {
|
||||
|
||||
const ipc = IpcService.getInstance();
|
||||
const bSaver = BeatSaverService.getInstance();
|
||||
const progress = ProgressBarService.getInstance();
|
||||
const themeService = ThemeService.getInstance();
|
||||
const playlistDownloader = PlaylistDownloaderService.getInstance();
|
||||
const mapsContainer = useRef<HTMLDivElement>(null);
|
||||
const windows = WindowManagerService.getInstance();
|
||||
|
||||
const [playlist, setPlaylist] = useState<BsvPlaylist>(null);
|
||||
const downloadedMap = useObservable(playlistDownloader.progress$.pipe(filter(download => !!download), map(download => [...(download.downloadedMaps ?? []), download?.current])), []);
|
||||
|
||||
const cover = playlist ? playlist.playlistImage : null;
|
||||
const title = playlist ? playlist.name : null
|
||||
const title = playlist ? playlist.name : null;
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -40,26 +45,40 @@ export default function OneClickDownloadPlaylist() {
|
||||
|
||||
const res = await playlistDownloader.oneClickInstallPlaylist(infos.data.bpListUrl).toPromise();
|
||||
|
||||
console.log("OMG C FINI");
|
||||
|
||||
resolve(res);
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
promise.finally(() => {
|
||||
sub.unsubscribe();
|
||||
windows.close("oneclick-download-playlist.html");
|
||||
})
|
||||
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => mapsContainer.current.scrollTo({
|
||||
left: mapsContainer.current.scrollWidth,
|
||||
behavior: "smooth"
|
||||
}), 500);
|
||||
}, [downloadedMap])
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<div className="relative w-screen h-screen overflow-hidden">
|
||||
{playlist && <BsmImage className="absolute top-0 left-0 w-full h-full" image={playlist.playlistImage}/>}
|
||||
<div className="w-full h-full backdrop-brightness-50 backdrop-blur-md flex flex-col justify-start items-center gap-10">
|
||||
<TitleBar template="oneclick-download-map.html"/>
|
||||
<BsmImage className="aspect-square w-1/2 object-cover rounded-md shadow-black shadow-lg" placeholder={defaultImage} image={cover} errorImage={defaultImage}/>
|
||||
<h1 className="overflow-hidden font-bold italic text-xl text-gray-200 tracking-wide w-full text-center whitespace-nowrap text-ellipsis px-2">{title}</h1>
|
||||
<div className="w-full h-full backdrop-brightness-50 backdrop-blur-md flex flex-col justify-start items-center">
|
||||
<TitleBar template="oneclick-download-playlist.html"/>
|
||||
<BsmImage className="mt-2 aspect-square w-1/2 object-cover rounded-md shadow-black shadow-lg" placeholder={defaultImage} image={cover} errorImage={defaultImage}/>
|
||||
<h1 className="mt-4 overflow-hidden font-bold italic text-xl text-gray-200 tracking-wide w-full text-center whitespace-nowrap text-ellipsis px-2">{title}</h1>
|
||||
<div className="w-full py-3 flex items-center justify-center max-w-full overflow-x-scroll overflow-y-hidden scrollbar scrollbar-thin scrollbar-track-transparent scrollbar-thumb-neutral-900" ref={mapsContainer}>
|
||||
<div className="flex justify-start items-start gap-2.5">
|
||||
{downloadedMap?.map(map => (
|
||||
map?.versions?.at(0)?.coverURL && <motion.img layout="position" key={map.id} className="block aspect-square w-14 object-cover rounded-md shadow-black shadow-md" src={map?.versions?.at(0)?.coverURL} initial={{scale: 0}} animate={{scale: 1}} whileHover={{rotate: 5}}/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<BsmProgressBar/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user