mirror of
https://github.com/Zagrios/bs-manager.git
synced 2026-07-03 14:08:25 +02:00
add mods loader and get installed mods finished
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 260 KiB |
@@ -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}));
|
||||
});
|
||||
@@ -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){
|
||||
|
||||
Reference in New Issue
Block a user