2023-12-13 14:32:57 +03:00
|
|
|
'use client';
|
|
|
|
|
2023-12-21 00:12:24 +03:00
|
|
|
import clsx from 'clsx';
|
2023-12-25 16:53:27 +03:00
|
|
|
import { createContext, useCallback, useContext, useLayoutEffect, useMemo, useState } from 'react';
|
2023-07-15 17:46:19 +03:00
|
|
|
|
2024-01-04 19:38:12 +03:00
|
|
|
import Tooltip from '@/components/ui/Tooltip';
|
2023-12-13 14:32:57 +03:00
|
|
|
import useLocalStorage from '@/hooks/useLocalStorage';
|
2024-03-26 12:49:38 +03:00
|
|
|
import { FontStyle } from '@/models/miscellaneous';
|
2024-01-06 03:15:02 +03:00
|
|
|
import { animationDuration } from '@/styling/animations';
|
|
|
|
import { darkT, IColorTheme, lightT } from '@/styling/color';
|
2024-03-27 15:32:59 +03:00
|
|
|
import { globals, storage } from '@/utils/constants';
|
2023-07-15 17:46:19 +03:00
|
|
|
|
2024-04-01 19:07:20 +03:00
|
|
|
interface IOptionsContext {
|
2023-12-28 14:04:44 +03:00
|
|
|
viewportHeight: string;
|
|
|
|
mainHeight: string;
|
|
|
|
|
|
|
|
colors: IColorTheme;
|
|
|
|
|
|
|
|
darkMode: boolean;
|
|
|
|
toggleDarkMode: () => void;
|
|
|
|
|
2024-04-27 15:19:20 +03:00
|
|
|
adminMode: boolean;
|
|
|
|
toggleAdminMode: () => void;
|
|
|
|
|
2024-03-26 12:49:38 +03:00
|
|
|
mathFont: FontStyle;
|
|
|
|
setMathFont: (value: FontStyle) => void;
|
|
|
|
|
2023-12-28 14:04:44 +03:00
|
|
|
noNavigationAnimation: boolean;
|
|
|
|
noNavigation: boolean;
|
|
|
|
toggleNoNavigation: () => void;
|
|
|
|
|
|
|
|
noFooter: boolean;
|
2024-04-01 19:07:20 +03:00
|
|
|
setNoFooter: React.Dispatch<React.SetStateAction<boolean>>;
|
2023-12-28 14:04:44 +03:00
|
|
|
|
|
|
|
showScroll: boolean;
|
2024-04-01 19:07:20 +03:00
|
|
|
setShowScroll: React.Dispatch<React.SetStateAction<boolean>>;
|
|
|
|
|
|
|
|
showHelp: boolean;
|
|
|
|
toggleShowHelp: () => void;
|
2024-03-12 19:54:10 +03:00
|
|
|
|
|
|
|
calculateHeight: (offset: string) => string;
|
2023-07-15 17:46:19 +03:00
|
|
|
}
|
|
|
|
|
2024-04-01 19:07:20 +03:00
|
|
|
const OptionsContext = createContext<IOptionsContext | null>(null);
|
|
|
|
export const useConceptOptions = () => {
|
|
|
|
const context = useContext(OptionsContext);
|
2023-07-25 00:20:37 +03:00
|
|
|
if (!context) {
|
2023-08-27 15:39:49 +03:00
|
|
|
throw new Error('useConceptTheme has to be used within <ThemeState.Provider>');
|
2023-07-25 00:20:37 +03:00
|
|
|
}
|
|
|
|
return context;
|
2023-12-28 14:04:44 +03:00
|
|
|
};
|
2023-07-15 17:46:19 +03:00
|
|
|
|
2024-04-01 19:07:20 +03:00
|
|
|
interface OptionsStateProps {
|
2023-12-28 14:04:44 +03:00
|
|
|
children: React.ReactNode;
|
2023-07-15 17:46:19 +03:00
|
|
|
}
|
|
|
|
|
2024-04-01 19:07:20 +03:00
|
|
|
export const OptionsState = ({ children }: OptionsStateProps) => {
|
2024-03-27 15:32:59 +03:00
|
|
|
const [darkMode, setDarkMode] = useLocalStorage(storage.themeDark, false);
|
2024-04-27 15:19:20 +03:00
|
|
|
const [adminMode, setAdminMode] = useLocalStorage(storage.themeDark, false);
|
2024-03-27 15:32:59 +03:00
|
|
|
const [mathFont, setMathFont] = useLocalStorage<FontStyle>(storage.rseditFont, 'math');
|
2024-04-01 19:07:20 +03:00
|
|
|
const [showHelp, setShowHelp] = useLocalStorage(storage.optionsHelp, true);
|
2023-07-25 00:20:37 +03:00
|
|
|
const [noNavigation, setNoNavigation] = useState(false);
|
2024-04-01 19:07:20 +03:00
|
|
|
|
|
|
|
const [colors, setColors] = useState<IColorTheme>(lightT);
|
|
|
|
|
2023-12-25 16:53:27 +03:00
|
|
|
const [noNavigationAnimation, setNoNavigationAnimation] = useState(false);
|
2023-08-27 15:39:49 +03:00
|
|
|
const [noFooter, setNoFooter] = useState(false);
|
2023-09-05 00:23:53 +03:00
|
|
|
const [showScroll, setShowScroll] = useState(false);
|
2023-07-15 17:46:19 +03:00
|
|
|
|
2023-08-27 15:39:49 +03:00
|
|
|
function setDarkClass(isDark: boolean) {
|
2023-07-15 17:46:19 +03:00
|
|
|
const root = window.document.documentElement;
|
|
|
|
if (isDark) {
|
|
|
|
root.classList.add('dark');
|
|
|
|
} else {
|
|
|
|
root.classList.remove('dark');
|
|
|
|
}
|
2023-07-20 17:11:03 +03:00
|
|
|
root.setAttribute('data-color-scheme', !isDark ? 'light' : 'dark');
|
2023-08-27 15:39:49 +03:00
|
|
|
}
|
2023-07-15 17:46:19 +03:00
|
|
|
|
2023-08-24 14:23:17 +03:00
|
|
|
useLayoutEffect(() => {
|
2023-12-13 14:32:57 +03:00
|
|
|
setDarkClass(darkMode);
|
2023-07-15 17:46:19 +03:00
|
|
|
}, [darkMode]);
|
|
|
|
|
2023-08-27 00:19:19 +03:00
|
|
|
useLayoutEffect(() => {
|
2023-12-28 14:04:44 +03:00
|
|
|
setColors(darkMode ? darkT : lightT);
|
2023-08-27 00:19:19 +03:00
|
|
|
}, [darkMode, setColors]);
|
|
|
|
|
2023-12-28 14:04:44 +03:00
|
|
|
const toggleNoNavigation = useCallback(() => {
|
2023-12-25 16:53:27 +03:00
|
|
|
if (noNavigation) {
|
|
|
|
setNoNavigationAnimation(false);
|
|
|
|
setNoNavigation(false);
|
|
|
|
} else {
|
|
|
|
setNoNavigationAnimation(true);
|
|
|
|
setTimeout(() => setNoNavigation(true), animationDuration.navigationToggle);
|
|
|
|
}
|
|
|
|
}, [noNavigation]);
|
|
|
|
|
2024-03-12 19:54:10 +03:00
|
|
|
const calculateHeight = useCallback(
|
|
|
|
(offset: string) => {
|
|
|
|
if (noNavigation) {
|
|
|
|
return `calc(100vh - (${offset}))`;
|
|
|
|
} else if (noFooter) {
|
|
|
|
return `calc(100vh - 3rem - (${offset}))`;
|
|
|
|
} else {
|
|
|
|
return `calc(100vh - 6.75rem - (${offset}))`;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
[noNavigation, noFooter]
|
|
|
|
);
|
|
|
|
|
2024-04-01 19:07:20 +03:00
|
|
|
const toggleDarkMode = useCallback(() => {
|
|
|
|
setDarkMode(prev => !prev);
|
|
|
|
window.location.reload();
|
|
|
|
}, [setDarkMode]);
|
|
|
|
|
2023-12-28 14:04:44 +03:00
|
|
|
const mainHeight = useMemo(() => {
|
2024-03-12 19:54:10 +03:00
|
|
|
return !noNavigation ? 'calc(100vh - 6.75rem)' : '100vh';
|
2023-08-24 14:23:17 +03:00
|
|
|
}, [noNavigation]);
|
|
|
|
|
2023-12-28 14:04:44 +03:00
|
|
|
const viewportHeight = useMemo(() => {
|
2024-03-12 19:54:10 +03:00
|
|
|
return !noNavigation ? 'calc(100vh - 3rem)' : '100vh';
|
2023-08-24 14:23:17 +03:00
|
|
|
}, [noNavigation]);
|
|
|
|
|
2023-07-15 17:46:19 +03:00
|
|
|
return (
|
2024-04-01 19:07:20 +03:00
|
|
|
<OptionsContext.Provider
|
2023-12-28 14:04:44 +03:00
|
|
|
value={{
|
|
|
|
darkMode,
|
2024-04-27 15:19:20 +03:00
|
|
|
adminMode,
|
2023-12-28 14:04:44 +03:00
|
|
|
colors,
|
2024-03-26 12:49:38 +03:00
|
|
|
mathFont,
|
|
|
|
setMathFont,
|
2023-12-28 14:04:44 +03:00
|
|
|
noNavigationAnimation,
|
|
|
|
noNavigation,
|
|
|
|
noFooter,
|
|
|
|
showScroll,
|
2024-04-01 19:07:20 +03:00
|
|
|
showHelp,
|
|
|
|
toggleDarkMode: toggleDarkMode,
|
2024-04-27 15:19:20 +03:00
|
|
|
toggleAdminMode: () => setAdminMode(prev => !prev),
|
2023-12-28 14:04:44 +03:00
|
|
|
toggleNoNavigation: toggleNoNavigation,
|
|
|
|
setNoFooter,
|
|
|
|
setShowScroll,
|
2024-04-01 19:07:20 +03:00
|
|
|
toggleShowHelp: () => setShowHelp(prev => !prev),
|
2023-12-28 14:04:44 +03:00
|
|
|
viewportHeight,
|
2024-03-12 19:54:10 +03:00
|
|
|
mainHeight,
|
|
|
|
calculateHeight
|
2023-12-28 14:04:44 +03:00
|
|
|
}}
|
|
|
|
>
|
|
|
|
<>
|
2024-01-04 19:30:10 +03:00
|
|
|
<Tooltip
|
2023-12-28 14:04:44 +03:00
|
|
|
float
|
2024-03-27 15:32:59 +03:00
|
|
|
id={`${globals.tooltip}`}
|
2023-12-28 14:04:44 +03:00
|
|
|
layer='z-topmost'
|
|
|
|
place='right-start'
|
|
|
|
className={clsx('mt-3 translate-y-1/2', 'max-w-[20rem]')}
|
|
|
|
/>
|
|
|
|
{children}
|
|
|
|
</>
|
2024-04-01 19:07:20 +03:00
|
|
|
</OptionsContext.Provider>
|
2023-12-28 14:04:44 +03:00
|
|
|
);
|
|
|
|
};
|