Commit Graph

6857 Commits

Author SHA1 Message Date
hayaksi1 7f56c15fb8 Drop the comments from the empty DM call guard
Review feedback: the member-count condition reads on its own.
2026-08-09 15:33:51 +03:00
hayaksi1 b725d37b0e Do not display pinned events that the client cannot render
The pinned events timeline is built with an exclusion filter rather than an
allowlist, so an event of a type the app has no renderer for reaches both
pinned surfaces. The banner falls through to the formatter catch-all and reads
"Unsupported event", and the list renders an unknown content tile.

Drop unknown content and message-like or state events that failed to parse from
both surfaces, along with any day divider left without an event to introduce,
and show the empty state when nothing renderable remains. The spec makes this
the client's call. Such an event can still be unpinned from the room timeline,
where it is still rendered.

Undecryptable and redacted events are untouched: they carry information the
user needs.
2026-08-09 15:20:13 +03: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 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 1299b5c897 Hide space children you have left that can only be joined by invitation
After leaving a room listed in a space, the room stayed in the child list with
a Join button, even though it can only be entered with a new invitation. It
disappeared only after leaving and reopening the space, because the server
omits it from the refetched hierarchy.

Apply the same rule locally in the presenter. The filter keys on the LEFT
membership combined with an invite join rule rather than on the derived
visibility, which collapses knock and unknown join rules into private and
would wrongly remove the Join button from knockable rooms.
2026-08-09 15:09:34 +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 72cc8f848d Drop the comments from the grouping timeout
Review feedback: the constant name and the test names carry the rule.
2026-08-09 14:51:30 +03:00
hayaksi1 8943c4e724 Drop the comments from the filter selection guard
Review feedback: the guard and the test name already say what the check
is for, so the narration was redundant.
2026-08-09 14:46:13 +03:00
hayaksi1 7ebcb86ee1 Drop the comment on the custom map style branch
Review feedback: the branch already reads as "use the custom url as it
is", so the explanation belongs in the commit rather than the source.
2026-08-09 14:44:30 +03:00
hayaksi1 4b85e2d31e Turn a matrix: URI in a message into a pill
A permalink written as a matrix: URI stayed plain text, while the same
link in matrix.to form became a pill. The pillifier only scanned
Patterns.WEB_URL, which cannot match a URI with no web scheme, even though
the permalink parser already understands matrix: URIs.

Those URIs are now scanned for as well, before the web pass, since
Patterns.WEB_URL otherwise claims the bare domain inside the URI and
whichever pass runs first wins the range. Each match also gets a URLSpan:
the timeline only reports URLSpans as clicks, so without one the pill
would look right and do nothing.

The composer path is untouched, since it pillifies without permalinks.

Relates to https://github.com/element-hq/element-x-android/issues/5319
2026-08-09 04:09:32 +03:00
hayaksi1 717efe46c5 Do not offer to start a call in a DM with no other member
A DM whose other member has left still offered the call button. Starting
that call put the user alone in a room nobody could join, with no way out
of the call screen.

The presenter now clears canStartCall for a DM with no other active
member. activeMembersCount counts joined and invited members, so a fresh
DM whose peer has been invited but has not joined yet can still start a
call. Joining an already ongoing call is untouched, so a call started
before the other member left stays reachable.

Relates to https://github.com/element-hq/element-x-android/issues/6189
2026-08-09 04:09:27 +03:00
hayaksi1 b5e95e27d4 Do not group timeline messages sent more than five minutes apart
Consecutive messages from the same sender were grouped into one bubble
block no matter how far apart they were sent, so a reply hours later
looked like part of the earlier burst and lost its own timestamp header.

computeGroupPosition now folds a five minute limit into the two
groupability flags it already computes. The delta is symmetric between a
pair of neighbours, so both items always agree on where the block splits
and every branch of the existing decision table keeps working unchanged.

Breaking a group on reactions, which the iOS client also does, is a
separate divergence and is not part of this.

Relates to https://github.com/element-hq/element-x-android/issues/4757
2026-08-09 03:51:48 +03:00
hayaksi1 17365a50d1 Keep saving files to Downloads once 32 files share the same name
MediaStore de-duplicates the display name of a new file itself, but its
uniquifier gives up after 32 collisions and throws IllegalStateException.
Saving then failed with "Sorry, an error occurred" and wrote nothing, and
because image.png is the name most screenshots arrive with, a user who
saves media regularly could reach a state where that name never saved
again without deleting files from Downloads by hand.

A new saveWithUniqueFileName helper in androidutils retries the insert
once with a suffixed name when the platform reports it cannot build a
unique one; a second failure propagates so genuine errors still surface.
withFileNameSuffix builds that name by inserting the suffix before the
extension, and handles names without one.

Both call sites are fixed: AndroidLocalMediaActions and DefaultFileSave
carried byte-identical logic and therefore the identical defect. While in
AndroidLocalMediaActions, a null output uri from ContentResolver.insert
now throws instead of reporting success without writing anything.

The pre-Android-Q path is untouched: it overwrites rather than
uniquifying, so it never reaches this limit.

Relates to https://github.com/element-hq/element-x-android/issues/6371
2026-08-09 01:59:25 +03:00
hayaksi1 e8ca16b74f Ignore a room list filter that is incompatible with an already selected one
Some room list filters are mutually exclusive, and the UI expresses that
by hiding the incompatible chips rather than disabling them. Nothing
enforced the rule on the write path, so two chips tapped in the same
frame, before the list could recompose, both applied. The room list then
matched nothing while the offending chip was hidden, leaving no way to
see or undo what was filtering the rooms.

DefaultFilterSelectionStrategy.select() now ignores a filter that is
incompatible with one already selected, so the same table buildFilters()
uses to hide chips also governs the selection itself. The currently
applied filters win and the late tap is dropped, which matches the
existing design where an incompatible chip is already on its way out of
the UI when it is tapped.

toggle(), deselect(), clear() and the FilterSelectionStrategy interface
are unchanged.

Relates to https://github.com/element-hq/element-x-android/issues/5383
2026-08-09 01:59:25 +03:00
hayaksi1 c7d8973507 Do not append the application MapTiler key to a custom map style url
When a homeserver publishes a map_style_url in its .well-known file, the
app appended its own MapTiler API key to it, producing a URL with two
query strings that the tile server rejects. The map then failed to load
for every user of that homeserver, with no way for the operator to opt
out.

MapTilerTileServerStyleUriBuilder.build() now appends ?key= only to the
URL it composes itself from the bundled base url and map ids. A non
blank customMapStyleUrl is returned verbatim, so the operator's own
credentials survive. This matches Element Web and the self-hosted tile
server documentation, both of which treat map_style_url as complete.

The two existing tests that pinned the old behaviour are updated, and
cases are added for a custom URL that already carries a key, one that
carries an unrelated query string, and a blank url falling back to the
built-in style.

Relates to https://github.com/element-hq/element-x-android/issues/7289
2026-08-09 01:59:25 +03:00
Jenna Vassar d7e6b64265 Dismiss the keyboard on continue and restore it after an error 2026-08-07 12:46:11 -07:00
Jenna Vassar 8c2cf9d95e Reference the Figma design on the account provider screen 2026-08-07 12:04:01 -07:00
Benoit Marty e66efcfc43 [LinkNewDevice] Disable QrCode rotation
#7303
2026-08-07 17:46:47 +02:00
Benoit Marty 2b2d86a804 Use Kotlin Duration. 2026-08-07 17:46:46 +02:00
Benoit Marty 4485c8a4c0 [LinkNewDevice] Fix second and next attempts to unlock using biometric failures.
`cipher.doFinal` cannot be called several times.
2026-08-07 17:46:46 +02:00
Benoit Marty 33979b6574 [LinkNewDevice] Add a 2 minutes timer to scan a QrCode
#7303
2026-08-07 17:46:46 +02: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
bxdxnn d36daca242 Fix 2026-08-07 13:44:43 +00:00
bxdxnn 221f13269e Fix 2026-08-07 13:42:16 +00:00
bxdxnn a04078aa9d Address review 2026-08-07 13:38:20 +00:00
Benoit Marty 64ba29f91a Merge branch 'develop' into feat/polls-max-selections 2026-08-07 14:03:17 +02:00
ganfra 14c0944d22 Merge branch 'develop' into feature/fga/user_status_last_pieces 2026-08-07 11:35:19 +02:00
ganfra 8d2686d1a9 Merge branch 'develop' into feature/fga/user_status_last_pieces 2026-08-07 10:12:32 +02:00
Jenna Vassar d04a3853b4 Add inline autocomplete for the account provider field 2026-08-06 12:11:18 -07:00
Jenna Vassar c2b3b0fe0f Remove the account provider search screen and homeserver resolver 2026-08-06 11:31:32 -07:00
Jenna Vassar df6ccd9dc3 Consolidate account provider selection into a single editable screen 2026-08-06 11:31:25 -07:00
Benoit Marty e568f1ec7a Fix deprecation warning on androidx.compose.material3.ListItem 2026-08-06 18:37:25 +02:00
Benoit Marty d1cf1aa09f Fix deprecation warning on androidx.compose.material3.ListItem 2026-08-06 18:35:17 +02:00
Benoit Marty dfe0dedf37 Merge pull request #7331 from element-hq/feature/bma/fixOverlap
Fix overlap issue.
2026-08-06 18:29:38 +02:00
Benoit Marty 9c66cd331f [Link new device] Handle split steps in the SDK 2026-08-06 17:22:10 +02:00
Benoit Marty 7adaeca7c7 Fix overlap issue.
Fixes #7327
2026-08-06 16:17:17 +02:00
ganfra a7d2b86fe0 Show loading and failure feedback when updating user status 2026-08-06 16:15:44 +02:00
Benoit Marty beccb1ddfa Fix tests 2026-08-06 15:03:13 +02:00
Benoit Marty 10f24e2b8d Send gitSha in the bug report content.
See https://github.com/element-hq/element-x-android-rageshakes/issues/14270
2026-08-06 14:46:28 +02:00
Benoit Marty 4dffd7ddef Move deviceId, gitBranch and gitSha to the developer screens. 2026-08-06 14:46:28 +02:00
ganfra 93ca5374d6 Add status emoji badge to current user avatar in home top bar 2026-08-05 16:14:59 +02:00
ganfra 863cece4fb Subscribe to own profile updates and gate on server support 2026-08-05 16:14:59 +02:00
ganfra 494dc026fa Create fun ProfileDetails.toMatrixUser method 2026-08-05 16:14:59 +02:00
Jenna Vassar 3c09fb37b9 Save the account provider to history on successful sign-in 2026-08-03 11:18:05 -07:00
Jenna Vassar 4714127cc0 Default the account provider to the most recently used one 2026-08-03 10:54:45 -07:00
Jorge Martin Espinosa 674354b1a6 Enforce HS disabling E2EE in DM creation too (Element Pro) (#7292)
This part was missing from the implementation of this Element Pro feature, which incorrectly only applied to rooms.
2026-07-29 09:17:41 +00:00
ganfra cc75e9386c Merge pull request #7287 from element-hq/renovate/org.matrix.rustcomponents-sdk-android-26.x
Update dependency org.matrix.rustcomponents:sdk-android to v26.07.28
2026-07-29 02:03:53 +02:00