Add screen to render Spaces (they are not supported yet)
This commit is contained in:
committed by
Benoit Marty
parent
1ed593926f
commit
49439034e4
@@ -128,7 +128,15 @@ class RoomFlowNode @AssistedInject constructor(
|
||||
Timber.d("Room membership: ${roomInfo.map { it.currentUserMembership }}")
|
||||
val info = roomInfo.getOrNull()
|
||||
if (info?.currentUserMembership == CurrentUserMembership.JOINED) {
|
||||
backstack.newRoot(NavTarget.JoinedRoom(roomId))
|
||||
if (info.isSpace) {
|
||||
// It should not happen, but probably due to an issue in the sliding sync,
|
||||
// we can have a space here in case the space has just been joined.
|
||||
// So navigate to the JoinRoom target for now, which will
|
||||
// handle the space not supported screen
|
||||
backstack.newRoot(NavTarget.JoinRoom(roomId))
|
||||
} else {
|
||||
backstack.newRoot(NavTarget.JoinedRoom(roomId))
|
||||
}
|
||||
} else {
|
||||
backstack.newRoot(NavTarget.JoinRoom(roomId))
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ import io.element.android.features.roomdirectory.api.RoomDescription
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.architecture.runUpdatingState
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
|
||||
@@ -57,6 +58,7 @@ class JoinRoomPresenter @AssistedInject constructor(
|
||||
private val matrixClient: MatrixClient,
|
||||
private val knockRoom: KnockRoom,
|
||||
private val acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState>,
|
||||
private val buildMeta: BuildMeta,
|
||||
) : Presenter<JoinRoomState> {
|
||||
interface Factory {
|
||||
fun create(
|
||||
@@ -135,6 +137,7 @@ class JoinRoomPresenter @AssistedInject constructor(
|
||||
contentState = contentState,
|
||||
acceptDeclineInviteState = acceptDeclineInviteState,
|
||||
knockAction = knockAction.value,
|
||||
applicationName = buildMeta.applicationName,
|
||||
eventSink = ::handleEvents
|
||||
)
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ data class JoinRoomState(
|
||||
val contentState: ContentState,
|
||||
val acceptDeclineInviteState: AcceptDeclineInviteState,
|
||||
val knockAction: AsyncAction<Unit>,
|
||||
val applicationName: String,
|
||||
val eventSink: (JoinRoomEvents) -> Unit
|
||||
) {
|
||||
val joinAuthorisationStatus = when (contentState) {
|
||||
|
||||
@@ -75,6 +75,15 @@ open class JoinRoomStateProvider : PreviewParameterProvider<JoinRoomState> {
|
||||
aJoinRoomState(
|
||||
contentState = aFailureContentState(roomIdOrAlias = A_ROOM_ALIAS.toRoomIdOrAlias())
|
||||
),
|
||||
aJoinRoomState(
|
||||
contentState = aLoadedContentState(
|
||||
roomId = RoomId("!aSpaceId:domain"),
|
||||
name = "A space",
|
||||
alias = null,
|
||||
topic = "This is the topic of a space",
|
||||
roomType = RoomType.Space,
|
||||
)
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -122,6 +131,7 @@ fun aJoinRoomState(
|
||||
contentState = contentState,
|
||||
acceptDeclineInviteState = acceptDeclineInviteState,
|
||||
knockAction = knockAction,
|
||||
applicationName = "AppName",
|
||||
eventSink = eventSink
|
||||
)
|
||||
|
||||
|
||||
@@ -20,8 +20,10 @@ import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -33,6 +35,7 @@ import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.libraries.designsystem.atomic.atoms.PlaceholderAtom
|
||||
import io.element.android.libraries.designsystem.atomic.atoms.RoomPreviewDescriptionAtom
|
||||
import io.element.android.libraries.designsystem.atomic.atoms.RoomPreviewSubtitleAtom
|
||||
@@ -55,6 +58,7 @@ import io.element.android.libraries.designsystem.theme.components.OutlinedButton
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
|
||||
import io.element.android.libraries.matrix.api.room.RoomType
|
||||
import io.element.android.libraries.matrix.ui.components.InviteSenderView
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
@@ -76,7 +80,10 @@ fun JoinRoomView(
|
||||
JoinRoomTopBar(onBackClicked = onBackPressed)
|
||||
},
|
||||
content = {
|
||||
JoinRoomContent(contentState = state.contentState)
|
||||
JoinRoomContent(
|
||||
contentState = state.contentState,
|
||||
applicationName = state.applicationName,
|
||||
)
|
||||
},
|
||||
footer = {
|
||||
JoinRoomFooter(
|
||||
@@ -95,7 +102,8 @@ fun JoinRoomView(
|
||||
},
|
||||
onRetry = {
|
||||
state.eventSink(JoinRoomEvents.RetryFetchingContent)
|
||||
}
|
||||
},
|
||||
onGoBack = onBackPressed,
|
||||
)
|
||||
}
|
||||
)
|
||||
@@ -116,6 +124,7 @@ private fun JoinRoomFooter(
|
||||
onJoinRoom: () -> Unit,
|
||||
onKnockRoom: () -> Unit,
|
||||
onRetry: () -> Unit,
|
||||
onGoBack: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
if (state.contentState is ContentState.Failure) {
|
||||
@@ -125,6 +134,13 @@ private fun JoinRoomFooter(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
size = ButtonSize.Large,
|
||||
)
|
||||
} else if (state.contentState is ContentState.Loaded && state.contentState.roomType == RoomType.Space) {
|
||||
Button(
|
||||
text = stringResource(CommonStrings.action_go_back),
|
||||
onClick = onGoBack,
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
size = ButtonSize.Large,
|
||||
)
|
||||
} else {
|
||||
val joinAuthorisationStatus = state.joinAuthorisationStatus
|
||||
when (joinAuthorisationStatus) {
|
||||
@@ -171,6 +187,7 @@ private fun JoinRoomFooter(
|
||||
@Composable
|
||||
private fun JoinRoomContent(
|
||||
contentState: ContentState,
|
||||
applicationName: String,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
when (contentState) {
|
||||
@@ -211,6 +228,21 @@ private fun JoinRoomContent(
|
||||
InviteSenderView(inviteSender = inviteSender)
|
||||
}
|
||||
RoomPreviewDescriptionAtom(contentState.topic ?: "")
|
||||
if (contentState.roomType == RoomType.Space) {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
Text(
|
||||
text = stringResource(R.string.screen_join_room_space_not_supported_title),
|
||||
textAlign = TextAlign.Center,
|
||||
style = ElementTheme.typography.fontBodyLgMedium,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.screen_join_room_space_not_supported_description, applicationName),
|
||||
textAlign = TextAlign.Center,
|
||||
style = ElementTheme.typography.fontBodyMdRegular,
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
memberCount = {
|
||||
|
||||
@@ -23,6 +23,7 @@ import io.element.android.features.invite.api.response.AcceptDeclineInviteState
|
||||
import io.element.android.features.joinroom.impl.JoinRoomPresenter
|
||||
import io.element.android.features.roomdirectory.api.RoomDescription
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
import io.element.android.libraries.di.SessionScope
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
@@ -37,6 +38,7 @@ object JoinRoomModule {
|
||||
client: MatrixClient,
|
||||
knockRoom: KnockRoom,
|
||||
acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState>,
|
||||
buildMeta: BuildMeta,
|
||||
): JoinRoomPresenter.Factory {
|
||||
return object : JoinRoomPresenter.Factory {
|
||||
override fun create(
|
||||
@@ -51,6 +53,7 @@ object JoinRoomModule {
|
||||
matrixClient = client,
|
||||
knockRoom = knockRoom,
|
||||
acceptDeclineInvitePresenter = acceptDeclineInvitePresenter,
|
||||
buildMeta = buildMeta,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_join_room_join_action">"Join room"</string>
|
||||
<string name="screen_join_room_knock_action">"Knock to join"</string>
|
||||
<string name="screen_join_room_space_not_supported_description">"%1$s does not support spaces yet. You can access spaces on web."</string>
|
||||
<string name="screen_join_room_space_not_supported_title">"Spaces are not supported yet"</string>
|
||||
<string name="screen_join_room_subtitle_knock">"Click the button below and a room administrator will be notified. You’ll be able to join the conversation once approved."</string>
|
||||
<string name="screen_join_room_subtitle_no_preview">"You must be a member of this room to view the message history."</string>
|
||||
<string name="screen_join_room_title_knock">"Want to join this room?"</string>
|
||||
|
||||
@@ -24,6 +24,7 @@ import io.element.android.features.joinroom.impl.di.KnockRoom
|
||||
import io.element.android.features.roomdirectory.api.RoomDescription
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.RoomAlias
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
@@ -36,6 +37,7 @@ import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_NAME
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.matrix.test.core.aBuildMeta
|
||||
import io.element.android.libraries.matrix.test.room.aRoomInfo
|
||||
import io.element.android.libraries.matrix.test.room.aRoomMember
|
||||
import io.element.android.libraries.matrix.ui.model.toInviteSender
|
||||
@@ -62,6 +64,7 @@ class JoinRoomPresenterTest {
|
||||
assertThat(state.contentState).isEqualTo(ContentState.Loading(A_ROOM_ID.toRoomIdOrAlias()))
|
||||
assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.Unknown)
|
||||
assertThat(state.acceptDeclineInviteState).isEqualTo(anAcceptDeclineInviteState())
|
||||
assertThat(state.applicationName).isEqualTo("AppName")
|
||||
cancelAndIgnoreRemainingEvents()
|
||||
}
|
||||
}
|
||||
@@ -414,6 +417,7 @@ class JoinRoomPresenterTest {
|
||||
roomDescription: Optional<RoomDescription> = Optional.empty(),
|
||||
matrixClient: MatrixClient = FakeMatrixClient(),
|
||||
knockRoom: KnockRoom = FakeKnockRoom(),
|
||||
buildMeta: BuildMeta = aBuildMeta(applicationName = "AppName"),
|
||||
acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState> = Presenter { anAcceptDeclineInviteState() }
|
||||
): JoinRoomPresenter {
|
||||
return JoinRoomPresenter(
|
||||
@@ -422,6 +426,7 @@ class JoinRoomPresenterTest {
|
||||
roomDescription = roomDescription,
|
||||
matrixClient = matrixClient,
|
||||
knockRoom = knockRoom,
|
||||
buildMeta = buildMeta,
|
||||
acceptDeclineInvitePresenter = acceptDeclineInvitePresenter
|
||||
)
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import androidx.compose.ui.test.junit4.AndroidComposeTestRule
|
||||
import androidx.compose.ui.test.junit4.createAndroidComposeRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.matrix.api.room.RoomType
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
import io.element.android.tests.testutils.EnsureNeverCalled
|
||||
import io.element.android.tests.testutils.EventsRecorder
|
||||
@@ -128,6 +129,21 @@ class JoinRoomViewTest {
|
||||
rule.clickOn(CommonStrings.action_retry)
|
||||
eventsRecorder.assertSingle(JoinRoomEvents.RetryFetchingContent)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `clicking on Go back when a space is displayed invokes the expected callback`() {
|
||||
val eventsRecorder = EventsRecorder<JoinRoomEvents>(expectEvents = false)
|
||||
ensureCalledOnce {
|
||||
rule.setJoinRoomView(
|
||||
aJoinRoomState(
|
||||
contentState = aLoadedContentState(roomType = RoomType.Space),
|
||||
eventSink = eventsRecorder,
|
||||
),
|
||||
onBackPressed = it
|
||||
)
|
||||
rule.clickOn(CommonStrings.action_go_back)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setJoinRoomView(
|
||||
|
||||
@@ -27,7 +27,7 @@ fun RoomPreviewSubtitleAtom(subtitle: String, modifier: Modifier = Modifier) {
|
||||
Text(
|
||||
modifier = modifier,
|
||||
text = subtitle,
|
||||
style = ElementTheme.typography.fontBodyLgRegular,
|
||||
style = ElementTheme.typography.fontBodyMdRegular,
|
||||
textAlign = TextAlign.Center,
|
||||
color = ElementTheme.colors.textSecondary,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user