import { Button, ContentRights, ContentWarnings, formatActivity, formatHandle, formatHandleWithAt, hexToRgba, layout, PlayerUI, ShareSheet, Text, useAuthor, useAvatar, useDID, useLivestreamStore, usePlayerStore, useTheme, useTitle, zero, } from "@streamplace/components"; import AQLink from "components/aqlink"; import FollowButton from "components/follow-button"; import { Image } from "expo-image"; import { ChevronLeft, ChevronRight } from "lucide-react-native"; import { Linking, Pressable, ScrollView, View } from "react-native"; import type { ActivityGame, ActivityLabel, } from "streamplace/src/lexicons/types/place/stream/defs"; import { LANG_TAG_PREFIX, LANGUAGES } from "../live-dashboard/livestream-panel"; import { KebabMenu } from "./desktop-ui/kebab"; const { gap, px, py, colors, r, borders } = zero; const ROSE_RING = "rgba(244, 114, 182, 0.32)"; const ATMOCO_STREAMS = [ { handle: "stream1.atmosphereconf.org", label: "Great Hall" }, { handle: "stream2.atmosphereconf.org", label: "Performance Theatre" }, { handle: "stream3.atmosphereconf.org", label: "Room 2301" }, ]; function AtMoCoNav({ currentHandle }: { currentHandle: string }) { const z = useTheme(); return ( Switch streams: {ATMOCO_STREAMS.map((stream) => { const isActive = currentHandle === stream.handle; return ( {stream.label} ); })} ); } export function BottomMetadata({ setShowChat, showChat, }: { setShowChat: (show: boolean) => void; showChat: boolean; }) { const profile = useAuthor(); const ls = useLivestreamStore((x) => x.livestream); const segment = useLivestreamStore((x) => x.segment); const mode = usePlayerStore((x) => x.mode); const did = useDID(); const contentWarnings = (segment?.contentWarnings?.warnings as string[]) || []; const contentRights = segment?.contentRights; const { theme } = useTheme(); const avatarUri = useAvatar(); const activity = ls?.record.activity as | ((ActivityGame | ActivityLabel) & { $type?: string }) | undefined; const activityLabel = activity ? formatActivity(activity) : null; const rawTags = ls?.record.tags as string[] | undefined; const tags = rawTags?.map((tag) => { if (tag.startsWith(LANG_TAG_PREFIX)) { const code = tag.slice(LANG_TAG_PREFIX.length); return LANGUAGES.find((l) => l.code === code)?.native ?? tag; } return tag; }); const hasMeta = activityLabel || (tags && tags.length > 0); return ( {/* Left: avatar + text stack */} {/* Avatar with rose ring */} {/* Handle + follow */} { if (profile?.handle) { Linking.openURL( `https://bsky.app/profile/${formatHandle(profile)}`, ); } }} style={{ flexShrink: 1, minWidth: 0 }} > {profile ? formatHandleWithAt(profile) : "@user"} {did && profile && ( )} {/* Title */} {useTitle()} {/* Activity + tags */} {hasMeta && ( {activityLabel && ( {activityLabel} )} {tags?.map((tag) => ( {tag} ))} )} {/* Right: controls */} {mode === "live" && ( )} {/* Content metadata */} {(contentWarnings.length > 0 || (contentRights && Object.keys(contentRights).length > 0)) && ( {contentRights && ( )} )} {/* Atmosphere Conference inter-stream nav. TODO: remove after conf */} {profile?.handle && ATMOCO_STREAMS.some((s) => s.handle === profile.handle) && ( )} ); }