mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-03 06:55:41 +00:00
Rename Event
This commit is contained in:
+4
-11
@@ -10,18 +10,11 @@ package io.element.android.features.preferences.impl.userstatus
|
|||||||
import io.element.android.libraries.matrix.api.user.UserStatus
|
import io.element.android.libraries.matrix.api.user.UserStatus
|
||||||
|
|
||||||
sealed interface UserStatusEvent {
|
sealed interface UserStatusEvent {
|
||||||
/** User tapped the status row — open the picker bottom sheet. */
|
data object OpenPicker : UserStatusEvent
|
||||||
data object Open : UserStatusEvent
|
data object DismissPicker : UserStatusEvent
|
||||||
/** User dismissed the bottom sheet without selecting. */
|
data class SetStatus(val status: UserStatus) : UserStatusEvent
|
||||||
data object Dismiss : UserStatusEvent
|
|
||||||
/** User selected a predefined or confirmed a custom status. */
|
|
||||||
data class Set(val status: UserStatus) : UserStatusEvent
|
|
||||||
/** User tapped "Custom…" in the bottom sheet. */
|
|
||||||
data object OpenCustomInput : UserStatusEvent
|
data object OpenCustomInput : UserStatusEvent
|
||||||
/** User tapped Cancel in the inline custom input row. */
|
|
||||||
data object CancelCustomInput : UserStatusEvent
|
data object CancelCustomInput : UserStatusEvent
|
||||||
/** User changed the emoji in the custom input row. */
|
|
||||||
data class UpdateCustomEmoji(val emoji: String) : UserStatusEvent
|
data class UpdateCustomEmoji(val emoji: String) : UserStatusEvent
|
||||||
/** User tapped the clear action on an existing status. */
|
data object ClearStatus : UserStatusEvent
|
||||||
data object Clear : UserStatusEvent
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-8
@@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
package io.element.android.features.preferences.impl.userstatus
|
package io.element.android.features.preferences.impl.userstatus
|
||||||
|
|
||||||
import androidx.compose.foundation.text.input.TextFieldState
|
|
||||||
import androidx.compose.foundation.text.input.clearText
|
import androidx.compose.foundation.text.input.clearText
|
||||||
|
import androidx.compose.foundation.text.input.rememberTextFieldState
|
||||||
import androidx.compose.foundation.text.input.setTextAndPlaceCursorAtEnd
|
import androidx.compose.foundation.text.input.setTextAndPlaceCursorAtEnd
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
@@ -18,11 +18,9 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import dev.zacsweers.metro.ContributesBinding
|
import dev.zacsweers.metro.ContributesBinding
|
||||||
import dev.zacsweers.metro.Inject
|
|
||||||
import io.element.android.libraries.architecture.Presenter
|
import io.element.android.libraries.architecture.Presenter
|
||||||
import io.element.android.libraries.di.SessionScope
|
import io.element.android.libraries.di.SessionScope
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
import io.element.android.libraries.matrix.api.user.UserStatus
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@ContributesBinding(SessionScope::class)
|
@ContributesBinding(SessionScope::class)
|
||||||
@@ -34,13 +32,13 @@ class UserStatusPresenter(
|
|||||||
override fun present(): UserStatusState {
|
override fun present(): UserStatusState {
|
||||||
val userProfile by matrixClient.userProfile.collectAsState()
|
val userProfile by matrixClient.userProfile.collectAsState()
|
||||||
var pickerState by remember { mutableStateOf<UserStatusPickerState>(UserStatusPickerState.Hidden) }
|
var pickerState by remember { mutableStateOf<UserStatusPickerState>(UserStatusPickerState.Hidden) }
|
||||||
val customTextFieldState = remember { TextFieldState() }
|
val customTextFieldState = rememberTextFieldState()
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
|
||||||
fun handleEvent(event: UserStatusEvent) {
|
fun handleEvent(event: UserStatusEvent) {
|
||||||
when (event) {
|
when (event) {
|
||||||
UserStatusEvent.Open -> pickerState = UserStatusPickerState.ShowingPicker
|
UserStatusEvent.OpenPicker -> pickerState = UserStatusPickerState.ShowingPicker
|
||||||
UserStatusEvent.Dismiss -> pickerState = UserStatusPickerState.Hidden
|
UserStatusEvent.DismissPicker -> pickerState = UserStatusPickerState.Hidden
|
||||||
UserStatusEvent.OpenCustomInput -> {
|
UserStatusEvent.OpenCustomInput -> {
|
||||||
val raw = userProfile.rawStatus
|
val raw = userProfile.rawStatus
|
||||||
if (raw != null) {
|
if (raw != null) {
|
||||||
@@ -53,11 +51,11 @@ class UserStatusPresenter(
|
|||||||
textFieldState = customTextFieldState,
|
textFieldState = customTextFieldState,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is UserStatusEvent.Set -> {
|
is UserStatusEvent.SetStatus -> {
|
||||||
pickerState = UserStatusPickerState.Hidden
|
pickerState = UserStatusPickerState.Hidden
|
||||||
coroutineScope.launch { matrixClient.setUserStatus(event.status) }
|
coroutineScope.launch { matrixClient.setUserStatus(event.status) }
|
||||||
}
|
}
|
||||||
UserStatusEvent.Clear -> {
|
UserStatusEvent.ClearStatus -> {
|
||||||
pickerState = UserStatusPickerState.Hidden
|
pickerState = UserStatusPickerState.Hidden
|
||||||
coroutineScope.launch { matrixClient.clearUserStatus() }
|
coroutineScope.launch { matrixClient.clearUserStatus() }
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ sealed interface UserStatusPickerState {
|
|||||||
data object Hidden : UserStatusPickerState
|
data object Hidden : UserStatusPickerState
|
||||||
data object ShowingPicker : UserStatusPickerState
|
data object ShowingPicker : UserStatusPickerState
|
||||||
data class CustomInput(
|
data class CustomInput(
|
||||||
val emoji: String = "😀",
|
val emoji: String,
|
||||||
val textFieldState: TextFieldState,
|
val textFieldState: TextFieldState,
|
||||||
) : UserStatusPickerState
|
) : UserStatusPickerState
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -65,20 +65,20 @@ fun UserStatusRow(
|
|||||||
if (displayedStatus != null) {
|
if (displayedStatus != null) {
|
||||||
CurrentStatusRow(
|
CurrentStatusRow(
|
||||||
displayedStatus = displayedStatus,
|
displayedStatus = displayedStatus,
|
||||||
onClick = { state.eventSink(UserStatusEvent.Open) },
|
onClick = { state.eventSink(UserStatusEvent.OpenPicker) },
|
||||||
onClear = { state.eventSink(UserStatusEvent.Clear) },
|
onClear = { state.eventSink(UserStatusEvent.ClearStatus) },
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
EmptyStatusRow(
|
EmptyStatusRow(
|
||||||
onClick = { state.eventSink(UserStatusEvent.Open) },
|
onClick = { state.eventSink(UserStatusEvent.OpenPicker) },
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (pickerState == UserStatusPickerState.ShowingPicker) {
|
if (pickerState == UserStatusPickerState.ShowingPicker) {
|
||||||
UserStatusPickerBottomSheet(
|
UserStatusPickerBottomSheet(
|
||||||
onDismiss = { state.eventSink(UserStatusEvent.Dismiss) },
|
onDismiss = { state.eventSink(UserStatusEvent.DismissPicker) },
|
||||||
onSelectPredefined = { status -> state.eventSink(UserStatusEvent.Set(status)) },
|
onSelectPredefined = { status -> state.eventSink(UserStatusEvent.SetStatus(status)) },
|
||||||
onSelectCustom = { state.eventSink(UserStatusEvent.OpenCustomInput) },
|
onSelectCustom = { state.eventSink(UserStatusEvent.OpenCustomInput) },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -90,7 +90,7 @@ fun UserStatusRow(
|
|||||||
onEmojiChange = { state.eventSink(UserStatusEvent.UpdateCustomEmoji(it)) },
|
onEmojiChange = { state.eventSink(UserStatusEvent.UpdateCustomEmoji(it)) },
|
||||||
onConfirm = {
|
onConfirm = {
|
||||||
state.eventSink(
|
state.eventSink(
|
||||||
UserStatusEvent.Set(UserStatus(pickerState.emoji, pickerState.textFieldState.text.toString()))
|
UserStatusEvent.SetStatus(UserStatus(pickerState.emoji, pickerState.textFieldState.text.toString()))
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onCancel = { state.eventSink(UserStatusEvent.CancelCustomInput) },
|
onCancel = { state.eventSink(UserStatusEvent.CancelCustomInput) },
|
||||||
|
|||||||
+7
-8
@@ -16,7 +16,6 @@ import io.element.android.libraries.matrix.api.user.UserStatus
|
|||||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import androidx.compose.foundation.text.input.TextFieldState
|
|
||||||
|
|
||||||
class UserStatusPresenterTest {
|
class UserStatusPresenterTest {
|
||||||
|
|
||||||
@@ -40,7 +39,7 @@ class UserStatusPresenterTest {
|
|||||||
createPresenter().present()
|
createPresenter().present()
|
||||||
}.test {
|
}.test {
|
||||||
val state = awaitItem()
|
val state = awaitItem()
|
||||||
state.eventSink(UserStatusEvent.Open)
|
state.eventSink(UserStatusEvent.OpenPicker)
|
||||||
assertThat(awaitItem().pickerState).isEqualTo(UserStatusPickerState.ShowingPicker)
|
assertThat(awaitItem().pickerState).isEqualTo(UserStatusPickerState.ShowingPicker)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -51,9 +50,9 @@ class UserStatusPresenterTest {
|
|||||||
createPresenter().present()
|
createPresenter().present()
|
||||||
}.test {
|
}.test {
|
||||||
val state = awaitItem()
|
val state = awaitItem()
|
||||||
state.eventSink(UserStatusEvent.Open)
|
state.eventSink(UserStatusEvent.OpenPicker)
|
||||||
awaitItem() // ShowingPicker
|
awaitItem() // ShowingPicker
|
||||||
state.eventSink(UserStatusEvent.Dismiss)
|
state.eventSink(UserStatusEvent.DismissPicker)
|
||||||
assertThat(awaitItem().pickerState).isEqualTo(UserStatusPickerState.Hidden)
|
assertThat(awaitItem().pickerState).isEqualTo(UserStatusPickerState.Hidden)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,7 +64,7 @@ class UserStatusPresenterTest {
|
|||||||
createPresenter(client).present()
|
createPresenter(client).present()
|
||||||
}.test {
|
}.test {
|
||||||
val status = UserStatus(emoji = "💬", text = "In a meeting")
|
val status = UserStatus(emoji = "💬", text = "In a meeting")
|
||||||
awaitItem().eventSink(UserStatusEvent.Set(status))
|
awaitItem().eventSink(UserStatusEvent.SetStatus(status))
|
||||||
val newState = awaitItem()
|
val newState = awaitItem()
|
||||||
assertThat(newState.pickerState).isEqualTo(UserStatusPickerState.Hidden)
|
assertThat(newState.pickerState).isEqualTo(UserStatusPickerState.Hidden)
|
||||||
assertThat(newState.displayedStatus).isEqualTo(DisplayedStatus.UserSet(status))
|
assertThat(newState.displayedStatus).isEqualTo(DisplayedStatus.UserSet(status))
|
||||||
@@ -93,7 +92,7 @@ class UserStatusPresenterTest {
|
|||||||
createPresenter(client).present()
|
createPresenter(client).present()
|
||||||
}.test {
|
}.test {
|
||||||
val status = UserStatus(emoji = "🌴", text = "Away")
|
val status = UserStatus(emoji = "🌴", text = "Away")
|
||||||
awaitItem().eventSink(UserStatusEvent.Set(status))
|
awaitItem().eventSink(UserStatusEvent.SetStatus(status))
|
||||||
// Single emission: pickerState=Hidden and displayedStatus both set in one recomposition
|
// Single emission: pickerState=Hidden and displayedStatus both set in one recomposition
|
||||||
awaitItem().eventSink(UserStatusEvent.OpenCustomInput)
|
awaitItem().eventSink(UserStatusEvent.OpenCustomInput)
|
||||||
val state = awaitItem()
|
val state = awaitItem()
|
||||||
@@ -133,9 +132,9 @@ class UserStatusPresenterTest {
|
|||||||
createPresenter(client).present()
|
createPresenter(client).present()
|
||||||
}.test {
|
}.test {
|
||||||
val status = UserStatus(emoji = "☕", text = "Be right back")
|
val status = UserStatus(emoji = "☕", text = "Be right back")
|
||||||
awaitItem().eventSink(UserStatusEvent.Set(status))
|
awaitItem().eventSink(UserStatusEvent.SetStatus(status))
|
||||||
// Single emission: pickerState=Hidden and displayedStatus both set in one recomposition
|
// Single emission: pickerState=Hidden and displayedStatus both set in one recomposition
|
||||||
awaitItem().eventSink(UserStatusEvent.Clear)
|
awaitItem().eventSink(UserStatusEvent.ClearStatus)
|
||||||
val clearedState = awaitItem()
|
val clearedState = awaitItem()
|
||||||
assertThat(clearedState.pickerState).isEqualTo(UserStatusPickerState.Hidden)
|
assertThat(clearedState.pickerState).isEqualTo(UserStatusPickerState.Hidden)
|
||||||
assertThat(clearedState.displayedStatus).isNull()
|
assertThat(clearedState.displayedStatus).isNull()
|
||||||
|
|||||||
Reference in New Issue
Block a user