Use localStorage hook
This commit is contained in:
parent
625f436163
commit
1bbf3b164a
|
@ -109,7 +109,7 @@ export const AppLayout = ({
|
||||||
onSwipedLeft: (SwipeEventData) => {
|
onSwipedLeft: (SwipeEventData) => {
|
||||||
if (menuGestures) {
|
if (menuGestures) {
|
||||||
if (SwipeEventData.velocity < SENSIBILITY_SWIPE) return;
|
if (SwipeEventData.velocity < SENSIBILITY_SWIPE) return;
|
||||||
if (mainPanelOpen === true) {
|
if (mainPanelOpen) {
|
||||||
setMainPanelOpen(false);
|
setMainPanelOpen(false);
|
||||||
} else if (isDefined(subPanel) && isDefined(contentPanel)) {
|
} else if (isDefined(subPanel) && isDefined(contentPanel)) {
|
||||||
setSubPanelOpen(true);
|
setSubPanelOpen(true);
|
||||||
|
@ -119,7 +119,7 @@ export const AppLayout = ({
|
||||||
onSwipedRight: (SwipeEventData) => {
|
onSwipedRight: (SwipeEventData) => {
|
||||||
if (menuGestures) {
|
if (menuGestures) {
|
||||||
if (SwipeEventData.velocity < SENSIBILITY_SWIPE) return;
|
if (SwipeEventData.velocity < SENSIBILITY_SWIPE) return;
|
||||||
if (subPanelOpen === true) {
|
if (subPanelOpen) {
|
||||||
setSubPanelOpen(false);
|
setSubPanelOpen(false);
|
||||||
} else {
|
} else {
|
||||||
setMainPanelOpen(true);
|
setMainPanelOpen(true);
|
||||||
|
@ -135,7 +135,7 @@ export const AppLayout = ({
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
document.getElementsByTagName("html")[0].style.fontSize = `${
|
document.getElementsByTagName("html")[0].style.fontSize = `${
|
||||||
(fontSize ?? 1) * 100
|
fontSize * 100
|
||||||
}%`;
|
}%`;
|
||||||
}, [fontSize]);
|
}, [fontSize]);
|
||||||
|
|
||||||
|
@ -159,18 +159,16 @@ export const AppLayout = ({
|
||||||
}, [currencyOptions, currencySelect, setCurrency]);
|
}, [currencyOptions, currencySelect, setCurrency]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (preferredLanguages) {
|
if (preferredLanguages.length === 0) {
|
||||||
if (preferredLanguages.length === 0) {
|
if (isDefinedAndNotEmpty(router.locale) && router.locales) {
|
||||||
if (isDefinedAndNotEmpty(router.locale) && router.locales) {
|
setPreferredLanguages(
|
||||||
setPreferredLanguages(
|
getDefaultPreferredLanguages(router.locale, router.locales)
|
||||||
getDefaultPreferredLanguages(router.locale, router.locales)
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (router.locale !== preferredLanguages[0]) {
|
|
||||||
router.replace(router.asPath, router.asPath, {
|
|
||||||
locale: preferredLanguages[0],
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
} else if (router.locale !== preferredLanguages[0]) {
|
||||||
|
router.replace(router.asPath, router.asPath, {
|
||||||
|
locale: preferredLanguages[0],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
preferredLanguages,
|
preferredLanguages,
|
||||||
|
@ -182,11 +180,11 @@ export const AppLayout = ({
|
||||||
|
|
||||||
const gridCol = useMemo(() => {
|
const gridCol = useMemo(() => {
|
||||||
if (isDefined(subPanel)) {
|
if (isDefined(subPanel)) {
|
||||||
if (mainPanelReduced === true) {
|
if (mainPanelReduced) {
|
||||||
return "grid-cols-[6rem_20rem_1fr]";
|
return "grid-cols-[6rem_20rem_1fr]";
|
||||||
}
|
}
|
||||||
return "grid-cols-[20rem_20rem_1fr]";
|
return "grid-cols-[20rem_20rem_1fr]";
|
||||||
} else if (mainPanelReduced === true) {
|
} else if (mainPanelReduced) {
|
||||||
return "grid-cols-[6rem_0px_1fr]";
|
return "grid-cols-[6rem_0px_1fr]";
|
||||||
}
|
}
|
||||||
return "grid-cols-[20rem_0px_1fr]";
|
return "grid-cols-[20rem_0px_1fr]";
|
||||||
|
@ -262,7 +260,7 @@ export const AppLayout = ({
|
||||||
`absolute inset-0 transition-[backdrop-filter] duration-500 [grid-area:content]
|
`absolute inset-0 transition-[backdrop-filter] duration-500 [grid-area:content]
|
||||||
mobile:z-10`,
|
mobile:z-10`,
|
||||||
cIf(
|
cIf(
|
||||||
(mainPanelOpen === true || subPanelOpen === true) && isMobile,
|
(mainPanelOpen || subPanelOpen) && isMobile,
|
||||||
"[backdrop-filter:blur(2px)]",
|
"[backdrop-filter:blur(2px)]",
|
||||||
"pointer-events-none touch-none"
|
"pointer-events-none touch-none"
|
||||||
)
|
)
|
||||||
|
@ -272,7 +270,7 @@ export const AppLayout = ({
|
||||||
className={cJoin(
|
className={cJoin(
|
||||||
"absolute inset-0 bg-shade transition-opacity duration-500",
|
"absolute inset-0 bg-shade transition-opacity duration-500",
|
||||||
cIf(
|
cIf(
|
||||||
(mainPanelOpen === true || subPanelOpen === true) && isMobile,
|
(mainPanelOpen || subPanelOpen) && isMobile,
|
||||||
"opacity-60",
|
"opacity-60",
|
||||||
"opacity-0"
|
"opacity-0"
|
||||||
)
|
)
|
||||||
|
@ -312,7 +310,7 @@ export const AppLayout = ({
|
||||||
mobile:border-r-0 mobile:border-l-[1px] mobile:[grid-area:content]`,
|
mobile:border-r-0 mobile:border-l-[1px] mobile:[grid-area:content]`,
|
||||||
turnSubIntoContent
|
turnSubIntoContent
|
||||||
? "mobile:w-full mobile:border-l-0"
|
? "mobile:w-full mobile:border-l-0"
|
||||||
: subPanelOpen === true
|
: subPanelOpen
|
||||||
? ""
|
? ""
|
||||||
: "mobile:translate-x-[100vw]"
|
: "mobile:translate-x-[100vw]"
|
||||||
)}
|
)}
|
||||||
|
@ -328,7 +326,7 @@ export const AppLayout = ({
|
||||||
transition-transform duration-300 [grid-area:main] [scrollbar-width:none]
|
transition-transform duration-300 [grid-area:main] [scrollbar-width:none]
|
||||||
webkit-scrollbar:w-0 mobile:z-10 mobile:w-[90%] mobile:justify-self-start
|
webkit-scrollbar:w-0 mobile:z-10 mobile:w-[90%] mobile:justify-self-start
|
||||||
mobile:[grid-area:content]`,
|
mobile:[grid-area:content]`,
|
||||||
cIf(mainPanelOpen === false, "mobile:-translate-x-full")
|
cIf(!mainPanelOpen, "mobile:-translate-x-full")
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<MainPanel langui={langui} />
|
<MainPanel langui={langui} />
|
||||||
|
@ -340,7 +338,7 @@ export const AppLayout = ({
|
||||||
border-t-[1px] border-dotted border-black bg-light [grid-area:navbar] desktop:hidden"
|
border-t-[1px] border-dotted border-black bg-light [grid-area:navbar] desktop:hidden"
|
||||||
>
|
>
|
||||||
<Ico
|
<Ico
|
||||||
icon={mainPanelOpen === true ? Icon.Close : Icon.Menu}
|
icon={mainPanelOpen ? Icon.Close : Icon.Menu}
|
||||||
className="mt-[.1em] cursor-pointer !text-2xl"
|
className="mt-[.1em] cursor-pointer !text-2xl"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
toggleMainPanelOpen();
|
toggleMainPanelOpen();
|
||||||
|
@ -365,7 +363,7 @@ export const AppLayout = ({
|
||||||
</p>
|
</p>
|
||||||
{isDefined(subPanel) && !turnSubIntoContent && (
|
{isDefined(subPanel) && !turnSubIntoContent && (
|
||||||
<Ico
|
<Ico
|
||||||
icon={subPanelOpen === true ? Icon.Close : subPanelIcon}
|
icon={subPanelOpen ? Icon.Close : subPanelIcon}
|
||||||
className="mt-[.1em] cursor-pointer !text-2xl"
|
className="mt-[.1em] cursor-pointer !text-2xl"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
toggleSubPanelOpen();
|
toggleSubPanelOpen();
|
||||||
|
@ -404,7 +402,7 @@ export const AppLayout = ({
|
||||||
</Popup>
|
</Popup>
|
||||||
|
|
||||||
<Popup
|
<Popup
|
||||||
state={configPanelOpen ?? false}
|
state={configPanelOpen}
|
||||||
onClose={() => setConfigPanelOpen(false)}
|
onClose={() => setConfigPanelOpen(false)}
|
||||||
>
|
>
|
||||||
<h2 className="text-2xl">{langui.settings}</h2>
|
<h2 className="text-2xl">{langui.settings}</h2>
|
||||||
|
@ -416,7 +414,7 @@ export const AppLayout = ({
|
||||||
{router.locales && (
|
{router.locales && (
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-xl">{langui.languages}</h3>
|
<h3 className="text-xl">{langui.languages}</h3>
|
||||||
{preferredLanguages && preferredLanguages.length > 0 && (
|
{preferredLanguages.length > 0 && (
|
||||||
<OrderableList
|
<OrderableList
|
||||||
items={
|
items={
|
||||||
new Map(
|
new Map(
|
||||||
|
@ -453,14 +451,14 @@ export const AppLayout = ({
|
||||||
setDarkMode(false);
|
setDarkMode(false);
|
||||||
setSelectedThemeMode(true);
|
setSelectedThemeMode(true);
|
||||||
},
|
},
|
||||||
active: selectedThemeMode === true && darkMode === false,
|
active: selectedThemeMode && darkMode,
|
||||||
text: langui.light,
|
text: langui.light,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
setSelectedThemeMode(false);
|
setSelectedThemeMode(false);
|
||||||
},
|
},
|
||||||
active: selectedThemeMode === false,
|
active: selectedThemeMode,
|
||||||
text: langui.auto,
|
text: langui.auto,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -468,7 +466,7 @@ export const AppLayout = ({
|
||||||
setDarkMode(true);
|
setDarkMode(true);
|
||||||
setSelectedThemeMode(true);
|
setSelectedThemeMode(true);
|
||||||
},
|
},
|
||||||
active: selectedThemeMode === true && darkMode === true,
|
active: selectedThemeMode && darkMode,
|
||||||
text: langui.dark,
|
text: langui.dark,
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
|
@ -492,20 +490,17 @@ export const AppLayout = ({
|
||||||
<ButtonGroup
|
<ButtonGroup
|
||||||
buttonsProps={[
|
buttonsProps={[
|
||||||
{
|
{
|
||||||
onClick: () => setFontSize((fontSize ?? 1) / 1.05),
|
onClick: () => setFontSize(fontSize / 1.05),
|
||||||
icon: Icon.TextDecrease,
|
icon: Icon.TextDecrease,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
onClick: () => setFontSize(1),
|
onClick: () => setFontSize(1),
|
||||||
text: `${((fontSize ?? 1) * 100).toLocaleString(
|
text: `${(fontSize * 100).toLocaleString(undefined, {
|
||||||
undefined,
|
maximumFractionDigits: 0,
|
||||||
{
|
})}%`,
|
||||||
maximumFractionDigits: 0,
|
|
||||||
}
|
|
||||||
)}%`,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
onClick: () => setFontSize((fontSize ?? 1) * 1.05),
|
onClick: () => setFontSize(fontSize * 1.05),
|
||||||
icon: Icon.TextIncrease,
|
icon: Icon.TextIncrease,
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
|
@ -516,13 +511,13 @@ export const AppLayout = ({
|
||||||
<h3 className="text-xl">{langui.font}</h3>
|
<h3 className="text-xl">{langui.font}</h3>
|
||||||
<div className="grid gap-2">
|
<div className="grid gap-2">
|
||||||
<Button
|
<Button
|
||||||
active={dyslexic === false}
|
active={!dyslexic}
|
||||||
onClick={() => setDyslexic(false)}
|
onClick={() => setDyslexic(false)}
|
||||||
className="font-zenMaruGothic"
|
className="font-zenMaruGothic"
|
||||||
text="Zen Maru Gothic"
|
text="Zen Maru Gothic"
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
active={dyslexic === true}
|
active={dyslexic}
|
||||||
onClick={() => setDyslexic(true)}
|
onClick={() => setDyslexic(true)}
|
||||||
className="font-openDyslexic"
|
className="font-openDyslexic"
|
||||||
text="OpenDyslexic"
|
text="OpenDyslexic"
|
||||||
|
@ -535,7 +530,7 @@ export const AppLayout = ({
|
||||||
<TextInput
|
<TextInput
|
||||||
placeholder="<player>"
|
placeholder="<player>"
|
||||||
className="w-48"
|
className="w-48"
|
||||||
value={playerName ?? ""}
|
value={playerName}
|
||||||
onChange={setPlayerName}
|
onChange={setPlayerName}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Fragment, useCallback } from "react";
|
import { Fragment, useCallback, useRef } from "react";
|
||||||
import { useBoolean } from "usehooks-ts";
|
import { useBoolean, useOnClickOutside } from "usehooks-ts";
|
||||||
import { Ico, Icon } from "components/Ico";
|
import { Ico, Icon } from "components/Ico";
|
||||||
import { cIf, cJoin } from "helpers/className";
|
import { cIf, cJoin } from "helpers/className";
|
||||||
|
|
||||||
|
@ -37,11 +37,12 @@ export const Select = ({
|
||||||
if (optionCount > 1) toggleOpened();
|
if (optionCount > 1) toggleOpened();
|
||||||
}, [options.length, value, toggleOpened]);
|
}, [options.length, value, toggleOpened]);
|
||||||
|
|
||||||
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
|
useOnClickOutside(ref, setClosed);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
onClickCapture={() => {
|
ref={ref}
|
||||||
setClosed();
|
|
||||||
}}
|
|
||||||
className={cJoin(
|
className={cJoin(
|
||||||
"relative text-center transition-[filter]",
|
"relative text-center transition-[filter]",
|
||||||
cIf(isOpened, "z-10 drop-shadow-shade-lg"),
|
cIf(isOpened, "z-10 drop-shadow-shade-lg"),
|
||||||
|
|
|
@ -35,7 +35,7 @@ export const PreviewCardCTAs = ({
|
||||||
<Button
|
<Button
|
||||||
icon={Icon.Favorite}
|
icon={Icon.Favorite}
|
||||||
text={expand ? langui.want_it : undefined}
|
text={expand ? langui.want_it : undefined}
|
||||||
active={libraryItemUserStatus?.[id] === LibraryItemUserStatus.Want}
|
active={libraryItemUserStatus[id] === LibraryItemUserStatus.Want}
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
setLibraryItemUserStatus((current) => {
|
setLibraryItemUserStatus((current) => {
|
||||||
|
@ -53,7 +53,7 @@ export const PreviewCardCTAs = ({
|
||||||
<Button
|
<Button
|
||||||
icon={Icon.BackHand}
|
icon={Icon.BackHand}
|
||||||
text={expand ? langui.have_it : undefined}
|
text={expand ? langui.have_it : undefined}
|
||||||
active={libraryItemUserStatus?.[id] === LibraryItemUserStatus.Have}
|
active={libraryItemUserStatus[id] === LibraryItemUserStatus.Have}
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
setLibraryItemUserStatus((current) => {
|
setLibraryItemUserStatus((current) => {
|
||||||
|
|
|
@ -1,64 +1,77 @@
|
||||||
import React, { ReactNode, useContext, useState } from "react";
|
import React, { ReactNode, useContext, useState } from "react";
|
||||||
|
import { useLocalStorage } from "usehooks-ts";
|
||||||
import { isDefined } from "helpers/others";
|
import { isDefined } from "helpers/others";
|
||||||
import { LibraryItemUserStatus, RequiredNonNullable } from "helpers/types";
|
import { LibraryItemUserStatus, RequiredNonNullable } from "helpers/types";
|
||||||
import { useDarkMode } from "hooks/useDarkMode";
|
import { useDarkMode } from "hooks/useDarkMode";
|
||||||
import { useStateWithLocalStorage } from "hooks/useStateWithLocalStorage";
|
|
||||||
|
|
||||||
interface AppLayoutState {
|
interface AppLayoutState {
|
||||||
subPanelOpen: boolean | undefined;
|
subPanelOpen: boolean;
|
||||||
toggleSubPanelOpen: () => void;
|
toggleSubPanelOpen: () => void;
|
||||||
setSubPanelOpen: React.Dispatch<
|
setSubPanelOpen: React.Dispatch<
|
||||||
React.SetStateAction<AppLayoutState["subPanelOpen"]>
|
React.SetStateAction<AppLayoutState["subPanelOpen"]>
|
||||||
>;
|
>;
|
||||||
configPanelOpen: boolean | undefined;
|
|
||||||
|
configPanelOpen: boolean;
|
||||||
toggleConfigPanelOpen: () => void;
|
toggleConfigPanelOpen: () => void;
|
||||||
setConfigPanelOpen: React.Dispatch<
|
setConfigPanelOpen: React.Dispatch<
|
||||||
React.SetStateAction<AppLayoutState["configPanelOpen"]>
|
React.SetStateAction<AppLayoutState["configPanelOpen"]>
|
||||||
>;
|
>;
|
||||||
searchPanelOpen: boolean | undefined;
|
|
||||||
|
searchPanelOpen: boolean;
|
||||||
toggleSearchPanelOpen: () => void;
|
toggleSearchPanelOpen: () => void;
|
||||||
setSearchPanelOpen: React.Dispatch<
|
setSearchPanelOpen: React.Dispatch<
|
||||||
React.SetStateAction<AppLayoutState["searchPanelOpen"]>
|
React.SetStateAction<AppLayoutState["searchPanelOpen"]>
|
||||||
>;
|
>;
|
||||||
mainPanelReduced: boolean | undefined;
|
|
||||||
|
mainPanelReduced: boolean;
|
||||||
toggleMainPanelReduced: () => void;
|
toggleMainPanelReduced: () => void;
|
||||||
setMainPanelReduced: React.Dispatch<
|
setMainPanelReduced: React.Dispatch<
|
||||||
React.SetStateAction<AppLayoutState["mainPanelReduced"]>
|
React.SetStateAction<AppLayoutState["mainPanelReduced"]>
|
||||||
>;
|
>;
|
||||||
mainPanelOpen: boolean | undefined;
|
|
||||||
|
mainPanelOpen: boolean;
|
||||||
toggleMainPanelOpen: () => void;
|
toggleMainPanelOpen: () => void;
|
||||||
setMainPanelOpen: React.Dispatch<
|
setMainPanelOpen: React.Dispatch<
|
||||||
React.SetStateAction<AppLayoutState["mainPanelOpen"]>
|
React.SetStateAction<AppLayoutState["mainPanelOpen"]>
|
||||||
>;
|
>;
|
||||||
darkMode: boolean | undefined;
|
|
||||||
|
darkMode: boolean;
|
||||||
toggleDarkMode: () => void;
|
toggleDarkMode: () => void;
|
||||||
setDarkMode: React.Dispatch<React.SetStateAction<AppLayoutState["darkMode"]>>;
|
setDarkMode: React.Dispatch<React.SetStateAction<AppLayoutState["darkMode"]>>;
|
||||||
selectedThemeMode: boolean | undefined;
|
|
||||||
|
selectedThemeMode: boolean;
|
||||||
toggleSelectedThemeMode: () => void;
|
toggleSelectedThemeMode: () => void;
|
||||||
setSelectedThemeMode: React.Dispatch<
|
setSelectedThemeMode: React.Dispatch<
|
||||||
React.SetStateAction<AppLayoutState["selectedThemeMode"]>
|
React.SetStateAction<AppLayoutState["selectedThemeMode"]>
|
||||||
>;
|
>;
|
||||||
fontSize: number | undefined;
|
|
||||||
|
fontSize: number;
|
||||||
setFontSize: React.Dispatch<React.SetStateAction<AppLayoutState["fontSize"]>>;
|
setFontSize: React.Dispatch<React.SetStateAction<AppLayoutState["fontSize"]>>;
|
||||||
dyslexic: boolean | undefined;
|
|
||||||
|
dyslexic: boolean;
|
||||||
toggleDyslexic: () => void;
|
toggleDyslexic: () => void;
|
||||||
setDyslexic: React.Dispatch<React.SetStateAction<AppLayoutState["dyslexic"]>>;
|
setDyslexic: React.Dispatch<React.SetStateAction<AppLayoutState["dyslexic"]>>;
|
||||||
currency: string | undefined;
|
|
||||||
|
currency: string;
|
||||||
setCurrency: React.Dispatch<React.SetStateAction<AppLayoutState["currency"]>>;
|
setCurrency: React.Dispatch<React.SetStateAction<AppLayoutState["currency"]>>;
|
||||||
playerName: string | undefined;
|
|
||||||
|
playerName: string;
|
||||||
setPlayerName: React.Dispatch<
|
setPlayerName: React.Dispatch<
|
||||||
React.SetStateAction<AppLayoutState["playerName"]>
|
React.SetStateAction<AppLayoutState["playerName"]>
|
||||||
>;
|
>;
|
||||||
preferredLanguages: string[] | undefined;
|
|
||||||
|
preferredLanguages: string[];
|
||||||
setPreferredLanguages: React.Dispatch<
|
setPreferredLanguages: React.Dispatch<
|
||||||
React.SetStateAction<AppLayoutState["preferredLanguages"]>
|
React.SetStateAction<AppLayoutState["preferredLanguages"]>
|
||||||
>;
|
>;
|
||||||
|
|
||||||
menuGestures: boolean;
|
menuGestures: boolean;
|
||||||
toggleMenuGestures: () => void;
|
toggleMenuGestures: () => void;
|
||||||
setMenuGestures: React.Dispatch<
|
setMenuGestures: React.Dispatch<
|
||||||
React.SetStateAction<AppLayoutState["menuGestures"]>
|
React.SetStateAction<AppLayoutState["menuGestures"]>
|
||||||
>;
|
>;
|
||||||
libraryItemUserStatus: Record<string, LibraryItemUserStatus> | undefined;
|
|
||||||
|
libraryItemUserStatus: Record<string, LibraryItemUserStatus>;
|
||||||
setLibraryItemUserStatus: React.Dispatch<
|
setLibraryItemUserStatus: React.Dispatch<
|
||||||
React.SetStateAction<AppLayoutState["libraryItemUserStatus"]>
|
React.SetStateAction<AppLayoutState["libraryItemUserStatus"]>
|
||||||
>;
|
>;
|
||||||
|
@ -68,38 +81,51 @@ const initialState: RequiredNonNullable<AppLayoutState> = {
|
||||||
subPanelOpen: false,
|
subPanelOpen: false,
|
||||||
toggleSubPanelOpen: () => null,
|
toggleSubPanelOpen: () => null,
|
||||||
setSubPanelOpen: () => null,
|
setSubPanelOpen: () => null,
|
||||||
|
|
||||||
configPanelOpen: false,
|
configPanelOpen: false,
|
||||||
setConfigPanelOpen: () => null,
|
setConfigPanelOpen: () => null,
|
||||||
toggleConfigPanelOpen: () => null,
|
toggleConfigPanelOpen: () => null,
|
||||||
|
|
||||||
searchPanelOpen: false,
|
searchPanelOpen: false,
|
||||||
setSearchPanelOpen: () => null,
|
setSearchPanelOpen: () => null,
|
||||||
toggleSearchPanelOpen: () => null,
|
toggleSearchPanelOpen: () => null,
|
||||||
|
|
||||||
mainPanelReduced: false,
|
mainPanelReduced: false,
|
||||||
setMainPanelReduced: () => null,
|
setMainPanelReduced: () => null,
|
||||||
toggleMainPanelReduced: () => null,
|
toggleMainPanelReduced: () => null,
|
||||||
|
|
||||||
mainPanelOpen: false,
|
mainPanelOpen: false,
|
||||||
toggleMainPanelOpen: () => null,
|
toggleMainPanelOpen: () => null,
|
||||||
setMainPanelOpen: () => null,
|
setMainPanelOpen: () => null,
|
||||||
|
|
||||||
darkMode: false,
|
darkMode: false,
|
||||||
toggleDarkMode: () => null,
|
toggleDarkMode: () => null,
|
||||||
setDarkMode: () => null,
|
setDarkMode: () => null,
|
||||||
|
|
||||||
selectedThemeMode: false,
|
selectedThemeMode: false,
|
||||||
toggleSelectedThemeMode: () => null,
|
toggleSelectedThemeMode: () => null,
|
||||||
setSelectedThemeMode: () => null,
|
setSelectedThemeMode: () => null,
|
||||||
|
|
||||||
fontSize: 1,
|
fontSize: 1,
|
||||||
setFontSize: () => null,
|
setFontSize: () => null,
|
||||||
|
|
||||||
dyslexic: false,
|
dyslexic: false,
|
||||||
toggleDyslexic: () => null,
|
toggleDyslexic: () => null,
|
||||||
setDyslexic: () => null,
|
setDyslexic: () => null,
|
||||||
|
|
||||||
currency: "USD",
|
currency: "USD",
|
||||||
setCurrency: () => null,
|
setCurrency: () => null,
|
||||||
|
|
||||||
playerName: "",
|
playerName: "",
|
||||||
setPlayerName: () => null,
|
setPlayerName: () => null,
|
||||||
|
|
||||||
preferredLanguages: [],
|
preferredLanguages: [],
|
||||||
setPreferredLanguages: () => null,
|
setPreferredLanguages: () => null,
|
||||||
|
|
||||||
menuGestures: true,
|
menuGestures: true,
|
||||||
toggleMenuGestures: () => null,
|
toggleMenuGestures: () => null,
|
||||||
setMenuGestures: () => null,
|
setMenuGestures: () => null,
|
||||||
|
|
||||||
libraryItemUserStatus: {},
|
libraryItemUserStatus: {},
|
||||||
setLibraryItemUserStatus: () => null,
|
setLibraryItemUserStatus: () => null,
|
||||||
};
|
};
|
||||||
|
@ -113,22 +139,22 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AppContextProvider = (props: Props): JSX.Element => {
|
export const AppContextProvider = (props: Props): JSX.Element => {
|
||||||
const [subPanelOpen, setSubPanelOpen] = useStateWithLocalStorage(
|
const [subPanelOpen, setSubPanelOpen] = useLocalStorage(
|
||||||
"subPanelOpen",
|
"subPanelOpen",
|
||||||
initialState.subPanelOpen
|
initialState.subPanelOpen
|
||||||
);
|
);
|
||||||
|
|
||||||
const [configPanelOpen, setConfigPanelOpen] = useStateWithLocalStorage(
|
const [configPanelOpen, setConfigPanelOpen] = useLocalStorage(
|
||||||
"configPanelOpen",
|
"configPanelOpen",
|
||||||
initialState.configPanelOpen
|
initialState.configPanelOpen
|
||||||
);
|
);
|
||||||
|
|
||||||
const [mainPanelReduced, setMainPanelReduced] = useStateWithLocalStorage(
|
const [mainPanelReduced, setMainPanelReduced] = useLocalStorage(
|
||||||
"mainPanelReduced",
|
"mainPanelReduced",
|
||||||
initialState.mainPanelReduced
|
initialState.mainPanelReduced
|
||||||
);
|
);
|
||||||
|
|
||||||
const [mainPanelOpen, setMainPanelOpen] = useStateWithLocalStorage(
|
const [mainPanelOpen, setMainPanelOpen] = useLocalStorage(
|
||||||
"mainPanelOpen",
|
"mainPanelOpen",
|
||||||
initialState.mainPanelOpen
|
initialState.mainPanelOpen
|
||||||
);
|
);
|
||||||
|
@ -136,43 +162,42 @@ export const AppContextProvider = (props: Props): JSX.Element => {
|
||||||
const [darkMode, selectedThemeMode, setDarkMode, setSelectedThemeMode] =
|
const [darkMode, selectedThemeMode, setDarkMode, setSelectedThemeMode] =
|
||||||
useDarkMode("darkMode", initialState.darkMode);
|
useDarkMode("darkMode", initialState.darkMode);
|
||||||
|
|
||||||
const [fontSize, setFontSize] = useStateWithLocalStorage(
|
const [fontSize, setFontSize] = useLocalStorage(
|
||||||
"fontSize",
|
"fontSize",
|
||||||
initialState.fontSize
|
initialState.fontSize
|
||||||
);
|
);
|
||||||
|
|
||||||
const [dyslexic, setDyslexic] = useStateWithLocalStorage(
|
const [dyslexic, setDyslexic] = useLocalStorage(
|
||||||
"dyslexic",
|
"dyslexic",
|
||||||
initialState.dyslexic
|
initialState.dyslexic
|
||||||
);
|
);
|
||||||
|
|
||||||
const [currency, setCurrency] = useStateWithLocalStorage(
|
const [currency, setCurrency] = useLocalStorage(
|
||||||
"currency",
|
"currency",
|
||||||
initialState.currency
|
initialState.currency
|
||||||
);
|
);
|
||||||
|
|
||||||
const [playerName, setPlayerName] = useStateWithLocalStorage(
|
const [playerName, setPlayerName] = useLocalStorage(
|
||||||
"playerName",
|
"playerName",
|
||||||
initialState.playerName
|
initialState.playerName
|
||||||
);
|
);
|
||||||
|
|
||||||
const [preferredLanguages, setPreferredLanguages] = useStateWithLocalStorage(
|
const [preferredLanguages, setPreferredLanguages] = useLocalStorage(
|
||||||
"preferredLanguages",
|
"preferredLanguages",
|
||||||
initialState.preferredLanguages
|
initialState.preferredLanguages
|
||||||
);
|
);
|
||||||
|
|
||||||
const [menuGestures, setMenuGestures] = useState(false);
|
const [menuGestures, setMenuGestures] = useState(false);
|
||||||
|
|
||||||
const [searchPanelOpen, setSearchPanelOpen] = useStateWithLocalStorage(
|
const [searchPanelOpen, setSearchPanelOpen] = useLocalStorage(
|
||||||
"searchPanelOpen",
|
"searchPanelOpen",
|
||||||
initialState.searchPanelOpen
|
initialState.searchPanelOpen
|
||||||
);
|
);
|
||||||
|
|
||||||
const [libraryItemUserStatus, setLibraryItemUserStatus] =
|
const [libraryItemUserStatus, setLibraryItemUserStatus] = useLocalStorage(
|
||||||
useStateWithLocalStorage(
|
"libraryItemUserStatus",
|
||||||
"libraryItemUserStatus",
|
initialState.libraryItemUserStatus
|
||||||
initialState.libraryItemUserStatus
|
);
|
||||||
);
|
|
||||||
|
|
||||||
const toggleSubPanelOpen = () => {
|
const toggleSubPanelOpen = () => {
|
||||||
setSubPanelOpen((current) => (isDefined(current) ? !current : current));
|
setSubPanelOpen((current) => (isDefined(current) ? !current : current));
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
import { useLocalStorage } from "usehooks-ts";
|
||||||
import { usePrefersDarkMode } from "./useMediaQuery";
|
import { usePrefersDarkMode } from "./useMediaQuery";
|
||||||
import { useStateWithLocalStorage } from "./useStateWithLocalStorage";
|
|
||||||
|
|
||||||
export const useDarkMode = (
|
export const useDarkMode = (
|
||||||
key: string,
|
key: string,
|
||||||
initialValue: boolean | undefined
|
initialValue: boolean
|
||||||
): [
|
): [
|
||||||
boolean | undefined,
|
boolean,
|
||||||
boolean | undefined,
|
boolean,
|
||||||
React.Dispatch<React.SetStateAction<boolean | undefined>>,
|
React.Dispatch<React.SetStateAction<boolean>>,
|
||||||
React.Dispatch<React.SetStateAction<boolean | undefined>>
|
React.Dispatch<React.SetStateAction<boolean>>
|
||||||
] => {
|
] => {
|
||||||
const [darkMode, setDarkMode] = useStateWithLocalStorage(key, initialValue);
|
const [darkMode, setDarkMode] = useLocalStorage(key, initialValue);
|
||||||
const prefersDarkMode = usePrefersDarkMode();
|
const prefersDarkMode = usePrefersDarkMode();
|
||||||
const [selectedThemeMode, setSelectedThemeMode] = useStateWithLocalStorage(
|
const [selectedThemeMode, setSelectedThemeMode] = useLocalStorage(
|
||||||
"selectedThemeMode",
|
"selectedThemeMode",
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedThemeMode === false) setDarkMode(prefersDarkMode);
|
if (!selectedThemeMode) setDarkMode(prefersDarkMode);
|
||||||
}, [selectedThemeMode, prefersDarkMode, setDarkMode]);
|
}, [selectedThemeMode, prefersDarkMode, setDarkMode]);
|
||||||
|
|
||||||
return [darkMode, selectedThemeMode, setDarkMode, setSelectedThemeMode];
|
return [darkMode, selectedThemeMode, setDarkMode, setSelectedThemeMode];
|
||||||
|
|
|
@ -42,7 +42,7 @@ export const useSmartLanguage = <T>({
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSelectedTranslationIndex(
|
setSelectedTranslationIndex(
|
||||||
getPreferredLanguage(
|
getPreferredLanguage(
|
||||||
preferredLanguages ?? [router.locale],
|
preferredLanguages,
|
||||||
availableLocales
|
availableLocales
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
import { isDefined } from "helpers/others";
|
|
||||||
|
|
||||||
export const useStateWithLocalStorage = <T>(
|
|
||||||
key: string,
|
|
||||||
initialValue: T
|
|
||||||
): [T | undefined, React.Dispatch<React.SetStateAction<T | undefined>>] => {
|
|
||||||
const [value, setValue] = useState<T | undefined>(undefined);
|
|
||||||
const [, setFromLocaleStorage] = useState<boolean>(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
try {
|
|
||||||
const item = localStorage.getItem(key);
|
|
||||||
if (isDefined(item)) {
|
|
||||||
setValue(JSON.parse(item) as T);
|
|
||||||
} else {
|
|
||||||
setValue(initialValue);
|
|
||||||
}
|
|
||||||
setFromLocaleStorage(true);
|
|
||||||
} catch (error) {
|
|
||||||
console.warn(`Error reading localStorage key “${key}”:`, error);
|
|
||||||
setValue(initialValue);
|
|
||||||
}
|
|
||||||
}, [initialValue, key]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (isDefined(value)) localStorage.setItem(key, JSON.stringify(value));
|
|
||||||
}, [value, key]);
|
|
||||||
|
|
||||||
return [value, setValue];
|
|
||||||
};
|
|
|
@ -1,38 +0,0 @@
|
||||||
import { useMemo } from "react";
|
|
||||||
import { usePrefersDarkMode } from "./useMediaQuery";
|
|
||||||
import { useStateWithLocalStorage } from "./useStateWithLocalStorage";
|
|
||||||
|
|
||||||
export enum TernaryDarkMode {
|
|
||||||
Dark = "dark",
|
|
||||||
Auto = "auto",
|
|
||||||
Light = "light",
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useTernaryDarkMode = (
|
|
||||||
key: string,
|
|
||||||
initialValue: TernaryDarkMode
|
|
||||||
): {
|
|
||||||
isDarkMode: boolean;
|
|
||||||
ternaryDarkMode: TernaryDarkMode | undefined;
|
|
||||||
setTernaryDarkMode: React.Dispatch<
|
|
||||||
React.SetStateAction<TernaryDarkMode | undefined>
|
|
||||||
>;
|
|
||||||
} => {
|
|
||||||
const [ternaryDarkMode, setTernaryDarkMode] = useStateWithLocalStorage(
|
|
||||||
key,
|
|
||||||
initialValue
|
|
||||||
);
|
|
||||||
const prefersDarkMode = usePrefersDarkMode();
|
|
||||||
const isDarkMode = useMemo(() => {
|
|
||||||
switch (ternaryDarkMode) {
|
|
||||||
case TernaryDarkMode.Light:
|
|
||||||
return false;
|
|
||||||
case TernaryDarkMode.Dark:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return prefersDarkMode;
|
|
||||||
}
|
|
||||||
}, [prefersDarkMode, ternaryDarkMode]);
|
|
||||||
|
|
||||||
return { isDarkMode, ternaryDarkMode, setTernaryDarkMode };
|
|
||||||
};
|
|
|
@ -120,7 +120,7 @@ const Library = ({
|
||||||
if (item.attributes.primary && !showPrimaryItems) return false;
|
if (item.attributes.primary && !showPrimaryItems) return false;
|
||||||
if (!item.attributes.primary && !showSecondaryItems) return false;
|
if (!item.attributes.primary && !showSecondaryItems) return false;
|
||||||
|
|
||||||
if (isDefined(filterUserStatus) && item.id && libraryItemUserStatus) {
|
if (isDefined(filterUserStatus) && item.id) {
|
||||||
if (isUntangibleGroupItem(item.attributes.metadata?.[0])) {
|
if (isUntangibleGroupItem(item.attributes.metadata?.[0])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue