diff --git a/packages/app/src/components/github-star-modal.tsx b/packages/app/src/components/github-star-modal.tsx new file mode 100644 index 0000000..36c985a --- /dev/null +++ b/packages/app/src/components/github-star-modal.tsx @@ -0,0 +1,126 @@ +'use client'; + +import { track } from '@/lib/analytics'; +import { Star } from 'lucide-react'; +import { useCallback, useEffect, useState } from 'react'; + +import { GITHUB_OWNER, GITHUB_REPO } from '@semianalysisai/inferencex-constants'; +import { Button } from '@/components/ui/button'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; + +const GITHUB_REPO_URL = `https://github.com/${GITHUB_OWNER}/${GITHUB_REPO}`; +export const STORAGE_KEY = 'inferencex-star-modal-dismissed'; +export const STARRED_KEY = 'inferencex-star-modal-starred'; +export const DISMISS_DURATION_MS = 7 * 24 * 60 * 60 * 1000; // 1 week + +let sessionDismissed = false; + +export function shouldShowModal(): boolean { + if (sessionDismissed) return false; + try { + if (localStorage.getItem(STARRED_KEY)) return false; + const value = localStorage.getItem(STORAGE_KEY); + if (!value) return true; + const dismissedAt = Number(value); + if (Number.isNaN(dismissedAt)) return true; + return Date.now() - dismissedAt >= DISMISS_DURATION_MS; + } catch { + return false; + } +} + +export function saveDismissTimestamp(): void { + try { + localStorage.setItem(STORAGE_KEY, String(Date.now())); + } catch { + // localStorage unavailable + } +} + +export function saveStarred(): void { + try { + localStorage.setItem(STARRED_KEY, '1'); + } catch { + // localStorage unavailable + } +} + +export function GitHubStarModal() { + const [open, setOpen] = useState(false); + const [ready, setReady] = useState(false); + + useEffect(() => { + if (shouldShowModal()) { + setOpen(true); + track('github_star_modal_shown'); + } + setReady(true); + }, []); + + const handleDismiss = useCallback(() => { + setOpen(false); + sessionDismissed = true; + saveDismissTimestamp(); + track('github_star_modal_dismissed'); + }, []); + + const handleStar = useCallback(() => { + window.open(GITHUB_REPO_URL, '_blank', 'noopener,noreferrer'); + setOpen(false); + sessionDismissed = true; + saveStarred(); + track('github_star_modal_starred'); + }, []); + + return ( + <> + {ready &&