diff --git a/js/desktop/src/features/particles/stream-card.tsx b/js/desktop/src/features/particles/stream-card.tsx deleted file mode 100644 index e133913..0000000 --- a/js/desktop/src/features/particles/stream-card.tsx +++ /dev/null @@ -1,191 +0,0 @@ -import { forwardRef, useMemo } from 'react'; -import { Headphones } from 'lucide-react'; -import { cn, getInitials } from '@/lib/utils'; -import { useLiveLatestChild } from '@/hooks/use-particle'; -import { useAuthStore } from '@/stores/auth-store'; -import { particlePath } from '@/lib/particle-path'; -import type { Particle, StreamProperties } from '@/api/types'; -import { useStreamAutoplay } from '@/hooks/use-stream-autoplay'; -import { ParticlePreview } from '@/features/particles/particle-preview'; -import { useNetwork } from '@/hooks/use-networks'; -import { HumanAvatar } from '@/components/human-avatar'; -import { RelativeTimestamp } from '@/components/relative-timestamp'; -import { Small } from '@/components/ui/typography'; - -interface StreamCardProps { - particle: Particle & { type: 'stream'; properties: StreamProperties }; - networkId: string; - onClick: () => void; - isSelected?: boolean; - shortcutKey?: number; -} - -export const StreamCard = forwardRef( - function StreamCard( - { particle, networkId, onClick, isSelected, shortcutKey }, - ref, - ) { - const streamPath = particlePath(networkId, [particle.id]); - const { latestChild } = useLiveLatestChild(streamPath); - const userId = useAuthStore((s) => s.user?.id) ?? ''; - const network = useNetwork(networkId); - - useStreamAutoplay(latestChild, particle, networkId, network ?? undefined); - - const hasActiveHuddle = - particle.huddle_active_participants && - particle.huddle_active_participants.length > 0; - const huddleCount = particle.huddle_active_participants?.length ?? 0; - - const isDM = - particle.visible_to.length === 2 && - particle.visible_to.every((v) => v.startsWith('human:')); - - const avatar = useMemo(() => { - if (isDM) { - const otherEntry = particle.visible_to.find( - (v) => v !== `human:${userId}`, - ); - if (otherEntry) { - const otherId = otherEntry.replace('human:', ''); - const otherHuman = network?.humans?.find((h) => h.id === otherId); - if (otherHuman) { - return { - initials: getInitials(otherHuman.email), - avatarObjectId: otherHuman.avatar_object_id ?? null, - }; - } - } - } - - if (latestChild) { - const creator = network?.humans?.find( - (h) => h.id === latestChild.created_by_human_id, - ); - if (creator) { - return { - initials: getInitials(creator.email), - avatarObjectId: creator.avatar_object_id ?? null, - }; - } - } - - return { - initials: particle.properties.name.slice(0, 2).toUpperCase(), - avatarObjectId: null, - }; - }, [ - isDM, - particle.visible_to, - particle.properties.name, - userId, - latestChild, - network, - ]); - - const isUnseen = useMemo(() => { - if (!latestChild) return false; - const latestChildTimestamp = latestChild.created_at.getTime(); - const userPlaybackPosition = - particle.playback_markers?.[userId]?.getTime() ?? 0; - return latestChildTimestamp > userPlaybackPosition; - }, [latestChild, particle.playback_markers, userId]); - - // For media particles with a transcript, show it as an overlay on the preview - const transcript = - latestChild?.type === 'media' - ? latestChild.properties.transcript?.transcript - : undefined; - - return ( -
{ - if (e.key === 'Enter' || e.key === ' ') onClick(); - }} - className={cn( - 'cursor-pointer overflow-hidden rounded-xl ring-1 ring-foreground/10 transition-all hover:ring-foreground/20', - isUnseen && 'ring-2 ring-primary', - isSelected && 'ring-2 ring-ring', - hasActiveHuddle && 'ring-2 ring-red-500/70', - )} - > - {/* Preview area */} -
- {hasActiveHuddle && ( -
- )} - {shortcutKey && ( - - {shortcutKey} - - )} - {latestChild ? ( - - ) : ( -
-

- No messages yet -

-
- )} - - {/* Transcript overlay for media with transcripts */} - {transcript && ( -
-

- {transcript} -

-
- )} -
- - {/* Info bar */} -
- - - {particle.properties.name} - -
- {hasActiveHuddle && ( - - - - {huddleCount} - - - )} - {latestChild && ( - - - - )} - {isUnseen && ( - - )} -
-
-
- ); - }, -);