-
Notifications
You must be signed in to change notification settings - Fork 746
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
Create the DM when sending an event #6127
Conversation
feeb70b
to
5c078bd
Compare
84a3240
to
596bd0b
Compare
b805645
to
d42a3da
Compare
596bd0b
to
53c73dc
Compare
53c73dc
to
2a597a8
Compare
e2ff5c4
to
79c6305
Compare
cc0280b
to
4b3d27a
Compare
@@ -78,6 +86,12 @@ internal class DefaultSendEventTask @Inject constructor( | |||
} | |||
} | |||
|
|||
private suspend fun createRoomAndSendEvent(params: SendEventTask.Params): String { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we could add a unit test for the case of local room id?
@@ -77,6 +81,7 @@ internal class DefaultCreateLocalRoomTask @Inject constructor( | |||
@SessionDatabase private val realmConfiguration: RealmConfiguration, | |||
private val createRoomBodyBuilder: CreateRoomBodyBuilder, | |||
private val userService: UserService, | |||
private val cryptoService: DefaultCryptoService, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should inject the interface CryptoService
instead, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh it is because the onStateEvent
is not part of the service interface... Strange maybe we should move the method to the interface. @bmarty What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I would not change it, I need it to register the local room in the crypto store in the same way as it is done for an existing room. I agree that it should be refactored, but I suppose that the intention was to not expose it in the interface.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should not inject service inside the SDK, and we should not inject implementations as well, but we have some exceptions...
The Service interface should contain only methods useful for the application, not the internal stuff.
So OK to keep it like this.
@@ -228,11 +237,40 @@ internal class DefaultCreateLocalRoomTask @Inject constructor( | |||
) | |||
} | |||
|
|||
val localRoomThreePidEvents = invited3Pids.map { body -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this could be extracted in 2 private methods? And I am struggling to understand the need for both LocalRoomThirdPartyInviteContent
and RoomThirdPartyInviteContent
. Since we are creating a local room, I thought we would only have LocalRoomThirdPartyInviteContent
. Maybe this could be explained through methods names or code comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I created a LocalRoomThirdPartyInviteContent
because I had to persist the full ThreePid
to propagate it to create the "real" room. When we invite someone by email to a room, the email address is obfuscated in the RoomThirdPartyInviteContent
and there is no way to retrieve it.
I created a new object for this purpose because I would not modify the existing object behaviour.
I also need the "RoomThirdPartyInviteContent" for the display of the timeline of the local room which should be as close as possible to a real room.
That's why I have both objects, I'll see to clarify this part.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update: I don't need it anymore the local event for the purpose of the room creation but it is still necessary for the correct display of the local timeline. I can remove it if we agree that the obfuscated three pid is enough.
} | ||
} | ||
} | ||
|
||
private suspend fun createRoomAndSendEvent(params: SendStateTask.Params): String { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could also add a unit test for this specific case.
...ava/im/vector/app/features/home/room/detail/timeline/helper/TimelineEventVisibilityHelper.kt
Show resolved
Hide resolved
...main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomFromLocalRoomTask.kt
Outdated
Show resolved
Hide resolved
...main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomFromLocalRoomTask.kt
Outdated
Show resolved
Hide resolved
...main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomFromLocalRoomTask.kt
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool feature! I added some suggestions mostly to ease reading of code. Let me know what do you think about it. I didn't test it but seeing the videos of the PR it looks good.
@mnaturel Thanks for your review! I totally agree about adding tests, I didn't mention it in the PR description but I'll add some unit tests, I would do it in a dedicated PR but I'll see if I can add some in this PR. BTW it's good to have your feedback on which part of code you suggest adding tests! |
4b3d27a
to
bfa840c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR! A few remarks on the implementation, will do some tests this afternoon.
@@ -70,6 +70,9 @@ object EventType { | |||
const val STATE_ROOM_ENCRYPTION = "m.room.encryption" | |||
const val STATE_ROOM_SERVER_ACL = "m.room.server_acl" | |||
|
|||
// This type is for local purposes, it should never be processed by the server | |||
const val LOCAL_STATE_ROOM_THIRD_PARTY_INVITE = "local.room.third_party_invite" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could be internal, as well as LocalRoomThirdPartyInviteContent
(and maybe move this class to the internal package?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -61,12 +64,12 @@ open class CreateRoomParams { | |||
* A list of user IDs to invite to the room. | |||
* This will tell the server to invite everyone in the list to the newly created room. | |||
*/ | |||
val invitedUserIds = mutableListOf<String>() | |||
var invitedUserIds: MutableList<String> = mutableListOf() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was it necessary to change from val
to var
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, otherwise Moshi will not be able to restore this field.
Btw I do not need to explicitly declare the type 90d688c
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure? All our Json data classes are using val
. When Moshi parse some Json, it stores the objects in temporary val, and then invoke the data class constructor. So it should work with val
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not a data class, when I originally tried by keeping the val
, some fields were not persisted, I thought that it was for another reason but changing to var
fixed the issue. I suppose that as these are not constructor fields, Moshi cannot do the same trick 😞
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not a data class
My bad, OK then!
*/ | ||
internal interface CreateLocalRoomStateEventsTask : Task<Params, List<Event>> { | ||
data class Params( | ||
val roomCreatorUserId: String, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The value will always be the current userId, no? In this case, it can be injected in the implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
listOf(localThirdPartyInviteEvent, thirdPartyInviteEvent) | ||
}.flatten() | ||
addAll(threePidEvents) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe rewrite to:
private fun MutableList<Event>.createRoomThreePidEvents() {
createRoomBody.invite3pids.orEmpty().forEach { body ->
val localThirdPartyInviteEvent = createLocalStateEvent(
type = EventType.LOCAL_STATE_ROOM_THIRD_PARTY_INVITE,
content = LocalRoomThirdPartyInviteContent(
isDirect = createRoomBody.isDirect.orFalse(),
membership = Membership.INVITE,
displayName = body.address,
thirdPartyInvite = body.toThreePid()
).toContent(),
)
val thirdPartyInviteEvent = createLocalStateEvent(
type = EventType.STATE_ROOM_THIRD_PARTY_INVITE,
content = RoomThirdPartyInviteContent(
displayName = body.address,
keyValidityUrl = null,
publicKey = null,
publicKeys = null
).toContent(),
)
add(localThirdPartyInviteEvent)
add(thirdPartyInviteEvent)
}
}
for clarity
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💯 I don't know why I made it complicated! cac4df7
* Generate the create state event related to the power levels using the given overridden values or the default values according to the specification. | ||
* Ref: https://spec.matrix.org/latest/client-server-api/#mroompower_levels | ||
*/ | ||
private fun MutableList<Event>.createRoomPowerLevelsEvent() = apply { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using = apply
is not necessary, since the return value is not used.
Better to use {
. (at all place in this class)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought by mistake it was necessary to chain the calls but not for my usage. 110caba
6a91920
to
cac4df7
Compare
SonarCloud Quality Gate failed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the update.
I have tested the feature, nomical case, i.e. inviting a matrixId and sending a text message, and this is working pretty well.
2 small glitches observed: first one on the timeline, when the room is created. 2nd one when going back to the room list, I can see twice the rooms for a few ms.
Nothing blocking though!
Approved!
Thanks for your feedback! The first glitch should be fixed by adding a loading wheel during the creation but I did not find a way to do it atm. |
Type of change
Content
Depends on #6051
Create the DM room when an event is sent from the local room timeline (text, image, audio, poll, location sharing...)
Motivation and context
Continue #5525
Screenshots / GIFs
Tests
Tested devices
Checklist