Skip to content

Commit 1109969

Browse files
fix: Move search mode selection into a cookie to avoid SSR flashes
1 parent eb04422 commit 1109969

File tree

6 files changed

+37
-9
lines changed

6 files changed

+37
-9
lines changed

packages/web/src/actions.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import { auth } from "./auth";
2525
import { getConnection } from "./data/connection";
2626
import { IS_BILLING_ENABLED } from "./ee/features/billing/stripe";
2727
import InviteUserEmail from "./emails/inviteUserEmail";
28-
import { MOBILE_UNSUPPORTED_SPLASH_SCREEN_DISMISSED_COOKIE_NAME, SINGLE_TENANT_ORG_DOMAIN, SOURCEBOT_GUEST_USER_ID, SOURCEBOT_SUPPORT_EMAIL } from "./lib/constants";
28+
import { MOBILE_UNSUPPORTED_SPLASH_SCREEN_DISMISSED_COOKIE_NAME, SEARCH_MODE_COOKIE_NAME, SINGLE_TENANT_ORG_DOMAIN, SOURCEBOT_GUEST_USER_ID, SOURCEBOT_SUPPORT_EMAIL } from "./lib/constants";
2929
import { orgDomainSchema, orgNameSchema, repositoryQuerySchema } from "./lib/schemas";
3030
import { TenancyMode, ApiKeyPayload } from "./lib/types";
3131
import { decrementOrgSeatCount, getSubscriptionForOrg } from "./ee/features/billing/serverUtils";
@@ -1998,6 +1998,13 @@ export const setAnonymousAccessStatus = async (domain: string, enabled: boolean)
19981998
});
19991999
});
20002000

2001+
export async function setSearchModeCookie(searchMode: "precise" | "agentic") {
2002+
const cookieStore = await cookies();
2003+
cookieStore.set(SEARCH_MODE_COOKIE_NAME, searchMode, {
2004+
httpOnly: false, // Allow client-side access
2005+
});
2006+
}
2007+
20012008
////// Helpers ///////
20022009

