When the homeserver advertises custom_recovery_passphrase_settings, always run
the custom passphrase flow, flooring min_character_count at 1 (covering missing,
zero, and negative values) so the derived passphrase can never be empty. Any
stronger minimum stays the operator's choice. Replaces the previous behaviour of
dropping the spec and falling back to the auto-generated key.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Publish the current queue head via a StateFlow so any host that subscribes
after a message is posted (e.g. a screen recomposing as a flow pops back to it)
still observes it. The previous mutex-gated flow delivered each message to a
single parked collector, which could starve the host actually on screen and
drop the snackbar. Adds a regression test for the late-subscriber case.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extract the IME-aware bring-into-view logic into a reusable designsystem
modifier and use it in the enter recovery key screen, replacing the inline
BringIntoViewRequester wiring.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When the homeserver advertises custom_recovery_passphrase_settings (and
the enterprise gate is enabled), the secure-backup setup lets the user
enter and confirm their own recovery key with a live strength indicator,
instead of receiving a generated one. The SDK derives the 4S key from the
passphrase and the base58 key is scrubbed everywhere so it is never
shown. Falls back to the generated-key flow when no spec is present or
the well-known fetch fails.
Snapshot PNGs are intentionally left out; the core team regenerates them
after the PR is opened.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
enableRecovery now takes an optional passphrase and returns the recovery
key as the suspend result (like resetRecoveryKey), avoiding the
flow/return-value race. For the passphrase path the SDK-derived base58
key is kept out of the session-scoped progress flow so it is never
surfaced to the user; the caller receives it as the return value and is
responsible for scrubbing it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add CustomRecoveryPassphraseRequirements to ElementWellKnown and decode
the custom_recovery_passphrase_settings block (currently just
min_character_count) from the homeserver's element.json. Invalid specs
(missing or non-positive min_character_count) are logged and mapped to
null so the setup flow falls back to the generated-key path. Field names
match the ESS well-known schema (element-enterprise#261).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extract the show/hide password trailing-icon into a reusable
PasswordVisibilityToggle so every password field reveals plaintext the
same way and announces the same a11y labels. Reuse it from the login and
reset-identity password fields. Pure refactor, no behaviour change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This happens when building a `ShortcutInfoCompat` in `DefaultNotificationConversationService.onSendMessage` when the provided room name is not null but it's empty.
* Fix media viewer flickering
This was caused by the data being loaded triggering an index update that got out of sync with the displayed items, and for an instant, the pager index pointed to the wrong data until it was refreshed
* Reuse the same 'displayer' function for both forwards and backwards pagination
* Make `dataFlow` a property so we don't create a new instance every time we access it
* Remove `pageDataComparator` as it prevented new items from being loaded when a pagination returned no valid items to display but has more items to load
Make sure we modify the current index when loading new data only if it was pointing to the input event id.
* Fix `MediaViewerDataSource` overriding the provided timestamp for `Loading` items
Test emitting different loading items from the data source results in the state displaying the different items, so they will trigger a new pagination attempt
* Add regression test to check loading -> error -> loading states will still trigger 2 separate `LoadMore` events
* Fix Maestro: tap on confirmation for inviting unknown users to a room
* Tap on back after inviting some user
* Tap on back again
* Confirm inviting someone to a DM
* Make fix conditional
`AnalyticsLongRunningTransaction.PushToWorkManager` was incorrectly used instead of `AnalyticsLongRunningTransaction.PushToNotification`, resulting in wrongly formatter analytic traces
* Improve `FetchPushForegroundService`'s reliability
- Don't use DI, we can just create the notification channel. This should speed up the creation of the service and reduce the number of `ForegroundServiceDidNotStartInTimeException` received. Also use `MainScope` instead of the app's coroutine scope.
- Move the wakelock releasing mechanism to `onDestroy` so it's always used. Previously, this would only happen when `stopService` was called, which would only happen when `stopSelf()` is called, but not when the OS or the service manager stops the service.
* Add fallback value for the notification channel title
* Replace the wrong string for the notification/channel title
---------
Co-authored-by: Benoit Marty <benoitm@element.io>
* Set `DmRoomDefinition.TwoPeople` in `ClientBuilder`. This applies the 'direct and with at most 2 non-service members' rule to what the SDK should consider a DM.
* Map `RoomInfo.isDm` from the SDK
* Map `NotificationData.isDm` from `NotificationInfo.roomInfo.isDm`
* Remove `RoomIsDmCheck` file as its extension functions are now redundant. Move `Room.isDm` helper function to `BaseRoom`.
* Map `isDm` in `SpaceRoom` from the SDK too
* Replace `isDirect` with `isDm` where possible
* Map `RoomMember.isServiceMember` from the SDK and use it to tell apart normal members of a room from service members (i.e. `RoomMembersState.getDirectRoomMember`)
* First live location sharing sending implementation
* Simplify logic around canStop sharing
* Add some debug logs around LiveLocationSharingService
* Add LiveLocationException
* Expose beaconId to identify the current share
* Throttle live location instead of debouncing
* Keep sync alive when sharing live location
* Improve LiveLocation sharing
* Show LiveLocationDisclaimer
* Read minDistanceUpdate in LiveLocationSharingService
* Set minDistanceUpdate in AdvancedSettings
* Display banner in room when sharing live location
* Fix tests around LiveLocationSharing
* Ensure shares are properly restarted/stopped when app is re-launched
* Ensure LLS data is cleared when session is removed
* Update and fix LLS tests
* Handle Start LLS in ui
* Add check LLS permissions
* Remove hardcoded strings
* Fix quality and format
* Create DeviceLocationProvider so we can share location data between sources (presenter/live location service)
* Update screenshots
* Fix warning
* Do not try to stop if it was not sharing
* Revert "Create DeviceLocationProvider so we can share location data between sources (presenter/live location service)"
This reverts commit ba12bd968e82941cc231bdbb449310b24c97c5b8.
* Tweak location provider config values
* Address PR review remarks
* Fix ktlint
* Update screenshots
* Fix some tests after merging develop
* Adjust TimelineItemLocationView ui to match figma
* Update screenshots
* Documentation and cleanup
* Remove temporary resource
---------
Co-authored-by: ElementBot <android@element.io>
Co-authored-by: Benoit Marty <benoit@matrix.org>
Co-authored-by: Benoit Marty <benoitm@matrix.org>
* Use just the other user's avatar for DM details. Remove `DmAvatars` component and other no longer needed data.
* Improve selection indicator by clipping the avatar to a circle shape
* Update screenshots
---------
Co-authored-by: ElementBot <android@element.io>