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.
* Add the multi-account announcement screen
A self-sizing bottom sheet telling users they can now add multiple accounts, matching the designs. Close and Add account both report back to the coordinator; nothing presents it yet.
* Use the Localazy strings for the multi-account announcement
The copy now lives in Localazy as screen.multi_account_announcement.*, named after the screen rather than the room list.
* Apply review suggestions to the multi-account announcement
- Use an ElementNavigationStack with a toolbar close button, like RedactConfirmationView, instead of an overlaid glass button.
* Remove the large text preview from the multi-account announcement
Other sheets built the same way don't snapshot Dynamic Type sizes, and the iOS 26 bar material it would show isn't rendered in snapshots.
* Use TitleAndIcon for the multi-account announcement
TitleAndIcon now takes an attributed subtitle (#6274), so the sheet no longer needs to rebuild its layout by hand. The snapshots are unchanged.
* Suggest recently visited rooms when forwarding messages
The Forward to screen now shows up to 5 recently visited rooms in a
Suggestions section, above a Chats section that lists every room. The
suggestions are never searched: while searching, only the Chats section
is shown and filtered. The source room, invites, spaces and upgraded
rooms are never suggested, and the section is hidden when there is
nothing to suggest.
The suggestions are resolved from the room summaries rather than room
proxies, so they show up without holding back the list, and they are
re-resolved as the room list loads after a cold start. ClientProxy now
exposes the recently visited room IDs for this.
The recently visited rooms filter is now async, so callers choose its
isolation instead of asserting it at runtime.
* Apply review suggestions to the forwarding suggestions
Rooms:
- Each room is listed once. Suggested rooms are left out of Chats unless
searching, where Chats lists every result. This also removes the
duplicated row whose selection changed without the tapped row's
animation.
- The Chats header is hidden when the section has no rooms.
Suggestions:
- Resolve them once when the screen opens instead of on every room list
update.
The forwarding screen now picks destinations for one or several
messages, so "Forward message" no longer fits. Use the common_forward_to
string from Localazy, as in the designs, and re-record its snapshots.
* Start message selection from the Forward action
Behind the multi-select developer option, choosing Forward on a message
now starts a selection with that message checked, instead of the
dedicated Select menu action which is removed. Only forwardable
messages can be selected: remote, decrypted, non-redacted events that
aren't state, unsupported, poll or live location items.
The chrome follows the Figma exploration: the room header stays, an X
in the trailing toolbar position ends the selection, rows show only the
checkbox (no highlight, 10pt gap to the bubble), and the composer is
replaced by a single primary "Forward N messages" button. The limits
are now 10 messages into 5 rooms.
Tapping the button forwards the selection in timeline order, never in
the order the messages were tapped. MessageForwardingItem carries
several contents and the forwarding screen sends them one after the
other per room, reporting a single error toast on partial failures.
The selection is kept while the forwarding screen is open so cancelling
it returns to the selection; it is cleared by the flow coordinator once
the messages are sent, or by the X in the timeline.
New plural action_forward_messages lives in Untranslated for now;
action_select and screen_room_selection_count are no longer used.
* Tidy the selection code after review
Reuse ToolbarButton's cancel role for the selection's toolbar item so it
matches the other screens on every OS version, and disable the room
header while selecting so the room details can't cover the selection.
Move the forwardable/selected item helpers next to the existing
nonisolated array extension, drop the unused MessageForwardingItem
initialisers and the single-item makeForwardingItem overload, and
simplify the forwarding loop now that a room either sends or isn't
reachable.
The action bar preview builds its own view model instead of putting
the shared mock into selection mode for every later preview, and a
test locks that Forward keeps forwarding directly in the pinned
timeline.
* Select messages to forward from the pinned timeline too
Forward is offered in the pinned events timeline, so with the flag on
it starts a selection there as well, with the same cancel item in the
toolbar and the same forward button at the bottom. Forwarding from
that sheet already dismisses the whole sheet, so the selection is
discarded with it. Only the media timelines keep forwarding a single
item directly.
* Confirm with a toast when messages are forwarded to several rooms
When a single room is picked the flow opens it, which is confirmation
enough. When several rooms are picked the user stays in the origin room,
so a "Messages forwarded" toast tells them it worked, as in the designs.
The new screen_room_message_forwarded / screen_room_messages_forwarded
strings live in Untranslated for now.
* Apply review suggestions to multi-message forwarding
Strings
- The forward button and the multi-room toast now use the Localazy
plurals action_forward_messages and screen_room_messages_forwarded;
the toast shows the count. The Untranslated copies and the unused
action_select are gone.
Selection
- Drop the dead startSelection view action and the redundant
canSelectMessages guard; tests start a selection through Forward
like the app does.
- Remove two comments on the selection state that restated the code.
Forwarding
- After a send, clear the selection in the room and any open thread
instead of working out which one started it; only one can be
selecting at a time.
- Explain that stickers are excluded because the SDK can only forward
m.room.message content.
* Rename the timeline selection to message selection
"Selection" alone was too generic in a timeline that also has text and
room selections. The selection state, toolbar, action bar and
accessibility types, the timeline state's property, the view actions
and the public clear method now say "message selection". Private
helpers keep their short names.
* Rename MessageForwardingItem to MessageForwardingPayload
The type now carries several messages, so "item" no longer described
it. The factory method and the variables and action labels holding it
follow the new name.
We decided against changing how unread activity is rendered in the room list, so the experiment and its developer option are no longer needed.
we have also added a notification settings entry for hiding the room list gray dots.
The search screen's empty state now lists the queries the user searched
for and the rooms they opened from the results, newest first, capped at 25
and stored in AppSettings. Tapping a query fills the search field, tapping
a room opens it, and both are reachable with a hardware keyboard.
Rooms are resolved from their identifiers as the room list loads, and
those the user has left or is only invited to are dropped. The history is
cleared on logout.
* 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>
* 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.
* 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>
* 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.
* 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
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.
* 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>
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.
* 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.