* Add a message search abstraction over the Rust SDK's local index
Wraps the SDK's search service so the rest of the app never sees MatrixRustSDK
types, following the existing convention in libraries/matrix.
- MessageSearch, MessageSearchService, MessageSearchResult and
MessageSearchPaginationState describe the surface in the api module.
- RustMessageSearch and RustMessageSearchService implement it, with
MessageSearchResultMapper and MessageSearchResultsProcessor turning SDK results
into Kotlin data classes.
- TantivyQueryEscaper escapes the query so a user typing ":)" or "AND" searches
for that literal text rather than tripping the tantivy parser, and joins every
word as a Must clause.
- Fakes and unit tests cover the mapping, the processor and the escaper, the last
checked against a real tantivy 0.26.1 parser.
* Attach the encrypted search index behind a disabled feature flag
Gives the client an on-device tantivy index encrypted with the session's client
secret, so encrypted rooms can be searched at all.
- The index store is attached at ClientBuilder time via withSearchIndexStore, in
a search-index directory alongside the session, keyed on the client secret. A
session without one gets no index.
- MatrixClient exposes isMessageSearchAvailable so callers gate on the real
indexing capability rather than on the raw flag, and getCacheSize() counts the
index directory so it stays visible in the settings figures.
- FeatureFlags.MessageSearch (feature.message_search) is off by default and
isFinished = false. It is read once at ClientBuilder time, so develop stays
releasable and nothing reaches a user.
* Simplify search index wiring following review
Tie search availability to the MessageSearch feature flag alone and let
the index be created without a client secret, encrypting it only when
the session has one, matching the SDK's SQLite stores. Make
getBaseClientBuilder take the flag as a required parameter and return
ClientBuilder directly again, dropping the BaseClientBuilder wrapper
and the mid-restore snapshot parameter. Check the flag through
FeatureFlagService in RustMatrixAuthenticationService instead of
caching it in a field, and revert the extra matrix_sdk_search tracing
target, which belongs in the SDK's defaults.
* Add a password strength estimator wrapping the SDK zxcvbn API
* Add tests for the password strength estimator SDK mapping
---------
Co-authored-by: ElementBot <android@element.io>
* Simplify how event content with captions are displayed
The caption component will now be added in `TimelineItemEventContentView` instead of separately in each `TimelineItem__View` component
* Make sure `CoilMediaFetcher` methods to fetch media throw errors
We need to catch them later to check if the content scanner marked some thumbnails or medias as invalid/unsafe in `AsyncImage` instances
* Add a `ContentScannerService` that allows us to manually scan a list of medias in an event and then update and store the results
The results take the form of `ContentValidationValue`, stored in a `ContentValidationState` instance tied to the event
* Create `EventContentValidationCache` to keep the `ContentValidationStates` for events in a room
* Expose `EventContentValidationCache` to Compose using `LocalEventContentValidationState`
Also add a couple of helper functions to avoid having to manually remember the states
* Use the new components to display invalid content in the timeline items
* Add `blurhash` to most media items so we can use it while validating the thumbnails/medias
* Fix custom layout issues with screenshot and UI tests
* Also check the validation state for replied-to events in the composer
* Fix and add tests
* Handle unrecoverable content validation errors too: display a 'not found' UI
* Improve the performance of `EqualWidthColumn` for the single item case
* Update screenshots
---------
Co-authored-by: ElementBot <android@element.io>
* Create a `ContentScanner` component:
- Add `:features:contentscanner:api` module with the interface.
- Implement the concrete component using the Rust SDK in `:libraries:matrix:impl`.
This can be used to both set up the content scanner media fetching in the SDK Client and manually scanning media sources from the Android side
* Create `ContentScannerUrlProvider` in a new `:features:contentscaner:api` module as a noop implementation
Use it as a placeholder for the code to instantiate a `RustContentScanner` with the fetched URL and set it as part of the SDK client.
* Expose the optional `ContentScanner` in the `@SessionScope`
* Split the storage part of the Element well-known retriever so it can be reused for the non-session bound retriever.
Also add the new `content_scanner_url` field to it.
This will be used by the enterprise code to fetch the actual content scanner url.
* Bump enterprise commit to have access to the actual content scanner url provider implementation
* Fix tests and lint issues
* Use the right namespace for `:features:contentscanner:api`, also use the right namespace for `impl`
---------
Co-authored-by: Benoit Marty <benoitm@element.io>
* Add read all messages feature: read all messages using Client.markAllRoomsAsRead() method
* Move the 'mark all rooms as read' footer as part of the list item
* Replace `showMarkAllRoomsAsReadConfirmation` and its associated event with `MarkAllRoomsAsRead(val needsConfirmation: Boolean)` and a `AsyncAction.Confirming` state
---------
Co-authored-by: Jorge Martín <jorgem@element.io>
* Support gallery messages
* Address review
* Remove unused function
* Fix indent
* Add "Gallery" message prefix
* Support galleries for image editing
* Fix tapping on a tile opens the last item
* Fix overflow count
* Add caption editing to gallery messages
* Use the new gallery string for prefix
* Lock sending galleries behind a feature flag
* Fix detekts
* Fix
* Ensure image edition is saved when navigating
* Fix sending media broken on edited gallery.
* Fix tests
* Order imports
* Remove unused parameters.
* Fix copyright header of new files.
* Fix Konsist test
* Extract new previews to a dedicated file.
* Sync strings
* Remove unused import
* Update screenshots
* Trigger CI
* Remove parameters with default value.
* More cleanup
* Restore sendAsFile behavior.
* Improve Preview.
* Improve Preview.
* Improve Preview.
* Fix gallery sending cancel and retry issue
* Ensure any previous job is cancelled.
* Fix issue in summary message
* Gallery feature is disabled by default.
* Kotlin convention
* Remove useless parenthesis
* Update screenshots
* Fix test
* List -> ImmutableList
* Remove useless code.
* Render formatted caption for attachment list.
* Replace set of Booleans by an enum
* Remove unused model for individual caption in a gallery Event.
* Fix tests
* Fix tests
* Rework MediaViewer entry point.
And ensure that the clicked image from the gallery is displayed first.
* Ensure gallery item can be click in the pinned message list
Improve the gallery item click handling code.
* Improve code and fix separator color
Closes#7101
* React on attachment item click
Improve code
* Improve code and support 0 items in gallery.
* Fix click on attachment item not rendering anything.
---------
Co-authored-by: Benoit Marty <benoitm@element.io>
Co-authored-by: Benoit Marty <benoit@matrix.org>
Co-authored-by: ElementBot <android@element.io>
- Use `uniffi.ruma_events` types for `MessageLikeEventType` and `StateEventType`.
- Fix tests: using those 2 classes can sometimes call the SDK under the hood, trying to load the native library. We ignore the tests that cause it for now.
* Fix ANRs when calculating DB sizes for Sentry
Instead of using the SDK's `Client.getStoreSizes()` method, manually check the sizes using the file system.
For this, the `SessionPaths` need to be synchronously accessible from a `MatrixClient`. I removed `SessionPathsProvider` too since it's not needed anymore.
The jump-to-unread FAB could surface an OutOfWindow target when the
fully-read marker event was either loaded-but-not-displayed (state/filtered
events) or when there was nothing displayable to jump to. Add two guards to
the recompute:
- Require roomInfo.numUnreadMessages > 0, so the FAB only appears when there
is genuinely unread "interesting" content (never state/hidden events).
- Add Timeline.isEventLoaded to distinguish "in the loaded window but not
rendered" from "genuinely outside the window", falling back to the SDK only
after the cheap display-index check (isKnown) misses.
The RustTimeline implementation reads the replay cache first and releases the
EventTimelineItem native handle via use {} when probing the SDK. Adds presenter
tests for the loaded-but-not-displayed and no-unread-messages branches.
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>
* Update dependency org.matrix.rustcomponents:sdk-android to v26.05.20
* Fix API breaks:
- Handle new `ClientBuildException.InvalidRawKey` variant.
- `RoomInfo` now has a `fullyReadEventId` .
---------
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Jorge Martín <jorgem@element.io>