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.Surface
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color 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.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView 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.ExperimentalGlideComposeApi
import com.bumptech.glide.integration.compose.GlideImage import com.bumptech.glide.integration.compose.GlideImage
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import network.loki.messenger.R import network.loki.messenger.R
import network.loki.messenger.databinding.ViewVisibleMessageContentBinding 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.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.database.Storage import org.thoughtcrime.securesms.database.Storage
import org.thoughtcrime.securesms.ui.AppTheme import org.thoughtcrime.securesms.ui.AppTheme
@ -102,23 +103,25 @@ class MessageDetailActivity : PassphraseRequiredActionBarActivity() {
intent.getLongExtra(MESSAGE_TIMESTAMP, -1L).let(viewModel::setMessageTimestamp) intent.getLongExtra(MESSAGE_TIMESTAMP, -1L).let(viewModel::setMessageTimestamp)
if (viewModel.state.value == null) {
finish()
return
}
ComposeView(this) ComposeView(this)
.apply { setContent { MessageDetailsScreen() } } .apply { setContent { MessageDetailsScreen() } }
.let(::setContentView) .let(::setContentView)
viewModel.event.observe(this) { lifecycleScope.launch {
startActivity(MediaPreviewActivity.getPreviewIntent(this, it)) viewModel.eventFlow.collect {
when (it) {
Event.Finish -> finish()
is Event.StartMediaPreview -> startActivity(
getPreviewIntent(this@MessageDetailActivity, it.args)
)
}
}
} }
} }
@Composable @Composable
private fun MessageDetailsScreen() { private fun MessageDetailsScreen() {
val state by viewModel.state.observeAsState(MessageDetailsState()) val state by viewModel.stateFlow.collectAsState()
AppTheme { AppTheme {
MessageDetails( MessageDetails(
state = state, state = state,

View File

@ -1,12 +1,14 @@
package org.thoughtcrime.securesms.conversation.v2 package org.thoughtcrime.securesms.conversation.v2
import android.net.Uri import android.net.Uri
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers 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 kotlinx.coroutines.launch
import network.loki.messenger.R import network.loki.messenger.R
import org.session.libsession.messaging.jobs.AttachmentDownloadJob import org.session.libsession.messaging.jobs.AttachmentDownloadJob
@ -38,17 +40,23 @@ class MessageDetailsViewModel @Inject constructor(
private val threadDb: ThreadDatabase, private val threadDb: ThreadDatabase,
) : ViewModel() { ) : ViewModel() {
private var _state = MutableLiveData(MessageDetailsState()) private val state = MutableStateFlow(MessageDetailsState())
val state: LiveData<MessageDetailsState> = _state val stateFlow = state.asStateFlow()
private var _event = MutableLiveData<MediaPreviewArgs>() private val event = Channel<Event>()
val event: LiveData<MediaPreviewArgs> = _event val eventFlow = event.receiveAsFlow()
fun setMessageTimestamp(timestamp: Long) { 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 val mmsRecord = record as? MmsMessageRecord
_state.value = record.run { state.value = record.run {
val slides = mmsRecord?.slideDeck?.slides ?: emptyList() val slides = mmsRecord?.slideDeck?.slides ?: emptyList()
MessageDetailsState( MessageDetailsState(
@ -106,10 +114,13 @@ class MessageDetailsViewModel @Inject constructor(
if (slide.isInProgress) return 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) { fun onAttachmentNeedsDownload(attachmentId: Long, mmsId: Long) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
JobQueue.shared.add(AttachmentDownloadJob(attachmentId, mmsId)) JobQueue.shared.add(AttachmentDownloadJob(attachmentId, mmsId))
@ -139,3 +150,8 @@ data class Attachment(
val uri: Uri?, val uri: Uri?,
val hasImage: Boolean val hasImage: Boolean
) )
sealed class Event {
object Finish: Event()
data class StartMediaPreview(val args: MediaPreviewArgs): Event()
}