Skip to content

Commit d9ce6dd

Browse files
committed
Save light/dark setting
1 parent 84be769 commit d9ce6dd

File tree

7 files changed

+181
-126
lines changed

7 files changed

+181
-126
lines changed

app/components/AuthButton.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { Link as RemixLink, useRouteLoaderData } from "@remix-run/react";
22
import { PiUserCircle, PiUserCircleFill } from "react-icons/pi";
3-
import { User } from "~/types/User";
3+
import { RootLoaderData } from "~/types/RootLoaderData";
44

55
export function AuthButton() {
6-
const user = useRouteLoaderData<User|null>("root");
6+
const { user } = useRouteLoaderData<RootLoaderData>("root") as unknown as RootLoaderData;
77

88
let authImage:JSX.Element = <PiUserCircle title={"Not logged in"} />;
99
if (user) {

app/components/ColorSchemeToggle.tsx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,33 @@
11
import React from "react";
2+
import { default as UnencryptedCookies } from 'js-cookie';
3+
import { RootLoaderData } from "~/types/RootLoaderData";
4+
import { useRouteLoaderData } from "@remix-run/react";
25

3-
function getColorScheme() {
6+
function getColorScheme(defaultTheme?: "light" | "dark") {
47

58
if (typeof window === 'undefined') {
6-
return 'light';
9+
defaultTheme = defaultTheme || 'light';
10+
console.log("getColorScheme: window is undefined: ", defaultTheme);
11+
return defaultTheme;
712
}
813

914
if (document.documentElement.hasAttribute('data-bs-theme')) {
15+
console.log("getColorScheme: data-bs-theme: ", document.documentElement.getAttribute('data-bs-theme'));
1016
return document.documentElement.getAttribute('data-bs-theme');
1117
}
1218

1319
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
20+
console.log("getColorScheme: dark");
1421
return 'dark';
1522
} else {
23+
console.log("getColorScheme: light");
1624
return 'light';
1725
}
1826
}
1927

2028
export function ColorSchemeToggle() {
21-
const [ currentScheme, setColorScheme ] = React.useState(getColorScheme());
29+
const { theme } = useRouteLoaderData<RootLoaderData>("root") as unknown as RootLoaderData;
30+
const [ currentScheme, setColorScheme ] = React.useState(getColorScheme(theme));
2231

2332
const onClick = (scheme: 'light' | 'dark' | 'auto') => {
2433
if (scheme == 'auto') {
@@ -28,6 +37,8 @@ export function ColorSchemeToggle() {
2837
scheme = 'light';
2938
}
3039
}
40+
UnencryptedCookies.set('color-theme', scheme, { path: '/' });
41+
localStorage.setItem('color-theme', scheme);
3142
document.documentElement.setAttribute('data-bs-theme', scheme);
3243
setColorScheme(scheme);
3344
}

app/root.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,13 @@ import { Footer } from "~/components/Footer";
1212
import { LoaderFunctionArgs } from "@remix-run/node";
1313

1414
import { authenticator } from "~/services/auth.server";
15+
import { RootLoaderData } from "./types/RootLoaderData";
1516

16-
export async function loader({ request }: LoaderFunctionArgs) {
17-
return await authenticator.isAuthenticated(request);
17+
export async function loader({ request }: LoaderFunctionArgs):Promise<RootLoaderData> {
18+
return {
19+
theme: request.headers.get("Cookie")?.includes("color-theme=dark") ? "dark" : "light",
20+
user: await authenticator.isAuthenticated(request),
21+
}
1822
}
1923

2024
export function Layout({ children }: { children: React.ReactNode }) {
@@ -23,6 +27,13 @@ export function Layout({ children }: { children: React.ReactNode }) {
2327
<head>
2428
<meta charSet="utf-8" />
2529
<meta name="viewport" content="width=device-width, initial-scale=1" />
30+
<script dangerouslySetInnerHTML={{ __html:`
31+
if (localStorage.getItem('color-theme') === 'dark' || (!('color-theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
32+
document.documentElement.setAttribute('data-bs-theme', 'dark');
33+
} else {
34+
document.documentElement.setAttribute('data-bs-theme', 'light');
35+
}`}}
36+
/>
2637
<link
2738
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
2839
rel="stylesheet"

app/routes/links._index.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { regex_link } from "~/db/schema";
1111
import { authenticator } from "~/services/auth.server";
1212
import { AdminIcon } from "~/components/AdminIcon";
1313
import LinksTable from "~/components/LinksTable";
14+
import { RootLoaderData } from "~/types/RootLoaderData";
1415

1516
export const meta: MetaFunction = () => {
1617
return [
@@ -28,12 +29,9 @@ export async function loader({ request }: LoaderFunctionArgs) {
2829

2930
const links = await dborm.select().from(regex_link).orderBy(desc(regex_link.rxl_created_at)).limit(100);
3031

31-
const user = authenticator.isAuthenticated(request);
32-
33-
3432
// Commit the session and return the message
3533
return json(
36-
{ links, message, user },
34+
{ links, message },
3735
{
3836
headers: {
3937
"Set-Cookie": await cookieStorage.commitSession(session),
@@ -42,7 +40,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
4240
);
4341
}
4442
export default function Index() {
45-
const user = useRouteLoaderData<User | null>("root");
43+
const { user } = useRouteLoaderData<RootLoaderData>("root") as unknown as RootLoaderData;
4644
const data = useLoaderData<typeof loader>();
4745

4846
const message = data.message as AlertMessage | undefined;

app/types/RootLoaderData.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { User } from "./User";
2+
3+
export type RootLoaderData = {
4+
user: User|null;
5+
theme: "light" | "dark";
6+
};

0 commit comments

Comments
 (0)