Member drawer filter (#1457)
* save member drawer sort filter in local storage * render member drawer with key * improve member search
This commit is contained in:
parent
b4e1ced3ed
commit
50429a3513
8 changed files with 71 additions and 44 deletions
|
@ -1,7 +1,7 @@
|
||||||
import React, { useEffect, KeyboardEvent as ReactKeyboardEvent } from 'react';
|
import React, { useEffect, KeyboardEvent as ReactKeyboardEvent } from 'react';
|
||||||
import { Editor } from 'slate';
|
import { Editor } from 'slate';
|
||||||
import { Avatar, AvatarFallback, AvatarImage, MenuItem, Text, color } from 'folds';
|
import { Avatar, AvatarFallback, AvatarImage, MenuItem, Text, color } from 'folds';
|
||||||
import { MatrixClient, RoomMember } from 'matrix-js-sdk';
|
import { MatrixClient, Room, RoomMember } from 'matrix-js-sdk';
|
||||||
|
|
||||||
import { AutocompleteQuery } from './autocompleteQuery';
|
import { AutocompleteQuery } from './autocompleteQuery';
|
||||||
import { AutocompleteMenu } from './AutocompleteMenu';
|
import { AutocompleteMenu } from './AutocompleteMenu';
|
||||||
|
@ -16,6 +16,7 @@ import { onTabPress } from '../../../utils/keyboard';
|
||||||
import { createMentionElement, moveCursor, replaceWithElement } from '../utils';
|
import { createMentionElement, moveCursor, replaceWithElement } from '../utils';
|
||||||
import { useKeyDown } from '../../../hooks/useKeyDown';
|
import { useKeyDown } from '../../../hooks/useKeyDown';
|
||||||
import { getMxIdLocalPart, getMxIdServer, validMxId } from '../../../utils/matrix';
|
import { getMxIdLocalPart, getMxIdServer, validMxId } from '../../../utils/matrix';
|
||||||
|
import { getMemberDisplayName, getMemberSearchStr } from '../../../utils/room';
|
||||||
|
|
||||||
type MentionAutoCompleteHandler = (userId: string, name: string) => void;
|
type MentionAutoCompleteHandler = (userId: string, name: string) => void;
|
||||||
|
|
||||||
|
@ -64,7 +65,7 @@ function UnknownMentionItem({
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserMentionAutocompleteProps = {
|
type UserMentionAutocompleteProps = {
|
||||||
roomId: string;
|
room: Room;
|
||||||
editor: Editor;
|
editor: Editor;
|
||||||
query: AutocompleteQuery<string>;
|
query: AutocompleteQuery<string>;
|
||||||
requestClose: () => void;
|
requestClose: () => void;
|
||||||
|
@ -77,21 +78,19 @@ const SEARCH_OPTIONS: UseAsyncSearchOptions = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const getRoomMemberStr: SearchItemStrGetter<RoomMember> = (roomMember) => [
|
const mxIdToName = (mxId: string) => getMxIdLocalPart(mxId) ?? mxId;
|
||||||
roomMember.name,
|
const getRoomMemberStr: SearchItemStrGetter<RoomMember> = (m, query) =>
|
||||||
getMxIdLocalPart(roomMember.userId) ?? roomMember.userId,
|
getMemberSearchStr(m, query, mxIdToName);
|
||||||
roomMember.userId,
|
|
||||||
];
|
|
||||||
|
|
||||||
export function UserMentionAutocomplete({
|
export function UserMentionAutocomplete({
|
||||||
roomId,
|
room,
|
||||||
editor,
|
editor,
|
||||||
query,
|
query,
|
||||||
requestClose,
|
requestClose,
|
||||||
}: UserMentionAutocompleteProps) {
|
}: UserMentionAutocompleteProps) {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
const room = mx.getRoom(roomId);
|
const roomId: string = room.roomId!;
|
||||||
const roomAliasOrId = room?.getCanonicalAlias() || roomId;
|
const roomAliasOrId = room.getCanonicalAlias() || roomId;
|
||||||
const members = useRoomMembers(mx, roomId);
|
const members = useRoomMembers(mx, roomId);
|
||||||
|
|
||||||
const [result, search, resetSearch] = useAsyncSearch(members, getRoomMemberStr, SEARCH_OPTIONS);
|
const [result, search, resetSearch] = useAsyncSearch(members, getRoomMemberStr, SEARCH_OPTIONS);
|
||||||
|
@ -129,6 +128,9 @@ export function UserMentionAutocomplete({
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const getName = (member: RoomMember) =>
|
||||||
|
getMemberDisplayName(room, member.userId) ?? getMxIdLocalPart(member.userId) ?? member.userId;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AutocompleteMenu headerContent={<Text size="L400">Mentions</Text>} requestClose={requestClose}>
|
<AutocompleteMenu headerContent={<Text size="L400">Mentions</Text>} requestClose={requestClose}>
|
||||||
{query.text === 'room' && (
|
{query.text === 'room' && (
|
||||||
|
@ -155,9 +157,9 @@ export function UserMentionAutocomplete({
|
||||||
as="button"
|
as="button"
|
||||||
radii="300"
|
radii="300"
|
||||||
onKeyDown={(evt: ReactKeyboardEvent<HTMLButtonElement>) =>
|
onKeyDown={(evt: ReactKeyboardEvent<HTMLButtonElement>) =>
|
||||||
onTabPress(evt, () => handleAutocomplete(roomMember.userId, roomMember.name))
|
onTabPress(evt, () => handleAutocomplete(roomMember.userId, getName(roomMember)))
|
||||||
}
|
}
|
||||||
onClick={() => handleAutocomplete(roomMember.userId, roomMember.name)}
|
onClick={() => handleAutocomplete(roomMember.userId, getName(roomMember))}
|
||||||
after={
|
after={
|
||||||
<Text size="T200" priority="300" truncate>
|
<Text size="T200" priority="300" truncate>
|
||||||
{roomMember.userId}
|
{roomMember.userId}
|
||||||
|
@ -166,7 +168,7 @@ export function UserMentionAutocomplete({
|
||||||
before={
|
before={
|
||||||
<Avatar size="200">
|
<Avatar size="200">
|
||||||
{avatarUrl ? (
|
{avatarUrl ? (
|
||||||
<AvatarImage src={avatarUrl} alt={roomMember.userId} />
|
<AvatarImage src={avatarUrl} alt={getName(roomMember)} />
|
||||||
) : (
|
) : (
|
||||||
<AvatarFallback
|
<AvatarFallback
|
||||||
style={{
|
style={{
|
||||||
|
@ -174,14 +176,14 @@ export function UserMentionAutocomplete({
|
||||||
color: color.Secondary.OnContainer,
|
color: color.Secondary.OnContainer,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text size="H6">{roomMember.name[0] || roomMember.userId[1]}</Text>
|
<Text size="H6">{getName(roomMember)[0]}</Text>
|
||||||
</AvatarFallback>
|
</AvatarFallback>
|
||||||
)}
|
)}
|
||||||
</Avatar>
|
</Avatar>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Text style={{ flexGrow: 1 }} size="B400" truncate>
|
<Text style={{ flexGrow: 1 }} size="B400" truncate>
|
||||||
{roomMember.name}
|
{getName(roomMember)}
|
||||||
</Text>
|
</Text>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
);
|
);
|
||||||
|
|
|
@ -17,7 +17,8 @@ export type UseAsyncSearchOptions = AsyncSearchOption & {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SearchItemStrGetter<TSearchItem extends object | string | number> = (
|
export type SearchItemStrGetter<TSearchItem extends object | string | number> = (
|
||||||
searchItem: TSearchItem
|
searchItem: TSearchItem,
|
||||||
|
query: string
|
||||||
) => string | string[];
|
) => string | string[];
|
||||||
|
|
||||||
export type UseAsyncSearchResult<TSearchItem extends object | string | number> = {
|
export type UseAsyncSearchResult<TSearchItem extends object | string | number> = {
|
||||||
|
@ -38,7 +39,7 @@ export const useAsyncSearch = <TSearchItem extends object | string | number>(
|
||||||
setResult(undefined);
|
setResult(undefined);
|
||||||
|
|
||||||
const handleMatch: MatchHandler<TSearchItem> = (item, query) => {
|
const handleMatch: MatchHandler<TSearchItem> = (item, query) => {
|
||||||
const itemStr = getItemStr(item);
|
const itemStr = getItemStr(item, query);
|
||||||
if (Array.isArray(itemStr))
|
if (Array.isArray(itemStr))
|
||||||
return !!itemStr.find((i) =>
|
return !!itemStr.find((i) =>
|
||||||
matchQuery(normalize(i, options?.normalizeOptions), query, options?.matchOptions)
|
matchQuery(normalize(i, options?.normalizeOptions), query, options?.matchOptions)
|
||||||
|
|
|
@ -46,14 +46,20 @@ import {
|
||||||
} from '../../hooks/useIntersectionObserver';
|
} from '../../hooks/useIntersectionObserver';
|
||||||
import { Membership } from '../../../types/matrix/room';
|
import { Membership } from '../../../types/matrix/room';
|
||||||
import { UseStateProvider } from '../../components/UseStateProvider';
|
import { UseStateProvider } from '../../components/UseStateProvider';
|
||||||
import { UseAsyncSearchOptions, useAsyncSearch } from '../../hooks/useAsyncSearch';
|
import {
|
||||||
|
SearchItemStrGetter,
|
||||||
|
UseAsyncSearchOptions,
|
||||||
|
useAsyncSearch,
|
||||||
|
} from '../../hooks/useAsyncSearch';
|
||||||
import { useDebounce } from '../../hooks/useDebounce';
|
import { useDebounce } from '../../hooks/useDebounce';
|
||||||
import colorMXID from '../../../util/colorMXID';
|
import colorMXID from '../../../util/colorMXID';
|
||||||
import { usePowerLevelTags, PowerLevelTag } from '../../hooks/usePowerLevelTags';
|
import { usePowerLevelTags, PowerLevelTag } from '../../hooks/usePowerLevelTags';
|
||||||
import { roomIdToTypingMembersAtom, selectRoomTypingMembersAtom } from '../../state/typingMembers';
|
import { roomIdToTypingMembersAtom, selectRoomTypingMembersAtom } from '../../state/typingMembers';
|
||||||
import { TypingIndicator } from '../../components/typing-indicator';
|
import { TypingIndicator } from '../../components/typing-indicator';
|
||||||
import { getMemberDisplayName } from '../../utils/room';
|
import { getMemberDisplayName, getMemberSearchStr } from '../../utils/room';
|
||||||
import { getMxIdLocalPart } from '../../utils/matrix';
|
import { getMxIdLocalPart } from '../../utils/matrix';
|
||||||
|
import { useSetting } from '../../state/hooks/settings';
|
||||||
|
import { settingsAtom } from '../../state/settings';
|
||||||
|
|
||||||
export const MembershipFilters = {
|
export const MembershipFilters = {
|
||||||
filterJoined: (m: RoomMember) => m.membership === Membership.Join,
|
filterJoined: (m: RoomMember) => m.membership === Membership.Join,
|
||||||
|
@ -159,7 +165,10 @@ const SEARCH_OPTIONS: UseAsyncSearchOptions = {
|
||||||
contain: true,
|
contain: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const getMemberItemStr = (m: RoomMember) => [m.name, m.userId];
|
|
||||||
|
const mxIdToName = (mxId: string) => getMxIdLocalPart(mxId) ?? mxId;
|
||||||
|
const getRoomMemberStr: SearchItemStrGetter<RoomMember> = (m, query) =>
|
||||||
|
getMemberSearchStr(m, query, mxIdToName);
|
||||||
|
|
||||||
type MembersDrawerProps = {
|
type MembersDrawerProps = {
|
||||||
room: Room;
|
room: Room;
|
||||||
|
@ -175,10 +184,12 @@ export function MembersDrawer({ room }: MembersDrawerProps) {
|
||||||
|
|
||||||
const membershipFilterMenu = useMembershipFilterMenu();
|
const membershipFilterMenu = useMembershipFilterMenu();
|
||||||
const sortFilterMenu = useSortFilterMenu();
|
const sortFilterMenu = useSortFilterMenu();
|
||||||
const [filter, setFilter] = useState<MembersFilterOptions>({
|
const [sortFilterIndex, setSortFilterIndex] = useSetting(settingsAtom, 'memberSortFilterIndex');
|
||||||
membershipFilter: membershipFilterMenu[0],
|
const [membershipFilterIndex, setMembershipFilterIndex] = useState(0);
|
||||||
sortFilter: sortFilterMenu[0],
|
|
||||||
});
|
const membershipFilter = membershipFilterMenu[membershipFilterIndex] ?? membershipFilterMenu[0];
|
||||||
|
const sortFilter = sortFilterMenu[sortFilterIndex] ?? sortFilterMenu[0];
|
||||||
|
|
||||||
const [onTop, setOnTop] = useState(true);
|
const [onTop, setOnTop] = useState(true);
|
||||||
|
|
||||||
const typingMembers = useAtomValue(
|
const typingMembers = useAtomValue(
|
||||||
|
@ -188,15 +199,15 @@ export function MembersDrawer({ room }: MembersDrawerProps) {
|
||||||
const filteredMembers = useMemo(
|
const filteredMembers = useMemo(
|
||||||
() =>
|
() =>
|
||||||
members
|
members
|
||||||
.filter(filter.membershipFilter.filterFn)
|
.filter(membershipFilter.filterFn)
|
||||||
.sort(filter.sortFilter.filterFn)
|
.sort(sortFilter.filterFn)
|
||||||
.sort((a, b) => b.powerLevel - a.powerLevel),
|
.sort((a, b) => b.powerLevel - a.powerLevel),
|
||||||
[members, filter]
|
[members, membershipFilter, sortFilter]
|
||||||
);
|
);
|
||||||
|
|
||||||
const [result, search, resetSearch] = useAsyncSearch(
|
const [result, search, resetSearch] = useAsyncSearch(
|
||||||
filteredMembers,
|
filteredMembers,
|
||||||
getMemberItemStr,
|
getRoomMemberStr,
|
||||||
SEARCH_OPTIONS
|
SEARCH_OPTIONS
|
||||||
);
|
);
|
||||||
if (!result && searchInputRef.current?.value) search(searchInputRef.current.value);
|
if (!result && searchInputRef.current?.value) search(searchInputRef.current.value);
|
||||||
|
@ -310,18 +321,18 @@ export function MembersDrawer({ room }: MembersDrawerProps) {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Menu style={{ padding: config.space.S100 }}>
|
<Menu style={{ padding: config.space.S100 }}>
|
||||||
{membershipFilterMenu.map((menuItem) => (
|
{membershipFilterMenu.map((menuItem, index) => (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={menuItem.name}
|
key={menuItem.name}
|
||||||
variant={
|
variant={
|
||||||
menuItem.name === filter.membershipFilter.name
|
menuItem.name === membershipFilter.name
|
||||||
? menuItem.color
|
? menuItem.color
|
||||||
: 'Surface'
|
: 'Surface'
|
||||||
}
|
}
|
||||||
aria-pressed={menuItem.name === filter.membershipFilter.name}
|
aria-pressed={menuItem.name === membershipFilter.name}
|
||||||
radii="300"
|
radii="300"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setFilter((f) => ({ ...f, membershipFilter: menuItem }));
|
setMembershipFilterIndex(index);
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -336,12 +347,12 @@ export function MembersDrawer({ room }: MembersDrawerProps) {
|
||||||
<Chip
|
<Chip
|
||||||
ref={anchorRef}
|
ref={anchorRef}
|
||||||
onClick={() => setOpen(!open)}
|
onClick={() => setOpen(!open)}
|
||||||
variant={filter.membershipFilter.color}
|
variant={membershipFilter.color}
|
||||||
size="400"
|
size="400"
|
||||||
radii="300"
|
radii="300"
|
||||||
before={<Icon src={Icons.Filter} size="50" />}
|
before={<Icon src={Icons.Filter} size="50" />}
|
||||||
>
|
>
|
||||||
<Text size="T200">{filter.membershipFilter.name}</Text>
|
<Text size="T200">{membershipFilter.name}</Text>
|
||||||
</Chip>
|
</Chip>
|
||||||
)}
|
)}
|
||||||
</PopOut>
|
</PopOut>
|
||||||
|
@ -365,14 +376,14 @@ export function MembersDrawer({ room }: MembersDrawerProps) {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Menu style={{ padding: config.space.S100 }}>
|
<Menu style={{ padding: config.space.S100 }}>
|
||||||
{sortFilterMenu.map((menuItem) => (
|
{sortFilterMenu.map((menuItem, index) => (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={menuItem.name}
|
key={menuItem.name}
|
||||||
variant="Surface"
|
variant="Surface"
|
||||||
aria-pressed={menuItem.name === filter.sortFilter.name}
|
aria-pressed={menuItem.name === sortFilter.name}
|
||||||
radii="300"
|
radii="300"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setFilter((f) => ({ ...f, sortFilter: menuItem }));
|
setSortFilterIndex(index);
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -392,7 +403,7 @@ export function MembersDrawer({ room }: MembersDrawerProps) {
|
||||||
radii="300"
|
radii="300"
|
||||||
after={<Icon src={Icons.Sort} size="50" />}
|
after={<Icon src={Icons.Sort} size="50" />}
|
||||||
>
|
>
|
||||||
<Text size="T200">{filter.sortFilter.name}</Text>
|
<Text size="T200">{sortFilter.name}</Text>
|
||||||
</Chip>
|
</Chip>
|
||||||
)}
|
)}
|
||||||
</PopOut>
|
</PopOut>
|
||||||
|
@ -452,7 +463,7 @@ export function MembersDrawer({ room }: MembersDrawerProps) {
|
||||||
|
|
||||||
{!fetchingMembers && !result && processMembers.length === 0 && (
|
{!fetchingMembers && !result && processMembers.length === 0 && (
|
||||||
<Text style={{ padding: config.space.S300 }} align="Center">
|
<Text style={{ padding: config.space.S300 }} align="Center">
|
||||||
{`No "${filter.membershipFilter.name}" Members`}
|
{`No "${membershipFilter.name}" Members`}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ export function RoomBaseView({ room, eventId }: RoomBaseViewProps) {
|
||||||
{screenSize === ScreenSize.Desktop && isDrawer && (
|
{screenSize === ScreenSize.Desktop && isDrawer && (
|
||||||
<>
|
<>
|
||||||
<Line variant="Background" direction="Vertical" size="300" />
|
<Line variant="Background" direction="Vertical" size="300" />
|
||||||
<MembersDrawer room={room} />
|
<MembersDrawer key={room.roomId} room={room} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -443,7 +443,7 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
|
||||||
)}
|
)}
|
||||||
{autocompleteQuery?.prefix === AutocompletePrefix.UserMention && (
|
{autocompleteQuery?.prefix === AutocompletePrefix.UserMention && (
|
||||||
<UserMentionAutocomplete
|
<UserMentionAutocomplete
|
||||||
roomId={roomId}
|
room={room}
|
||||||
editor={editor}
|
editor={editor}
|
||||||
query={autocompleteQuery}
|
query={autocompleteQuery}
|
||||||
requestClose={handleCloseAutocomplete}
|
requestClose={handleCloseAutocomplete}
|
||||||
|
|
|
@ -193,7 +193,7 @@ export const MessageEditor = as<'div', MessageEditorProps>(
|
||||||
)}
|
)}
|
||||||
{autocompleteQuery?.prefix === AutocompletePrefix.UserMention && (
|
{autocompleteQuery?.prefix === AutocompletePrefix.UserMention && (
|
||||||
<UserMentionAutocomplete
|
<UserMentionAutocomplete
|
||||||
roomId={roomId}
|
room={room}
|
||||||
editor={editor}
|
editor={editor}
|
||||||
query={autocompleteQuery}
|
query={autocompleteQuery}
|
||||||
requestClose={handleCloseAutocomplete}
|
requestClose={handleCloseAutocomplete}
|
||||||
|
|
|
@ -3,14 +3,16 @@ import { atom } from 'jotai';
|
||||||
const STORAGE_KEY = 'settings';
|
const STORAGE_KEY = 'settings';
|
||||||
export type MessageSpacing = '0' | '100' | '200' | '300' | '400' | '500';
|
export type MessageSpacing = '0' | '100' | '200' | '300' | '400' | '500';
|
||||||
export type MessageLayout = 0 | 1 | 2;
|
export type MessageLayout = 0 | 1 | 2;
|
||||||
|
|
||||||
export interface Settings {
|
export interface Settings {
|
||||||
themeIndex: number;
|
themeIndex: number;
|
||||||
useSystemTheme: boolean;
|
useSystemTheme: boolean;
|
||||||
isMarkdown: boolean;
|
isMarkdown: boolean;
|
||||||
editorToolbar: boolean;
|
editorToolbar: boolean;
|
||||||
isPeopleDrawer: boolean;
|
|
||||||
useSystemEmoji: boolean;
|
useSystemEmoji: boolean;
|
||||||
|
|
||||||
|
isPeopleDrawer: boolean;
|
||||||
|
memberSortFilterIndex: number;
|
||||||
enterForNewline: boolean;
|
enterForNewline: boolean;
|
||||||
messageLayout: MessageLayout;
|
messageLayout: MessageLayout;
|
||||||
messageSpacing: MessageSpacing;
|
messageSpacing: MessageSpacing;
|
||||||
|
@ -28,9 +30,10 @@ const defaultSettings: Settings = {
|
||||||
useSystemTheme: true,
|
useSystemTheme: true,
|
||||||
isMarkdown: true,
|
isMarkdown: true,
|
||||||
editorToolbar: false,
|
editorToolbar: false,
|
||||||
isPeopleDrawer: true,
|
|
||||||
useSystemEmoji: false,
|
useSystemEmoji: false,
|
||||||
|
|
||||||
|
isPeopleDrawer: true,
|
||||||
|
memberSortFilterIndex: 0,
|
||||||
enterForNewline: false,
|
enterForNewline: false,
|
||||||
messageLayout: 0,
|
messageLayout: 0,
|
||||||
messageSpacing: '400',
|
messageSpacing: '400',
|
||||||
|
|
|
@ -13,6 +13,7 @@ import {
|
||||||
NotificationCountType,
|
NotificationCountType,
|
||||||
RelationType,
|
RelationType,
|
||||||
Room,
|
Room,
|
||||||
|
RoomMember,
|
||||||
} from 'matrix-js-sdk';
|
} from 'matrix-js-sdk';
|
||||||
import { CryptoBackend } from 'matrix-js-sdk/lib/common-crypto/CryptoBackend';
|
import { CryptoBackend } from 'matrix-js-sdk/lib/common-crypto/CryptoBackend';
|
||||||
import { AccountDataEvent } from '../../types/matrix/accountData';
|
import { AccountDataEvent } from '../../types/matrix/accountData';
|
||||||
|
@ -293,6 +294,15 @@ export const getMemberDisplayName = (room: Room, userId: string): string | undef
|
||||||
return name;
|
return name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getMemberSearchStr = (
|
||||||
|
member: RoomMember,
|
||||||
|
query: string,
|
||||||
|
mxIdToName: (mxId: string) => string
|
||||||
|
): string[] => [
|
||||||
|
member.rawDisplayName === member.userId ? mxIdToName(member.userId) : member.rawDisplayName,
|
||||||
|
query.startsWith('@') || query.indexOf(':') > -1 ? member.userId : mxIdToName(member.userId),
|
||||||
|
];
|
||||||
|
|
||||||
export const getMemberAvatarMxc = (room: Room, userId: string): string | undefined => {
|
export const getMemberAvatarMxc = (room: Room, userId: string): string | undefined => {
|
||||||
const member = room.getMember(userId);
|
const member = room.getMember(userId);
|
||||||
return member?.getMxcAvatarUrl();
|
return member?.getMxcAvatarUrl();
|
||||||
|
|
Loading…
Reference in a new issue