feat: add themes
This commit is contained in:
@@ -12,7 +12,7 @@ import {
|
||||
useLoaderData,
|
||||
useLocation,
|
||||
} from 'react-router';
|
||||
import { ThemeProvider } from 'remix-themes';
|
||||
import { PreventFlashOnWrongTheme, ThemeProvider, useTheme } from 'remix-themes';
|
||||
import { getOptionalLoaderSession } from 'server/utils/get-loader-session';
|
||||
|
||||
import { SessionProvider } from '@documenso/lib/client-only/providers/session';
|
||||
@@ -84,13 +84,13 @@ export async function loader({ request }: Route.LoaderArgs) {
|
||||
);
|
||||
}
|
||||
|
||||
export function Layout({ children }: { children: React.ReactNode }) {
|
||||
const { publicEnv, theme, lang } = useLoaderData<typeof loader>() || {};
|
||||
export function App() {
|
||||
const { publicEnv, lang, session, ...data } = useLoaderData<typeof loader>() || {};
|
||||
|
||||
// const [theme] = useTheme();
|
||||
const [theme] = useTheme();
|
||||
|
||||
return (
|
||||
<html translate="no" lang={lang} data-theme={theme ?? ''}>
|
||||
<html translate="no" lang={lang} className={theme ?? ''}>
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
||||
@@ -102,18 +102,25 @@ export function Layout({ children }: { children: React.ReactNode }) {
|
||||
<Meta />
|
||||
<Links />
|
||||
<meta name="google" content="notranslate" />
|
||||
{/* <PreventFlashOnWrongTheme ssrTheme={Boolean(theme)} /> */}
|
||||
<PreventFlashOnWrongTheme ssrTheme={Boolean(data.theme)} />
|
||||
|
||||
<Suspense>
|
||||
<PostHogPageview />
|
||||
</Suspense>
|
||||
</head>
|
||||
<body>
|
||||
{children}
|
||||
<SessionProvider session={session}>
|
||||
<TooltipProvider>
|
||||
<TrpcProvider>
|
||||
<Outlet />
|
||||
<Toaster />
|
||||
</TrpcProvider>
|
||||
</TooltipProvider>
|
||||
</SessionProvider>
|
||||
|
||||
<ScrollRestoration />
|
||||
<Scripts />
|
||||
|
||||
{/* Todo: Do we want this here? */}
|
||||
<RefreshOnFocus />
|
||||
|
||||
<script
|
||||
@@ -126,7 +133,14 @@ export function Layout({ children }: { children: React.ReactNode }) {
|
||||
);
|
||||
}
|
||||
|
||||
export default function App({ loaderData }: Route.ComponentProps) {
|
||||
/**
|
||||
* We have this weird setup with:
|
||||
* - No root layout
|
||||
* - AppWithTheme
|
||||
*
|
||||
* To handle remix-themes.
|
||||
*/
|
||||
export default function AppWithTheme({ loaderData }: Route.ComponentProps) {
|
||||
const location = useLocation();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -134,18 +148,9 @@ export default function App({ loaderData }: Route.ComponentProps) {
|
||||
}, [location.pathname]);
|
||||
|
||||
return (
|
||||
<SessionProvider session={loaderData.session}>
|
||||
{/* Todo: Themes (this won't work for now) */}
|
||||
<ThemeProvider specifiedTheme={loaderData.theme} themeAction="/api/theme">
|
||||
<TooltipProvider>
|
||||
<TrpcProvider>
|
||||
<Outlet />
|
||||
|
||||
<Toaster />
|
||||
</TrpcProvider>
|
||||
</TooltipProvider>
|
||||
</ThemeProvider>
|
||||
</SessionProvider>
|
||||
<ThemeProvider specifiedTheme={loaderData.theme} themeAction="/api/theme">
|
||||
<App />
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { createCookieSessionStorage } from 'react-router';
|
||||
import { createThemeSessionResolver } from 'remix-themes';
|
||||
|
||||
import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
|
||||
import { env } from '@documenso/lib/utils/env';
|
||||
import { getCookieDomain, useSecureCookies } from '@documenso/lib/constants/auth';
|
||||
|
||||
const themeSessionStorage = createCookieSessionStorage({
|
||||
cookie: {
|
||||
@@ -10,10 +9,9 @@ const themeSessionStorage = createCookieSessionStorage({
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
secrets: ['insecure-secret'], // Todo: Don't need secret
|
||||
// Todo: Check this works on production.
|
||||
// Set domain and secure only if in production
|
||||
...(env('NODE_ENV') === 'production' ? { domain: NEXT_PUBLIC_WEBAPP_URL(), secure: true } : {}),
|
||||
secrets: ['insecure-secret-do-not-care'],
|
||||
secure: useSecureCookies,
|
||||
domain: getCookieDomain(),
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import type { Context } from 'hono';
|
||||
import { deleteCookie, getSignedCookie, setSignedCookie } from 'hono/cookie';
|
||||
|
||||
import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
|
||||
import { useSecureCookies } from '@documenso/lib/constants/auth';
|
||||
import { getCookieDomain, useSecureCookies } from '@documenso/lib/constants/auth';
|
||||
import { appLog } from '@documenso/lib/utils/debugger';
|
||||
import { env } from '@documenso/lib/utils/env';
|
||||
|
||||
@@ -20,12 +19,6 @@ const getAuthSecret = () => {
|
||||
return authSecret;
|
||||
};
|
||||
|
||||
const getAuthDomain = () => {
|
||||
const url = new URL(NEXT_PUBLIC_WEBAPP_URL());
|
||||
|
||||
return url.hostname;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generic auth session cookie options.
|
||||
*/
|
||||
@@ -34,7 +27,7 @@ export const sessionCookieOptions = {
|
||||
path: '/',
|
||||
sameSite: useSecureCookies ? 'none' : 'lax', // Todo: This feels wrong?
|
||||
secure: useSecureCookies,
|
||||
domain: getAuthDomain(),
|
||||
domain: getCookieDomain(),
|
||||
// Todo: Max age for specific auth cookies.
|
||||
} as const;
|
||||
|
||||
|
||||
@@ -56,3 +56,9 @@ export const useSecureCookies =
|
||||
const secureCookiePrefix = useSecureCookies ? '__Secure-' : '';
|
||||
|
||||
export const formatSecureCookieName = (name: string) => `${secureCookiePrefix}${name}`;
|
||||
|
||||
export const getCookieDomain = () => {
|
||||
const url = new URL(NEXT_PUBLIC_WEBAPP_URL());
|
||||
|
||||
return url.hostname;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user