From 655010844adcf45b1427a05a64d27409523e0d8d Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 18 May 2021 13:27:34 +0100 Subject: [PATCH 1/2] Switch to using QueryMatcher for add existing to space dialog This helps it support filtering by alias --- .../dialogs/AddExistingToSpaceDialog.tsx | 55 +++++++++++-------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx index af52fbce6c..faeaa80c15 100644 --- a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx +++ b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx @@ -38,6 +38,7 @@ import {sortRooms} from "../../../stores/room-list/algorithms/tag-sorting/Recent import ProgressBar from "../elements/ProgressBar"; import {SpaceFeedbackPrompt} from "../../structures/SpaceRoomView"; import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar"; +import QueryMatcher from "../../../autocomplete/QueryMatcher"; interface IProps extends IDialogProps { matrixClient: MatrixClient; @@ -74,37 +75,47 @@ export const AddExistingToSpace: React.FC = ({ onFinished, }) => { const cli = useContext(MatrixClientContext); - const visibleRooms = useMemo(() => sortRooms(cli.getVisibleRooms()), [cli]); + const visibleRooms = useMemo(() => cli.getVisibleRooms().filter(r => r.getMyMembership() === "join"), [cli]); const [selectedToAdd, setSelectedToAdd] = useState(new Set()); const [progress, setProgress] = useState(null); const [error, setError] = useState(null); const [query, setQuery] = useState(""); - const lcQuery = query.toLowerCase(); + const lcQuery = query.toLowerCase().trim(); - const existingSubspaces = SpaceStore.instance.getChildSpaces(space.roomId); - const existingSubspacesSet = new Set(existingSubspaces); - const existingRoomsSet = new Set(SpaceStore.instance.getChildRooms(space.roomId)); + const existingSubspacesSet = useMemo(() => new Set(SpaceStore.instance.getChildSpaces(space.roomId)), [space]); + const existingRoomsSet = useMemo(() => new Set(SpaceStore.instance.getChildRooms(space.roomId)), [space]); - const joinRule = space.getJoinRule(); - const [spaces, rooms, dms] = visibleRooms.reduce((arr, room) => { - if (room.getMyMembership() !== "join") return arr; - if (!room.name.toLowerCase().includes(lcQuery)) return arr; + const [spaces, rooms, dms] = useMemo(() => { + let rooms = visibleRooms; - if (room.isSpaceRoom()) { - if (room !== space && !existingSubspacesSet.has(room)) { - arr[0].push(room); - } - } else if (!existingRoomsSet.has(room)) { - if (!DMRoomMap.shared().getUserIdForRoomId(room.roomId)) { - arr[1].push(room); - } else if (joinRule !== "public") { - // Only show DMs for non-public spaces as they make very little sense in spaces other than "Just Me" ones. - arr[2].push(room); - } + if (lcQuery) { + const matcher = new QueryMatcher(visibleRooms, { + keys: ["name"], + funcs: [r => r.getCanonicalAlias() ?? r.getAltAliases()?.[0]], + shouldMatchWordsOnly: false, + }); + + rooms = matcher.match(lcQuery); } - return arr; - }, [[], [], []]); + + const joinRule = space.getJoinRule(); + return sortRooms(rooms).reduce((arr, room) => { + if (room.isSpaceRoom()) { + if (room !== space && !existingSubspacesSet.has(room)) { + arr[0].push(room); + } + } else if (!existingRoomsSet.has(room)) { + if (!DMRoomMap.shared().getUserIdForRoomId(room.roomId)) { + arr[1].push(room); + } else if (joinRule !== "public") { + // Only show DMs for non-public spaces as they make very little sense in spaces other than "Just Me" ones. + arr[2].push(room); + } + } + return arr; + }, [[], [], []]); + }, [visibleRooms, space, lcQuery, existingRoomsSet, existingSubspacesSet]); const addRooms = async () => { setError(null); From edb20267801fa7d20eb2a93ce092627e7c716649 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 18 May 2021 13:31:53 +0100 Subject: [PATCH 2/2] Support any alias not just first --- src/autocomplete/QueryMatcher.ts | 9 +++++++-- .../views/dialogs/AddExistingToSpaceDialog.tsx | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/autocomplete/QueryMatcher.ts b/src/autocomplete/QueryMatcher.ts index ea6e0882fd..73bb37ff0f 100644 --- a/src/autocomplete/QueryMatcher.ts +++ b/src/autocomplete/QueryMatcher.ts @@ -21,7 +21,7 @@ import {removeHiddenChars} from "matrix-js-sdk/src/utils"; interface IOptions { keys: Array; - funcs?: Array<(T) => string>; + funcs?: Array<(T) => string | string[]>; shouldMatchWordsOnly?: boolean; // whether to apply unhomoglyph and strip diacritics to fuzz up the search. Defaults to true fuzzy?: boolean; @@ -69,7 +69,12 @@ export default class QueryMatcher { if (this._options.funcs) { for (const f of this._options.funcs) { - keyValues.push(f(object)); + const v = f(object); + if (Array.isArray(v)) { + keyValues.push(...v); + } else { + keyValues.push(v); + } } } diff --git a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx index faeaa80c15..9a7f96e653 100644 --- a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx +++ b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx @@ -92,7 +92,7 @@ export const AddExistingToSpace: React.FC = ({ if (lcQuery) { const matcher = new QueryMatcher(visibleRooms, { keys: ["name"], - funcs: [r => r.getCanonicalAlias() ?? r.getAltAliases()?.[0]], + funcs: [r => [r.getCanonicalAlias(), ...r.getAltAliases()].filter(Boolean)], shouldMatchWordsOnly: false, });