diff --git a/src/interface/web/app/common/layoutHelper.tsx b/src/interface/web/app/common/layoutHelper.tsx index 11b1043d..5c34e641 100644 --- a/src/interface/web/app/common/layoutHelper.tsx +++ b/src/interface/web/app/common/layoutHelper.tsx @@ -4,11 +4,12 @@ export function ContentSecurityPolicy() { httpEquiv="Content-Security-Policy" content="default-src 'self' https://assets.khoj.dev; media-src * blob:; - script-src 'self' https://assets.khoj.dev https://app.chatwoot.com 'unsafe-inline' 'unsafe-eval'; - connect-src 'self' blob: https://ipapi.co/json ws://localhost:42110; - style-src 'self' https://assets.khoj.dev 'unsafe-inline' https://fonts.googleapis.com; - img-src 'self' data: blob: https://*.khoj.dev https://*.googleusercontent.com https://*.google.com/ https://*.gstatic.com; + script-src 'self' https://assets.khoj.dev https://app.chatwoot.com https://accounts.google.com 'unsafe-inline' 'unsafe-eval'; + connect-src 'self' blob: https://ipapi.co/json ws://localhost:42110 https://accounts.google.com; + style-src 'self' https://assets.khoj.dev 'unsafe-inline' https://fonts.googleapis.com https://accounts.google.com; + img-src 'self' data: blob: https://*.khoj.dev https://accounts.google.com https://*.googleusercontent.com https://*.google.com/ https://*.gstatic.com; font-src 'self' https://assets.khoj.dev https://fonts.gstatic.com; + frame-src 'self' https://accounts.google.com; child-src 'self' https://app.chatwoot.com; object-src 'none';" > diff --git a/src/interface/web/app/components/loginPrompt/GoogleSignIn.tsx b/src/interface/web/app/components/loginPrompt/GoogleSignIn.tsx new file mode 100644 index 00000000..82909d8e --- /dev/null +++ b/src/interface/web/app/components/loginPrompt/GoogleSignIn.tsx @@ -0,0 +1,20 @@ +// GoogleSignIn.tsx +"use client"; + +import Script from "next/script"; + +interface GoogleSignInProps { + onLoad?: () => void; +} + +export function GoogleSignIn({ onLoad }: GoogleSignInProps) { + return ( + + ); +} diff --git a/src/interface/web/app/components/loginPrompt/loginPrompt.tsx b/src/interface/web/app/components/loginPrompt/loginPrompt.tsx index 3871f48a..ebf9707e 100644 --- a/src/interface/web/app/components/loginPrompt/loginPrompt.tsx +++ b/src/interface/web/app/components/loginPrompt/loginPrompt.tsx @@ -18,10 +18,23 @@ import { DialogTitle, } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; -import { ArrowLeft, GoogleCardboardLogo, GoogleLogo, Spinner } from "@phosphor-icons/react"; +import { + ArrowLeft, + ArrowsClockwise, + GoogleCardboardLogo, + GoogleLogo, + LineVertical, + PaperPlane, + PaperPlaneTilt, + PencilSimple, + Spinner, + CaretLeft, + CaretRight, +} from "@phosphor-icons/react"; import Link from "next/link"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import useSWR from "swr"; +import { GoogleSignIn } from "./GoogleSignIn"; export interface LoginPromptProps { loginRedirectMessage: string; @@ -46,6 +59,20 @@ export default function LoginPrompt(props: LoginPromptProps) { const [email, setEmail] = useState(""); const [checkEmail, setCheckEmail] = useState(false); + const [recheckEmail, setRecheckEmail] = useState(false); + + const [currentTip, setCurrentTip] = useState(0); + const [autoRotate, setAutoRotate] = useState(true); + + // Add these handler functions in your component + const nextSlide = () => { + setCurrentTip((prev) => (prev + 1) % tips.length); + setAutoRotate(false); + }; + const prevSlide = () => { + setCurrentTip((prev) => (prev - 1 + tips.length) % tips.length); + setAutoRotate(false); + }; const handleGoogleSignIn = () => { if (!data?.google?.client_id || !data?.google?.redirect_uri) return; @@ -67,6 +94,39 @@ export default function LoginPrompt(props: LoginPromptProps) { window.location.href = `https://accounts.google.com/o/oauth2/v2/auth?${params}`; }; + const handleGoogleScriptLoad = () => { + // Initialize Google Sign In after script loads + window.google.accounts.id.initialize({ + client_id: "blahblahblah.apps.googleusercontent.com", + callback: handleGoogleSignIn, + auto_select: false, + login_uri: "http://localhost:42110/auth/redirect", + }); + + // Render the button + window.google.accounts.id.renderButton(document.getElementById("g_id_signin")!, { + theme: "outline", + size: "large", + width: "100%", + }); + }; + + const tips = [ + { src: "/documents_tip.png", alt: "Documents tip" }, + { src: "/personalize_tip.png", alt: "Personalize tip" }, + { src: "/automate_tip.png", alt: "Automate tip" }, + ]; + + useEffect(() => { + if (!autoRotate) return; + + const timer = setInterval(() => { + setCurrentTip((prev) => (prev + 1) % tips.length); + }, 3000); // Rotate every 3 seconds + + return () => clearInterval(timer); + }, [autoRotate]); + function handleMagicLinkSignIn() { fetch("/auth/magic", { method: "POST", @@ -78,6 +138,9 @@ export default function LoginPrompt(props: LoginPromptProps) { .then((res) => { if (res.ok) { setCheckEmail(true); + if (checkEmail) { + setRecheckEmail(true); + } return res.json(); } else { throw new Error("Failed to send magic link"); @@ -93,72 +156,156 @@ export default function LoginPrompt(props: LoginPromptProps) { return ( - + - + {/* Sign in to Khoj to continue {props.loginRedirectMessage}. - + */} + {useEmailSignIn && ( { setUseEmailSignIn(false); }} > + + + {checkEmail ? "Check your email" : "Sign in with Email"} + + + + {checkEmail + ? recheckEmail + ? "A new link has been sent. Click on the link in your email to sign-in" + : "Click on the link in your email to sign-in" + : "You will receive a sign-in link on the email address you provide below"} + setEmail(e.target.value)} /> - {checkEmail ? "Check your email" : "Send magic link"} + + {checkEmail ? "Check your email" : "Send sign in link"} + {checkEmail && ( + + { + handleMagicLinkSignIn(); + }} + > + + Resend email + + + { + setEmail(""); + setCheckEmail(false); + }} + > + + Use a different email + + + )} )} {!useEmailSignIn && ( - - - {isLoading ? ( - - ) : ( - - )} - Continue with Google - + + + {tips.map((tip, index) => ( + + ))} + + + + + + + + + + Sign In for free to start using Khoj: Your AI-powered second + brain + + + + + {/* */} + + {isLoading ? ( + + ) : ( + + )} + Continue with Google + - { - setUseEmailSignIn(true); - }} - > - Continue with Email - + { + setUseEmailSignIn(true); + }} + > + + Continue with Email + + + + By logging in, you agree to our{" "} + + Terms of Service. + + )} - - By logging in, you agree to our{" "} - Terms of Service. - - - - diff --git a/src/interface/web/public/automate_tip.png b/src/interface/web/public/automate_tip.png new file mode 100644 index 00000000..c17c9638 Binary files /dev/null and b/src/interface/web/public/automate_tip.png differ diff --git a/src/interface/web/public/documents_tip.png b/src/interface/web/public/documents_tip.png new file mode 100644 index 00000000..464855bd Binary files /dev/null and b/src/interface/web/public/documents_tip.png differ diff --git a/src/interface/web/public/personalize_tip.png b/src/interface/web/public/personalize_tip.png new file mode 100644 index 00000000..e72b6f93 Binary files /dev/null and b/src/interface/web/public/personalize_tip.png differ