Skip to content

Split MatrixRoom into MatrixRoom and JoinedMatrixRoom #4561

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Apr 23, 2025

Conversation

jmartinesp
Copy link
Member

@jmartinesp jmartinesp commented Apr 9, 2025

Content

  • Split MatrixRoom into JoinedMatrixRoom.
  • Split the implementation classes of MatrixRoom too.
  • Turn RoomPreview into NotJoinedRoom.
  • Update RustRoomFactory to use the new interfaces, remove the existing room cache.
  • Adapt RustMatrixClient and RustTimeline to the new interfaces.
  • Adapt DI to the split
  • Adapt the rest of the app using JoinedMatrixRoom where needed.

Motivation and context

Since some time ago, the joined rooms in the SDK don't need a live timeline anymore. This was previously a precondition and we had to get a Room from RoomListItem.fullRoom(), having initialised the live timeline before.

Now we can instead just call Client.getRoom(roomId) to get a room, joined or not, if it exists locally in the SDK's DB, and the timeline doesn't have to be initialised at that point, so we can initialise the timeline if needed lazily. In a previous PR I tried doing exactly this, but initialising the timeline can fail so having a joined room with no timeline in some UI contexts could be dangerous and would need new error UI states or retries.

So in the end, the solution was to have the RustRoomFactory return both rooms with and without timeline, depending on what's asked from it, and make the joined room having a timeline mandatory for those UI contexts, but not for the rest of the app.

Tests

It's difficult to say what we should test, but I guess it would be joining and leaving rooms, checking the preview of rooms known and unknown and of course anything inside the chat screen or a child node of it should still work as before. So to sum up, everything should still work as it used to, and rooms should still be fast to load.

Tested devices

  • Physical
  • Emulator
  • OS version(s): 14

Checklist

  • Changes have been tested on an Android device or Android emulator with API 24
  • UI change has been tested on both light and dark themes
  • Accessibility has been taken into account. See https://github.com/element-hq/element-x-android/blob/develop/CONTRIBUTING.md#accessibility
  • Pull request is based on the develop branch
  • Pull request title will be used in the release note, it clearly define what will change for the user
  • Pull request includes screenshots or videos if containing UI changes
  • You've made a self review of your PR

Copy link
Contributor

github-actions bot commented Apr 9, 2025

📱 Scan the QR code below to install the build (arm64 only) for this PR.
QR code
If you can't scan the QR code you can install the build via this link: https://i.diawi.com/FgXjg9

Copy link

codecov bot commented Apr 9, 2025

Codecov Report

Attention: Patch coverage is 43.34828% with 379 lines in your changes missing coverage. Please review.

Project coverage is 79.99%. Comparing base (bc5c771) to head (e0cd1d1).
Report is 3 commits behind head on develop.

Files with missing lines Patch % Lines
...android/libraries/matrix/impl/room/RustBaseRoom.kt 0.00% 125 Missing ⚠️
...droid/libraries/matrix/impl/room/JoinedRustRoom.kt 0.00% 96 Missing ⚠️
...roid/libraries/matrix/impl/room/RustRoomFactory.kt 6.45% 58 Missing ⚠️
...droid/libraries/matrix/test/room/FakeJoinedRoom.kt 80.95% 18 Missing and 2 partials ⚠️
.../android/libraries/matrix/impl/RustMatrixClient.kt 5.00% 18 Missing and 1 partial ⚠️
...id/libraries/matrix/impl/room/NotJoinedRustRoom.kt 0.00% 12 Missing ⚠️
...android/libraries/matrix/test/room/FakeBaseRoom.kt 88.76% 10 Missing ⚠️
...lement/android/x/di/DefaultRoomComponentFactory.kt 0.00% 4 Missing ⚠️
...s/matrix/api/room/RoomNotificationSettingsState.kt 55.55% 2 Missing and 2 partials ⚠️
...oid/libraries/matrix/impl/timeline/RustTimeline.kt 42.85% 2 Missing and 2 partials ⚠️
... and 17 more
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #4561      +/-   ##
===========================================
- Coverage    80.01%   79.99%   -0.03%     
===========================================
  Files         2103     2107       +4     
  Lines        55786    55811      +25     
  Branches      6939     6954      +15     
