* Migrate final batch of tests from Jest to Vitest
* Update test-utils imports
* Move test-utils
* Remove the remainder of Jest
* Make tsc & knip happy
Conflicts:
pnpm-lock.yaml
* Fix bad merge conflict
* Iterate
* Remove legacy Module & Customisation API
in favour of the new runtime modules system
* Delint
* Remove unused i18n string
* Fix tests
* Fix test
* Fix tests
* Iterate
* Fix bad merge
* Bump Module API version
* Bump module-api compatibility ranges
* Update docs
* Fix semver ranges
* Update test module API version
* Too many versions
* Too many versions again
* feat: Add tokenizer mode support for message search
Add user-facing setting to choose tokenizer mode (language-based vs N-gram)
for local message search. N-gram tokenization supports CJK languages and
mixed-language content. Includes confirmation dialog for mode changes
(requires reindex) and automatic checkpoint recovery.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: Add tokenizer mode support for event indexing (desktop side)
Add N-gram tokenizer support to Seshat search index initialization.
Refactors initEventIndex into a testable module with dependency injection,
supporting both language-based and N-gram tokenization modes. Includes
automatic database recreation fallback and unit tests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: propagate non-reindex errors instead of deleting search index
Previously, any Seshat open failure that wasn't a ReindexError would
silently delete the EventStore and recreate it, losing the user's search
index on transient errors like filesystem locks or passphrase issues.
Restore the original behavior: only handle ReindexError with recovery
logic, and propagate all other errors to the caller (which shows an
error to the user via sendError).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: update lockfile for tokenizer mode branch
* Fix tokenizer mode CI failures
* Address tokenizer mode review comments
* chore: update tokenizer mode copyright headers
* fix: address tokenizer mode lint errors
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Will Hunt <2072976+Half-Shot@users.noreply.github.com>
* Move thread summary max-width application override to the shared component
* Make the storybook use more relevant data and also add descriptions for each story
* Fix the hover boundaries
* Apply application theme background colors when selection Element Web as global styling
* Updated screenshots
* Fixes for pre migration issues in Card view
* Better card and search stories. Also mimic the 'narrow' logic from ScopedRoomContext and view model in the storybook
* Add timestamps to all single event stories
* Updated snapshots
* Updated screenshots
* Only apply opacity for Search story in interactive mode
* Avoid the search result opacity to avoid a11y failure
* Simplified the tiles rendering logic
* Add a default people section
* Rename "Chats" section to "Rooms"
* Update e2e tests
* Fix tests after merge (jest usage instead of vitest)
* Add new settings to enable or disable people section
* Wire up new setting to disable people section
* Update e2e tests
* Amend unwanted dev file change
* Update e2e screenshots
* Enable People section by default
* Update preference settings snapshot
* Update e2e tests
* Update other e2e tests
* Restrict dnd of dm and rooms
* Fix outdated comment in section
* Add people section storybook screenshots
* Remove useless story
* Revert local dev changes
* Move tests into section header view test file
* Revert unwanted changes
* Apply .mx_LegacyDialogButton to all buttons that rely on the cascading rule.
* Fixup a few cases of old rules winning out.
* update snaps
* More snapshots
* Also apply to input[type="submit"]
* Add snapshot tests for ones that miss coverage
* More coverage for the coverage gods
* stabilize
* Update SessionRestoreErrorDialog.test.tsx
* copyright update
* Add missing min-width and min-height overrides for ImageBodyView
* Use the media story to render ImageBody with small/medium/large images to show the min and max size overrides
* Updated snapshots
* Chaneg stories to render one image per message
* Updated storybook screenshots
* Align view model with the current EventTileView contract
* Use presentation context at every application call for EventTileView
* Render EventTileView from UnwrappedEventTile
* Remove the legacy styling
* Added missing receipt gutter logic
* Adding Card as a new shape, used in TimelineCard panel
* Added visual tests for the Card story
* Migrate EventTile layout styling and enhanced the story book rendering
* Migrate preview, notification, thread, and file shapes
* Use MemberAvatar and RoomAvatar in storybook
* Make slot styling self-contained and clean up corresponding application styling
* Clean up action bar styling
* Clean up event tile styling overrides
* RoomView realted styling fixes
* Adjustments for threads list
* Adjustments to File view
* Adjustments to Card shape
* More styling cleanup
* Updated Playwright test selectors
* Update the story book with more relevant data
* Fix oxlint and update story screenshots
* Restored conditional notification-badge slot rendering to avoid empty wrappers
* Fixed tests and snapshots
* Remove the unused UnreadNotificationBadge
* Updated snapshots and removed a11y failing story test
* Fix test locator hooks
* Fixed styling and logic issues in appearance settings
* Fixes to slotSender and slotBody placement for group layout
* Reorder style sheet for better readability
* Fix for spacing between slotSender, slotBody and reply-chain
* Fix more Playwright test loacators
* Clean up event tile class overrides
* Fix the slotBody styling
* More clean up of unused locators
* Styling fixes
* Fixes to test locators and styling for bubble and irc layout
* Locator fixes, updated snapshots, layout adjustements
* Fix for selected and editing markers and timestamp pos
* Styling fixes to bubble layout. Also dismiss releaseAnnouncements
* Styling updates and dont wait for release announcements anymore
* Styling adjustments
* Make the Playwright test wait for UI to settle before taking screenshot.
* Updated screenshot - the only difference is scroll pos
* Fixing test locators and styling adjustments
* Updated the test to reflect ellipsis, hence the screenshot update
* More test locators and styling adjustments
* Updated snapshots and screenshots
* More locator fixes and snapshots
* Restore the original screenshot
* Added Search result specific styling and make reply chain density aware
* Test locators and styling adjustments
* More styling fixes
* Updated snapshot
* oxfmt
* Styling adjustment and updated snapshots
* Styling adjustement
* Restore the font-12px override on thread view ViewSourceEvent
* Adjust styles for thread view bubble layout of ViewEventSoucrce
* More adjustments
* Styling adjustments
* Fix the bubble layout thread view event source alignment
* Fix the thread view without destroying the room view
* Removing !important
* Updated snapshots after merge
* Put back !important until MemberAvatarView is actually used in event tiles
* Updated snapshots
* Use hideJumpToBottomButton to avoid flakiness
* More hideJumpToBottomButton
* Say when a spotlight search found nothing instead of selecting a filter
Spotlight had no empty state, so a query matching nothing left the filter
shortcuts as the only options in the dialog. The first option is selected by
default, so pressing enter after typing switched the dialog into the public
spaces filter. Leaving that filter needs backspace on an empty query, which is
not discoverable, so a mistyped search quietly changed what was being searched.
A no-results entry now sits above the shortcuts when a query returns nothing. It
takes the default selection, so enter does nothing rather than choosing a filter,
and it says why the list is empty. The shortcuts are still one arrow key away.
The room directory screenshot covers a search that matches nothing, so it now
shows the new row and its baseline is regenerated. The one-result baseline in the
same spec is deliberately untouched: a search that does find something never
renders the row, and leaving that image alone keeps the diff honest about which
state actually changed.
Tests: a query matching nothing followed by enter leaves no filter applied.
* Only show the spotlight enter hint on options that do something
The no results entry is an Option like every other row, and Option always drew the ↵ hint
into its end adornment, so a tile that exists purely to be inert still advertised a
keyboard shortcut. Its onClick is null precisely so that enter stops dropping the user
into a filter, which left the hint promising something that could not happen.
Option now draws the hint only when it was given an onClick. The stylesheet already takes
this line for the other case where enter would not fire — it hides the prompt whenever
focus leaves the search box, "as in this state pressing enter would not actuate that
option" — so this extends a rule the component already had rather than inventing one, and
any later option that is only there to be read gets it right without thinking about it.
Tests: the no results entry is asserted to render without the prompt while the start chat
shortcut beside it keeps one; it fails without the change. The room directory linux
screenshot is regenerated, and the one result shot next to it came back byte-identical,
which is what shows the render matches CI rather than quietly baking in a local one.
* Render the inert spotlight option as a plain unavailable option
The "No results found" entry has to be a listbox option so that it, rather
than one of the "other searches" shortcuts below it, takes the default
selection the roving tabindex hands to the first item that mounts. That is
the whole point of the entry: it gives the initial selection somewhere
harmless to land instead of dropping the user into a filter they never
asked for.
Routing it through AccessibleButton to get there was wrong, though. That
gave a row nobody can activate the click and Enter/Space handlers of a
button, plus the pointer cursor that comes with mx_AccessibleButton, so it
advertised an interaction it does not have.
Options without an onClick now render as a bare li carrying role="option"
and aria-disabled, which is the standard way to express an entry that is
present and announced but not selectable. Screen readers following
aria-activedescendant land on it and hear that there is nothing to pick,
and the shortcuts stay one arrow key away.
Saving a notification setting could fail without saying so: reconciliation
runs in the background and a rejection went nowhere, so a change the user
had made simply did not take effect and nothing on screen admitted it. The
tab now surfaces the failure, and offers a Try again action rather than
telling the user to try again without giving them any way to do so.
Making that action honest took two fixes underneath it. The queue that
serialises reconciliation chained each task onto the fulfilment of the
previous one, so a single rejection parked a rejected promise at the head
of the queue permanently: every later task skipped its own body and
re-reported that first error, which meant nothing could be retried and no
further settings change would take effect until the tab was reopened.
Chaining onto settlement instead lets the queue carry on.
The cached copy of the server's push rules was also only refreshed after a
successful apply. Changes are applied in stages, so a failure part-way
through leaves earlier stages committed while the cache still describes
the state before them; a retry would recompute the same diff and ask the
server to delete rules it had already deleted, which it answers with a
404. Re-reading the rules when an apply fails lets the retry pick up the
work that is actually outstanding. The user's own choice is deliberately
left untouched by that refresh, since that is what the retry re-applies.
The error is also cleared when a reconciliation succeeds and not only when
one starts, so a change that went through cannot leave the failure notice
standing behind it.
The notice itself is spaced away from the labs banner below it, and its
action sits beside the message while there is room and drops underneath
once there is not, instead of at the fixed breakpoint Compound would
otherwise use. Compound tints only the icon on a critical alert and leaves
the message in the default body colour, so the message takes the semantic
critical text token and reads like warnings elsewhere; the action is a
sibling of it and keeps its own colour.
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
* Render textual events as plain text in chat exports
* Assert the text a textual event view model produces
Both new cases dropped the view model they built, which is what SonarCloud flags as a useless instantiation: a constructor called only for its side effect on a mock, with nothing holding the result. Binding it and asserting the content it puts in its snapshot removes the warning and makes the case check the outcome rather than only the call it goes through to reach it.
* Migrate batch of tests from Jest to Vitest
* Migrate batch of tests from Jest to Vitest
* Migrate batch of tests from Jest to Vitest
* Migrate batch of tests from Jest to Vitest
* Migrate batch of tests from Jest to Vitest
* Migrate components/views/right_panel of tests from Jest to Vitest
The MSC4506 knock push rule pushes knocks to users who can act on them,
but a knock rendered as nothing: textForMemberEvent had no knock case,
so the desktop notification had an empty body and was dropped, and the
timeline showed no trace of the request. Render the full ask-to-join
lifecycle, matching Element X wording and gated behind the ask to join
labs flag:
* knock: "Alice is requesting to join"
* invite after knock: "Bob granted access to Alice"
* self-leave after knock: "Alice is no longer interested in joining"
* kick after knock: "Bob rejected Alice's request to join"
EventListSummary learns matching knocked / knock_accepted /
knock_retracted / knock_denied transitions so membership summaries can
describe the knock -> accept -> join sequence, and the knock Playwright
tests assert the summarised and expanded timeline (closing the room
settings dialog first where it overlapped the timeline).
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* Add to shared components the content of section creation dialog
* Add a vm for the section creation view
* Use new vm and view in section creation dialog
* Clean up lang, test and css
* Move section name step into its own component
* Add a room picker view component
* Use room picker in section creation
* Add shared component screenshots
* Can add rooms when creating or editing a section
* Fix rich list taking too much space
* Fix exisiting e2e test
* Wire up the the selected room when creating the section from the room item menu
* Add e2e tests
* Rename "edition" to "editing"
* Fix SettingsFlag not working correctly with settings with invertedSettingName attribute
* Add new settings to consider activity as unread
* Display Notifications.activityIsUnread settings in notification settings
* Wire up unread filter to Notifications.activityIsUnread settings
* Update RoomListStore tests
* Update notification screenshots
* Add e2e test
* Avoid to read Settings at every matches of UnreadFilter
* Make components layout aware and fix IRC styling
* Move styling to shared components
* Move styling to shared and clean up unused application overrides
* Fix linter errors and update snapshots and screenshots
* Add missing EventPresentationContextProvider ad adjust IRC styling
* IRC liine height fix
* The lesser of two evils for IRC layout issue
* Fix IRC layout for ViewSourceEvent
* Cleanup application styling overrides and add bubble and compact styling to DisambiguatedProfile
* Udpated screenshots for irc layout
* Let the parent position DisambiguatedProfile in bubble layout. More screenshot updates for IRC layout
* Updated screenshots
* Updated screenshot
* Show the promotion warning when your own power level comes from the room default
Promoting somebody to your own level is irreversible, so the confirmation exists to
catch it. It read our level straight out of the power levels event's `users` map,
which only lists people who have been given a level individually. Anyone sitting on
`users_default` is absent from that map, so in a room whose default is 50 the lookup
came back undefined, the guard's leading truthiness test failed, and the promotion
went through with no confirmation at all — precisely the case the warning is for.
The same truthiness test also discarded an explicit level of zero, and the map never
lists room creators, who since room version 12 outrank every assignable level.
Reading the level off our own `RoomMember` fixes all three: the SDK already resolves
an explicit entry, then `users_default`, then zero, and reports creators as infinite.
The comparison then needs an explicit undefined check rather than a truthiness one so
that a legitimate zero still counts, and the self-demotion branch is corrected the
same way.
The existing tests had `room.getMember` returning undefined for everybody, which no
real room does, so they are given a stub that resolves levels the way the SDK does.
Two cases are added: our level coming from `users_default`, which fails without this
change, and a creator, which documents that infinity never matches a promotion.
* Give the power level editor test a room that knows its members
The self-demotion case in the `<PowerLevelEditor />` suite drives the change through the
component, so it goes down the same path the view model now takes: our own level is read
off our `RoomMember` rather than out of the power levels event's `users` map. That suite's
room answers `getMember` with `undefined` for everybody, so the lookup found no level at
all, the guard fell through, and the confirmation the test then waits for never opened.
Handing the mock our own member, at the level the event it already builds grants us,
restores the case the test was written for. It is the same correction the view model's own
suite needed, and for the same reason: no real room reports that none of its members
exist, least of all the person doing the demoting.
The comment left beside the lookup goes with it. What it said belongs here and in the pull
request, not in the file.
* one slow preview no longer blocks up the current batch of previews from loading
* show failed and loading url previews
* composer url preview summary bar
* prefer site icon
* icon to show when there is no icon to show
* loading and failed previews
* collapse working
* clear all button working
* clear cache on empty composer
* remove preview button
* attach empty bundle when all urls previews are to be suppressed
* Reconcile url-preview foundation with develop's base
- Restore entries-based visibility/skip logic in the view model (drop
leftover previews-based branch from the cherry-pick merge)
- Pass collapsed/toggleCollapsed in both wrapper render paths
- Pass collapse props from the storybook wrapper
* fixed lint errors
* fixed more lint errors
* shut up sonar qube
* updated shared-components unit test snapshots
* made bar a div again
* update snapshot
* fixed aria label violations
* wait for tall image to load before capturing snapshot (claude wrote this)
* updated snapshot
* added onkeydown handler to summary div
* fixed tests for new view model
* made summary bar no longer clickable
* banners snapshot update
* bundles error-solid in vitest
* updated snapshot
* use uncollapsed composer url preview in vitest
* formatting
* restore mocks after each test
* corrected mocking logic
* sitename is not returned by /preview_url and so is not used
* uncollapse the composer url preview during test
* refactored to remove code duplication (and pass the CI)
* chrome tests fix
* updated test
* tests for failed/loading entries in composer url preview
* formatting
* fixed issue where composer url preview pops up after message is sent
* ensured links not in the preview view will not be shown
* changed css to match design
* fixed linter errors
* updated storybook screnshots
* updated css to not use hard values
* resolves some of the reviews
* some more of the reviews resolves
* usecallback
* uses translations
* apply some review changes
* fixed more reviews stuff
* applied comments
* removes matrix.to links from urlpreviews
* fixed some oxlint stuff
* regenerated snapshot
* removed pointless void
* fixed tests and stuff
* dark theme icon lightness
* reviews
* corrected types
* uses predefined colours
* Add new ModuleApi to set the CaCartsPem
* Wire up the new api
* Update packages/module-api/src/api/client-creation-management.ts
* unit test
* fixup! Add new ModuleApi to set the CaCartsPem
* fixup! Update packages/module-api/src/api/client-creation-management.ts
* fixup! fixup! Update packages/module-api/src/api/client-creation-management.ts
* fixup! fixup! fixup! Update packages/module-api/src/api/client-creation-management.ts
This fallback code path was looking for the wrong error code (M_UNRECOGNIZED is the correct code for endpoints that a server does not implement, and is what Synapse returns on the transports endpoint in practice when msc4143_enabled is false).
* Add missing placement state contract for root and line
* Add editing, information and failure state
* Add bubble placement from state
* Add media and sticker line styling
* Added reply chain styling
* Add interactive stories for states and separate test confgis for baseline screenshots
* Use shared components instead of mocks where available
* Added more relevant slot content data
* Add missing states and use presentation context
* Add state styling
* Fix irc layout dom ordering
* Rearrange styling and add screenshots
* Removed stale screenshots
* Fix Sonar issue
* Add missing layout rule styling and replace legacy application CSS variables
* Updated snapshots
* Minor changes to styling for bubble container and border radius defaults
* rtc: fallback to well-known only if config allows
* Use existing rtc transports cached by client
* post rebase fixes
* post rebase test update
* cleanup callstore tests
* Lint + fmt fixes
* postrebase: update useCall tests
* fixup: fix mocking on useRoomCall task
* fix lint
* fixup lint
* fix missing act in react test
* fix client mocks
* fix test mocking for rtc discovery
* fix test mocking
* fix Callstore testing
* lint:js-fix
* add missing mocks
* Fix duplicate ElementWidgetDriver test cases
* Avoid logging warning about well-known foci when they are undefined
---------
Co-authored-by: Robin <robin@robin.town>
Clicking on custom now opens settings ready to enter a custom status
so most of this PR is passing the flags through for the UI to start in
that state.
* Stop messages flickering through the file panel as they are sent
A filtered timeline set is handed the room's pending events unless it is told
otherwise, and those are the whole room's pending events rather than the ones
the filter would have kept. So every message typed into the room appeared in
the file panel for as long as it took the remote echo to arrive, at which
point the filter finally threw it out again.
The file panel now asks for its timeline set without them. Nothing is lost by
that: a file sent from the panel still appears the moment it is sent, because
the panel adds live events itself and checks the message type while doing so,
which the pending list never did.
Tests: the file panel asks for a timeline set which does not carry the room's
pending events.
* Filter the pending events a filtered timeline set shows
Suppressing the file panel's pending events wholesale was the wrong lever: it is
an all-or-nothing switch on the room's detached pending list, so it also hid
files the user had just sent, and the e2e caught the panel staying empty.
Filter them instead. A timeline set already carries the filter it was built with,
so the pending events it hands the panel can be held to the same test as the
events the server returns. Files being sent still appear immediately; the text
messages that used to flicker through never qualify. Panels with no filter, which
is every other caller, are untouched.
---------
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>