detekt's default configuration excludes test source sets from
`TooManyFunctions` and `StringLiteralDuplication`, but not from
`LargeClass`, so large test classes were reported and had to carry a
`@Suppress("LargeClass")` annotation.
Add the same kind of exclusion to the `LargeClass` rule in
`tools/detekt/detekt.yml` and remove the 24 now-redundant suppressions
from test files. The two remaining suppressions are in production code,
where the rule still applies.
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both created a dedicated timeline for each operation performed in a thread, and
never closed it, leaking SDK resources. Apply the same treatment as PollRepository:
replace getTimeline() with a scoped withTimeline() helper, which closes the created
timeline once the operation completes, whether it succeeds, fails or gets cancelled.
In DefaultMediaSender.sendGallery(), waiting for the upload handler is now done
inside the block, so that the timeline stays open until the upload completes.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
emptyNode() renders nothing at all, which is fine for a placeholder that is left
within a few frames, but makes the application look frozen when the wait can
last, or never end.
Add a delayBeforeShowingContent parameter to emptyNode(): when it is finite, a
progress indicator and a "Loading…" label fade in after that delay, reusing the
existing DelayedVisibility helper. It defaults to Duration.INFINITE, so the
splash screen keeps rendering an empty canvas.
Use a one second delay on the two placeholders which are not guaranteed to be
left: the FTUE one, rendered while waiting for the session verified status, and
the LoggedInFlowNode one, rendered while the FTUE state is unknown.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
sessionPaths keeps pointing at the directories of the account which has
just been logged in, and it was never reset. Adding another account
calls setHomeserver(), whose rotateSessionPath() starts by deleting the
directories of the previous sessionPaths, so the file and cache
directories of the first account were wiped.
finalizeClientCreation() now forgets the session paths once the login
succeeded. It is done there rather than in clear() on purpose: after a
failed attempt the directories are orphaned and must still be deleted by
the rotateSessionPath() of the next attempt.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Since the login flows stopped handing their client over to
RustMatrixClientFactory and let finalizeClientCreation() build a fresh
one from the SessionData, two problems appeared.
The client built by loginWithQrCode() was never owned by anyone: it is
not assigned to currentClient, so clear() had nothing to close and the
Rust Client stayed open for the whole app lifetime, holding the session
stores of the freshly logged in account. It is now tracked in
currentClient, and also disposed of when the QR login fails, which is
safe because that flow always builds its own client.
The client of the session was also built while the login client was
still open. Both use the same session paths, so their state and crypto
SQLite stores, and the search index when message search is enabled, were
opened twice at the same time with no cross process lock to protect
them. clear() now runs before the final client is created.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Update dependency org.matrix.rustcomponents:sdk-android to v26.09.08
* Fix API breaks:
- There's no `SyncServiceBuilder.withProfilesExtension()` method anymore. This is now enabled unconditionally in the SDK.
- Timeline filters no longer use the `org.matrix.rustcomponents.sdk.TimelineEventFilter` FFI wrapper, but the `uniffi.matrix_sdk_ui.TimelineEventFilter` type directly. This also changes the underlying types used for inclusion/exclusion.
---------
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Jorge Martín <jorgem@element.io>
Fix API breaks:
- A new `Mentions` room list filter is available.
- `RoomListService.subscribeToRooms` is now `RoomListService.setRoomSubscriptions`.
- `enableAutomaticBackPagination` moved from `Client` to `ClientBuilder`.
The -dontwarn is still required: firebase-messaging ships no consumer rules and
we exclude firebase-analytics from its dependencies. Only rename the file to
consumer-rules.keep and reword the comment, which embedded a local path.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The rule only kept the class, but ShowkaseBrowserActivity instantiates it with
Class.forName(...).getDeclaredConstructor().newInstance(), so R8 was free to
strip the constructor. Also drop the AGP template comments and rename the file
to .keep, for consistency with app/proguard.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The three rules came from a 2022 comment on Retrofit issue #3751. Retrofit
3.0.0 now ships META-INF/proguard/retrofit2.pro, which contains two of them
verbatim and covers retrofit2.Call through its conditional return-type rule.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Keep the push foreground service alive while notifications are fetched
* Release the push foreground service as soon as results are handed over
---------
Signed-off-by: Johannes Marbach <n0-0ne+github@mailbox.org>
* Make sure `enforce_element_pro` is taken into account in FOSS
* Make sure we crate `RustTemporaryMatrixClient` instances with a proper `serverName` value
Ask the SDK to track receipts on message-like events only, for the live
timeline and for the focused and threaded ones, so all three agree. The
disabled case for the media and pinned-event timelines is unchanged.
This matches the behaviour on Element X iOS.
The SDK attaches the receipt to the preceding event rather than the next
one, which is the placement its API offers.
The dialog now reads "Confirm removal" over "Are you sure you wish to remove
this message?", with the reason field marked as optional beneath it, rather
than a bare title and a labelled field. TextFieldDialog gained a supporting
text so the field can carry that note.
The pending removal moves from a nullable timeline item to redactEventAction,
an AsyncAction whose Confirming state carries the event id, so it is modelled
the same way as every other action the user has to confirm.
Introduce io.element.android.libraries.mediaviewer.api.FileViewerEntryPoint, a
reusable screen which renders content that is not a Matrix media the same way the
media viewer renders a file, with Share and Download actions.
The caller provides a filename, a mime type and the whole content as a String.
The node writes it to a temporary file in the cache directory, then reuses
LocalMediaView (so text content goes through TextFileViewer) and LocalMediaActions
for sharing and saving on disk. The node is contributed to AppScope so that the
screen can be used from any graph, since MediaViewerNode itself is bound to
RoomScope and depends on the timeline data sources.
Also route MimeTypes.Json to TextFileView in LocalMediaView, so that a json file
is rendered as text instead of falling back to the generic file card.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>