diff --git a/CHANGELOG.md b/CHANGELOG.md index 89540918..33963c52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/packages/web/src/app/[domain]/components/githubStarToast.tsx b/packages/web/src/app/[domain]/components/githubStarToast.tsx new file mode 100644 index 00000000..2e482ff1 --- /dev/null +++ b/packages/web/src/app/[domain]/components/githubStarToast.tsx @@ -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: ( +