Skip to content

Commit 5edfc9a

Browse files
authored
Support searching autocomplete via nicknames (#1028)
<!-- Please read https://github.com/SableClient/Sable/blob/dev/CONTRIBUTING.md before submitting your pull request --> ### Description <!-- Please include a summary of the change. Please also include relevant motivation and context. List any dependencies that are required for this change. --> Fixes #1006 #### Type of change - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] This change requires a documentation update ### Checklist: - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings ### AI disclosure: - [ ] Partially AI assisted (clarify which code was AI assisted and briefly explain what it does). - [ ] Fully AI generated (explain what all the generated code does in moderate detail). <!-- Write any explanation required here, but do not generate the explanation using AI!! You must prove you understand what the code in this PR does. -->
2 parents faec72b + b5a922a commit 5edfc9a

5 files changed

Lines changed: 39 additions & 12 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
default: patch
3+
---
4+
5+
Add support for searching users via nicknames in the autocomplete menu.

src/app/components/editor/autocomplete/UserMentionAutocomplete.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { KeyboardEvent as ReactKeyboardEvent } from 'react';
2-
import { useEffect } from 'react';
2+
import { useCallback, useEffect } from 'react';
33
import type { Editor } from 'slate';
44
import { Avatar, MenuItem, Text } from 'folds';
55
import { userFallbackIcon } from '$components/icons/phosphor';
@@ -86,8 +86,6 @@ const SEARCH_OPTIONS: UseAsyncSearchOptions = {
8686
};
8787

8888
const mxIdToName = (mxId: string) => getMxIdLocalPart(mxId) ?? mxId;
89-
const getRoomMemberStr: SearchItemStrGetter<RoomMember> = (m, query) =>
90-
getMemberSearchStr(m, query, mxIdToName);
9189

9290
export function UserMentionAutocomplete({
9391
room,
@@ -102,6 +100,11 @@ export function UserMentionAutocomplete({
102100
const roomAliasOrId = room.getCanonicalAlias() || roomId;
103101
const members = useRoomMembers(mx, roomId);
104102

103+
const getRoomMemberStr = useCallback<SearchItemStrGetter<RoomMember>>(
104+
(m, searchQuery) => getMemberSearchStr(m, searchQuery, mxIdToName, nicknames),
105+
[nicknames]
106+
);
107+
105108
const [result, search, resetSearch] = useAsyncSearch(members, getRoomMemberStr, SEARCH_OPTIONS);
106109
const autoCompleteMembers = (result ? result.items.slice(0, 20) : members.slice(0, 20)).filter(
107110
withAllowedMembership

src/app/features/common-settings/members/Members.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ import { useFlattenPowerTagMembers, useGetMemberPowerTag } from '$hooks/useMembe
4242
import { useRoomCreators } from '$hooks/useRoomCreators';
4343
import { getMouseEventCords } from '$utils/dom';
4444
import { getMxIdServer } from '$utils/mxIdHelper';
45+
import { useAtomValue } from 'jotai';
46+
import { nicknamesAtom } from '$state/nicknames';
4547

4648
const SEARCH_OPTIONS: UseAsyncSearchOptions = {
4749
limit: 1000,
@@ -54,14 +56,13 @@ const SEARCH_OPTIONS: UseAsyncSearchOptions = {
5456
};
5557

5658
const mxIdToName = (mxId: string) => getMxIdLocalPart(mxId) ?? mxId;
57-
const getRoomMemberStr: SearchItemStrGetter<RoomMember> = (m, query) =>
58-
getMemberSearchStr(m, query, mxIdToName);
5959

6060
type MembersProps = {
6161
requestClose: () => void;
6262
};
6363
export function Members({ requestClose }: MembersProps) {
6464
const mx = useMatrixClient();
65+
const nicknames = useAtomValue(nicknamesAtom);
6566
const useAuthentication = useMediaAuthentication();
6667
const room = useRoom();
6768
const members = useRoomMembers(mx, room.roomId);
@@ -94,6 +95,11 @@ export function Members({ requestClose }: MembersProps) {
9495
[members, membershipFilter, memberSort, memberPowerSort]
9596
);
9697

98+
const getRoomMemberStr = useCallback<SearchItemStrGetter<RoomMember>>(
99+
(m, query) => getMemberSearchStr(m, query, mxIdToName, nicknames),
100+
[nicknames]
101+
);
102+
97103
const [result, search, resetSearch] = useAsyncSearch(
98104
sortedMembers,
99105
getRoomMemberStr,

src/app/features/room/MembersDrawer.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,15 +233,14 @@ const SEARCH_OPTIONS: UseAsyncSearchOptions = {
233233
};
234234

235235
const mxIdToName = (mxId: string) => getMxIdLocalPart(mxId) ?? mxId;
236-
const getRoomMemberStr: SearchItemStrGetter<RoomMember> = (m, query) =>
237-
getMemberSearchStr(m, query, mxIdToName);
238236

239237
type MembersDrawerProps = {
240238
room: Room;
241239
members: RoomMember[];
242240
};
243241
export function MembersDrawer({ room, members }: MembersDrawerProps) {
244242
const mx = useMatrixClient();
243+
const nicknames = useAtomValue(nicknamesAtom);
245244
const useAuthentication = useMediaAuthentication();
246245
const scrollRef = useRef<HTMLDivElement>(null);
247246
const searchInputRef = useRef<HTMLInputElement>(null);
@@ -273,6 +272,11 @@ export function MembersDrawer({ room, members }: MembersDrawerProps) {
273272
[members, membershipFilter, memberSort, memberPowerSort]
274273
);
275274

275+
const getRoomMemberStr = useCallback<SearchItemStrGetter<RoomMember>>(
276+
(m, query) => getMemberSearchStr(m, query, mxIdToName, nicknames),
277+
[nicknames]
278+
);
279+
276280
const [result, search, resetSearch] = useAsyncSearch(
277281
filteredMembers,
278282
getRoomMemberStr,

src/app/utils/room.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -595,11 +595,20 @@ export const getMemberDisplayName = (
595595
export const getMemberSearchStr = (
596596
member: RoomMember,
597597
query: string,
598-
mxIdToName: (mxId: string) => string
599-
): string[] => [
600-
member.rawDisplayName === member.userId ? mxIdToName(member.userId) : member.rawDisplayName,
601-
query.startsWith('@') || query.indexOf(':') > -1 ? member.userId : mxIdToName(member.userId),
602-
];
598+
mxIdToName: (mxId: string) => string,
599+
nicknames?: Record<string, string>
600+
): string[] => {
601+
const nickname = nicknames?.[member.userId];
602+
const displayName =
603+
member.rawDisplayName === member.userId ? mxIdToName(member.userId) : member.rawDisplayName;
604+
const idStr =
605+
query.startsWith('@') || query.indexOf(':') > -1 ? member.userId : mxIdToName(member.userId);
606+
607+
const strings: string[] = [];
608+
if (nickname) strings.push(nickname);
609+
strings.push(displayName, idStr);
610+
return strings;
611+
};
603612

604613
export const getMemberAvatarMxc = (room: Room, userId: string): string | undefined => {
605614
const member = room.getMember(userId);

0 commit comments

Comments
 (0)