From 7f3c7f47f26aebaee2c5d707f48bdd568970b9d0 Mon Sep 17 00:00:00 2001 From: Nishant-k-sagar <147799872+Nishant-k-sagar@users.noreply.github.com> Date: Tue, 24 Mar 2026 21:35:37 +0000 Subject: [PATCH 1/9] feat: add placeholder text to login and register inputs --- surfsense_web/app/(home)/login/LocalLoginForm.tsx | 2 ++ surfsense_web/app/(home)/register/page.tsx | 3 +++ 2 files changed, 5 insertions(+) diff --git a/surfsense_web/app/(home)/login/LocalLoginForm.tsx b/surfsense_web/app/(home)/login/LocalLoginForm.tsx index cb3ee73a1..f8dad43c4 100644 --- a/surfsense_web/app/(home)/login/LocalLoginForm.tsx +++ b/surfsense_web/app/(home)/login/LocalLoginForm.tsx @@ -166,6 +166,7 @@ export function LocalLoginForm() { id="email" type="email" required + placeholder="you@example.com" value={username} onChange={(e) => setUsername(e.target.value)} className={`mt-1 block w-full rounded-md border px-3 py-1.5 md:py-2 shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 dark:bg-gray-800 dark:text-white transition-all ${ @@ -189,6 +190,7 @@ export function LocalLoginForm() { id="password" type={showPassword ? "text" : "password"} required + placeholder="Enter your password" value={password} onChange={(e) => setPassword(e.target.value)} className={`mt-1 block w-full rounded-md border pr-10 px-3 py-1.5 md:py-2 shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 dark:bg-gray-800 dark:text-white transition-all ${ diff --git a/surfsense_web/app/(home)/register/page.tsx b/surfsense_web/app/(home)/register/page.tsx index 60c3ba1be..bfde70d24 100644 --- a/surfsense_web/app/(home)/register/page.tsx +++ b/surfsense_web/app/(home)/register/page.tsx @@ -231,6 +231,7 @@ export default function RegisterPage() { id="email" type="email" required + placeholder="you@example.com" value={email} onChange={(e) => setEmail(e.target.value)} className={`mt-1 block w-full rounded-md border px-3 py-1.5 md:py-2 shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 dark:bg-gray-800 dark:text-white transition-all ${ @@ -253,6 +254,7 @@ export default function RegisterPage() { id="password" type="password" required + placeholder="Enter your password" value={password} onChange={(e) => setPassword(e.target.value)} className={`mt-1 block w-full rounded-md border px-3 py-1.5 md:py-2 shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 dark:bg-gray-800 dark:text-white transition-all ${ @@ -275,6 +277,7 @@ export default function RegisterPage() { id="confirmPassword" type="password" required + placeholder="Confirm your password" value={confirmPassword} onChange={(e) => setConfirmPassword(e.target.value)} className={`mt-1 block w-full rounded-md border px-3 py-1.5 md:py-2 shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 dark:bg-gray-800 dark:text-white transition-all ${ From 6f64a2de9bbe260d2cdd212b67372af439eb0642 Mon Sep 17 00:00:00 2001 From: Nishant-k-sagar <147799872+Nishant-k-sagar@users.noreply.github.com> Date: Tue, 24 Mar 2026 22:38:21 +0000 Subject: [PATCH 2/9] perf: replace img with Next.js Image for avatars --- surfsense_web/components/assistant-ui/user-message.tsx | 5 ++++- surfsense_web/components/public-chat/public-thread.tsx | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/surfsense_web/components/assistant-ui/user-message.tsx b/surfsense_web/components/assistant-ui/user-message.tsx index 1c0525277..7f4bc0eb7 100644 --- a/surfsense_web/components/assistant-ui/user-message.tsx +++ b/surfsense_web/components/assistant-ui/user-message.tsx @@ -1,6 +1,7 @@ import { ActionBarPrimitive, MessagePrimitive, useAssistantState } from "@assistant-ui/react"; import { useAtomValue } from "jotai"; import { FileText, Pen } from "lucide-react"; +import Image from "next/image"; import { type FC, useState } from "react"; import { messageDocumentsMapAtom } from "@/atoms/chat/mentioned-documents.atom"; import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button"; @@ -24,9 +25,11 @@ const UserAvatar: FC = ({ displayName, avatarUrl }) => { if (avatarUrl && !hasError) { return ( - {displayName setHasError(true)} diff --git a/surfsense_web/components/public-chat/public-thread.tsx b/surfsense_web/components/public-chat/public-thread.tsx index e88e5aae7..b0c0582e7 100644 --- a/surfsense_web/components/public-chat/public-thread.tsx +++ b/surfsense_web/components/public-chat/public-thread.tsx @@ -8,6 +8,7 @@ import { useAssistantState, } from "@assistant-ui/react"; import { CheckIcon, CopyIcon } from "lucide-react"; +import Image from "next/image"; import { type FC, type ReactNode, useState } from "react"; import { MarkdownText } from "@/components/assistant-ui/markdown-text"; import { ToolFallback } from "@/components/assistant-ui/tool-fallback"; @@ -75,9 +76,11 @@ const UserAvatar: FC void } if (avatarUrl && !hasError) { return ( - {displayName Date: Wed, 25 Mar 2026 10:31:35 +0800 Subject: [PATCH 3/9] fix: add missing clearTimeout cleanup in CopyButton useEffect Closes #934 --- surfsense_web/components/ui/code-block-node.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/surfsense_web/components/ui/code-block-node.tsx b/surfsense_web/components/ui/code-block-node.tsx index 23cc163a1..d323fc894 100644 --- a/surfsense_web/components/ui/code-block-node.tsx +++ b/surfsense_web/components/ui/code-block-node.tsx @@ -143,9 +143,11 @@ function CopyButton({ const [hasCopied, setHasCopied] = React.useState(false); React.useEffect(() => { - setTimeout(() => { + if (!hasCopied) return; + const timer = setTimeout(() => { setHasCopied(false); }, 2000); + return () => clearTimeout(timer); }, [hasCopied]); return ( From 8d8c36fc5972fc6173ac9e6357c14eab84a65bfc Mon Sep 17 00:00:00 2001 From: likiosliu Date: Wed, 25 Mar 2026 10:32:11 +0800 Subject: [PATCH 4/9] fix: use stable references for event listeners in Spotlight component Anonymous arrow functions create different references on add/remove, so the listeners were never actually removed. Closes #933 --- surfsense_web/components/ui/spotlight.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/surfsense_web/components/ui/spotlight.tsx b/surfsense_web/components/ui/spotlight.tsx index 2258e8814..3047559e1 100644 --- a/surfsense_web/components/ui/spotlight.tsx +++ b/surfsense_web/components/ui/spotlight.tsx @@ -48,14 +48,17 @@ export function Spotlight({ useEffect(() => { if (!parentElement) return; + const handleEnter = () => setIsHovered(true); + const handleLeave = () => setIsHovered(false); + parentElement.addEventListener("mousemove", handleMouseMove); - parentElement.addEventListener("mouseenter", () => setIsHovered(true)); - parentElement.addEventListener("mouseleave", () => setIsHovered(false)); + parentElement.addEventListener("mouseenter", handleEnter); + parentElement.addEventListener("mouseleave", handleLeave); return () => { parentElement.removeEventListener("mousemove", handleMouseMove); - parentElement.removeEventListener("mouseenter", () => setIsHovered(true)); - parentElement.removeEventListener("mouseleave", () => setIsHovered(false)); + parentElement.removeEventListener("mouseenter", handleEnter); + parentElement.removeEventListener("mouseleave", handleLeave); }; }, [parentElement, handleMouseMove]); From cbb93518b6bb2b926ea84741e60038a139310963 Mon Sep 17 00:00:00 2001 From: likiosliu Date: Wed, 25 Mar 2026 10:32:53 +0800 Subject: [PATCH 5/9] fix: remove unused useRouter and useParams in SidebarHeader Closes #944 --- surfsense_web/components/layout/ui/sidebar/SidebarHeader.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/surfsense_web/components/layout/ui/sidebar/SidebarHeader.tsx b/surfsense_web/components/layout/ui/sidebar/SidebarHeader.tsx index 9d6642623..2c8539dc8 100644 --- a/surfsense_web/components/layout/ui/sidebar/SidebarHeader.tsx +++ b/surfsense_web/components/layout/ui/sidebar/SidebarHeader.tsx @@ -1,7 +1,6 @@ "use client"; import { ChevronsUpDown, Settings, UserPen } from "lucide-react"; -import { useParams, useRouter } from "next/navigation"; import { useTranslations } from "next-intl"; import { Button } from "@/components/ui/button"; import { @@ -29,9 +28,6 @@ export function SidebarHeader({ className, }: SidebarHeaderProps) { const t = useTranslations("sidebar"); - const router = useRouter(); - const params = useParams(); - const searchSpaceId = params.search_space_id as string; return (
From 16ffdd898a706e0fdb1a69b52ad40e53aa305556 Mon Sep 17 00:00:00 2001 From: likiosliu Date: Wed, 25 Mar 2026 10:40:06 +0800 Subject: [PATCH 6/9] fix: add missing setTimeout cleanup in hero section collision effect Closes #940 --- .../components/homepage/hero-section.tsx | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/surfsense_web/components/homepage/hero-section.tsx b/surfsense_web/components/homepage/hero-section.tsx index 830f9febf..3e7bccccb 100644 --- a/surfsense_web/components/homepage/hero-section.tsx +++ b/surfsense_web/components/homepage/hero-section.tsx @@ -277,21 +277,24 @@ const CollisionMechanism = ({ }, [cycleCollisionDetected, parentRef]); useEffect(() => { - if (collision.detected && collision.coordinates) { - setTimeout(() => { - setCollision({ detected: false, coordinates: null }); - setCycleCollisionDetected(false); - // Set beam opacity to 0 - if (beamRef.current) { - beamRef.current.style.opacity = "1"; - } - }, 2000); + if (!collision.detected || !collision.coordinates) return; - // Reset the beam animation after a delay - setTimeout(() => { - setBeamKey((prevKey) => prevKey + 1); - }, 2000); - } + const timer1 = setTimeout(() => { + setCollision({ detected: false, coordinates: null }); + setCycleCollisionDetected(false); + if (beamRef.current) { + beamRef.current.style.opacity = "1"; + } + }, 2000); + + const timer2 = setTimeout(() => { + setBeamKey((prevKey) => prevKey + 1); + }, 2000); + + return () => { + clearTimeout(timer1); + clearTimeout(timer2); + }; }, [collision]); return ( From 1967c14a8ed9ad459330f7df82326f73ebf22f28 Mon Sep 17 00:00:00 2001 From: likiosliu Date: Wed, 25 Mar 2026 10:40:35 +0800 Subject: [PATCH 7/9] fix: add rel="noopener noreferrer" to target="_blank" link in link-toolbar Closes #938 --- surfsense_web/components/ui/link-toolbar.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/surfsense_web/components/ui/link-toolbar.tsx b/surfsense_web/components/ui/link-toolbar.tsx index 4f5988ded..f44b5a1d1 100644 --- a/surfsense_web/components/ui/link-toolbar.tsx +++ b/surfsense_web/components/ui/link-toolbar.tsx @@ -187,6 +187,7 @@ function LinkOpenButton() { }} aria-label="Open link in a new tab" target="_blank" + rel="noopener noreferrer" > From 967f9762c3ac61cf9f7f5a58be8acc793c0bfb17 Mon Sep 17 00:00:00 2001 From: likiosliu Date: Wed, 25 Mar 2026 10:41:56 +0800 Subject: [PATCH 8/9] fix: replace key={index} with stable keys in pricing component Use plan.name and feature text as keys instead of array indices. Closes #942 --- surfsense_web/components/pricing.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/surfsense_web/components/pricing.tsx b/surfsense_web/components/pricing.tsx index 0023a3eaf..731c3654c 100644 --- a/surfsense_web/components/pricing.tsx +++ b/surfsense_web/components/pricing.tsx @@ -101,9 +101,9 @@ export function Pricing({ plans.length === 2 ? "md:grid-cols-2 max-w-5xl mx-auto" : "md:grid-cols-3" )} > - {plans.map((plan, index) => ( + {plans.map((plan) => (
    - {plan.features.map((feature, idx) => ( -
  • + {plan.features.map((feature) => ( +
  • {feature}
  • From e3f5b7923abcc6b2792ed5bc2323850cb60a709f Mon Sep 17 00:00:00 2001 From: "DESKTOP-RTLN3BA\\$punk" Date: Tue, 24 Mar 2026 20:44:14 -0700 Subject: [PATCH 9/9] Add index parameter to plans.map callback in Pricing component Made-with: Cursor --- surfsense_web/components/pricing.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/surfsense_web/components/pricing.tsx b/surfsense_web/components/pricing.tsx index 731c3654c..9a8e29c32 100644 --- a/surfsense_web/components/pricing.tsx +++ b/surfsense_web/components/pricing.tsx @@ -101,7 +101,7 @@ export function Pricing({ plans.length === 2 ? "md:grid-cols-2 max-w-5xl mx-auto" : "md:grid-cols-3" )} > - {plans.map((plan) => ( + {plans.map((plan, index) => (