advancement on oneClick model AND lazy loading react windows

This commit is contained in:
MathieuG-P
2022-12-24 18:19:59 +01:00
parent 6c5190eacb
commit 2aed523480
19 changed files with 440 additions and 47 deletions
+2 -1
View File
@@ -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';
+15
View File
@@ -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
View File
@@ -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 = {