1
0
mirror of https://github.com/element-hq/element-web.git synced 2026-10-24 23:19:26 +03:00

321 Commits

Author SHA1 Message Date
renovate[bot]
2a939f7bf8 Update testcontainers docker digests (#35520)
* Update testcontainers docker digests

* Enable Synapse url previews in playwright

Due to Synapse config defaults change

* Fix explicit mentions playwright tests

Due to Synapse config defaults change

* Update playwright screenshots

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2026-10-23 19:49:29 +00:00
Skye Elliot
df9d6798d0 Allow generating a recovery key when logging out and this is the last device (#35401)
* feat(web): add a success style to `EncryptionCard`

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(web): generate the recovery key inside the logout dialog

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(web): cover generating the recovery key inside the logout dialog

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore: Group translations under settings|encryption|recovery

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 12:12:45 +00:00
Johannes Marbach
fc4d45cce1 Keep opening voice-only calls in PiP when the lobby is skipped (#35495)
* Keep opening voice-only calls in PiP when the lobby is skipped

* Ignore Vitest's console-log teardown race in unit test runs

Vitest intermittently fails a run where every test passed with 'Closing rpc while "onUserConsoleLog" was pending'
(vitest-dev/vitest#11153).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Revert "Ignore Vitest's console-log teardown race in unit test runs"

This reverts commit 0c1084c6a4.

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 18:49:34 +00:00
Michael Telatynski
b64db9894b Fix another merge conflict issue 2026-10-16 15:28:24 +01:00
RiotRobot
2a21153a3a Merge remote-tracking branch 'origin/master' into develop
# Conflicts:
#	apps/web/package.json
#	apps/web/playwright/e2e/crypto/toasts.spec.ts
#	apps/web/src/Lifecycle.ts
#	apps/web/src/components/structures/auth/CompleteSecurity.test.tsx
#	pnpm-lock.yaml
2026-10-16 13:18:58 +00:00
ElementRobot
d4d201782f Fix crash when preview room is under the fold (#35490) (#35500)
Co-authored-by: Florian Duros <florianduros@element.io>
2026-10-16 14:03:26 +01:00
Florian Duros
440079b599 Fix crash when preview room is under the fold (#35490)
* Fix crash when previewed room is under the fold

* Cast visibility type to avoid ts-ignore
2026-10-16 11:19:07 +00:00
renovate[bot]
3bddaab412 Update react (#35348)
* Update react

* Update patch

* Fix test

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2026-10-16 09:53:13 +00:00
Richard van der Hoff
fc4c0390ff Copy changes for "set up recovery" (#35437)
* Update "your chats are backed up" copy

... in the Settings dialog (RecoveryPanel), and the "set up recovery" toast.

* Change labels on "set up recovery" UI

* Add help text to 'Allow key storage' toggle

* update playwright snapshots
2026-10-15 23:01:37 +00:00
Matthew Hodgson
da1ef31b68 Open a call that is already in progress maximised, even for voice (#35443)
The header's Join button for a voice call went through the voice-call
PiP shortcut, so (outside DMs, where Element Call skips the lobby) the
user landed in a lobby inside a PiP. Only starting a voice call should
open in PiP; joining one in progress opens it maximised like video.
2026-10-15 14:45:31 +00:00
Michael Telatynski
ad9c1ccffb Deflake more tests (#35472)
* Fix mock route race condition in playwright test

Fixes https://github.com/element-hq/element-web/issues/34942

* Fix axe racing with button being enabled in playwright test

Fixes https://github.com/element-hq/element-web/issues/31919

* Fix race condition in audio player test

Fixes https://github.com/element-hq/element-web/issues/27760

* Fix slow favicon vitest test

Preload base image
2026-10-15 07:56:51 +00:00
Milton Moura
db69764acd Fix PiP dragger when displaying over widgets (#35395)
Signed-off-by: Milton Moura <milton.moura@nordeck.net>
Co-authored-by: Milton Moura <milton.moura@nordeck.net>
2026-10-14 13:53:28 +00:00
Michael Telatynski
b39d7266fa Fix dangling promises in test files (#35462)
* Fix floating promises in test files

Enables typescript/no-floating-promises

Fixes https://github.com/element-hq/element-web/issues/35300

* Fix flaky url preview test due to expecting old class names
2026-10-14 13:28:12 +00:00
Michael Telatynski
206e7a7ea4 Fix some flaky Playwright tests (#35337)
* Fix race condition in routing

The cached value was written back asynchronously so doing A->B->A quickly enough would skip the last transition.

Fixes https://github.com/element-hq/element-web/issues/29795

* Fix testcontainers logs not being attached in certain cases

* Fix race with MAS-issued tokens not being immediately accepted by Synapse

* Fix race condition with logging back in too quickly whilst logout has not finished

Fixes https://github.com/element-hq/element-web/issues/30153
Fixes https://github.com/element-hq/element-web/issues/31316

* Iterate

* Iterate

* Iterate
2026-10-14 12:44:04 +00:00
Skye Elliot
d514d6ddb8 Use a dialog to prompt the user about their recovery key when logging out (#35398)
* fix(web): match logout confirmation copy to new design

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Skye Elliot <actuallyori@gmail.com>

* refactor(web): let `LogoutDialog` open any encryption settings state

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(web): warn about recovery key when removing the only device

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Skye Elliot <actuallyori@gmail.com>

* test(web): cover recovery key warning when removing the only device

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Skye Elliot <actuallyori@gmail.com>

* fixup! refactor(web): let `LogoutDialog` open any encryption settings state

---------

Signed-off-by: Skye Elliot <actuallyori@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 15:08:26 +00:00
Richard van der Hoff
5455765fe5 Remove introductory screen from "create recovery key" flow (#35451)
* Remove introductory screen from "create recovery key" flow.

Between them, https://github.com/element-hq/element-meta/issues/3188 and
https://github.com/element-hq/element-meta/issues/3185 move all the information
about "what is a recovery key" into the toasts and modals that lead into the
"create recovery key" flow, thus making the introductory screen redundant.

Fixes https://github.com/element-hq/element-web/issues/35428

* update broken vitest

* playwright: Move body of `enableKeyBackup` into a `step`

... to make the logs a bit clearer

* Fix broken playwright tests
2026-10-13 14:32:33 +00:00
Michael Telatynski
6d8ff234e2 Fix playwright flaky tests (#35453)
* Fix edge case in edit history dialog

Where an edit happens while the dialog is opened and the event content is overwritten.

Fixes https://github.com/element-hq/element-web/issues/34399

* Fix test race condition with RTE

Fixes https://github.com/element-hq/element-web/issues/33663

* Fix race condition in tests around toasts

Fixes https://github.com/element-hq/element-web/issues/27804
2026-10-13 14:16:26 +00:00
rbondesson
bbe8b076b4 Support informational message and sender profile hints for custom renderers (#35371)
* Extend the module api hints with renderAsInformationalMessage and renderSenderProfile

* Use the new render hints in EventTiles and MainGrouper

* Update tests

* Use datatestid tags in playwritgh tests

* Fix playwright tests

* Better documentation and updated test

* Add renderGroupSummary to module api

* Merge custom group summaries with existing

* Add tests for custom group summaries

* Adjust custom renderer tests

* Reuse custom renderer metadata during timeline rendering

* Defer event-list summary generation until collapse

* Updated tests

* renderAsInformationalMessage to renderAsInfoMessage

* Fix sonar issues

* Added spy tracking and restore

* oxfmt

* Added TSDoc
2026-10-13 13:18:56 +00:00
Michael Telatynski
f82a8eafe3 Fix more race conditions in routing (#35385)
* Fix more race conditions in routing

Claude assisted

It identified 2 issues:
+ Malformed percent-encoding was unhandled
+ Routing could race with the browser handler causing the latest hash to be ignored

* Fix playwright utility `goTo` being racy

Fixes https://github.com/element-hq/element-web/issues/28872

* Workaround for happy-dom issue https://github.com/capricorn86/happy-dom/issues/2479
2026-10-13 07:53:33 +00:00
mxandreas
702043ca57 Don't allow to skip device verification by default (#35364)
* Reapply not allowing skip device verification by default.

Reverts the revert commit 417fa60b0e.

* Switch to a new local store entry to check if verification is enforced, that is only set when the force_verification is true at the login.

* Test that force_verification does not affect existing sessions.

* Update test title

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

* Fix formatting

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

* Fix test title

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

* Address review comments for 'should not force verification on reload if force_verification is enabled after login' test.

---------

Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2026-10-12 13:27:34 +00:00
Andy Balaam
ba531b906d Remodel "Can't confirm" dialog to match designs (#35375) 2026-10-09 13:47:03 +00:00
David Baker
1ddb4049e0 Update compound-web to 10.3.1 (#35390)
* Update compound-web to 10.3.1

To fix tooltip overflow bug

* Fix success to accent

* snapshot/test updates

* Gah the snapshots

* more snapshots

* Last lot of snapshots, hopefully

* Change the brittle CSS override to reflect the new CSS

* Same hack on date picker context menu

* s/success/accent/ and another padding override

* Update for really tiny font rendering differences
2026-10-09 12:20:01 +00:00
Michael Telatynski
f03ce37cce Deflake playwright tests (#35392)
* Deflake decryption-failure-messages playwright test

By waiting for things to happen in the right order

* Deflake sliding-sync playwright test

By waiting for things to happen in the right order
2026-10-09 11:17:23 +00:00
Johannes Marbach
d89ee058f2 Remove feature_disable_call_per_sender_encryption (#35396) 2026-10-09 08:48:34 +00:00
Michael Telatynski
ec6c5ea7ab Fix flaky room-list-panel playwright tests (#35389)
Testing drag and drop is fun...
2026-10-09 08:04:21 +00:00
Will Hunt
56ec209d49 Drop support for migrating libolm sessions (#35138)
* Remove the libolm to rust crypto store migration

* Add LegacyCryptoUnsupportedView to shared-components

* Show LegacyCryptoUnsupportedView when an unmigrated libolm crypto store is found

* Replace crypto migration e2e test with legacy crypto store test

* Cleanup loadSession, reduce congivitive complexity.

* Improve centering and spacing of view

* update snap

* changes for review

* lint

* Don't format the dump file

* Re-add missing files
2026-10-08 11:27:39 +00:00
ElementRobot
5b37fd39eb Revert "Do not allow skip device verification by default (#35259)" (#35343) (#35345)
This reverts commit 789de241d3.

(cherry picked from commit 417fa60b0e)

Co-authored-by: Andy Balaam <andy.balaam@matrix.org>
2026-10-08 08:39:23 +00:00
Florian Duros
d0c778e8c4 Update Pill and PillInput design (#35370)
* Update compound design tokens to 11.2.0

* Update Pill design

* Update PillInput design

* Update screenshots

* Update snapshots

* Update ImageView snapshot

* Update e2e screenshots
2026-10-08 08:15:25 +00:00
Michael Telatynski
41d5cc1d3b Switch audio-player.spec.ts to using a retrying assertion (#35373)
To deflake some tests
2026-10-07 17:19:32 +00:00
Andy Balaam
32a835405b Offer 'Sign out' on the identity reset page if there is no other option (#35307)
* Offer 'Sign out' on the identity reset page if there is no other option

* Fix incorrect prop documentation after review

* Update comments to reflect the 'Sign out' variant
2026-10-07 11:08:38 +00:00
renovate[bot]
6c2e29e27b Update testcontainers docker digests (#35365)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-07 09:27:40 +00:00
Paul Chobert
161aef320f Stop writing removed legacy mention rules from the Labs notification settings (#35035)
* Stop writing removed legacy mention rules from labs notification settings

Matrix v1.17 removed the legacy text-matching mention push rules
(.m.rule.contains_display_name, .m.rule.contains_user_name,
.m.rule.roomnotif) from the base rule set (MSC4210), and Synapse is
about to stop serving them by default. The labs notification settings
page wrote those three rules on every save regardless. Against a server
that no longer serves them the page never converges: Synapse currently
accepts the writes with 200 without serving the rules, so the "Update"
banner never clears and the page stays locked, and once the server
answers 404 as the spec requires every save fails.

The reconciler now only writes the legacy rules when they are present
in the rules fetched from the server, the same way the intentional
rules are gated on supportsIntentionalMentions.

Adds reconciler tests with the legacy rules absent and present, and
Playwright specs that run against Synapse with msc4210_enabled both
off and on.

* Split the labs mention rules e2e helper into explicit steps

Replace the shared parameterised test with small helpers that each spec
calls in order, so neither spec branches on the server mode. Each spec
asserts its own precondition and its own final state of the legacy rule.

Clicking "Proceed" is now unconditional and waits for the banner. Every
fresh account shows it, and the old one-shot presence check raced the
push rules fetch.

* Update copyright holder in labs mention rules e2e tests

* Cover all legacy mention rules in the labs notification e2e tests

* Keep proceeding until the labs update banner is gone in e2e tests

While the server serves the legacy mention rules, one click on "Proceed"
does not always unlock the labs notification settings page. The page writes
a legacy rule and its intentional counterpart in parallel, and
monitorSyncedPushRules copies the legacy rule's actions onto the intentional
one whenever a sync shows them out of step. When that sync lands between
the two writes, the monitor puts the old actions back, the page re-reads
the rules, still sees a difference and keeps the banner until the user
proceeds again.

That race is in the app and predates these tests, which are about which
rules get written. It made the served-mode spec flaky, so the helper now
proceeds until the banner is gone.

* Give the labs update banner click a timeout in e2e tests

click() waits for the "Proceed" button to be visible. On a retry the banner
may already be gone, which is why the helper checks for it before clicking.
A banner that goes away between that check and the click would still make
click() wait until the test times out, so the click now gives up after a
second and the next attempt finds the banner gone.
2026-10-07 07:47:24 +00:00
renovate[bot]
7e0a4fbecd Update testcontainers docker digests (#35333)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-06 17:20:39 +00:00
Will Hunt
3c3db95f1a Fix sliding sync invite flake (#35342) 2026-10-06 15:00:32 +00:00
Andy Balaam
417fa60b0e Revert "Do not allow skip device verification by default (#35259)" (#35343)
This reverts commit 789de241d3.
2026-10-06 14:56:46 +00:00
mxandreas
789de241d3 Do not allow skip device verification by default (#35259)
* Change the default of `force_verification` to `true`.

* Fix tests for not skipping verification by default.

* Fix tests and snapshots for not skipping verification by default.

* Update screenshots.
2026-10-06 09:12:47 +00:00
David Baker
066518dfd7 Collection of EN string changes, Pt. 2 (#35289)
* Collection of EN string changes, Pt. 2

The webapp itself

* Sort i18n file

* Update tests/snapshots

and also change the rest of the "room" strings to "chat"

* more tests / snapshots

* More snapshots / tests

* More tests & snapshots

* Even more tests / snapshots

* More snapshots / tests

* Playwright screenshots pt. 1

* More screenshots

* More tests / screenshots

* One more 'devices'
2026-10-05 13:19:59 +01:00
renovate[bot]
baff62f58e Update testcontainers docker digests (#35303)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-05 09:15:51 +00:00
Andy Balaam
6e6f8d9502 Update wording of crypto stuff during sign-in (#35239)
* Update intro wording on the Confirm your digital identity page

* Update wording of Can't confirm screen
2026-10-02 10:57:53 +00:00
Florian Duros
0046435cc8 Improve invite button UX in member list (#35270)
* Clean up memberlist invte container

It's cleaner to rely on the container padding and flexbox rules to place
the children.

* Use primary button for invit button in memberlist

* Update e2e test
2026-10-01 21:52:27 +00:00
Michael Telatynski
5a7e141079 Deflake some playwright tests (#35275)
* Deflake some playwright tests

* Remove slow test flag from encryption tab tests

Removed slow test indication from encryption tab tests.
2026-10-01 11:57:51 +00:00
David Baker
6eabcfb901 Collection of EN string changes, Pt.1 (#35115)
* Collection of EN string changes

Pt. 1: shared components

* Update room list primary filters snapshots

* Other snapshot updates

* Update view source string

* more snapshots

* More Unreads/Unread

* Another view source

* More snapshots

* New conversation / new and another anyways

* s/jump/scroll/

* snapshot

* Screenshots

and jump/scroll to date in story

* More screenshots

* Update tests for New conversation -> New

* Unreads

* More playwright string changes

* screenshots

* Change 'chat' back to 'room'

* Chat back to room

* Fix screenshot

and add one that was somehow missing(??)

* regen screenshots

* Stale screenshot & vitest 5 snapshots

* Another s/Jumnp/Scroll/

* Translate 'contact account provider' button on room status bar

And update it from 'contact admin'

* Snapshot
2026-10-01 10:55:55 +00:00
Michael Telatynski
97e2e7b69f Stabilise Compound random avatar colours in Playwright tests (#35281) 2026-10-01 08:49:46 +00:00
Florian Duros
a64fe4233a Show the open room in the room list before joining it (#35207)
* Show the open room in the room list before joining it

The room list builds an item for the open room from the client's room or the room summary, without adding the room to the client or to the room list store.

* Add unit tests

* Add e2e tests
2026-09-30 12:40:18 +00:00
Andy Balaam
f01c4218c7 Offer 'Sign out' on the verification page instead of 'Remove this device' (#35211) 2026-09-28 12:26:44 +00:00
Timo
5fae057a60 Element call as a react component (#34935)
* Add an end-to-end Element Call test with a real MatrixRTC backend

Element Web's Playwright coverage of Element Call has only ever used a stand-in:
`sample-files/fake-element-call.html`, a page that does just enough for the widget
plumbing to be exercised. Nothing in the suite has ever carried media.

This adds one real call between two users, through the Element Call the build under
test ships (`@element-hq/element-call-embedded`, copied to `widgets/element-call/`),
against a real MatrixRTC backend:

- `testcontainers/livekit.ts` — a LiveKit SFU advertising loopback so the browser
  reaches it through published ports on macOS as well as Linux.
- `testcontainers/lk-jwt-service.ts` — the authorisation service, validating OpenID
  tokens over Synapse's federation API.
- `testcontainers/matrix-rtc.ts` — starts the two and produces the Synapse
  configuration that announces the transport (MSC4143) and enables the MSCs Element
  Call needs.
- `services.ts` — a `matrixRTC` worker option turning all of that on.

`routeConfigJson` no longer hard-codes the dev server's origin: it resolves
`config.json` against the context's `baseURL`, so a `BASE_URL` other than the default
works, and other origins a test loads keep their own.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Make Renovate actually see the new testcontainer images

The custom manager's `depName` group is `[^@]+`, which matches newlines and
quotes, so it is only bounded by the next `@` in the file. In `synapse.ts` and
`mas.ts` an `@element-hq/…` import happens to sit above the image literal and
caps it; `livekit.ts` and `lk-jwt-service.ts` import `testcontainers` and `yaml`,
so the match instead starts at that import and swallows everything up to the
image name. Renovate gets a nonsense package name, finds nothing, and the pins
quietly rot.

Exclude quotes and whitespace from both groups. All four digest-pinned files now
extract correctly, synapse and mas unchanged.

Bump lk-jwt-service to 0.7.0 while here.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Address the bundled Element Call by directory, not by index.html

The full-call spec passed against the webpack dev server and failed in CI, where
the production build is hosted by `serve`.

`ElementCall.generateWidgetUrl` built `./widgets/element-call/index.html#…`.
`serve` has `cleanUrls` on by default, so it 301s that to the extensionless
`/widgets/element-call`. Element Call's `index.html` references its chunks
relatively (`./assets/…`), and against a base with no trailing slash the browser
resolves those to `/widgets/assets/…` — 404. Element Call never boots, so the
lobby never appears and the test times out.

Address the directory instead. It is the same deployment, the trailing slash
sidesteps the redirect, and the hash is overwritten further down either way. This
is not only a test concern: Netlify also strips `.html` by default, and that is
what serves the PR previews and develop.element.io.

Doing it here rather than in the spec keeps the test honest — it exercises the
widget URL Element Web really generates, with no `Developer.elementCallUrl`
override. Setting `cleanUrls` in a `serve.json` was the other candidate and is
not viable: any value other than the default also stops `serve` resolving `/` to
`index.html`, which breaks every other test.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* EC react component Plan

* The implemantation Element Call React Component with mocked EC react
component

* final plan

* tests

* update plan to not do e2e tests in EW but in EC

* Start using the real react component instead of the mock (activation
react EC)

* add playwright e2e tests

* fix transport discovery (pass in via config. Hack the well-known source
for servers not supporting get_transports)

* stylesheet fixes

* Update element-call-react-plan.md

* add docuemnt pip

* Depend on the Element Call component from its git branch

`@element-hq/element-call-component` was a `link:` to a hand-built
`dist/` in a machine-local worktree. It is now a git dependency on the
`component` directory of element-hq/element-call, on the
`valere/component_ec_M1` branch (element-call#4233), whose `prepare`
script builds the component on install; pnpm has to be allowed to run
it (`allowBuilds`). The ref goes back to `main` once that PR has merged.

The branch first needs the commit that adds the component's manifest
and build (`toger5/component-package-manifest` in the EC checkout);
until it is pushed, `path:/component` resolves to no manifest and the
lockfile keeps the old `link:` entry. Both are written up in the plan.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* use the component_ec_m1 dep lock file entries

* fix element call reloading

* pass the right theme to element-call component

* bump element-call-component

* Return a call from the browser PiP window to where it left from

Closing the Document Picture-in-Picture window always dropped the call
into Element Web's floating PiP, even when it had filled the room's call
view a moment earlier and the user was still looking at that room.

The store now remembers whether the call left from the call view, and
on release opens the call view again when it did — unless the call has
ended, the user has moved to another room, or the user opened the call
view themselves (which is what closed the window). A call that was
floating in Element Web's PiP before goes back there, as it did.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Draw the call header's outline icons a little smaller

The room header's icons are Compound's solid set, but minimise,
maximise and pop-out exist only as outlines: Compound has no filled
counterparts, and nothing else in the set says what they say. At the
solid icons' size their open strokes look heavy-handed next to them.

Scaling the glyphs down slightly inside the buttons lets them sit
comfortably next to their neighbours without changing the buttons'
footprint.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Hand a persisted tree to the remaining placeholder on unmount

When two PersistedElements for the same key mount in one React commit
(a call returning from the browser PiP window into the call view, while
Element Web's floating PiP briefly shows it as well), whichever rendered
the tree last owns the child's ref. If that one is then the one to
unmount, it hid the tree, and the survivor, never having been handed the
child, could not show it again.

On unmount, if another placeholder is mounted, render the tree once more
with the most recently mounted survivor's wrapper so it takes over the
child and positions it; only hide the tree when nothing is left to show
it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Adjust to updates done in EC
(simpler public api. More resilient to prop changes)

* package.json back to EC branch valere/component_ec_M1

* fix closing in component mode

* Configure pnpm store location in workflows

Keep the pnpm store out of node_modules to prevent incorrect
bundling of element-call-component when building git dependencies.

* update docs on EC packaging improvements

* fix ci

* Update pnpm-lock and tsconfig

* Move the browser Picture-in-Picture window and call header changes to a follow-up

Keeps this PR to Element Call as a React component. The Document
Picture-in-Picture window (DocumentPipStore, useDocumentPip, the
PersistedElement detach/reattach and placeholder hand-over, the
PipContainer awareness of it), the call header's minimise, maximise and
pop-out buttons with their outline-icon sizing, the browser API typings,
their strings, tests and e2e spec move to toger5/ec-document-pip.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* bump to main branch EC

* fix CI failing due to pnpm store

* remove docs and dev journals

* review

* CI: silence zizmor's github-env finding on the pnpm store action

zizmor flags every $GITHUB_ENV write inside a composite action, because it
cannot see which triggers the action will be used from. The value written
here is a constant built from RUNNER_TEMP with nothing attacker-controlled
in it, so suppress the finding the way the repo does elsewhere.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Keep the ready promise's rejection from going unobserved

close() rejects the pending ready promise so that a start() still waiting on
the component learns the call went away instead of hanging until the timeout.
Usually nothing is waiting, and the unobserved rejection then surfaced as an
unhandled promise rejection, which crashed the Vitest worker running
Call.test.ts. Mark the promise as handled before rejecting it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* review

* review: double import

* move types to EC repo (just import them here)

* review: refactor ElementCallAppTile to a MVVM shared compoenent

* merge useEffectiveTheme and useTheme hooks

* cnvert the ElementCallMock to MVVM

* use unstable EC branch. DO NOT MERGE UNTI THIS COMMIT IS REVERTED
this branch is used to test CI with the new exports from EC.
We need to first merge:
https://github.com/element-hq/element-call/pull/4269 before we can put
this back to main (revert this commit).

* Move Node and pnpm setup into a single action

The setup-node-pnpm action now includes pnpm/action-setup and
actions/setup-node alongside the store relocation, eliminating
boilerplate across workflows and fixing the setup order in one place.

* fix broken lock file

* test for review change "reject on promise race"

* review: letter spacing

* Import the EC CSS layered

* Use self-repository syntax

* Fix import path

* Fix webpack

* Revert actions syntax as Sonar doesn't seem compatible with it

* Switch to Flex

* Switch to a11y label

* Take client from SdkContext

* Make strings in mock view translatable

* Keep class names in EW

* Move mock view to shared components and add stories

* Exempt voip|element_call_mock|title

* Fix tests

* Clarify doc string

* Add labs.md entry

* Use text element

* Remove redundant test

* Remove redundant test

* Delint

* Format

* Update snapshots

* Bump element-call

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Johannes Marbach <n0-0ne+github@mailbox.org>
2026-09-25 15:12:19 +00:00
Florian Duros
c603611951 Improve knocking workflow (#35140)
* Fetch room summmary and then peek when displaying an unkown room

* Update tests

* Update e2e tests
2026-09-25 14:25:16 +00:00
Nathanaël
8978841c64 Add cross-room thread panels to Threads Activity Centre (#32851)
* feat(TAC): add cross-room thread panels to Threads Activity Centre

Adds two new tabs to the TAC popup (Rooms / All threads / My threads):

- "Rooms" tab: existing behaviour — rooms with unread threads
- "All threads" tab: flat list of all unread threads from those rooms,
shown as two-line rows (room avatar + name, sender + message preview)
- "My threads" tab: same layout but filtered to threads the user
participated in (as root sender or replier), across all rooms

Implementation notes:
- Export doesTimelineHaveUnreadMessages from Unread.ts for per-thread
unread detection
- Participation check covers both thread root and replies
- Uses server-side notification counts as primary unread signal,
falling back to timeline inspection for activity-level unread
- settingTACOnlyNotifs applies to the Rooms tab only; thread tabs show
all unread participated threads regardless of notification level

Warning:
I know threads and unread are very difficult topics. But in daily job
we are many to strungle to find and follow threads, in which rooms
and where. So I started this not to provide a perfect solution, but
as starting point to sustain the improvment regarding this issue.
(And to see if at least we could have something in-house)
Honestly I think this would benefit a lot from the ongoing work
on element-web new architecture - which I did not took time to dive in -
and on every MSCs and synapse that will provide threads subscribe and
unsubscribe mechanisms.
Finally, this definetly needs design!

Closes #28036

* feat(TAC): replace hideChevron with compound nav-hint; dot yields to chevron on hover

Move the notification dot to the trailing edge of the thread row as a
direct MenuItem child (order: 998). The compound nav-hint chevron sits
at order: 999 in the same position. On hover, compound's `~ *` rule
naturally hides the dot; a targeted override keeps the text content
visible. This removes the hideChevron workaround entirely.

* feat(TAC): redesign per Figma — My threads / Other threads tabs

Replace 3 tabs (Rooms | All | My) with 2 mutually exclusive tabs:
"My threads" (default) and "Other threads". Categorise via server data
(thread.hasCurrentUserParticipated, highlight count); mentions/keywords
land in My threads even when not participated.

The tac_only_notifications setting is scoped to "Other threads" only:
My threads always shows participated or highlighted threads regardless
of the setting. In Other threads, setting=true drops activity-only
(local-detected) entries; setting=false keeps them. Default flipped to
false. The setting label now reads "In the Other threads tab, only
show notifications". The rooms list and greatestNotificationLevel only
reflect rooms that contribute at least one displayed thread.

Drop the doesRoomHaveUnreadThreads() room-level pre-filter; it
short-circuited on muted rooms and on rooms with no local timeline
activity, hiding participated threads in muted rooms and missing
server-pushed highlights that hadn't surfaced locally. The per-thread
loop now decides inclusion based on server counts (authoritative) plus
a lazy local fallback. Mute is applied per-room inside the Other
threads branch only, preserving the "muted rooms don't clutter Other
threads" guarantee while letting them still contribute to My threads.

UI: Compound NavBar/NavItem for tabs, hide the menu title, fixed popup
height for ~6 cells, 40px avatars. Zero Compound FloatingMenu's
padding-block so the tabs + rows containers control their own spacing.
Fix hover regression by overriding Compound's chevron-replaces-content
sibling rule so the dot and content stay visible.

* fix(TAC): don't surface read participated threads in My threads

The local unread heuristic (doesTimelineHaveUnreadMessages) reports a
participated thread as unread when the user replied but isn't the literal
last sender — e.g. a later reaction/edit/redaction landed after their
reply. The js-sdk's read shortcut only fires for the very last event (see
the "second-last event" TODO in room-receipts.ts), so the latest incoming
message, older than the user's reply, still reads as unread.

Guard the local fallback with hasUnreadAfterMyLatestReply: treat the thread
as read once the user's own latest reply is at/after the latest incoming
message. Server notification counts still take precedence and the
muted-room fallback is preserved.

* feat(TAC): use shared message-preview store and Compound typography

Render thread-row previews via MessagePreviewStore (consistent edit/reply/
emote/HTML handling with the room list) and resolve sender names with
getSenderName. Apply Compound Text typography to the room name, sender and
preview, dropping the equivalent font rules from CSS.

Open a thread with a two-card stack (thread list beneath the thread view) so
the thread view gets a working back button, mirroring Action.ShowThread.
Extract evaluateThreadUnread from computeUnreadThreadRooms and collapse the
per-tab render branches into a single active-tab selection.

* fix(TAC): keep locally-replied threads in My threads

Thread.hasCurrentUserParticipated is set only from the homeserver's
bundled current_user_participated flag, which lags behind local activity.
Right after the user replies in someone else's thread, the flag is still
false, so the thread was wrongly categorised under Other threads.

Complement the server flag by inspecting the local timeline: if the
current user authored a sent m.thread reply, the thread is theirs. This
matches the server's participated semantics (isRelation(m.thread) &&
!status), the same test the rest of the app uses for a real reply.

* test(TAC): port unit tests to colocated vitest after upstream migration

Upstream migrated the Threads Activity Centre unit tests from jest
(test/unit-tests/.../*-test.tsx) to colocated vitest (src/.../*.test.tsx)
in #34800. Re-apply our redesigned My threads / Other threads test suite
on top of that migration:

- Convert jest.* -> vi.* and jest-matrix-react -> test-utils-rtl imports.
- Replace the pre-redesign test bodies with the participated/other-threads
  suite matching the current component API.
- Update notification-badge assertions to the shared NotificationBadgeView
  data-notification-level attribute (NotificationBadge MVVM refactor).
- Drop the obsolete ThreadsActivityCentre snapshot (redesign uses explicit
  assertions, no snapshots).

* fixes requested in review

- replace `enum TACView` with a string union
- extract tab selection into `getActiveTabContent`
- `Array<ThreadData>` -> `ThreadData[]`, `Result` -> exported `UnreadThreadRooms`
- add tsdoc to `ThreadData`
- trim `computeUnreadThreadRooms` tsdoc
- restore `tac_only_notifications` default to true
- use Compound spacing tokens, incl. `--cpd-space-0-5x` for the 2px gap
- use Compound semantic colour tokens instead of `$*-content`
- use the Compound `Text` component for the empty caption
- drop all `!important` added by this PR, scoping rules under `[role="menu"]` instead
- restore `hideChevron` on `MenuItem` rather than hiding the chevron in CSS
- drop the dead `mx_ThreadsActivityCentreRow` class
- link the upstream issues/PRs from both workaround tsdocs

* fix(TAC): focus on threadsPanel

* fix(TAC): use 444px width to match Figma design

* feat(TAC): use the room list's notification decoration on thread rows

Thread rows rendered `StatelessNotificationBadge` with `forceDot`, which
collapsed three states into three 8px dots differing only in hue — grey for
activity, green for a notification, red for a mention. That encodes state by
colour alone (WCAG 1.4.1), red/green being the worst pair to pick, and
`forceDot` discarded the count so 1 and 30 unread looked identical.

Use the same decoration as the room list instead, so the states differ by
shape: an `@` icon for a mention, a counter for a notification, a plain dot
for activity, and the bell for a thread in a muted room. This reuses the
presentational component from shared-components rather than the app-side one,
which needs a `RoomNotificationState` that has no per-thread equivalent.

The count and the room's muted flag are now carried on `ThreadData`, and the
row's `aria-label` spells out the unread state — the label overrides the row's
content, so the new visible counter would otherwise go unannounced.

Also fixes `assertThreadsInTac`, which matched `mx_NotificationBadge_level_*`
classes that exist nowhere in the tree; it goes back to the
`data-notification-level` selector, kept alive by the row wrapper.

* fix(TAC): drop a thread as soon as it is read

A thread stayed listed, counter and all, for as long as the homeserver took
to push fresh notification counts — the js-sdk never recomputes `total`
locally, and only zeroes counts when we sent the last event ourselves.
Since presence was `hasServerNotifs || <local checks>`, reading changed
nothing until the next sync said so.

Check our read receipt before the server counts, so an explicit receipt on
the thread's latest known event wins over a stale count, and recompute on
`RoomEvent.Receipt` rather than waiting for the next sync.

* fix(TAC): drop the workarounds now fixed in the js-sdk

`hasUnreadAfterMyLatestReply` guarded a false positive in
`doesTimelineHaveUnreadMessages`, and `hasCurrentUserSentInThread` covered
`Thread.hasCurrentUserParticipated` being stale right after we reply. Both
root causes are fixed upstream, so the guards go and their coverage moves to
the js-sdk specs.

Fixed by matrix-org/matrix-js-sdk#5525 (treat an event as read if the user
sent a later one) and matrix-org/matrix-js-sdk#5516 (set
hasCurrentUserParticipated when the current user sends a thread reply).

Note both land after the js-sdk commit this repo currently pins, so the two
bugs reappear until that pin advances.

* test(TAC): update playwright tests for the redesigned panel

The e2e expectations still described the pre-redesign TAC, and the
workflows never ran on this PR, so none of it showed up as red:

- a mention now makes a thread ours, so the mentioning thread is asserted
  in "My threads" and the two plain ones in "Other threads", newest first
- clicking a row opens the thread itself, so "mark all as read" steps back
  to the list first, via the card's back button
- one call site still used `clickRoomInTac`, renamed to `clickThreadInTac`
  when the TAC moved from one row per room to one per thread

Screenshots regenerated with `pnpm test:playwright:screenshots`.

* fix(TAC): restore the e2e helper's types

The playwright project is type-checked separately from the app
(`tsc --noEmit --project playwright`), and this branch had loosened the TAC
helper in ways that only fail there: optional fixture names, dropped non-null
assertions, a MessageBuilder constructor whose three fields are never read,
and a nullable messageFinder.

Put those back the way develop has them, keeping only the changes this PR
needs: clickThreadInTac, switchToOtherThreadsTab, assertThreadsInTac and
clickBackToThreadList.

* test: update notification settings snapshots for the renamed setting

This PR rescoped `Notifications.tac_only_notifications` to the Other threads
tab and renamed its label accordingly, which changes the notification settings
screen. Regenerate the two vitest snapshots and the two playwright baselines
that still carried the old wording.

* Address review comments

---------

Co-authored-by: Florian Duros <florianduros@element.io>
2026-09-25 08:17:19 +00:00
David Langley
d3dafba29c Make Spotlight result text and badges legible at rest and in high contrast (#35037)
Two colour defects in Spotlight results, plus a test that could not see either:

- The public-room alias and the room context details are 12px text in
  $tertiary-content at rest, which is 3.5:1 against the dialog background in the
  light and dark themes - below the WCAG AA 4.5:1 for text that size. Use
  $secondary-content at rest (5.2:1 light and dark, 8.9:1 high contrast).
  Hovered and selected rows keep $primary-content, since secondary is only
  4.2:1 against the hover background.

- In the light high-contrast theme a leftover override painted the notification
  badge with the dialog background whenever its row was hovered or selected,
  turning a red count badge into a white disc and hiding the count. Remove it;
  the badge's own colours are fine (count text is 5.3:1 on red and grey).

The legibility test claimed to cover "text across Spotlight surfaces" but only
ever scanned a single hovered row, so neither defect could fail it. It now
returns two matching rooms per search so a row at rest sits beside the selected
one, puts the joined room in a space so context details are rendered, and leaves
an unread mention so the first result - selected by default - carries a badge
with a count. axe scans all rows for contrast; the selected badged row and a row
at rest are also screenshotted, the former because axe reports the overlapping
badge as incomplete rather than as a violation, the latter to pin the resting
colours. No hover and no retry is needed. Against the previous CSS the test
fails in all three themes on exactly these defects; with the fix it passes 30/30
across them.

Fixes #34991
Fixes #34841

Signed-off-by: David Langley <davidl@element.io>
2026-09-23 17:18:36 +00:00
renovate[bot]
b0e36593a9 Update testcontainers docker digests (#35161)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-23 16:00:58 +00:00