mirror of
https://github.com/Zagrios/bs-manager.git
synced 2026-07-03 14:08:25 +02:00
advancement on oneClick model AND lazy loading react windows
This commit is contained in:
@@ -168,6 +168,7 @@ const configuration: webpack.Configuration = {
|
||||
new HtmlWebpackPlugin(getHtmlPageOptions("launcher.html")),
|
||||
new HtmlWebpackPlugin(getHtmlPageOptions("oneclick-download-map.html")),
|
||||
new HtmlWebpackPlugin(getHtmlPageOptions("oneclick-download-playlist.html")),
|
||||
new HtmlWebpackPlugin(getHtmlPageOptions("oneclick-download-model.html")),
|
||||
|
||||
],
|
||||
|
||||
|
||||
@@ -150,6 +150,7 @@ const configuration: webpack.Configuration = {
|
||||
new HtmlWebpackPlugin(getHtmlPageOptions("launcher.html")),
|
||||
new HtmlWebpackPlugin(getHtmlPageOptions("oneclick-download-map.html")),
|
||||
new HtmlWebpackPlugin(getHtmlPageOptions("oneclick-download-playlist.html")),
|
||||
new HtmlWebpackPlugin(getHtmlPageOptions("oneclick-download-model.html")),
|
||||
|
||||
],
|
||||
};
|
||||
|
||||
Generated
+103
-5
@@ -2202,6 +2202,17 @@
|
||||
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/plist": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.2.tgz",
|
||||
"integrity": "sha512-ULqvZNGMv0zRFvqn8/4LSPtnmN4MfhlPNtJCTpKuIIxGVGZ2rYWzFXrvEBoh9CVyqSE7D6YFRJ1hydLHI6kbWw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@types/node": "*",
|
||||
"xmlbuilder": ">=11.0.1"
|
||||
}
|
||||
},
|
||||
"@types/prettier": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.1.tgz",
|
||||
@@ -2238,12 +2249,12 @@
|
||||
}
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"version": "17.0.18",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.18.tgz",
|
||||
"integrity": "sha512-rLVtIfbwyur2iFKykP2w0pl/1unw26b5td16d5xMgp7/yjTHomkyxPYChFoCr/FtEX1lN9wY6lFj1qvKdS5kDw==",
|
||||
"version": "18.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.10.tgz",
|
||||
"integrity": "sha512-E42GW/JA4Qv15wQdqJq8DL4JhNpB3prJgjgapN3qJT9K2zO5IIAQh4VXvCEDupoqAwnz0cY4RlXeC/ajX5SFHg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react": "^17"
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-outside-click-handler": {
|
||||
@@ -2363,6 +2374,13 @@
|
||||
"integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/verror": {
|
||||
"version": "1.10.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.6.tgz",
|
||||
"integrity": "sha512-NNm+gdePAX1VGvPcGZCDKQZKYSiAWigKhKaz5KF94hG6f2s8de9Ow5+7AbXoeKxL8gavZfk4UquSAygOF2duEQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@types/webpack-bundle-analyzer": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.6.0.tgz",
|
||||
@@ -3168,6 +3186,13 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"ast-metadata-inferer": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/ast-metadata-inferer/-/ast-metadata-inferer-0.7.0.tgz",
|
||||
@@ -4257,6 +4282,16 @@
|
||||
"yaml": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"crc": {
|
||||
"version": "3.8.0",
|
||||
"resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz",
|
||||
"integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"buffer": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"crc-32": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
|
||||
@@ -4850,8 +4885,36 @@
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@types/plist": "^3.0.1",
|
||||
"@types/verror": "^1.10.3",
|
||||
"ajv": "^6.10.0",
|
||||
"crc": "^3.8.0",
|
||||
"iconv-corefoundation": "^1.1.7",
|
||||
"plist": "^3.0.4",
|
||||
"smart-buffer": "^4.0.2"
|
||||
"smart-buffer": "^4.0.2",
|
||||
"verror": "^1.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"dns-equal": {
|
||||
@@ -6581,6 +6644,13 @@
|
||||
"yauzl": "^2.10.0"
|
||||
}
|
||||
},
|
||||
"extsprintf": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz",
|
||||
"integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
@@ -7485,6 +7555,13 @@
|
||||
"ms": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"iconv-corefoundation": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz",
|
||||
"integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||
@@ -13577,6 +13654,27 @@
|
||||
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
|
||||
"dev": true
|
||||
},
|
||||
"verror": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz",
|
||||
"integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
"extsprintf": "^1.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"w3c-hr-time": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",
|
||||
|
||||
+1
-1
@@ -153,7 +153,7 @@
|
||||
"@types/jest": "^27.5.2",
|
||||
"@types/node": "17.0.23",
|
||||
"@types/react": "^17.0.48",
|
||||
"@types/react-dom": "^17.0.17",
|
||||
"@types/react-dom": "^18.0.10",
|
||||
"@types/react-outside-click-handler": "^1.3.1",
|
||||
"@types/react-test-renderer": "^17.0.2",
|
||||
"@types/terser-webpack-plugin": "^5.0.4",
|
||||
|
||||
@@ -9,4 +9,5 @@ import './window-manager-ipcs';
|
||||
import './bs-mods-ipcs';
|
||||
import './bs-maps-ipcs';
|
||||
import './beat-saver-ipcs';
|
||||
import './bs-playlist-ipcs';
|
||||
import './bs-playlist-ipcs';
|
||||
import './model-saber.ipcs';
|
||||
@@ -0,0 +1,15 @@
|
||||
import { ipcMain } from "electron";
|
||||
import { IpcRequest } from "shared/models/ipc";
|
||||
import { ModelSaberService } from "../services/thrid-party/model-saber/model-saber.service";
|
||||
import { UtilsService } from "../services/utils.service";
|
||||
|
||||
ipcMain.on("ms-get-model-by-id", async (event, request: IpcRequest<string|number>) => {
|
||||
const utils = UtilsService.getInstance();
|
||||
const ms = ModelSaberService.getInstance();
|
||||
|
||||
ms.getModelById(request.args).then(model => {
|
||||
utils.ipcSend(request.responceChannel, {success: true, data: model});
|
||||
}).catch(e => {
|
||||
utils.ipcSend(request.responceChannel, {success: false, error: e});
|
||||
})
|
||||
});
|
||||
+4
-1
@@ -18,6 +18,8 @@ import { DeepLinkService } from './services/deep-link.service';
|
||||
import { AppWindow } from 'shared/models/window-manager/app-window.model';
|
||||
import { LocalMapsManagerService } from './services/additional-content/local-maps-manager.service';
|
||||
import { LocalPlaylistsManagerService } from './services/additional-content/local-playlists-manager.service';
|
||||
import { ModelSaberService } from './services/thrid-party/model-saber/model-saber.service';
|
||||
import { LocalModelsManagerService } from './services/additional-content/local-models-manager.service';
|
||||
|
||||
export const PRELOAD_PATH = app.isPackaged ? path.join(__dirname, 'preload.js') : path.join(__dirname, '../../.erb/dll/preload.js')
|
||||
|
||||
@@ -59,6 +61,7 @@ const createWindow = async (window: AppWindow = "launcher.html") => {
|
||||
const initServicesMustBeInitialized = () => {
|
||||
LocalMapsManagerService.getInstance();
|
||||
LocalPlaylistsManagerService.getInstance();
|
||||
LocalModelsManagerService.getInstance();
|
||||
// Model
|
||||
}
|
||||
|
||||
@@ -89,7 +92,7 @@ else{
|
||||
|
||||
app.whenReady().then(() => {
|
||||
|
||||
process.argv.push("bsplaylist://playlist/https://api.beatsaver.com/playlists/id/11199/download/beatsaver-11199.bplist"); // to force deep-link (oneClick map)
|
||||
process.argv.push("modelsaber://saber/1670981586/r_Happy Crimbo!.saber"); // to force deep-link (oneClick map)
|
||||
|
||||
initServicesMustBeInitialized();
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
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";
|
||||
|
||||
export class LocalModelsManagerService {
|
||||
|
||||
private static instance: LocalModelsManagerService;
|
||||
|
||||
public static getInstance(): LocalModelsManagerService{
|
||||
if(!LocalModelsManagerService.instance){ LocalModelsManagerService.instance = new LocalModelsManagerService(); }
|
||||
return LocalModelsManagerService.instance;
|
||||
}
|
||||
|
||||
private readonly DEEP_LINKS = {
|
||||
ModelSaber: "modelsaber",
|
||||
};
|
||||
|
||||
private readonly deepLink: DeepLinkService;
|
||||
private readonly utils: UtilsService;
|
||||
private readonly windows: WindowManagerService;
|
||||
|
||||
private constructor(){
|
||||
this.deepLink = DeepLinkService.getInstance();
|
||||
this.utils = UtilsService.getInstance();
|
||||
this.windows = WindowManagerService.getInstance();
|
||||
|
||||
this.deepLink.addLinkOpenedListener(this.DEEP_LINKS.ModelSaber, (link) => {
|
||||
log.info("DEEP-LINK RECEIVED FROM", this.DEEP_LINKS.ModelSaber, link);
|
||||
const url = new URL(link);
|
||||
|
||||
const type = url.host
|
||||
const id = url.pathname.replace("/", '').split("/").at(0);
|
||||
|
||||
this.openOneClickDownloadModelWindow(id, type);
|
||||
});
|
||||
}
|
||||
|
||||
private openOneClickDownloadModelWindow(id: string, type: string){
|
||||
|
||||
// TODO make once
|
||||
ipcMain.on("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");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
import { splitIntoChunk } from "../../../helpers/array-tools";
|
||||
import { BsvMapDetail } from "shared/models/maps";
|
||||
import { BsvPlaylist, BsvPlaylistPage, SearchParams } from "shared/models/maps/beat-saver.model";
|
||||
import { BsvPlaylist, SearchParams } from "shared/models/maps/beat-saver.model";
|
||||
import { BeatSaverApiService } from "./beat-saver-api.service";
|
||||
import { red } from "tailwindcss/colors";
|
||||
|
||||
export class BeatSaverService {
|
||||
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
import fetch from "node-fetch";
|
||||
import { ApiResult } from "renderer/models/api/api.model";
|
||||
import { MSGetQuery, MSGetQueryFilter, MSGetResponse } from "shared/models/model-saber/model-saber.model";
|
||||
|
||||
export class ModelSaberApiService {
|
||||
|
||||
private static instance: ModelSaberApiService;
|
||||
|
||||
public static getInstance(): ModelSaberApiService{
|
||||
if(!ModelSaberApiService.instance){ ModelSaberApiService.instance = new ModelSaberApiService(); }
|
||||
return ModelSaberApiService.instance;
|
||||
}
|
||||
|
||||
private readonly API_URL = "https://modelsaber.com/api/v2/";
|
||||
private readonly ENDPOINTS = {get: "get.php", types: "types.php"};
|
||||
|
||||
private constructor(){}
|
||||
|
||||
private parseFilters(filters: MSGetQueryFilter[]): string{
|
||||
|
||||
if(!filters){ return null; }
|
||||
|
||||
const parsed = filters.map(filter => {
|
||||
const stringFilter = filter.type === "searchName" ? filter.value : `${filter.type}:${filter.value}`;
|
||||
return filter.isNegative ? `-${stringFilter}` : stringFilter;
|
||||
});
|
||||
|
||||
return parsed.join(",");
|
||||
|
||||
}
|
||||
|
||||
private buildUrlQuery(query: MSGetQuery): URLSearchParams{
|
||||
|
||||
if(!query){ return new URLSearchParams(); }
|
||||
|
||||
const filterQuery = this.parseFilters(query.filter);
|
||||
|
||||
const searchParams = {
|
||||
...(query.type && {type: query.type}),
|
||||
...(query.platform && {platform: query.platform}),
|
||||
...(query.start && {start: `${query.start}`}),
|
||||
...(query.end && {end: `${query.end}`}),
|
||||
...(query.sort && {sort: query.sort}),
|
||||
...(query.sortDirection && {sortDirection: query.sortDirection}),
|
||||
...(filterQuery && {filter: filterQuery}),
|
||||
}
|
||||
|
||||
return new URLSearchParams(searchParams);
|
||||
|
||||
}
|
||||
|
||||
public async searchModel(query: MSGetQuery): Promise<ApiResult<MSGetResponse>>{
|
||||
|
||||
const url = new URL(this.ENDPOINTS.get, this.API_URL);
|
||||
|
||||
url.search = this.buildUrlQuery(query).toString();
|
||||
|
||||
const res = await fetch(url.toString());
|
||||
|
||||
if(!res.ok){
|
||||
return {data: null, status: res.status};
|
||||
}
|
||||
|
||||
const data = await res.json() as MSGetResponse;
|
||||
|
||||
return {data, status: res.status};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
import { MSGetQuery, MSGetQueryFilter, MSModel } from "shared/models/model-saber/model-saber.model";
|
||||
import { ModelSaberApiService } from "./model-saber-api.service";
|
||||
|
||||
export class ModelSaberService {
|
||||
|
||||
private static instance: ModelSaberService;
|
||||
@@ -7,6 +10,36 @@ export class ModelSaberService {
|
||||
return ModelSaberService.instance;
|
||||
}
|
||||
|
||||
private constructor(){}
|
||||
private readonly modelSaberApi: ModelSaberApiService;
|
||||
|
||||
private constructor(){
|
||||
this.modelSaberApi = ModelSaberApiService.getInstance();
|
||||
}
|
||||
|
||||
public async getModelById(id: number|string): Promise<MSModel>{
|
||||
|
||||
const query: MSGetQuery = {
|
||||
start: 0,
|
||||
end: 1,
|
||||
platform: "pc",
|
||||
filter: [{type: "id", value: id}]
|
||||
}
|
||||
|
||||
try{
|
||||
const res = await this.modelSaberApi.searchModel(query);
|
||||
|
||||
if(res.status !== 200){ return null; }
|
||||
|
||||
if(Object.keys(res.data).length === 0){
|
||||
return null;
|
||||
}
|
||||
|
||||
return res.data[`${id}`];
|
||||
}
|
||||
catch(e){
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
export class ModelSaberApiService {
|
||||
|
||||
private static instance: ModelSaberApiService;
|
||||
|
||||
public static getInstance(): ModelSaberApiService{
|
||||
if(!ModelSaberApiService.instance){ ModelSaberApiService.instance = new ModelSaberApiService(); }
|
||||
return ModelSaberApiService.instance;
|
||||
}
|
||||
|
||||
private readonly API_URL = "https://modelsaber.com/api/v2";
|
||||
private readonly ENDPOINTS = {get: "get.php", types: "types.php"};
|
||||
|
||||
private constructor(){}
|
||||
|
||||
public searchModel(search: any): any{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,6 +15,7 @@ export class WindowManagerService{
|
||||
"index.html": {width: 1080, height: 720, minWidth: 900, minHeight: 500},
|
||||
"oneclick-download-map.html": {width: 350, height: 400, minWidth: 350, minHeight: 400, resizable: false},
|
||||
"oneclick-download-playlist.html": {width: 350, height: 400, minWidth: 350, minHeight: 400, resizable: false},
|
||||
"oneclick-download-model.html": {width: 350, height: 400, minWidth: 350, minHeight: 400, resizable: false},
|
||||
}
|
||||
|
||||
private readonly baseWindowOption: BrowserWindowConstructorOptions = {
|
||||
|
||||
+25
-16
@@ -1,31 +1,40 @@
|
||||
//@ts-ignore
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import { HashRouter } from 'react-router-dom';
|
||||
import App from './windows/App';
|
||||
import Launcher from './windows/Launcher';
|
||||
import 'tailwindcss/tailwind.css';
|
||||
import './index.css'
|
||||
import OneClickDownloadMap from './windows/OneClick/OneClickDownloadMap';
|
||||
import OneClickDownloadPlaylist from './windows/OneClick/OneClickDownloadPlaylist';
|
||||
|
||||
const launcherContainer = document.getElementById('launcher');
|
||||
const oneclickDownloadMapContainer = document.getElementById('oneclick-download-map');
|
||||
const oneclickDownloadPlaylistContainer = document.getElementById('oneclick-download-playlist');
|
||||
const oneclickDownloadModelContainer = document.getElementById('oneclick-download-model');
|
||||
|
||||
if(!!launcherContainer){
|
||||
createRoot(launcherContainer).render(<Launcher/>);
|
||||
if(launcherContainer){
|
||||
import("./windows/Launcher").then(reactWindow => {
|
||||
createRoot(launcherContainer).render(<reactWindow.default/>);
|
||||
});
|
||||
}
|
||||
else if(!!oneclickDownloadMapContainer){
|
||||
createRoot(oneclickDownloadMapContainer).render(<OneClickDownloadMap/>);
|
||||
else if(oneclickDownloadMapContainer){
|
||||
import("./windows/OneClick/OneClickDownloadMap").then(reactWindow => {
|
||||
createRoot(oneclickDownloadMapContainer).render(<reactWindow.default/>);
|
||||
});
|
||||
}
|
||||
else if(!!oneclickDownloadPlaylistContainer){
|
||||
createRoot(oneclickDownloadPlaylistContainer).render(<OneClickDownloadPlaylist/>);
|
||||
else if(oneclickDownloadPlaylistContainer){
|
||||
import("./windows/OneClick/OneClickDownloadPlaylist").then(reactWindow => {
|
||||
createRoot(oneclickDownloadPlaylistContainer).render(<reactWindow.default/>);
|
||||
});
|
||||
}
|
||||
else if(oneclickDownloadModelContainer){
|
||||
import("./windows/OneClick/OneClickDownloadModel").then(reactWindow => {
|
||||
createRoot(oneclickDownloadModelContainer).render(<reactWindow.default/>);
|
||||
});
|
||||
}
|
||||
else{
|
||||
const root = document.getElementById('root');
|
||||
createRoot(root).render(
|
||||
<HashRouter>
|
||||
<App />
|
||||
</HashRouter>
|
||||
);
|
||||
import("./windows/App").then(reactWindow => {
|
||||
createRoot(root).render(
|
||||
<HashRouter>
|
||||
<reactWindow.default/>
|
||||
</HashRouter>
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -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-model"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,25 @@
|
||||
import { MSModel } from "shared/models/model-saber/model-saber.model";
|
||||
import { IpcService } from "../ipc.service";
|
||||
|
||||
export class ModelSaberService {
|
||||
|
||||
private static instance: ModelSaberService;
|
||||
|
||||
public static getInstance(): ModelSaberService{
|
||||
if(!ModelSaberService.instance){ ModelSaberService.instance = new ModelSaberService(); }
|
||||
return ModelSaberService.instance;
|
||||
}
|
||||
|
||||
private readonly ipc: IpcService;
|
||||
|
||||
private constructor(){
|
||||
this.ipc = IpcService.getInstance();
|
||||
}
|
||||
|
||||
public async getModelById(id: number|string): Promise<MSModel>{
|
||||
const res = await this.ipc.send<MSModel>("ms-get-model-by-id", {args: id});
|
||||
if(!res.success){ return null; }
|
||||
return res.data;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { IpcService } from "renderer/services/ipc.service";
|
||||
import { ThemeService } from "renderer/services/theme.service";
|
||||
import { ModelSaberService } from "renderer/services/thrird-partys/model-saber.service";
|
||||
import { MSModel } from "shared/models/model-saber/model-saber.model";
|
||||
|
||||
export default function OneClickDownloadModel() {
|
||||
|
||||
const ipc = IpcService.getInstance();
|
||||
const themeService = ThemeService.getInstance();
|
||||
const modelSaber = ModelSaberService.getInstance();
|
||||
|
||||
const [model, setModel] = useState<MSModel>(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'); }
|
||||
});
|
||||
|
||||
const promise = new Promise(async (resolve, reject) => {
|
||||
|
||||
const infos = await ipc.send<{id: string, type: string}>("one-click-model-info");
|
||||
|
||||
if(!infos.success){ reject(); }
|
||||
|
||||
const model = await modelSaber.getModelById(infos.data.id);
|
||||
|
||||
setModel(() => model);
|
||||
|
||||
// Download model
|
||||
|
||||
});
|
||||
|
||||
return () => {
|
||||
sub.unsubscribe();
|
||||
}
|
||||
}, [])
|
||||
|
||||
|
||||
return (
|
||||
<div>OneClickDownloadModel</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
export interface MSModel {
|
||||
tags: string[],
|
||||
type: MSModelType,
|
||||
name: string,
|
||||
author: string,
|
||||
thumbnail: string,
|
||||
id: number,
|
||||
hash: string,
|
||||
bsaber: string,
|
||||
status: string,
|
||||
discordid: string,
|
||||
discord?: string,
|
||||
variationid?: number,
|
||||
platform: MSModelPlatform,
|
||||
download: string,
|
||||
install_link: string,
|
||||
date: string
|
||||
}
|
||||
|
||||
export type MSModelType = "saber"|"platform"|"bloq"|"misc"|"avatar";
|
||||
export type MSModelPlatform = "pc"|"quest"|"all";
|
||||
|
||||
export interface MSGetQuery {
|
||||
type?: MSModelType;
|
||||
platform?: MSModelPlatform,
|
||||
start?: number,
|
||||
end?: number,
|
||||
sort?: MSGetSort,
|
||||
sortDirection?: MSGetSortDirection,
|
||||
filter?: MSGetQueryFilter[]
|
||||
}
|
||||
|
||||
export interface MSGetQueryFilter {
|
||||
type:MSGetQueryFilterType,
|
||||
value: string|number,
|
||||
isNegative?: boolean
|
||||
}
|
||||
|
||||
export type MSGetResponse<T extends string = string> = Record<T, MSModel>;
|
||||
export type MSGetSort = "date"|"name"|"author"
|
||||
export type MSGetSortDirection = "asc"|"desc"
|
||||
export type MSGetQueryFilterType = "author"|"name"|"tag"|"hash"|"discordid"|"id"|"searchName"
|
||||
@@ -2,5 +2,6 @@ export type AppWindow = (
|
||||
"index.html" |
|
||||
"launcher.html" |
|
||||
"oneclick-download-map.html"|
|
||||
"oneclick-download-playlist.html"
|
||||
"oneclick-download-playlist.html"|
|
||||
"oneclick-download-model.html"
|
||||
);
|
||||
Reference in New Issue
Block a user