JoinRoomEvents -> JoinRoomEvent

This commit is contained in:
Benoit Marty
2026-08-25 09:57:38 +02:00
parent 55a7d278c9
commit 19221a8042
7 changed files with 79 additions and 79 deletions
@@ -10,15 +10,15 @@ package io.element.android.features.joinroom.impl
import io.element.android.features.invite.api.InviteData
sealed interface JoinRoomEvents {
data object RetryFetchingContent : JoinRoomEvents
data object DismissErrorAndHideContent : JoinRoomEvents
data object JoinRoom : JoinRoomEvents
data object KnockRoom : JoinRoomEvents
data object ForgetRoom : JoinRoomEvents
data class CancelKnock(val requiresConfirmation: Boolean) : JoinRoomEvents
data class UpdateKnockMessage(val message: String) : JoinRoomEvents
data object ClearActionStates : JoinRoomEvents
data class AcceptInvite(val inviteData: InviteData) : JoinRoomEvents
data class DeclineInvite(val inviteData: InviteData, val blockUser: Boolean) : JoinRoomEvents
sealed interface JoinRoomEvent {
data object RetryFetchingContent : JoinRoomEvent
data object DismissErrorAndHideContent : JoinRoomEvent
data object JoinRoom : JoinRoomEvent
data object KnockRoom : JoinRoomEvent
data object ForgetRoom : JoinRoomEvent
data class CancelKnock(val requiresConfirmation: Boolean) : JoinRoomEvent
data class UpdateKnockMessage(val message: String) : JoinRoomEvent
data object ClearActionStates : JoinRoomEvent
data class AcceptInvite(val inviteData: InviteData) : JoinRoomEvent
data class DeclineInvite(val inviteData: InviteData, val blockUser: Boolean) : JoinRoomEvent
}
@@ -151,37 +151,37 @@ class JoinRoomPresenter(
contentState.markRoomInviteAsSeen()
}
fun handleEvent(event: JoinRoomEvents) {
fun handleEvent(event: JoinRoomEvent) {
when (event) {
JoinRoomEvents.JoinRoom -> coroutineScope.joinRoom(joinAction)
is JoinRoomEvents.KnockRoom -> coroutineScope.knockRoom(knockAction, knockMessage)
is JoinRoomEvents.AcceptInvite -> {
JoinRoomEvent.JoinRoom -> coroutineScope.joinRoom(joinAction)
is JoinRoomEvent.KnockRoom -> coroutineScope.knockRoom(knockAction, knockMessage)
is JoinRoomEvent.AcceptInvite -> {
acceptDeclineInviteState.eventSink(
AcceptDeclineInviteEvent.AcceptInvite(event.inviteData)
)
}
is JoinRoomEvents.DeclineInvite -> {
is JoinRoomEvent.DeclineInvite -> {
acceptDeclineInviteState.eventSink(
AcceptDeclineInviteEvent.DeclineInvite(invite = event.inviteData, blockUser = event.blockUser, shouldConfirm = true)
)
}
is JoinRoomEvents.CancelKnock -> coroutineScope.cancelKnockRoom(event.requiresConfirmation, cancelKnockAction)
JoinRoomEvents.RetryFetchingContent -> {
is JoinRoomEvent.CancelKnock -> coroutineScope.cancelKnockRoom(event.requiresConfirmation, cancelKnockAction)
JoinRoomEvent.RetryFetchingContent -> {
retryCount++
}
JoinRoomEvents.ClearActionStates -> {
JoinRoomEvent.ClearActionStates -> {
knockAction.value = AsyncAction.Uninitialized
joinAction.value = AsyncAction.Uninitialized
cancelKnockAction.value = AsyncAction.Uninitialized
forgetRoomAction.value = AsyncAction.Uninitialized
}
is JoinRoomEvents.UpdateKnockMessage -> {
is JoinRoomEvent.UpdateKnockMessage -> {
knockMessage = event.message.take(MAX_KNOCK_MESSAGE_LENGTH)
}
JoinRoomEvents.DismissErrorAndHideContent -> {
JoinRoomEvent.DismissErrorAndHideContent -> {
isDismissingContent = true
}
JoinRoomEvents.ForgetRoom -> coroutineScope.forgetRoom(forgetRoomAction)
JoinRoomEvent.ForgetRoom -> coroutineScope.forgetRoom(forgetRoomAction)
}
}
@@ -37,7 +37,7 @@ data class JoinRoomState(
val knockMessage: String,
val hideInviteAvatars: Boolean,
val canReportRoom: Boolean,
val eventSink: (JoinRoomEvents) -> Unit
val eventSink: (JoinRoomEvent) -> Unit
) {
val isJoinActionUnauthorized = joinAction is AsyncAction.Failure && joinAction.error is JoinRoom.Failures.UnauthorizedJoin
val joinAuthorisationStatus = when (contentState) {
@@ -207,7 +207,7 @@ fun aJoinRoomState(
knockMessage: String = "",
hideInviteAvatars: Boolean = false,
canReportRoom: Boolean = true,
eventSink: (JoinRoomEvents) -> Unit = {}
eventSink: (JoinRoomEvent) -> Unit = {}
) = JoinRoomState(
roomIdOrAlias = roomIdOrAlias,
contentState = contentState,
@@ -115,33 +115,33 @@ fun JoinRoomView(
contentState = state.contentState,
knockMessage = state.knockMessage,
hideAvatarsImages = state.hideAvatarsImages,
onKnockMessageUpdate = { state.eventSink(JoinRoomEvents.UpdateKnockMessage(it)) },
onKnockMessageUpdate = { state.eventSink(JoinRoomEvent.UpdateKnockMessage(it)) },
)
},
footer = {
JoinRoomFooter(
joinAuthorisationStatus = state.joinAuthorisationStatus,
onAcceptInvite = { inviteData ->
state.eventSink(JoinRoomEvents.AcceptInvite(inviteData))
state.eventSink(JoinRoomEvent.AcceptInvite(inviteData))
},
onDeclineInvite = { inviteData, blockUser ->
if (state.canReportRoom && blockUser) {
onDeclineInviteAndBlockUser(inviteData)
} else {
state.eventSink(JoinRoomEvents.DeclineInvite(inviteData, blockUser = blockUser))
state.eventSink(JoinRoomEvent.DeclineInvite(inviteData, blockUser = blockUser))
}
},
onJoinRoom = {
state.eventSink(JoinRoomEvents.JoinRoom)
state.eventSink(JoinRoomEvent.JoinRoom)
},
onKnockRoom = {
state.eventSink(JoinRoomEvents.KnockRoom)
state.eventSink(JoinRoomEvent.KnockRoom)
},
onCancelKnock = {
state.eventSink(JoinRoomEvents.CancelKnock(requiresConfirmation = true))
state.eventSink(JoinRoomEvent.CancelKnock(requiresConfirmation = true))
},
onForgetRoom = {
state.eventSink(JoinRoomEvents.ForgetRoom)
state.eventSink(JoinRoomEvent.ForgetRoom)
},
onGoBack = onBackClick,
)
@@ -152,9 +152,9 @@ fun JoinRoomView(
RetryDialog(
title = stringResource(R.string.screen_join_room_loading_alert_title),
content = stringResource(CommonStrings.error_network_or_server_issue),
onRetry = { state.eventSink(JoinRoomEvents.RetryFetchingContent) },
onRetry = { state.eventSink(JoinRoomEvent.RetryFetchingContent) },
onDismiss = {
state.eventSink(JoinRoomEvents.DismissErrorAndHideContent)
state.eventSink(JoinRoomEvent.DismissErrorAndHideContent)
onBackClick()
}
)
@@ -166,7 +166,7 @@ fun JoinRoomView(
errorTitle = { stringResource(CommonStrings.common_something_went_wrong) },
errorMessage = { stringResource(CommonStrings.error_network_or_server_issue) },
onSuccess = { onJoinSuccess() },
onErrorDismiss = { state.eventSink(JoinRoomEvents.ClearActionStates) },
onErrorDismiss = { state.eventSink(JoinRoomEvent.ClearActionStates) },
)
}
AsyncActionView(
@@ -174,19 +174,19 @@ fun JoinRoomView(
errorTitle = { stringResource(CommonStrings.common_something_went_wrong) },
errorMessage = { stringResource(CommonStrings.error_network_or_server_issue) },
onSuccess = { onKnockSuccess() },
onErrorDismiss = { state.eventSink(JoinRoomEvents.ClearActionStates) },
onErrorDismiss = { state.eventSink(JoinRoomEvent.ClearActionStates) },
)
AsyncActionView(
async = state.forgetAction,
errorTitle = { stringResource(CommonStrings.common_something_went_wrong) },
errorMessage = { stringResource(CommonStrings.error_network_or_server_issue) },
onSuccess = { onForgetSuccess() },
onErrorDismiss = { state.eventSink(JoinRoomEvents.ClearActionStates) },
onErrorDismiss = { state.eventSink(JoinRoomEvent.ClearActionStates) },
)
AsyncActionView(
async = state.cancelKnockAction,
onSuccess = { onCancelKnockSuccess() },
onErrorDismiss = { state.eventSink(JoinRoomEvents.ClearActionStates) },
onErrorDismiss = { state.eventSink(JoinRoomEvent.ClearActionStates) },
errorTitle = { stringResource(CommonStrings.common_something_went_wrong) },
errorMessage = { stringResource(CommonStrings.error_network_or_server_issue) },
confirmationDialog = {
@@ -195,8 +195,8 @@ fun JoinRoomView(
title = stringResource(R.string.screen_join_room_cancel_knock_alert_title),
submitText = stringResource(R.string.screen_join_room_cancel_knock_alert_confirmation),
cancelText = stringResource(CommonStrings.action_no),
onSubmitClick = { state.eventSink(JoinRoomEvents.CancelKnock(requiresConfirmation = false)) },
onDismiss = { state.eventSink(JoinRoomEvents.ClearActionStates) },
onSubmitClick = { state.eventSink(JoinRoomEvent.CancelKnock(requiresConfirmation = false)) },
onDismiss = { state.eventSink(JoinRoomEvent.ClearActionStates) },
)
},
)
@@ -388,8 +388,8 @@ class JoinRoomPresenterTest {
skipItems(1)
awaitItem().also { state ->
state.eventSink(JoinRoomEvents.AcceptInvite(inviteData))
state.eventSink(JoinRoomEvents.DeclineInvite(inviteData, false))
state.eventSink(JoinRoomEvent.AcceptInvite(inviteData))
state.eventSink(JoinRoomEvent.DeclineInvite(inviteData, false))
assert(eventSinkRecorder)
.isCalledExactly(2)
@@ -422,7 +422,7 @@ class JoinRoomPresenterTest {
presenter.test {
skipItems(1)
awaitItem().also { state ->
state.eventSink(JoinRoomEvents.JoinRoom)
state.eventSink(JoinRoomEvent.JoinRoom)
}
awaitItem().also { state ->
assertThat(state.joinAction).isEqualTo(AsyncAction.Loading)
@@ -453,14 +453,14 @@ class JoinRoomPresenterTest {
presenter.test {
skipItems(1)
awaitItem().also { state ->
state.eventSink(JoinRoomEvents.JoinRoom)
state.eventSink(JoinRoomEvent.JoinRoom)
}
awaitItem().also { state ->
assertThat(state.joinAction).isEqualTo(AsyncAction.Loading)
}
awaitItem().also { state ->
assertThat(state.joinAction).isEqualTo(AsyncAction.Failure(AN_EXCEPTION))
state.eventSink(JoinRoomEvents.ClearActionStates)
state.eventSink(JoinRoomEvent.ClearActionStates)
}
awaitItem().also { state ->
assertThat(state.joinAction).isEqualTo(AsyncAction.Uninitialized)
@@ -480,7 +480,7 @@ class JoinRoomPresenterTest {
presenter.test {
skipItems(1)
awaitItem().also { state ->
state.eventSink(JoinRoomEvents.JoinRoom)
state.eventSink(JoinRoomEvent.JoinRoom)
}
awaitItem().also { state ->
assertThat(state.joinAction).isEqualTo(AsyncAction.Loading)
@@ -683,17 +683,17 @@ class JoinRoomPresenterTest {
presenter.test {
skipItems(1)
awaitItem().also { state ->
state.eventSink(JoinRoomEvents.UpdateKnockMessage(knockMessage))
state.eventSink(JoinRoomEvent.UpdateKnockMessage(knockMessage))
}
awaitItem().also { state ->
state.eventSink(JoinRoomEvents.KnockRoom)
state.eventSink(JoinRoomEvent.KnockRoom)
}
assertThat(awaitItem().knockAction).isEqualTo(AsyncAction.Loading)
awaitItem().also { state ->
assertThat(state.knockAction).isEqualTo(AsyncAction.Success(Unit))
fakeKnockRoom.lambda = knockRoomFailure
state.eventSink(JoinRoomEvents.KnockRoom)
state.eventSink(JoinRoomEvent.KnockRoom)
}
assertThat(awaitItem().knockAction).isEqualTo(AsyncAction.Loading)
@@ -731,17 +731,17 @@ class JoinRoomPresenterTest {
presenter.test {
skipItems(1)
awaitItem().also { state ->
state.eventSink(JoinRoomEvents.CancelKnock(true))
state.eventSink(JoinRoomEvent.CancelKnock(true))
}
awaitItem().also { state ->
assertThat(state.cancelKnockAction).isEqualTo(AsyncAction.ConfirmingNoParams)
state.eventSink(JoinRoomEvents.CancelKnock(false))
state.eventSink(JoinRoomEvent.CancelKnock(false))
}
assertThat(awaitItem().cancelKnockAction).isEqualTo(AsyncAction.Loading)
awaitItem().also { state ->
assertThat(state.cancelKnockAction).isEqualTo(AsyncAction.Success(Unit))
cancelKnockRoom.lambda = cancelKnockRoomFailure
state.eventSink(JoinRoomEvents.CancelKnock(false))
state.eventSink(JoinRoomEvent.CancelKnock(false))
}
assertThat(awaitItem().cancelKnockAction).isEqualTo(AsyncAction.Loading)
awaitItem().also { state ->
@@ -778,14 +778,14 @@ class JoinRoomPresenterTest {
presenter.test {
skipItems(1)
awaitItem().also { state ->
state.eventSink(JoinRoomEvents.ForgetRoom)
state.eventSink(JoinRoomEvent.ForgetRoom)
}
assertThat(awaitItem().forgetAction).isEqualTo(AsyncAction.Loading)
awaitItem().also { state ->
assertThat(state.forgetAction).isEqualTo(AsyncAction.Success(Unit))
fakeForgetRoom.lambda = forgetRoomFailure
state.eventSink(JoinRoomEvents.ForgetRoom)
state.eventSink(JoinRoomEvent.ForgetRoom)
}
assertThat(awaitItem().forgetAction).isEqualTo(AsyncAction.Loading)
@@ -34,7 +34,7 @@ import org.junit.Test
class JoinRoomViewTest : RobolectricTest() {
@Test
fun `clicking on back invoke the expected callback`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<JoinRoomEvents>(expectEvents = false)
val eventsRecorder = EventsRecorder<JoinRoomEvent>(expectEvents = false)
ensureCalledOnce {
setJoinRoomView(
aJoinRoomState(
@@ -48,7 +48,7 @@ class JoinRoomViewTest : RobolectricTest() {
@Test
fun `clicking on Join room on CanJoin room emits the expected Event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<JoinRoomEvents>()
val eventsRecorder = EventsRecorder<JoinRoomEvent>()
setJoinRoomView(
aJoinRoomState(
contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanJoin),
@@ -56,12 +56,12 @@ class JoinRoomViewTest : RobolectricTest() {
),
)
clickOn(R.string.screen_join_room_join_action)
eventsRecorder.assertSingle(JoinRoomEvents.JoinRoom)
eventsRecorder.assertSingle(JoinRoomEvent.JoinRoom)
}
@Test
fun `clicking on Knock room on CanKnock room emits the expected Event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<JoinRoomEvents>()
val eventsRecorder = EventsRecorder<JoinRoomEvent>()
setJoinRoomView(
aJoinRoomState(
contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanKnock),
@@ -70,12 +70,12 @@ class JoinRoomViewTest : RobolectricTest() {
),
)
clickOn(R.string.screen_join_room_knock_action)
eventsRecorder.assertSingle(JoinRoomEvents.KnockRoom)
eventsRecorder.assertSingle(JoinRoomEvent.KnockRoom)
}
@Test
fun `clicking on closing Knock error emits the expected Event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<JoinRoomEvents>()
val eventsRecorder = EventsRecorder<JoinRoomEvent>()
setJoinRoomView(
aJoinRoomState(
contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanKnock),
@@ -84,12 +84,12 @@ class JoinRoomViewTest : RobolectricTest() {
),
)
clickOn(CommonStrings.action_ok)
eventsRecorder.assertSingle(JoinRoomEvents.ClearActionStates)
eventsRecorder.assertSingle(JoinRoomEvent.ClearActionStates)
}
@Test
fun `clicking on cancel knock request emit the expected Event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<JoinRoomEvents>()
val eventsRecorder = EventsRecorder<JoinRoomEvent>()
setJoinRoomView(
aJoinRoomState(
contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.IsKnocked),
@@ -97,12 +97,12 @@ class JoinRoomViewTest : RobolectricTest() {
),
)
clickOn(R.string.screen_join_room_cancel_knock_action)
eventsRecorder.assertSingle(JoinRoomEvents.CancelKnock(true))
eventsRecorder.assertSingle(JoinRoomEvent.CancelKnock(true))
}
@Test
fun `clicking on closing Cancel Knock error emits the expected Event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<JoinRoomEvents>()
val eventsRecorder = EventsRecorder<JoinRoomEvent>()
setJoinRoomView(
aJoinRoomState(
contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.IsKnocked),
@@ -111,12 +111,12 @@ class JoinRoomViewTest : RobolectricTest() {
),
)
clickOn(CommonStrings.action_ok)
eventsRecorder.assertSingle(JoinRoomEvents.ClearActionStates)
eventsRecorder.assertSingle(JoinRoomEvent.ClearActionStates)
}
@Test
fun `clicking on closing Join error emits the expected Event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<JoinRoomEvents>()
val eventsRecorder = EventsRecorder<JoinRoomEvent>()
setJoinRoomView(
aJoinRoomState(
contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanKnock),
@@ -125,12 +125,12 @@ class JoinRoomViewTest : RobolectricTest() {
),
)
clickOn(CommonStrings.action_ok)
eventsRecorder.assertSingle(JoinRoomEvents.ClearActionStates)
eventsRecorder.assertSingle(JoinRoomEvent.ClearActionStates)
}
@Test
fun `when joining room is successful, the expected callback is invoked`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<JoinRoomEvents>(expectEvents = false)
val eventsRecorder = EventsRecorder<JoinRoomEvent>(expectEvents = false)
ensureCalledOnce {
setJoinRoomView(
aJoinRoomState(
@@ -144,7 +144,7 @@ class JoinRoomViewTest : RobolectricTest() {
@Test
fun `clicking on Accept when JoinAuthorisationStatus is IsInvited emits the expected Event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<JoinRoomEvents>()
val eventsRecorder = EventsRecorder<JoinRoomEvent>()
val inviteData = anInviteData()
setJoinRoomView(
aJoinRoomState(
@@ -153,12 +153,12 @@ class JoinRoomViewTest : RobolectricTest() {
),
)
clickOn(CommonStrings.action_accept)
eventsRecorder.assertSingle(JoinRoomEvents.AcceptInvite(inviteData))
eventsRecorder.assertSingle(JoinRoomEvent.AcceptInvite(inviteData))
}
@Test
fun `clicking on Decline when JoinAuthorisationStatus is IsInvited emits the expected Event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<JoinRoomEvents>()
val eventsRecorder = EventsRecorder<JoinRoomEvent>()
val inviteData = anInviteData()
setJoinRoomView(
aJoinRoomState(
@@ -167,13 +167,13 @@ class JoinRoomViewTest : RobolectricTest() {
),
)
clickOn(CommonStrings.action_decline)
eventsRecorder.assertSingle(JoinRoomEvents.DeclineInvite(inviteData, false))
eventsRecorder.assertSingle(JoinRoomEvent.DeclineInvite(inviteData, false))
}
@Test
fun `clicking on Decline and block when JoinAuthorisationStatus is IsInvited and can report room, the expected callback is invoked`() {
runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<JoinRoomEvents>(expectEvents = false)
val eventsRecorder = EventsRecorder<JoinRoomEvent>(expectEvents = false)
val inviteData = anInviteData()
val joinRoomState = aJoinRoomState(
contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.IsInvited(inviteData, aRoomMember().toInviteSender())),
@@ -192,7 +192,7 @@ class JoinRoomViewTest : RobolectricTest() {
@Test
fun `clicking on Decline and block when JoinAuthorisationStatus is IsInvited and cant report room, emits the expected Event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<JoinRoomEvents>()
val eventsRecorder = EventsRecorder<JoinRoomEvent>()
val inviteData = anInviteData()
val joinRoomState = aJoinRoomState(
contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.IsInvited(inviteData, aRoomMember().toInviteSender())),
@@ -201,12 +201,12 @@ class JoinRoomViewTest : RobolectricTest() {
)
setJoinRoomView(state = joinRoomState)
clickOn(R.string.screen_join_room_decline_and_block_button_title)
eventsRecorder.assertSingle(JoinRoomEvents.DeclineInvite(inviteData, true))
eventsRecorder.assertSingle(JoinRoomEvent.DeclineInvite(inviteData, true))
}
@Test
fun `clicking on Retry when an error occurs emits the expected Event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<JoinRoomEvents>()
val eventsRecorder = EventsRecorder<JoinRoomEvent>()
setJoinRoomView(
aJoinRoomState(
contentState = aFailureContentState(),
@@ -214,12 +214,12 @@ class JoinRoomViewTest : RobolectricTest() {
),
)
clickOn(CommonStrings.action_retry)
eventsRecorder.assertSingle(JoinRoomEvents.RetryFetchingContent)
eventsRecorder.assertSingle(JoinRoomEvent.RetryFetchingContent)
}
@Test
fun `clicking on ok when user is unauthorized the expected callback`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<JoinRoomEvents>(expectEvents = false)
val eventsRecorder = EventsRecorder<JoinRoomEvent>(expectEvents = false)
ensureCalledOnce {
setJoinRoomView(
aJoinRoomState(
@@ -235,7 +235,7 @@ class JoinRoomViewTest : RobolectricTest() {
@Test
fun `clicking on forget when user is banned invokes the expected callback`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<JoinRoomEvents>()
val eventsRecorder = EventsRecorder<JoinRoomEvent>()
setJoinRoomView(
aJoinRoomState(
contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.IsBanned(null, null)),
@@ -243,7 +243,7 @@ class JoinRoomViewTest : RobolectricTest() {
),
)
clickOn(R.string.screen_join_room_forget_action)
eventsRecorder.assertSingle(JoinRoomEvents.ForgetRoom)
eventsRecorder.assertSingle(JoinRoomEvent.ForgetRoom)
}
}