Skip to content

Commit 98057c1

Browse files
authored
Merge pull request #3725 from element-hq/feature/fga/knock_request_to_join
Feature: knock request to join
2 parents f1e8d3f + 7588b4e commit 98057c1

File tree

62 files changed

+755
-336
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+755
-336
lines changed

features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ class AcceptDeclineInvitePresenter @Inject constructor(
9494

9595
private fun CoroutineScope.declineInvite(roomId: RoomId, declinedAction: MutableState<AsyncAction<RoomId>>) = launch {
9696
suspend {
97-
client.getInvitedRoom(roomId)?.use {
98-
it.declineInvite().getOrThrow()
97+
client.getPendingRoom(roomId)?.use {
98+
it.leave().getOrThrow()
9999
notificationCleaner.clearMembershipNotificationForRoom(client.sessionId, roomId)
100100
}
101101
roomId

features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import io.element.android.libraries.matrix.test.A_ROOM_ID
2222
import io.element.android.libraries.matrix.test.A_ROOM_NAME
2323
import io.element.android.libraries.matrix.test.A_SESSION_ID
2424
import io.element.android.libraries.matrix.test.FakeMatrixClient
25-
import io.element.android.libraries.matrix.test.room.FakeInvitedRoom
25+
import io.element.android.libraries.matrix.test.room.FakePendingRoom
2626
import io.element.android.libraries.matrix.test.room.join.FakeJoinRoom
2727
import io.element.android.libraries.push.api.notifications.NotificationCleaner
2828
import io.element.android.libraries.push.test.notifications.FakeNotificationCleaner
@@ -78,7 +78,7 @@ class AcceptDeclineInvitePresenterTest {
7878
Result.failure<Unit>(RuntimeException("Failed to leave room"))
7979
}
8080
val client = FakeMatrixClient().apply {
81-
getInvitedRoomResults[A_ROOM_ID] = FakeInvitedRoom(declineInviteResult = declineInviteFailure)
81+
getPendingRoomResults[A_ROOM_ID] = FakePendingRoom(declineInviteResult = declineInviteFailure)
8282
}
8383
val presenter = createAcceptDeclineInvitePresenter(client = client)
8484
presenter.test {
@@ -121,7 +121,7 @@ class AcceptDeclineInvitePresenterTest {
121121
Result.success(Unit)
122122
}
123123
val client = FakeMatrixClient().apply {
124-
getInvitedRoomResults[A_ROOM_ID] = FakeInvitedRoom(declineInviteResult = declineInviteSuccess)
124+
getPendingRoomResults[A_ROOM_ID] = FakePendingRoom(declineInviteResult = declineInviteSuccess)
125125
}
126126
val presenter = createAcceptDeclineInvitePresenter(
127127
client = client,

features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomEvents.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ sealed interface JoinRoomEvents {
1111
data object RetryFetchingContent : JoinRoomEvents
1212
data object JoinRoom : JoinRoomEvents
1313
data object KnockRoom : JoinRoomEvents
14-
data object ClearError : JoinRoomEvents
14+
data class CancelKnock(val requiresConfirmation: Boolean) : JoinRoomEvents
15+
data class UpdateKnockMessage(val message: String) : JoinRoomEvents
16+
data object ClearActionStates : JoinRoomEvents
1517
data object AcceptInvite : JoinRoomEvents
1618
data object DeclineInvite : JoinRoomEvents
1719
}

features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomNode.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ class JoinRoomNode @AssistedInject constructor(
4343
state = state,
4444
onBackClick = ::navigateUp,
4545
onJoinSuccess = ::navigateUp,
46-
onKnockSuccess = ::navigateUp,
46+
onCancelKnockSuccess = ::navigateUp,
47+
onKnockSuccess = { },
4748
modifier = modifier
4849
)
4950
acceptDeclineInviteView.Render(

features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ import androidx.compose.runtime.mutableStateOf
1717
import androidx.compose.runtime.produceState
1818
import androidx.compose.runtime.remember
1919
import androidx.compose.runtime.rememberCoroutineScope
20+
import androidx.compose.runtime.saveable.rememberSaveable
2021
import androidx.compose.runtime.setValue
2122
import dagger.assisted.Assisted
2223
import dagger.assisted.AssistedInject
2324
import im.vector.app.features.analytics.plan.JoinedRoom
2425
import io.element.android.features.invite.api.response.AcceptDeclineInviteEvents
2526
import io.element.android.features.invite.api.response.AcceptDeclineInviteState
2627
import io.element.android.features.invite.api.response.InviteData
28+
import io.element.android.features.joinroom.impl.di.CancelKnockRoom
2729
import io.element.android.features.joinroom.impl.di.KnockRoom
2830
import io.element.android.features.roomdirectory.api.RoomDescription
2931
import io.element.android.libraries.architecture.AsyncAction
@@ -46,6 +48,8 @@ import kotlinx.coroutines.CoroutineScope
4648
import kotlinx.coroutines.launch
4749
import java.util.Optional
4850

51+
private const val MAX_KNOCK_MESSAGE_LENGTH = 500
52+
4953
class JoinRoomPresenter @AssistedInject constructor(
5054
@Assisted private val roomId: RoomId,
5155
@Assisted private val roomIdOrAlias: RoomIdOrAlias,
@@ -55,6 +59,7 @@ class JoinRoomPresenter @AssistedInject constructor(
5559
private val matrixClient: MatrixClient,
5660
private val joinRoom: JoinRoom,
5761
private val knockRoom: KnockRoom,
62+
private val cancelKnockRoom: CancelKnockRoom,
5863
private val acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState>,
5964
private val buildMeta: BuildMeta,
6065
) : Presenter<JoinRoomState> {
@@ -75,6 +80,8 @@ class JoinRoomPresenter @AssistedInject constructor(
7580
val roomInfo by matrixClient.getRoomInfoFlow(roomId.toRoomIdOrAlias()).collectAsState(initial = Optional.empty())
7681
val joinAction: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
7782
val knockAction: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
83+
val cancelKnockAction: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
84+
var knockMessage by rememberSaveable { mutableStateOf("") }
7885
val contentState by produceState<ContentState>(
7986
initialValue = ContentState.Loading(roomIdOrAlias),
8087
key1 = roomInfo,
@@ -110,7 +117,7 @@ class JoinRoomPresenter @AssistedInject constructor(
110117
fun handleEvents(event: JoinRoomEvents) {
111118
when (event) {
112119
JoinRoomEvents.JoinRoom -> coroutineScope.joinRoom(joinAction)
113-
JoinRoomEvents.KnockRoom -> coroutineScope.knockRoom(knockAction)
120+
is JoinRoomEvents.KnockRoom -> coroutineScope.knockRoom(knockAction, knockMessage)
114121
JoinRoomEvents.AcceptInvite -> {
115122
val inviteData = contentState.toInviteData() ?: return
116123
acceptDeclineInviteState.eventSink(
@@ -123,12 +130,17 @@ class JoinRoomPresenter @AssistedInject constructor(
123130
AcceptDeclineInviteEvents.DeclineInvite(inviteData)
124131
)
125132
}
133+
is JoinRoomEvents.CancelKnock -> coroutineScope.cancelKnockRoom(event.requiresConfirmation, cancelKnockAction)
126134
JoinRoomEvents.RetryFetchingContent -> {
127135
retryCount++
128136
}
129-
JoinRoomEvents.ClearError -> {
137+
JoinRoomEvents.ClearActionStates -> {
130138
knockAction.value = AsyncAction.Uninitialized
131139
joinAction.value = AsyncAction.Uninitialized
140+
cancelKnockAction.value = AsyncAction.Uninitialized
141+
}
142+
is JoinRoomEvents.UpdateKnockMessage -> {
143+
knockMessage = event.message.take(MAX_KNOCK_MESSAGE_LENGTH)
132144
}
133145
}
134146
}
@@ -138,7 +150,9 @@ class JoinRoomPresenter @AssistedInject constructor(
138150
acceptDeclineInviteState = acceptDeclineInviteState,
139151
joinAction = joinAction.value,
140152
knockAction = knockAction.value,
153+
cancelKnockAction = cancelKnockAction.value,
141154
applicationName = buildMeta.applicationName,
155+
knockMessage = knockMessage,
142156
eventSink = ::handleEvents
143157
)
144158
}
@@ -153,9 +167,19 @@ class JoinRoomPresenter @AssistedInject constructor(
153167
}
154168
}
155169

156-
private fun CoroutineScope.knockRoom(knockAction: MutableState<AsyncAction<Unit>>) = launch {
170+
private fun CoroutineScope.knockRoom(knockAction: MutableState<AsyncAction<Unit>>, message: String) = launch {
157171
knockAction.runUpdatingState {
158-
knockRoom(roomId)
172+
knockRoom(roomIdOrAlias, message, serverNames)
173+
}
174+
}
175+
176+
private fun CoroutineScope.cancelKnockRoom(requiresConfirmation: Boolean, cancelKnockAction: MutableState<AsyncAction<Unit>>) = launch {
177+
if (requiresConfirmation) {
178+
cancelKnockAction.value = AsyncAction.ConfirmingNoParams
179+
} else {
180+
cancelKnockAction.runUpdatingState {
181+
cancelKnockRoom(roomId)
182+
}
159183
}
160184
}
161185
}
@@ -206,14 +230,15 @@ internal fun MatrixRoomInfo.toContentState(): ContentState {
206230
name = name,
207231
topic = topic,
208232
alias = canonicalAlias,
209-
numberOfMembers = activeMembersCount.toLong(),
233+
numberOfMembers = activeMembersCount,
210234
isDm = isDm,
211235
roomType = if (isSpace) RoomType.Space else RoomType.Room,
212236
roomAvatarUrl = avatarUrl,
213237
joinAuthorisationStatus = when {
214238
currentUserMembership == CurrentUserMembership.INVITED -> JoinAuthorisationStatus.IsInvited(
215239
inviteSender = inviter?.toInviteSender()
216240
)
241+
currentUserMembership == CurrentUserMembership.KNOCKED -> JoinAuthorisationStatus.IsKnocked
217242
isPublic -> JoinAuthorisationStatus.CanJoin
218243
else -> JoinAuthorisationStatus.Unknown
219244
}

features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ data class JoinRoomState(
2424
val acceptDeclineInviteState: AcceptDeclineInviteState,
2525
val joinAction: AsyncAction<Unit>,
2626
val knockAction: AsyncAction<Unit>,
27+
val cancelKnockAction: AsyncAction<Unit>,
2728
val applicationName: String,
29+
val knockMessage: String,
2830
val eventSink: (JoinRoomEvents) -> Unit
2931
) {
3032
val joinAuthorisationStatus = when (contentState) {
@@ -68,6 +70,7 @@ sealed interface ContentState {
6870

6971
sealed interface JoinAuthorisationStatus {
7072
data class IsInvited(val inviteSender: InviteSender?) : JoinAuthorisationStatus
73+
data object IsKnocked : JoinAuthorisationStatus
7174
data object CanKnock : JoinAuthorisationStatus
7275
data object CanJoin : JoinAuthorisationStatus
7376
data object Unknown : JoinAuthorisationStatus

features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ open class JoinRoomStateProvider : PreviewParameterProvider<JoinRoomState> {
8181
isDm = true,
8282
)
8383
),
84+
aJoinRoomState(
85+
contentState = aLoadedContentState(
86+
name = "A knocked Room",
87+
joinAuthorisationStatus = JoinAuthorisationStatus.IsKnocked
88+
)
89+
)
8490
)
8591
}
8692

@@ -124,13 +130,17 @@ fun aJoinRoomState(
124130
acceptDeclineInviteState: AcceptDeclineInviteState = anAcceptDeclineInviteState(),
125131
joinAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
126132
knockAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
133+
cancelKnockAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
134+
knockMessage: String = "",
127135
eventSink: (JoinRoomEvents) -> Unit = {}
128136
) = JoinRoomState(
129137
contentState = contentState,
130138
acceptDeclineInviteState = acceptDeclineInviteState,
131139
joinAction = joinAction,
132140
knockAction = knockAction,
141+
cancelKnockAction = cancelKnockAction,
133142
applicationName = "AppName",
143+
knockMessage = knockMessage,
134144
eventSink = eventSink
135145
)
136146

0 commit comments

Comments
 (0)