mirror of
https://github.com/Zagrios/bs-manager.git
synced 2026-07-03 14:08:25 +02:00
Merge branch 'master' into feature/oculus-pcvr-download/274
This commit is contained in:
@@ -573,5 +573,13 @@
|
||||
"ReleaseImg": "https://clan.akamai.steamstatic.com/images/32055887/58621b3cb8bf42fcfbf3b97fe47aa91b290eea04.png",
|
||||
"ReleaseDate": "1693824747",
|
||||
"year": "2023"
|
||||
},
|
||||
{
|
||||
"BSVersion": "1.32.0",
|
||||
"BSManifest": "1660149393914874041",
|
||||
"ReleaseURL": "https://steamcommunity.com/games/620980/announcements/detail/3723971545002767483",
|
||||
"ReleaseImg": "https://clan.cloudflare.steamstatic.com/images/32055887/02284793f06188caf740da66939679afc25415e4.png",
|
||||
"ReleaseDate": "1696517680",
|
||||
"year": "2023"
|
||||
}
|
||||
]
|
||||
@@ -17,5 +17,6 @@
|
||||
{"username": "Phil", "type": "gold"},
|
||||
{"username": "Protocrush", "type": "gold"},
|
||||
{"username": "ServerMensch", "type": "gold"},
|
||||
{"username": "policepigou"}
|
||||
{"username": "policepigou"},
|
||||
{"username": "Karlito", "type": "gold"}
|
||||
]
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"maps": {
|
||||
"title": "Shared maps",
|
||||
"search-bar": {
|
||||
"search-placeholder": "Search installed maps",
|
||||
"search-placeholder": "Search a map",
|
||||
"filters-btn": "Filters",
|
||||
"dropdown": {
|
||||
"export-maps": "Export maps",
|
||||
@@ -738,7 +738,7 @@
|
||||
},
|
||||
"panel": {
|
||||
"actions": {
|
||||
"search": "Search installed models",
|
||||
"search": "Search a model",
|
||||
"drop-down": {
|
||||
"delete": "Delete models",
|
||||
"export": "Export models"
|
||||
|
||||
Generated
+41
-20
@@ -19,7 +19,7 @@
|
||||
"electron-debug": "^3.2.0",
|
||||
"electron-log": "^4.4.8",
|
||||
"electron-store": "^8.1.0",
|
||||
"electron-updater": "^6.1.4",
|
||||
"electron-updater": "^6.1.5",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"framer-motion": "^10.16.4",
|
||||
"fs-extra": "^11.1.1",
|
||||
@@ -88,7 +88,7 @@
|
||||
"css-loader": "^6.7.1",
|
||||
"css-minimizer-webpack-plugin": "^4.1.0",
|
||||
"detect-port": "^1.3.0",
|
||||
"electron": "^26.2.1",
|
||||
"electron": "^27.0.0",
|
||||
"electron-builder": "^24.6.3",
|
||||
"electron-devtools-installer": "^3.2.0",
|
||||
"electron-notarize": "^1.2.1",
|
||||
@@ -5513,6 +5513,19 @@
|
||||
"typescript": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/config-file-ts/node_modules/typescript": {
|
||||
"version": "4.9.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
|
||||
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/confusing-browser-globals": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz",
|
||||
@@ -6736,9 +6749,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron": {
|
||||
"version": "26.2.1",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-26.2.1.tgz",
|
||||
"integrity": "sha512-SNT24Cf/wRvfcFZQoERXjzswUlg5ouqhIuA2t9x2L7VdTn+2Jbs0QXRtOfzcnOV/raVMz3e8ICyaU2GGeciKLg==",
|
||||
"version": "27.0.0",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-27.0.0.tgz",
|
||||
"integrity": "sha512-mr3Zoy82l8XKK/TgguE5FeNeHZ9KHXIGIpUMjbjZWIREfAv+X2Q3vdX6RG0Pmi1K23AFAxANXQezIHBA2Eypwg==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
@@ -6920,9 +6933,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/electron-updater": {
|
||||
"version": "6.1.4",
|
||||
"resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.1.4.tgz",
|
||||
"integrity": "sha512-yYAJc6RQjjV4WtInZVn+ZcLyXRhbVXoomKEfUUwDqIk5s2wxzLhWaor7lrNgxODyODhipjg4SVPMhJHi5EnsCA==",
|
||||
"version": "6.1.5",
|
||||
"resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.1.5.tgz",
|
||||
"integrity": "sha512-RFoncoSbAWYN3CVOFFrEUB5O2V81REAnA4IXQ8enGTSbUjjv+z54TYp23y/3e63oiV3W8grhblJmn9oyH/LnVg==",
|
||||
"dependencies": {
|
||||
"builder-util-runtime": "9.2.1",
|
||||
"fs-extra": "^10.1.0",
|
||||
@@ -18031,9 +18044,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "4.9.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz",
|
||||
"integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==",
|
||||
"version": "4.7.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
|
||||
"integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@@ -23468,6 +23481,14 @@
|
||||
"requires": {
|
||||
"glob": "^7.1.6",
|
||||
"typescript": "^4.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"typescript": {
|
||||
"version": "4.9.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
|
||||
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"confusing-browser-globals": {
|
||||
@@ -24358,9 +24379,9 @@
|
||||
}
|
||||
},
|
||||
"electron": {
|
||||
"version": "26.2.1",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-26.2.1.tgz",
|
||||
"integrity": "sha512-SNT24Cf/wRvfcFZQoERXjzswUlg5ouqhIuA2t9x2L7VdTn+2Jbs0QXRtOfzcnOV/raVMz3e8ICyaU2GGeciKLg==",
|
||||
"version": "27.0.0",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-27.0.0.tgz",
|
||||
"integrity": "sha512-mr3Zoy82l8XKK/TgguE5FeNeHZ9KHXIGIpUMjbjZWIREfAv+X2Q3vdX6RG0Pmi1K23AFAxANXQezIHBA2Eypwg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@electron/get": "^2.0.0",
|
||||
@@ -24523,9 +24544,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"electron-updater": {
|
||||
"version": "6.1.4",
|
||||
"resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.1.4.tgz",
|
||||
"integrity": "sha512-yYAJc6RQjjV4WtInZVn+ZcLyXRhbVXoomKEfUUwDqIk5s2wxzLhWaor7lrNgxODyODhipjg4SVPMhJHi5EnsCA==",
|
||||
"version": "6.1.5",
|
||||
"resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.1.5.tgz",
|
||||
"integrity": "sha512-RFoncoSbAWYN3CVOFFrEUB5O2V81REAnA4IXQ8enGTSbUjjv+z54TYp23y/3e63oiV3W8grhblJmn9oyH/LnVg==",
|
||||
"requires": {
|
||||
"builder-util-runtime": "9.2.1",
|
||||
"fs-extra": "^10.1.0",
|
||||
@@ -32866,9 +32887,9 @@
|
||||
}
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.9.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz",
|
||||
"integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA=="
|
||||
"version": "4.7.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
|
||||
"integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ=="
|
||||
},
|
||||
"unbox-primitive": {
|
||||
"version": "1.0.2",
|
||||
|
||||
+2
-2
@@ -179,7 +179,7 @@
|
||||
"css-loader": "^6.7.1",
|
||||
"css-minimizer-webpack-plugin": "^4.1.0",
|
||||
"detect-port": "^1.3.0",
|
||||
"electron": "^26.2.1",
|
||||
"electron": "^27.0.0",
|
||||
"electron-builder": "^24.6.3",
|
||||
"electron-devtools-installer": "^3.2.0",
|
||||
"electron-notarize": "^1.2.1",
|
||||
@@ -240,7 +240,7 @@
|
||||
"electron-debug": "^3.2.0",
|
||||
"electron-log": "^4.4.8",
|
||||
"electron-store": "^8.1.0",
|
||||
"electron-updater": "^6.1.4",
|
||||
"electron-updater": "^6.1.5",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"framer-motion": "^10.16.4",
|
||||
"fs-extra": "^11.1.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "bs-manager",
|
||||
"version": "1.3.1-alpha.2",
|
||||
"version": "1.3.2",
|
||||
"description": "BSManager",
|
||||
"main": "./dist/main/main.js",
|
||||
"author": {
|
||||
|
||||
@@ -6,6 +6,7 @@ import { BsmLocalMap } from "shared/models/maps/bsm-local-map.interface";
|
||||
import { BsvMapDetail } from "shared/models/maps";
|
||||
import { IpcService } from "../services/ipc.service";
|
||||
import { from } from "rxjs";
|
||||
import log from "electron-log"
|
||||
|
||||
const ipc = IpcService.getInstance();
|
||||
|
||||
@@ -71,6 +72,7 @@ ipc.on("one-click-install-map", async (request: IpcRequest<BsvMapDetail>) => {
|
||||
utils.ipcSend(request.responceChannel, { success: true });
|
||||
})
|
||||
.catch(err => {
|
||||
log.error(err);
|
||||
utils.ipcSend(request.responceChannel, { success: false, error: err });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,6 +2,7 @@ import { ipcMain } from "electron";
|
||||
import { IpcRequest } from "shared/models/ipc";
|
||||
import { LocalPlaylistsManagerService } from "../services/additional-content/local-playlists-manager.service";
|
||||
import { UtilsService } from "../services/utils.service";
|
||||
import log from "electron-log";
|
||||
|
||||
ipcMain.on("one-click-install-playlist", async (event, request: IpcRequest<string>) => {
|
||||
const utils = UtilsService.getInstance();
|
||||
@@ -13,6 +14,7 @@ ipcMain.on("one-click-install-playlist", async (event, request: IpcRequest<strin
|
||||
utils.ipcSend(request.responceChannel, { success: true });
|
||||
})
|
||||
.catch(e => {
|
||||
log.error(e);
|
||||
utils.ipcSend(request.responceChannel, { success: false, error: e });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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<string>) => {
|
||||
shell.openExternal(request.args);
|
||||
});
|
||||
@@ -35,8 +20,7 @@ ipc.on<string>("choose-folder", async (req, reply) => {
|
||||
});
|
||||
|
||||
ipcMain.on("window.progression", async (event, request: IpcRequest<number>) => {
|
||||
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[] }>) => {
|
||||
|
||||
@@ -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<AppWindow>("open-window-then-close-all", (req, reply) => {
|
||||
const windowManager = WindowManagerService.getInstance();
|
||||
|
||||
@@ -17,18 +34,6 @@ ipc.on<AppWindow>("open-window-then-close-all", (req, reply) => {
|
||||
reply(from(res));
|
||||
});
|
||||
|
||||
ipc.on<AppWindow>("close-all-windows", async (req, reply) => {
|
||||
await launcher.restoreSteamVR();
|
||||
const windowManager = WindowManagerService.getInstance();
|
||||
reply(of(windowManager.closeAllWindows(req.args)));
|
||||
});
|
||||
|
||||
ipc.on<AppWindow[]>("close-windows", async (req, reply) => {
|
||||
await launcher.restoreSteamVR();
|
||||
const windowManager = WindowManagerService.getInstance();
|
||||
reply(of(windowManager.close(...req.args)));
|
||||
});
|
||||
|
||||
ipc.on<AppWindow>("open-window-or-focus", (req, reply) => {
|
||||
const windowManager = WindowManagerService.getInstance();
|
||||
reply(from(windowManager.openWindowOrFocus(req.args)));
|
||||
|
||||
@@ -89,6 +89,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);
|
||||
|
||||
+8
-1
@@ -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"); },
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@@ -7,22 +7,21 @@ import { InstallationLocationService } from "../installation-location.service";
|
||||
import { UtilsService } from "../utils.service";
|
||||
import crypto from "crypto";
|
||||
import { lstatSync } from "fs";
|
||||
import { copy, createReadStream, ensureDir, unlink } from "fs-extra";
|
||||
import { copy, createReadStream, ensureDir, realpath, unlink } from "fs-extra";
|
||||
import StreamZip from "node-stream-zip";
|
||||
import { RequestService } from "../request.service";
|
||||
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<void>) => {
|
||||
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<BsmLocalMapsProgress> {
|
||||
@@ -290,10 +295,16 @@ export class LocalMapsManagerService {
|
||||
|
||||
const versions = await this.localVersion.getInstalledVersions();
|
||||
const downloadedMap = await this.downloadMap(map, versions.pop());
|
||||
const downloadedMapRealFolder = await realpath(path.dirname(downloadedMap.path));
|
||||
|
||||
for (const version of versions) {
|
||||
const versionMapsPath = await this.getMapsFolderPath(version);
|
||||
await ensureDir(versionMapsPath);
|
||||
|
||||
if((await realpath(versionMapsPath)) === downloadedMapRealFolder){
|
||||
continue;
|
||||
}
|
||||
|
||||
await copy(downloadedMap.path, path.join(versionMapsPath, path.basename(downloadedMap.path)), { overwrite: true });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<void>) => {
|
||||
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<string> {
|
||||
|
||||
@@ -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 { copySync } from "fs-extra";
|
||||
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<void>) => {
|
||||
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<DownloadPlaylistProgression> {
|
||||
@@ -180,14 +183,27 @@ export class LocalPlaylistsManagerService {
|
||||
|
||||
const { bpListPath, mapsPath } = await lastValueFrom(this.downloadPlaylist(bpListUrl, versions.pop()));
|
||||
|
||||
if(mapsPath?.length === 0 || !bpListPath) {
|
||||
return;
|
||||
}
|
||||
|
||||
const realSourceMapsFolder = await realpath(path.dirname(mapsPath[0]));
|
||||
|
||||
for (const version of versions) {
|
||||
await this.installBPListFile(bpListPath, version);
|
||||
|
||||
const versionMapsFolder = await this.maps.getMapsFolderPath(version);
|
||||
const realDestMapsFolder = await realpath(versionMapsFolder);
|
||||
|
||||
if(realSourceMapsFolder === realDestMapsFolder) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const mapPath of mapsPath) {
|
||||
const versionMapsFolder = await this.maps.getMapsFolderPath(version);
|
||||
|
||||
const mapDest = path.join(versionMapsFolder, path.basename(mapPath));
|
||||
|
||||
copySync(mapPath, mapDest, { overwrite: true });
|
||||
await copy(mapPath, mapDest, { overwrite: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ export class BSLauncherService {
|
||||
bsProcess.removeAllListeners("error");
|
||||
bsProcess.removeAllListeners("exit");
|
||||
resolve(-1);
|
||||
}, 15_000);
|
||||
}, 30_000);
|
||||
|
||||
}).then(exitCode => {
|
||||
log.info("BS process exit code", exitCode);
|
||||
@@ -183,7 +183,13 @@ export class BSLauncherService {
|
||||
shortcutLink = new URL(shortcutLink);
|
||||
}
|
||||
|
||||
return objectFromEntries(shortcutLink.searchParams.entries()) as ShortcutParams;
|
||||
const params = objectFromEntries(shortcutLink.searchParams.entries()) as ShortcutParams;
|
||||
|
||||
if(typeof params.additionalArgs === "string"){
|
||||
params.additionalArgs = [params.additionalArgs];
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
public shortcutLinkToLaunchOptions(shortcutLink: string|URL): LaunchOption{
|
||||
|
||||
@@ -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<T>(listener: IpcListener<T>) {
|
||||
return (event: Electron.IpcMainEvent, req: IpcRequest<T>) => {
|
||||
const window = this.windows.getAppWindowFromWebContents(event.sender);
|
||||
const window = BrowserWindow.fromWebContents(event.sender);
|
||||
const replier = (data: Observable<unknown>) => this.connectStream(req.responceChannel, window, data);
|
||||
listener(req, replier);
|
||||
};
|
||||
}
|
||||
|
||||
public send<T>(channel: string, window: AppWindow, response?: T | Error): void {
|
||||
this.windows.getWindow(window)?.webContents?.send(channel, response);
|
||||
public send<T>(channel: string, window: BrowserWindow, response?: T | Error): void {
|
||||
window.webContents?.send(channel, response);
|
||||
}
|
||||
|
||||
private connectStream(channel: string, window: AppWindow, observable: Observable<unknown>): void {
|
||||
private connectStream(channel: string, window: BrowserWindow, observable: Observable<unknown>): 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<T>(channel: string, listener: IpcListener<T>): void {
|
||||
ipcMain.on(channel, this.buildProxyListener(listener));
|
||||
public on<T>(channel: string, listener: IpcListener<T>, ipc = ipcMain): void {
|
||||
ipc.on(channel, this.buildProxyListener(listener));
|
||||
}
|
||||
|
||||
public once<T>(channel: string, listener: IpcListener<T>): void {
|
||||
ipcMain.once(channel, this.buildProxyListener(listener));
|
||||
public once<T>(channel: string, listener: IpcListener<T>, ipc = ipcMain): void {
|
||||
ipc.once(channel, this.buildProxyListener(listener));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<AppWindow, BrowserWindow> = new Map<AppWindow, BrowserWindow>();
|
||||
|
||||
private constructor() {}
|
||||
|
||||
public static getInstance() {
|
||||
@@ -40,13 +37,6 @@ export class UtilsService {
|
||||
return path.join(app.getPath("temp"), app.getName());
|
||||
}
|
||||
|
||||
public setMainWindows(windows: Map<AppWindow, BrowserWindow>) {
|
||||
this.windows = windows;
|
||||
}
|
||||
public getMainWindows(win: AppWindow) {
|
||||
return this.windows.get(win);
|
||||
}
|
||||
|
||||
public async taskRunning(task: string): Promise<boolean> {
|
||||
try {
|
||||
const processes = await psList();
|
||||
@@ -60,7 +50,7 @@ export class UtilsService {
|
||||
|
||||
public ipcSend<T = unknown>(channel: string, response: IpcResponse<T>): 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);
|
||||
}
|
||||
|
||||
@@ -32,8 +32,6 @@ export class WindowManagerService {
|
||||
webPreferences: { preload: this.PRELOAD_PATH, webSecurity: !this.IS_DEBUG },
|
||||
};
|
||||
|
||||
private readonly windows = new Map<string, BrowserWindow>();
|
||||
|
||||
public static getInstance(): WindowManagerService {
|
||||
if (!WindowManagerService.instance) {
|
||||
WindowManagerService.instance = new WindowManagerService();
|
||||
@@ -65,17 +63,6 @@ export class WindowManagerService {
|
||||
window.show();
|
||||
});
|
||||
|
||||
window.once("closed", () => {
|
||||
this.windows.delete(url);
|
||||
if (!this.windows.size) {
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
|
||||
this.windows.set(url, window);
|
||||
this.utilsService.setMainWindows(this.windows as Map<AppWindow, BrowserWindow>); // TODO : remove
|
||||
|
||||
|
||||
return promise.then(() => window);
|
||||
}
|
||||
|
||||
@@ -85,33 +72,26 @@ export class WindowManagerService {
|
||||
}
|
||||
|
||||
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: 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<void> {
|
||||
const win = this.getWindow(window);
|
||||
|
||||
if (win) {
|
||||
win.focus();
|
||||
|
||||
const win = this.getWindows(window);
|
||||
|
||||
if (win.length) {
|
||||
win[0].focus();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
</header>
|
||||
);
|
||||
}
|
||||
if (template === "oneclick-download-map.html" || template === "oneclick-download-playlist.html" || template === "oneclick-download-model.html" || "shortcut-launch.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">
|
||||
<div id="window-title" className="pl-1">
|
||||
<span className="text-gray-100 font-bold text-xs italic">BSManager</span>
|
||||
</div>
|
||||
|
||||
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 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"/>
|
||||
</svg>
|
||||
</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"/>
|
||||
</svg>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
Vendored
+6
@@ -11,6 +11,12 @@ declare global {
|
||||
sep: "/"|"\\";
|
||||
join: (...args: string[]) => string;
|
||||
};
|
||||
window: {
|
||||
close: () => void;
|
||||
minimise: () => void;
|
||||
maximise: () => void;
|
||||
unmaximise: () => void;
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,14 +22,6 @@ export class WindowManagerService {
|
||||
return lastValueFrom(this.ipcService.sendV2<void>("open-window-then-close-all", { args: window }));
|
||||
}
|
||||
|
||||
public closeAll(except?: AppWindow): Promise<void> {
|
||||
return lastValueFrom(this.ipcService.sendV2<void>("close-all-windows", { args: except }));
|
||||
}
|
||||
|
||||
public close(...win: AppWindow[]): Promise<void> {
|
||||
return lastValueFrom(this.ipcService.sendV2<void>("close-windows", { args: win }));
|
||||
}
|
||||
|
||||
public openWindowOrFocus(window: AppWindow): Promise<void> {
|
||||
return lastValueFrom(this.ipcService.sendV2<void, AppWindow>("open-window-or-focus", { args: window }));
|
||||
}
|
||||
|
||||
@@ -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<BsvMapDetail>(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();
|
||||
});
|
||||
|
||||
}, []);
|
||||
|
||||
@@ -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<MSModel>(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();
|
||||
});
|
||||
|
||||
}, []);
|
||||
|
||||
@@ -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<HTMLDivElement>(null);
|
||||
const windows = useService(WindowManagerService);
|
||||
const notification = useService(NotificationService);
|
||||
|
||||
const [playlist, setPlaylist] = useState<BsvPlaylist>(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(() => {
|
||||
|
||||
@@ -59,7 +59,7 @@ export default function ShortcutLaunch() {
|
||||
});
|
||||
|
||||
sub.add(() => {
|
||||
windows.close("shortcut-launch.html");
|
||||
window.electron.window.close();
|
||||
});
|
||||
|
||||
return () => sub.unsubscribe();
|
||||
|
||||
Reference in New Issue
Block a user