-
Notifications
You must be signed in to change notification settings - Fork 128
Add sticky event support #3513
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add sticky event support #3513
Changes from 12 commits
4bfe5c5
2dcb823
f3abcb6
3ffaf33
1546c04
abcf300
6580555
b90bf7d
3337768
a9586fe
b34bee0
63be993
e523776
e0c0923
49d5a54
e313cf0
bd94e41
3e0e1cc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,7 +20,6 @@ import { | |
MatrixRTCSessionManagerEvents, | ||
type MatrixRTCSession, | ||
} from "matrix-js-sdk/lib/matrixrtc"; | ||
import { logger } from "matrix-js-sdk/lib/logger"; | ||
|
||
import { getKeyForRoom } from "../e2ee/sharedKeyManagement"; | ||
|
||
|
@@ -114,19 +113,49 @@ const roomIsJoinable = (room: Room): boolean => { | |
} | ||
}; | ||
|
||
/** | ||
* Determines if a given room has call events in it, and therefore | ||
* is likely to be a call room. | ||
* @param room The Matrix room instance. | ||
* @returns `true` if the room has call events. | ||
*/ | ||
const roomHasCallMembershipEvents = (room: Room): boolean => { | ||
switch (room.getMyMembership()) { | ||
case KnownMembership.Join: | ||
return !!room | ||
.getLiveTimeline() | ||
.getState(EventTimeline.FORWARDS) | ||
?.events?.get(EventType.GroupCallMemberPrefix); | ||
case KnownMembership.Knock: | ||
// Assume that a room you've knocked on is able to hold calls | ||
// Check our room membership first, to rule out any rooms | ||
// we can't have a call in. | ||
const myMembership = room.getMyMembership(); | ||
if (myMembership === KnownMembership.Knock) { | ||
// Assume that a room you've knocked on is able to hold calls | ||
return true; | ||
} else if (myMembership !== KnownMembership.Join) { | ||
// Otherwise, non-joined rooms should never show up. | ||
return false; | ||
} | ||
|
||
// Legacy member state checks (cheaper to check.) | ||
const timeline = room.getLiveTimeline(); | ||
if ( | ||
timeline | ||
.getState(EventTimeline.FORWARDS) | ||
?.events?.has(EventType.GroupCallMemberPrefix) | ||
) { | ||
return true; | ||
} | ||
|
||
// Check for *active* calls using sticky events. | ||
for (const sticky of room._unstable_getStickyEvents()) { | ||
if (sticky.getType() === EventType.GroupCallMemberPrefix) { | ||
return true; | ||
default: | ||
return false; | ||
} | ||
} | ||
|
||
// Otherwise, check recent event history to see if anyone had | ||
// sent a call membership in here. | ||
return timeline.getEvents().some( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no API to get the sticky events? Having the sticky key doesn't make the event sticky. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is this method exactly? Try some heuristic to see if a room is a call room? like Or if there might be an active call? |
||
(e) => | ||
// Membership events only count if both of these are true | ||
e.unstableStickyInfo && e.getType() === EventType.GroupCallMemberPrefix, | ||
); | ||
// Otherwise, it's *unlikely* this room was ever a call. | ||
}; | ||
|
||
export function useGroupCallRooms(client: MatrixClient): GroupCallRoom[] { | ||
|
@@ -140,24 +169,22 @@ export function useGroupCallRooms(client: MatrixClient): GroupCallRoom[] { | |
.filter(roomHasCallMembershipEvents) | ||
.filter(roomIsJoinable); | ||
const sortedRooms = sortRooms(client, rooms); | ||
Promise.all( | ||
sortedRooms.map((room) => { | ||
const session = client.matrixRTC.getRoomSession(room); | ||
return { | ||
roomAlias: room.getCanonicalAlias() ?? undefined, | ||
roomName: room.name, | ||
avatarUrl: room.getMxcAvatarUrl()!, | ||
room, | ||
session, | ||
participants: session.memberships | ||
.filter((m) => m.userId) | ||
.map((m) => room.getMember(m.userId!)) | ||
.filter((m) => m) as RoomMember[], | ||
}; | ||
}), | ||
) | ||
.then((items) => setRooms(items)) | ||
.catch(logger.error); | ||
const items = sortedRooms.map((room) => { | ||
const session = client.matrixRTC.getRoomSession(room); | ||
return { | ||
roomAlias: room.getCanonicalAlias() ?? undefined, | ||
roomName: room.name, | ||
avatarUrl: room.getMxcAvatarUrl()!, | ||
room, | ||
session, | ||
participants: session.memberships | ||
.filter((m) => m.sender) | ||
.map((m) => room.getMember(m.sender!)) | ||
.filter((m) => m) as RoomMember[], | ||
}; | ||
}); | ||
|
||
setRooms(items); | ||
} | ||
|
||
updateRooms(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,7 @@ import { ElementWidgetActions, widget, type WidgetHelpers } from "./widget"; | |
import { MatrixRTCTransportMissingError } from "./utils/errors"; | ||
import { getUrlParams } from "./UrlParams"; | ||
import { getSFUConfigWithOpenID } from "./livekit/openIDSFU.ts"; | ||
import { preferStickyEvents } from "./settings/settings.ts"; | ||
|
||
const FOCI_WK_KEY = "org.matrix.msc4143.rtc_foci"; | ||
|
||
|
@@ -118,14 +119,12 @@ export async function enterRTCSession( | |
transport: LivekitTransport, | ||
options: EnterRTCSessionOptions = { | ||
encryptMedia: true, | ||
useNewMembershipManager: true, | ||
useExperimentalToDeviceTransport: false, | ||
useMultiSfu: true, | ||
}, | ||
): Promise<void> { | ||
const { | ||
encryptMedia, | ||
useNewMembershipManager = true, | ||
useExperimentalToDeviceTransport = false, | ||
useMultiSfu = true, | ||
} = options; | ||
|
@@ -148,7 +147,6 @@ export async function enterRTCSession( | |
{ | ||
notificationType, | ||
callIntent, | ||
useNewMembershipManager, | ||
manageMediaKeys: encryptMedia, | ||
...(useDeviceSessionMemberEvents !== undefined && { | ||
useLegacyMemberEvents: !useDeviceSessionMemberEvents, | ||
|
@@ -164,6 +162,7 @@ export async function enterRTCSession( | |
membershipEventExpiryMs: | ||
matrixRtcSessionConfig?.membership_event_expiry_ms, | ||
useExperimentalToDeviceTransport, | ||
unstableSendStickyEvents: preferStickyEvents.getValue(), | ||
|
||
}, | ||
); | ||
if (widget) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Presumably we should refer to
RTCMembership
here rather thanGroupCallMemberPrefix
(though TBH we could probably replace this entire function body withreturn true;
and it would be fine… we're definitely not aiming to support using the SPA in cases where the homeserver is also used by messenger apps… well, maybe we are with the guest access use case, but I don't think we'll care about giving guest access users a home page at all.)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
100%.
Lets keep the function in for now. There might be some use for it in the guest case and it is very detangled from the rest of element-call -> not complexifying the codebase. (just makes it larger)