diff --git a/src/DevMenu.tsx b/src/DevMenu.tsx index b4a2e4d35..e66f8a458 100644 --- a/src/DevMenu.tsx +++ b/src/DevMenu.tsx @@ -1,12 +1,12 @@ -import React, { useEffect } from "react"; +import React, { useEffect, useRef } from "react"; import Typography from "@mui/material/Typography"; import { Player } from "@player"; import { AugmentationName } from "@enums"; -import { General } from "./DevMenu/ui/General"; -import { TimeSkip } from "./DevMenu/ui/TimeSkip"; +import { GeneralDev } from "./DevMenu/ui/GeneralDev"; +import { TimeSkipDev } from "./DevMenu/ui/TimeSkipDev"; import { StatsDev } from "./DevMenu/ui/StatsDev"; import { FactionsDev } from "./DevMenu/ui/FactionsDev"; @@ -27,18 +27,28 @@ import { EntropyDev } from "./DevMenu/ui/EntropyDev"; import { Exploit } from "./Exploits/Exploit"; import { useRerender } from "./ui/React/hooks"; +import { AutoExpandContext, getAutoExpandData, setAutoExpandData } from "./ui/AutoExpand/AutoExpandContext"; export function DevMenuRoot(): React.ReactElement { + const autoExpandContextValue = useRef({ + data: getAutoExpandData(), + set: (key: string, expanded: boolean) => { + autoExpandContextValue.current.data[key] = expanded; + setAutoExpandData(autoExpandContextValue.current.data); + }, + }); + useEffect(() => { Player.giveExploit(Exploit.YoureNotMeantToAccessThis); }, []); + // Pass rerender to certain subpages in case certain tabs are now valid/invalid due to changes made on those pages // Rerender periodically in case game state changes (e.g. player starts gang or buys wse account through a script) const rerender = useRerender(400); return ( - <> + Development Menu - Only meant to be used for testing/debugging - + @@ -60,9 +70,9 @@ export function DevMenuRoot(): React.ReactElement { {Player.sleeves.length > 0 && } {Player.augmentations.some((aug) => aug.name === AugmentationName.StaneksGift1) && } - + - + ); } diff --git a/src/DevMenu/ui/AchievementsDev.tsx b/src/DevMenu/ui/AchievementsDev.tsx index 98e5c6901..4536053e2 100644 --- a/src/DevMenu/ui/AchievementsDev.tsx +++ b/src/DevMenu/ui/AchievementsDev.tsx @@ -1,6 +1,5 @@ import React, { useState } from "react"; -import Accordion from "@mui/material/Accordion"; import AccordionSummary from "@mui/material/AccordionSummary"; import AccordionDetails from "@mui/material/AccordionDetails"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; @@ -15,6 +14,7 @@ import { Player } from "@player"; import { achievements } from "../../Achievements/Achievements"; import { Engine } from "../../engine"; import type { AchievementId } from "../../Achievements/Types"; +import { AutoExpandAccordion } from "../../ui/AutoExpand/AutoExpandAccordion"; export function AchievementsDev(): React.ReactElement { const [playerAchievement, setPlayerAchievements] = useState(Player.achievements.map((m) => m.ID)); @@ -48,7 +48,7 @@ export function AchievementsDev(): React.ReactElement { } return ( - + }> Achievements @@ -109,6 +109,6 @@ export function AchievementsDev(): React.ReactElement { - + ); } diff --git a/src/DevMenu/ui/AugmentationsDev.tsx b/src/DevMenu/ui/AugmentationsDev.tsx index 135c7ec01..0d5036ecf 100644 --- a/src/DevMenu/ui/AugmentationsDev.tsx +++ b/src/DevMenu/ui/AugmentationsDev.tsx @@ -2,7 +2,6 @@ import { Player } from "@player"; import React from "react"; import { Clear, ExpandMore } from "@mui/icons-material"; import { - Accordion, AccordionDetails, AccordionSummary, Autocomplete, @@ -19,6 +18,7 @@ import { AugmentationName, FactionName } from "@enums"; import { Factions } from "../../Faction/Factions"; import { FactionChooser } from "./FactionChooser"; import { getFactionAugmentationsFiltered } from "../../Faction/FactionHelpers"; +import { AutoExpandAccordion } from "../../ui/AutoExpand/AutoExpandAccordion"; export function AugmentationsDev(): React.ReactElement { const [augmentation, setAugmentation] = React.useState(null); @@ -76,7 +76,7 @@ export function AugmentationsDev(): React.ReactElement { ); return ( - + }> Augmentations @@ -117,6 +117,6 @@ export function AugmentationsDev(): React.ReactElement { - + ); } diff --git a/src/DevMenu/ui/BladeburnerDev.tsx b/src/DevMenu/ui/BladeburnerDev.tsx index b36c638b3..96b90df93 100644 --- a/src/DevMenu/ui/BladeburnerDev.tsx +++ b/src/DevMenu/ui/BladeburnerDev.tsx @@ -6,7 +6,6 @@ import { InputLabel, MenuItem, FormControl, - Accordion, AccordionSummary, AccordionDetails, } from "@mui/material"; @@ -19,6 +18,7 @@ import { BladeburnerSkillName, CityName } from "@enums"; import { Skills as AllSkills } from "../../Bladeburner/data/Skills"; import { Bladeburner } from "../../Bladeburner/Bladeburner"; import { getEnumHelper } from "../../utils/EnumHelper"; +import { AutoExpandAccordion } from "../../ui/AutoExpand/AutoExpandAccordion"; const bigNumber = 1e27; @@ -152,7 +152,7 @@ export function BladeburnerDev({ bladeburner }: { bladeburner: Bladeburner }): R const resetOperationSuccesses = () => (bladeburner.operations[AllOperations[operationTarget].name].successes = 0); return ( - + }> Bladeburner @@ -395,6 +395,6 @@ export function BladeburnerDev({ bladeburner }: { bladeburner: Bladeburner }): R - + ); } diff --git a/src/DevMenu/ui/CodingContractsDev.tsx b/src/DevMenu/ui/CodingContractsDev.tsx index 0f0a714d7..66b5f4675 100644 --- a/src/DevMenu/ui/CodingContractsDev.tsx +++ b/src/DevMenu/ui/CodingContractsDev.tsx @@ -1,6 +1,5 @@ import React, { useState } from "react"; -import Accordion from "@mui/material/Accordion"; import AccordionSummary from "@mui/material/AccordionSummary"; import AccordionDetails from "@mui/material/AccordionDetails"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; @@ -15,6 +14,7 @@ import { generateRandomContractOnHome, } from "../../CodingContract/ContractGenerator"; import { CodingContractName } from "@enums"; +import { AutoExpandAccordion } from "../../ui/AutoExpand/AutoExpandAccordion"; import { getEnumHelper } from "../../utils/EnumHelper"; export function CodingContractsDev(): React.ReactElement { @@ -35,7 +35,7 @@ export function CodingContractsDev(): React.ReactElement { } return ( - + }> Coding Contracts @@ -63,6 +63,6 @@ export function CodingContractsDev(): React.ReactElement { - + ); } diff --git a/src/DevMenu/ui/CompaniesDev.tsx b/src/DevMenu/ui/CompaniesDev.tsx index 0e2e42652..7338759bd 100644 --- a/src/DevMenu/ui/CompaniesDev.tsx +++ b/src/DevMenu/ui/CompaniesDev.tsx @@ -1,6 +1,5 @@ import React, { useMemo, useState } from "react"; -import Accordion from "@mui/material/Accordion"; import AccordionSummary from "@mui/material/AccordionSummary"; import AccordionDetails from "@mui/material/AccordionDetails"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; @@ -15,6 +14,7 @@ import { Adjuster } from "./Adjuster"; import { getEnumHelper } from "../../utils/EnumHelper"; import { getRecordValues } from "../../Types/Record"; import { MaxFavor } from "../../Faction/formulas/favor"; +import { AutoExpandAccordion } from "../../ui/AutoExpand/AutoExpandAccordion"; const largeAmountOfReputation = 1e12; @@ -75,7 +75,7 @@ export function CompaniesDev(): React.ReactElement { } return ( - + }> Companies @@ -152,6 +152,6 @@ export function CompaniesDev(): React.ReactElement { - + ); } diff --git a/src/DevMenu/ui/CorporationDev.tsx b/src/DevMenu/ui/CorporationDev.tsx index a99f915d6..ebc641551 100644 --- a/src/DevMenu/ui/CorporationDev.tsx +++ b/src/DevMenu/ui/CorporationDev.tsx @@ -1,6 +1,5 @@ import React from "react"; -import Accordion from "@mui/material/Accordion"; import AccordionSummary from "@mui/material/AccordionSummary"; import AccordionDetails from "@mui/material/AccordionDetails"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; @@ -9,6 +8,7 @@ import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; import { Adjuster } from "./Adjuster"; import { Player } from "@player"; +import { AutoExpandAccordion } from "../../ui/AutoExpand/AutoExpandAccordion"; const bigNumber = 1e27; @@ -76,7 +76,7 @@ export function CorporationDev(): React.ReactElement { } return ( - + }> Corporation @@ -131,6 +131,6 @@ export function CorporationDev(): React.ReactElement { - + ); } diff --git a/src/DevMenu/ui/EntropyDev.tsx b/src/DevMenu/ui/EntropyDev.tsx index 7b00bb8bd..538f69849 100644 --- a/src/DevMenu/ui/EntropyDev.tsx +++ b/src/DevMenu/ui/EntropyDev.tsx @@ -1,6 +1,5 @@ import React from "react"; -import Accordion from "@mui/material/Accordion"; import AccordionSummary from "@mui/material/AccordionSummary"; import AccordionDetails from "@mui/material/AccordionDetails"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; @@ -8,10 +7,11 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import Typography from "@mui/material/Typography"; import { Player } from "@player"; import { Adjuster } from "./Adjuster"; +import { AutoExpandAccordion } from "../../ui/AutoExpand/AutoExpandAccordion"; export function EntropyDev(): React.ReactElement { return ( - + }> Entropy @@ -37,6 +37,6 @@ export function EntropyDev(): React.ReactElement { }} /> - + ); } diff --git a/src/DevMenu/ui/FactionsDev.tsx b/src/DevMenu/ui/FactionsDev.tsx index 08471c471..3bcd9e18b 100644 --- a/src/DevMenu/ui/FactionsDev.tsx +++ b/src/DevMenu/ui/FactionsDev.tsx @@ -1,6 +1,5 @@ import React, { useState } from "react"; import { - Accordion, AccordionSummary, AccordionDetails, Button, @@ -27,6 +26,7 @@ import { getEnumHelper } from "../../utils/EnumHelper"; import { useRerender } from "../../ui/React/hooks"; import { MaxFavor } from "../../Faction/formulas/favor"; import { FactionChooser } from "./FactionChooser"; +import { AutoExpandAccordion } from "../../ui/AutoExpand/AutoExpandAccordion"; const largeAmountOfReputation = 1e12; @@ -119,7 +119,7 @@ export function FactionsDev(): React.ReactElement { } return ( - + }> Factions @@ -237,6 +237,6 @@ export function FactionsDev(): React.ReactElement { - + ); } diff --git a/src/DevMenu/ui/GangDev.tsx b/src/DevMenu/ui/GangDev.tsx index 5e331cbaa..e64c75d8b 100644 --- a/src/DevMenu/ui/GangDev.tsx +++ b/src/DevMenu/ui/GangDev.tsx @@ -1,13 +1,13 @@ import React from "react"; import Typography from "@mui/material/Typography"; -import Accordion from "@mui/material/Accordion"; import AccordionSummary from "@mui/material/AccordionSummary"; import AccordionDetails from "@mui/material/AccordionDetails"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import { Adjuster } from "./Adjuster"; import { Player } from "@player"; +import { AutoExpandAccordion } from "../../ui/AutoExpand/AutoExpandAccordion"; const bigNumber = 1e27; @@ -33,7 +33,7 @@ export function GangDev(): React.ReactElement { } return ( - + }> Gang @@ -58,6 +58,6 @@ export function GangDev(): React.ReactElement { - + ); } diff --git a/src/DevMenu/ui/General.tsx b/src/DevMenu/ui/GeneralDev.tsx similarity index 96% rename from src/DevMenu/ui/General.tsx rename to src/DevMenu/ui/GeneralDev.tsx index 7ac5ab814..8f9bb4c2c 100644 --- a/src/DevMenu/ui/General.tsx +++ b/src/DevMenu/ui/GeneralDev.tsx @@ -1,6 +1,5 @@ import React, { useEffect, useState } from "react"; import { - Accordion, AccordionSummary, AccordionDetails, Button, @@ -26,8 +25,9 @@ import { getEnumHelper } from "../../utils/EnumHelper"; import { formatRam } from "../../ui/formatNumber"; import { resetGangs } from "../../Gang/AllGangs"; import { finishBitNode } from "../../BitNode/BitNodeUtils"; +import { AutoExpandAccordion } from "../../ui/AutoExpand/AutoExpandAccordion"; -export function General({ parentRerender }: { parentRerender: () => void }): React.ReactElement { +export function GeneralDev({ parentRerender }: { parentRerender: () => void }): React.ReactElement { const rerender = useRerender(400); const [error, setError] = useState(false); const [corporationName, setCorporationName] = useState(""); @@ -114,7 +114,7 @@ export function General({ parentRerender }: { parentRerender: () => void }): Rea const ramValues = [8, 64, 1024, 1048576, 1073741824]; return ( - + }> General @@ -210,6 +210,6 @@ export function General({ parentRerender }: { parentRerender: () => void }): Rea - + ); } diff --git a/src/DevMenu/ui/ProgramsDev.tsx b/src/DevMenu/ui/ProgramsDev.tsx index 920e42914..ee2efa16f 100644 --- a/src/DevMenu/ui/ProgramsDev.tsx +++ b/src/DevMenu/ui/ProgramsDev.tsx @@ -1,6 +1,5 @@ import React, { useState } from "react"; -import Accordion from "@mui/material/Accordion"; import AccordionSummary from "@mui/material/AccordionSummary"; import AccordionDetails from "@mui/material/AccordionDetails"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; @@ -11,6 +10,7 @@ import Select, { SelectChangeEvent } from "@mui/material/Select"; import { Player } from "@player"; import MenuItem from "@mui/material/MenuItem"; import { CompletedProgramName } from "@enums"; +import { AutoExpandAccordion } from "../../ui/AutoExpand/AutoExpandAccordion"; export function ProgramsDev(): React.ReactElement { const [program, setProgram] = useState(CompletedProgramName.bruteSsh); @@ -29,7 +29,7 @@ export function ProgramsDev(): React.ReactElement { } return ( - + }> Programs @@ -62,6 +62,6 @@ export function ProgramsDev(): React.ReactElement { - + ); } diff --git a/src/DevMenu/ui/ServersDev.tsx b/src/DevMenu/ui/ServersDev.tsx index 0ebf99224..b3af705c1 100644 --- a/src/DevMenu/ui/ServersDev.tsx +++ b/src/DevMenu/ui/ServersDev.tsx @@ -1,6 +1,5 @@ import React, { useState } from "react"; -import Accordion from "@mui/material/Accordion"; import AccordionSummary from "@mui/material/AccordionSummary"; import AccordionDetails from "@mui/material/AccordionDetails"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; @@ -11,6 +10,7 @@ import { GetServer, GetAllServers } from "../../Server/AllServers"; import { Server } from "../../Server/Server"; import Autocomplete from "@mui/material/Autocomplete"; import TextField from "@mui/material/TextField"; +import { AutoExpandAccordion } from "../../ui/AutoExpand/AutoExpandAccordion"; export function ServersDev(): React.ReactElement { const [server, setServer] = useState("home"); @@ -99,7 +99,7 @@ export function ServersDev(): React.ReactElement { } return ( - + }> Servers @@ -178,6 +178,6 @@ export function ServersDev(): React.ReactElement { - + ); } diff --git a/src/DevMenu/ui/SleevesDev.tsx b/src/DevMenu/ui/SleevesDev.tsx index 19dbad80e..f3645365c 100644 --- a/src/DevMenu/ui/SleevesDev.tsx +++ b/src/DevMenu/ui/SleevesDev.tsx @@ -1,6 +1,5 @@ import React from "react"; -import Accordion from "@mui/material/Accordion"; import AccordionSummary from "@mui/material/AccordionSummary"; import AccordionDetails from "@mui/material/AccordionDetails"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; @@ -9,6 +8,7 @@ import Button from "@mui/material/Button"; import Typography from "@mui/material/Typography"; import { Player } from "@player"; import { Adjuster } from "./Adjuster"; +import { AutoExpandAccordion } from "../../ui/AutoExpand/AutoExpandAccordion"; export function SleevesDev(): React.ReactElement { function sleeveMaxAllShock(): void { @@ -42,7 +42,7 @@ export function SleevesDev(): React.ReactElement { } return ( - + }> Sleeves @@ -91,6 +91,6 @@ export function SleevesDev(): React.ReactElement { - + ); } diff --git a/src/DevMenu/ui/SourceFilesDev.tsx b/src/DevMenu/ui/SourceFilesDev.tsx index 4ba12c620..6fad286b2 100644 --- a/src/DevMenu/ui/SourceFilesDev.tsx +++ b/src/DevMenu/ui/SourceFilesDev.tsx @@ -1,6 +1,6 @@ import React, { useCallback } from "react"; -import { Accordion, AccordionSummary, AccordionDetails, Button, ButtonGroup, Typography } from "@mui/material"; +import { AccordionSummary, AccordionDetails, Button, ButtonGroup, Typography } from "@mui/material"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import { makeStyles } from "tss-react/mui"; @@ -8,6 +8,7 @@ import { Player } from "@player"; import { Sleeve } from "../../PersonObjects/Sleeve/Sleeve"; import { ButtonWithTooltip } from "../../ui/Components/ButtonWithTooltip"; import { MaxSleevesFromCovenant } from "../../PersonObjects/Sleeve/SleeveCovenantPurchases"; +import { AutoExpandAccordion } from "../../ui/AutoExpand/AutoExpandAccordion"; // Update as additional BitNodes get implemented const validSFN = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]; @@ -114,7 +115,7 @@ export function SourceFilesDev({ parentRerender }: { parentRerender: () => void }; return ( - + }> Source-Files @@ -135,6 +136,6 @@ export function SourceFilesDev({ parentRerender }: { parentRerender: () => void - + ); } diff --git a/src/DevMenu/ui/StanekDev.tsx b/src/DevMenu/ui/StanekDev.tsx index bc6ae8221..6ba8491f4 100644 --- a/src/DevMenu/ui/StanekDev.tsx +++ b/src/DevMenu/ui/StanekDev.tsx @@ -3,13 +3,13 @@ import React from "react"; import { staneksGift } from "../../CotMG/Helper"; import { Player } from "@player"; -import Accordion from "@mui/material/Accordion"; import AccordionSummary from "@mui/material/AccordionSummary"; import AccordionDetails from "@mui/material/AccordionDetails"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import Typography from "@mui/material/Typography"; import { Adjuster } from "./Adjuster"; +import { AutoExpandAccordion } from "../../ui/AutoExpand/AutoExpandAccordion"; export function StanekDev(): React.ReactElement { function addCycles(): void { @@ -49,7 +49,7 @@ export function StanekDev(): React.ReactElement { } return ( - + }> Stanek's Gift @@ -83,6 +83,6 @@ export function StanekDev(): React.ReactElement { - + ); } diff --git a/src/DevMenu/ui/StatsDev.tsx b/src/DevMenu/ui/StatsDev.tsx index 3cd5355fe..7298dae19 100644 --- a/src/DevMenu/ui/StatsDev.tsx +++ b/src/DevMenu/ui/StatsDev.tsx @@ -1,6 +1,5 @@ import React from "react"; -import Accordion from "@mui/material/Accordion"; import AccordionSummary from "@mui/material/AccordionSummary"; import AccordionDetails from "@mui/material/AccordionDetails"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; @@ -14,6 +13,7 @@ import { Player } from "@player"; import { dialogBoxCreate } from "../../ui/React/DialogBox"; import { calculateExp } from "../../PersonObjects/formulas/skill"; import { currentNodeMults } from "../../BitNode/BitNodeMultipliers"; +import { AutoExpandAccordion } from "../../ui/AutoExpand/AutoExpandAccordion"; const bigNumber = 1e27; @@ -221,7 +221,7 @@ export function StatsDev(): React.ReactElement { const [levelOfNormalStats, setLevelOfNormalStats] = React.useState(""); return ( - + }> Experience / Stats @@ -297,6 +297,6 @@ export function StatsDev(): React.ReactElement { - + ); } diff --git a/src/DevMenu/ui/StockMarketDev.tsx b/src/DevMenu/ui/StockMarketDev.tsx index 4c052b989..b54156ef4 100644 --- a/src/DevMenu/ui/StockMarketDev.tsx +++ b/src/DevMenu/ui/StockMarketDev.tsx @@ -1,6 +1,5 @@ import React, { useState } from "react"; -import Accordion from "@mui/material/Accordion"; import AccordionSummary from "@mui/material/AccordionSummary"; import AccordionDetails from "@mui/material/AccordionDetails"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; @@ -12,6 +11,7 @@ import { Money } from "../../ui/React/Money"; import { dialogBoxCreate } from "../../ui/React/DialogBox"; import { StockMarket as SM } from "../../StockMarket/StockMarket"; import { Stock } from "../../StockMarket/Stock"; +import { AutoExpandAccordion } from "../../ui/AutoExpand/AutoExpandAccordion"; export function StockMarketDev(): React.ReactElement { const [stockPrice, setStockPrice] = useState(0); @@ -81,7 +81,7 @@ export function StockMarketDev(): React.ReactElement { ); } return ( - + }> Stock Market @@ -116,6 +116,6 @@ export function StockMarketDev(): React.ReactElement { - + ); } diff --git a/src/DevMenu/ui/TimeSkip.tsx b/src/DevMenu/ui/TimeSkipDev.tsx similarity index 81% rename from src/DevMenu/ui/TimeSkip.tsx rename to src/DevMenu/ui/TimeSkipDev.tsx index aef323ba6..5bfc3673f 100644 --- a/src/DevMenu/ui/TimeSkip.tsx +++ b/src/DevMenu/ui/TimeSkipDev.tsx @@ -1,6 +1,5 @@ import React from "react"; -import Accordion from "@mui/material/Accordion"; import AccordionSummary from "@mui/material/AccordionSummary"; import AccordionDetails from "@mui/material/AccordionDetails"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; @@ -10,10 +9,9 @@ import Button from "@mui/material/Button"; import { Player } from "@player"; import { Engine } from "../../engine"; import { dialogBoxCreate } from "../../ui/React/DialogBox"; +import { AutoExpandAccordion } from "../../ui/AutoExpand/AutoExpandAccordion"; -// Update as additional BitNodes get implemented - -export function TimeSkip(): React.ReactElement { +export function TimeSkipDev(): React.ReactElement { function timeskip(time: number) { return () => { Player.lastUpdate -= time; @@ -23,7 +21,7 @@ export function TimeSkip(): React.ReactElement { } return ( - + }> Time skip @@ -32,6 +30,6 @@ export function TimeSkip(): React.ReactElement { - + ); } diff --git a/src/ui/AutoExpand/AutoExpandAccordion.tsx b/src/ui/AutoExpand/AutoExpandAccordion.tsx new file mode 100644 index 000000000..e3f7ee7c2 --- /dev/null +++ b/src/ui/AutoExpand/AutoExpandAccordion.tsx @@ -0,0 +1,29 @@ +import React, { useContext, useState } from "react"; +import Accordion from "@mui/material/Accordion"; +import { AutoExpandContext } from "./AutoExpandContext"; + +export function AutoExpandAccordion({ + cacheKey, + unmountOnExit, + children, +}: { + cacheKey: string; + unmountOnExit: boolean; + children: NonNullable; +}) { + const autoExpandContextValue = useContext(AutoExpandContext); + const [expanded, setExpanded] = useState(autoExpandContextValue.data[cacheKey] ?? false); + return ( + { + setExpanded(expanded); + autoExpandContextValue.set(cacheKey, expanded); + }} + > + {children} + + ); +} diff --git a/src/ui/AutoExpand/AutoExpandContext.tsx b/src/ui/AutoExpand/AutoExpandContext.tsx new file mode 100644 index 000000000..955df701f --- /dev/null +++ b/src/ui/AutoExpand/AutoExpandContext.tsx @@ -0,0 +1,44 @@ +import { createContext } from "react"; +import { assertObject } from "../../utils/TypeAssertion"; + +export type AutoExpandDataType = Record; + +export type AutoExpandContextValueType = { + data: AutoExpandDataType; + set: (key: string, expanded: boolean) => void; +}; + +export const AutoExpandContext = createContext({ + data: {}, + set: () => { + throw new Error("Unimplemented function"); + }, +}); + +const localStorageKey = "AutoExpandData"; + +export function getAutoExpandData(): AutoExpandDataType { + const storedDataString = localStorage.getItem(localStorageKey); + if (storedDataString == null) { + return {}; + } + let storedAutoExpandData: unknown; + try { + storedAutoExpandData = JSON.parse(storedDataString); + assertObject(storedAutoExpandData); + for (const [key, value] of Object.entries(storedAutoExpandData)) { + if (typeof key !== "string" || typeof value !== "boolean") { + throw new Error(`Invalid autoExpandData. Stored data string: ${storedDataString}`); + } + } + } catch (error) { + console.error(error); + localStorage.removeItem(localStorageKey); + return {}; + } + return storedAutoExpandData as AutoExpandDataType; +} + +export function setAutoExpandData(data: AutoExpandDataType): void { + localStorage.setItem(localStorageKey, JSON.stringify(data)); +}