Skip to content

Commit

Permalink
feat: manually switch color scheme
Browse files Browse the repository at this point in the history
  • Loading branch information
stonith404 committed Dec 24, 2022
1 parent cabaee5 commit ef21bac
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 28 deletions.
67 changes: 67 additions & 0 deletions frontend/src/components/account/ThemeSwitcher.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import {
Box,
Center,
ColorScheme,
SegmentedControl,
Stack,
useMantineColorScheme,
} from "@mantine/core";
import { useColorScheme } from "@mantine/hooks";
import { useState } from "react";
import { TbDeviceLaptop, TbMoon, TbSun } from "react-icons/tb";
import usePreferences from "../../hooks/usePreferences";

const ThemeSwitcher = () => {
const preferences = usePreferences();
const [colorScheme, setColorScheme] = useState(
preferences.get("colorScheme")
);
const { toggleColorScheme } = useMantineColorScheme();
const systemColorScheme = useColorScheme();

return (
<Stack>
<SegmentedControl
value={colorScheme}
onChange={(value) => {
preferences.set("colorScheme", value);
setColorScheme(value);
toggleColorScheme(
value == "system" ? systemColorScheme : (value as ColorScheme)
);
}}
data={[
{
label: (
<Center>
<TbMoon size={16} />
<Box ml={10}>Dark</Box>
</Center>
),
value: "dark",
},
{
label: (
<Center>
<TbSun size={16} />
<Box ml={10}>Light</Box>
</Center>
),
value: "light",
},
{
label: (
<Center>
<TbDeviceLaptop size={16} />
<Box ml={10}>System</Box>
</Center>
),
value: "system",
},
]}
/>
</Stack>
);
};

export default ThemeSwitcher;
30 changes: 30 additions & 0 deletions frontend/src/hooks/usePreferences.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const defaultPreferences = [
{
key: "colorScheme",
value: "system",
},
];

const get = (key: string) => {
if (typeof window !== "undefined") {
const preferences = JSON.parse(localStorage.getItem("preferences") ?? "{}");
return (
preferences[key] ??
defaultPreferences.find((p) => p.key == key)?.value ??
null
);
}
};

const set = (key: string, value: string) => {
if (typeof window !== "undefined") {
const preferences = JSON.parse(localStorage.getItem("preferences") ?? "{}");
preferences[key] = value;
localStorage.setItem("preferences", JSON.stringify(preferences));
}
};
const usePreferences = () => {
return { get, set };
};

export default usePreferences;
59 changes: 35 additions & 24 deletions frontend/src/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
ColorScheme,
ColorSchemeProvider,
Container,
LoadingOverlay,
MantineProvider,
Expand All @@ -11,7 +12,8 @@ import type { AppProps } from "next/app";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import Header from "../components/navBar/NavBar";
import useConfig, { ConfigContext } from "../hooks/config.hook";
import { ConfigContext } from "../hooks/config.hook";
import usePreferences from "../hooks/usePreferences";
import { UserContext } from "../hooks/user.hook";
import authService from "../services/auth.service";
import configService from "../services/config.service";
Expand All @@ -25,9 +27,9 @@ import { GlobalLoadingContext } from "../utils/loading.util";
function App({ Component, pageProps }: AppProps) {
const systemTheme = useColorScheme();
const router = useRouter();
const config = useConfig();
const preferences = usePreferences();

const [colorScheme, setColorScheme] = useState<ColorScheme>();
const [colorScheme, setColorScheme] = useState<ColorScheme>("light");
const [isLoading, setIsLoading] = useState(true);
const [user, setUser] = useState<CurrentUser | null>(null);
const [configVariables, setConfigVariables] = useState<Config[] | null>(null);
Expand Down Expand Up @@ -56,7 +58,11 @@ function App({ Component, pageProps }: AppProps) {
}, [router.asPath]);

useEffect(() => {
setColorScheme(systemTheme);
setColorScheme(
preferences.get("colorScheme") == "system"
? systemTheme
: preferences.get("colorScheme")
);
}, [systemTheme]);

return (
Expand All @@ -65,26 +71,31 @@ function App({ Component, pageProps }: AppProps) {
withNormalizeCSS
theme={{ colorScheme, ...globalStyle }}
>
<GlobalStyle />
<NotificationsProvider>
<ModalsProvider>
<GlobalLoadingContext.Provider value={{ isLoading, setIsLoading }}>
{isLoading ? (
<LoadingOverlay visible overlayOpacity={1} />
) : (
<ConfigContext.Provider value={configVariables}>
<UserContext.Provider value={{ user, setUser }}>
<LoadingOverlay visible={isLoading} overlayOpacity={1} />
<Header />
<Container>
<Component {...pageProps} />
</Container>
</UserContext.Provider>{" "}
</ConfigContext.Provider>
)}
</GlobalLoadingContext.Provider>
</ModalsProvider>
</NotificationsProvider>
<ColorSchemeProvider
colorScheme={colorScheme}
toggleColorScheme={(value) => setColorScheme(value ?? "light")}
>
<GlobalStyle />
<NotificationsProvider>
<ModalsProvider>
<GlobalLoadingContext.Provider value={{ isLoading, setIsLoading }}>
{isLoading ? (
<LoadingOverlay visible overlayOpacity={1} />
) : (
<ConfigContext.Provider value={configVariables}>
<UserContext.Provider value={{ user, setUser }}>
<LoadingOverlay visible={isLoading} overlayOpacity={1} />
<Header />
<Container>
<Component {...pageProps} />
</Container>
</UserContext.Provider>{" "}
</ConfigContext.Provider>
)}
</GlobalLoadingContext.Provider>
</ModalsProvider>
</NotificationsProvider>
</ColorSchemeProvider>
</MantineProvider>
);
}
Expand Down
12 changes: 8 additions & 4 deletions frontend/src/pages/account/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { useRouter } from "next/router";
import { Tb2Fa } from "react-icons/tb";
import * as yup from "yup";
import showEnableTotpModal from "../../components/account/showEnableTotpModal";
import ThemeSwitcher from "../../components/account/ThemeSwitcher";
import useUser from "../../hooks/user.hook";
import authService from "../../services/auth.service";
import userService from "../../services/user.service";
Expand Down Expand Up @@ -164,8 +165,6 @@ const Account = () => {
</Tabs.List>

<Tabs.Panel value="totp" pt="xs">
{/* TODO: This is ugly, make it prettier */}
{/* If we have totp enabled, show different text */}
{user.totpVerified ? (
<>
<form
Expand Down Expand Up @@ -236,8 +235,13 @@ const Account = () => {
</Tabs.Panel>
</Tabs>
</Paper>

<Center mt={80}>
<Paper withBorder p="xl" mt="lg">
<Title order={5} mb="xs">
Color scheme
</Title>
<ThemeSwitcher />
</Paper>
<Center mt={80} mb="lg">
<Stack>
<Button
variant="light"
Expand Down

0 comments on commit ef21bac

Please sign in to comment.