From c416f5d5e8fb8c4158db06cadad83e41e0fd6ea0 Mon Sep 17 00:00:00 2001 From: Max Leiter Date: Sat, 20 May 2023 15:41:53 -0700 Subject: [PATCH] migrate header info back to client-side --- next.config.mjs | 5 +- src/app/(drift)/(auth)/components/index.tsx | 12 +-- .../(auth)/components/query-handler.tsx | 13 ++- src/app/(drift)/layout.tsx | 11 +-- src/app/components/cmdk/pages/home.tsx | 3 +- src/app/components/header/buttons.tsx | 99 ++++++++++--------- src/app/components/header/index.tsx | 12 +-- src/app/components/header/mobile.tsx | 20 +--- src/app/lib/set-theme.ts | 9 -- src/lib/constants.ts | 1 - src/lib/use-session-swr.ts | 2 +- 11 files changed, 79 insertions(+), 108 deletions(-) delete mode 100644 src/app/lib/set-theme.ts diff --git a/next.config.mjs b/next.config.mjs index 87b5ccb9..25f8337a 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -4,15 +4,14 @@ import bundleAnalyzer from "@next/bundle-analyzer" const nextConfig = { reactStrictMode: true, experimental: { - // esmExternals: true, - appDir: true, + appDir: true }, rewrites() { return [ { source: "/file/raw/:id", destination: `/api/raw/:id` - }, + } ] }, images: { diff --git a/src/app/(drift)/(auth)/components/index.tsx b/src/app/(drift)/(auth)/components/index.tsx index 7ddc6252..c1d3be4f 100644 --- a/src/app/(drift)/(auth)/components/index.tsx +++ b/src/app/(drift)/(auth)/components/index.tsx @@ -1,6 +1,6 @@ "use client" -import { startTransition, Suspense, useState } from "react" +import { useState } from "react" import styles from "./auth.module.css" import Link from "../../../components/link" import { signIn } from "next-auth/react" @@ -52,10 +52,7 @@ function Auth({ }) setSubmitting(false) } else { - startTransition(() => { - router.push("/new") - router.refresh() - }) + router.push("/new") } } @@ -75,10 +72,7 @@ function Auth({ return (
- {/* Suspense boundary because useSearchParams causes static bailout */} - - - +

Sign {signText}

diff --git a/src/app/(drift)/(auth)/components/query-handler.tsx b/src/app/(drift)/(auth)/components/query-handler.tsx index e5f1f2d0..02e51d32 100644 --- a/src/app/(drift)/(auth)/components/query-handler.tsx +++ b/src/app/(drift)/(auth)/components/query-handler.tsx @@ -2,9 +2,9 @@ import { useToasts } from "@components/toasts" import { useSearchParams } from "next/navigation" -import { useEffect } from "react" +import { Suspense, useEffect } from "react" -export function ErrorQueryParamsHandler() { +function _ErrorQueryParamsHandler() { const queryParams = useSearchParams() const { setToast } = useToasts() @@ -19,3 +19,12 @@ export function ErrorQueryParamsHandler() { return null } + +export function ErrorQueryParamsHandler() { + /* Suspense boundary because useSearchParams causes static bailout */ + return ( + + <_ErrorQueryParamsHandler /> + + ) +} diff --git a/src/app/(drift)/layout.tsx b/src/app/(drift)/layout.tsx index 4807daac..ae1269fd 100644 --- a/src/app/(drift)/layout.tsx +++ b/src/app/(drift)/layout.tsx @@ -6,10 +6,7 @@ import Header from "@components/header" import { Inter } from "next/font/google" import { getMetadata } from "src/app/lib/metadata" import dynamic from "next/dynamic" -import { cookies } from "next/headers" const inter = Inter({ subsets: ["latin"], variable: "--inter-font" }) -import { THEME_COOKIE, DEFAULT_THEME, SIGNED_IN_COOKIE } from "@lib/constants" -import { Suspense } from "react" const CmdK = dynamic(() => import("@components/cmdk"), { ssr: false }) @@ -18,10 +15,6 @@ export default async function RootLayout({ }: { children: React.ReactNode }) { - const cookiesList = cookies() - const theme = cookiesList.get(THEME_COOKIE)?.value || DEFAULT_THEME - const isAuthenticated = Boolean(cookiesList.get(SIGNED_IN_COOKIE)?.value) - return ( // suppressHydrationWarning is required because of next-themes @@ -30,9 +23,7 @@ export default async function RootLayout({ - Loading...}> -
- +
{children} diff --git a/src/app/components/cmdk/pages/home.tsx b/src/app/components/cmdk/pages/home.tsx index 9b116a09..d124c34b 100644 --- a/src/app/components/cmdk/pages/home.tsx +++ b/src/app/components/cmdk/pages/home.tsx @@ -2,7 +2,6 @@ import { Command } from "cmdk" import { useTheme } from "next-themes" import { useRouter } from "next/navigation" import { FilePlus, Moon, Search, Settings, Sun } from "react-feather" -import { setDriftTheme } from "src/app/lib/set-theme" import { CmdKPage } from ".." import Item from "../item" @@ -42,7 +41,7 @@ export default function HomePage({ { - setDriftTheme(resolvedTheme === "dark" ? "light" : "dark", setTheme) + setTheme(resolvedTheme === "dark" ? "light" : "dark") }} icon={resolvedTheme === "dark" ? : } > diff --git a/src/app/components/header/buttons.tsx b/src/app/components/header/buttons.tsx index f9f1ff89..617f447a 100644 --- a/src/app/components/header/buttons.tsx +++ b/src/app/components/header/buttons.tsx @@ -2,8 +2,8 @@ import { useSelectedLayoutSegments } from "next/navigation" import FadeIn from "@components/fade-in" -import { setDriftTheme } from "src/app/lib/set-theme" import { + Circle, Home, Moon, PlusCircle, @@ -18,6 +18,7 @@ import Link from "@components/link" import { useSessionSWR } from "@lib/use-session-swr" import { useTheme } from "next-themes" import styles from "./buttons.module.css" +import { useEffect, useState } from "react" // constant width for sign in / sign out buttons to avoid CLS const SIGN_IN_WIDTH = 110 @@ -38,27 +39,6 @@ type Tab = { } ) -export function HeaderButtons({ - isAuthenticated, - theme: initialTheme -}: { - isAuthenticated: boolean - theme: string -}) { - const { isAdmin, userId } = useSessionSWR() - const { resolvedTheme } = useTheme() - return ( - <> - {getButtons({ - isAuthenticated, - theme: resolvedTheme ? resolvedTheme : initialTheme, - isAdmin, - userId - })} - - ) -} - function NavButton(tab: Tab) { const segment = useSelectedLayoutSegments().slice(-1)[0] const isActive = segment === tab.value.toLowerCase() @@ -89,32 +69,51 @@ function NavButton(tab: Tab) { } } -function ThemeButton({ theme }: { theme: string }) { - const { setTheme } = useTheme() +function ThemeButton() { + const { setTheme, resolvedTheme } = useTheme() + const [mounted, setMounted] = useState(false) + + useEffect(() => { + setMounted(true) + }, []) + return ( - : } - value="dark" - onClick={() => { - setDriftTheme(theme === "dark" ? "light" : "dark", setTheme) - }} - key="theme" - /> + <> + {!mounted && ( + } + value="dark" + href="" + key="theme" + /> + )} + {mounted && ( + {resolvedTheme === "dark" ? : } + } + value="dark" + onClick={() => { + setTheme(resolvedTheme === "dark" ? "light" : "dark") + }} + key="theme" + /> + )} + ) } -export function getButtons({ - isAuthenticated, - theme, - isAdmin, - userId -}: { - isAuthenticated: boolean - theme: string - isAdmin?: boolean - userId?: string -}) { +export function HeaderButtons(): JSX.Element { + const { isAdmin, isAuthenticated, userId } = useSessionSWR() + + useEffect(() => { + if (isAuthenticated && !userId) { + signOut() + } + }, [isAuthenticated, userId]) + return ( <> - + {isAdmin && ( )} + {isAuthenticated === undefined && ( + } + value="signin" + href="/signin" + width={SIGN_IN_WIDTH} + /> + )} ) } diff --git a/src/app/components/header/index.tsx b/src/app/components/header/index.tsx index 0242be1b..c4baa646 100644 --- a/src/app/components/header/index.tsx +++ b/src/app/components/header/index.tsx @@ -2,21 +2,15 @@ import styles from "./header.module.css" import { HeaderButtons } from "./buttons" import MobileHeader from "./mobile" -export default function Header({ - theme, - isAuthenticated -}: { - theme: string - isAuthenticated: boolean -}) { +export default function Header() { return (
- +
- +
) } diff --git a/src/app/components/header/mobile.tsx b/src/app/components/header/mobile.tsx index 9b34f4d8..4f20b3f1 100644 --- a/src/app/components/header/mobile.tsx +++ b/src/app/components/header/mobile.tsx @@ -6,23 +6,9 @@ import Button from "@components/button" import { Menu } from "react-feather" import clsx from "clsx" import styles from "./mobile.module.css" -import { getButtons } from "./buttons" -import { useSessionSWR } from "@lib/use-session-swr" - -export default function MobileHeader({ - isAuthenticated, - theme -}: { - isAuthenticated: boolean - theme: string -}) { - const { isAdmin } = useSessionSWR() - const buttons = getButtons({ - isAuthenticated, - theme, - isAdmin - }) +import { HeaderButtons } from "./buttons" +export default function MobileHeader() { // TODO: this is a hack to close the radix ui menu when a next link is clicked const onClick = () => { document.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape" })) @@ -40,7 +26,7 @@ export default function MobileHeader({ - {buttons.props.children.map((button: JSX.Element) => ( + {HeaderButtons().props.children.map((button: JSX.Element) => ( void) { - setter(theme) - cookies.set(THEME_COOKIE, theme, { path: "/" }) -} diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 920e42c5..d44ea68e 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -10,7 +10,6 @@ export function isAllowedVisibilityForWebpage( export const DEFAULT_THEME = "dark" export const SIGNED_IN_COOKIE = "next-auth.session-token" -export const THEME_COOKIE = "drift-theme" // Code files for uploading with drag and drop and syntax highlighting export const allowedFileTypes = [ diff --git a/src/lib/use-session-swr.ts b/src/lib/use-session-swr.ts index 27da0c24..e9240359 100644 --- a/src/lib/use-session-swr.ts +++ b/src/lib/use-session-swr.ts @@ -10,7 +10,7 @@ export function useSessionSWR(swrOpts: SWRConfiguration = {}) { mutate } = useSWR("/api/auth/session", { fetcher: (url) => fetch(url).then((res) => res.json()) as Promise, - revalidateOnFocus: false, + revalidateOnFocus: true, ...swrOpts })