Files
t5de-hub/apps/web/app/rooms/page.tsx
T
dhkatzandClaude Opus 5.5 6ba4d83317
CI / test (push) Successful in 6m38s
Room channel and rooms list
The realtime connection now carries the IMVU chats a client is in: the hub tells each proxy in a chat which
other T5DE users are there and what community products they wear (adult products only to adult accounts), on
joining and on every change. Rooms T5DE users enter are looked up on IMVU; those that are public, listed and
whose owner turned on "List my public rooms" appear on the new Rooms page, with the T5DE users in them who
show they're online. AP rooms are shown to adults only.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-29 18:14:43 -07:00

56 lines
2.2 KiB
TypeScript

import type { Metadata } from "next";
import { PageHeader, Tag } from "@/components/status";
import { Card, CardContent } from "@/components/ui/card";
import { api, unwrap } from "@/lib/api";
export const metadata: Metadata = { title: "Rooms" };
export default async function Rooms() {
const { rooms } = await api.rooms.get().then(unwrap);
return (
<>
<PageHeader title="Rooms">Public IMVU rooms of T5DE users.</PageHeader>
{rooms.length === 0 ? (
<Card>
<CardContent>
<p className="py-6 text-sm text-muted-foreground">No rooms listed yet.</p>
</CardContent>
</Card>
) : (
<ul className="grid gap-4 sm:grid-cols-2">
{rooms.map((r) => (
<li key={r.instanceId}>
<Card className="h-full overflow-hidden py-0">
{r.imageURL && (
// IMVU's own image of the room, from IMVU.
<img src={r.imageURL} alt="" className="aspect-[332/281] w-full bg-muted object-cover" loading="lazy" />
)}
<CardContent className="space-y-3 pb-6">
<div className="flex flex-wrap items-center gap-2">
<a href={r.url} className="font-medium underline-offset-4 hover:underline" rel="noreferrer">
{r.name}
</a>
{r.adult && <Tag tone="adult">AP</Tag>}
{r.t5de.length > 0 && (
<Tag tone="online" dot>
{r.t5de.length} on T5DE
</Tag>
)}
</div>
<p className="text-xs text-muted-foreground">
{r.owner.username} · {r.occupancy}/{r.capacity}
</p>
{r.description && <p className="line-clamp-3 text-sm whitespace-pre-line">{r.description}</p>}
{r.t5de.length > 0 && (
<p className="text-xs text-muted-foreground">Here now: {r.t5de.map((u) => u.username).join(", ")}</p>
)}
</CardContent>
</Card>
</li>
))}
</ul>
)}
</>
);
}