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:
@@ -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 = {
|
||||
|
||||
Reference in New Issue
Block a user