mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-06-18 21:15:16 +02:00
refactor(web): consume runtime config in auth and dashboard flows
This commit is contained in:
parent
9ef2c6a60e
commit
c5dd55e964
9 changed files with 74 additions and 61 deletions
|
|
@ -7,10 +7,10 @@ import { useRouter } from "next/navigation";
|
|||
import { useTranslations } from "next-intl";
|
||||
import { useState } from "react";
|
||||
import { loginMutationAtom } from "@/atoms/auth/auth-mutation.atoms";
|
||||
import { useRuntimeConfig } from "@/components/providers/runtime-config";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Spinner } from "@/components/ui/spinner";
|
||||
import { getAuthErrorDetails, isNetworkError } from "@/lib/auth-errors";
|
||||
import { AUTH_TYPE } from "@/lib/env-config";
|
||||
import { ValidationError } from "@/lib/error";
|
||||
import { trackLoginAttempt, trackLoginFailure, trackLoginSuccess } from "@/lib/posthog/events";
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ export function LocalLoginForm() {
|
|||
title: null,
|
||||
message: null,
|
||||
});
|
||||
const authType = AUTH_TYPE;
|
||||
const { authType } = useRuntimeConfig();
|
||||
const router = useRouter();
|
||||
const [{ mutateAsync: login, isPending: isLoggingIn }] = useAtom(loginMutationAtom);
|
||||
|
||||
|
|
|
|||
5
surfsense_web/app/(home)/login/layout.tsx
Normal file
5
surfsense_web/app/(home)/login/layout.tsx
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import { RuntimeConfig } from "@/components/providers/runtime-config.server";
|
||||
|
||||
export default function LoginLayout({ children }: { children: React.ReactNode }) {
|
||||
return <RuntimeConfig>{children}</RuntimeConfig>;
|
||||
}
|
||||
|
|
@ -6,11 +6,10 @@ import { useTranslations } from "next-intl";
|
|||
import { Suspense, useEffect, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { Logo } from "@/components/Logo";
|
||||
import { useRuntimeConfig } from "@/components/providers/runtime-config";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useGlobalLoadingEffect } from "@/hooks/use-global-loading";
|
||||
import { getAuthErrorDetails, shouldRetry } from "@/lib/auth-errors";
|
||||
import { setRedirectPath } from "@/lib/auth-utils";
|
||||
import { AUTH_TYPE } from "@/lib/env-config";
|
||||
import { AmbientBackground } from "./AmbientBackground";
|
||||
import { GoogleLoginButton } from "./GoogleLoginButton";
|
||||
import { LocalLoginForm } from "./LocalLoginForm";
|
||||
|
|
@ -19,8 +18,7 @@ function LoginContent() {
|
|||
const t = useTranslations("auth");
|
||||
const tCommon = useTranslations("common");
|
||||
const router = useRouter();
|
||||
const [authType, setAuthType] = useState<string | null>(null);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const { authType } = useRuntimeConfig();
|
||||
const [urlError, setUrlError] = useState<{ title: string; message: string } | null>(null);
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
|
|
@ -96,19 +94,7 @@ function LoginContent() {
|
|||
duration: 4000,
|
||||
});
|
||||
}
|
||||
|
||||
// Get the auth type from centralized config
|
||||
setAuthType(AUTH_TYPE);
|
||||
setIsLoading(false);
|
||||
}, [searchParams, t, tCommon]);
|
||||
|
||||
// Use global loading screen for auth type determination - spinner animation won't reset
|
||||
useGlobalLoadingEffect(isLoading);
|
||||
|
||||
// Show nothing while loading - the GlobalLoadingProvider handles the loading UI
|
||||
if (isLoading) {
|
||||
return null;
|
||||
}
|
||||
}, [router, searchParams, t, tCommon]);
|
||||
|
||||
if (authType === "GOOGLE") {
|
||||
return <GoogleLoginButton />;
|
||||
|
|
|
|||
5
surfsense_web/app/(home)/register/layout.tsx
Normal file
5
surfsense_web/app/(home)/register/layout.tsx
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import { RuntimeConfig } from "@/components/providers/runtime-config.server";
|
||||
|
||||
export default function RegisterLayout({ children }: { children: React.ReactNode }) {
|
||||
return <RuntimeConfig>{children}</RuntimeConfig>;
|
||||
}
|
||||
|
|
@ -9,11 +9,11 @@ import { useEffect, useState } from "react";
|
|||
import { type ExternalToast, toast } from "sonner";
|
||||
import { registerMutationAtom } from "@/atoms/auth/auth-mutation.atoms";
|
||||
import { Logo } from "@/components/Logo";
|
||||
import { useRuntimeConfig } from "@/components/providers/runtime-config";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Spinner } from "@/components/ui/spinner";
|
||||
import { getAuthErrorDetails, isNetworkError, shouldRetry } from "@/lib/auth-errors";
|
||||
import { getBearerToken } from "@/lib/auth-utils";
|
||||
import { AUTH_TYPE } from "@/lib/env-config";
|
||||
import { AppError, ValidationError } from "@/lib/error";
|
||||
import {
|
||||
trackRegistrationAttempt,
|
||||
|
|
@ -25,6 +25,7 @@ import { AmbientBackground } from "../login/AmbientBackground";
|
|||
export default function RegisterPage() {
|
||||
const t = useTranslations("auth");
|
||||
const tCommon = useTranslations("common");
|
||||
const { authType } = useRuntimeConfig();
|
||||
const [email, setEmail] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [confirmPassword, setConfirmPassword] = useState("");
|
||||
|
|
@ -44,10 +45,10 @@ export default function RegisterPage() {
|
|||
router.replace("/dashboard");
|
||||
return;
|
||||
}
|
||||
if (AUTH_TYPE !== "LOCAL") {
|
||||
if (authType !== "LOCAL") {
|
||||
router.push("/login");
|
||||
}
|
||||
}, [router]);
|
||||
}, [authType, router]);
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
|
|
|||
42
surfsense_web/app/dashboard/dashboard-shell.tsx
Normal file
42
surfsense_web/app/dashboard/dashboard-shell.tsx
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { USER_QUERY_KEY } from "@/atoms/user/user-query.atoms";
|
||||
import { useGlobalLoadingEffect } from "@/hooks/use-global-loading";
|
||||
import { ensureTokensFromElectron, getBearerToken, redirectToLogin } from "@/lib/auth-utils";
|
||||
import { queryClient } from "@/lib/query-client/client";
|
||||
|
||||
export function DashboardShell({ children }: { children: React.ReactNode }) {
|
||||
const [isCheckingAuth, setIsCheckingAuth] = useState(true);
|
||||
|
||||
// Use the global loading screen - spinner animation won't reset
|
||||
useGlobalLoadingEffect(isCheckingAuth);
|
||||
|
||||
useEffect(() => {
|
||||
async function checkAuth() {
|
||||
let token = getBearerToken();
|
||||
if (!token) {
|
||||
const synced = await ensureTokensFromElectron();
|
||||
if (synced) token = getBearerToken();
|
||||
}
|
||||
if (!token) {
|
||||
redirectToLogin();
|
||||
return;
|
||||
}
|
||||
queryClient.invalidateQueries({ queryKey: [...USER_QUERY_KEY] });
|
||||
setIsCheckingAuth(false);
|
||||
}
|
||||
checkAuth();
|
||||
}, []);
|
||||
|
||||
// Return null while loading - the global provider handles the loading UI
|
||||
if (isCheckingAuth) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col ">
|
||||
<div className="flex-1 min-h-0">{children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,46 +1,14 @@
|
|||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { USER_QUERY_KEY } from "@/atoms/user/user-query.atoms";
|
||||
import { useGlobalLoadingEffect } from "@/hooks/use-global-loading";
|
||||
import { ensureTokensFromElectron, getBearerToken, redirectToLogin } from "@/lib/auth-utils";
|
||||
import { queryClient } from "@/lib/query-client/client";
|
||||
import { RuntimeConfig } from "@/components/providers/runtime-config.server";
|
||||
import { DashboardShell } from "./dashboard-shell";
|
||||
|
||||
interface DashboardLayoutProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export default function DashboardLayout({ children }: DashboardLayoutProps) {
|
||||
const [isCheckingAuth, setIsCheckingAuth] = useState(true);
|
||||
|
||||
// Use the global loading screen - spinner animation won't reset
|
||||
useGlobalLoadingEffect(isCheckingAuth);
|
||||
|
||||
useEffect(() => {
|
||||
async function checkAuth() {
|
||||
let token = getBearerToken();
|
||||
if (!token) {
|
||||
const synced = await ensureTokensFromElectron();
|
||||
if (synced) token = getBearerToken();
|
||||
}
|
||||
if (!token) {
|
||||
redirectToLogin();
|
||||
return;
|
||||
}
|
||||
queryClient.invalidateQueries({ queryKey: [...USER_QUERY_KEY] });
|
||||
setIsCheckingAuth(false);
|
||||
}
|
||||
checkAuth();
|
||||
}, []);
|
||||
|
||||
// Return null while loading - the global provider handles the loading UI
|
||||
if (isCheckingAuth) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col ">
|
||||
<div className="flex-1 min-h-0">{children}</div>
|
||||
</div>
|
||||
<RuntimeConfig>
|
||||
<DashboardShell>{children}</DashboardShell>
|
||||
</RuntimeConfig>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
5
surfsense_web/app/desktop/login/layout.tsx
Normal file
5
surfsense_web/app/desktop/login/layout.tsx
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import { RuntimeConfig } from "@/components/providers/runtime-config.server";
|
||||
|
||||
export default function DesktopLoginLayout({ children }: { children: React.ReactNode }) {
|
||||
return <RuntimeConfig>{children}</RuntimeConfig>;
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|||
import { toast } from "sonner";
|
||||
import { loginMutationAtom } from "@/atoms/auth/auth-mutation.atoms";
|
||||
import { DEFAULT_SHORTCUTS, keyEventToAccelerator } from "@/components/desktop/shortcut-recorder";
|
||||
import { useIsGoogleAuth } from "@/components/providers/runtime-config";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
|
|
@ -17,9 +18,8 @@ import { Spinner } from "@/components/ui/spinner";
|
|||
import { useElectronAPI } from "@/hooks/use-platform";
|
||||
import { searchSpacesApiService } from "@/lib/apis/search-spaces-api.service";
|
||||
import { setBearerToken } from "@/lib/auth-utils";
|
||||
import { AUTH_TYPE, BACKEND_URL } from "@/lib/env-config";
|
||||
import { BACKEND_URL } from "@/lib/env-config";
|
||||
|
||||
const isGoogleAuth = AUTH_TYPE === "GOOGLE";
|
||||
type ShortcutKey = "generalAssist" | "quickAsk" | "screenshotAssist";
|
||||
type ShortcutMap = typeof DEFAULT_SHORTCUTS;
|
||||
|
||||
|
|
@ -189,6 +189,7 @@ function HotkeyRow({
|
|||
export default function DesktopLoginPage() {
|
||||
const router = useRouter();
|
||||
const api = useElectronAPI();
|
||||
const isGoogleAuth = useIsGoogleAuth();
|
||||
const [{ mutateAsync: login, isPending: isLoggingIn }] = useAtom(loginMutationAtom);
|
||||
|
||||
const [email, setEmail] = useState("");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue