Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | 6x 6x 27x 27x 27x 40x 40x 27x 27x 27x 24x 3x 2x 1x 27x 27x 27x 22x 27x 3x 27x 1x 27x 13x 6x 27x 6x 6x 6x 7x 7x 27x 24x | import React, { createContext, useContext, useEffect, useMemo, useState } from "react";
import { ThemeProvider, StyledEngineProvider } from "@mui/material/styles";
import { Box, CssBaseline } from "@mui/material";
import { useSelector } from "react-redux";
import { createUiTheme } from "@/theme/ui";
import RTL from "@/theme/ui/options/right-to-left";
import { themeIDs } from "./CustomColors";
import { getPortalRole } from "@/authentication/auth0";
const ThemeToggleContext = createContext();
export const ThemeToggleProvider = ({ children }) => {
const [themeMode, setThemeMode] = useState("light");
const [themePreset, setThemePreset] = useState("default");
const [themeDirection] = useState("ltr");
const teacherThemeState = useSelector((state) => state?.TeacherThemes || null);
const studentThemeState = useSelector((state) => state?.StudentThemes || null);
const role = getPortalRole();
const reduxThemeState = (() => {
if (role === "teacher") {
return teacherThemeState;
}
if (role === "student") {
return studentThemeState;
}
return null;
})();
const safeThemeMode = themeMode || "light";
const safeThemePreset = themePreset || "default";
const theme = useMemo(
() =>
createUiTheme({
mode: safeThemeMode,
preset: safeThemePreset,
direction: themeDirection,
}),
[safeThemeMode, safeThemePreset, themeDirection]
);
const toggleThemeMode = () => {
setThemeMode((prevMode) => (prevMode === "light" ? "dark" : "light"));
};
const changeThemePreset = (newPreset) => {
setThemePreset(newPreset);
};
// Modified by Allan Ninal — this effect had no else branch, so clearing the saved
// theme left whatever was already applied on screen. `_deleteTeacherTheme.fulfilled`
// nulls both fields precisely so this provider can fall back ("slice clears local
// cache so ThemeContext defaults", in the slice), but nothing here did. Reset while
// in a dark saved theme and the app said "Theme reverted to default" and stayed
// dark, disagreeing with the server until the next reload. ThemePresets calls
// changeThemePreset("default") itself, which hid half of it — the preset reverted,
// the mode did not.
//
// A hand-picked mode is not at risk from the plain else: this only runs when the
// dependencies CHANGE, and toggling by hand does not touch the slice. I first
// guarded it with a "was a theme ever applied" ref, then removed it — no realistic
// transition could tell the two apart, so it was complexity no test could justify.
useEffect(() => {
if (reduxThemeState?.selectedTheme && reduxThemeState?.colorMode) {
const themeId = reduxThemeState.selectedTheme._id;
const mappedPreset = Object.entries(themeIDs).find(([, id]) => id === themeId)?.[0] || "default";
setThemeMode(reduxThemeState.colorMode);
setThemePreset(mappedPreset);
return;
}
setThemeMode("light");
setThemePreset("default");
}, [reduxThemeState?.selectedTheme, reduxThemeState?.colorMode]);
return (
<ThemeToggleContext.Provider value={{ themeMode, toggleThemeMode, themePreset, changeThemePreset }}>
<StyledEngineProvider injectFirst>
<ThemeProvider theme={theme}>
<RTL themeDirection={themeDirection}>
<CssBaseline enableColorScheme />
<Box
sx={{
transition: "background-color 0.3s ease, color 0.3s ease",
bgcolor: "background.default",
color: "text.primary",
minHeight: "100%",
}}
>
{children}
</Box>
</RTL>
</ThemeProvider>
</StyledEngineProvider>
</ThemeToggleContext.Provider>
);
};
export const useThemeToggle = () => useContext(ThemeToggleContext);
|