Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add search context to ask sourcebot context selector. [#397](https://github.com/sourcebot-dev/sourcebot/pull/397)
- Add ability to include/exclude connection in search context. [#399](https://github.com/sourcebot-dev/sourcebot/pull/399)
- Search context refactor to search scope and demo card UI changes. [#405](https://github.com/sourcebot-dev/sourcebot/pull/405)
- Add GitHub star toast. [#409](https://github.com/sourcebot-dev/sourcebot/pull/409)

### Fixed
- Fixed multiple writes race condition on config file watcher. [#398](https://github.com/sourcebot-dev/sourcebot/pull/398)
Expand Down
84 changes: 84 additions & 0 deletions packages/web/src/app/[domain]/components/githubStarToast.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
'use client';

import { useToast } from "@/components/hooks/use-toast";
import { ToastAction } from "@/components/ui/toast";
import { useEffect } from "react";
import { GitHubLogoIcon } from "@radix-ui/react-icons";
import { captureEvent } from "@/hooks/useCaptureEvent";

const POPUP_SHOWN_COOKIE = "github_popup_shown";
const POPUP_START_TIME_COOKIE = "github_popup_start_time";
const POPUP_DELAY_S = 60;
const SOURCEBOT_GITHUB_URL = "https://github.com/sourcebot-dev/sourcebot";

function getCookie(name: string): string | null {
if (typeof document === "undefined") return null;

const cookies = document.cookie.split(';').map(cookie => cookie.trim());
const targetCookie = cookies.find(cookie => cookie.startsWith(`${name}=`));

if (!targetCookie) return null;

return targetCookie.substring(`${name}=`.length);
}

function setCookie(name: string, value: string, days: number = 365) {
if (typeof document === "undefined") return;

try {
const expires = new Date();
expires.setTime(expires.getTime() + (days * 24 * 60 * 60 * 1000));
document.cookie = `${name}=${value}; expires=${expires.toUTCString()}; path=/; SameSite=Lax`;
} catch (error) {
console.warn('Failed to set GitHub popup cookie:', error);
}
}

export const GitHubStarToast = () => {
const { toast } = useToast();

useEffect(() => {
const hasShownPopup = getCookie(POPUP_SHOWN_COOKIE);
const startTime = getCookie(POPUP_START_TIME_COOKIE);

if (hasShownPopup) {
return;
}

const currentTime = Date.now();
if (!startTime) {
setCookie(POPUP_START_TIME_COOKIE, currentTime.toString());
return;
}

const elapsed = currentTime - parseInt(startTime, 10);
if (elapsed >= (POPUP_DELAY_S * 1000)) {
toast({
title: "Star us on GitHub ❤️",
description: "If you've found Sourcebot useful, please consider starring us on GitHub. Your support means a lot!",
duration: 15 * 1000,
action: (
<div className="flex flex-col gap-1">
<ToastAction
altText="GitHub Button"
onClick={() => {
captureEvent('wa_github_star_toast_clicked', {});
window.open(SOURCEBOT_GITHUB_URL, "_blank");
}}
>
<div className="flex items-center gap-2">
<GitHubLogoIcon className="w-4 h-4" />
Sourcebot
</div>
</ToastAction>
</div>
)
});

captureEvent('wa_github_star_toast_displayed', {});
setCookie(POPUP_SHOWN_COOKIE, "true");
}
}, [toast]);

return null;
}
2 changes: 2 additions & 0 deletions packages/web/src/app/[domain]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { GcpIapAuth } from "./components/gcpIapAuth";
import { getAnonymousAccessStatus, getMemberApprovalRequired } from "@/actions";
import { JoinOrganizationCard } from "@/app/components/joinOrganizationCard";
import { LogoutEscapeHatch } from "@/app/components/logoutEscapeHatch";
import { GitHubStarToast } from "./components/githubStarToast";

interface LayoutProps {
children: React.ReactNode,
Expand Down Expand Up @@ -134,6 +135,7 @@ export default async function Layout({
<SyntaxGuideProvider>
{children}
<SyntaxReferenceGuide />
<GitHubStarToast />
</SyntaxGuideProvider>
)
}
3 changes: 3 additions & 0 deletions packages/web/src/lib/posthogEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,5 +293,8 @@ export type PosthogEventMap = {
exampleTitle: string,
exampleUrl: string,
},
//////////////////////////////////////////////////////////////////
wa_github_star_toast_displayed: {},
wa_github_star_toast_clicked: {},
}
export type PosthogEvent = keyof PosthogEventMap;