mirror of
https://github.com/Zagrios/bs-manager.git
synced 2026-07-03 14:08:25 +02:00
Merge pull request #540 from Zagrios/qol/dont-reinstall-all-mods-by-default
[qol] dont reinstall all mods by default
This commit is contained in:
@@ -73,7 +73,8 @@
|
||||
"mods-not-available": "Für diese Version von Beat Saber sind noch keine Mods verfügbar",
|
||||
"buttons": {
|
||||
"more-infos": "Mehr Infos",
|
||||
"install-or-update": "Installieren oder aktualisieren"
|
||||
"install-or-update": "Installieren oder aktualisieren",
|
||||
"reinstall-all": "Alles neu installieren"
|
||||
},
|
||||
"mods-grid": {
|
||||
"header-bar": {
|
||||
|
||||
@@ -73,7 +73,8 @@
|
||||
"mods-not-available": "No mods are available yet for this version of Beat Saber",
|
||||
"buttons": {
|
||||
"more-infos": "More info",
|
||||
"install-or-update": "Install or update"
|
||||
"install-or-update": "Install or update",
|
||||
"reinstall-all": "Reinstall all"
|
||||
},
|
||||
"mods-grid": {
|
||||
"header-bar": {
|
||||
|
||||
@@ -73,7 +73,8 @@
|
||||
"mods-not-available": "Aún no hay mods disponibles para esta versión de Beat Saber",
|
||||
"buttons": {
|
||||
"more-infos": "Más información",
|
||||
"install-or-update": "Instalar o actualizar"
|
||||
"install-or-update": "Instalar o actualizar",
|
||||
"reinstall-all": "Reinstalar todo"
|
||||
},
|
||||
"mods-grid": {
|
||||
"header-bar": {
|
||||
|
||||
@@ -73,7 +73,8 @@
|
||||
"mods-not-available": "Aucun mod n'est encore disponible pour cette version de Beat Saber",
|
||||
"buttons": {
|
||||
"more-infos": "Plus d'infos",
|
||||
"install-or-update": "Installer ou mettre à jour"
|
||||
"install-or-update": "Installer ou mettre à jour",
|
||||
"reinstall-all": "Tout réinstaller"
|
||||
},
|
||||
"mods-grid": {
|
||||
"header-bar": {
|
||||
|
||||
@@ -73,7 +73,8 @@
|
||||
"mods-not-available": "このバージョンで使用できるMODはまだありません。",
|
||||
"buttons": {
|
||||
"more-infos": "詳細情報",
|
||||
"install-or-update": "インストールとアップデート"
|
||||
"install-or-update": "インストールとアップデート",
|
||||
"reinstall-all": "すべて再インストール"
|
||||
},
|
||||
"mods-grid": {
|
||||
"header-bar": {
|
||||
|
||||
@@ -73,7 +73,8 @@
|
||||
"mods-not-available": "Не найдены моды для этой версии Beat Saber",
|
||||
"buttons": {
|
||||
"more-infos": "Подробнее",
|
||||
"install-or-update": "Установить или обновить"
|
||||
"install-or-update": "Установить или обновить",
|
||||
"reinstall-all": "Переустановить все"
|
||||
},
|
||||
"mods-grid": {
|
||||
"header-bar": {
|
||||
|
||||
@@ -73,7 +73,8 @@
|
||||
"mods-not-available": "該版本 BeatSaber 暫無可用 Mod",
|
||||
"buttons": {
|
||||
"more-infos": "更多資訊",
|
||||
"install-or-update": "安裝或更新"
|
||||
"install-or-update": "安裝或更新",
|
||||
"reinstall-all": "重新安裝全部"
|
||||
},
|
||||
"mods-grid": {
|
||||
"header-bar": {
|
||||
|
||||
@@ -73,7 +73,8 @@
|
||||
"mods-not-available": "该版本 BeatSaber 暂无可用 Mod",
|
||||
"buttons": {
|
||||
"more-infos": "更多信息",
|
||||
"install-or-update": "安装或更新"
|
||||
"install-or-update": "安装或更新",
|
||||
"reinstall-all": "重新安装全部"
|
||||
},
|
||||
"mods-grid": {
|
||||
"header-bar": {
|
||||
|
||||
@@ -346,15 +346,12 @@ export class BsModsManagerService {
|
||||
throw CustomError.fromError(new Error("No mods to install"), "no-mods");
|
||||
}
|
||||
|
||||
const deps = await this.resolveDependencies(mods, version);
|
||||
mods.push(...deps);
|
||||
|
||||
const bsipa = mods.find(mod => mod.name.toLowerCase() === "bsipa");
|
||||
if (bsipa) {
|
||||
mods = mods.filter(mod => mod.name.toLowerCase() !== "bsipa");
|
||||
}
|
||||
|
||||
this.nbModsToInstall = mods.length + (bsipa && 1);
|
||||
this.nbModsToInstall = mods.length + (bsipa ? 1 : 0);
|
||||
this.nbInstalledMods = 0;
|
||||
|
||||
if (bsipa) {
|
||||
|
||||
@@ -6,11 +6,12 @@ import { useClickOutside } from "renderer/hooks/use-click-outside.hook";
|
||||
import { useThemeColor } from "renderer/hooks/use-theme-color.hook";
|
||||
import { getCorrectTextColor } from "renderer/helpers/correct-text-color";
|
||||
|
||||
type BsmButtonType = "primary" | "secondary" | "success" | "cancel" | "error" | "none";
|
||||
export type BsmButtonType = "primary" | "secondary" | "success" | "cancel" | "error" | "none";
|
||||
|
||||
type Props = {
|
||||
className?: string;
|
||||
style?: CSSProperties;
|
||||
iconStyle?: CSSProperties;
|
||||
imgClassName?: string;
|
||||
iconClassName?: string;
|
||||
icon?: BsmIconType;
|
||||
@@ -29,7 +30,7 @@ type Props = {
|
||||
textClassName?: string;
|
||||
};
|
||||
|
||||
export const BsmButton = forwardRef<unknown, Props>(({ className, style, imgClassName, iconClassName, icon, image, text, type, active, withBar = true, disabled, onClickOutside, onClick, typeColor, color, title, iconColor, textClassName }, forwardedRef) => {
|
||||
export const BsmButton = forwardRef<unknown, Props>(({ className, style, iconStyle, imgClassName, iconClassName, icon, image, text, type, active, withBar = true, disabled, onClickOutside, onClick, typeColor, color, title, iconColor, textClassName }, forwardedRef) => {
|
||||
const t = useTranslation();
|
||||
const { firstColor, secondColor } = useThemeColor();
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
@@ -86,10 +87,10 @@ export const BsmButton = forwardRef<unknown, Props>(({ className, style, imgClas
|
||||
return (
|
||||
<div ref={setRef} onClick={handleClick} title={t(title)} className={`${className} overflow-hidden group ${!withBar && !disabled && (!!typeColor || !!color) && "hover:brightness-[1.15]"} ${disabled ? "brightness-75 cursor-not-allowed" : "cursor-pointer"} ${renderTypeColor}`} style={{ ...style, backgroundColor: primaryColor || color }}>
|
||||
{image && <BsmImage image={image} className={imgClassName} />}
|
||||
{icon && <BsmIcon icon={icon} className={iconClassName ?? "h-full w-full text-gray-800 dark:text-white"} style={{ color: iconColor || textColor }} />}
|
||||
{icon && <BsmIcon icon={icon} className={iconClassName ?? "size-full text-gray-800 dark:text-white"} style={{ ...(iconStyle ?? {}), color: (iconColor || textColor) }} />}
|
||||
{text &&
|
||||
(type === "submit" ? (
|
||||
<button type="submit" className={textClassName || "h-full w-full"} style={{ ...(!!textColor && { color: textColor }) }}>
|
||||
<button type="submit" className={textClassName || "size-full"} style={{ ...(!!textColor && { color: textColor }) }}>
|
||||
{t(text)}
|
||||
</button>
|
||||
) : (
|
||||
@@ -99,8 +100,8 @@ export const BsmButton = forwardRef<unknown, Props>(({ className, style, imgClas
|
||||
))}
|
||||
{withBar && (
|
||||
<div className="absolute bottom-0 left-0 w-full h-1 bg-current" style={{ color: secondColor }}>
|
||||
<div className="absolute top-0 left-0 h-full w-full bg-current brightness-50" />
|
||||
<div className={`absolute top-0 left-0 h-full w-full bg-inherit -translate-x-full group-hover:translate-x-0 transition-transform shadow-center shadow-current ${active && "translate-x-0"}`} />
|
||||
<div className="absolute top-0 left-0 size-full bg-current brightness-50" />
|
||||
<div className={`absolute top-0 left-0 size-full bg-inherit -translate-x-full group-hover:translate-x-0 transition-transform shadow-center shadow-current ${active && "translate-x-0"}`} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { forwardRef, LegacyRef, useImperativeHandle, useRef, useState } from "react";
|
||||
import { BsmIconType, BsmIcon } from "../svgs/bsm-icon.component";
|
||||
import { BsmButton } from "./bsm-button.component";
|
||||
import { BsmButton, BsmButtonType } from "./bsm-button.component";
|
||||
import { useTranslation } from "renderer/hooks/use-translation.hook";
|
||||
import { AnimatePresence } from "framer-motion";
|
||||
import { useClickOutside } from "renderer/hooks/use-click-outside.hook";
|
||||
import { cn } from "renderer/helpers/css-class.helpers";
|
||||
|
||||
export interface DropDownItem {
|
||||
text: string;
|
||||
@@ -11,8 +12,17 @@ export interface DropDownItem {
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
type ClassNames = {
|
||||
mainContainer?: string;
|
||||
button?: string;
|
||||
itemsContainer?: string;
|
||||
iconClassName?: string;
|
||||
}
|
||||
|
||||
type Props = {
|
||||
className?: string;
|
||||
classNames?: ClassNames;
|
||||
buttonColor?: BsmButtonType;
|
||||
items?: DropDownItem[];
|
||||
align?: "left" | "right" | "center";
|
||||
withBar?: boolean;
|
||||
@@ -24,7 +34,7 @@ type Props = {
|
||||
textClassName?: string;
|
||||
};
|
||||
|
||||
export const BsmDropdownButton = forwardRef(({ className, items, align, withBar = true, icon = "settings", buttonClassName, menuTranslationY, children, text, textClassName }: Props, fowardRed) => {
|
||||
export const BsmDropdownButton = forwardRef(({ className, classNames, buttonColor, items, align, withBar = true, icon = "settings", buttonClassName, menuTranslationY, children, text, textClassName }: Props, fowardRed) => {
|
||||
const [expanded, setExpanded] = useState(false);
|
||||
const t = useTranslation();
|
||||
const ref = useRef(fowardRed);
|
||||
@@ -63,9 +73,9 @@ export const BsmDropdownButton = forwardRef(({ className, items, align, withBar
|
||||
})();
|
||||
|
||||
return (
|
||||
<div ref={ref as unknown as LegacyRef<HTMLDivElement>} className={className}>
|
||||
<BsmButton onClick={() => setExpanded(!expanded)} className={buttonClassName ?? defaultButtonClassName} icon={icon} active={expanded} textClassName={textClassName} onClickOutside={handleClickOutside} withBar={withBar} text={text} />
|
||||
<div className={`py-1 w-fit absolute cursor-pointer top-[calc(100%-4px)] rounded-md bg-inherit text-sm text-gray-800 dark:text-gray-200 shadow-md shadow-black transition-[scale] duration-150 ease-in-out ${alignClass}`} style={{ scale: expanded ? "1" : "0", translate: `0 ${menuTranslationY}` }}>
|
||||
<div ref={ref as unknown as LegacyRef<HTMLDivElement>} className={cn(className, classNames?.mainContainer)}>
|
||||
<BsmButton onClick={() => setExpanded(!expanded)} className={cn(buttonClassName ?? defaultButtonClassName, classNames?.button)} icon={icon} active={expanded} textClassName={textClassName} onClickOutside={handleClickOutside} withBar={withBar} text={text} typeColor={buttonColor} iconClassName={classNames?.iconClassName}/>
|
||||
<div className={cn(`py-1 w-fit absolute cursor-pointer top-[calc(100%-4px)] rounded-md bg-inherit text-sm text-gray-800 dark:text-gray-200 shadow-md shadow-black transition-[scale] duration-150 ease-in-out ${alignClass}`, classNames?.itemsContainer)} style={{ scale: expanded ? "1" : "0", translate: `0 ${menuTranslationY}` }}>
|
||||
{items?.map(
|
||||
i =>
|
||||
i && (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { BsmButton } from "renderer/components/shared/bsm-button.component";
|
||||
import { BsmCheckbox } from "renderer/components/shared/bsm-checkbox.component";
|
||||
import { Mod } from "shared/models/mods/mod.interface";
|
||||
import { CSSProperties, MouseEvent, useRef } from "react";
|
||||
import { CSSProperties, MouseEvent, useMemo, useRef } from "react";
|
||||
import { useThemeColor } from "renderer/hooks/use-theme-color.hook";
|
||||
import { BsModsManagerService } from "renderer/services/bs-mods-manager.service";
|
||||
import { useObservable } from "renderer/hooks/use-observable.hook";
|
||||
@@ -9,6 +9,7 @@ import { PageStateService } from "renderer/services/page-state.service";
|
||||
import useDoubleClick from "use-double-click";
|
||||
import { gt } from "semver";
|
||||
import { useService } from "renderer/hooks/use-service.hook";
|
||||
import { useOnUpdate } from "renderer/hooks/use-on-update.hook";
|
||||
|
||||
type Props = { className?: string; mod: Mod; installedVersion: string; isDependency?: boolean; isSelected?: boolean; onChange?: (val: boolean) => void; wantInfo?: boolean; onWantInfo?: (mod: Mod) => void };
|
||||
|
||||
@@ -20,6 +21,8 @@ export function ModItem({ className, mod, installedVersion, isDependency, isSele
|
||||
const uninstalling = useObservable(() => modsManager.isUninstalling$);
|
||||
const clickRef = useRef();
|
||||
|
||||
const isChecked = useMemo(() => isDependency || isSelected || mod.required, [isDependency, isSelected, mod.required]);
|
||||
|
||||
useDoubleClick({
|
||||
onSingleClick: e => handleWantInfo(e),
|
||||
onDoubleClick: e => handleOnChange(e),
|
||||
@@ -27,6 +30,10 @@ export function ModItem({ className, mod, installedVersion, isDependency, isSele
|
||||
latency: 175,
|
||||
});
|
||||
|
||||
useOnUpdate(() => {
|
||||
onChange(isChecked);
|
||||
}, [isChecked]);
|
||||
|
||||
const wantInfoStyle: CSSProperties = wantInfo ? { borderColor: themeColor } : { borderColor: "transparent" };
|
||||
const isOutDated = installedVersion ? gt(mod.version, installedVersion) : false;
|
||||
|
||||
@@ -34,21 +41,19 @@ export function ModItem({ className, mod, installedVersion, isDependency, isSele
|
||||
modsManager.uninstallMod(mod, pageState.getState());
|
||||
};
|
||||
|
||||
const handleWantInfo = (e: MouseEvent<Element, MouseEvent>) => {
|
||||
const handleWantInfo = (e: MouseEvent) => {
|
||||
e.preventDefault();
|
||||
onWantInfo(mod);
|
||||
};
|
||||
const handleOnChange = (e: MouseEvent<Element, MouseEvent>) => {
|
||||
const handleOnChange = (e: MouseEvent) => {
|
||||
e.preventDefault();
|
||||
onChange(!isChecked);
|
||||
};
|
||||
|
||||
const isChecked = isDependency || isSelected || mod.required;
|
||||
|
||||
return (
|
||||
<li ref={clickRef} className={`${className} group`}>
|
||||
<div className="h-full aspect-square flex items-center justify-center p-[7px] rounded-l-md bg-inherit ml-3 border-2 border-r-0 z-[1] group-hover:brightness-90" style={wantInfoStyle}>
|
||||
<BsmCheckbox className="h-full aspect-square z-[1] relative bg-inherit" onChange={onChange} disabled={mod.required || isDependency} checked={isChecked} />
|
||||
<BsmCheckbox className="h-full aspect-square z-[1] relative bg-inherit" onChange={() => onChange(!isChecked)} disabled={mod.required || isDependency} checked={isChecked} />
|
||||
</div>
|
||||
<span className="bg-inherit py-2 pl-3 font-bold text-sm whitespace-nowrap border-t-2 border-b-2 blur-none group-hover:brightness-90" style={wantInfoStyle}>
|
||||
{mod.name}
|
||||
|
||||
@@ -12,7 +12,7 @@ import { useService } from "renderer/hooks/use-service.hook";
|
||||
type Props = { modsMap: Map<string, Mod[]>; installed: Map<string, Mod[]>; modsSelected: Mod[]; onModChange: (selected: boolean, mod: Mod) => void; moreInfoMod?: Mod; onWantInfos: (mod: Mod) => void };
|
||||
|
||||
export function ModsGrid({ modsMap, installed, modsSelected, onModChange, moreInfoMod, onWantInfos }: Props) {
|
||||
|
||||
|
||||
const pageState = useService(PageStateService);
|
||||
const modsManager = useService(BsModsManagerService);
|
||||
|
||||
@@ -24,7 +24,7 @@ export function ModsGrid({ modsMap, installed, modsSelected, onModChange, moreIn
|
||||
if (!installed?.get(key)) {
|
||||
return undefined;
|
||||
}
|
||||
const installedMod = installed.get(key).find(m => m.name === mod.name);
|
||||
const installedMod = installed.get(key).find(m => m._id === mod._id);
|
||||
if (!installedMod) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -36,16 +36,16 @@ export function ModsGrid({ modsMap, installed, modsSelected, onModChange, moreIn
|
||||
const deps = m.dependencies.map(dep =>
|
||||
Array.from(modsMap.values())
|
||||
.flat()
|
||||
.find(m => dep.name === m.name)
|
||||
.find(m => dep._id === m._id)
|
||||
);
|
||||
if (deps.some(depMod => depMod.name === mod.name)) {
|
||||
if (deps.some(depMod => depMod._id === mod._id)) {
|
||||
return true;
|
||||
}
|
||||
return deps.some(depMod => depMod.dependencies.some(depModDep => depModDep.name === mod.name));
|
||||
return deps.some(depMod => depMod.dependencies.some(depModDep => depModDep._id === mod._id));
|
||||
});
|
||||
};
|
||||
|
||||
const isSelected = (mod: Mod): boolean => modsSelected.some(m => m.name === mod.name);
|
||||
const isSelected = (mod: Mod): boolean => modsSelected.some(m => m._id === mod._id);
|
||||
|
||||
const handleInput = (val: string) => setFilter(val.toLowerCase());
|
||||
|
||||
@@ -61,8 +61,8 @@ export function ModsGrid({ modsMap, installed, modsSelected, onModChange, moreIn
|
||||
return (
|
||||
modsMap && (
|
||||
<div className="grid gap-y-1 grid-cols-[40px_min-content_min-content_min-content_1fr_min-content] bg-light-main-color-2 dark:bg-main-color-2 text-main-color-1 dark:text-light-main-color-1">
|
||||
<span className="absolute z-10 top-0 w-full h-8 bg-inherit" />
|
||||
<span className="z-10 sticky flex items-center justify-end top-0 bg-inherit border-b-2 border-main-color-1">
|
||||
<span className="absolute z-10 top-0 w-full h-8 bg-inherit rounded-tl-md" />
|
||||
<span className="z-10 sticky flex items-center justify-end top-0 bg-inherit border-b-2 border-main-color-1 rounded-tl-md">
|
||||
<BsmButton className="rounded-full h-6 w-6 p-[2px]" withBar={false} icon="search" onClick={handleToogleFilter} />
|
||||
</span>
|
||||
<span className="z-10 sticky top-0 flex items-center bg-inherit border-main-color-1 border-b-2 h-8 px-1 whitespace-nowrap">{filterEnabled ? <motion.input autoFocus className="bg-main-color-1 rounded-md h-6 px-2" initial={{ width: 0 }} animate={{ width: "250px" }} transition={{ ease: "easeInOut", duration: 0.15 }} onChange={e => handleInput(e.target.value)} /> : <span className="w-full text-center">{t("pages.version-viewer.mods.mods-grid.header-bar.name")}</span>}</span>
|
||||
|
||||
@@ -19,12 +19,14 @@ import { ModsDisclaimerModal } from "renderer/components/modal/modal-types/mods-
|
||||
import { OsDiagnosticService } from "renderer/services/os-diagnostic.service";
|
||||
import { lt } from "semver";
|
||||
import { useService } from "renderer/hooks/use-service.hook";
|
||||
import { NotificationService } from "renderer/services/notification.service";
|
||||
|
||||
export function ModsSlide({ version, onDisclamerDecline }: { version: BSVersion; onDisclamerDecline: () => void }) {
|
||||
const ACCEPTED_DISCLAIMER_KEY = "accepted-mods-disclaimer";
|
||||
|
||||
const modsManager = useService(BsModsManagerService);
|
||||
const configService = useService(ConfigurationService);
|
||||
const notification = useService(NotificationService);
|
||||
const linkOpener = useService(LinkOpenerService);
|
||||
const modals = useService(ModalService);
|
||||
const os = useService(OsDiagnosticService);
|
||||
@@ -35,6 +37,7 @@ export function ModsSlide({ version, onDisclamerDecline }: { version: BSVersion;
|
||||
const [modsInstalled, setModsInstalled] = useState(null as Map<string, Mod[]>);
|
||||
const [modsSelected, setModsSelected] = useState([] as Mod[]);
|
||||
const [moreInfoMod, setMoreInfoMod] = useState(null as Mod);
|
||||
const [reinstallAllMods, setReinstallAllMods] = useState(false);
|
||||
const isOnline = useObservable(() => os.isOnline$);
|
||||
const installing = useObservable(() => modsManager.isInstalling$);
|
||||
|
||||
@@ -51,15 +54,17 @@ export function ModsSlide({ version, onDisclamerDecline }: { version: BSVersion;
|
||||
};
|
||||
|
||||
const handleModChange = (selected: boolean, mod: Mod) => {
|
||||
|
||||
if (selected) {
|
||||
return setModsSelected([...modsSelected, mod]);
|
||||
return setModsSelected(mods => {
|
||||
if (mods.some(m => m._id === mod._id)) {
|
||||
return mods;
|
||||
}
|
||||
return [...mods, mod];
|
||||
});
|
||||
}
|
||||
const mods = [...modsSelected];
|
||||
mods.splice(
|
||||
mods.findIndex(m => m.name === mod.name),
|
||||
1
|
||||
);
|
||||
setModsSelected(mods);
|
||||
|
||||
setModsSelected(mods => mods.filter(m => m._id !== mod._id));
|
||||
};
|
||||
|
||||
const handleMoreInfo = (mod: Mod) => {
|
||||
@@ -76,25 +81,28 @@ export function ModsSlide({ version, onDisclamerDecline }: { version: BSVersion;
|
||||
linkOpener.open(moreInfoMod.link);
|
||||
};
|
||||
|
||||
const installMods = () => {
|
||||
const installMods = (reinstallAll: boolean): void => {
|
||||
|
||||
setReinstallAllMods(() => false);
|
||||
|
||||
if (installing) {
|
||||
return;
|
||||
}
|
||||
|
||||
const modsToInstall = modsSelected.filter(mod => {
|
||||
const corespondingMod = modsAvailable.get(mod.category).find(availabeMod => availabeMod._id === mod._id);
|
||||
const installedMod = modsInstalled.get(mod.category)?.find(installedMod => installedMod.name === mod.name);
|
||||
const installedMod = modsInstalled.get(mod.category)?.find(installedMod => installedMod._id === mod._id);
|
||||
|
||||
if (corespondingMod?.version && lt(corespondingMod.version, mod.version)) {
|
||||
return false;
|
||||
}
|
||||
if(reinstallAll || !installedMod){ return true; }
|
||||
|
||||
if(installedMod?.version && lt(mod.version, installedMod?.version)){
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return lt(installedMod.version, mod.version);
|
||||
});
|
||||
|
||||
if (!modsToInstall.length) {
|
||||
notification.notifyInfo({ title: "Mods déjà installées", desc: "Tous les mods séléctionnées sont déjà installées" });
|
||||
loadMods();
|
||||
return;
|
||||
}
|
||||
|
||||
modsManager.installMods(modsToInstall, version).then(() => {
|
||||
loadMods();
|
||||
});
|
||||
@@ -186,13 +194,17 @@ export function ModsSlide({ version, onDisclamerDecline }: { version: BSVersion;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<div className="grow overflow-y-scroll w-full min-h-0 scrollbar-default">
|
||||
<div className="grow overflow-y-scroll w-full min-h-0 scrollbar-default p-0 m-0">
|
||||
<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="text-center rounded-md px-2 py-[2px]" text="pages.version-viewer.mods.buttons.more-infos" typeColor="cancel" withBar={false} disabled={!moreInfoMod} onClick={handleOpenMoreInfo} style={{ width: downloadWith }} />
|
||||
<div ref={downloadRef}>
|
||||
<BsmButton className="text-center rounded-md px-2 py-[2px]" text="pages.version-viewer.mods.buttons.install-or-update" withBar={false} disabled={installing} typeColor="primary" onClick={installMods} />
|
||||
<div className="shrink-0 flex items-center justify-between px-3 py-2">
|
||||
<BsmButton className="flex items-center justify-center rounded-md px-1 h-8" text="pages.version-viewer.mods.buttons.more-infos" typeColor="cancel" withBar={false} disabled={!moreInfoMod} onClick={handleOpenMoreInfo} style={{ width: downloadWith }}/>
|
||||
<div ref={downloadRef} className="flex h-8 justify-center items-center gap-px overflow-hidden rounded-md">
|
||||
<div className="grow h-full relative">
|
||||
<BsmButton className="relative left-0 flex items-center justify-center px-2 size-full transition-[top] duration-200 ease-in-out" text="pages.version-viewer.mods.buttons.install-or-update" typeColor="primary" withBar={false} onClick={() => installMods(false)} style={{ top: reinstallAllMods ? "-100%" : "0" }} />
|
||||
<BsmButton className="relative left-0 flex items-center justify-center px-2 size-full transition-[top] duration-200 ease-in-out " text="pages.version-viewer.mods.buttons.reinstall-all" typeColor="primary" withBar={false} onClick={() => installMods(true)} style={{ top: reinstallAllMods ? "-100%" : "0" }}/>
|
||||
</div>
|
||||
<BsmButton className="flex items-center justify-center shrink-0 h-full" iconClassName="transition-transform size-full ease-in-out duration-200" iconStyle={{ transform: reinstallAllMods ? "rotate(360deg)" : "rotate(180deg)" }} icon="chevron-top" typeColor="primary" withBar={false} onClick={() => setReinstallAllMods(prev => !prev)}/>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
@@ -201,7 +213,7 @@ export function ModsSlide({ version, onDisclamerDecline }: { version: BSVersion;
|
||||
|
||||
return (
|
||||
<div ref={ref} 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">{renderContent()}</div>
|
||||
<div className="relative flex flex-col grow-0 bg-light-main-color-2 dark:bg-main-color-2 size-full rounded-md shadow-black shadow-center overflow-hidden">{renderContent()}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user