===========================================
+ Hits         44638    44644       +6     
- Misses        8755     8772      +17     
- Partials      2393     2395       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@jmartinesp jmartinesp force-pushed the feat/split-matrix-room-into-joined-and-not-joined branch from 39bbc07 to a045768 Compare April 14, 2025 13:41
@jmartinesp jmartinesp added the PR-Misc For other changes label Apr 15, 2025
@jmartinesp jmartinesp marked this pull request as ready for review April 15, 2025 11:52
@jmartinesp jmartinesp requested a review from a team as a code owner April 15, 2025 11:52
@jmartinesp jmartinesp requested review from ganfra and removed request for a team April 15, 2025 11:52
Copy link
Member

@ganfra ganfra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some first remarks to discuss

import kotlinx.coroutines.flow.StateFlow
import java.io.Closeable
import java.io.File

interface MatrixRoom : Closeable {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should take the opportunity to simplify names?
MatrixRoom to BaseRoomor simply Room
JoinedMatrixRoom to JoinedRoom

maxSize = CACHE_SIZE,
onEntryRemoved = { evicted, roomId, oldRoom, _ ->
Timber.d("On room removed from cache: $roomId, evicted: $evicted")
oldRoom.roomListItem.close()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we remove this?

Copy link
Member Author

@jmartinesp jmartinesp Apr 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The room cache should not be needed if we have the persistent event cache in the app, and it can even be problematic to have it around since clearing the cache for a room needs the room to not have a live timeline instantiated, otherwise the cache won't be cleared, and if we keep references to the Rust Room we also keep references to its timeline, I think.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So lets remove completely the cache?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I did that, did I miss anything 🤔 ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, I think I got tricked by github ui

* Forget the room if we had access to it, and it was left or banned.
*/
suspend fun forget(): Result<Unit>
interface NotJoinedRoom : AutoCloseable {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I like this NotJoinedRoom because it's a bit confusing how the api looks like in comparison with JoinedRoom
Maybe just being able to fetch RoomPreviewInfo and when needed a BaseRoom using getRoom would be enough?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the SDK level we were thinking about making the getRoomPreview methods return a struct (or a data class in Kotlin) with both the preview info and the optional Room instance, so I made these changes trying to follow that suggestion. Maybe we can discuss this with the Rust team if the API is not what we want.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, this just feel a bit strange to use, but why not...

@@ -52,8 +53,8 @@ interface MatrixClient {
val mediaLoader: MatrixMediaLoader
val sessionCoroutineScope: CoroutineScope
val ignoredUsersFlow: StateFlow<ImmutableList<UserId>>
suspend fun getJoinedRoom(roomId: RoomId): JoinedMatrixRoom?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I'd prefer a method on the BaseRoom to initialise a JoinedRoom from it

class BaseRoom {
   ...
    suspend fun asJoined(): JoinedMatrixRoom()? 
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We actually need the RoomListItem to instantiate the live timeline, so it may not be that easy 🫤 . We could keep a reference to the item in the base room, maybe, or to the RoomListService.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, lets keep it like this then

Copy link
Member

@ganfra ganfra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, looks good to me, hopefully won't break things!
Can you just make the changes on the names like I said? thanks!

This new interface is the one which has guaranteed access to a live timeline, while the `MatrixRoom` one has access to a subset of features rooms both in joined and not joined can access.
This interface now has some `RoomPreviewInfo` and optional access to the `MatrixRoom` if it's a local room we can get from the SDK.
This means creating `getBaseRoom` and `getJoinedRoomOrPreview` methods to get either a `MatrixRoom` or either a `JoinedMatrixRoom` or `NotJoinedRoom` from the SDK.

The previously used room cache has been removed, as it's no longer needed with the persistent event cache.
- JoinedRoom
- NotJoinedRoom
- BaseRoom
- RoomInfo
- RoomMembersState
- RoomInfoMapper
- RoomPowerLevels
etc.
@jmartinesp jmartinesp force-pushed the feat/split-matrix-room-into-joined-and-not-joined branch from a045768 to b59a4f2 Compare April 23, 2025 11:06
Copy link

@jmartinesp jmartinesp merged commit 619aa6f into develop Apr 23, 2025
29 of 31 checks passed
@jmartinesp jmartinesp deleted the feat/split-matrix-room-into-joined-and-not-joined branch April 23, 2025 13:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
PR-Misc For other changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants