Provider hell be gone

This commit is contained in:
DrMint 2022-11-04 01:48:00 +01:00
parent 0c4d43b891
commit 8456268270
8 changed files with 94 additions and 109 deletions

View File

@ -13,7 +13,7 @@ import { prettyLanguage } from "helpers/formatters";
import { filterHasAttributes, isDefined } from "helpers/others";
import { atoms } from "contexts/atoms";
import { useAtomGetter, useAtomPair } from "helpers/atoms";
import { ThemeMode } from "contexts/SettingsProvider";
import { ThemeMode } from "contexts/settings";
export const SettingsPopup = (): JSX.Element => {
const [preferredLanguages, setPreferredLanguages] = useAtomPair(

View File

@ -1,17 +1,28 @@
import React, { useCallback, useState } from "react";
import { useEffectOnce } from "usehooks-ts";
import { atom } from "jotai";
import { UploadImageFragment } from "graphql/generated";
import { LightBox } from "components/LightBox";
import { filterDefined } from "helpers/others";
import { useAtomSetter } from "helpers/atoms";
import { lightBox } from "contexts/atoms";
import { atomPairing, useAtomSetter } from "helpers/atoms";
export const LightBoxProvider = ({ children }: { children: React.ReactNode }): JSX.Element => {
export const lightBoxAtom = atomPairing(
atom<{
showLightBox: (
images: (UploadImageFragment | string | null | undefined)[],
index?: number
) => void;
}>({ showLightBox: () => null })
);
export const lightBox = lightBoxAtom[0]
export const LightBoxProvider = (): JSX.Element => {
const [isLightBoxVisible, setLightBoxVisibility] = useState(false);
const [lightBoxImages, setLightBoxImages] = useState<(UploadImageFragment | string)[]>([]);
const [lightBoxIndex, setLightBoxIndex] = useState(0);
const setShowLightBox = useAtomSetter(lightBox);
const setShowLightBox = useAtomSetter(lightBoxAtom);
useEffectOnce(() =>
setShowLightBox({
@ -30,17 +41,14 @@ export const LightBoxProvider = ({ children }: { children: React.ReactNode }): J
}, []);
return (
<>
<LightBox
isVisible={isLightBoxVisible}
onCloseRequest={closeLightBox}
image={lightBoxImages[lightBoxIndex]}
isNextImageAvailable={lightBoxIndex < lightBoxImages.length - 1}
isPreviousImageAvailable={lightBoxIndex > 0}
onPressNext={() => setLightBoxIndex((current) => current + 1)}
onPressPrevious={() => setLightBoxIndex((current) => current - 1)}
/>
{children}
</>
<LightBox
isVisible={isLightBoxVisible}
onCloseRequest={closeLightBox}
image={lightBoxImages[lightBoxIndex]}
isNextImageAvailable={lightBoxIndex < lightBoxImages.length - 1}
isPreviousImageAvailable={lightBoxIndex > 0}
onPressNext={() => setLightBoxIndex((current) => current + 1)}
onPressPrevious={() => setLightBoxIndex((current) => current - 1)}
/>
);
};

View File

@ -4,7 +4,7 @@ import { useScrollIntoView } from "hooks/useScrollIntoView";
import { useAtomSetter } from "helpers/atoms";
import { atoms } from "contexts/atoms";
export const AppLayoutProvider = ({ children }: { children: React.ReactNode }): JSX.Element => {
export const useAppLayout = (): void => {
const router = useRouter();
const setSettingsOpened = useAtomSetter(atoms.layout.settingsOpened);
@ -26,6 +26,4 @@ export const AppLayoutProvider = ({ children }: { children: React.ReactNode }):
}, [router, setSettingsOpened, setMainPanelOpened, setSubPanelOpened]);
useScrollIntoView();
return <>{children}</>;
};

View File

@ -1,12 +1,17 @@
import { atomWithStorage } from "jotai/utils";
import { atom } from "jotai";
import { localData } from "contexts/LocalDataProvider";
import { containerQueries } from "contexts/ContainerQueriesProvider";
import { atomWithStorage } from "jotai/utils";
import { localData } from "contexts/localData";
import { containerQueries } from "contexts/containerQueries";
import { atomPairing } from "helpers/atoms";
import { UploadImageFragment } from "graphql/generated";
import { ThemeMode } from "contexts/SettingsProvider";
import { settings } from "contexts/settings";
import { lightBox } from "contexts/LightBoxProvider";
/* [ LAYOUT ATOMS ] */
/*
* I'm getting a weird error if I put those atoms in appLayout.ts
* So I'm putting the atoms here. Sucks, I know.
*/
/* [ APPLAYOUT ATOMS ] */
const mainPanelReduced = atomPairing(atomWithStorage("isMainPanelReduced", false));
const settingsOpened = atomPairing(atomWithStorage("isSettingsOpened", false));
@ -24,37 +29,6 @@ const layout = {
terminalMode,
};
/* [ SETTINGS ATOMS ] */
const preferredLanguagesAtom = atomPairing(atomWithStorage<string[]>("preferredLanguages", []));
const themeModeAtom = atomPairing(atomWithStorage<ThemeMode>("themeMode", ThemeMode.Auto));
const darkModeAtom = atomPairing(atom(false));
const fontSizeAtom = atomPairing(atomWithStorage("fontSize", 1));
const dyslexicAtom = atomPairing(atomWithStorage("isDyslexic", false));
const currencyAtom = atomPairing(atomWithStorage("currency", "USD"));
const playerNameAtom = atomPairing(atomWithStorage("playerName", ""));
export const settings = {
preferredLanguages: preferredLanguagesAtom,
themeMode: themeModeAtom,
darkMode: darkModeAtom,
fontSize: fontSizeAtom,
dyslexic: dyslexicAtom,
currency: currencyAtom,
playerName: playerNameAtom,
};
/* [ LIGHTBOX ATOMS ] */
export const lightBox = atomPairing(
atom<{
showLightBox: (
images: (UploadImageFragment | string | null | undefined)[],
index?: number
) => void;
}>({ showLightBox: () => null })
);
/* [ TERMINAL ATOMS ] */
const previousLines = atomPairing(atom<string[]>([]));
@ -66,10 +40,10 @@ const terminal = {
};
export const atoms = {
settings,
layout,
terminal,
localData,
lightBox: lightBox[0],
lightBox,
containerQueries,
settings,
};

View File

@ -2,7 +2,7 @@ import { atom, Getter } from "jotai";
import { atomPairing, useAtomSetter } from "helpers/atoms";
import { useOnResize } from "hooks/useOnResize";
import { Ids } from "types/ids";
import { settings } from "contexts/atoms";
import { settings } from "contexts/settings";
type Size =
| "2xl"
@ -135,11 +135,7 @@ export const containerQueries = {
isSubPanelAtLeast7xl,
};
export const ContainerQueriesContextProvider = ({
children,
}: {
children: React.ReactNode;
}): JSX.Element => {
export const useContainerQueries = (): void => {
const setScreenWidth = useAtomSetter(screenWidth);
const setContentPanelWidth = useAtomSetter(contentPanelWidth);
const setSubPanelWidth = useAtomSetter(subPanelWidth);
@ -147,6 +143,4 @@ export const ContainerQueriesContextProvider = ({
useOnResize(Ids.Body, (width) => setScreenWidth(width));
useOnResize(Ids.ContentPanel, (width) => setContentPanelWidth(width));
useOnResize(Ids.SubPanel, (width) => setSubPanelWidth(width));
return <>{children}</>;
};

View File

@ -30,7 +30,7 @@ export const localData = {
const getFileName = (name: LocalDataFile): string => `/local-data/${name}.json`;
export const LocalDataProvider = ({ children }: { children: React.ReactNode }): JSX.Element => {
export const useLocalData = (): void => {
const setLanguages = useAtomSetter(languages);
const setCurrencies = useAtomSetter(currencies);
const setLangui = useAtomSetter(langui);
@ -56,6 +56,4 @@ export const LocalDataProvider = ({ children }: { children: React.ReactNode }):
console.log("[useLocalData] Refresh langui");
setLangui(processLangui(rawLangui, locale));
}, [locale, rawLangui, setLangui]);
return <>{children}</>;
};

View File

@ -1,11 +1,11 @@
import { useRouter } from "next/router";
import { useLayoutEffect, useEffect } from "react";
import { useAtomGetter, useAtomPair } from "helpers/atoms";
import { atom } from "jotai";
import { atomWithStorage } from "jotai/utils";
import { atomPairing, useAtomGetter, useAtomPair } from "helpers/atoms";
import { getDefaultPreferredLanguages } from "helpers/locales";
import { isDefined, isDefinedAndNotEmpty } from "helpers/others";
import { usePrefersDarkMode } from "hooks/useMediaQuery";
import { SettingsPopup } from "components/Panels/SettingsPopup";
import { settings } from "contexts/atoms";
export enum ThemeMode {
Dark = "dark",
@ -13,13 +13,31 @@ export enum ThemeMode {
Light = "light",
}
export const SettingsProvider = ({ children }: { children: React.ReactNode }): JSX.Element => {
const preferredLanguagesAtom = atomPairing(atomWithStorage<string[]>("preferredLanguages", []));
const themeModeAtom = atomPairing(atomWithStorage<ThemeMode>("themeMode", ThemeMode.Auto));
const darkModeAtom = atomPairing(atom(false));
const fontSizeAtom = atomPairing(atomWithStorage("fontSize", 1));
const dyslexicAtom = atomPairing(atomWithStorage("isDyslexic", false));
const currencyAtom = atomPairing(atomWithStorage("currency", "USD"));
const playerNameAtom = atomPairing(atomWithStorage("playerName", ""));
export const settings = {
preferredLanguages: preferredLanguagesAtom,
themeMode: themeModeAtom,
darkMode: darkModeAtom,
fontSize: fontSizeAtom,
dyslexic: dyslexicAtom,
currency: currencyAtom,
playerName: playerNameAtom,
};
export const useSettings = (): void => {
const router = useRouter();
const [preferredLanguages, setPreferredLanguages] = useAtomPair(settings.preferredLanguages);
const fontSize = useAtomGetter(settings.fontSize);
const isDyslexic = useAtomGetter(settings.dyslexic);
const [isDarkMode, setDarkMode] = useAtomPair(settings.darkMode);
const themeMode = useAtomGetter(settings.themeMode);
const [preferredLanguages, setPreferredLanguages] = useAtomPair(preferredLanguagesAtom);
const fontSize = useAtomGetter(fontSizeAtom);
const isDyslexic = useAtomGetter(dyslexicAtom);
const [isDarkMode, setDarkMode] = useAtomPair(darkModeAtom);
const themeMode = useAtomGetter(themeModeAtom);
useLayoutEffect(() => {
const html = document.getElementsByTagName("html")[0];
@ -82,11 +100,4 @@ export const SettingsProvider = ({ children }: { children: React.ReactNode }): J
);
}
}, [preferredLanguages, router, setPreferredLanguages]);
return (
<>
<SettingsPopup />
{children}
</>
);
};

View File

@ -16,29 +16,31 @@ import "styles/others.css";
import "styles/rc-slider.css";
import "styles/tippy.css";
import { LocalDataProvider } from "contexts/LocalDataProvider";
import { useLocalData } from "contexts/localData";
import { useAppLayout } from "contexts/appLayout";
import { LightBoxProvider } from "contexts/LightBoxProvider";
import { AppLayoutProvider } from "contexts/AppLayoutProvider";
import { SettingsProvider } from "contexts/SettingsProvider";
import { ContainerQueriesContextProvider } from "contexts/ContainerQueriesProvider";
import { SettingsPopup } from "components/Panels/SettingsPopup";
import { useSettings } from "contexts/settings";
import { useContainerQueries } from "contexts/containerQueries";
const AccordsLibraryApp = (props: AppProps): JSX.Element => (
<LocalDataProvider>
<SettingsProvider>
<AppLayoutProvider>
<ContainerQueriesContextProvider>
<LightBoxProvider>
<Script
async
defer
data-website-id={process.env.NEXT_PUBLIC_UMAMI_ID}
src={`${process.env.NEXT_PUBLIC_UMAMI_URL}/umami.js`}
/>
<props.Component {...props.pageProps} />
</LightBoxProvider>
</ContainerQueriesContextProvider>
</AppLayoutProvider>
</SettingsProvider>
</LocalDataProvider>
);
const AccordsLibraryApp = (props: AppProps): JSX.Element => {
useLocalData();
useAppLayout();
useSettings();
useContainerQueries();
return (
<>
<SettingsPopup />
<LightBoxProvider />
<Script
async
defer
data-website-id={process.env.NEXT_PUBLIC_UMAMI_ID}
src={`${process.env.NEXT_PUBLIC_UMAMI_URL}/umami.js`}
/>
<props.Component {...props.pageProps} />
</>
);
};
export default AccordsLibraryApp;