Send typing notification #2240
This commit is contained in:
parent
80270d1cc5
commit
bfb6b32740
9 changed files with 62 additions and 2 deletions
|
|
@ -43,6 +43,7 @@ sealed interface MessageComposerEvents {
|
|||
data class ToggleTextFormatting(val enabled: Boolean) : MessageComposerEvents
|
||||
data object CancelSendAttachment : MessageComposerEvents
|
||||
data class Error(val error: Throwable) : MessageComposerEvents
|
||||
data class TypingNotice(val isTyping: Boolean) : MessageComposerEvents
|
||||
data class SuggestionReceived(val suggestion: Suggestion?) : MessageComposerEvents
|
||||
data class InsertMention(val mention: MentionSuggestion) : MessageComposerEvents
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import android.Manifest
|
|||
import android.annotation.SuppressLint
|
||||
import android.net.Uri
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.getValue
|
||||
|
|
@ -207,6 +208,15 @@ class MessageComposerPresenter @Inject constructor(
|
|||
.collect()
|
||||
}
|
||||
|
||||
DisposableEffect(Unit) {
|
||||
// Declare that the user is not typing anymore when the composer is disposed
|
||||
onDispose {
|
||||
appCoroutineScope.launch {
|
||||
room.typingNotice(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun handleEvents(event: MessageComposerEvents) {
|
||||
when (event) {
|
||||
MessageComposerEvents.ToggleFullScreenState -> isFullScreen.value = !isFullScreen.value
|
||||
|
|
@ -299,6 +309,11 @@ class MessageComposerPresenter @Inject constructor(
|
|||
is MessageComposerEvents.Error -> {
|
||||
analyticsService.trackError(event.error)
|
||||
}
|
||||
is MessageComposerEvents.TypingNotice -> {
|
||||
localCoroutineScope.launch {
|
||||
room.typingNotice(event.isTyping)
|
||||
}
|
||||
}
|
||||
is MessageComposerEvents.SuggestionReceived -> {
|
||||
suggestionSearchTrigger.value = event.suggestion
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,6 +78,10 @@ internal fun MessageComposerView(
|
|||
state.eventSink(MessageComposerEvents.Error(error))
|
||||
}
|
||||
|
||||
fun onTyping(typing: Boolean) {
|
||||
state.eventSink(MessageComposerEvents.TypingNotice(typing))
|
||||
}
|
||||
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
fun onRequestFocus() {
|
||||
coroutineScope.launch {
|
||||
|
|
@ -121,6 +125,7 @@ internal fun MessageComposerView(
|
|||
onDeleteVoiceMessage = onDeleteVoiceMessage,
|
||||
onSuggestionReceived = ::onSuggestionReceived,
|
||||
onError = ::onError,
|
||||
onTyping = ::onTyping,
|
||||
currentUserId = state.currentUserId,
|
||||
onRichContentSelected = ::sendUri,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -873,6 +873,21 @@ class MessageComposerPresenterTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - handle typing notice event`() = runTest {
|
||||
val room = FakeMatrixRoom()
|
||||
val presenter = createPresenter(room = room, coroutineScope = this)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitFirstItem()
|
||||
assertThat(room.typingRecord).isEmpty()
|
||||
initialState.eventSink.invoke(MessageComposerEvents.TypingNotice(true))
|
||||
initialState.eventSink.invoke(MessageComposerEvents.TypingNotice(false))
|
||||
assertThat(room.typingRecord).isEqualTo(listOf(true, false))
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun ReceiveTurbine<MessageComposerState>.backToNormalMode(state: MessageComposerState, skipCount: Int = 0): MessageComposerState {
|
||||
state.eventSink.invoke(MessageComposerEvents.CloseSpecialMode)
|
||||
skipItems(skipCount)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue