Commit Graph

15273 Commits

Author SHA1 Message Date
Benoit Marty 650b38429c Show a Message not found placeholder when a replied to message cannot be loaded (#7376)
* Show a Message not found placeholder when a replied to message cannot be loaded

When the replied to event could not be fetched, the reply preview rendered the
raw SDK error string in critical styling, and tapping it emitted a focus
request that could never succeed, so the user got a dead end dialog.

Render the localised error_message_not_found string in the neutral italic style
already used for redacted and undecryptable replies, and drop the click handler
for that case. The existing key is reused rather than adding a new one; a "you
do not have access" wording was rejected because this state covers any failure
to load the event, not only a permission problem.

* Update screenshots

* Trigger CI after recording screenshots

---------

Co-authored-by: ElementBot <android@element.io>
2026-08-10 11:59:37 +02:00
renovate[bot] 829dbb1563 Update zizmorcore/zizmor-action action to v0.6.2 (#7383)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-10 08:16:20 +00:00
hayaksi1 09efb04a8f Hold the revealed event ids in a plain set
The store no longer needs a mutableStateSetOf: an ordinary Set kept in a
mutableStateOf does the same job, and matches DefaultMediaPreviewConfigStateStore.

The Compose state itself has to stay. TimelineProtectionPresenter derives
ProtectionState from the store inside a derivedStateOf, so the set must be a
snapshot object for a reveal to invalidate it and reach the timeline. Backing it
with a plain mutableSetOf leaves the presenter with nothing to observe and it
stops emitting after ShowContent.
2026-08-10 10:59:22 +03:00
Eklavya Jandial 19c6526841 [Task] Show active call participants in the people list #7199 (#7300) 2026-08-10 09:40:12 +02:00
hayaksi1 aa7b9b8721 Trigger CI after recording screenshots 2026-08-09 15:47:29 +03:00
hayaksi1 acb9e0e082 Trigger CI after recording screenshots 2026-08-09 15:47:26 +03:00
ElementBot 7989361114 Update screenshots 2026-08-09 12:41:41 +00:00
ElementBot 4c1d660cf3 Update screenshots 2026-08-09 12:41:30 +00:00
hayaksi1 6533a10ab9 Keep manually revealed media visible when re-entering a room
The set of revealed event ids lived on TimelineProtectionPresenter, which is
scoped to the room graph. That graph is rebuilt every time the room is opened,
so the set was empty on re-entry and every revealed image was hidden again.

Move it into a session scoped TimelineProtectionStore. The store is in memory
rather than persisted: revealing media is a privacy control and there is no
hide action today, so keeping the reveals for the session leaves restarting the
app as a way to undo one, and the set is dropped on logout.
2026-08-09 15:19:46 +03:00
hayaksi1 05528dbd3d Let users enter their full Matrix user ID when searching for a homeserver
The account provider search treated its whole input as a host, so a full user
ID was probed as https://@alice:example.org, which never resolves, and the
permissive URL fallback then offered that invalid address as a provider.

Recognise a complete user ID and resolve the homeserver from its server name,
preserving a port when there is one. Input that starts with @ but is not yet a
complete user ID resolves nothing, so no candidate is produced while the user
is still typing. Detection reuses MatrixPatterns.isUserId and UserId.domainName
rather than a new pattern.
2026-08-09 15:19:45 +03:00
hayaksi1 38398c24b2 Show a Message not found placeholder when a replied to message cannot be loaded
When the replied to event could not be fetched, the reply preview rendered the
raw SDK error string in critical styling, and tapping it emitted a focus
request that could never succeed, so the user got a dead end dialog.

Render the localised error_message_not_found string in the neutral italic style
already used for redacted and undecryptable replies, and drop the click handler
for that case. The existing key is reused rather than adding a new one; a "you
do not have access" wording was rejected because this state covers any failure
to load the event, not only a permission problem.
2026-08-09 15:19:45 +03:00
hayaksi1 33bdf968c5 Expose global account data get and set on MatrixClient
MatrixClient had no way to read or write global account data although the
underlying client supports it.

Add getAccountData and setAccountData to the interface and implement them in
RustMatrixClient using the same withContext/runCatchingExceptions idiom as the
neighbouring methods. The content is the raw JSON string the SDK returns and
accepts: event types are open ended, so a typed wrapper belongs to whichever
caller needs one. Scope is limited to global account data; the room level
variant and the change notification APIs can follow when a feature needs them.
2026-08-09 15:10:00 +03:00
hayaksi1 5140b7c3c8 Fix the feature module template writing the impl build script into the api module
Generating a feature with the Generate Module from Template plugin produced a
module that could not build: features/<name>/api/build.gradle.kts was written
from the impl template, giving the api module a dependency on itself and an
impl namespace.

FeatureModule.json declared BUILD_GRADLE_API and BUILD_GRADLE_IMPL, both
defaulting to build.gradle.kts, and used them as fileTemplates keys. The plugin
resolves keys to filenames before matching, so both collapsed to one key and
the second overwrote the first. The same matching code falls back to a suffix
match on the path, so DefaultXEntryPoint also matched the key XEntryPoint and
was generated from the api template.

Key both by directory, which the plugin supports for exactly this case, and
drop the two now-unused placeholders. The file templates themselves were
correct and are unchanged. The onboarding doc gains a note that an already
imported template must be removed before re-importing, since the plugin keeps
its own copy.
2026-08-09 15:10:00 +03:00
hayaksi1 d04779c8fd Copy a blocked user's Matrix ID by long pressing them
The blocked users list displayed each Matrix ID but offered no way to get it
out of the app, which is what someone who blocked a user for abuse needs in
order to report them onwards.

Long press now copies the Matrix ID and confirms with a snackbar, reusing the
ClipboardHelper and SnackbarDispatcher idiom from the user profile screen. A
short tap still opens the unblock confirmation. The row declares a long click
label so the action is announced by a screen reader. No new string is needed.
2026-08-09 15:09:59 +03:00
hayaksi1 ed82505946 Show the alias or the direct message user's Matrix ID in the room picker
The forward and share room picker showed only a display name, so several
direct messages or rooms sharing a name were indistinguishable.

Render a secondary line: the canonical alias when the room has one, otherwise
the other person's Matrix ID for a direct message. No model change was needed,
because heroes is populated only for a direct message with exactly one hero,
so heroes.singleOrNull() is the peer.
2026-08-09 15:09:59 +03:00
hayaksi1 8272523b5b Keep playing a voice message when the screen turns off
The ExoPlayer backing voice messages was built without a wake mode, so it
defaulted to C.WAKE_MODE_NONE and held no wake lock. The CPU was free to
suspend once the screen turned off, cutting playback short.

Build it with C.WAKE_MODE_LOCAL instead. The media is a local file, so no
WifiLock is needed, and android.permission.WAKE_LOCK is already in the merged
manifest. The media viewer players are left alone: they already pause on
ON_PAUSE, so a wake lock there would keep the CPU awake for a player the user
has intentionally backgrounded.
2026-08-09 15:09:33 +03:00
hayaksi1 aff71cf1b9 Use a dedicated string for the Mute room notification mode
Two of the three modes on the room notification settings screen had
screen-scoped keys; the third reused common_mute, which also labels the Mute
action button on the room details screen. A translator could not fix one
occurrence without breaking the other.

Add screen_room_notification_settings_mode_mute and use it at both places on
that screen. The English value is unchanged, so nothing renders differently.
The action button keeps common_mute, which is the one context where the
generic verb is correct.
2026-08-09 15:09:33 +03:00
hayaksi1 1b7631b84e Do not draw the media loading progress bar under the status bar
The media viewer is edge to edge and the loading progress indicator was the
top-most child of a container that only applied navigation bar padding, so it
was laid out at y=0, behind the status bar and any display cutout.

Give it safeDrawing horizontal and top padding, reusing the idiom already used
by MediaViewerBottomBar in the same file. The inset deliberately does not come
from the scaffold content padding, which collapses to zero when the user taps
to hide the overlay.
2026-08-09 15:09:33 +03:00
ElementBot 813122eebd Update screenshots 2026-08-09 11:48:53 +00:00
hayaksi1 baf28f85cf Keep the opened image on screen when the media gallery fails to load
Opening an image from the timeline replaces it with a full-screen page
reading "error". Two things go wrong. The viewer already holds the item
that was tapped, but building the surrounding media timeline can fail and
the failure overwrites that cached item, so the picture the user asked for
disappears. And the failure page renders the exception message straight
from the SDK, which is developer text with nothing actionable in it.

Emit the failure only when there is nothing cached, so a viewer opened on
a specific event keeps showing that event and stays usable while the rest
of the gallery is unavailable. Where there really is nothing to show, the
page now uses the same alert icon, title and message as the other error
states in this screen, built from strings that already exist.

The trade-off is that the timeline error is no longer surfaced in the
cache case; it is still logged. Swapping it for a snackbar would need a
new surface in the viewer and is left out.
2026-08-09 13:52:55 +03:00
hayaksi1 32f7a9c836 Do not notify about an event sent by another account on the same device
With several accounts logged in, sending a message from one of them raises
a notification on every other account that shares the room. The device
notifies its owner about something the owner has just done, and the more
accounts share a room the more copies arrive.

Resolve the set of logged-in user ids once per push batch and drop an event
whose sender is one of the other accounts, using the filtered-out result
the notification pipeline already understands, so it is recorded in push
history rather than turned into a fallback notification.

The receiving session is removed from that set, which keeps the change a
strict no-op for a single account and protects the local echo that the
reply action pushes back through the same path. Filtering happens at the
one point that sees every kind of push, so messages, polls, call invites,
ringing calls and room invites are all covered.

Filtering is unconditional and has no setting; multiple accounts sit
behind an experimental flag that is off by default, so nothing changes for
a stock build.
2026-08-09 13:38:28 +03:00
hayaksi1 f5a2d5bf88 Do not linkify the server part of a fediverse handle as an email address
A fediverse handle such as `@name@server.tld` contains a substring that
`Linkify.EMAIL_ADDRESSES` recognises as a valid address, so the timeline
renders `name@server.tld` as a tappable `mailto:` link. Tapping it opens a
mail composer addressed to an account that does not accept mail.

Drop a newly added `mailto:` span when the character immediately before it
is `@`. This mirrors what Android already does for web URLs, where
`Linkify.sUrlMatchFilter` rejects a match preceded by `@` — which is why
the handle currently produces exactly one stray mailto span and no partial
link is left behind once it is removed.

Author-supplied links are unaffected: spans that were already present
before linkification are excluded from the check and restored as before. A
genuine address written directly after an `@` — "mail me @support@element.io"
— is no longer linkified, which is the same trade-off Android already makes
for web URLs.
2026-08-09 13:16:04 +03:00
Benoit Marty 044737a3a7 Merge pull request #6719 from element-hq/feature/bma/qrCodeLoginIteration
QR code login iteration
2026-08-07 17:31:50 +02:00
Benoit Marty 668243f658 Use value instead of first(). 2026-08-07 16:43:52 +02:00
Benoit Marty 8f8c3af8c5 [LinkNewDevice] Log continuation / cancellation failure. 2026-08-07 16:42:49 +02:00
ganfra 06862ff3b2 Test synchronizes on profile persistence instead of advanceUntilIdle 2026-08-07 16:30:03 +02:00
ganfra 7d5877c659 Merge pull request #7330 from element-hq/renovate/constraintlayout.compose
Update dependency androidx.constraintlayout:constraintlayout-compose to v1.1.2
2026-08-07 14:44:47 +02:00
ganfra 9b39843e69 Add withProfilesExtension override to FakeFfiSyncServiceBuilder 2026-08-07 14:22:52 +02:00
renovate[bot] df925c29e4 Update dependency org.jsoup:jsoup to v1.23.1 (#7332)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Benoit Marty <benoitm@element.io>
2026-08-07 14:06:22 +02:00
Benoit Marty 07ca468847 Merge pull request #7136 from element-hq/fix/a11y-invite-people
Announce checked/unchecked state for user rows in invite screen
2026-08-07 14:00:01 +02:00
ElementBot b7c0374c7c Update screenshots 2026-08-07 09:53:47 +00:00
ganfra 14c0944d22 Merge branch 'develop' into feature/fga/user_status_last_pieces 2026-08-07 11:35:19 +02:00
Benoit Marty 293faec03b Merge pull request #7175 from element-hq/renovate/androidx.compose.material3-material3-1.x
Update dependency androidx.compose.material3:material3 to v1.5.0-alpha23
2026-08-07 10:45:22 +02:00
ganfra 8d2686d1a9 Merge branch 'develop' into feature/fga/user_status_last_pieces 2026-08-07 10:12:32 +02:00
renovate[bot] e1daec6728 Update dependency androidx.constraintlayout:constraintlayout-compose to v1.1.2 2026-08-07 08:06:16 +00:00
renovate[bot] 8a164228bd Update dependency com.google.firebase:firebase-bom to v34.17.0 (#7333)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Benoit Marty <benoitm@element.io>
2026-08-07 10:02:28 +02:00
Benoit Marty b5e9f42058 Fix compilation issue 2026-08-07 09:52:54 +02:00
ElementBot 0e1cb2df5e Update screenshots 2026-08-07 07:20:49 +00:00
ElementBot ed44cd776c Update Gradle Wrapper from 9.6.1 to 9.7.0 (#7335)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2026-08-07 09:12:21 +02:00
renovate[bot] e3ce557576 Update metro to v1.4.0 (#7334)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-07 09:08:52 +02:00
Benoit Marty 701cf4b2f9 Merge branch 'develop' into renovate/androidx.compose.material3-material3-1.x 2026-08-07 09:06:19 +02:00
renovate[bot] d3f35cb90c Update dependency io.element.android:element-call-embedded to v0.23.0 (#7323)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-06 18:39:06 +02:00
renovate[bot] 73119273c2 Update dependency org.maplibre.gl:android-sdk to v13.4.1 (#7305)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-06 18:38:49 +02:00
renovate[bot] 87b56861e6 Update dependency io.sentry:sentry-android to v8.51.0 (#7301)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-06 18:38:21 +02:00
Benoit Marty e568f1ec7a Fix deprecation warning on androidx.compose.material3.ListItem 2026-08-06 18:37:25 +02:00
Benoit Marty c8c8971889 Fix detekt false positive 2026-08-06 18:35:18 +02:00
Benoit Marty d1cf1aa09f Fix deprecation warning on androidx.compose.material3.ListItem 2026-08-06 18:35:17 +02:00
renovate[bot] d2b4a85453 Update dependency androidx.compose.material3:material3 to v1.5.0-alpha23 2026-08-06 18:35:17 +02:00
renovate[bot] b1b52da38e Update reactivecircus/android-emulator-runner action to v2.38.0 (#7189)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-06 18:32:08 +02:00
renovate[bot] f8ce3e9b70 Merge pull request #7329 from element-hq/renovate/constraintlayout
Update dependency androidx.constraintlayout:constraintlayout to v2.2.2
2026-08-06 18:31:36 +02:00