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) && (
)}
);
}