Syncs the fork from upstream v0.25.0 to v0.28.0 (196 upstream commits;
v0.27 was skipped upstream), bringing matrix-js-sdk develop up to the
SDK 44 MatrixRTC changes (livekit_alias / oldest_membership removed),
delayed-leave delegation to the SFU, and the HostBridge host interface.
Lotus changes carried across the refactors:
- widget: upstream no longer exports a widget singleton (initializer hands
initializeWidget()'s result to React). The Lotus host integration
(src/lotus/*) reads `widget` at call time, so a Lotus-only exported
reference is set by initializeWidget.
- useTheme: theme classes now go on the root element (the body in the
widget build); the lotusTheme / lotusTransparent / lotusHostControls
classes follow it.
- LocalMember: [lotus #46] keep retrying network errors until the delayed
leave would fire (Math.max), on upstream's restructured timings.
- UrlConfiguration moved to its own file; autoGainControl moved with it.
- errors: upstream switched to i18n.t; SFUTokenRefusedError follows.
- keyboard shortcuts: Lotus host hotkeys still win over focusIsClaimed().
- GroupCallErrorBoundary: the reconnect handler uses the widget reference
(upstream dropped the widget prop).
Config: v0.26 renamed matrix_rtc_session.delayed_leave_event_* to
delayed_leave.{delay_ms,restart_ms,restart_timeout_ms} with no fallback,
and the embedded build no longer emits a config.json. The production
config (public/element-call/config.json on LXC 106, not in git) must move
to the new keys when this ships, or calls lose the 60 s grace (lotus #46).
Embedded version 0.28.0-lotus.1.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
* Give the microphone level its own observable
* Add a microphone level meter
* Show speakers and microphones in the quick audio menu
* Wire speaker selection through the call footer
* Add stories for the meter and the device menu
* Add end-to-end specs for the quick audio menu
* Keep the footer while a menu opened from it is open
* Use the shared audio capture stub in the lobby test
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
"Failed to connect to Livekit server (Reason: ServerUnreachable)" left a
user with nothing to try; they retried for a long time and gave up.
- Title "Couldn't connect to voice". The message depends on the reason:
unreachable/timeout-style errors explain that voice needs its own live
connection, which VPNs, antivirus web shields and some networks block,
even when chat works, and say what to try; NotAllowed says the call may
be full or access changed.
- The raw reason, status and message move under Technical details.
- LivekitConnectionError and PeerConnectionTimeoutError now get a
Try again button (the existing reconnect path), shown as primary: the
Lotus theme renders `secondary` as dark-on-dark.
Verified in the Lotus client against a local LiveKit with the signal
socket and validate request blocked: the dialog appears after ~20 s;
unblocking and pressing Try again joins with the mic published.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
When the voice-limit guard (or any JWT service) answers 403 with a reason —
"This voice channel is full.", "You don't have permission to …" — EC wrapped it
in FailToGetOpenIdToken and the user saw the generic error page with
OPEN_ID_ERROR. A 403 MatrixError with a non-empty `error` now throws
SFUTokenRefusedError ("Can't join this call" + the server's sentence), so the
reason is the description. Other failures are unchanged. Unit-tested.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
toggleScreenSharing only had `.catch(logger.error)`, so a getDisplayMedia
request that hangs (element-call-rageshakes#17152: Element Desktop on
Windows, the user pressed the screen share button 14 times in 25 seconds
and the log shows nothing but the toggle lines and livekit-client's
"waiting for pending publication promise timed out") left the user with
a button that does nothing and us with no evidence of why.
Log when a toggle is requested and when it completes or fails, with the
elapsed time, so a hang is visible in the logs. Explicit failures other
than the user cancelling the picker show as a non-modal "Could not start
screen sharing" toast. Nothing is inferred from a toggle taking a long
time: the user may simply be choosing what to share.
This is the mode in which we sent membership events with the 'oldest membership' transport selection algorithm, which stopped being the default back in version 0.21.0. Users will no longer be able to select this mode in developer settings, and admins will no longer be able to select legacy mode through the config either. The app will still continue to support *receiving* membership events with the 'oldest membership' transport selection algorithm from others, however.
Run `yarn i18n` to extract new translation keys for the media quality
settings, and update the DeveloperSettingsTab snapshot to include the
Camera quality, Screen sharing, and Audio processing sections.
once)
The local jwt token needs to be aquired via the right endpoint. The
endpoint defines how our rtcBackendIdentity is computed. Based on us
using sticky events or state events we also need to use the right
endpoint. This cannot be done generically in the connection manager. The
jwt token now is computed in the localTransport and the resolved sfu
config is passed to the connection manager.
Add JWT endpoint version and SFU config support Pin matrix-js-sdk to a
specific commit and update dev auth image tag. Propagate SFU config and
JWT endpoint choice through local transport, ConnectionManager and
Connection; add JwtEndpointVersion enum and LocalTransportWithSFUConfig
type. Add NO_MATRIX_2 auth error and locale string, thread
rtcBackendIdentity through UI props, and include related test, CSS and
minor imports updates
- Replace MatrixLivekitItem with MatrixLivekitMember, add displayName$
and participantId, and use explicit LiveKit participant types
- Make sessionBehaviors$ accept a props object and return a typed
RxRtcSession
- Update CallViewModel to use the new session behaviors, rebuild media
items from matrixLivekitMembers, handle missing connections and use
participantId-based keys
- Change localMembership/localTransport to accept Behavior-based
options, read options.value for enterRTCSession, and fix advertised
transport selection order
- Update tests and minor UI adjustments (settings modal livekitRooms
stubbed) and fix JSON formatting in locales
Remove preferStickyEvents and multiSfu in favor of a MatrixRTCMode
enum/setting (Legacy, Compatibil, Matrix_2_0). Move session join/leave,
track pause/resume, and config error handling out of CallViewModel into
the localMembership module. Update developer settings UI, i18n strings,
and related RTC session helpers and wiring accordingly.
* add sticky event support
- use new js-sdk
- use custom synapse
- don't filter rooms by existing call state events
Signed-off-by: Timo K <toger5@hotmail.de>
* enable sticky events in the joinSessionConfig
Signed-off-by: Timo K <toger5@hotmail.de>
* Remove unused useNewMembershipmanager setting
* Add prefer sticky setting]
* Fixup call detection logic to allow sticky events
* lint
* update docker image
* More tidy
* update checksum
* bump js-sdk fix sticky events type
Signed-off-by: Timo K <toger5@hotmail.de>
* fix demo
Signed-off-by: Timo K <toger5@hotmail.de>
* always use multi sfu if we are using sticky events.
Signed-off-by: Timo K <toger5@hotmail.de>
* review
Signed-off-by: Timo K <toger5@hotmail.de>
* lint
Signed-off-by: Timo K <toger5@hotmail.de>
* Always consider multi-SFU mode enabled when using sticky events
CallViewModel would pass the wrong transport to enterRtcSession when the user enabled sticky events but didn't manually enable multi-SFU mode as well. This likely would've added some confusion to our attempts to test these modes.
* Fix test type errors
* add todo comment
Signed-off-by: Timo K <toger5@hotmail.de>
---------
Signed-off-by: Timo K <toger5@hotmail.de>
Co-authored-by: Half-Shot <will@half-shot.uk>
Co-authored-by: Robin <robin@robin.town>