oneclick install map from bsv now work

This commit is contained in:
MathieuG-P
2022-12-18 03:41:53 +01:00
parent c626b850c9
commit bdfb7a156f
26 changed files with 394 additions and 125 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
import '@testing-library/jest-dom';
import { render } from '@testing-library/react';
import App from '../renderer/App';
import App from '../renderer/windows/App';
describe('App', () => {
it('should render', () => {
+12 -1
View File
@@ -15,7 +15,7 @@ ipcMain.on("bsv-search-map", async (event, request: IpcRequest<SearchParams>) =>
})
});
ipcMain.on("bsv-bet-map-details-from-hashs", async (event, request: IpcRequest<string[]>) => {
ipcMain.on("bsv-get-map-details-from-hashs", async (event, request: IpcRequest<string[]>) => {
const utlis = UtilsService.getInstance();
const bsvService = BeatSaverService.getInstance();
@@ -24,4 +24,15 @@ ipcMain.on("bsv-bet-map-details-from-hashs", async (event, request: IpcRequest<s
}).catch(e => {
utlis.ipcSend(request.responceChannel, {success: false, error: e});
})
});
ipcMain.on("bsv-get-map-details-by-id", async (event, request: IpcRequest<string>) => {
const utlis = UtilsService.getInstance();
const bsvService = BeatSaverService.getInstance();
bsvService.getMapDetailsById(request.args).then(maps => {
utlis.ipcSend(request.responceChannel, {success: true, data: maps});
}).catch(e => {
utlis.ipcSend(request.responceChannel, {success: false, error: e});
})
});
+12
View File
@@ -84,6 +84,18 @@ ipcMain.on("download-map", async (event, request: IpcRequest<{map: BsvMapDetail,
});
});
ipcMain.on("one-click-install-map", async (event, request: IpcRequest<BsvMapDetail>) => {
const utils = UtilsService.getInstance();
const maps = LocalMapsManagerService.getInstance();
maps.oneClickDownloadMap(request.args).then(() => {
utils.ipcSend(request.responceChannel, {success: true});
}).catch(err => {
console.log(err);
utils.ipcSend(request.responceChannel, {success: false, error: err});
});
});
ipcMain.on("register-maps-deep-link", async (event, request: IpcRequest<void>) => {
const maps = LocalMapsManagerService.getInstance();
+33 -7
View File
@@ -15,6 +15,9 @@ import './ipcs';
import { UtilsService } from './services/utils.service';
import { WindowManagerService } from './services/window-manager.service';
import { DeepLinkService } from './services/deep-link.service';
import { AppWindow } from 'shared/models/window-manager/app-window.model';
import { LocalMapsManagerService } from './services/maps/local-maps-manager.service';
import { argv } from 'process';
export const PRELOAD_PATH = app.isPackaged ? path.join(__dirname, 'preload.js') : path.join(__dirname, '../../.erb/dll/preload.js')
@@ -48,11 +51,17 @@ const installExtensions = async () => {
return installer.default(extensions.map((name) => installer[name]), forceDownload).catch(console.log);
};
const createWindow = async () => {
const createWindow = async (window: AppWindow = "launcher.html") => {
if(isDebug){ await installExtensions(); }
WindowManagerService.getInstance().openWindow("launcher.html");
WindowManagerService.getInstance().openWindow(window);
};
const initServicesMustBeInitialized = () => {
LocalMapsManagerService.getInstance();
// Playlist
// Model
}
app.on('window-all-closed', () => {
// Respect the OSX convention of having the application in memory even
// after all windows have been closed
@@ -68,9 +77,30 @@ if(!gotTheLock){
}
else{
app.on('second-instance', (e, argv) => {
const deepLink = argv.find(arg => DeepLinkService.getInstance().isDeepLink(arg));
if(!deepLink){ return; }
DeepLinkService.getInstance().dispatchLinkOpened(deepLink);
});
app.whenReady().then(() => {
//process.argv.push("beatsaver://2d133");
initServicesMustBeInitialized();
createWindow();
const deepLink = process.argv.find(arg => DeepLinkService.getInstance().isDeepLink(arg));
if(!deepLink){
createWindow();
}
else{
DeepLinkService.getInstance().dispatchLinkOpened(deepLink);
}
protocol.registerFileProtocol('file', (request, callback) => {
const pathname = decodeURI(request.url.replace('file:///', ''));
@@ -78,8 +108,4 @@ else{
});
}).catch(log.error);
app.on('open-url', (event, url) => {
DeepLinkService.getInstance().dispatchLinkOpened(url);
});
}
+15
View File
@@ -16,6 +16,8 @@ export class DeepLinkService {
private readonly listeners = new Map<string, Listerner[]>()
private constructor(){}
public registerDeepLink(protocol: string): boolean{
if(process.defaultApp && process.argv.length >= 2){
@@ -79,6 +81,19 @@ export class DeepLinkService {
}
public isDeepLink(link: string): boolean{
try{
const url = new URL(link);
const protocol = url.protocol.replace(":", "");
return Array.from(this.listeners.keys()).some(key => key === protocol);
}
catch(e){
return false;
}
}
}
type Listerner = (link: string) => void;
@@ -14,6 +14,9 @@ import sanitize from "sanitize-filename";
import archiver from "archiver";
import { DeepLinkService } from "../deep-link.service";
import log from 'electron-log';
import { WindowManagerService } from "../window-manager.service";
import { ipcMain } from "electron";
import { IpcRequest } from 'shared/models/ipc';
export class LocalMapsManagerService {
@@ -37,6 +40,7 @@ export class LocalMapsManagerService {
private readonly utils: UtilsService;
private readonly reqService: RequestService;
private readonly deepLink: DeepLinkService;
private readonly windows: WindowManagerService;
private constructor(){
this.localVersion = BSLocalVersionService.getInstance();
@@ -44,13 +48,16 @@ export class LocalMapsManagerService {
this.utils = UtilsService.getInstance();
this.reqService = RequestService.getInstance();
this.deepLink = DeepLinkService.getInstance();
this.windows = WindowManagerService.getInstance();
this.deepLink.addLinkOpenedListener(this.DEEP_LINKS.BeatSaver, (link) => {
log.info("RECEIVED FROM", this.DEEP_LINKS.BeatSaver, link);
log.info("MAP RECEIVED FROM", this.DEEP_LINKS.BeatSaver, link);
this.openOneClickDownloadMapWindow(new URL(link).host);
});
this.deepLink.addLinkOpenedListener(this.DEEP_LINKS.ScoreSaber, (link) => {
log.info("RECEIVED FROM", this.DEEP_LINKS.ScoreSaber, link);
log.info("MAP RECEIVED FROM", this.DEEP_LINKS.ScoreSaber, link);
this.openOneClickDownloadMapWindow(new URL(link).host, true);
});
}
@@ -130,6 +137,18 @@ export class LocalMapsManagerService {
}
private openOneClickDownloadMapWindow(mapId: string, isHash = false): void{
this.windows.openWindow("oneclick-download-map.html");
console.log("oui");
ipcMain.once("one-click-map-info", async (event, req: IpcRequest<void>) => {
this.utils.ipcSend(req.responceChannel, {success: true, data: {id: mapId, isHash}});
});
}
public async getMaps(version?: BSVersion): Promise<BsmLocalMap[]>{
const levelsFolder = await this.getMapsFolderPath(version);
@@ -185,6 +204,8 @@ 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);
@@ -198,11 +219,11 @@ export class LocalMapsManagerService {
}
public async downloadMap(map: BsvMapDetail, version?: BSVersion){
public async downloadMap(map: BsvMapDetail, version?: BSVersion): Promise<string>{
if(!map.versions.at(0).hash){ throw "Cannot download map, no hash found"; }
const zipUrl = `https://r2cdn.beatsaver.com/${map.versions.at(0).hash}.zip`
const zipUrl = map.versions.at(0).downloadURL;
const mapsFolder = await this.getMapsFolderPath(version);
@@ -220,6 +241,8 @@ export class LocalMapsManagerService {
await zip.close();
unlinkSync(zipPath);
return mapPath;
}
public async exportMaps(version: BSVersion, maps: BsmLocalMap[], outPath: string){
@@ -250,6 +273,32 @@ 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){
if(await this.versionIsLinked(version)){ continue; }
const versionMapsPath = await this.getMapsFolderPath(version);
this.utils.createFolderIfNotExist(versionMapsPath);
console.log(downloadedMap, path.join(versionMapsPath, path.basename(downloadedMap)));
copySync(downloadedMap, path.join(versionMapsPath, path.basename(downloadedMap)), {overwrite: true});
}
}
public enableDeepLinks(): boolean{
return Array.from(Object.values(this.DEEP_LINKS)).every(link => this.deepLink.registerDeepLink(link));
}
@@ -89,6 +89,16 @@ export class BeatSaverApiService {
}
public async getMapDetailsById(id: string): Promise<ApiResult<BsvMapDetail>>{
const res = await fetch(`${this.bsaverApiUrl}/maps/id/${id}`);
const data = await res.json() as BsvMapDetail;
return {status: res.status, data};
}
public async searchMaps(search: SearchParams): Promise<ApiResult<SearchResponse>>{
console.log(search);
@@ -47,6 +47,13 @@ export class BeatSaverService {
return mapDetails;
}
public async getMapDetailsById(id: string): Promise<BsvMapDetail>{
const res = await this.bsaverApi.getMapDetailsById(id);
return res.data;
}
public searchMaps(search: SearchParams): Promise<BsvMapDetail[]>{
return this.bsaverApi.searchMaps(search).then(res => {
+8 -4
View File
@@ -12,7 +12,8 @@ export class WindowManagerService{
private readonly appWindowsOptions: Record<AppWindow, BrowserWindowConstructorOptions> = {
"launcher.html": {width: 380, height: 500, minWidth: 380, minHeight: 500, resizable: false},
"index.html": {width: 1080, height: 720, minWidth: 900, minHeight: 500}
"index.html": {width: 1080, height: 720, minWidth: 900, minHeight: 500},
"oneclick-download-map.html": {width: 350, height: 400, minWidth: 350, minHeight: 400, resizable: false}
}
private readonly baseWindowOption: BrowserWindowConstructorOptions = {
@@ -32,15 +33,18 @@ export class WindowManagerService{
private constructor(){}
public openWindow(windowType: AppWindow): Promise<BrowserWindow>{
const window = new BrowserWindow({...this.appWindowsOptions[windowType], ...this.baseWindowOption});
public openWindow(windowType: AppWindow, options?: BrowserWindowConstructorOptions): Promise<BrowserWindow>{
const window = new BrowserWindow({...this.appWindowsOptions[windowType], ...this.baseWindowOption, ...options});
console.log({...this.appWindowsOptions[windowType], ...this.baseWindowOption, ...options});
const promise = window.loadURL(resolveHtmlPath(windowType));
window.removeMenu();
window.setMenu(null);
window.once("ready-to-show", () => {
if (!window) { throw new Error('"window" is not defined'); }
return window.show();
window.show();
});
window.once("closed", () => {
@@ -58,7 +58,7 @@ export const LocalMapsListPanel = forwardRef(({version, className, filter, searc
const handleDelete = useCallback((map: BsmLocalMap) => {
mapsManager.deleteMaps([map], version).then(res => res && loadMaps())
}, []);
}, [version]);
const extractMapDiffs = (map: BsmLocalMap): Map<BsvMapCharacteristic, ParsedMapDiff[]> => {
const res = new Map<BsvMapCharacteristic, ParsedMapDiff[]>();
@@ -14,20 +14,6 @@
align-items: center;
}
#window-controls {
display: grid;
grid-template-columns: repeat(3, 46px);
height: 100%;
}
#window-controls .button {
grid-row: 1 / span 1;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
}
#close-button:hover {
background: #E81123 !important;
@@ -2,7 +2,7 @@ import { useState } from 'react';
import { IpcService } from 'renderer/services/ipc.service';
import './title-bar.component.css'
export default function TitleBar({template = "main"} : {template?: "update"|"main"}) {
export default function TitleBar({template = "main"} : {template?: "update"|"main"|"oneclick"}) {
const ipcService = IpcService.getInstance();
@@ -30,24 +30,51 @@ export default function TitleBar({template = "main"} : {template?: "update"|"mai
setMaximized(!maximized);
}
return (
<header id="titlebar" className="min-h-[22px] bg-light-main-color-1 shrink-0 dark:bg-main-color-1 w-screen h-[22px] flex content-center items-center justify-start z-10">
<div id="drag-region" className='grow basis-0 h-full'>
{template !== "update" && (<div id="window-title" className='pl-1'>
<span className='text-gray-800 dark:text-gray-100 font-bold text-xs italic'>BSManager</span>
</div>)}
</div>
{template !== "update" && (<div id="window-controls">
<div onClick={minimizeWindow} className="button button text-gray-800 dark:text-gray-200 hover:bg-gray-300 dark:hover:bg-[#4F545C] cursor-pointer" id="min-button" >
<svg aria-hidden="false" width="12" height="12" viewBox="0 0 12 12"><rect fill="currentColor" width="10" height="1" x="1" y="6"> </rect></svg>
</div>
<div onClick={toogleMaximize} className="button text-gray-800 dark:text-gray-200 hover:bg-gray-300 dark:hover:bg-[#4F545C] cursor-pointer" id="max-button">
<svg aria-hidden="false" width="12" height="12" viewBox="0 0 12 12"><rect width="9" height="9" x="1.5" y="1.5" fill="none" stroke="currentColor"> </rect></svg>
</div>
<div onClick={closeWindow} className="button text-gray-800 dark:text-gray-200 cursor-pointer" id="close-button" draggable="false">
<svg aria-hidden="false" width="12" height="12" viewBox="0 0 12 12"><polygon fill="currentColor" fillRule="evenodd" points="11 1.576 6.583 6 11 10.424 10.424 11 6 6.583 1.576 11 1 10.424 5.417 6 1 1.576 1.576 1 6 5.417 10.424 1"> </polygon></svg>
</div>
</div>)}
</header>
)
if(template === "main"){
return (
<header id="titlebar" className="min-h-[22px] bg-light-main-color-1 shrink-0 dark:bg-main-color-1 w-screen h-[22px] flex content-center items-center justify-start z-10">
<div id="drag-region" className='grow basis-0 h-full'>
<div id="window-title" className='pl-1'>
<span className='text-gray-800 dark:text-gray-100 font-bold text-xs italic'>BSManager</span>
</div>
</div>
<div id="window-controls" className="h-full flex shrink-0">
<div onClick={minimizeWindow} className="text-gray-800 dark:text-gray-200 hover:bg-gray-300 dark:hover:bg-[#4F545C] cursor-pointer w-11 h-full shrink-0 flex justify-center items-center" id="min-button" >
<svg aria-hidden="false" width="12" height="12" viewBox="0 0 12 12"><rect fill="currentColor" width="10" height="1" x="1" y="6"> </rect></svg>
</div>
<div onClick={toogleMaximize} className="text-gray-800 dark:text-gray-200 hover:bg-gray-300 dark:hover:bg-[#4F545C] cursor-pointer w-11 h-full shrink-0 flex justify-center items-center" id="max-button">
<svg aria-hidden="false" width="12" height="12" viewBox="0 0 12 12"><rect width="9" height="9" x="1.5" y="1.5" fill="none" stroke="currentColor"> </rect></svg>
</div>
<div onClick={closeWindow} className="text-gray-800 dark:text-gray-200 cursor-pointer w-11 h-full shrink-0 flex justify-center items-center" id="close-button" draggable="false">
<svg aria-hidden="false" width="12" height="12" viewBox="0 0 12 12"><polygon fill="currentColor" fillRule="evenodd" points="11 1.576 6.583 6 11 10.424 10.424 11 6 6.583 1.576 11 1 10.424 5.417 6 1 1.576 1.576 1 6 5.417 10.424 1"> </polygon></svg>
</div>
</div>
</header>
);
}
if(template === "update"){
return (
<header id="titlebar" className="min-h-[22px] bg-transparent w-screen h-[22px] z-10">
<div id="drag-region" className='grow basis-0 h-full'></div>
</header>
)
}
if(template === "oneclick"){
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'>
<div id="window-title" className='pl-1'>
<span className='text-gray-100 font-bold text-xs italic'>BSManager</span>
</div>
</div>
<div id="window-controls" className="h-full flex shrink-0">
<div onClick={closeWindow} className="text-gray-200 cursor-pointer w-7 h-full shrink-0 flex justify-center items-center rounded-bl-md" id="close-button" draggable="false">
<svg aria-hidden="false" width="12" height="12" viewBox="0 0 12 12"><polygon fill="currentColor" fillRule="evenodd" points="11 1.576 6.583 6 11 10.424 10.424 11 6 6.583 1.576 11 1 10.424 5.417 6 1 1.576 1.576 1 6 5.417 10.424 1"> </polygon></svg>
</div>
</div>
</header>
);
}
}
+5
View File
@@ -7,6 +7,11 @@
font-family: acumin-pro, sans-serif;
}
html, body{
margin: 0; padding: 0;
box-sizing: border-box;
}
html.dark{
background-color: #202225;
}
+7 -2
View File
@@ -1,16 +1,21 @@
//@ts-ignore
import { createRoot } from 'react-dom/client';
import { HashRouter } from 'react-router-dom';
import App from './App';
import Launcher from './Launcher';
import App from './windows/App';
import Launcher from './windows/Launcher';
import 'tailwindcss/tailwind.css';
import './index.css'
import OneClickDownloadMap from './windows/OneClick/OneClickDownloadMap';
const launcherContainer = document.getElementById('launcher');
const oneclickDownloadMapContainer = document.getElementById('oneclick-download-map');
if(!!launcherContainer){
createRoot(launcherContainer).render(<Launcher/>)
}
else if(!!oneclickDownloadMapContainer){
createRoot(oneclickDownloadMapContainer).render(<OneClickDownloadMap/>)
}
else{
const root = document.getElementById('root');
createRoot(root).render(
+14
View File
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://use.typekit.net/okr8ven.css">
<meta charset="utf-8" />
<meta
http-equiv="Content-Security-Policy"
content="script-src 'self' 'unsafe-inline'"
/>
</head>
<body>
<div id="oneclick-download-map"></div>
</body>
</html>
@@ -122,6 +122,16 @@ export class MapsDownloaderService {
this.downloadedListerners.splice(funcIndex, 1);
}
public async oneClickInstallMap(map: BsvMapDetail): Promise<boolean>{
this.progressBar.showFake(0.008);
const res = await this.ipc.send<void, BsvMapDetail>("one-click-install-map", {args: map});
return res.success;
}
public get isDownloading(): boolean{
return !!this.currentDownload$.value;
}
@@ -1,6 +1,5 @@
import { LinkMapsModal } from "renderer/components/modal/modal-types/link-maps-modal.component";
import { UnlinkMapsModal } from "renderer/components/modal/modal-types/unlink-maps-modal.component";
import { finalize } from "rxjs/operators";
import { Subject, Observable } from "rxjs";
import { BSVersion } from "shared/bs-version.interface";
import { BsmLocalMap } from "shared/models/maps/bsm-local-map.interface";
@@ -4,6 +4,8 @@ import { IpcService } from "./ipc.service";
import { NotificationService } from "./notification.service";
import { CSSProperties } from "react";
import { ProgressionInterface } from "shared/models/progress-bar";
import { from } from "rxjs";
import { of } from "rxjs";
export class ProgressBarService{
@@ -73,6 +75,10 @@ export class ProgressBarService{
this._progression$.next({progression: 100});
}
public open(): void{
this.show(of(0), true, this._style$.value);
}
public hide(unsubscribe: boolean = true){
if(unsubscribe){ this.unsubscribe(); }
this._visible$.next(false);
@@ -17,10 +17,16 @@ export class BeatSaverService {
}
public async getMapDetailsFromHashs(hashs: string[]): Promise<BsvMapDetail[]>{
const res = await this.ipc.send<BsvMapDetail[], string[]>("bsv-bet-map-details-from-hashs", {args: hashs});
const res = await this.ipc.send<BsvMapDetail[], string[]>("bsv-get-map-details-from-hashs", {args: hashs});
return res.data ?? [];
}
public async getMapDetailsById(id: string): Promise<BsvMapDetail>{
const res = await this.ipc.send<BsvMapDetail, string>("bsv-get-map-details-by-id", {args: id});
return res.data ?? null;
}
public async searchMaps(search: SearchParams): Promise<BsvMapDetail[]>{
const res = await this.ipc.send<BsvMapDetail[], SearchParams>("bsv-search-map", {args: search});
return res.data ?? []
@@ -1,18 +1,18 @@
import { NavBar } from "./components/nav-bar/nav-bar.component";
import TitleBar from "./components/title-bar/title-bar.component";
import { NavBar } from "../components/nav-bar/nav-bar.component";
import TitleBar from "../components/title-bar/title-bar.component";
import { Routes, Route, useLocation } from "react-router-dom";
import { AvailableVersionsList } from "./pages/available-versions-list.components";
import { VersionViewer } from "./pages/version-viewer.component";
import { Modal } from "./components/modal/modal.component";
import { SettingsPage } from "./pages/settings-page.component";
import { BsmProgressBar } from "./components/progress-bar/bsm-progress-bar.component";
import { AvailableVersionsList } from "../pages/available-versions-list.components";
import { VersionViewer } from "../pages/version-viewer.component";
import { Modal } from "../components/modal/modal.component";
import { SettingsPage } from "../pages/settings-page.component";
import { BsmProgressBar } from "../components/progress-bar/bsm-progress-bar.component";
import { useEffect } from "react";
import { ThemeService } from "./services/theme.service";
import { NotificationOverlay } from "./components/notification/notification-overlay.component";
import { PageStateService } from "./services/page-state.service";
import { MapsPage } from "./pages/maps-page.component";
import { ThemeService } from "../services/theme.service";
import { NotificationOverlay } from "../components/notification/notification-overlay.component";
import { PageStateService } from "../services/page-state.service";
import { MapsPage } from "../pages/maps-page.component";
import "tailwindcss/tailwind.css";
import { BsmIframeView } from "./components/shared/bsm-map-preview.component";
import { BsmIframeView } from "../components/shared/bsm-map-preview.component";
import 'tippy.js/dist/tippy.css';
export default function App() {
@@ -1,12 +1,12 @@
import { motion } from "framer-motion";
import { useEffect, useRef, useState } from "react";
import { BsManagerIcon } from "./components/nav-bar/bsmanager-icon.component";
import { BsmProgressBar } from "./components/progress-bar/bsm-progress-bar.component";
import TitleBar from "./components/title-bar/title-bar.component";
import { useTranslation } from "./hooks/use-translation.hook";
import { AutoUpdaterService } from "./services/auto-updater.service";
import { ThemeService } from "./services/theme.service";
import { WindowManagerService } from "./services/window-manager.service";
import { BsManagerIcon } from "../components/nav-bar/bsmanager-icon.component";
import { BsmProgressBar } from "../components/progress-bar/bsm-progress-bar.component";
import TitleBar from "../components/title-bar/title-bar.component";
import { useTranslation } from "../hooks/use-translation.hook";
import { AutoUpdaterService } from "../services/auto-updater.service";
import { ThemeService } from "../services/theme.service";
import { WindowManagerService } from "../services/window-manager.service";
export default function Launcher() {
@@ -22,6 +22,7 @@ export default function Launcher() {
useEffect(() => {
const sub = themeService.theme$.subscribe(() => {
if(themeService.isDark || (themeService.isOS && window.matchMedia('(prefers-color-scheme: dark)').matches)){ document.documentElement.classList.add('dark'); }
else { document.documentElement.classList.remove('dark'); }
@@ -0,0 +1,75 @@
import { useEffect, 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 { IpcService } from "renderer/services/ipc.service";
import { MapsDownloaderService } from "renderer/services/maps-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 { BsvMapDetail } from "shared/models/maps";
import defaultImage from '../../../../assets/images/default-version-img.jpg'
export default function OneClickDownloadMap() {
const ipc = IpcService.getInstance();
const bsv = BeatSaverService.getInstance();
const mapsDownloader = MapsDownloaderService.getInstance();
const themeService = ThemeService.getInstance();
const progressBar = ProgressBarService.getInstance();
const [mapInfo, setMapInfo] = useState<BsvMapDetail>(null);
const cover = mapInfo ? mapInfo.versions.at(0).coverURL : null;
useEffect(() => {
const sub = themeService.theme$.subscribe(() => {
if(themeService.isDark || (themeService.isOS && window.matchMedia('(prefers-color-scheme: dark)').matches)){ document.documentElement.classList.add('dark'); }
else { document.documentElement.classList.remove('dark'); }
});
progressBar.open();
ipc.send<{id: string, isHash: boolean}>("one-click-map-info").then(res => {
console.log(res);
if(res.data.isHash){
return bsv.getMapDetailsFromHashs([res.data.id]).then(res => setMapInfo(() => res.at(0)));
}
bsv.getMapDetailsById(res.data.id).then(async map => {
setMapInfo(() => map);
mapsDownloader.oneClickInstallMap(map).finally(() => ipc.sendLazy('window.close'));
});
});
return () => {
sub.unsubscribe();
}
}, [])
console.log(mapInfo);
return (
<div className="relative w-screen h-screen overflow-hidden">
<div className="w-full h-full absolute top-0 left-0">
<BsmImage className="absolute top-0 left-0 w-full h-full object-cover bg-center" placeholder={defaultImage} image={cover}/>
</div>
<div className="w-full h-full absolute top-0 left-0 backdrop-blur-md backdrop-brightness-50 flex flex-col justify-start items-center gap-10">
<TitleBar template="oneclick"/>
<BsmImage className="aspect-square w-1/2 object-cover rounded-md bg-center shadow-black shadow-lg" placeholder={defaultImage} image={cover}/>
<h1 className="font-bold italic text-xl text-gray-200 tracking-wide">{mapInfo?.name ?? "Chargement de la map..."}</h1>
</div>
<BsmProgressBar/>
</div>
)
}
@@ -1 +1,5 @@
export type AppWindow = "index.html" | "launcher.html";
export type AppWindow = (
"index.html" |
"launcher.html" |
"oneclick-download-map.html"
);