import { XIcon } from "lucide-react"; import React from "react"; import { Link } from "react-router"; import useSWR from "swr"; import ExternalLink from "src/components/ExternalLink"; import { Button } from "src/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle, } from "src/components/ui/card"; import { Dialog, DialogClose, DialogContent, DialogDescription, DialogTitle, } from "src/components/ui/dialog"; import { localStorageKeys } from "src/constants"; import { cn } from "src/lib/utils"; import { swrFetcher } from "src/utils/swr"; type StoryCta = { label: string; url: string; openInNewTab: boolean; }; type Story = { id: string; title: string; avatar: string; videoId?: string; cta?: StoryCta; }; type StoryApiResponse = { id: number; title: string; avatar: string; videoId?: string; cta?: StoryCta; }; function youTubeEmbedUrl(videoId: string) { return `https://www.youtube-nocookie.com/embed/${videoId}?autoplay=1&rel=0`; } function loadViewedStoryIds(): Set { try { const raw = localStorage.getItem(localStorageKeys.homeStoriesViewed); if (!raw) { return new Set(); } const parsed = JSON.parse(raw) as unknown; if (!Array.isArray(parsed)) { return new Set(); } return new Set(parsed.filter((id): id is string => typeof id === "string")); } catch { return new Set(); } } function persistViewedStoryIds(ids: Set) { try { localStorage.setItem( localStorageKeys.homeStoriesViewed, JSON.stringify([...ids]) ); } catch { // ignore quota / private mode } } function StoryAvatar({ story, viewed }: { story: Story; viewed: boolean }) { return (
{`${story.title}
); } export function StoriesWidget() { const { data, error, isLoading } = useSWR( "/api/alby/stories", swrFetcher ); const [activeStory, setActiveStory] = React.useState(null); const [viewedIds, setViewedIds] = React.useState>(loadViewedStoryIds); const stories = React.useMemo( () => error || !data ? [] : data.map((story) => ({ id: String(story.id), title: story.title, avatar: story.avatar, videoId: story.videoId, cta: story.cta, })), [data, error] ); const markStoryViewed = React.useCallback((storyId: string) => { setViewedIds((prev) => { if (prev.has(storyId)) { return prev; } const next = new Set(prev); next.add(storyId); persistViewedStoryIds(next); return next; }); }, []); if (!isLoading && stories.length === 0) { return null; } return ( <> Stories
{isLoading && ( Loading stories... )} {!isLoading && stories.map((story) => { const viewed = viewedIds.has(story.id); return ( ); })}
!open && setActiveStory(null)} > {activeStory && (
{activeStory.title} Watch the latest update {activeStory.videoId && (