* Widen the macOS title-bar drag strips so the window is easy to move
With titleBarStyle: "hidden" there is no native title bar, so the macOS window can only be
moved via the -webkit-app-region: drag strips above the room and left-panel headers. Those
strips were only ~13-24px tall and too thin to reliably grab, making the window awkward to
move.
Raise the drag strips above the room, left-panel and space headers to 32px (matching the
traffic-light offset already used elsewhere in the file) for a comfortable grab zone;
interactive controls keep -webkit-app-region: no-drag so they stay clickable. The injected CSS
is also extracted into a pure buildTitleBarCss() helper so the string contract can be
unit-tested.
* Address review: use author copyright, cover setupMacosTitleBar, drop dead selector
Use my own copyright on the new test file rather than New Vector's.
Add tests for setupMacosTitleBar() itself: the platform guard and the
enter-full-screen / leave-full-screen / did-finish-load lifecycle were
previously never executed, leaving the diff below the 80% coverage gate.
Drop the .mx_LeftPanel_newRoomList::before rule: #34040 removed that class
from the product, so the rule matched nothing and the border-right it carried
was silently lost from the left panel. Fold it back into .mx_LeftPanel::before,
with a regression test covering the separator.
---------
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
* Warn when an encrypted search runs before the index has finished building
When a search runs in an encrypted room while the local Seshat index is still
crawling not-yet-indexed history, results can silently come back partial.
SearchWarning now subscribes to the event index's changedCheckpoint progress and
shows a polite (role=status) notice while the crawl is in progress, clearing
automatically the moment indexing finishes.
* Scope the partial-index warning to the room being searched
The warning was driven by `currentRoom() !== null`, which is a global signal:
it is non-null while the crawler has any outstanding checkpoint for any room.
Searching a fully-crawled room while an unrelated room was still being crawled
therefore claimed the results may be incomplete when they were not.
Drive it from `crawlingRooms()` instead, which reports the rooms with
outstanding checkpoints by id, and pass the search scope and room id in from
RoomSearchAuxPanel: a room-scoped search now asks only about that room, while
an all-rooms search still reacts to any outstanding checkpoint. Using room ids
throughout also avoids `currentRoom()` returning null, and so under-reporting a
crawl, when the js-sdk does not know the room at the head of the queue.
The `changedCheckpoint` payload only carries the globally-current room and
cannot answer a per-room question, so the handler re-reads the checkpoint set.
* Also warn when the searched room has not been indexed at all
The crawl set cannot see a room that has no checkpoint: before the initial
checkpoints have been seeded, such a room is absent from it and looks identical
to one that has been fully crawled. That is the case issue #32253 describes, so
ask isRoomIndexed() as well, and warn when the index holds no events for the
room being searched.
Only ask it while the crawler still has work outstanding. That is what the
warning claims, and the index has no event for its contents changing --
changedCheckpoint fires on checkpoint transitions only, and an idle crawler is
silent -- so a warning raised once the crawler had drained would never be
re-evaluated and would stick.
Rename the hook to useIsIndexIncomplete, as it no longer answers the narrower
question of whether a crawl is in progress. Re-seed it from the checkpoint set
on each scope or room change so that the previous search's answer is not left
on screen while the lookup is in flight, but not on each checkpoint change,
which would blink an already-earned warning off and on again.
Also reword the crawlingRooms() doc, which described the set as the rooms being
crawled when it holds every queued checkpoint too.
---------
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
* Make the text copy button use IconButton
This obviously should be a shared component, but design is looking at
what it will actually look like long term, so until then, let's at
least make it use compound's IconButton so it gets the hover background
state, and sort out the padding & margins.
Requires https://github.com/element-hq/compound-web/pull/528
* snapshots & add aria-label
* more snapshots
* Remove unnecessary width & height
update other screenshots with expected changes
* One more screenshot
* This really shouldn't be necessary: see what test fails
* Fix test to look in screen for the labels
Because the labels from the tooltip don't go in the container, they
get added to the dom at the top level in a floaty bit.
* update snapshots again
* Fix button size
and also add comment to the other place where we fudge the padding
* Update snapshots
* Align to center
* Screenshots
* use url preview bundle preview content in timeline
* fixed linting errors
* claude wrote a test!
* moved reading settings from the view model into the component
* claude wrote more tests
* applied reviews
* Support for reading m.call status
(well, the prefixed version)
* Abstract the details away in userStatusFromProfile
make the validate functions non-exported
* Add test
* format the oxen
* Remove set function
should be in the other PR
* Conform to oxlint rule jsx-a11y/role-has-required-aria-props
* Conform to oxlint rule jsx-a11y/role-supports-aria-props
* Conform to oxlint rule jsx-a11y/interactive-supports-focus
* Conform to oxlint rule jsx-a11y/click-events-have-key-events
* Update snapshots
Both the tooltip ("Video call") and the aria-label attribute ("Join video call") were trying to set different labels. I propose that the "Video call" tooltip should actually count as a description.
* Move more tests over to vitest
* Add exception for test_setting
* Update find-unused-settings script
To not consider usage in tests as real usage
* Remove legacy font settings
They have been being migrated for over 2 years at this point and are flagged by the script as unused
* Re-add test
* Make the persistent-storage request observable and warn when it is denied
The end-to-end encryption crypto store lives in IndexedDB. If the origin's storage is not
durable, Chromium can evict it under storage pressure, forcing a logout and recovery-key
re-entry. tryPersistStorage() requested navigator.storage.persist() but only logged the
boolean result, so a denial was invisible.
Make the request observable: it is now async and checks persisted() first (short-circuiting
to avoid re-requesting/re-prompting), a failure to query the state no longer blocks the
request, and a denial warns via the logger (captured by rageshakes) with a stronger
desktop-specific message. It never rejects - the sole caller treats it as fire-and-forget.
This makes the risk observable but cannot by itself guarantee durability: no Electron
main-process API can force per-origin persistence, so a complete cure needs a follow-up.
* Address review: log query errors, drop the requestStorageAccess fallback and the desktop-specific warning
- Include the caught error when the persisted-state query fails.
- Remove the document.requestStorageAccess branch: it is the Storage Access
API (cross-site cookie/storage access), not durability, and all supported
browsers (Safari >= 15.2 included) have navigator.storage.persist().
- Drop the desktop-specific suffix from the denial warning.
- Reword the fire-and-forget doc to avoid referencing the caller.
- Simplify the test harness: no descriptor save/restore, delete the stub in
afterEach.
* Space the collapsed space panel separator away from the macOS traffic lights
On macOS the frameless window draws the traffic light buttons over the top
of the space panel. The cluster is inset 9px and is roughly 52px wide, so it
ends about 61px from the window edge. The collapsed space panel is 68px wide,
which left its right-hand separator crowding the green button.
Widen the collapsed panel to 76px on macOS so the separator gets about 15px
of clearance, in line with the compound 4x spacing step. The rule is added to
the styling already injected for the macOS title bar, so it only affects the
desktop app on macOS and is removed in full screen along with the rest.
Fixes https://github.com/element-hq/element-web/issues/32012
Notes: Fix the collapsed space panel separator sitting too close to the macOS traffic light buttons.
* Use contributor copyright header on the new test file
* Add user status to autocomplete suggestion
* Add test for PillCompletion titleIcon
* Convert to vitest
* Add test for UserStatusIcon
* Switch the user status icon view to be a view model based component
* Screenshots
* Add .catch
* Add test for UserProvider
* Expose SDKContextClass via window for debugging
* Remove stores from window if they are exposed via sdkContext
* Avoid usages of global store instance where React context is accessible
* Remove more usages of singleton store getter in favour of contexts
* Remove more usages of singleton store getter in favour of contexts
* Fix tests by adding SDKContext.Provider
* Fix tests by adding SDKContext.Provider
* Fix tests by adding SDKContext.Provider
* Fix tests by adding SDKContext.Provider
* Fix tests
* Fix tests
* Fix tests
* Iterate
* Fix bad merge
* Iterate
* Fix tests
* Iterate
* Iterate
* Iterate
* Iterate
* Iterate
* Improve coverage
* Improve coverage
* Automatically recover from a renderer crash instead of leaving a blank window
The renderer (or GPU process) could die and leave a permanent blank/white window with no
UI, escapable only by killing the whole app. Add a dedicated renderer-recovery module that
detects render-process-gone / unresponsive and reloads or recreates the renderer with capped
backoff, giving up only after repeated failures.
Route the dock-activate and window-show paths through it as well, so a crash that happened
while the window was hidden is recovered before the window is shown rather than surfacing the
white screen.
* Address review: use author copyright and drop empty beforeEach
* Fetch authenticated media through the session for "Save image as"
The desktop "Save image as" context-menu item fetched http(s) images with the
main-process global fetch(), which bypasses the session's webRequest interceptors —
including the authenticated-media handlers in media-auth.ts that rewrite the download
URL and attach the Authorization header. On modern Synapse (authenticated media,
MSC3916) that fetch is rejected with 401/404, so saving an image failed (#32362).
Extract the save logic into a dedicated save-image.ts and fetch network URLs through
the image's Electron session (webContents.session.fetch) so the auth interceptors
apply; data: URLs are still decoded directly into a NativeImage. The module also keeps
the extension-aware encoding (jpg/jpeg/bmp/png) so its contract can be unit-tested.
* Use the contributor's own copyright header on the new save-image files
* Add user status to dm room header
Also bumps the gap on the room header items to 8px because that's
what the designs have and I'm assuming it applies to everything, not
just the user status: pending design confirmation.
* Turns out the icons did have 8px gap
but via 4px of padding for reasons I can't discern
* Adjust spacing to 1.5x
as requested by design
* add tests
* Update screenshots
* add test for user status updating
* Upgrade to TypeScript 7
for massive tsc speed gains
Those on WebStorm will want to upgrade to EAP to reap the benefits of the new TSGo compiler
Some things (module-api & shared-components) which utilise unplugin-dts (and api-extractor) need to hold a copy of ts6 for its conventional lib format and API. TS7 ships with no API until TS7.1.
Other things which use eslint also need ts6 for typescript-eslint.
Some type changes were necessary as TS7 caught some issues.
* Add knip exception
* Fix bad merge
* Fetches link previews for all links in message (instead of just the first one)
* message url component to display preview for multiple urls
* Revert visible behaviour back to only showing one URL preview
While fetching all link previews in the text message.
* Moved URL preview VM to MessageComposer
* Added com.beeper.linkpreviews to messages sent with the markdown compositor
* MSC 4452 implemented for the older (markdown) composer
* claude told me to use logger instead of console
* Previews generated with snapshot instead of vm
* moved attachPreviews to a separate file
* added attach URL previews to rich text editor
* don't let attachUrlPreviews block clearning the composer
* fixed linter errors
* moved url preview behind labs feature gate
* passed linters
* moved lab feature checking to where attach preview is used
* claude wrote some unit tests for url previewing
* fixed linter errors
* added feature to labs.md
* fixed linter errors
* fixed oxfmt error
* set previews to none if all previews failed
* resolved PR reviews besides the ones that requires a larger code change
* moved url preview VM creation to message composer
* removed delay when clearing composer url preview on message send
* minor changes to stop using globals everywhere
* moved debouncing responsibility to urlpreviewVM
* minor lint fixes
* added comment
* remove composer content from the state of urlpreview, moved it to the vm
* urlpreviewwrapper depends on the vm only
* added comments
* edited the comment
* updated snapshots
* claude fixed tests
* enable feature for tests that requires MSC4095
* updated snapshot
* Add a common view snapshot type
This will contain the common snapshot values used by both dm ongoing
call tile view and room ongoing call tile view.
* Implement the common join button component
* Implement the call icon component
* Implement the common container component
* Support single digit minutes in existing clock component
* Implement the view for duration component
* Add static profile pics to be used in storybook tests
* Implement view for member avatar component
* Implement view for face pile component
* Implement RoomOngoingCallTileView
* Implement DmOngoingCallTileView
* Support the new tiles in RootTileView
* Export all the views
* Update all the screenshots
* Implement view model for duration view
* Implement vm for face pile view
* Implement vm for member avatar view
* Expose call store via the sdk context
* Add method to get all calls in store
* Add store to track latest notification event per room
* Also expose new store via sdk context
* Create a base vm for both tiles
* Implement the room ongoing call tile vm
* Implement the dm ongoing call tile vm
* Support new tile vms in the root tile vm
* Rename getCallInRoom -> getCallOrThrow
* Change confusing comment in test
* Check existing events first and use decryption promise
* Clarify recompute vs update in code comment
* Use vi.mocked instead of ts-ignore
* Change type of size to number
* Import only the type
* Pass size as number instead of string
* Check if call is jistsi call in root tile
* Add more tests
* Rename isCallIgnored -> isCallDeclined
* Add a comment about the 10px margin
* Add comments to explain css heights and widths