Use Channel and Flow to avoid duplicate events

This commit is contained in:
andrew 2023-07-11 13:28:44 +09:30
parent 1845b60dac
commit d83532b6af
2 changed files with 40 additions and 21 deletions

View File

@ -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,

View File

@ -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<MessageDetailsState> = _state
private val state = MutableStateFlow(MessageDetailsState())
val stateFlow = state.asStateFlow()
private var _event = MutableLiveData<MediaPreviewArgs>()
val event: LiveData<MediaPreviewArgs> = _event
private val event = Channel<Event>()
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()
}