add mods loader and get installed mods finished

This commit is contained in:
MathieuG-P
2022-09-28 00:39:44 +02:00
parent e8cd849623
commit 98dccb1831
9 changed files with 93 additions and 26 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 260 KiB

+9
View File
@@ -11,4 +11,13 @@ ipcMain.on("get-available-mods", (event, request: IpcRequest<BSVersion>) => {
modsManager.getAvailableMods(request.args).then(mods => {
utils.ipcSend(request.responceChannel, {success: true, data: mods});
}).catch(() => utils.ipcSend(request.responceChannel, {success: false}));
});
ipcMain.on("get-installed-mods", (event, request: IpcRequest<BSVersion>) => {
const utils = UtilsService.getInstance();
const modsManager = BsModsManagerService.getInstance();
modsManager.getInstalledMods(request.args).then(mods => {
utils.ipcSend(request.responceChannel, {success: true, data: mods});
}).catch(() => utils.ipcSend(request.responceChannel, {success: false}));
});
-4
View File
@@ -31,10 +31,6 @@ log.catchErrors();
const utilsService = UtilsService.getInstance();
utilsService.setAssetsPath(app.isPackaged ? path.join(process.resourcesPath, 'assets') : path.join(__dirname, '../../assets'));
BsModsManagerService.getInstance().getInstalledMods({BSVersion: "1.18.3"}).then(mods => {
console.log(mods);
})
if (process.env.NODE_ENV === 'production') {
const sourceMapSupport = require('source-map-support');
sourceMapSupport.install();
@@ -14,6 +14,8 @@ export class BsModsManagerService {
private bsLocalService: BSLocalVersionService;
private utilsService: UtilsService;
private manifestMatches: Mod[];
public static getInstance(): BsModsManagerService{
if(!BsModsManagerService.instance){ BsModsManagerService.instance = new BsModsManagerService(); }
return BsModsManagerService.instance;
@@ -51,12 +53,24 @@ export class BsModsManagerService {
return (async() => {
const filePath = path.join(modsPath, f)
const ext = path.extname(f);
if(ext !== ".dll" && ext !== ".exe" && ext !== ".manifest"){ return; }
if(ext !== ".dll" && ext !== ".exe" && ext !== ".manifest"){ return undefined; }
const hash = await md5File(filePath);
return this.getModFromHash(hash);
const mod = await this.getModFromHash(hash);
if(!mod){ return undefined; }
if(ext === ".manifest"){
this.manifestMatches.push(mod);
return undefined;
}
if(filePath.includes("Libs")){
if(!this.manifestMatches.some(m => m.name === mod.name)){ return undefined; }
const modIndex = this.manifestMatches.indexOf(mod);
if(modIndex > -1){ this.manifestMatches.splice(modIndex, 1); }
}
return mod;
})()
});
return Promise.all(promises)
const mods = await Promise.all(promises)
return mods.filter(m => !!m);
}
private async getBsipaInstalled(version: BSVersion): Promise<Mod>{
@@ -72,10 +86,17 @@ export class BsModsManagerService {
}
public async getInstalledMods(version: BSVersion): Promise<Mod[]>{
this.manifestMatches = [];
await this.beatModsApi.loadAllMods();
this.getBsipaInstalled(version).then(bsipa => console.log(bsipa));
this.getModsInDir(version, ModsInstallFolder.LIBS).then(mods => console.log(mods));
return [];
const bsipa = await this.getBsipaInstalled(version);
return Promise.all([
this.getModsInDir(version, ModsInstallFolder.PLUGINS_PENDING),
this.getModsInDir(version, ModsInstallFolder.LIBS_PENDING),
this.getModsInDir(version, ModsInstallFolder.PLUGINS),
this.getModsInDir(version, ModsInstallFolder.LIBS)
]).then(dirMods => {
return [((!!bsipa) && bsipa), ...Array.from(new Map<string, Mod>(dirMods.flat().map(m => [m.name, m])).values())];
})
}
public installMods(mods: Mod[], version: BSVersion){
@@ -0,0 +1,23 @@
import {motion, useCycle} from "framer-motion"
import { useState } from "react"
type Props = {className?: string, nbClickToShow?: number, children?: JSX.Element}
export function SpoilerClick({className, children, nbClickToShow = 5}: Props) {
const [remainingClicks, setRemainingClicks] = useState(nbClickToShow);
const [translateY, setTranslateY] = useState("100%")
console.log(translateY);
const handleClicks = () => {
if(remainingClicks - 1 > 0){ setRemainingClicks(nb => nb - 1); }
setTranslateY(`${(((remainingClicks - 1) / nbClickToShow) * 100)}%`)
}
return (
<motion.div className={className} initial={{y: translateY}} animate={{y: translateY}} transition={{type: "spring", stiffness: 300, mass: 1 }} onClick={handleClicks}>
{children}
</motion.div>
)
}
@@ -21,7 +21,7 @@ export function BsmCheckbox({className, checked, onChange, disabled} : Props) {
{!disabled && <div className="glow-on-hover !w-[calc(100%+6px)] !h-[calc(100%+6px)] !-top-[3px] !-left-[3px] group-hover:opacity-100"/>}
<div className={`w-full h-full bg-inherit border-2 rounded-md overflow-hidden flex items-center justify-center relative ${disabled ? "brightness-50 cursor-not-allowed" : "cursor-pointer"}`} onClickCapture={e => {e.stopPropagation(); handleClick()}}>
<motion.span className="absolute w-full h-full flex items-center justify-center" style={{backgroundColor: checkedColor}} initial={checked ? {scale: 1} : {scale: 0}} animate={checked ? {scale: 1} : {scale: 0}} transition={{duration: .1}}>
<motion.span className="absolute w-full h-full flex items-center justify-center" style={{backgroundColor: checkedColor}} initial={checked ? {scale: 1} : {scale: 0}} animate={checked ? {scale: 1} : {scale: 0}} transition={{duration: .15}}>
<BsmIcon icon="check" style={{color: iconColor}}/>
</motion.span>
</div>
@@ -36,7 +36,7 @@ export function ModsGrid({modsMap, installed, modsSelected, onModChange, moreInf
}
return modsMap && (
<div className="grid gap-y-1 grid-cols-[40px_min-content_min-content_min-content_1fr_min-content]">
<div className="grid gap-y-1 grid-cols-[40px_min-content_min-content_min-content_1fr_min-content]">
<span className="absolute z-10 top-0 w-full h-8 bg-main-color-2"/>
<span className="z-10 sticky flex items-center justify-center top-0 bg-main-color-2 border-b-2 border-main-color-1">
<div className="pl-4">
@@ -8,7 +8,10 @@ import { ConfigurationService } from "renderer/services/configuration.service";
import { DefaultConfigKey } from "renderer/config/default-configuration.config";
import { BsmButton } from "renderer/components/shared/bsm-button.component";
import { IpcService } from "renderer/services/ipc.service";
import BeatWaitingImg from "../../../../../../assets/images/apngs/beat-waiting.png"
import { SpoilerClick } from "renderer/components/shared/UwU/spoiler-click.component";
import YuruYuriDance from "../../../../../../assets/images/gifs/yuruyuri-dance.gif"
export function ModsSlide({version}: {version: BSVersion}) {
const modsManager = BsModsManagerService.getInstance();
@@ -54,12 +57,15 @@ export function ModsSlide({version}: {version: BSVersion}) {
useEffect(() => {
if(isVisible){
modsManager.getAvailableMods(version).then(mods => {
setModsAvailable(modsToCategoryMap(mods));
Promise.all([
modsManager.getAvailableMods(version),
modsManager.getInstalledMods(version)
]).then(([available, installed]) => {
const defaultMods = configService.get<string[]>("default_mods" as DefaultConfigKey);
setModsSelected(mods.filter(m => m.required || defaultMods.some(d => m.name === d)));
setModsAvailable(modsToCategoryMap(available));
setModsSelected(available.filter(m => m.required || defaultMods.some(d => m.name === d)));
setModsInstalled(modsToCategoryMap(installed))
});
modsManager.getInstalledMods(version).then(mods => setModsInstalled(modsToCategoryMap(mods)));
}
return () => {
@@ -75,13 +81,25 @@ export function ModsSlide({version}: {version: BSVersion}) {
<VisibilitySensor onChange={setIsVisible}>
<div className='shrink-0 w-full h-full px-8 pb-7 flex justify-center'>
<div className='relative flex flex-col grow-0 bg-light-main-color-2 dark:bg-main-color-2 h-full w-full rounded-md shadow-black shadow-center overflow-hidden'>
<div className="overflow-scroll w-full shrink min-h-0 scrollbar-thin scrollbar-thumb-neutral-900 scrollbar-thumb-rounded-full">
<ModsGrid modsMap={modsAvailable} installed={modsInstalled} modsSelected={modsSelected} onModChange={handleModChange} moreInfoMod={moreInfoMod} onWantInfos={handleMoreInfo}/>
</div>
<div className="h-10 shrink-0 flex items-center justify-between px-3">
<BsmButton className="rounded-md px-2 py-[2px]" text="Plus d'infos" typeColor="cancel" withBar={false} disabled={!moreInfoMod} onClick={handleOpenMoreInfo}/>
<BsmButton className="rounded-md px-2 py-[2px]" text="Installer ou mettre à jour" withBar={false} typeColor="primary" onClick={installMods}/>
</div>
{modsAvailable ? (
<>
<div className="overflow-scroll w-full shrink min-h-0 scrollbar-thin scrollbar-thumb-neutral-900 scrollbar-thumb-rounded-full">
<ModsGrid modsMap={modsAvailable} installed={modsInstalled} modsSelected={modsSelected} onModChange={handleModChange} moreInfoMod={moreInfoMod} onWantInfos={handleMoreInfo}/>
</div>
<div className="h-10 shrink-0 flex items-center justify-between px-3">
<BsmButton className="rounded-md px-2 py-[2px]" text="Plus d'infos" typeColor="cancel" withBar={false} disabled={!moreInfoMod} onClick={handleOpenMoreInfo}/>
<BsmButton className="rounded-md px-2 py-[2px]" text="Installer ou mettre à jour" withBar={false} typeColor="primary" onClick={installMods}/>
</div>
</>
) : (
<div className="w-full h-full flex flex-col items-center justify-center relative">
<img className="w-32 h-32 spin-loading" src={BeatWaitingImg}></img>
<span className="text-xl mt-3 h-0 italic">Chargement des mods...</span>
<SpoilerClick className="absolute right-5 w-20 h-[120px] bottom-5 cursor-pointer">
<img className="relative w-full" src={YuruYuriDance}/>
</SpoilerClick>
</div>
)}
</div>
</div>
</VisibilitySensor>
@@ -21,8 +21,8 @@ export class BsModsManagerService {
return this.ipcService.send<Mod[], BSVersion>("get-available-mods", {args: version}).then(res => res.data);
}
public async getInstalledMods(version: BSVersion): Promise<Mod[]>{
return [];
public getInstalledMods(version: BSVersion): Promise<Mod[]>{
return this.ipcService.send<Mod[], BSVersion>("get-installed-mods", {args: version}).then(res => res.data);
}
public installMods(mods: Mod[], version: BSVersion){