feat: enhance room data retrieval with server domain extraction

This commit is contained in:
2026-02-21 22:21:56 +11:00
parent ef55d1583f
commit f00e20b1ac
2 changed files with 67 additions and 10 deletions

View File

@@ -5,7 +5,7 @@ import { JoinRule, MatrixClient } from 'matrix-js-sdk';
import { useAtomValue } from 'jotai'; import { useAtomValue } from 'jotai';
import { createMentionElement, moveCursor, replaceWithElement } from '../utils'; import { createMentionElement, moveCursor, replaceWithElement } from '../utils';
import { getDirectRoomAvatarUrl } from '../../../utils/room'; import { getDirectRoomAvatarUrl, guessPerfectParent } from '../../../utils/room';
import { useMatrixClient } from '../../../hooks/useMatrixClient'; import { useMatrixClient } from '../../../hooks/useMatrixClient';
import { AutocompleteQuery } from './autocompleteQuery'; import { AutocompleteQuery } from './autocompleteQuery';
import { AutocompleteMenu } from './AutocompleteMenu'; import { AutocompleteMenu } from './AutocompleteMenu';
@@ -18,6 +18,7 @@ import { allRoomsAtom } from '../../../state/room-list/roomList';
import { factoryRoomIdByActivity } from '../../../utils/sort'; import { factoryRoomIdByActivity } from '../../../utils/sort';
import { RoomAvatar, RoomIcon } from '../../room-avatar'; import { RoomAvatar, RoomIcon } from '../../room-avatar';
import { getViaServers } from '../../../plugins/via-servers'; import { getViaServers } from '../../../plugins/via-servers';
import { roomToParentsAtom } from '../../../state/room/roomToParents';
type MentionAutoCompleteHandler = (roomAliasOrId: string, name: string) => void; type MentionAutoCompleteHandler = (roomAliasOrId: string, name: string) => void;
@@ -78,6 +79,7 @@ export function RoomMentionAutocomplete({
}: RoomMentionAutocompleteProps) { }: RoomMentionAutocompleteProps) {
const mx = useMatrixClient(); const mx = useMatrixClient();
const mDirects = useAtomValue(mDirectAtom); const mDirects = useAtomValue(mDirectAtom);
const roomToParents = useAtomValue(roomToParentsAtom);
const allRooms = useAtomValue(allRoomsAtom).sort(factoryRoomIdByActivity(mx)); const allRooms = useAtomValue(allRoomsAtom).sort(factoryRoomIdByActivity(mx));
@@ -103,6 +105,42 @@ export function RoomMentionAutocomplete({
else resetSearch(); else resetSearch();
}, [query.text, search, resetSearch]); }, [query.text, search, resetSearch]);
// Build space hierarchy path for a room
const getSpacePath = useCallback((rId: string): string | null => {
// Skip DMs
if (mDirects.has(rId)) return null;
const buildParentChain = (currentRoomId: string): string[] => {
const parents = roomToParents.get(currentRoomId);
if (!parents || parents.size === 0) {
return [];
}
const parentsList = Array.from(parents);
let chosenParent: string;
if (parentsList.length === 1) {
chosenParent = parentsList[0];
} else {
const orphanParents = parentsList.filter(p => !roomToParents.has(p));
if (orphanParents.length > 0) {
chosenParent = guessPerfectParent(mx, currentRoomId, orphanParents) ?? orphanParents[0];
} else {
chosenParent = parentsList[0];
}
}
const parentRoom = mx.getRoom(chosenParent);
if (!parentRoom?.name) return [];
const upperChain = buildParentChain(chosenParent);
return [...upperChain, parentRoom.name];
};
const parentChain = buildParentChain(rId);
return parentChain.length > 0 ? parentChain.join(' > ') : null;
}, [mx, mDirects, roomToParents]);
const handleAutocomplete: MentionAutoCompleteHandler = (roomAliasOrId, name) => { const handleAutocomplete: MentionAutoCompleteHandler = (roomAliasOrId, name) => {
const mentionRoom = mx.getRoom(roomAliasOrId); const mentionRoom = mx.getRoom(roomAliasOrId);
const viaServers = mentionRoom ? getViaServers(mentionRoom) : undefined; const viaServers = mentionRoom ? getViaServers(mentionRoom) : undefined;
@@ -144,6 +182,11 @@ export function RoomMentionAutocomplete({
const handleSelect = () => handleAutocomplete(room.getCanonicalAlias() ?? rId, room.name); const handleSelect = () => handleAutocomplete(room.getCanonicalAlias() ?? rId, room.name);
// Get space hierarchy path or canonical alias or empty string
const spacePath = getSpacePath(rId);
const alias = room.getCanonicalAlias();
const secondaryText = spacePath || alias || '';
return ( return (
<MenuItem <MenuItem
key={rId} key={rId}
@@ -154,9 +197,11 @@ export function RoomMentionAutocomplete({
} }
onClick={handleSelect} onClick={handleSelect}
after={ after={
<Text size="T200" priority="300" truncate> secondaryText && (
{room.getCanonicalAlias() ?? ''} <Text size="T200" priority="300" truncate>
</Text> {secondaryText}
</Text>
)
} }
before={ before={
<Avatar size="200"> <Avatar size="200">

View File

@@ -305,12 +305,19 @@ async function getChannels(matrixClient: any) {
return rooms return rooms
.filter((room: any) => !room.isSpaceRoom()) .filter((room: any) => !room.isSpaceRoom())
.map((room: any) => ({ .map((room: any) => {
roomId: room.roomId, // Extract server domain from roomId (!localpart:domain.tld)
name: room.name || 'Unnamed Room', const serverMatch = room.roomId.match(/:(.+)$/);
isDirect: room.getMyMembership() === 'invite' ? false : room.guessDMUserId() !== null, const server = serverMatch ? serverMatch[1] : null;
avatar: room.getMxcAvatarUrl() || null,
})) return {
roomId: room.roomId,
name: room.name || 'Unnamed Room',
server: server,
isDirect: room.getMyMembership() === 'invite' ? false : room.guessDMUserId() !== null,
avatar: room.getMxcAvatarUrl() || null,
};
})
.sort((a: any, b: any) => a.name.localeCompare(b.name)); .sort((a: any, b: any) => a.name.localeCompare(b.name));
} }
@@ -362,9 +369,14 @@ async function getCurrentRoom(matrixClient: any) {
throw new Error(`Current room not found: ${currentRoomId}`); throw new Error(`Current room not found: ${currentRoomId}`);
} }
// Extract server domain from roomId (!localpart:domain.tld)
const serverMatch = room.roomId.match(/:(.+)$/);
const server = serverMatch ? serverMatch[1] : null;
return { return {
roomId: room.roomId, roomId: room.roomId,
name: room.name || 'Unnamed Room', name: room.name || 'Unnamed Room',
server: server,
avatar: room.getMxcAvatarUrl() || null, avatar: room.getMxcAvatarUrl() || null,
isDirect: room.guessDMUserId() !== null, isDirect: room.guessDMUserId() !== null,
}; };