Implement MSC3575: Sliding Sync (#8328)

* Add labs flag for sliding sync; add sliding_sync_proxy_url to config.json

* Disable the labs toggle if sliding_sync_proxy_url is not set

* Do validation checks on the sliding sync proxy URL before enabling it in Labs

* Enable sliding sync and add SlidingSyncManager

* Get room subscriptions working

* Hijack renderSublists in sliding sync mode

* Add support for sorting alphabetically/recency and room name filters

* Filter out tombstoned rooms; start adding show more logic

list ranges update but the UI doesn't

* update the UI when the list is updated

* bugfix: make sure the list sorts numerically

* Get invites transitioning correctly

* Force enable sliding sync and labs for now

* Linting

* Disable spotlight search

* Initial cypress plugins for Sliding Sync Proxy

* Use --rm when running Synapse in Docker for Cypress tests

* Update src/MatrixClientPeg.ts

Co-authored-by: Travis Ralston <travisr@matrix.org>

* Update src/components/views/rooms/RoomSublist.tsx

Co-authored-by: Travis Ralston <travisr@matrix.org>

* Update src/settings/controllers/SlidingSyncController.ts

Co-authored-by: Travis Ralston <travisr@matrix.org>

* Update src/components/views/rooms/RoomSublist.tsx

Co-authored-by: Travis Ralston <travisr@matrix.org>

* WIP add room searching to spotlight search

* Only read sliding sync results when there is a result, else use the local cache

* Use feature_sliding_sync not slidingSync

* Some review comments

* More review comments

* Use RoomViewStore to set room subscriptions

* Comment why any

* Update src/components/views/rooms/RoomSublist.tsx

Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>

* Fix cypress docker abstraction

* Iterate sliding sync proxy support

* Stash mostly functional test

* Update sliding sync proxy image

* i18n

* Add support for spaces; use list ID -> index mappings

- Mappings are more reusable and easier to understand than
  racing for index positions.
- Register for all spaces immediately on startup.

* When the active space is updated, update the list registration

* Set spaces filter in the correct place

* Skeleton placeholder whilst loading the space

* Filter out spaces from the room list

* Use the new txn_id promises

* Ensure we actually resolve list registrations

* Fix matrix-org/sliding-sync#30: don't show tombstoned search results

* Remove unused imports

* Add SYNCV3_SECRET to proxy to ensure it starts up; correct aliases for SS test

* Add another basic sliding sync e2e test

* Unbreak netlify

* Add more logging for debugging duplicate rooms

* If sliding sync is enabled, always use the rooms result even if it's empty

* Drop-in copy of RoomListStore for sliding sync

* Remove conditionals from RoomListStore - we have SlidingRoomListStore now

* WIP SlidingRoomListStore

* Add most sliding sync logic to SlidingRoomListStore

Still lots of logic in RoomSublist. Broken things:
 - Join count is wrong completely.
 - No skeleton placeholder when switching spaces.

* Migrate joined count to SS RLS

* Reinstate the skeleton UI when the list is loading

* linting

* Add support for sticky rooms based on the currently active room

* Add a bunch of passing SS E2E tests; some WIP

* Unbreak build from git merge

* Suppress unread indicators in sliding sync mode

* Add regression test for https://github.com/matrix-org/sliding-sync/issues/28

* Add invite test flows; show the invite list

The refactor to SS RLS removed the invite list entirely.

* Remove show more click as it wasn't the bug

* Linting and i18n

* only enable SS by default on netlify

* Jest fixes; merge conflict fixes; remove debug logging; use right sort enum values

* Actually fix jest tests

* Add support for favourites and low priority

* Bump sliding sync version

* Update sliding sync labs to be user configurable

* delint

* To disable SS or change proxy URL the user has to log out

* Review comments

* Linting

* Apply suggestions from code review

Co-authored-by: Travis Ralston <travisr@matrix.org>

* Update src/stores/room-list/SlidingRoomListStore.ts

Co-authored-by: Travis Ralston <travisr@matrix.org>

* Review comments

* Add issue link for TODO markers

* Linting

* Apply suggestions from code review

Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>

* More review comments

* More review comments

* stricter types

Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
Co-authored-by: Travis Ralston <travisr@matrix.org>
This commit is contained in:
kegsay 2022-09-07 16:42:39 +01:00 committed by GitHub
parent 5bdae150fa
commit a215027c6b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 1632 additions and 51 deletions

View file

@ -92,6 +92,7 @@ import { RoomResultContextMenus } from "./RoomResultContextMenus";
import { RoomContextDetails } from "../../rooms/RoomContextDetails";
import { TooltipOption } from "./TooltipOption";
import { isLocalRoom } from "../../../../utils/localRoom/isLocalRoom";
import { useSlidingSyncRoomSearch } from "../../../../hooks/useSlidingSyncRoomSearch";
const MAX_RECENT_SEARCHES = 10;
const SECTION_LIMIT = 50; // only show 50 results per section for performance reasons
@ -242,7 +243,7 @@ export const useWebSearchMetrics = (numResults: number, queryLength: number, via
}, [numResults, queryLength, viaSpotlight]);
};
const findVisibleRooms = (cli: MatrixClient) => {
const findVisibleRooms = (cli: MatrixClient): Room[] => {
return cli.getVisibleRooms().filter(room => {
// Do not show local rooms
if (isLocalRoom(room)) return false;
@ -340,25 +341,43 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", initialFilter = n
searchProfileInfo,
searchParams,
);
const isSlidingSyncEnabled = SettingsStore.getValue("feature_sliding_sync");
let {
loading: slidingSyncRoomSearchLoading,
rooms: slidingSyncRooms,
search: searchRoomsServerside,
} = useSlidingSyncRoomSearch();
useDebouncedCallback(isSlidingSyncEnabled, searchRoomsServerside, searchParams);
if (!isSlidingSyncEnabled) {
slidingSyncRoomSearchLoading = false;
}
const possibleResults = useMemo<Result[]>(
() => {
const roomResults = findVisibleRooms(cli).map(toRoomResult);
// If we already have a DM with the user we're looking for, we will
// show that DM instead of the user themselves
const alreadyAddedUserIds = roomResults.reduce((userIds, result) => {
const userId = DMRoomMap.shared().getUserIdForRoomId(result.room.roomId);
if (!userId) return userIds;
if (result.room.getJoinedMemberCount() > 2) return userIds;
userIds.add(userId);
return userIds;
}, new Set<string>());
const userResults = [];
for (const user of [...findVisibleRoomMembers(cli), ...users]) {
// Make sure we don't have any user more than once
if (alreadyAddedUserIds.has(user.userId)) continue;
alreadyAddedUserIds.add(user.userId);
const userResults: IMemberResult[] = [];
let roomResults: IRoomResult[];
let alreadyAddedUserIds: Set<string>;
if (isSlidingSyncEnabled) {
// use the rooms sliding sync returned as the server has already worked it out for us
roomResults = slidingSyncRooms.map(toRoomResult);
} else {
roomResults = findVisibleRooms(cli).map(toRoomResult);
// If we already have a DM with the user we're looking for, we will
// show that DM instead of the user themselves
alreadyAddedUserIds = roomResults.reduce((userIds, result) => {
const userId = DMRoomMap.shared().getUserIdForRoomId(result.room.roomId);
if (!userId) return userIds;
if (result.room.getJoinedMemberCount() > 2) return userIds;
userIds.add(userId);
return userIds;
}, new Set<string>());
for (const user of [...findVisibleRoomMembers(cli), ...users]) {
// Make sure we don't have any user more than once
if (alreadyAddedUserIds.has(user.userId)) continue;
alreadyAddedUserIds.add(user.userId);
userResults.push(toMemberResult(user));
userResults.push(toMemberResult(user));
}
}
return [
@ -382,7 +401,7 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", initialFilter = n
...publicRooms.map(toPublicRoomResult),
].filter(result => filter === null || result.filter.includes(filter));
},
[cli, users, profile, publicRooms, filter],
[cli, users, profile, publicRooms, slidingSyncRooms, isSlidingSyncEnabled, filter],
);
const results = useMemo<Record<Section, Result[]>>(() => {
@ -401,10 +420,13 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", initialFilter = n
possibleResults.forEach(entry => {
if (isRoomResult(entry)) {
if (!entry.room.normalizedName?.includes(normalizedQuery) &&
!entry.room.getCanonicalAlias()?.toLowerCase().includes(lcQuery) &&
!entry.query?.some(q => q.includes(lcQuery))
) return; // bail, does not match query
// sliding sync gives the correct rooms in the list so we don't need to filter
if (!isSlidingSyncEnabled) {
if (!entry.room.normalizedName?.includes(normalizedQuery) &&
!entry.room.getCanonicalAlias()?.toLowerCase().includes(lcQuery) &&
!entry.query?.some(q => q.includes(lcQuery))
) return; // bail, does not match query
}
} else if (isMemberResult(entry)) {
if (!entry.query?.some(q => q.includes(lcQuery))) return; // bail, does not match query
} else if (isPublicRoomResult(entry)) {
@ -455,7 +477,7 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", initialFilter = n
}
return results;
}, [trimmedQuery, filter, cli, possibleResults, memberComparator]);
}, [trimmedQuery, filter, cli, possibleResults, isSlidingSyncEnabled, memberComparator]);
const numResults = sum(Object.values(results).map(it => it.length));
useWebSearchMetrics(numResults, query.length, true);
@ -1208,7 +1230,7 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", initialFilter = n
aria-label={_t("Search")}
aria-describedby="mx_SpotlightDialog_keyboardPrompt"
/>
{ (publicRoomsLoading || peopleLoading || profileLoading) && (
{ (publicRoomsLoading || peopleLoading || profileLoading || slidingSyncRoomSearchLoading) && (
<Spinner w={24} h={24} />
) }
</div>