Commit Graph

527 Commits

Author SHA1 Message Date
Sedat Qaja d01d04846a feat(healthchat): advertise the account status in settings
Pending approval and an incomplete profile were only visible in the
members tab, which a new user has no reason to open.
2026-10-09 14:41:58 +02:00
Sedat Qaja b70e77f7c5 feat(healthchat): show default contacts while approval is pending
An unapproved account only gets the server's default contacts, which are
its way to reach support — list them instead of discarding them, and hide
the search field that cannot return anything.
2026-10-09 14:23:39 +02:00
joel.poyet b475cc7e9a Let members edit their profile and invite others (#12)
* Add HealthChat API and extended profile services

Expose OpenID tokens and homeserver credentials from the client proxy, and
add fork-only services for the HealthChat member directory backend
(api.healthchat.ch) plus a service that reads MSC4133 extended profile
fields directly from the homeserver. Groundwork for the members tab and
the profile screens.

Claude-Session: https://claude.ai/code/session_013qdTbAWsZj2quQzEkagXaS

* Show extended profile details on the profile screens

Add a UserProfileScreenHook that lets the fork inject an extra Form
section below the header of the user profile and room member details
screens. The HealthChat implementation loads the MSC4133 extended
profile fields and renders them with tappable phone/email/website
links, hiding the section entirely for profiles without any fields.

Strings live in a new fork-only HealthChat.strings table (de/en/fr,
generated as HealthChatL10n via SwiftGen) since Untranslated.strings
pins the English bundle.

Claude-Session: https://claude.ai/code/session_013qdTbAWsZj2quQzEkagXaS

* Add a member directory tab

Add a HomeTabsHook that lets the fork append an extra tab to the home
tab bar, and a HealthChat members flow behind it: a directory of all
approved members from the HealthChat API with server-side search,
pending-approval and error states, chat shortcuts and pushed member
profiles. Chats and calls are handed back to the session flow via the
hook's actions publisher.

Claude-Session: https://claude.ai/code/session_013qdTbAWsZj2quQzEkagXaS

* Let members edit their profile and invite others

Add a native profile editor for the HealthChat extended profile fields
(13 fields plus avatar, saved as a partial diff through the HealthChat
API so displayname derivation and Zitadel sync stay server-side), an
invitation sheet (email plus personal note) and a profile-completeness
hint on the member directory.

A new UserDetailsEditScreenHook lets the fork substitute the profile
editor behind the settings user row — the stock display-name editor
would let users edit a value the next profile update derives away.

Claude-Session: https://claude.ai/code/session_013qdTbAWsZj2quQzEkagXaS
2026-09-22 18:27:37 +02:00
joel.poyet 93149f1cbd Add a member directory tab (#11)
* Add HealthChat API and extended profile services

Expose OpenID tokens and homeserver credentials from the client proxy, and
add fork-only services for the HealthChat member directory backend
(api.healthchat.ch) plus a service that reads MSC4133 extended profile
fields directly from the homeserver. Groundwork for the members tab and
the profile screens.

Claude-Session: https://claude.ai/code/session_013qdTbAWsZj2quQzEkagXaS

* Show extended profile details on the profile screens

Add a UserProfileScreenHook that lets the fork inject an extra Form
section below the header of the user profile and room member details
screens. The HealthChat implementation loads the MSC4133 extended
profile fields and renders them with tappable phone/email/website
links, hiding the section entirely for profiles without any fields.

Strings live in a new fork-only HealthChat.strings table (de/en/fr,
generated as HealthChatL10n via SwiftGen) since Untranslated.strings
pins the English bundle.

Claude-Session: https://claude.ai/code/session_013qdTbAWsZj2quQzEkagXaS

* Add a member directory tab

Add a HomeTabsHook that lets the fork append an extra tab to the home
tab bar, and a HealthChat members flow behind it: a directory of all
approved members from the HealthChat API with server-side search,
pending-approval and error states, chat shortcuts and pushed member
profiles. Chats and calls are handed back to the session flow via the
hook's actions publisher.

Claude-Session: https://claude.ai/code/session_013qdTbAWsZj2quQzEkagXaS
2026-09-22 18:26:37 +02:00
joel.poyet 352d25f2bb Show extended profile details on the profile screens (#10)
* Add HealthChat API and extended profile services

Expose OpenID tokens and homeserver credentials from the client proxy, and
add fork-only services for the HealthChat member directory backend
(api.healthchat.ch) plus a service that reads MSC4133 extended profile
fields directly from the homeserver. Groundwork for the members tab and
the profile screens.

Claude-Session: https://claude.ai/code/session_013qdTbAWsZj2quQzEkagXaS

* Show extended profile details on the profile screens

Add a UserProfileScreenHook that lets the fork inject an extra Form
section below the header of the user profile and room member details
screens. The HealthChat implementation loads the MSC4133 extended
profile fields and renders them with tappable phone/email/website
links, hiding the section entirely for profiles without any fields.

Strings live in a new fork-only HealthChat.strings table (de/en/fr,
generated as HealthChatL10n via SwiftGen) since Untranslated.strings
pins the English bundle.

Claude-Session: https://claude.ai/code/session_013qdTbAWsZj2quQzEkagXaS
2026-09-22 18:25:27 +02:00
joel.poyet 2c1270ec79 Rebrand as HealthChat and pin the account provider to healthchat.ch
Applies the HealthChat product identity through the fork seams upstream already
provides, so no upstream logic files are touched and merges stay clean.

- Variants/HealthChat/healthchat.yml holds the identity scalars (display name,
  bundle id ch.healthchat.element, app group, development team) and is included
  permanently from project.yml. APP_NAME stays ElementX so the module name and
  @testable import ElementX keep working.
- ElementX/Sources/AppHooks/HealthChat/ registers an AppSettings hook pinning
  accountProviders to healthchat.ch with other providers disabled, push through
  sygnal.healthchat.ch and a custom-scheme OIDC redirect; plus a Compound hook
  recolouring the accent token family to the HealthChat blue.
- Entitlements are edited directly in ElementX/SupportingFiles/target.yml rather
  than in the variant, because XcodeGen concatenates arrays on include-merge and
  a variant can override scalars but cannot remove array entries. Drops the
  Element Classic app group and keychain group, and narrows associated domains
  to app.healthchat.ch, keeping matrix.to for permalinks.
- Info.plist CFBundleName now follows APP_DISPLAY_NAME — it, not
  CFBundleDisplayName, is what the web authentication sign-in alert shows.
- App logo and app icon assets swapped in place; the onboarding welcome title
  moves to a new screen_onboarding_welcome_title_ios untranslated string.
2026-09-22 18:19:59 +02:00
ElementRobot e32e1dd388 Translations update (#6111)
* Translations update

* update preview tests

---------

Co-authored-by: Element CI <ci@element.io>
Co-authored-by: Mauro Romito <mauro.romito@element.io>
2026-09-08 13:08:25 +02:00
Mauro 346a1e8ebb Redaction reason (#6098) 2026-09-07 18:57:05 +02:00
Stefan Ceriu 2ae8b9bf75 Promote knocking to labs 2026-09-03 11:44:32 +03:00
Stefan Ceriu 6839258111 Promote gallery messages to labs 2026-09-03 11:44:32 +03:00
Matthew Hodgson eec2facab1 Add a Mentions room list filter (#5885)
* Add a Mentions room list filter

Adds a new filter chip to the room list that shows only rooms with
unread mentions, using the new mentions room list filter from the
Rust SDK (matrix-org/matrix-rust-sdk branch matthew/mentions-filter).

The SDK version needs bumping to a release that includes the new
filter kind before this can build against the released components.

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

* Order the room list filters by expected usage

Move Favourites ahead of People and Rooms so the more commonly used
filters (Unreads, Mentions, Favourites) sit first in the chip row —
Rooms and Invites are used rarely enough that it's fine for them to
wrap off the side.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uk8aPxHn3BHCe52L226jdG

* update the SDK and use the appropriate rust filter types

* preview tests + app settings flag for mentions

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Mauro Romito <mauro.romito@element.io>
2026-09-01 18:08:00 +02:00
ElementRobot 9b22ca3cd2 Translations update (#6088)
* Translations update

* swiftformat .

* update previews

---------

Co-authored-by: Element CI <ci@element.io>
Co-authored-by: Mauro Romito <mauro.romito@element.io>
2026-08-31 12:30:26 +02:00
Aaron Thornburgh 600b9224b3 Updates to Notification Settings (#6075)
* Updates to Notification Settings

Move "Invitations" and "Notify me on @room" to the section labeled "Notify me for"

* Record preview snapshots

* Update @room mentions label.
2026-08-27 14:21:15 +01:00
Element CI b864918686 Translations update 2026-08-24 14:49:17 +02:00
ElementRobot f090f30e7e Translations update (#6036)
* Translations update

* Update snapshots.
2026-08-17 14:17:05 +00:00
ElementRobot 3f6021bcd1 Translations update (#5999)
Co-authored-by: Element CI <ci@element.io>
2026-08-10 09:50:06 +01:00
Mauro Romito 1407a1d5b4 implemented a11y for galleries 2026-08-03 14:33:12 +02:00
ElementRobot 9a1db7e664 Translations update (#5965)
Co-authored-by: Element CI <ci@element.io>
2026-08-03 09:56:19 +01:00
Matthew Hodgson a8c79fdd46 Implements push notifications for LLS via MSC4505 (#5872)
* Render live location share start push notifications in the NSE

Live location sharing starts with a cleartext org.matrix.msc3672.beacon_info
STATE event, which the NSE previously rendered as the generic fallback
notification because NotificationContentBuilder only handled message-like
event content.

- Handle .state(.beaconInfo) in NotificationContentBuilder: sender display
  name as the title (same as other messages) with a new localized body,
  "Started sharing their live location".
- Let beaconInfo state events through NotificationHandler's preprocessing
  (all other state events are still discarded).
- Add notification_live_location_started_body, imported from Localazy.
- Unit tests for the new state-event notification paths.

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

* rename processMessageLike in processAsMessage

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Mauro Romito <mauro.romito@element.io>
2026-07-27 16:31:47 +02:00
ElementRobot 5262350b40 Translations update (#5931)
* Translations update

* update preview tests

---------

Co-authored-by: Element CI <ci@element.io>
Co-authored-by: Mauro Romito <mauro.romito@element.io>
2026-07-27 14:36:14 +02:00
Doug 94313173f0 Add a warning to the Link New Device instructions. (#5916) 2026-07-22 14:56:49 +01:00
Stefan Ceriu c0385ccdfa Change the first search tab name from Rooms to Chats (still untranslated for now) 2026-07-22 15:40:56 +03:00
Doug a0ec5ed9dd Add the UI for your own user status in the Settings screen. (#5888)
* Show the user's own Status emoji on the SettingsScreen.

* Add the UI for setting your own status.

* Add placeholder action for selecting a custom emoji and fix some accessibility issues.
2026-07-17 12:21:51 +01:00
ElementRobot e8db3cff77 Translations update (#5865)
Co-authored-by: Element CI <ci@element.io>
2026-07-13 11:10:27 +01:00
Doug 2c4775f357 Add the UserStatus and a status field on UserProfile/RoomMember/TimelineItemSender. 2026-07-10 17:59:42 +01:00
Mauro Romito 5ba9296a65 new location request permission strings 2026-07-09 14:54:24 +02:00
Mauro a2c1ca06dd Content Scanning View (#5831)
* implement a MediaView to delegate at the view level the usage of the content scanner service, to determine how to render the media.

* fix for a small design mismatch

* fix for greedy error state

* updated naming

* just making some screenshot that have been affected by a string change on Localazy

* pr suggestions + updated strings
2026-07-06 16:15:27 +02: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
ElementRobot bfd3756671 Translations update (#5802)
Co-authored-by: Element CI <ci@element.io>
2026-06-29 11:12:13 +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
Mauro Romito 24af5804d6 use … in place of ... 2026-06-23 15:38:41 +02:00
Mauro Romito 2dc4a24333 update preview tests 2026-06-23 15:38:41 +02:00
Mauro Romito d60b41a05f Add a programmatic label to the join room by address field
The field relied on its placeholder for a label, which VoiceOver only reads
while empty. Set a persistent accessibility label so it's always announced.

Addresses #5256.
2026-06-23 15:38:41 +02:00
Mauro Romito 87d18fe8e3 migrated the max answers poll feature strings to localazy 2026-06-23 13:05:48 +02:00
svetoslav-sportinno 30e4e6339d Add max selections support for polls (#5726) 2026-06-22 13:39:12 +02:00
amshak 9f92e181b0 Added a chevron to collapsed call buttons in the DM (#5755)
* Added a chevron to collapsed call buttons in the DM

This makes the context menu more intuitive and easy to find. Inspired by the collapsed state of call buttons in Whatsapp that I saw recently

* Shortening video/voice call button strings

Currently the text is unnecessarily long, I have reduced to button text

# Conflicts:
#	ElementX/Sources/Generated/Strings+Untranslated.swift

* Move translations to localazy

---------

Co-authored-by: Stefan Ceriu <stefan.ceriu@gmail.com>
2026-06-22 13:23:37 +03:00
Mauro Romito f32b9eeb26 Mark RoomSummary extensions as nonisolated
The RoomSummary struct is nonisolated, so its CustomStringConvertible and
helper extensions should be too.
2026-06-19 13:45:38 +02:00
Mauro Romito 8a4e4d1903 Give the media upload preview a descriptive VoiceOver title
The QLPreviewItem used the media's file name as its title, which VoiceOver
read as cryptic alt text. Provide a descriptive "Photo preview" / "Video
preview" title based on the media type instead.

Addresses #5240, #5241.
2026-06-19 13:45:38 +02:00
Stefan Ceriu fbbdb6f5f7 Fix iOS specific notification sound localizable keys. 2026-06-19 14:11:28 +03: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
Mauro Romito dc29be5898 voiceover reads add avatar when there is no avatar yet 2026-06-16 18:25:37 +02:00
Element CI 34ada2d933 Translations update 2026-06-08 13:36:03 +02:00
Element CI 24b9143901 Translations update 2026-06-01 12:23:01 +01:00
Element CI 0f976a49aa Translations update 2026-05-25 16:50:05 +03:00
Stefan Ceriu 9609fa4616 Add notification setting sound translatables 2026-05-21 17:59:04 +03:00
Stefan Ceriu 3bbf31bea6 Add jump to unread translatable 2026-05-21 17:59:04 +03:00
Stefan Ceriu 9a3473137c Remove unused untranslated crypto keys 2026-05-21 17:59:04 +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