Commit Graph
7 Commits
Author SHA1 Message Date
Quentin GliechandClaude Fable 5.1 1c8930daa0 Join the call as soon as a request to join is accepted
An invite that replaced a request to join was read as somebody else being
mid-join. Nobody always is: a host without auto-join, a join that failed, or
a fresh load already at that membership left the user waiting with nothing to
press but "Cancel request". The lobby now takes such an invite up itself,
showing a joining state, and offers a join of the user's own if that fails.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-09 22:44:59 +02:00
Quentin GliechandClaude Fable 5.1 d78c204ef4 Let the lobby ask its host for membership changes
Running as a widget, Element Call has no access token of its own, so a room
it is not in can only be entered by the host: the lobby ended at a
full-screen "Room not found" for every room the user had not already joined.

Membership changes now go through a `ChangeMembership` function, which the
host supplies when it keeps the access token to itself and Element Call
builds from its own client when it does not. Either way the answer is the
membership the request resulted in, which for the client is the one an
accepted request implies: local room state still holds the previous
membership until the next sync. The host takes an `io.element.membership`
action carrying `{action: "join" | "knock" | "cancel_knock", reason?}`. An
error reply carrying `matrix_api_error` is the homeserver's own refusal; one
without it means the host does not implement the action, which leaves the
lobby saying the user cannot get in this way. Element Call also asks to
receive `m.room.join_rules`, and reads the state event rather than
`Room.getJoinRule()`, since a host that grants no such capability is
otherwise indistinguishable from an invite-only room.

What the lobby opens on comes from our membership, the membership it
replaced and the join rule. A restricted or knock-restricted room offers a
join, because the widget cannot evaluate `allowed_room_ids` and the host can.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-09 22:44:59 +02:00
Quentin GliechandClaude Fable 5.1 3653a7fd05 Give the lobby a join state instead of an enter callback
`LobbyView` took `onEnter`, `enterLabel` and `waitingForInvite`, which cannot
express a declined, banned or invite-only room, so each of those ended at a
full-screen error and took the camera preview with it.

It now takes a `LobbyJoinState`, one of seven kinds, and renders both the
button and a message under the preview from it. `KnockLobbyView` passes
through what the loader offers, which is a single `lobby` state in place of
`canKnock` and `waitForInvite`, so a decline, a ban, or a room that takes
neither joins nor knocks keeps the user in the lobby. Waiting says what it is
waiting for and offers a way to withdraw the request.

The loader drives that state from the lobby's own callbacks rather than from
the load promise, so a refused request leaves the user where they were, and
every membership listener it adds is dropped when the effect is cleaned up.
What it knows of a room nobody has joined is a `PreJoinRoomInfo`, built from
a summary or from a `Room`, so a ban Element Call finds at load time is a
lobby state as well.

Denied and banned reuse the translated `group_call_loader.*` copy, so four
strings are new.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-09 22:44:59 +02:00
Quentin GliechandClaude Fable 5.1 1c8a6487e9 Remove the stray page.pause() calls from the Playwright specs
They halt a headless run until the inspector is closed, which never happens
in CI.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-09 22:44:59 +02:00
Quentin GliechandClaude Fable 5.1 1f7e930137 Name the button the room auth screen's licence caption points at
The caption said "Join call now"; the form's button reads "Continue".

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-09 22:44:59 +02:00
Quentin GliechandClaude Fable 5.1 a7fdade61a Tolerate a registration flow that carries no params
`registerRequest({})` rejects with the registration flows, and a homeserver
may answer with no `params` at all, which threw a TypeError on the landing
and login screens and left them without a privacy policy link.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-09 22:44:59 +02:00
Quentin GliechandClaude Fable 5.1 302f6f7efa Allow overriding the dev server TLS certificate via environment
EC_DEV_TLS_KEY / EC_DEV_TLS_CERT point vite at a key pair the developer's
browser already trusts, instead of the checked-in Element Call Dev CA.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-09 22:44:59 +02:00