20032010
const parseConnectionConfig = (config: string) => {

packages/web/src/app/[domain]/chat/components/newChatPanel.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export const NewChatPanel = ({
2222
repos,
2323
order,
2424
}: NewChatPanelProps) => {
25-
const [selectedRepos, setSelectedRepos] = useLocalStorage<string[]>("selectedRepos", []);
25+
const [selectedRepos, setSelectedRepos] = useLocalStorage<string[]>("selectedRepos", [], { initializeWithValue: false });
2626
const { createNewChatThread, isLoading } = useCreateNewChatThread();
2727
const [isRepoSelectorOpen, setIsRepoSelectorOpen] = useState(false);
2828

packages/web/src/app/[domain]/components/homepage/agenticSearch.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ export const AgenticSearch = ({
126126
const { createNewChatThread, isLoading } = useCreateNewChatThread();
127127
const dropdownRef = useRef<HTMLDivElement>(null);
128128
const editor = useSlate();
129-
const [selectedRepos, setSelectedRepos] = useLocalStorage<string[]>("selectedRepos", []);
129+
const [selectedRepos, setSelectedRepos] = useLocalStorage<string[]>("selectedRepos", [], { initializeWithValue: false });
130130
const domain = useDomain();
131131
const [isRepoSelectorOpen, setIsRepoSelectorOpen] = useState(false);
132132

packages/web/src/app/[domain]/components/homepage/index.tsx

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ import { SourcebotLogo } from "@/app/components/sourcebotLogo";
44
import { LanguageModelInfo } from "@/features/chat/types";
55
import { RepositoryQuery } from "@/lib/types";
66
import { useHotkeys } from "react-hotkeys-hook";
7-
import { useLocalStorage } from "usehooks-ts";
87
import { AgenticSearch } from "./agenticSearch";
98
import { PreciseSearch } from "./preciseSearch";
109
import { SearchMode } from "./toolbar";
1110
import { CustomSlateEditor } from "@/features/chat/customSlateEditor";
11+
import { setSearchModeCookie } from "@/actions";
12+
import { useCallback, useState } from "react";
1213

1314
interface HomepageProps {
1415
initialRepos: RepositoryQuery[];
@@ -18,20 +19,27 @@ interface HomepageProps {
1819
createdAt: Date;
1920
name: string | null;
2021
}[];
22+
initialSearchMode: SearchMode;
2123
}
2224

2325

2426
export const Homepage = ({
2527
initialRepos,
2628
languageModels,
2729
chatHistory,
30+
initialSearchMode,
2831
}: HomepageProps) => {
29-
const [searchMode, setSearchMode] = useLocalStorage<SearchMode>("search-mode", "precise", { initializeWithValue: false });
32+
const [searchMode, setSearchMode] = useState<SearchMode>(initialSearchMode);
3033
const isAgenticSearchEnabled = languageModels.length > 0;
3134

35+
const onSearchModeChanged = useCallback(async (newMode: SearchMode) => {
36+
setSearchMode(newMode);
37+
await setSearchModeCookie(newMode);
38+
}, [setSearchMode]);
39+
3240
useHotkeys("mod+i", (e) => {
3341
e.preventDefault();
34-
setSearchMode("agentic");
42+
onSearchModeChanged("agentic");
3543
}, {
3644
enableOnFormTags: true,
3745
enableOnContentEditable: true,
@@ -40,7 +48,7 @@ export const Homepage = ({
4048

4149
useHotkeys("mod+p", (e) => {
4250
e.preventDefault();
43-
setSearchMode("precise");
51+
onSearchModeChanged("precise");
4452
}, {
4553
enableOnFormTags: true,
4654
enableOnContentEditable: true,
@@ -61,7 +69,7 @@ export const Homepage = ({
6169
searchModeSelectorProps={{
6270
searchMode: "precise",
6371
isAgenticSearchEnabled,
64-
onSearchModeChange: setSearchMode,
72+
onSearchModeChange: onSearchModeChanged,
6573
}}
6674
/>
6775
) : (
@@ -70,7 +78,7 @@ export const Homepage = ({
7078
searchModeSelectorProps={{
7179
searchMode: "agentic",
7280
isAgenticSearchEnabled,
73-
onSearchModeChange: setSearchMode,
81+
onSearchModeChange: onSearchModeChanged,
7482
}}
7583
languageModels={languageModels}
7684
repos={initialRepos}

packages/web/src/app/[domain]/page.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import { PageNotFound } from "./components/pageNotFound";
99
import { UpgradeToast } from "./components/upgradeToast";
1010
import { ServiceErrorException } from "@/lib/serviceError";
1111
import { auth } from "@/auth";
12+
import { cookies } from "next/headers";
13+
import { SEARCH_MODE_COOKIE_NAME } from "@/lib/constants";
1214

1315
export default async function Home({ params: { domain } }: { params: { domain: string } }) {
1416
const org = await getOrgFromDomain(domain);
@@ -32,6 +34,15 @@ export default async function Home({ params: { domain } }: { params: { domain: s
3234

3335
const indexedRepos = repos.filter((repo) => repo.indexedAt !== undefined);
3436

37+
// Read search mode from cookie, defaulting to agentic if not set
38+
// (assuming a language model is configured).
39+
const cookieStore = await cookies();
40+
const searchModeCookie = cookieStore.get(SEARCH_MODE_COOKIE_NAME);
41+
const initialSearchMode = (
42+
searchModeCookie?.value === "agentic" ||
43+
searchModeCookie?.value === "precise"
44+
) ? searchModeCookie.value : models.length > 0 ? "agentic" : "precise";
45+
3546
return (
3647
<div className="flex flex-col items-center overflow-hidden min-h-screen">
3748
<NavigationMenu
@@ -43,6 +54,7 @@ export default async function Home({ params: { domain } }: { params: { domain: s
4354
initialRepos={indexedRepos}
4455
languageModels={models}
4556
chatHistory={chatHistory}
57+
initialSearchMode={initialSearchMode}
4658
/>
4759
<Footer />
4860
</div>

packages/web/src/lib/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export const TEAM_FEATURES = [
2323
]
2424

2525
export const MOBILE_UNSUPPORTED_SPLASH_SCREEN_DISMISSED_COOKIE_NAME = 'sb.mobile-unsupported-splash-screen-dismissed';
26+
export const SEARCH_MODE_COOKIE_NAME = 'sb.search-mode';
2627

2728
// NOTE: changing SOURCEBOT_GUEST_USER_ID may break backwards compatibility since this value is used
2829
// to detect old guest users in the DB. If you change this value ensure it doesn't break upgrade flows

0 commit comments

Comments
 (0)