mirror of
https://github.com/Zagrios/bs-manager.git
synced 2026-07-03 14:08:25 +02:00
add mods disclaimer
This commit is contained in:
@@ -8,7 +8,9 @@
|
||||
"playlists": "Playlists",
|
||||
"models": "Models",
|
||||
"cancel": "Cancel",
|
||||
"delete": "Delete"
|
||||
"delete": "Delete",
|
||||
"accept": "Accept",
|
||||
"refuse": "Refuse"
|
||||
},
|
||||
"pages": {
|
||||
"version-viewer": {
|
||||
@@ -492,6 +494,14 @@
|
||||
"download-maps": {
|
||||
"search-btn": "Search",
|
||||
"loading-maps": "Loading maps..."
|
||||
},
|
||||
"mods-disclaimer":{
|
||||
"title": "disclaimer",
|
||||
"p-1": "By choosing to use mods, you understand that:",
|
||||
"li-1": "You may experience problems that don't exist in the vanilla game. 99.9% of bugs, crashes, and lag are due to mods.",
|
||||
"li-2": "Mods are subject to being broken by updates and that's normal - be patient and respectful when this happens, as modders are volunteers with real lives.",
|
||||
"li-3": "Beat Games aren't purposefully trying to break mods. They wish to work on the codebase and sometimes this breaks mods, but they are not out to kill mods.",
|
||||
"p-2": "Do not attack the game developers for issues related to mods, and vice versa - modders and game developers are two separate groups. Just don't be a jerk ok."
|
||||
}
|
||||
},
|
||||
"maps": {
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
"playlists": "Playlists",
|
||||
"models": "Modelos",
|
||||
"cancel": "Cancelar",
|
||||
"delete": "Borrar"
|
||||
"delete": "Borrar",
|
||||
"accept": "Aceptar",
|
||||
"refuse": "Rechazar"
|
||||
},
|
||||
"pages": {
|
||||
"version-viewer": {
|
||||
@@ -492,6 +494,14 @@
|
||||
"download-maps": {
|
||||
"search-btn": "buscar",
|
||||
"loading-maps": "Cargando mapas..."
|
||||
},
|
||||
"mods-disclaimer":{
|
||||
"title": "descargo de responsabilidad",
|
||||
"p-1": "Al elegir usar mods, entiendes y aceptas que:",
|
||||
"li-1": "Es posible que encuentres problemas que no existen en el juego base. El 99,9% de los errores, bloqueos y ralentizaciones son debidos a los mods.",
|
||||
"li-2": "Es probable que los mods dejen de funcionar debido a las actualizaciones y eso es normal. Sé paciente y respetuoso cuando suceda esto, ya que los modders son voluntarios y tienen una vida.",
|
||||
"li-3": "Beat Games no está intencionalmente tratando de romper los mods. Quieren mejorar el juego base y a veces esto rompe los mods, pero no es su objetivo matar a los mods.",
|
||||
"p-2": "No ataques a los desarrolladores por problemas relacionados con los mods y viceversa. Los modders y los desarrolladores son dos grupos distintos. No seas tonto, ¿de acuerdo?"
|
||||
}
|
||||
},
|
||||
"maps": {
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
"playlists": "Playlists",
|
||||
"models": "Modèles",
|
||||
"cancel": "Annuler",
|
||||
"delete": "Supprimer"
|
||||
"delete": "Supprimer",
|
||||
"accept": "Accepter",
|
||||
"refuse": "Refuser"
|
||||
},
|
||||
"pages": {
|
||||
"version-viewer": {
|
||||
@@ -492,6 +494,14 @@
|
||||
"download-maps": {
|
||||
"search-btn": "Rechercher",
|
||||
"loading-maps": "Chargement des maps..."
|
||||
},
|
||||
"mods-disclaimer":{
|
||||
"title": "avis de non-responsabilité",
|
||||
"p-1": "En choisissant d'utiliser des mods, vous comprenez et acceptez que :",
|
||||
"li-1": "Vous pouvez rencontrer des problèmes qui n'existent pas dans le jeu de base. 99.9% des bugs, plantages et ralentissements sont dus aux mods.",
|
||||
"li-2": "Les mods sont susceptibles de ne plus fonctionner à cause des mises à jour et c'est normal - soyez patient et respectueux lorsque cela se produit, parce que les moddeurs sont bénévoles et ont une vie.",
|
||||
"li-3": "Beat Games ne cherche pas volontairement à casser les mods. Ils souhaitent améliorer la base du jeu et parfois cela casse les mods, mais ce n'est pas dans leur objectif de tuer les mods.",
|
||||
"p-2": "N'attaquez pas les développeurs pour des problèmes relatifs aux mods, et inversement - les moddeurs et les développeurs sont deux groupes distincts. Ne sois pas idiot, d'accord ?"
|
||||
}
|
||||
},
|
||||
"maps": {
|
||||
|
||||
Generated
+5
-10
@@ -10354,7 +10354,8 @@
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
|
||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
||||
"dev": true
|
||||
},
|
||||
"object-hash": {
|
||||
"version": "3.0.0",
|
||||
@@ -11280,6 +11281,7 @@
|
||||
"version": "15.8.1",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
@@ -11672,7 +11674,8 @@
|
||||
"react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"dev": true
|
||||
},
|
||||
"react-range": {
|
||||
"version": "1.8.14",
|
||||
@@ -11737,14 +11740,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-visibility-sensor": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/react-visibility-sensor/-/react-visibility-sensor-5.1.1.tgz",
|
||||
"integrity": "sha512-cTUHqIK+zDYpeK19rzW6zF9YfT4486TIgizZW53wEZ+/GPBbK7cNS0EHyJVyHYacwFEvvHLEKfgJndbemWhB/w==",
|
||||
"requires": {
|
||||
"prop-types": "^15.7.2"
|
||||
}
|
||||
},
|
||||
"read-cache": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
||||
|
||||
@@ -244,7 +244,6 @@
|
||||
"react-dom": "^18.2.0",
|
||||
"react-range": "^1.8.14",
|
||||
"react-router-dom": "^6.3.0",
|
||||
"react-visibility-sensor": "^5.1.1",
|
||||
"regedit": "^5.1.1",
|
||||
"rxjs": "^7.5.6",
|
||||
"sanitize-filename": "^1.6.3",
|
||||
|
||||
@@ -23,7 +23,7 @@ export function AvailableVersionsSlider() {
|
||||
|
||||
return (
|
||||
<div className="w-full h-fit max-h-full flex flex-col items-center grow min-h-0">
|
||||
<TabNavBar className="mb-3" tabsText={availableYears} onTabChange={setSelectedYear}/>
|
||||
<TabNavBar className="mb-3" tabIndex={yearIndex} tabsText={availableYears} onTabChange={setSelectedYear}/>
|
||||
<ol className="w-full min-h-0 flex transition-transform duration-300" style={{transform: `translate(${-(yearIndex * 100)}%, 0)`}}>
|
||||
{ availableYears.map(year =>
|
||||
<AvailableVersionsSlide key={year} year={year}/>
|
||||
|
||||
+2
-2
@@ -82,7 +82,7 @@ export function MapsPlaylistsPanel({version}: Props) {
|
||||
{index === 0 &&(
|
||||
<div className="h-full flex absolute right-0 top-0 gap-1.5 items-center pr-2">
|
||||
{isOnline && (
|
||||
<motion.div whileHover={"hover"} whileTap={"tap"} className="relative h-[calc(100%-5px)] flex flex-row justify-center items-center shrink-0 rounded-full overflow-hidden pr-2" style={{color}} onClick={e => {e.stopPropagation(); onClickAdd(index)}}>
|
||||
<motion.div whileHover="hover" whileTap="tap" className="relative h-[calc(100%-5px)] flex flex-row justify-center items-center shrink-0 rounded-full overflow-hidden pr-2" style={{color}} onClick={e => {e.stopPropagation(); onClickAdd(index)}}>
|
||||
<span className="absolute top-0 left-0 h-full w-full brightness-50 opacity-75 dark:opacity-20 dark:filter-none" style={{backgroundColor: "currentcolor"}}/>
|
||||
<motion.div className="h-full p-0.5" variants={variants}>
|
||||
<BsmIcon className="block h-full aspect-square brightness-150" icon="add"/>
|
||||
@@ -128,7 +128,7 @@ export function MapsPlaylistsPanel({version}: Props) {
|
||||
<BsmDropdownButton className="h-full flex aspect-square relative rounded-full z-[1] bg-light-main-color-1 dark:bg-main-color-3" buttonClassName="rounded-full h-full w-full p-[6px]" icon="three-dots" withBar={false} items={dropDownItems} menuTranslationY="6px" align="center"/>
|
||||
</nav>
|
||||
<div className="w-full h-full flex flex-col bg-light-main-color-3 dark:bg-main-color-2 rounded-md shadow-black shadow-md overflow-hidden">
|
||||
<TabNavBar className="!rounded-none shadow-sm" tabsText={["misc.maps", "misc.playlists"]} onTabChange={setTabIndex} renderTab={renderTab}/>
|
||||
<TabNavBar className="!rounded-none shadow-sm" tabIndex={tabIndex} tabsText={["misc.maps", "misc.playlists"]} onTabChange={setTabIndex} renderTab={renderTab}/>
|
||||
<div className="w-full grow min-h-0 flex flex-row items-center transition-transform duration-300" style={{transform: `translate(${-(tabIndex * 100)}%, 0)`}}>
|
||||
<LocalMapsListPanel ref={mapsRef} className="w-full h-full shrink-0 flex flex-col" version={version} filter={mapFilter} search={mapSearch}/>
|
||||
<div className="w-full h-full shrink-0 flex flex-col justify-center items-center content-center gap-2 overflow-hidden">
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { BsmButton } from "renderer/components/shared/bsm-button.component";
|
||||
import { BsmImage } from "renderer/components/shared/bsm-image.component";
|
||||
import { useTranslation } from "renderer/hooks/use-translation.hook";
|
||||
import { ModalComponent, ModalExitCode } from "renderer/services/modale.service";
|
||||
import BeatConflict from '../../../../../assets/images/apngs/beat-conflict.png'
|
||||
|
||||
export const ModsDisclaimerModal: ModalComponent<void, void> = ({resolver}) => {
|
||||
|
||||
const t = useTranslation();
|
||||
|
||||
return (
|
||||
<form className="max-w-[800px] text-gray-800 dark:text-gray-200">
|
||||
<h1 className="text-3xl uppercase tracking-wide w-full text-center text-gray-800 dark:text-gray-200">{t("modals.mods-disclaimer.title")}</h1>
|
||||
<BsmImage className="mx-auto h-20" image={BeatConflict} />
|
||||
<p className="mb-1">{t("modals.mods-disclaimer.p-1")}</p>
|
||||
<ul className="list-disc w-full pl-6">
|
||||
<li>{t("modals.mods-disclaimer.li-1")}</li>
|
||||
<li>{t("modals.mods-disclaimer.li-2")}</li>
|
||||
<li>{t("modals.mods-disclaimer.li-3")}</li>
|
||||
</ul>
|
||||
<p className="mt-1">{t("modals.mods-disclaimer.p-2")}</p>
|
||||
<div className="grid grid-flow-col grid-cols-2 gap-4 pt-3">
|
||||
<BsmButton typeColor="cancel" className="rounded-md text-center transition-all" onClick={() => {resolver({exitCode: ModalExitCode.CANCELED})}} withBar={false} text="misc.refuse"/>
|
||||
<BsmButton typeColor="primary" className="rounded-md text-center transition-all" onClick={() => {resolver({exitCode: ModalExitCode.COMPLETED})}} withBar={false} text="misc.accept"/>
|
||||
</div>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
import { DetailedHTMLProps, Fragment, useState } from "react";
|
||||
import { DetailedHTMLProps, Fragment } from "react";
|
||||
import { useThemeColor } from "renderer/hooks/use-theme-color.hook";
|
||||
import { useTranslation } from "renderer/hooks/use-translation.hook";
|
||||
|
||||
type Props = {
|
||||
tabIndex: number
|
||||
tabsText: string[],
|
||||
onTabChange: (index: number) => void,
|
||||
className?: string,
|
||||
@@ -11,12 +12,12 @@ type Props = {
|
||||
|
||||
export function TabNavBar(props: Props) {
|
||||
|
||||
const [currentTabIndex, setCurrentTabIndex] = useState(0);
|
||||
const currentIndex = props.tabIndex ?? 0;
|
||||
|
||||
const t = useTranslation();
|
||||
const secondColor = useThemeColor("second-color");
|
||||
|
||||
const selectTab = (index: number) => {
|
||||
setCurrentTabIndex(index);
|
||||
props.onTabChange(index);
|
||||
}
|
||||
|
||||
@@ -24,7 +25,7 @@ export function TabNavBar(props: Props) {
|
||||
<nav className={`relative h-8 shrink-0 cursor-pointer rounded-md overflow-hidden shadow-md shadow-black bg-light-main-color-2 dark:bg-main-color-2 ${props.className}`}>
|
||||
<div className="absolute w-full h-1 bottom-0" style={{color: secondColor}}>
|
||||
<span className="absolute h-full w-full bg-current brightness-50" />
|
||||
<span className="absolute h-full block bg-current transition-transform duration-300 shadow-center shadow-current" style={{transform: `translate(${currentTabIndex * 100}%, 0)`, width: `calc(100% / ${props.tabsText.length})`}}/>
|
||||
<span className="absolute h-full block bg-current transition-transform duration-300 shadow-center shadow-current" style={{transform: `translate(${currentIndex * 100}%, 0)`, width: `calc(100% / ${props.tabsText.length})`}}/>
|
||||
</div>
|
||||
<ul className="grid" style={{gridTemplateColumns: `repeat(${props.tabsText.length}, minmax(0, 1fr))`}}>
|
||||
{props.tabsText.map((text, index) => (
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useEffect, useLayoutEffect, useRef, useState } from "react";
|
||||
import { BsModsManagerService } from "renderer/services/bs-mods-manager.service";
|
||||
import { BSVersion } from "shared/bs-version.interface";
|
||||
import VisibilitySensor from 'react-visibility-sensor';
|
||||
import { Mod } from "shared/models/mods/mod.interface";
|
||||
import { ModsGrid } from "./mods-grid.component";
|
||||
import { ConfigurationService } from "renderer/services/configuration.service";
|
||||
@@ -15,14 +14,21 @@ import { skip, filter } from "rxjs/operators";
|
||||
import { Subscription } from "rxjs";
|
||||
import { useTranslation } from "renderer/hooks/use-translation.hook";
|
||||
import { LinkOpenerService } from "renderer/services/link-opener.service";
|
||||
import { useInView } from "framer-motion";
|
||||
import { ModalExitCode, ModalService } from "renderer/services/modale.service";
|
||||
import { ModsDisclaimerModal } from "renderer/components/modal/modal-types/mods-disclaimer-modal.component";
|
||||
|
||||
export function ModsSlide({version}: {version: BSVersion}) {
|
||||
export function ModsSlide({version, onDisclamerDecline}: {version: BSVersion, onDisclamerDecline: () => void}) {
|
||||
|
||||
const ACCEPTED_DISCLAIMER_KEY = "accepted-mods-disclaimer";
|
||||
|
||||
const modsManager = BsModsManagerService.getInstance();
|
||||
const configService = ConfigurationService.getInstance();
|
||||
const linkOpener = LinkOpenerService.getInstance();
|
||||
const modals = ModalService.getInsance();
|
||||
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
const ref = useRef(null);
|
||||
const isVisible = useInView(ref, {amount: .5});
|
||||
const [modsAvailable, setModsAvailable] = useState(null as Map<string, Mod[]>);
|
||||
const [modsInstalled, setModsInstalled] = useState(null as Map<string, Mod[]>);
|
||||
const [modsSelected, setModsSelected] = useState([] as Mod[]);
|
||||
@@ -81,10 +87,27 @@ export function ModsSlide({version}: {version: BSVersion}) {
|
||||
const subs: Subscription[] = [];
|
||||
|
||||
if(isVisible){
|
||||
loadMods();
|
||||
subs.push(modsManager.isUninstalling$.pipe(skip(1), filter(uninstalling => !uninstalling)).subscribe(() => {
|
||||
|
||||
const promise = new Promise<boolean>(async resolve => {
|
||||
|
||||
if(configService.get<boolean>(ACCEPTED_DISCLAIMER_KEY)){ return resolve(true); }
|
||||
|
||||
const res = await modals.openModal(ModsDisclaimerModal);
|
||||
const haveAccepted = res.exitCode === ModalExitCode.COMPLETED;
|
||||
|
||||
if(haveAccepted){ configService.set(ACCEPTED_DISCLAIMER_KEY, true) }
|
||||
|
||||
resolve(haveAccepted);
|
||||
|
||||
});
|
||||
|
||||
promise.then(canLoad => {
|
||||
if(!canLoad){ return onDisclamerDecline?.(); }
|
||||
loadMods();
|
||||
}))
|
||||
subs.push(modsManager.isUninstalling$.pipe(skip(1), filter(uninstalling => !uninstalling)).subscribe(() => {
|
||||
loadMods();
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
return () => {
|
||||
@@ -105,33 +128,31 @@ export function ModsSlide({version}: {version: BSVersion}) {
|
||||
|
||||
|
||||
return (
|
||||
<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'>
|
||||
{modsAvailable ? (
|
||||
<>
|
||||
<div className="overflow-scroll w-full 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="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>
|
||||
</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">{t("pages.version-viewer.mods.loading-mods")}</span>
|
||||
<SpoilerClick className="absolute right-5 w-20 h-[120px] bottom-5 cursor-pointer">
|
||||
<img className="relative w-full" src={YuruYuriDance}/>
|
||||
</SpoilerClick>
|
||||
<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'>
|
||||
{modsAvailable ? (
|
||||
<>
|
||||
<div className="overflow-scroll w-full 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>
|
||||
<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>
|
||||
</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} alt=" "/>
|
||||
<span className="text-xl mt-3 h-0 italic">{t("pages.version-viewer.mods.loading-mods")}</span>
|
||||
<SpoilerClick className="absolute right-5 w-20 h-[120px] bottom-5 cursor-pointer">
|
||||
<img className="relative w-full" src={YuruYuriDance} alt=" "/>
|
||||
</SpoilerClick>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</VisibilitySensor>
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
@@ -57,6 +57,10 @@ export function VersionViewer() {
|
||||
});
|
||||
}
|
||||
|
||||
const handleModsDisclaimerDecline = () => {
|
||||
setCurrentTabIndex(() => 0);
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -64,13 +68,13 @@ export function VersionViewer() {
|
||||
<div className="relative flex items-center flex-col w-full h-full text-gray-200 backdrop-blur-lg">
|
||||
<BsmImage className='relative object-cover h-28' image={BSLogo}/>
|
||||
<h1 className='relative text-4xl font-bold italic -top-3'>{state.name ? `${state.BSVersion} - ${state.name}` : state.BSVersion}</h1>
|
||||
<TabNavBar className='my-3' tabsText={["misc.launch", "misc.maps", "misc.mods"]} onTabChange={(i : number) => setCurrentTabIndex(i)}/>
|
||||
<TabNavBar className='my-3' tabIndex={currentTabIndex} tabsText={["misc.launch", "misc.maps", "misc.mods"]} onTabChange={(i : number) => setCurrentTabIndex(i)}/>
|
||||
<div className='mt-2 w-full min-h-0 grow flex transition-transform duration-300' style={{transform: `translate(${-(currentTabIndex * 100)}%, 0)`}}>
|
||||
<LaunchSlide version={state}/>
|
||||
<div className="w-full shrink-0 px-3 pb-3 flex flex-col items-center">
|
||||
<MapsPlaylistsPanel version={state}/>
|
||||
</div>
|
||||
<ModsSlide version={state}/>
|
||||
<ModsSlide version={state} onDisclamerDecline={handleModsDisclaimerDecline}/>
|
||||
</div>
|
||||
</div>
|
||||
<BsmDropdownButton className='absolute top-5 right-5 h-9 w-9 bg-light-main-color-2 dark:bg-main-color-2 rounded-md' items={[
|
||||
|
||||
Reference in New Issue
Block a user