From d83532b6af85c28523bcd8592b667d35b8c8fbee Mon Sep 17 00:00:00 2001 From: andrew Date: Tue, 11 Jul 2023 13:28:44 +0930 Subject: [PATCH] Use Channel and Flow to avoid duplicate events --- .../conversation/v2/MessageDetailActivity.kt | 25 +++++++------ .../v2/MessageDetailsViewModel.kt | 36 +++++++++++++------ 2 files changed, 40 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/MessageDetailActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/MessageDetailActivity.kt index 8f23101953..0ce83f9afa 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/MessageDetailActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/MessageDetailActivity.kt @@ -32,8 +32,8 @@ import androidx.compose.material.LocalTextStyle import androidx.compose.material.Surface import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -48,13 +48,14 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView -import androidx.core.content.ContextCompat +import androidx.lifecycle.lifecycleScope import com.bumptech.glide.integration.compose.ExperimentalGlideComposeApi import com.bumptech.glide.integration.compose.GlideImage import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.launch import network.loki.messenger.R import network.loki.messenger.databinding.ViewVisibleMessageContentBinding -import org.thoughtcrime.securesms.MediaPreviewActivity +import org.thoughtcrime.securesms.MediaPreviewActivity.getPreviewIntent import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity import org.thoughtcrime.securesms.database.Storage import org.thoughtcrime.securesms.ui.AppTheme @@ -102,23 +103,25 @@ class MessageDetailActivity : PassphraseRequiredActionBarActivity() { intent.getLongExtra(MESSAGE_TIMESTAMP, -1L).let(viewModel::setMessageTimestamp) - if (viewModel.state.value == null) { - finish() - return - } - ComposeView(this) .apply { setContent { MessageDetailsScreen() } } .let(::setContentView) - viewModel.event.observe(this) { - startActivity(MediaPreviewActivity.getPreviewIntent(this, it)) + lifecycleScope.launch { + viewModel.eventFlow.collect { + when (it) { + Event.Finish -> finish() + is Event.StartMediaPreview -> startActivity( + getPreviewIntent(this@MessageDetailActivity, it.args) + ) + } + } } } @Composable private fun MessageDetailsScreen() { - val state by viewModel.state.observeAsState(MessageDetailsState()) + val state by viewModel.stateFlow.collectAsState() AppTheme { MessageDetails( state = state, diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/MessageDetailsViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/MessageDetailsViewModel.kt index ad4bf24d43..7f97645b69 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/MessageDetailsViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/MessageDetailsViewModel.kt @@ -1,12 +1,14 @@ package org.thoughtcrime.securesms.conversation.v2 import android.net.Uri -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.launch import network.loki.messenger.R import org.session.libsession.messaging.jobs.AttachmentDownloadJob @@ -38,17 +40,23 @@ class MessageDetailsViewModel @Inject constructor( private val threadDb: ThreadDatabase, ) : ViewModel() { - private var _state = MutableLiveData(MessageDetailsState()) - val state: LiveData = _state + private val state = MutableStateFlow(MessageDetailsState()) + val stateFlow = state.asStateFlow() - private var _event = MutableLiveData() - val event: LiveData = _event + private val event = Channel() + val eventFlow = event.receiveAsFlow() fun setMessageTimestamp(timestamp: Long) { - val record = mmsSmsDatabase.getMessageForTimestamp(timestamp) ?: return + val record = mmsSmsDatabase.getMessageForTimestamp(timestamp) + + if (record == null) { + viewModelScope.launch { event.send(Event.Finish) } + return + } + val mmsRecord = record as? MmsMessageRecord - _state.value = record.run { + state.value = record.run { val slides = mmsRecord?.slideDeck?.slides ?: emptyList() MessageDetailsState( @@ -106,10 +114,13 @@ class MessageDetailsViewModel @Inject constructor( if (slide.isInProgress) return - _event.value = MediaPreviewArgs(slide, state.mmsRecord, state.thread) + viewModelScope.launch { + MediaPreviewArgs(slide, state.mmsRecord, state.thread) + .let(Event::StartMediaPreview) + .let { event.send(it) } + } } - fun onAttachmentNeedsDownload(attachmentId: Long, mmsId: Long) { viewModelScope.launch(Dispatchers.IO) { JobQueue.shared.add(AttachmentDownloadJob(attachmentId, mmsId)) @@ -139,3 +150,8 @@ data class Attachment( val uri: Uri?, val hasImage: Boolean ) + +sealed class Event { + object Finish: Event() + data class StartMediaPreview(val args: MediaPreviewArgs): Event() +} \ No newline at end of file