RoomListItemViewModel rebuilt the "Move to section" submenu list via
getCustomSectionData() inside every snapshot rebuild - i.e. on every
notification, name, tag or call update of every live room item - even
though the available sections only change when the custom section
settings change. Each call rebuilds the record from settings and does
an O(spaces) existence check per section.
Cache the available sections (tag + name) in the view model and
rebuild them only from the settings watchers; per-room snapshots now
only derive the cheap isSelected flag. Also watch
RoomList.CustomSectionData so section renames propagate to the
submenu (previously only the order setting was watched).
* refactor(room-list): migrate SpaceStore off the legacy room list store
SpaceStore.setActiveRoomInSpace iterated the legacy RoomListStore's
`orderedLists` in `TAG_ORDER`; switch it to the space-aware
RoomListStoreV3.getSortedRoomsInActiveSpace() accessor. This drops the
last non-UI dependency on the legacy store and on `TAG_ORDER` (exported
from LegacyRoomList, deleted next).
* feat(room-list)!: remove the legacy room list UI
Delete the old sublist-based room list and its components now that the
new RoomListPanel is the default. Removed: LegacyRoomList,
LegacyRoomListHeader, RoomSublist, ExtraTile, RoomTile (+ Subtitle/
CallSummary), RoomBreadcrumbs and RoomSearch, plus their styles and
tests.
LeftPanel collapses to the RoomListPanel-only path. The shared
`contextMenuBelow` helper is relocated into RoomResultContextMenus (its
only remaining consumer).
* feat(room-list)!: remove the legacy RoomListStore
The legacy sublist-based room list UI is gone, so the old
`stores/room-list` store (Algorithm, sorters, filters, layout store,
space
watcher) has no remaining consumers. Delete the directory and its tests.
MatrixChat.forgetRoom no longer calls the legacy `manualRoomUpdate`; the
new room list store removes the room on the `AfterForgetRoom` dispatch
that still fires. Drop the `mxRoomListStore`/`mxRoomListLayoutStore`
globals and the now-dead test imports.
* feat(room-list)!: remove the feature_new_room_list labs flag
The new room list is now the only room list, so remove the
feature_new_room_list labs flag and make its enabled behaviour
unconditional everywhere it was gated:
- LoggedInView: always use the resizable layout and
NEW_ROOM_LIST_MIN_WIDTH;
drop the collapsible/minimized legacy path.
- SpaceStore: People and Favourites are dropped from metaSpaceOrder (per
the
long-standing TODO on the removed accessor).
- MessagePreviewStore: stop appending thread replies to previews.
- Settings, SidebarUserSettingsTab, PreferencesUserSettingsTab,
QuickSettingsButton, SpacePanel, LandmarkNavigation: drop the flag
reads and
legacy branches.
Update the tests that toggled the flag; the People/Favourites meta space
tests covered behaviour that the flag (default on) already disabled.
* feat(room-list)!: remove the dead legacy left-panel resizer
LoggedInView still built the old `Resizer`/`CollapseDistributor` over an
`lp-resizer` ResizeHandle and persisted `mx_lhs_size`. That handle is no
longer rendered (the resizable layout is now driven by
LeftResizablePanelView + ResizerViewModel, which persists its own state
via RoomList.panelSize/RoomList.isPanelCollapsed), so the old resizer
was
inert dead code left over from the legacy room list.
Remove createResizer/loadResizer/loadResizerPreferences, the
_resizeContainer/resizeHandler refs, the ResizeHandle render, the
mx_lhs_size handling and NEW_ROOM_LIST_MIN_WIDTH, plus the unit tests
that
exercised the mocked resizer.
* feat(room-list)!: update i18n files
* refactor(room-list): remove the now-unused collapseLhs state
`collapseLhs` is write-only since the left panel no longer collapses: it
was last read by LoggedInView's `shouldUseMinimizedUI`, removed with the
feature_new_room_list flag. Drop it from MatrixChat's IState (and its
assignments), collapsing the hide/show_left_panel handlers to just the
`notifyLeftHandleResized()` call they still need, and from
LoggedInView's
IProps and the test props.
* fix(room-list): instantiate message previewers lazily
Removing the unused SettingsStore import from MessagePreviewStore (when
the
feature_new_room_list flag was dropped) changed module load order and
exposed a latent circular dependency: ReactionEventPreview imports
MessagePreviewStore, which eagerly did `new ReactionEventPreview()` at
module-eval — so importing ReactionEventPreview first (as its unit test
does) hit "ReactionEventPreview is not a constructor".
Construct the previewers lazily on first use (cached) instead of at
module
load, so nothing dereferences a mid-evaluation module. Fixes
ReactionEventPreview-test.
* test(room-list): remove `feature_new_room_list` labs flag in e2e tests
* chore: remove remaining `newRoomList` flag
* chore: cleanup theme files
* fix: restore the re-resizable TouchEvent polyfill
* chore: remove usage of breadcrumbs settings in BreadcrumbStore
* Revert "fix(room-list): instantiate message previewers lazily"
This reverts commit 4e6eedfff0449c68a96c0470a4eb425b5aec5512.
* chore: remove unused function in BreadCrumbStore
* test: remove unused fuction of BreadcrumStore in tests
* test: add tests for RoomResultContextMenu
* Separate out SDKContext
...from SDKContextClass, as the comments hopefully explain.
Also make the captitalisation consistent.
* Adding the new file usually helps too
* Fix import
* More comment
* Update the various imports of SDKContextClass
* Also fix case of TestSDKContext
* Update the mock
* fix(room-list): instantiate message previewers lazily
Removing the unused SettingsStore import from MessagePreviewStore (when
the
feature_new_room_list flag is dropped) changed module load order and
exposed a latent circular dependency: ReactionEventPreview imports
MessagePreviewStore, which eagerly did `new ReactionEventPreview()` at
module-eval — so importing ReactionEventPreview first (as its unit test
does) hit "ReactionEventPreview is not a constructor".
Construct the previewers lazily on first use (cached) instead of at
module
load, so nothing dereferences a mid-evaluation module. Fixes
ReactionEventPreview-test.
* refactor: pass MessagePreviewStore to ReactEventPreview
* Modify LinkPreview to export shared atomics
* Implement MessageComposerUrlPreviewView
* Create UrlPreviewFetcher utility function
* Modify view models
* Implement in composer
* Support running tests in dom-less vitest environment
* Add a playwright test
* hide another one
* fmt
* cleanup
* test rte too
* fixup
* Add back docstring
* cleanup
* off by one
* remove description check
* Cleanup hacks
* Remove another hack
* cleanup
* one more
* fixup window here too
* whoops type
* Rename to be cleaeer
* Trim URLs first
* fix bug
* Pluralise the multi-session remove button and confirmation dialog
When several sessions are selected in Settings > Sessions, the bulk remove button and its confirmation dialog used the singular "Remove this device" string. The singular "this" misleadingly implied the current device would be removed. Use the existing count-aware settings|sessions|sign_out_n_sessions key, matching the other-sessions menu, so the label reads "Remove N sessions".
Fixes#33812
* Update device-management e2e test for the pluralised remove button
The multi-select remove button now reads "Remove N sessions" instead of "Remove this device", so update the Playwright assertion to match.
* Put "Cancel" before "Remove N sessions" in the bulk session action bar
In the "Other sessions" multi-select action bar, "Remove N sessions" was
rendered before "Cancel", which placed the destructive action on the left.
Swap the two buttons so "Cancel" is on the left and "Remove N sessions" on the
right, per review feedback on #33983.
* Move ToastContext and utilities to shared components
* lint
* fix type
* cleanup
* fix broken test
* fix lint
* Add more tests for ToastContext
* Potential fix for pull request finding 'Unused variable, import, function or class'
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
---------
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
* Mock out window.addEventListener globally
As some code uses it
* Move to setupGlobals
* clean up import
* Only needed if we don't have happy-dom
* thank you!
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
---------
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
* feat:add missing methods to rls V3
* feat: use rls v3 methods instead of old alrgorithms
* feat: move stabel function to own utils
* feat: use this new moved functions
* test: cleaner test
* Don't re-export MainSplitContentType enum
I don't see why this was necessary, importing RoomView pulls in all sort
of stuff, whereas RoomContext is much smaller.
* ts, not tsx
* unintentional change
* Forward the scroller element and scroll handle through VirtualizedList
The room list needs two things the generic list did not expose: the underlying
scroll container (to observe which items are genuinely visible) and the imperative
scroll handle (to scroll an item into view). Forward an optional scrollerRef from
useVirtualizedList and pass scrollHandleRef through FlatVirtualizedList, mirroring
what GroupedVirtualizedList already exposes. Both are additive and optional, so other
consumers are unaffected.
Signed-off-by: David Langley <langley.dave@gmail.com>
* Add an unread-activity toast to the room list
Show a clickable "You have unread activity" pill when there are unread rooms
scrolled below the visible fold, including unreads hidden inside collapsed sections
whose header is below the fold. Clicking it scrolls the next such unread into view.
The visible fold is tracked with an IntersectionObserver over the rendered item
elements, so the toast appears as soon as a room crosses the fold rather than only
once it leaves Virtuoso's overscan buffer. The toast click is wired through an
imperative scroll handle the view registers with the view model.
Signed-off-by: David Langley <langley.dave@gmail.com>
* Change toast to target notifications only, not unread activity.
* Fix formatting and refresh Toast snapshots for compound-web 9.7.0
- Apply oxfmt to the room list view model and virtualized view.
- Refresh the RoomListToast/RoomListView story snapshots: compound-web
9.7.0 moves the typography classes onto the toast .content element and
rebuilds the Toast CSS module hashes.
- Add the missing UnreadActivityToast render snapshot baseline.
* Add e2e tests for the room list unread activity toast
Cover the unread-activity toast end to end:
- it appears for a notifying room scrolled below the fold and clicking it
scrolls that room into view (then the toast clears);
- a room with only an unread-activity dot (no notification count) does not
raise it;
- a collapsed section hiding a notifying room raises it, and clicking
scrolls the section header into view.
* Add visual snapshot baselines for the unread-activity toast stories
* Converge room-list toast codepaths into a single state-driven toast
Reviewer feedback: the unread-activity toast and the transient event toasts
(section_created / chat_moved) should share one mechanism, with toast
lifecycle and precedence owned by the view model rather than split across a
separate snapshot flag and a view-level ternary.
- RoomListViewModel now reconciles the transient event toast and the derived
unread-activity state into a single snapshot.toast via recomputeToast(); the
event toast still takes precedence and auto-dismisses, and the unread toast
reappears once it clears. Drops hasUnreadActivityBelow from the snapshot.
- RoomListView renders a single RoomListToast driven by snapshot.toast; the
ToastType union gains 'unread_activity'. The standalone UnreadActivityToast
component is folded into RoomListToast (clickable arrow-down variant).
- Adds VM tests for the unread-activity toast and the event/unread precedence.
* Pre-bundle the room-list dnd-kit + virtuoso graph in vitest browser mode
The room-list suites (RoomListView, VirtualizedRoomListView,
RoomListItemMoreOptionsMenu) import a heavy @dnd-kit + react-virtuoso graph.
Only @dnd-kit/abstract was pinned in optimizeDeps.include; @dnd-kit/dom,
@dnd-kit/react, @dnd-kit/abstract/modifiers and react-virtuoso were left to
runtime discovery. Under CI load the browser-mode dep optimizer can discover
them late, re-bundle and reload the page, which fails the in-flight
setupTests.ts import for those suites. Pinning the whole graph forces it into
the initial optimize pass so no re-run happens while tests load.
---------
Signed-off-by: David Langley <langley.dave@gmail.com>
* feat(rls): centralize room-list section ordering via getOrderedSections
Introduce a single source of truth for the ordered list of section
tags (defaults + custom) in section.ts. RoomListStoreV3 no longer
hard-codes the default tag order — it asks section.ts.
* feat(vm): add section reorder logic to RoomListStoreV3 and view model
* refactor(sc): extract RoomListSectionHeaderContent from RoomListSectionHeaderView
* feat(sc): add drag-and-drop reordering for room-list sections
* test(sc): update existing tests
* test: add new tests
* test(sc): add snapshot test for overlay
* test(e2e): add playright test for dnd of sections
* feat: tweak opacity
* fix: section detection when dragged
* feat: use relative position in section order
* chore: move style to room list section header view
* test: add e2e test for moving section before another
* feat: make favourite and low priority no draggable
* test: remove deprecated e2e test
* fix: type correctly dnd provider and hooks
* fix: use String instead of casting to string
* fix: wrong a11y attributes on section header
* test: fix keyboard navigation e2e tests
* feat: use custom a11y announcement for dnd
* fix: add aria-hidden to the overlay
* chore: remove duplicated code in a11Y announcement
* fix: increase keyboard drag offset
* fix: tests
* fix: virtuoso computed item key
* fix: aria-expanded double annoncement why dragging
* fix: re-add screen reader instructions
* chore: remove unused import
* fix: reduce keyboard drag offset
* fix: improve text readback on unread section
* feat: use a custom a11y plugin instead of buitin a11y plugin
* chore: formatting
* test: fix incorrect tests
* chore: use randomUUID
* fix: try to make test working
* fix: put back mock
* fix: circular import
* Revert "fix: circular import"
This reverts commit 6c69313ade9ed2ab17a4622c692b435fbdb94ad2.
* chore: add @dnd-kit/abstract to optimizeDeps.include
* test: fix e2e tests
* fix: disable interaction with section when dragging
* fix: be more explicit if the section will be dropped before or after
* fix: add info that space is dropping too
* fix: scroll to dropped section
* test: fix virtualized room list test
* chore: update lang
* chore: fix dead code analyze
* test: add provider section story
* fix: lang
* fix: again lang...
* fix: improve voice over on chrome
* test: upate snapshot
* fix: add readback when a section is over a non droppable element
* Replace override raw-loader with `?raw` query
For compatibility with vite/st
* Make knip happy
* Fix icon in Jitsi lobby
* Fix jest config for `?raw`
* Remove stale `$webapp` alias
* Ensure css files loaded as `?raw` do not get bundled
* Switch from prettier to oxfmt
* Make knip happy
* Make knip happy
* Apply suggestion from @t3chguy
* Rename .oxfmtrc.json to .oxfmtrc.jsonc
* Make oxfmt happier
* Add user status on user profile icon
Currently unstyled & no tests
* Style the user status icon
* Update snapshot
for avatar wrapper
* More snapshot updates
* add if braces
* Split out user status functions
to avoid circular dep which has the weird effect of just breaking
jest's mocking.
* type imports
* Update imports
* Update snapshot
* Tests
* baseline image
* Just snapshot the component itself
* User status in user menu
first pass, unstyled
* fix export
* superstylin'
* snapshots
* Add story & test
* Snapshots
and re-use the repeated rules
* Tests
* Fix jest lcov projectRoot config
* Change tooltip text to just 'clear'
* Add comment & fix console warn
* Remove all options screenshot
as it's not really particularly useful as a preset story
* remove stale screenshot
* fix imports
---------
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
* Use vitest for some EW unit tests
* Ensure library builds are done before unit tests
* Stabilise jest tests
* Move more tests over
* Make sonar happier
* Update types/node for happy-dom compat again
* Decrease max-workers to stabilise jest tests
* Split jest over 3 runners to alleviate memory woes
* Switch jest to runInBand
* Attempt to deflake jest tests
* tweak coverage
* tweak coverage
* fix: don't display the empty/collapse icon when the room list is empty
* Fix jest lcov projectRoot config
---------
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
* First version of shared component
* Refactor as a functional component
* Add unit tests and more documentation
* Fix problem where wrappedRef was used by parent before assignment was performed.
* Use the shared component in app/web
* Clean up unused styling
* Added scrollbar-gutters as default styling in shared component
* Make sure the legacy mx_AutoHideScrollbar is set in app/web
* Updated snapshots
* Removing default style, scrollbar-gutter: stable;
* Updated snapshots
* useRef on wrapperRef to avoid loop in rendering
* scrollbar-width does not propagate
* Add AutoHideScrollbar to RoomListView
* Fix Prettier issue
* Updated snapshots
* Updated snapshot after merge
* Fix Sonar issue