fix(room-preview): make the preview card actually populate + richer
Two review agents found the preview card degrades to 'id + logo + Join' for real
reasons. Fixes:
- **via was dropped at the summary fetch** (root cause). RoomSummaryLoader now
accepts + forwards `via` to getRoomSummary (and keys the query on it);
JoinBeforeNavigate passes viaServers; the lobby Preview chip carries data-via and
Lobby.handleOpenRoom appends it to the navigated URL. Without this, previews of
rooms the HS isn't already in came back sparse/404.
- **No loading/error state** -> RoomSummaryLoader now surfaces {loading,error};
JoinBeforeNavigate shows a Spinner while loading instead of the degraded card.
- **Room id leaked as name AND topic AND header** -> stop using the raw `!id` as
the topic fallback (show 'No description'); name falls back to canonical_alias
then alias-localpart; the page header shows the summary name.
- **Richer, membership-aware card**: forward canonical_alias (shown under the name),
world_readable ('Readable' badge), and membership -> the button now shows Accept
invite / Requested / Banned correctly instead of a Join that lies; a 'hero' layout
for the single-preview page (primary Join button, unclamped topic). Removed dead
`|| undefined ||`.
IRoomSummary re-adds canonical_alias (the SDK type Omit<>s it though MSC3266
returns it). 738 tests pass, build clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -36,7 +36,7 @@ import { useCategoryHandler } from '../../hooks/useCategoryHandler';
|
||||
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
||||
import { allRoomsAtom } from '../../state/room-list/roomList';
|
||||
import { getCanonicalAliasOrRoomId, rateLimitedActions } from '../../utils/matrix';
|
||||
import { getSpaceRoomPath } from '../../pages/pathUtils';
|
||||
import { getSpaceRoomPath, withSearchParam } from '../../pages/pathUtils';
|
||||
import { StateEvent } from '../../../types/matrix/room';
|
||||
import { CanDropCallback, useDnDMonitor } from './DnD';
|
||||
import { ASCIILexicalTable, orderKeys } from '../../utils/ASCIILexicalTable';
|
||||
@@ -411,8 +411,13 @@ export function Lobby() {
|
||||
const handleOpenRoom: MouseEventHandler<HTMLButtonElement> = (evt) => {
|
||||
const rId = evt.currentTarget.getAttribute('data-room-id');
|
||||
if (!rId) return;
|
||||
// Preview chips carry the room's resident servers so getRoomSummary can
|
||||
// resolve a room the homeserver isn't already in (else the preview is sparse).
|
||||
const via = evt.currentTarget.getAttribute('data-via');
|
||||
const pSpaceIdOrAlias = getCanonicalAliasOrRoomId(mx, space.roomId);
|
||||
navigate(getSpaceRoomPath(pSpaceIdOrAlias, getCanonicalAliasOrRoomId(mx, rId)));
|
||||
let path = getSpaceRoomPath(pSpaceIdOrAlias, getCanonicalAliasOrRoomId(mx, rId));
|
||||
if (via) path = withSearchParam(path, { viaServers: via });
|
||||
navigate(path);
|
||||
};
|
||||
|
||||
const togglePinToSidebar = useCallback(
|
||||
|
||||
@@ -102,14 +102,17 @@ function RoomJoinButton({ roomId, via }: RoomJoinButtonProps) {
|
||||
// room isn't joined — renders the preview card instead of the timeline.
|
||||
function RoomPreviewChip({
|
||||
roomId,
|
||||
via,
|
||||
onOpen,
|
||||
}: {
|
||||
roomId: string;
|
||||
via?: string[];
|
||||
onOpen: MouseEventHandler<HTMLButtonElement>;
|
||||
}) {
|
||||
return (
|
||||
<Chip
|
||||
data-room-id={roomId}
|
||||
data-via={via && via.length > 0 ? via.join(',') : undefined}
|
||||
onClick={onOpen}
|
||||
variant="Secondary"
|
||||
fill="None"
|
||||
@@ -391,7 +394,7 @@ export const RoomItemCard = as<'div', RoomItemCardProps>(
|
||||
</Box>
|
||||
) : (
|
||||
<Box shrink="No" gap="100" alignItems="Center">
|
||||
<RoomPreviewChip roomId={roomId} onOpen={onOpen} />
|
||||
<RoomPreviewChip roomId={roomId} via={content.via} onOpen={onOpen} />
|
||||
<RoomJoinButton roomId={roomId} via={content.via} />
|
||||
</Box>
|
||||
)
|
||||
@@ -439,7 +442,7 @@ export const RoomItemCard = as<'div', RoomItemCardProps>(
|
||||
joinRule={summary.join_rule}
|
||||
options={
|
||||
<Box shrink="No" gap="100" alignItems="Center">
|
||||
<RoomPreviewChip roomId={roomId} onOpen={onOpen} />
|
||||
<RoomPreviewChip roomId={roomId} via={content.via} onOpen={onOpen} />
|
||||
<RoomJoinButton roomId={roomId} via={content.via} />
|
||||
</Box>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user