Skip to content

Commit 1df8390

Browse files
authored
feat(web): auth-gate code search submit on Ask GH (#1680)
1 parent 72aa634 commit 1df8390

10 files changed

Lines changed: 67 additions & 6 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
- Added login wall for code search for Ask GitHub. [#1680](https://github.com/sourcebot-dev/sourcebot/pull/1680)
12+
1013
### Removed
1114
- Removed the Ask Sourcebot first-visit tutorial banner. [#1675](https://github.com/sourcebot-dev/sourcebot/pull/1675)
1215
- Removed suggested example queries from the Ask landing page. [#1674](https://github.com/sourcebot-dev/sourcebot/pull/1674)

‎packages/web/src/app/(app)/browse/layout.tsx‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { LayoutClient } from "./layoutClient";
22
import { getConfiguredLanguageModelsInfo } from "@/features/chat/utils.server";
3+
import { auth } from "@/auth";
4+
import { env } from "@sourcebot/shared";
35

46
interface LayoutProps {
57
children: React.ReactNode;
@@ -8,9 +10,15 @@ interface LayoutProps {
810
export default async function Layout({
911
children,
1012
}: LayoutProps) {
11-
const languageModels = await getConfiguredLanguageModelsInfo();
13+
const [languageModels, session] = await Promise.all([
14+
getConfiguredLanguageModelsInfo(),
15+
auth(),
16+
]);
1217
return (
13-
<LayoutClient isSearchAssistSupported={languageModels.length > 0}>
18+
<LayoutClient
19+
isSearchAssistSupported={languageModels.length > 0}
20+
showLoginWall={env.EXPERIMENT_ASK_GH_ENABLED === "true" && !session?.user}
21+
>
1422
{children}
1523
</LayoutClient>
1624
)

‎packages/web/src/app/(app)/browse/layoutClient.tsx‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@ import { Separator } from "@/components/ui/separator";
1414
interface LayoutProps {
1515
children: React.ReactNode;
1616
isSearchAssistSupported: boolean;
17+
showLoginWall: boolean;
1718
}
1819

1920
export function LayoutClient({
2021
children,
2122
isSearchAssistSupported,
23+
showLoginWall,
2224
}: LayoutProps) {
2325
const { repoName, revisionName, pathType } = useBrowseParams();
2426
return (
@@ -33,6 +35,7 @@ export function LayoutClient({
3335
}}
3436
className="w-full"
3537
isSearchAssistSupported={isSearchAssistSupported}
38+
showLoginWall={showLoginWall}
3639
/>
3740
</div>
3841
<Separator />

‎packages/web/src/app/(app)/components/searchBar/searchBar.tsx‎

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import Link from "next/link";
4747
import { CaseSensitiveIcon, RegexIcon, Wand2Icon } from "lucide-react";
4848
import { SearchAssistBox } from "./searchAssistBox";
4949
import useCaptureEvent from "@/hooks/useCaptureEvent";
50+
import { LoginDialog } from "@/app/components/loginDialog";
5051

5152
const LANGUAGE_MODEL_DOCS_URL = "https://docs.sourcebot.dev/docs/configuration/language-model-providers";
5253

@@ -60,6 +61,7 @@ interface SearchBarProps {
6061
}
6162
autoFocus?: boolean;
6263
isSearchAssistSupported: boolean;
64+
showLoginWall: boolean;
6365
}
6466

6567
const searchBarKeymap: readonly KeyBinding[] = ([
@@ -107,6 +109,7 @@ export const SearchBar = ({
107109
query: defaultQuery = "",
108110
} = {},
109111
isSearchAssistSupported,
112+
showLoginWall,
110113
}: SearchBarProps) => {
111114
const router = useRouter();
112115
const captureEvent = useCaptureEvent();
@@ -120,6 +123,7 @@ export const SearchBar = ({
120123
const [isHistorySearchEnabled, setIsHistorySearchEnabled] = useState(false);
121124
const [isRegexEnabled, setIsRegexEnabled] = useState(defaultIsRegexEnabled);
122125
const [isCaseSensitivityEnabled, setIsCaseSensitivityEnabled] = useState(defaultIsCaseSensitivityEnabled);
126+
const [loginCallbackUrl, setLoginCallbackUrl] = useState<string>();
123127

124128
const focusEditor = useCallback(() => editorRef.current?.view?.focus(), []);
125129
const focusSuggestionsBox = useCallback(() => suggestionBoxRef.current?.focus(), []);
@@ -230,8 +234,24 @@ export const SearchBar = ({
230234
[SearchQueryParams.isRegexEnabled, isRegexEnabled ? "true" : null],
231235
[SearchQueryParams.isCaseSensitivityEnabled, isCaseSensitivityEnabled ? "true" : null],
232236
);
237+
238+
if (showLoginWall) {
239+
if (query.trim().length === 0) {
240+
return;
241+
}
242+
captureEvent('wa_publicsaas_cs_login_wall_prompted', {});
243+
setLoginCallbackUrl(url);
244+
return;
245+
}
246+
233247
router.push(url);
234-
}, [router, isRegexEnabled, isCaseSensitivityEnabled]);
248+
}, [
249+
captureEvent,
250+
isCaseSensitivityEnabled,
251+
isRegexEnabled,
252+
router,
253+
showLoginWall,
254+
]);
235255

236256
return (
237257
<div
@@ -401,6 +421,15 @@ export const SearchBar = ({
401421
cursorPosition={cursorPosition}
402422
{...suggestionData}
403423
/>
424+
<LoginDialog
425+
isOpen={loginCallbackUrl !== undefined}
426+
onOpenChange={(open) => {
427+
if (!open) {
428+
setLoginCallbackUrl(undefined);
429+
}
430+
}}
431+
callbackUrl={loginCallbackUrl}
432+
/>
404433
</div>
405434
)
406435
}

‎packages/web/src/app/(app)/search/components/searchLandingPage.tsx‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ import { isServiceError } from "@/lib/utils"
1010

1111
export interface SearchLandingPageProps {
1212
isSearchAssistSupported: boolean;
13+
showLoginWall: boolean;
1314
}
1415

1516
export const SearchLandingPage = async ({
1617
isSearchAssistSupported,
18+
showLoginWall,
1719
}: SearchLandingPageProps) => {
1820
const carouselRepos = await getRepos({
1921
where: {
@@ -39,6 +41,7 @@ export const SearchLandingPage = async ({
3941
autoFocus={true}
4042
className="border-none pt-0.5 pb-0"
4143
isSearchAssistSupported={isSearchAssistSupported}
44+
showLoginWall={showLoginWall}
4245
/>
4346
<Separator />
4447
<div className="w-full flex flex-row items-center bg-accent rounded-b-md px-2">

‎packages/web/src/app/(app)/search/components/searchResultsPage.tsx‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ interface SearchResultsPageProps {
3939
isRegexEnabled: boolean;
4040
isCaseSensitivityEnabled: boolean;
4141
isSearchAssistSupported: boolean;
42+
showLoginWall: boolean;
4243
}
4344

4445
export const SearchResultsPage = ({
@@ -47,6 +48,7 @@ export const SearchResultsPage = ({
4748
isRegexEnabled,
4849
isCaseSensitivityEnabled,
4950
isSearchAssistSupported,
51+
showLoginWall,
5052
}: SearchResultsPageProps) => {
5153
const router = useRouter();
5254
const { setSearchHistory } = useSearchHistory();
@@ -179,6 +181,7 @@ export const SearchResultsPage = ({
179181
}}
180182
className="w-full"
181183
isSearchAssistSupported={isSearchAssistSupported}
184+
showLoginWall={showLoginWall}
182185
/>
183186
</div>
184187
<Separator />

‎packages/web/src/app/(app)/search/page.tsx‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { env } from "@sourcebot/shared";
2+
import { auth } from "@/auth";
23
import { SearchLandingPage } from "./components/searchLandingPage";
34
import { SearchResultsPage } from "./components/searchResultsPage";
45
import { getConfiguredLanguageModelsInfo } from "@/features/chat/utils.server";
@@ -16,12 +17,19 @@ export default async function SearchPage(props: SearchPageProps) {
1617
const query = searchParams?.query;
1718
const isRegexEnabled = searchParams?.isRegexEnabled === "true";
1819
const isCaseSensitivityEnabled = searchParams?.isCaseSensitivityEnabled === "true";
20+
const session = await auth();
21+
const showLoginWall = env.EXPERIMENT_ASK_GH_ENABLED === "true" && !session?.user;
1922

2023
const languageModels = await getConfiguredLanguageModelsInfo();
2124
const isSearchAssistSupported = languageModels.length > 0;
2225

2326
if (query === undefined || query.length === 0) {
24-
return <SearchLandingPage isSearchAssistSupported={isSearchAssistSupported} />
27+
return (
28+
<SearchLandingPage
29+
isSearchAssistSupported={isSearchAssistSupported}
30+
showLoginWall={showLoginWall}
31+
/>
32+
)
2533
}
2634

2735
return (
@@ -31,6 +39,7 @@ export default async function SearchPage(props: SearchPageProps) {
3139
isRegexEnabled={isRegexEnabled}
3240
isCaseSensitivityEnabled={isCaseSensitivityEnabled}
3341
isSearchAssistSupported={isSearchAssistSupported}
42+
showLoginWall={showLoginWall}
3443
/>
3544
)
3645
}

packages/web/src/features/chat/components/chatBox/loginDialog.tsx renamed to packages/web/src/app/components/loginDialog.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@ import { usePathname } from "next/navigation";
1313
interface LoginDialogProps {
1414
isOpen: boolean;
1515
onOpenChange: (open: boolean) => void;
16+
callbackUrl?: string;
1617
}
1718

1819
export const LoginDialog = ({
1920
isOpen,
2021
onOpenChange,
22+
callbackUrl,
2123
}: LoginDialogProps) => {
2224
const pathname = usePathname();
2325

@@ -33,7 +35,7 @@ export const LoginDialog = ({
3335
<div className="mt-4">
3436
<AuthMethodSelector
3537
context="login"
36-
callbackUrl={pathname}
38+
callbackUrl={callbackUrl ?? pathname}
3739
hideSecurityNotice={true}
3840
/>
3941
</div>

‎packages/web/src/features/chat/components/chatBox/chatBox.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { useSuggestionsData } from "./useSuggestionsData";
2424
import { useToast } from "@/components/hooks/use-toast";
2525
import { SearchContextQuery } from "@/lib/types";
2626
import isEqual from "fast-deep-equal/react";
27-
import { LoginDialog } from "./loginDialog";
27+
import { LoginDialog } from "@/app/components/loginDialog";
2828
import { usePathname } from "next/navigation";
2929
import { ATTACHMENT_MAX_IMAGE_BYTES, ATTACHMENT_MAX_TURN_TEXT_BYTES, PENDING_CHAT_SUBMISSION_SESSION_STORAGE_KEY } from "@/features/chat/constants";
3030
import useCaptureEvent from "@/hooks/useCaptureEvent";

‎packages/web/src/lib/posthogEvents.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,7 @@ export type PosthogEventMap = {
537537
},
538538
//////////////////////////////////////////////////////////////////
539539
wa_askgh_login_wall_prompted: {},
540+
wa_publicsaas_cs_login_wall_prompted: {},
540541
//////////////////////////////////////////////////////////////////
541542
askgh_repo_index_requested: {
542543
owner: string,

0 commit comments

Comments
 (0)