diff --git a/src/main/ipcs/os-controls-ipcs.ts b/src/main/ipcs/os-controls-ipcs.ts index 8af72c06..a5b42525 100644 --- a/src/main/ipcs/os-controls-ipcs.ts +++ b/src/main/ipcs/os-controls-ipcs.ts @@ -1,4 +1,4 @@ -import { ipcMain, shell, dialog, app } from "electron"; +import { ipcMain, shell, dialog, app, BrowserWindow } from "electron"; import { UtilsService } from "../services/utils.service"; import { IpcRequest } from "shared/models/ipc"; import { SystemNotificationOptions } from "shared/models/notification/system-notification.model"; @@ -11,21 +11,6 @@ import { from, of } from "rxjs"; const ipc = IpcService.getInstance(); -ipcMain.on("window.maximize", async () => { - const utils = UtilsService.getInstance(); - utils.getMainWindows("index.html")?.maximize(); -}); - -ipcMain.on("window.minimize", async () => { - const utils = UtilsService.getInstance(); - utils.getMainWindows("index.html")?.minimize(); -}); - -ipcMain.on("window.reset", async () => { - const utils = UtilsService.getInstance(); - utils.getMainWindows("index.html")?.restore(); -}); - ipcMain.on("new-window", async (event, request: IpcRequest) => { shell.openExternal(request.args); }); @@ -35,8 +20,7 @@ ipc.on("choose-folder", async (req, reply) => { }); ipcMain.on("window.progression", async (event, request: IpcRequest) => { - const utils = UtilsService.getInstance(); - utils.getMainWindows("index.html")?.setProgressBar(request.args / 100); + BrowserWindow.fromWebContents(event.sender)?.setProgressBar(request.args / 100); }); ipcMain.on("save-file", async (event, request: IpcRequest<{ filename?: string; filters?: Electron.FileFilter[] }>) => { diff --git a/src/main/ipcs/window-manager-ipcs.ts b/src/main/ipcs/window-manager-ipcs.ts index 791b2753..94b54e6e 100644 --- a/src/main/ipcs/window-manager-ipcs.ts +++ b/src/main/ipcs/window-manager-ipcs.ts @@ -1,12 +1,29 @@ import { WindowManagerService } from "../services/window-manager.service"; import { AppWindow } from "shared/models/window-manager/app-window.model"; -import { BSLauncherService } from "../services/bs-launcher.service"; import { IpcService } from "../services/ipc.service"; -import { from, of } from "rxjs"; +import { from } from "rxjs"; +import { BrowserWindow, ipcMain } from "electron"; -const launcher = BSLauncherService.getInstance(); const ipc = IpcService.getInstance(); +// Native windows control, do not pass through IPC service +ipcMain.on("close-window", async (event) => { + BrowserWindow.fromWebContents(event.sender)?.close(); +}); + +ipcMain.on("maximise-window", async (event) => { + BrowserWindow.fromWebContents(event.sender)?.maximize(); +}); + +ipcMain.on("minimise-window", async (event) => { + BrowserWindow.fromWebContents(event.sender)?.minimize(); +}); + +ipcMain.on("unmaximise-window", async (event) => { + BrowserWindow.fromWebContents(event.sender)?.unmaximize(); +}); + + ipc.on("open-window-then-close-all", (req, reply) => { const windowManager = WindowManagerService.getInstance(); @@ -17,18 +34,6 @@ ipc.on("open-window-then-close-all", (req, reply) => { reply(from(res)); }); -ipc.on("close-all-windows", async (req, reply) => { - await launcher.restoreSteamVR(); - const windowManager = WindowManagerService.getInstance(); - reply(of(windowManager.closeAllWindows(req.args))); -}); - -ipc.on("close-windows", async (req, reply) => { - await launcher.restoreSteamVR(); - const windowManager = WindowManagerService.getInstance(); - reply(of(windowManager.close(...req.args))); -}); - ipc.on("open-window-or-focus", (req, reply) => { const windowManager = WindowManagerService.getInstance(); reply(from(windowManager.openWindowOrFocus(req.args))); diff --git a/src/main/main.ts b/src/main/main.ts index 2271cd00..b7525d88 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -83,6 +83,11 @@ if (!gotTheLock) { DeepLinkService.getInstance().dispatchLinkOpened(deepLink); }); + app.on("window-all-closed", () => { + if (process.platform === "darwin") { return; } + app.quit(); + }) + app.whenReady().then(() => { app.setAppUserModelId(APP_NAME); diff --git a/src/main/preload.ts b/src/main/preload.ts index 61ced3c1..ca0f53b1 100644 --- a/src/main/preload.ts +++ b/src/main/preload.ts @@ -26,5 +26,12 @@ contextBridge.exposeInMainWorld("electron", { join: (...args: string[]): string => { return args.join(sep); } + }, + window: { + close: () => { ipcRenderer.send("close-window"); }, + minimise: () => { ipcRenderer.send("minimise-window"); }, + maximise: () => { ipcRenderer.send("maximise-window"); }, + unmaximise: () => { ipcRenderer.send("unmaximise-window"); }, } -}); + +}); \ No newline at end of file diff --git a/src/main/services/additional-content/local-maps-manager.service.ts b/src/main/services/additional-content/local-maps-manager.service.ts index 3b3c1b29..426393d2 100644 --- a/src/main/services/additional-content/local-maps-manager.service.ts +++ b/src/main/services/additional-content/local-maps-manager.service.ts @@ -14,15 +14,14 @@ import sanitize from "sanitize-filename"; 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"; -import { Observable, lastValueFrom } from "rxjs"; +import { Observable, lastValueFrom, of } from "rxjs"; import { Archive } from "../../models/archive.class"; import { deleteFolder, ensureFolderExist, getFilesInFolder, getFoldersInFolder, pathExist } from "../../helpers/fs.helpers"; import { readFile } from "fs/promises"; import { FolderLinkerService } from "../folder-linker.service"; import { allSettled } from "../../../shared/helpers/promise.helpers"; import { splitIntoChunk } from "../../../shared/helpers/array.helpers"; +import { IpcService } from "../ipc.service"; export class LocalMapsManagerService { private static instance: LocalMapsManagerService; @@ -49,6 +48,7 @@ export class LocalMapsManagerService { private readonly reqService: RequestService; private readonly deepLink: DeepLinkService; private readonly windows: WindowManagerService; + private readonly ipc: IpcService; private readonly linker = FolderLinkerService.getInstance(); private constructor() { @@ -59,6 +59,7 @@ export class LocalMapsManagerService { this.deepLink = DeepLinkService.getInstance(); this.windows = WindowManagerService.getInstance(); this.linker = FolderLinkerService.getInstance(); + this.ipc = IpcService.getInstance(); this.deepLink.addLinkOpenedListener(this.DEEP_LINKS.BeatSaver, link => { log.info("DEEP-LINK RECEIVED FROM", this.DEEP_LINKS.BeatSaver, link); @@ -126,7 +127,7 @@ export class LocalMapsManagerService { } private async downloadMapZip(zipUrl: string): Promise<{ zip: StreamZip.StreamZipAsync; zipPath: string }> { - const fileName = path.basename(zipUrl); + const fileName = `${path.basename(zipUrl, ".zip")}-${crypto.randomUUID()}.zip`; const tempPath = this.utils.getTempPath(); await ensureFolderExist(this.utils.getTempPath()); const dest = path.join(tempPath, fileName); @@ -138,11 +139,15 @@ export class LocalMapsManagerService { } private openOneClickDownloadMapWindow(mapId: string, isHash = false): void { - ipcMain.once("one-click-map-info", async (event, req: IpcRequest) => { - this.utils.ipcSend(req.responceChannel, { success: true, data: { id: mapId, isHash } }); + this.windows.openWindow("oneclick-download-map.html").then(window => { + + this.ipc.once("one-click-map-info", async (_, reply) => { + reply(of({ id: mapId, isHash })); + }, window.webContents.ipc); + }); - this.windows.openWindow("oneclick-download-map.html"); + } public getMaps(version?: BSVersion): Observable { diff --git a/src/main/services/additional-content/local-models-manager.service.ts b/src/main/services/additional-content/local-models-manager.service.ts index bdaead49..7365f28f 100644 --- a/src/main/services/additional-content/local-models-manager.service.ts +++ b/src/main/services/additional-content/local-models-manager.service.ts @@ -1,8 +1,5 @@ import { DeepLinkService } from "../deep-link.service"; import log from "electron-log"; -import { ipcMain } from "electron"; -import { IpcRequest } from "shared/models/ipc"; -import { UtilsService } from "../utils.service"; import { WindowManagerService } from "../window-manager.service"; import { MSModel, MSModelType } from "../../../shared/models/models/model-saber.model"; import { BSVersion } from "shared/bs-version.interface"; @@ -14,13 +11,14 @@ import sanitize from "sanitize-filename"; import { Progression, ensureFolderExist, unlinkPath } from "../../helpers/fs.helpers"; import { MODEL_FILE_EXTENSIONS, MODEL_TYPES, MODEL_TYPE_FOLDERS } from "../../../shared/models/models/constants"; import { InstallationLocationService } from "../installation-location.service"; -import { Observable, Subscription, lastValueFrom } from "rxjs"; +import { Observable, Subscription, lastValueFrom, of } from "rxjs"; import { readdir } from "fs/promises"; import md5File from "md5-file"; import { allSettled } from "../../../shared/helpers/promise.helpers"; import { ModelSaberService } from "../thrid-party/model-saber/model-saber.service"; import { BsmLocalModel } from "shared/models/models/bsm-local-model.interface"; import { Archive } from "../../models/archive.class"; +import { IpcService } from "../ipc.service"; export class LocalModelsManagerService { private static instance: LocalModelsManagerService; @@ -37,21 +35,21 @@ export class LocalModelsManagerService { }; private readonly deepLink: DeepLinkService; - private readonly utils: UtilsService; private readonly windows: WindowManagerService; private readonly localVersion: BSLocalVersionService; private readonly installPaths: InstallationLocationService; private readonly request: RequestService; private readonly modelSaber: ModelSaberService; + private readonly ipc: IpcService; private constructor() { this.deepLink = DeepLinkService.getInstance(); - this.utils = UtilsService.getInstance(); this.windows = WindowManagerService.getInstance(); this.localVersion = BSLocalVersionService.getInstance(); this.request = RequestService.getInstance(); this.installPaths = InstallationLocationService.getInstance(); this.modelSaber = ModelSaberService.getInstance(); + this.ipc = IpcService.getInstance(); this.deepLink.addLinkOpenedListener(this.DEEP_LINKS.ModelSaber, link => { log.info("DEEP-LINK RECEIVED FROM", this.DEEP_LINKS.ModelSaber, link); @@ -65,11 +63,13 @@ export class LocalModelsManagerService { } private openOneClickDownloadModelWindow(id: string, type: string) { - ipcMain.once("one-click-model-info", async (_event, req: IpcRequest) => { - this.utils.ipcSend(req.responceChannel, { success: true, data: { id, type } }); - }); + this.windows.openWindow("oneclick-download-model.html").then(window => { - this.windows.openWindow("oneclick-download-model.html"); + this.ipc.once("one-click-model-info", (_, reply) => { + reply(of({ id, type })); + }, window.webContents.ipc); + + }); } private async getModelFolderPath(type: MSModelType, version?: BSVersion): Promise { diff --git a/src/main/services/additional-content/local-playlists-manager.service.ts b/src/main/services/additional-content/local-playlists-manager.service.ts index d9621f80..4e713c5a 100644 --- a/src/main/services/additional-content/local-playlists-manager.service.ts +++ b/src/main/services/additional-content/local-playlists-manager.service.ts @@ -1,5 +1,5 @@ import path from "path"; -import { BehaviorSubject, Observable, lastValueFrom } from "rxjs"; +import { BehaviorSubject, Observable, lastValueFrom, of } from "rxjs"; import { BSVersion } from "shared/bs-version.interface"; import { BSLocalVersionService } from "../bs-local-version.service"; import { DeepLinkService } from "../deep-link.service"; @@ -8,14 +8,13 @@ import { UtilsService } from "../utils.service"; import { LocalMapsManagerService } from "./local-maps-manager.service"; import log from "electron-log"; import { isValidUrl } from "../../../shared/helpers/url.helpers"; -import { ipcMain } from "electron"; import { WindowManagerService } from "../window-manager.service"; -import { IpcRequest } from "shared/models/ipc"; import { BPList, DownloadPlaylistProgression } from "shared/models/playlists/playlist.interface"; import { copyFileSync, readFileSync } from "fs"; import { BeatSaverService } from "../thrid-party/beat-saver/beat-saver.service"; import { copy, realpath } from "fs-extra"; import { ensureFolderExist, pathExist } from "../../helpers/fs.helpers"; +import { IpcService } from "../ipc.service"; export class LocalPlaylistsManagerService { private static instance: LocalPlaylistsManagerService; @@ -39,6 +38,7 @@ export class LocalPlaylistsManagerService { private readonly deepLink: DeepLinkService; private readonly windows: WindowManagerService; private readonly bsaver: BeatSaverService; + private readonly ipc: IpcService; private constructor() { this.maps = LocalMapsManagerService.getInstance(); @@ -48,6 +48,7 @@ export class LocalPlaylistsManagerService { this.deepLink = DeepLinkService.getInstance(); this.windows = WindowManagerService.getInstance(); this.bsaver = BeatSaverService.getInstance(); + this.ipc = IpcService.getInstance(); this.deepLink.addLinkOpenedListener(this.DEEP_LINKS.BeatSaver, link => { log.info("DEEP-LINK RECEIVED FROM", this.DEEP_LINKS.BeatSaver, link); @@ -112,11 +113,13 @@ export class LocalPlaylistsManagerService { } private openOneClickDownloadPlaylistWindow(downloadUrl: string): void { - ipcMain.once("one-click-playlist-info", async (event, req: IpcRequest) => { - this.utils.ipcSend(req.responceChannel, { success: true, data: { bpListUrl: downloadUrl, id: this.getPlaylistIdFromDownloadUrl(downloadUrl) } }); - }); + this.windows.openWindow("oneclick-download-playlist.html").then(window => { - this.windows.openWindow("oneclick-download-playlist.html"); + this.ipc.once("one-click-playlist-info", (_, reply) => { + reply(of({ bpListUrl: downloadUrl, id: this.getPlaylistIdFromDownloadUrl(downloadUrl) })) + }, window.webContents.ipc); + + }); } public downloadPlaylist(bpListUrl: string, version: BSVersion): Observable { diff --git a/src/main/services/bs-installer.service.ts b/src/main/services/bs-installer.service.ts index 160da5db..12df2e0e 100644 --- a/src/main/services/bs-installer.service.ts +++ b/src/main/services/bs-installer.service.ts @@ -6,12 +6,12 @@ import { spawnSync } from "child_process"; import log from "electron-log"; import { InstallationLocationService } from "./installation-location.service"; import { BSLocalVersionService } from "./bs-local-version.service"; -import { WindowManagerService } from "./window-manager.service"; import { copy, ensureDir } from "fs-extra"; import { pathExist } from "../helpers/fs.helpers"; import { Observable, map } from "rxjs"; import { DepotDownloaderArgsOptions, DepotDownloaderErrorEvent, DepotDownloaderEvent, DepotDownloaderEventType, DepotDownloaderInfoEvent } from "../../shared/models/depot-downloader.model"; import { DepotDownloader } from "../models/depot-downloader.class"; +import { app } from "electron"; export class BSInstallerService { private static instance: BSInstallerService; @@ -19,7 +19,6 @@ export class BSInstallerService { private readonly utils: UtilsService; private readonly installLocationService: InstallationLocationService; private readonly localVersionService: BSLocalVersionService; - private readonly windows: WindowManagerService; private depotDownloader: DepotDownloader; @@ -27,9 +26,8 @@ export class BSInstallerService { this.utils = UtilsService.getInstance(); this.installLocationService = InstallationLocationService.getInstance(); this.localVersionService = BSLocalVersionService.getInstance(); - this.windows = WindowManagerService.getInstance(); - this.windows.getWindow("index.html")?.on("close", () => { + app.on("before-quit", () => { this.depotDownloader?.stop(); }); } diff --git a/src/main/services/ipc.service.ts b/src/main/services/ipc.service.ts index 9ef6ff4f..f33f94cb 100644 --- a/src/main/services/ipc.service.ts +++ b/src/main/services/ipc.service.ts @@ -1,9 +1,7 @@ import { IpcRequest } from "shared/models/ipc"; -import { ipcMain } from "electron"; +import { BrowserWindow, ipcMain } from "electron"; import { Observable } from "rxjs"; import { IpcCompleteChannel, IpcErrorChannel, IpcTearDownChannel } from "shared/models/ipc/ipc-response.interface"; -import { AppWindow } from "shared/models/window-manager/app-window.model"; -import { WindowManagerService } from "./window-manager.service"; import { IpcReplier } from "shared/models/ipc/ipc-request.interface"; import log from "electron-log"; @@ -17,11 +15,7 @@ export class IpcService { return IpcService.instance; } - private readonly windows: WindowManagerService; - - private constructor() { - this.windows = WindowManagerService.getInstance(); - } + private constructor() {} private getErrorChannel(channel: string): IpcErrorChannel { return `${channel}_error`; @@ -37,17 +31,17 @@ export class IpcService { private buildProxyListener(listener: IpcListener) { return (event: Electron.IpcMainEvent, req: IpcRequest) => { - const window = this.windows.getAppWindowFromWebContents(event.sender); + const window = BrowserWindow.fromWebContents(event.sender); const replier = (data: Observable) => this.connectStream(req.responceChannel, window, data); listener(req, replier); }; } - public send(channel: string, window: AppWindow, response?: T | Error): void { - this.windows.getWindow(window)?.webContents?.send(channel, response); + public send(channel: string, window: BrowserWindow, response?: T | Error): void { + window.webContents?.send(channel, response); } - private connectStream(channel: string, window: AppWindow, observable: Observable): void { + private connectStream(channel: string, window: BrowserWindow, observable: Observable): void { const sub = observable.subscribe({ next: data => this.send(channel, window, data), @@ -58,19 +52,19 @@ export class IpcService { complete: () => this.send(this.getCompleteChannel(channel), window) }) - ipcMain.once(this.getTearDownChannel(channel), () => sub.unsubscribe()); + window.webContents.ipc.once(this.getTearDownChannel(channel), () => sub.unsubscribe()); sub.add(() => { - ipcMain.removeAllListeners(this.getTearDownChannel(channel)); + window.webContents.ipc.removeAllListeners(this.getTearDownChannel(channel)); }); } - public on(channel: string, listener: IpcListener): void { - ipcMain.on(channel, this.buildProxyListener(listener)); + public on(channel: string, listener: IpcListener, ipc = ipcMain): void { + ipc.on(channel, this.buildProxyListener(listener)); } - public once(channel: string, listener: IpcListener): void { - ipcMain.once(channel, this.buildProxyListener(listener)); + public once(channel: string, listener: IpcListener, ipc = ipcMain): void { + ipc.once(channel, this.buildProxyListener(listener)); } } diff --git a/src/main/services/utils.service.ts b/src/main/services/utils.service.ts index 8f233e2a..52d061d9 100644 --- a/src/main/services/utils.service.ts +++ b/src/main/services/utils.service.ts @@ -2,7 +2,6 @@ import path from "path"; import { app, BrowserWindow } from "electron"; import { IpcResponse } from "shared/models/ipc"; import log from "electron-log"; -import { AppWindow } from "shared/models/window-manager/app-window.model"; import psList from "ps-list"; // TODO : REFACTOR @@ -12,8 +11,6 @@ export class UtilsService { private assetsPath: string = app.isPackaged ? path.join(process.resourcesPath, "assets") : path.join(__dirname, "../../../assets"); - private windows: Map = new Map(); - private constructor() {} public static getInstance() { @@ -40,13 +37,6 @@ export class UtilsService { return path.join(app.getPath("temp"), app.getName()); } - public setMainWindows(windows: Map) { - this.windows = windows; - } - public getMainWindows(win: AppWindow) { - return this.windows.get(win); - } - public async taskRunning(task: string): Promise { try { const processes = await psList(); @@ -60,7 +50,7 @@ export class UtilsService { public ipcSend(channel: string, response: IpcResponse): void { try { - Array.from(this.windows.values()).forEach(window => window?.webContents?.send(channel, response)); + BrowserWindow.getAllWindows().forEach(window => window?.webContents?.send(channel, response)); } catch (error) { log.error(error); } diff --git a/src/main/services/window-manager.service.ts b/src/main/services/window-manager.service.ts index 5046f325..69bf99b8 100644 --- a/src/main/services/window-manager.service.ts +++ b/src/main/services/window-manager.service.ts @@ -31,8 +31,6 @@ export class WindowManagerService { webPreferences: { preload: this.PRELOAD_PATH, webSecurity: false }, }; - private readonly windows: Map = new Map(); - public static getInstance(): WindowManagerService { if (!WindowManagerService.instance) { WindowManagerService.instance = new WindowManagerService(); @@ -64,47 +62,30 @@ export class WindowManagerService { window.show(); }); - window.once("closed", () => { - this.windows.delete(windowType); - if (!this.windows.size) { - app.quit(); - } - }); - - this.windows.set(windowType, window); - this.utilsService.setMainWindows(this.windows); - return promise.then(() => window); } public closeAllWindows(except?: AppWindow) { - this.windows.forEach((window, key) => { - if (key === except) { - return; - } + BrowserWindow.getAllWindows().forEach(window => { + if (except && window.webContents.getURL().includes(except)) { return; } window.close(); }); } - public close(...win: AppWindow[]) { - win.forEach(window => { - this.windows.get(window)?.close(); - }); + public getWindows(window: AppWindow): BrowserWindow[] { + return BrowserWindow.getAllWindows().filter(w => w.webContents.getURL().includes(window)); } - public getWindow(window: AppWindow): BrowserWindow { - return this.windows.get(window); - } - - public getAppWindowFromWebContents(sender: Electron.WebContents): AppWindow { - return Array.from(this.windows.entries()).find(([, value]) => value.webContents.id === sender.id)[0]; + public getBrowserWindowsFromWebContents(sender: Electron.WebContents): BrowserWindow { + return BrowserWindow.fromWebContents(sender); } public openWindowOrFocus(window: AppWindow): Promise { - const win = this.getWindow(window); - - if (win) { - win.focus(); + + const win = this.getWindows(window); + + if (win.length) { + win[0].focus(); return Promise.resolve(); } diff --git a/src/renderer/components/title-bar/title-bar.component.tsx b/src/renderer/components/title-bar/title-bar.component.tsx index 22d9e7ae..9045d91f 100644 --- a/src/renderer/components/title-bar/title-bar.component.tsx +++ b/src/renderer/components/title-bar/title-bar.component.tsx @@ -3,7 +3,6 @@ import { useObservable } from "renderer/hooks/use-observable.hook"; import { useThemeColor } from "renderer/hooks/use-theme-color.hook"; import { AudioPlayerService } from "renderer/services/audio-player.service"; import { IpcService } from "renderer/services/ipc.service"; -import { WindowManagerService } from "renderer/services/window-manager.service"; import { AppWindow } from "shared/models/window-manager/app-window.model"; import { BsmButton } from "../shared/bsm-button.component"; import { BsmRange } from "../shared/bsm-range.component"; @@ -15,7 +14,6 @@ import { lastValueFrom } from "rxjs"; export default function TitleBar({ template = "index.html" }: { template: AppWindow }) { const ipcService = useService(IpcService); - const windows = useService(WindowManagerService); const audio = useService(AudioPlayerService); const volume = useObservable(audio.volume$, audio.volume); @@ -37,19 +35,19 @@ export default function TitleBar({ template = "index.html" }: { template: AppWin const [maximized, setMaximized] = useState(false); const closeWindow = () => { - return windows.close(template); + return window.electron.window.close(); }; const maximizeWindow = () => { - ipcService.sendLazy("window.maximize"); + window.electron.window.maximise(); }; const minimizeWindow = () => { - ipcService.sendLazy("window.minimize"); + window.electron.window.minimise(); }; const resetWindow = () => { - ipcService.sendLazy("window.reset"); + window.electron.window.unmaximise(); }; const toogleMaximize = () => { @@ -119,22 +117,21 @@ export default function TitleBar({ template = "index.html" }: { template: AppWin ); } - if (template === "oneclick-download-map.html" || template === "oneclick-download-playlist.html" || template === "oneclick-download-model.html" || "shortcut-launch.html") { - return ( -
-
-
- BSManager -
+ + return ( +
+
+
+ BSManager
-
-
- - - -
+
+
+
+ + +
-
- ); - } +
+
+ ); } diff --git a/src/renderer/preload.d.ts b/src/renderer/preload.d.ts index ab023814..93ad048c 100644 --- a/src/renderer/preload.d.ts +++ b/src/renderer/preload.d.ts @@ -11,6 +11,12 @@ declare global { sep: "/"|"\\"; join: (...args: string[]) => string; }; + window: { + close: () => void; + minimise: () => void; + maximise: () => void; + unmaximise: () => void; + }; }; } } diff --git a/src/renderer/services/window-manager.service.ts b/src/renderer/services/window-manager.service.ts index 24ae8c25..a1f85709 100644 --- a/src/renderer/services/window-manager.service.ts +++ b/src/renderer/services/window-manager.service.ts @@ -22,14 +22,6 @@ export class WindowManagerService { return lastValueFrom(this.ipcService.sendV2("open-window-then-close-all", { args: window })); } - public closeAll(except?: AppWindow): Promise { - return lastValueFrom(this.ipcService.sendV2("close-all-windows", { args: except })); - } - - public close(...win: AppWindow[]): Promise { - return lastValueFrom(this.ipcService.sendV2("close-windows", { args: win })); - } - public openWindowOrFocus(window: AppWindow): Promise { return lastValueFrom(this.ipcService.sendV2("open-window-or-focus", { args: window })); } diff --git a/src/renderer/windows/OneClick/OneClickDownloadMap.tsx b/src/renderer/windows/OneClick/OneClickDownloadMap.tsx index fe8833d4..8e30a8b1 100644 --- a/src/renderer/windows/OneClick/OneClickDownloadMap.tsx +++ b/src/renderer/windows/OneClick/OneClickDownloadMap.tsx @@ -8,8 +8,7 @@ import { MapsDownloaderService } from "renderer/services/maps-downloader.service import { NotificationService } from "renderer/services/notification.service"; import { ProgressBarService } from "renderer/services/progress-bar.service"; import { BeatSaverService } from "renderer/services/thrird-partys/beat-saver.service"; -import { WindowManagerService } from "renderer/services/window-manager.service"; -import { timer } from "rxjs"; +import { lastValueFrom } from "rxjs"; import { BsvMapDetail } from "shared/models/maps"; import defaultImage from "../../../../assets/images/default-version-img.jpg"; import { useService } from "renderer/hooks/use-service.hook"; @@ -20,7 +19,6 @@ export default function OneClickDownloadMap() { const bsv = useService(BeatSaverService); const mapsDownloader = useService(MapsDownloaderService); const progressBar = useService(ProgressBarService); - const windows = useService(WindowManagerService); const notification = useService(NotificationService); const [mapInfo, setMapInfo] = useState(null); @@ -34,13 +32,9 @@ export default function OneClickDownloadMap() { progressBar.open(); const promise = (async () => { - const ipcRes = await ipc.send<{ id: string; isHash: boolean }>("one-click-map-info"); - - if (!ipcRes.success) { - throw ipcRes.error; - } + const ipcRes = await lastValueFrom(ipc.sendV2<{ id: string; isHash: boolean }>("one-click-map-info")); - const mapDetails = ipcRes.data.isHash ? (await bsv.getMapDetailsFromHashs([ipcRes.data.id])).at(0) : await bsv.getMapDetailsById(ipcRes.data.id); + const mapDetails = ipcRes.isHash ? (await bsv.getMapDetailsFromHashs([ipcRes.id])).at(0) : await bsv.getMapDetailsById(ipcRes.id); setMapInfo(() => mapDetails); @@ -52,7 +46,6 @@ export default function OneClickDownloadMap() { throw new Error("Failed to download map with OneClick"); } - await timer(300).toPromise(); })(); promise.catch(() => { @@ -64,7 +57,7 @@ export default function OneClickDownloadMap() { }); promise.finally(() => { - windows.close("oneclick-download-map.html"); + window.electron.window.close(); }); }, []); diff --git a/src/renderer/windows/OneClick/OneClickDownloadModel.tsx b/src/renderer/windows/OneClick/OneClickDownloadModel.tsx index a0ec0925..f4f5096f 100644 --- a/src/renderer/windows/OneClick/OneClickDownloadModel.tsx +++ b/src/renderer/windows/OneClick/OneClickDownloadModel.tsx @@ -7,11 +7,11 @@ import { IpcService } from "renderer/services/ipc.service"; import { NotificationService } from "renderer/services/notification.service"; import { ProgressBarService } from "renderer/services/progress-bar.service"; import { ModelSaberService } from "renderer/services/thrird-partys/model-saber.service"; -import { WindowManagerService } from "renderer/services/window-manager.service"; import { MSModel } from "shared/models/models/model-saber.model"; import defaultImage from "../../../../assets/images/default-version-img.jpg"; import { ModelsDownloaderService } from "renderer/services/models-management/models-downloader.service"; import { useService } from "renderer/hooks/use-service.hook"; +import { lastValueFrom } from "rxjs"; export default function OneClickDownloadModel() { @@ -19,7 +19,6 @@ export default function OneClickDownloadModel() { const modelSaber = useService(ModelSaberService); const progress = useService(ProgressBarService); const modelDownloader = useService(ModelsDownloaderService); - const windows = useService(WindowManagerService); const notification = useService(NotificationService); const [model, setModel] = useState(null); @@ -31,13 +30,9 @@ export default function OneClickDownloadModel() { useEffect(() => { const promise = (async () => { - const infos = await ipc.send<{ id: string; type: string }>("one-click-model-info"); + const infos = await lastValueFrom(ipc.sendV2<{ id: string; type: string }>("one-click-model-info")); - if (!infos.success) { - throw infos.error; - } - - const model = await modelSaber.getModelById(infos.data.id); + const model = await modelSaber.getModelById(infos.id); if (!model) { throw new Error("Failed to get model from ModelSaber"); @@ -63,7 +58,7 @@ export default function OneClickDownloadModel() { }); promise.finally(() => { - windows.close("oneclick-download-model.html") + window.electron.window.close(); }); }, []); diff --git a/src/renderer/windows/OneClick/OneClickDownloadPlaylist.tsx b/src/renderer/windows/OneClick/OneClickDownloadPlaylist.tsx index 11a19008..10519fe4 100644 --- a/src/renderer/windows/OneClick/OneClickDownloadPlaylist.tsx +++ b/src/renderer/windows/OneClick/OneClickDownloadPlaylist.tsx @@ -9,7 +9,6 @@ import { IpcService } from "renderer/services/ipc.service"; import { NotificationService } from "renderer/services/notification.service"; import { PlaylistDownloaderService } from "renderer/services/playlist-downloader.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"; @@ -22,7 +21,6 @@ export default function OneClickDownloadPlaylist() { const bSaver = useService(BeatSaverService); const playlistDownloader = useService(PlaylistDownloaderService); const mapsContainer = useRef(null); - const windows = useService(WindowManagerService); const notification = useService(NotificationService); const [playlist, setPlaylist] = useState(null); @@ -41,15 +39,11 @@ export default function OneClickDownloadPlaylist() { useEffect(() => { const promise = (async () => { - const infos = await ipc.send<{ bpListUrl: string; id: string }>("one-click-playlist-info"); + const infos = await lastValueFrom(ipc.sendV2<{ bpListUrl: string; id: string }>("one-click-playlist-info")); - if (!infos.success) { - throw infos.error; - } + bSaver.getPlaylistDetailsById(infos.id).then(details => setPlaylist(details)); - bSaver.getPlaylistDetailsById(infos.data.id).then(details => setPlaylist(details)); - - return lastValueFrom(playlistDownloader.oneClickInstallPlaylist(infos.data.bpListUrl)); + return lastValueFrom(playlistDownloader.oneClickInstallPlaylist(infos.bpListUrl)); })(); promise.catch(() => { @@ -61,8 +55,9 @@ export default function OneClickDownloadPlaylist() { }); promise.finally(() => { - windows.close("oneclick-download-playlist.html"); + window.electron.window.close(); }); + }, []); useEffect(() => { diff --git a/src/renderer/windows/ShortcutLaunch.tsx b/src/renderer/windows/ShortcutLaunch.tsx index 0a215a75..53dcdafe 100644 --- a/src/renderer/windows/ShortcutLaunch.tsx +++ b/src/renderer/windows/ShortcutLaunch.tsx @@ -59,7 +59,7 @@ export default function ShortcutLaunch() { }); sub.add(() => { - windows.close("shortcut-launch.html"); + window.electron.window.close(); }); return () => sub.unsubscribe();