Commit Graph

415 Commits

Author SHA1 Message Date
Mauro 9093631f8b Periphery cleanup (#5893) 2026-07-20 11:16:11 +02:00
Doug 85f28d017d Update the SDK and handle API breaks. (#5871)
* Update the SDK and handle API breaks.

* Rename sdkUserThing to rustUserThing for consistency.

* Add user status ClientProxy methods.

* Rename UserStatus.UserSet to UserStatus.Raw.
2026-07-14 16:35:37 +01:00
Doug 2c4775f357 Add the UserStatus and a status field on UserProfile/RoomMember/TimelineItemSender. 2026-07-10 17:59:42 +01:00
Stefan Ceriu 4fbfc87551 Add a Messages tab to global search
Split global search into Rooms and Messages tabs. The Messages tab lists
matching events with the room's name and avatar, a sender-prefixed preview,
rich media (image/video/audio/file) previews, and a loading indicator, then
paginates as you scroll. Queries are debounced and the previous one is
superseded so late results can't clobber a newer search.
2026-07-03 13:39:45 +03:00
Mauro 5ea4b46604 Content Scanner Service (#5826)
* implemented the content scanner service with caching and a way to use in the state store context

* fix swiftformat comment enforcing

* pr suggestions
2026-07-02 17:12:39 +02:00
Doug ace05b97d0 Combine the user's own display name/avatar into a single profile.
This is in preparation for adding the user status fields into the profile.
2026-07-02 13:09:34 +01:00
Doug b8860baf49 Rename SearchUsersResultsProxy to SearchUsersResults. It also proxies nothing. 2026-07-02 13:09:34 +01:00
Doug 3ef66cdd05 Rename UserProfileProxy to UserProfile. It's a pure struct and proxies nothing.
Also remove the redundant `userID` property given `id` already exists (for Identifiable conformance).
2026-07-02 13:09:34 +01:00
Doug f3da459d16 Ensure that the current user is the device owner before linking a new device. (#5773) 2026-06-26 16:24:18 +01:00
Stefan Ceriu 0bd32d24fd Switch to a custom HomeserverReachability instead of different publishers 2026-06-24 20:49:49 +03:00
Stefan Ceriu 3ccaa04554 Don't show the server unreachable banner while the client is suspended
homeserverReachabilityPublisher now reports unreachable while suspended so media loading parks instead of failing against a closed store. The reachability banner was keyed off the same publisher, so pausing the client would surface a spurious "Server unreachable" message.

Expose a separate homeserverConnectivityPublisher derived from the sync service state alone (it stays reachable while suspended) and key the banner off that, keeping the suspend-aware publisher for gating work that needs an open store.
2026-06-24 20:49:49 +03:00
svetoslav-sportinno 30e4e6339d Add max selections support for polls (#5726) 2026-06-22 13:39:12 +02:00
Stefan Ceriu 7f1b6086ae Search tab (#5754)
* Add a developer flag for the search tab
Introduces a globalSearchEnabled user preference (off by default) with a toggle in Developer Options, used to gate the new search experience.

* Support search role tabs in the tab coordinator
Migrates the NavigationTabCoordinator to SwiftUI's value-based Tab API and adds an isSearch option so a tab can adopt the iOS 26 .search role, which detaches it into the trailing search button in the tab bar.

* Moves room search to a new screen
Adds a new screen that filters the alternate room summary provider as you type, shows an empty state, and lists matching rooms with their matrix identifier. Supports hardware keyboard selection (arrow keys to move through results, return to open) by reaching into the system search field.

* Present search in a dedicated tab
Adds the search tab to the chats flow on iOS 26 when the flag is enabled, rendered as the detached .search role button. The Cmd+K shortcut now selects this tab, and the home screen's inline search is hidden while the tab is available.

* Remove the old global search screen
The dedicated search tab replaces the Cmd+K floating window, so the GlobalSearchScreen, its window plumbing in the WindowManager, and its presentation in the chats flow are all removed.
2026-06-19 13:50:17 +03:00
Mauro a520d94760 Swift 6 Migration (#5733)
* Enable Swift 6.2 with default main actor isolation for the app target

Turn on SWIFT_VERSION 6.2, SWIFT_APPROACHABLE_CONCURRENCY and SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor for the ElementX target, matching the NSE and Share Extension (which already use 6.2 without the main actor default).

# Conflicts:
#	ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

* Update the code generation templates for Swift 6

Emit nonisolated/@unchecked Sendable mocks and nonisolated string enums, and mark async mock methods @concurrent so they keep suspending like the real implementations (otherwise intermediate states are unobservable in tests). Includes the regenerated mocks and strings.

# Conflicts:
#	ElementX/Sources/Mocks/Generated/GeneratedMocks.swift

* Make the data layer and services nonisolated and Sendable

Annotate the value-type models, Rust SDK proxy wrappers, timeline item graph, settings, logging and NSE-shared types as nonisolated, and conform the service protocols to Sendable so their existentials can cross isolation boundaries. These types run off the main actor and no longer inherit the target's default main actor isolation.

* Adopt the new isolation across call sites, mocks and signatures

Update call sites, closure signatures and mock configuration helpers to match the nonisolated/Sendable data layer, including the main actor isolated mock inits and the @Sendable filter on recentlyVisitedRooms.

^ Conflicts:
^	ElementX/Sources/Services/SecureBackup/SecureBackupController.swift

* Remove redundant @MainActor annotations

With the app target defaulting to main actor isolation, the explicit @MainActor on view models, coordinators, views and their protocols is no longer required.

* Fix concurrency hotspots surfaced by the migration

Resolve the room summary main-thread deadlock by moving diff processing onto AsyncStreams, add the SDKListener.onMainActor FIFO bridge for SDK callbacks, hop KVO/timer/UIKit callbacks to the main actor via assumeIsolated, add isolated deinits, and apply the few justified nonisolated(unsafe) escapes for queue-confined Apple APIs.

* Fix the unit tests for Swift 6 concurrency

Hop the waitForConfirmation body onto the caller's actor (Swift Testing runs confirmation closures off-actor), and adjust the affected suites and async signatures.

* offload diffs on concurrent threads instead of main actor

* make room info protocols sendable

* use a task group for fetching data so that everything runs concurrently in the TextRoomTimelineView when getting the preview.

* use the generic onMainActor implementation, which already makes a stream and send the continuation on the main actor.

* small pr comments issues being addressed

* update enterprise

* Update StaticCode to 1.1.0 and specify the required Swift isolation.

* fix ElementCallServiceTests

* update enterprise

* re-generate mocks

* update enterprise

* enterprise new code conformed to swift 6

---------

Co-authored-by: Doug <douglase@element.io>
2026-06-18 17:55:31 +02:00
Michael 7edca8b5a1 Add a recovery key screen hook. (#5684)
update generateRecoveryKey to take a passphrase option

Wire up AppHooks with recovery key hook

Update xcodeproj

Review fixups

Review fixups

Make the `SecureBackupRecoveryState.viewMode` extension private

Bump the enterprise submodule
2026-06-18 13:28:57 +01:00
Stefan Ceriu 02b114d40b Make ClientProxy.pauseServices async and drop its completion block
`pauseServices` took a completion block only because it was historically
called from `deinit`, which can't await (the SE-0371 note). `deinit` now
stops the sync itself, so the sole remaining caller is the AppCoordinator,
which can await instead.

Make `pauseServices` async and update the AppCoordinator background-task
and lifecycle call sites to await it, calling the OS-facing completions
(endBackgroundTask / setTaskCompleted) afterwards. This also removes the
`MainActor.assumeIsolated` workaround — awaiting a @MainActor method hops
onto the main actor cleanly — and fixes a latent bug where a nil `self` in
the background app refresh expiration handler would skip setTaskCompleted.
2026-06-17 15:17:06 +03:00
Stefan Ceriu 713af64fc6 Switch the clientProxy's start/stop sync semantics to service pausing and resuming to better match underlying behaviors 2026-06-05 14:54:36 +03:00
Stefan Ceriu e4a7322250 Expose the async nature of the ClientProxy startSync method 2026-06-05 14:54:36 +03:00
Mauro da5360c8e8 Hide user dot and track own user marker in Live Location mode. (#5707)
* added a new tracking mode for following a marker and the logic for switching such tracking mode

* implemented the follow marker tracking mode

* improved and added new tests
2026-06-05 13:51:57 +02:00
Stefan Ceriu 2e7b2d1487 Regenerate the mocks 2026-06-03 08:57:04 +03:00
Stefan Ceriu bb2cbb6592 Generate a mock for the TimelineControllerProtocol 2026-05-29 17:48:00 +03:00
Danny eae464ecd7 Timeline: add a Jump to Unread button and a new-message badge on the scroll-to-bottom button. (#5506)
* Timeline: add a Jump to Unread button and a new-message badge on the scroll-to-bottom button.

* Rename scrollToFirstUnread to scrollToReadMarker for consistency with isReadMarkerVisible.

* Cache readMarkerUniqueID and unreadMessageCount as stored properties on TimelineState.

* TimelineViewModel: rename newTimelineItems and drop redundant ordering comment.

* Use Compound chevron icons in TimelineScrollButton.

* Fix TimelineScrollButton layout at large dynamic type sizes.

* Add a trailingAccessory slot to topBanners and use it to dodge banners with the jump-to-read-marker button.

* Put jump-to-read-marker behind a developer-options feature flag.

* Fine-tune TimelineScrollButton sizing and badge colour.

* Remove TimelineScrollButton chevron offset that was compensating for SF Symbol centering.

* Drop the new-messages count, replace with a presence dot.

* Move both timeline scroll buttons to bottom-right and revert topBanners trailingAccessory slot.

* Position TimelineScrollButton badge above for up direction and below for down direction.

* Add long-press mark-as-read pill to the timeline scroll buttons

* Read isSwitchingTimelines from state in updateHasNewMessagesAtBottom.

* Use assertionFailure when scrollToReadMarker is called with no read marker.

* Add TimelineScrollButton preview snapshots.

* (fix) design and various self-review issues

* (fix) suppress scroll button tap after long-press

* (feat) fall back to RoomInfo.fullyReadEventID for jump-to-unread

* (fix) hide jump-to-unread immediately after mark-as-read

* (fix) align with newer matrix-rust-sdk surface

* Bump the RustSDK to v26.05.20

---------

Signed-off-by: Daniel Anderson <daniel.anderson@toptal.com>
Co-authored-by: Stefan Ceriu <stefan.ceriu@gmail.com>
2026-05-21 15:03:32 +03:00
Michael dd0de4d7b0 Custom Notification Tones (#5527)
* added foundation for custom notifications

* feat: add localizations for tone names

also, if available, include the pro sound in the element x sound list

* use a static file location to store the notification tone

and update the file at that location when selected

* if there's a problem previewing or setting the alert tone, toast the user with the error

* rename tone directory

* create NotificationToneManager to handle tone business logic

* conform to project formatting

* assign custom sound to actual notifications

* dry up notification generation in the nse

* add compilation condition for including notification alert tone and remove from share extension

* swift format had some opinions

* flatten the notification tone ui, removing system/elementx designations

* fix stored file url breaking due to sandbox path changes

* tone manager can import custom tones and provide a list of imported tones

* ui support for custom tones

* can delete custom imported tones

* sort the custom tones

* add additional preset sounds

* can choose caf files for custom sounds and fix location persistence issues

* store sound locations with relative links

this is a better solution than storing bookmarks since bookmark resolution can be variable and differ from freshly derived urls

* add docs for new notification features

* run tone conversion in background

* resolved several ai found issues

* added protocol and mocks for notification tone manager

* added tests for notification settings screen vm interactions with the tone manager

* add tests for notification tone manager

* rename element tone names per feedback

* move custom tone option to the top of the notification tone list

* rename Tone to Sound for consistency with Android

* remove additional bundled tones

* restore accidentally deleted Element Default sound file

* system alert tones are filtered by what's available on the system prior to finalizing the collection

* Add a couple more caf file conversion log statements

* Simplify the notification sound conversion logic

* Update notification sound strings in sync with Android

* update xcodeproj after rebase

* remove conditional compilation and include NotificationAlertSound in share extension

* Use AudioPlayer instead of custom tone previewer and remove the previewer

* rename NotificationTone

* Consolidate and move errors to top of NotificationToneManager

* tone manager no longer depends on userinterfacecontroller

* Move static Tone properties to NotificationToneManager

* resolve view model initializer feedback

* update xcodeproj

* fatalerror when tone manager cannot init

* Remove banner icon on alert tone error

* fixup review feedback

* Moved URL handling to NotificationToneManager
2026-05-20 15:40:34 +03:00
Michael 5a07c98afc Make AnalyticsService mockable via `AnalyticsServiceProtocol (#5599)
* Create AnalyticsServiceProtocol and conform AnalyticsService

* Replace AnalyticsService properties and arguments with AnalyticsServiceProtocol

* Inline AnalyticsServiceMock replacing old mock

* handle more complex AnalyticsServiceMock callsites

* move documentation from AnalyticsService to AnalyticsServiceProtocol
2026-05-20 08:23:58 +03:00
Mauro 6c0aaa7a58 Invite the DM recipient to a new room (#5588)
* handle the details to invite users flow.

* implemented the room creation in the invite screen, and its dismissal + navigaton to the newly created room

* updated preview and unit tests

* pr suggestions
2026-05-18 10:08:07 +02:00
Mauro Romito a4a857003c use isDM from the SDK to determine if a spaceRoom, a joinedRoom or a notificationItem are from a dm room. 2026-05-14 13:47:44 +02:00
Stefan Ceriu f70182d09a Add a developer option button for marking every single room as read (#5582)
This will use an underlying SDK method and send a private read receipt plus a fully read marker in every single room the user is part of. It will most likely be a long operation that will get rate limited so the task is set to run detached for as long as it takes.
2026-05-13 19:46:52 +03:00
Mauro Romito d5170ae4cc Revert "use isDm from the SDK to determine if a room is a direct one to one room."
This reverts commit 58d0841bedb9cc40bd5880a76f3cc1f56c3b8bdb.
2026-05-06 13:04:11 +02:00
Mauro Romito b5d9f03ad0 use isDm from the SDK to determine if a room is a direct one to one room. 2026-05-06 13:04:11 +02:00
Mauro 76f744b9c4 Live Location Sharing - handle server echoes (#5514)
* Track active live location sessions by ID instead of timeout.

# Conflicts:
#	ElementX/Sources/Services/Location/LiveLocationManager.swift

* implemented a system to promote starting session to active sesessions to send locations at the right time, and a system to remove a local session if it's handled by an external device.

* pr suggestions

---------

Co-authored-by: Doug <douglase@element.io>
2026-04-30 13:18:36 +00:00
Mauro Romito 6dc6eed9e3 stop showing live location disclaimer when accepted. 2026-04-22 18:17:17 +02:00
Mauro Romito ad2143f334 use current value subject and current value publisher for LiveLocationShare updates 2026-04-22 16:43:18 +02:00
Mauro 55f82e69b1 Improve Live Location Sharing with reduced accuracy mode (#5461) 2026-04-22 13:12:03 +02:00
Mauro Romito 2250087cfe handle reduced accuracy authorization case 2026-04-21 13:51:40 +02:00
Mauro Romito 53f6c66a8b use CLLocationManager directly to handle location updates since is more reliable in bg and more configurable 2026-04-21 12:32:50 +02:00
Mauro Romito 676c90c484 allow users to set live location minimum distance update 2026-04-21 12:32:50 +02:00
Valere Fedronic d49a6e5a5d Support for ongoing voice vs video call + joining (#5399) 2026-04-21 09:11:52 +00:00
Doug eef4a2497a Add support for homeserver capabilities to disable the UserDetailsEditScreen UI. (#5421)
Add support for homeserver capabilities to disable editing your user profile.

Also updates editable avatar size/formatting to match the latest Figma at the same time.
2026-04-17 11:52:46 +01:00
Mauro Romito a40fab5f5e pr suggestions 2026-04-14 14:17:27 +02:00
Mauro Romito facba008e7 implement APIs for LLS observation 2026-04-14 14:17:27 +02:00
Mauro 8bfdc70b9c Fix LiveLocationManager flaky tests (#5389) 2026-04-13 18:05:47 +02:00
Doug 7c812201cb Verify Element X with an existing Element Classic account. (#5374)
* Read and import the secrets from ClassicAppAccounts.

* Record snapshots.

* Add some documentation, tidy up tests and fix the dismissal of the backup instructions.

* Workaround flakey tests (the fulfilments weren't always firing).

* Allow a custom Classic App deep link URL to be configured.
2026-04-13 15:30:09 +01:00
Doug 1a5a709e27 Add a view to show the user's account from Element Classic. (#5361)
No presentation logic yet.
2026-04-08 21:18:03 +01:00
Mauro Romito d9a480b1c6 pr suggestions 2026-04-03 12:36:45 +02:00
Mauro Romito df5570281b implement the start, send and stop functions 2026-04-03 12:36:45 +02:00
Stefan Ceriu a358cacf31 Hook up the RoomThreadList to the RoomFlowCoordinator state machine and presenting threads. 2026-04-01 14:09:23 +03:00
Stefan Ceriu 4abf9112f4 Rename "Auxiliary" windows to "Secondary" windows 2026-03-31 20:33:33 +03:00
Stefan Ceriu 3b858a4073 Disable multiple windows when screen lock is enabled. 2026-03-31 20:33:33 +03:00
Stefan Ceriu b7333b9b5f Clean up the window manager and its protocols 2026-03-31 20:33:33 +03:00
Stefan Ceriu bb61db285b Dismiss a room's window when its flow finishes as there's no longer a reason for it to be alive. 2026-03-31 20:33:33 +03:00