Skip to content
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
65762c4
Switch sliding sync support to simplified sliding sync
dbkr Sep 12, 2024
2593998
Remove txn_id handling, ensure we always resend when req params change
kegsay Sep 13, 2024
6fba79c
Fix some tests
kegsay Sep 13, 2024
e26e926
Fix remaining tests
kegsay Sep 13, 2024
c75c06a
Mark TODOs on tests which need to die
kegsay Sep 13, 2024
7444094
Linting
kegsay Sep 13, 2024
bf7be48
Make comments lie less
kegsay Sep 13, 2024
ade2c86
void
kegsay Sep 13, 2024
b8c3419
Always sent full extension request
kegsay Sep 13, 2024
85400e9
Fix test
kegsay Sep 13, 2024
c44818f
Remove usage of deprecated field
kegsay Sep 13, 2024
aeeb25f
Hopefully fix DM names
kegsay Sep 13, 2024
244ca62
Refactor how heroes are handled in Room
kegsay Sep 16, 2024
bd3f9f7
Fix how heroes work
kegsay Sep 16, 2024
581b419
Linting
kegsay Sep 16, 2024
39b4e9d
Ensure that when SSS omits heroes we don't forget we had heroes
kegsay Sep 16, 2024
11e7a3d
Check the right flag when doing timeline trickling
kegsay Sep 16, 2024
511a873
Also change when the backpagination token is set
kegsay Sep 16, 2024
181d786
Remove list ops and server-provided sort positions
kegsay Sep 17, 2024
679a984
Linting
kegsay Sep 17, 2024
cf37e43
Add Room.bumpStamp
kegsay Sep 17, 2024
426aa93
Update crypto wasm lib
kegsay Sep 18, 2024
63a636f
Add performance logging
kegsay Sep 18, 2024
f8d4161
Fix breaking change in crypto wasm v8
kegsay Sep 18, 2024
1fd6675
Update crypto wasm for breaking changes
kegsay Sep 18, 2024
8616294
Mark all tracked users as dirty on expired SSS connections
kegsay Sep 18, 2024
3833273
Merge remote-tracking branch 'origin/develop' into dbkr/sss
dbkr Nov 21, 2024
8b7213b
add ts extension
dbkr Nov 21, 2024
c6f8440
Fix typedoc ref
dbkr Nov 21, 2024
336797e
Add method to interface
dbkr Nov 21, 2024
af846e7
Merge branch 'develop' into dbkr/sss
dbkr Dec 13, 2024
ec83c14
Don't force membership to invite
dbkr Dec 17, 2024
a75a263
Merge branch 'develop' into dbkr/sss
dbkr Feb 12, 2025
dec2cb0
Missed merge
dbkr Feb 12, 2025
1634b83
Type import
dbkr Feb 12, 2025
ebef4cd
Make coverage happier
dbkr Feb 12, 2025
ef87316
More test coverage
dbkr Feb 12, 2025
1dc3b4c
Merge branch 'develop' into dbkr/sss
dbkr Feb 17, 2025
f1d53cf
Grammar & formatting
dbkr Mar 6, 2025
4ece850
Remove markAllTrackedUsersAsDirty from crypto API
dbkr Mar 6, 2025
60f7bca
Remove I from interface
dbkr Mar 6, 2025
7954040
API doc
dbkr Mar 6, 2025
1d020df
Move Hero definition to room-summary
dbkr Mar 6, 2025
cc6ad7f
make comment more specific
dbkr Mar 6, 2025
e4527b5
Move internal details into room.ts
dbkr Mar 6, 2025
42099bb
Use terser arrow function syntax
dbkr Mar 7, 2025
38467e6
Move comment to where we do the lookup
dbkr Mar 6, 2025
ff25912
Clarify comment
dbkr Mar 7, 2025
26069c9
Add comment
dbkr Mar 7, 2025
de7c5ea
Add tsdoc
dbkr Mar 7, 2025
8a26967
more comment
dbkr Mar 7, 2025
a7d013f
Remove unrelated changes
dbkr Mar 7, 2025
7028a88
Add docs & make fields optional
dbkr Mar 7, 2025
ee0219e
Type import
dbkr Mar 7, 2025
eeffb20
Merge branch 'develop' into dbkr/sss
dbkr Mar 10, 2025
d55a9ea
Clarify sync versions
dbkr Mar 13, 2025
6ea801b
Make tsdoc comment & add info on when it's used.
dbkr Mar 13, 2025
5a30e34
Rephrase comment
dbkr Mar 13, 2025
8ca0c04
Prettier
dbkr Mar 13, 2025
7506df2
Only fetch member for hero in legacy sync mode
dbkr Mar 14, 2025
7d8aeee
Split out a separate method to set SSS room summary
dbkr Mar 14, 2025
54492a8
Type import
dbkr Mar 14, 2025
793ae01
Make link work
dbkr Mar 14, 2025
d793a10
Nope, linter treats it as an unused import
dbkr Mar 14, 2025
7cca95a
Add link the other way
dbkr Mar 14, 2025
085a2d4
Add more detail to doc
dbkr Mar 18, 2025
bd6ba39
Remove unnecessary cast
dbkr Mar 18, 2025
7e1eb16
Remove length > 0 check
dbkr Mar 18, 2025
5c44bbb
Doc params
dbkr Mar 18, 2025
5f0b2e3
Remove unnecessary undefined comparison
dbkr Mar 18, 2025
0030998
Put the comparison back
dbkr Mar 18, 2025
707a7f5
Fix comment
dbkr Mar 18, 2025
532d885
Fix comment
dbkr Mar 18, 2025
06b0fd4
Merge branch 'develop' into dbkr/sss
dbkr Mar 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/common-crypto/CryptoBackend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,9 @@ export interface SyncCryptoCallbacks {
onSyncCompleted(syncState: OnSyncCompletedData): void;

/**
* Mark all tracked user's device lists as dirty.
* Mark all tracked users' device lists as dirty.
*
* This method will cause additional /keys/query requests on the server, so should be used only
* This method will cause additional `/keys/query` requests on the server, so should be used only
* when the client has desynced tracking device list deltas from the server.
* In MSC4186: Simplified Sliding Sync, this can happen when the server expires the connection.
*/
Expand Down
6 changes: 0 additions & 6 deletions src/crypto-api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -418,12 +418,6 @@ export interface CryptoApi {
*/
getEncryptionInfoForEvent(event: MatrixEvent): Promise<EventEncryptionInfo | null>;

/**
* All users *whose device lists we are tracking* are flagged as needing a
* key query. Users whose devices we are not tracking are ignored.
*/
markAllTrackedUsersAsDirty(): Promise<void>;

/**
* Encrypts a given payload object via Olm to-device messages to a given
* set of devices.
Expand Down
39 changes: 37 additions & 2 deletions src/models/room-summary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,51 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import type { Hero } from "./room.ts";
/**
* A stripped m.room.member event which contains the key renderable fields from the event,
* sent only in simplified sliding sync (not sync v2).
*/
export type Hero = {
userId: string;
displayName?: string;
avatarUrl?: string;
};

/**
* High level summary information for a room
*/
export interface IRoomSummary {
/**
* The room heroes: a selected set of members that can be used when summarising or
* generating a name for a room. List of user IDs.
*/
"m.heroes": string[];
/**
* The number of joined members in the room.
*/
"m.joined_member_count"?: number;
/**
* The number of invited members in the room.
*/
"m.invited_member_count"?: number;
}
export interface IRoomSummaryMSC4186 {

/**
* High level summary information for a room (MSC4186 sliding sync)
*/
export interface RoomSummaryMSC4186 {
/**
* The room heroes: a selected set of members that can be used when summarising or
* generating a name for a room.
*/
"m.heroes": Hero[];
/**
* The number of joined members in the room.
*/
"m.joined_member_count"?: number;
/**
* The number of invited members in the room.
*/
"m.invited_member_count"?: number;
}

Expand Down
49 changes: 24 additions & 25 deletions src/models/room.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import {
} from "./event.ts";
import { EventStatus } from "./event-status.ts";
import { RoomMember } from "./room-member.ts";
import { type IRoomSummary, type IRoomSummaryMSC4186, RoomSummary } from "./room-summary.ts";
import { type IRoomSummary, type RoomSummaryMSC4186, type Hero, RoomSummary } from "./room-summary.ts";
import { logger } from "../logger.ts";
import { TypedReEmitter } from "../ReEmitter.ts";
import {
Expand Down Expand Up @@ -178,20 +178,6 @@ export type RoomEmittedEvents =
| BeaconEvent.LivenessChange
| PollEvent.New;

// A Hero is a stripped m.room.member event which contains the key renderable fields from the event.
// It is used in MSC4186 (Simplified Sliding Sync) as a replacement for the old 'summary' field.
// The old form simply contained the hero's user ID, which forced clients to then look up the
// m.room.member event in the current state. This is entirely decoupled in SSS. To ensure this
// works in a backwards compatible way, we will A) only set displayName/avatarUrl with server-provided
// values, B) always prefer the hero values if they are set, over calling `.getMember`. This means
// in SSS mode we will always use the heroes if they exist, but in sync v2 mode these fields will
// never be set and hence we will always do getMember lookups (at the right time as well).
export type Hero = {
userId: string;
displayName?: string;
avatarUrl?: string;
};

export type RoomEventHandlerMap = {
/**
* Fires when the logged in user's membership in the room is updated.
Expand Down Expand Up @@ -376,6 +362,8 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
// read by megolm via getter; boolean value - null indicates "use global value"
private blacklistUnverifiedDevices?: boolean;
private selfMembership?: Membership;
// A Hero is a stripped m.room.member event which contains the key renderable fields from the event.
// It is used in MSC4186 (Simplified Sliding Sync) as a replacement for the old 'summary' field.
private heroes: Hero[] | null = null;
// flags to stop logspam about missing m.room.create events
private getTypeWarning = false;
Expand Down Expand Up @@ -958,8 +946,15 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
const nonFunctionalHeroes = this.heroes?.filter((h) => !functionalMembers.includes(h.userId));
const hasHeroes = Array.isArray(nonFunctionalHeroes) && nonFunctionalHeroes.length;
if (hasHeroes) {
// use first hero which exists
// use first hero that has a display name or avatar url, or whose user ID
// can be looked up as a member of the room
for (const hero of nonFunctionalHeroes) {
// The old form of heroes simply contained the hero's user ID, which forced clients to then look up the
// m.room.member event in the current state. This is entirely decoupled in SSS. To ensure this
// works in a backwards compatible way, we will A) only set displayName/avatarUrl with server-provided
// values, B) always prefer the hero values if they are set, over calling `.getMember`. This means
// in SSS mode we will use the heroes if the display name or avatar URL fields are set, but in sync v2
// mode these fields will never be set and hence we will always do getMember lookups (at the right time as well).
if (!hero.displayName && !hero.avatarUrl) {
// attempt to look up renderable fields from the m.room.member event if it exists
const member = this.getMember(hero.userId);
Expand Down Expand Up @@ -1679,16 +1674,16 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
return this.setUnreadNotificationCount(type, count);
}

public setSummary(summary: IRoomSummary | IRoomSummaryMSC4186): void {
/**
* Takes either a legacy or MSC4186 room summary and updates the room with it.
* The summary will be converted to a legacy style summary in order to be emitted
* in the `RoomEvent.Summary` event.
*
* @param summary - The room summary to update the room with
*/
public setSummary(summary: IRoomSummary | RoomSummaryMSC4186): void {
// map heroes onto the MSC4186 form as that has more data
const heroes = summary["m.heroes"]?.map((h) => {
if (typeof h === "string") {
return {
userId: h,
};
}
return h;
});
const heroes = summary["m.heroes"]?.map((h) => (typeof h === "string" ? { userId: h } : h));
const joinedCount = summary["m.joined_member_count"];
const invitedCount = summary["m.invited_member_count"];
if (Number.isInteger(joinedCount)) {
Expand All @@ -1704,6 +1699,7 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
});
}

// Convert back to the legacy heroes format for the `RoomEvent.Summary` event.
summary["m.heroes"] = heroes?.map((h) => h.userId);

this.emit(RoomEvent.Summary, summary as IRoomSummary);
Expand Down Expand Up @@ -3540,6 +3536,9 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
inviteJoinCount--;
return;
}
// If the hero has a display name, use that.
// Otherwise, look their user ID up in the membership and use
// the name from there, or the user ID as a last resort.
if (hero.displayName) {
otherNames.push(hero.displayName);
} else {
Expand Down
3 changes: 0 additions & 3 deletions src/sliding-sync-sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,6 @@ export class SlidingSyncSdk {
}

private async onRoomData(roomId: string, roomData: MSC3575RoomData): Promise<void> {
const start = new Date().getTime();
let room = this.client.store.getRoom(roomId);
if (!room) {
if (!roomData.initial) {
Expand All @@ -393,7 +392,6 @@ export class SlidingSyncSdk {
room = _createAndReEmitRoom(this.client, roomId, this.opts);
}
await this.processRoomData(this.client, room!, roomData);
logger.log(`onRoomData ${roomId} took ${new Date().getTime() - start}ms`);
}

private onLifecycle(state: SlidingSyncState, resp: MSC3575SlidingSyncResponse | null, err?: Error): void {
Expand All @@ -402,7 +400,6 @@ export class SlidingSyncSdk {
}
switch (state) {
case SlidingSyncState.Complete:
logger.log(`SlidingSyncState.Complete with ${Object.keys(resp?.rooms || []).length} rooms`);
this.purgeNotifications();
if (!resp) {
break;
Expand Down
8 changes: 6 additions & 2 deletions src/sliding-sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,14 @@ export interface MSC3575SlidingSyncRequest {
clientTimeout?: number;
}

/**
* New format of hero introduced in MSC4186 with display name and avatar URL
* in addition to just user_id
*/
export interface MSC4186Hero {
user_id: string;
displayname: string;
avatar_url: string;
displayname?: string;
avatar_url?: string;
}

export interface MSC3575RoomData {
Expand Down