feat(room-preview): preview affordance in space lobby + explore grids
Follow-up to the room-preview work so you can actually reach a preview from the room lists, not just via a matrix.to link: - Space lobby (RoomItem): un-joined child rooms now show an Eye 'Preview' chip next to Join. It routes through the existing onOpen (data-room-id -> space/room path), which renders the full JoinBeforeNavigate preview card because the room isn't joined. - Explore grids (Server + Featured): pass join_rule (and encryption, where the summary provides it) to RoomCard, so the directory/featured cards — which already are full preview cards — now show the join-rule chip and a Request-to-join button for knock rooms instead of a Join that fails. 738 tests pass, build clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -97,6 +97,31 @@ function RoomJoinButton({ roomId, via }: RoomJoinButtonProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Open the full preview page (JoinBeforeNavigate) for an un-joined room. onOpen
|
||||||
|
// reads data-room-id and navigates to the space→room path, which — because the
|
||||||
|
// room isn't joined — renders the preview card instead of the timeline.
|
||||||
|
function RoomPreviewChip({
|
||||||
|
roomId,
|
||||||
|
onOpen,
|
||||||
|
}: {
|
||||||
|
roomId: string;
|
||||||
|
onOpen: MouseEventHandler<HTMLButtonElement>;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Chip
|
||||||
|
data-room-id={roomId}
|
||||||
|
onClick={onOpen}
|
||||||
|
variant="Secondary"
|
||||||
|
fill="None"
|
||||||
|
size="400"
|
||||||
|
radii="Pill"
|
||||||
|
aria-label="Preview room"
|
||||||
|
>
|
||||||
|
<Icon size="50" src={Icons.Eye} />
|
||||||
|
</Chip>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function RoomProfileLoading() {
|
function RoomProfileLoading() {
|
||||||
return (
|
return (
|
||||||
<Box grow="Yes" gap="300">
|
<Box grow="Yes" gap="300">
|
||||||
@@ -365,7 +390,10 @@ export const RoomItemCard = as<'div', RoomItemCardProps>(
|
|||||||
</Chip>
|
</Chip>
|
||||||
</Box>
|
</Box>
|
||||||
) : (
|
) : (
|
||||||
|
<Box shrink="No" gap="100" alignItems="Center">
|
||||||
|
<RoomPreviewChip roomId={roomId} onOpen={onOpen} />
|
||||||
<RoomJoinButton roomId={roomId} via={content.via} />
|
<RoomJoinButton roomId={roomId} via={content.via} />
|
||||||
|
</Box>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@@ -409,7 +437,12 @@ export const RoomItemCard = as<'div', RoomItemCardProps>(
|
|||||||
memberCount={summary.num_joined_members}
|
memberCount={summary.num_joined_members}
|
||||||
suggested={content.suggested}
|
suggested={content.suggested}
|
||||||
joinRule={summary.join_rule}
|
joinRule={summary.join_rule}
|
||||||
options={<RoomJoinButton roomId={roomId} via={content.via} />}
|
options={
|
||||||
|
<Box shrink="No" gap="100" alignItems="Center">
|
||||||
|
<RoomPreviewChip roomId={roomId} onOpen={onOpen} />
|
||||||
|
<RoomJoinButton roomId={roomId} via={content.via} />
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ export function FeaturedRooms() {
|
|||||||
name={roomSummary?.name}
|
name={roomSummary?.name}
|
||||||
topic={roomSummary?.topic}
|
topic={roomSummary?.topic}
|
||||||
memberCount={roomSummary?.num_joined_members}
|
memberCount={roomSummary?.num_joined_members}
|
||||||
|
joinRule={roomSummary?.join_rule}
|
||||||
|
encrypted={!!roomSummary?.['im.nheko.summary.encryption']}
|
||||||
onView={navigateSpace}
|
onView={navigateSpace}
|
||||||
renderTopicViewer={(name, topic, requestClose) => (
|
renderTopicViewer={(name, topic, requestClose) => (
|
||||||
<RoomTopicViewer
|
<RoomTopicViewer
|
||||||
@@ -101,6 +103,8 @@ export function FeaturedRooms() {
|
|||||||
name={roomSummary?.name}
|
name={roomSummary?.name}
|
||||||
topic={roomSummary?.topic}
|
topic={roomSummary?.topic}
|
||||||
memberCount={roomSummary?.num_joined_members}
|
memberCount={roomSummary?.num_joined_members}
|
||||||
|
joinRule={roomSummary?.join_rule}
|
||||||
|
encrypted={!!roomSummary?.['im.nheko.summary.encryption']}
|
||||||
onView={navigateRoom}
|
onView={navigateRoom}
|
||||||
renderTopicViewer={(name, topic, requestClose) => (
|
renderTopicViewer={(name, topic, requestClose) => (
|
||||||
<RoomTopicViewer
|
<RoomTopicViewer
|
||||||
|
|||||||
@@ -604,6 +604,7 @@ export function PublicRooms() {
|
|||||||
topic={chunkRoom.topic}
|
topic={chunkRoom.topic}
|
||||||
memberCount={chunkRoom.num_joined_members}
|
memberCount={chunkRoom.num_joined_members}
|
||||||
roomType={chunkRoom.room_type}
|
roomType={chunkRoom.room_type}
|
||||||
|
joinRule={chunkRoom.join_rule}
|
||||||
onView={
|
onView={
|
||||||
chunkRoom.room_type === RoomType.Space
|
chunkRoom.room_type === RoomType.Space
|
||||||
? navigateSpace
|
? navigateSpace
|
||||||
|
|||||||
Reference in New Issue
Block a user