From 1845b60dace0f389bdfef5704ce06672847eb9a5 Mon Sep 17 00:00:00 2001 From: andrew <andrewgallasch@gmail.com> Date: Tue, 11 Jul 2023 12:28:04 +0930 Subject: [PATCH] Refactor slide out of MessageDetailsActivity --- .../securesms/MediaPreviewActivity.java | 4 ++ .../securesms/MediaPreviewArgs.kt | 11 ++++ .../conversation/v2/MessageDetailActivity.kt | 42 +++--------- .../v2/MessageDetailsViewModel.kt | 66 ++++++++++++++----- 4 files changed, 74 insertions(+), 49 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/MediaPreviewArgs.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java b/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java index a1648e0763..e9ee120e26 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java @@ -146,6 +146,10 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im } }; + public static Intent getPreviewIntent(Context context, MediaPreviewArgs args) { + return getPreviewIntent(context, args.getSlide(), args.getMmsRecord(), args.getThread()); + } + public static Intent getPreviewIntent(Context context, Slide slide, MmsMessageRecord mms, Recipient threadRecipient) { Intent previewIntent = null; if (MediaPreviewActivity.isContentTypeSupported(slide.getContentType()) && slide.getUri() != null) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewArgs.kt b/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewArgs.kt new file mode 100644 index 0000000000..00e2c3d6d8 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewArgs.kt @@ -0,0 +1,11 @@ +package org.thoughtcrime.securesms + +import org.session.libsession.utilities.recipients.Recipient +import org.thoughtcrime.securesms.database.model.MmsMessageRecord +import org.thoughtcrime.securesms.mms.Slide + +data class MediaPreviewArgs( + val slide: Slide, + val mmsRecord: MmsMessageRecord?, + val thread: Recipient?, +) 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 5397c30736..8f23101953 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 @@ -38,7 +38,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.layout.layout import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -49,18 +48,12 @@ 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.lifecycle.lifecycleScope +import androidx.core.content.ContextCompat import com.bumptech.glide.integration.compose.ExperimentalGlideComposeApi import com.bumptech.glide.integration.compose.GlideImage import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch import network.loki.messenger.R import network.loki.messenger.databinding.ViewVisibleMessageContentBinding -import org.session.libsession.messaging.jobs.AttachmentDownloadJob -import org.session.libsession.messaging.jobs.JobQueue -import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress -import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment import org.thoughtcrime.securesms.MediaPreviewActivity import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity import org.thoughtcrime.securesms.database.Storage @@ -109,7 +102,7 @@ class MessageDetailActivity : PassphraseRequiredActionBarActivity() { intent.getLongExtra(MESSAGE_TIMESTAMP, -1L).let(viewModel::setMessageTimestamp) - if (viewModel.details.value == null) { + if (viewModel.state.value == null) { finish() return } @@ -117,34 +110,23 @@ class MessageDetailActivity : PassphraseRequiredActionBarActivity() { ComposeView(this) .apply { setContent { MessageDetailsScreen() } } .let(::setContentView) + + viewModel.event.observe(this) { + startActivity(MediaPreviewActivity.getPreviewIntent(this, it)) + } } @Composable private fun MessageDetailsScreen() { - val state by viewModel.details.observeAsState(MessageDetailsState()) + val state by viewModel.state.observeAsState(MessageDetailsState()) AppTheme { MessageDetails( state = state, onReply = { setResultAndFinish(ON_REPLY) }, onResend = state.error?.let { { setResultAndFinish(ON_RESEND) } }, onDelete = { setResultAndFinish(ON_DELETE) }, - onClickImage = { i -> - val slide = state.attachments[i].slide - // only open to downloaded images - if (slide.transferState == AttachmentTransferProgress.TRANSFER_PROGRESS_FAILED) { - // Restart download here (on IO thread) - (slide.asAttachment() as? DatabaseAttachment)?.let { attachment -> - onAttachmentNeedsDownload(attachment.attachmentId.rowId, state.mmsRecord!!.getId()) - } - } - if (!slide.isInProgress) MediaPreviewActivity.getPreviewIntent( - this, - slide, - state.mmsRecord, - state.thread, - ).let(::startActivity) - }, - onAttachmentNeedsDownload = ::onAttachmentNeedsDownload, + onClickImage = { viewModel.onClickImage(it) }, + onAttachmentNeedsDownload = viewModel::onAttachmentNeedsDownload, ) } } @@ -156,12 +138,6 @@ class MessageDetailActivity : PassphraseRequiredActionBarActivity() { finish() } - - private fun onAttachmentNeedsDownload(attachmentId: Long, mmsId: Long) { - lifecycleScope.launch(Dispatchers.IO) { - JobQueue.shared.add(AttachmentDownloadJob(attachmentId, mmsId)) - } - } } @SuppressLint("ClickableViewAccessibility") 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 890c82c0a9..ad4bf24d43 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,13 +1,21 @@ 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.launch import network.loki.messenger.R +import org.session.libsession.messaging.jobs.AttachmentDownloadJob +import org.session.libsession.messaging.jobs.JobQueue +import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment import org.session.libsession.utilities.Util import org.session.libsession.utilities.recipients.Recipient +import org.thoughtcrime.securesms.MediaPreviewArgs import org.thoughtcrime.securesms.database.AttachmentDatabase import org.thoughtcrime.securesms.database.LokiMessageDatabase import org.thoughtcrime.securesms.database.MmsSmsDatabase @@ -30,15 +38,21 @@ class MessageDetailsViewModel @Inject constructor( private val threadDb: ThreadDatabase, ) : ViewModel() { + private var _state = MutableLiveData(MessageDetailsState()) + val state: LiveData<MessageDetailsState> = _state + + private var _event = MutableLiveData<MediaPreviewArgs>() + val event: LiveData<MediaPreviewArgs> = _event + fun setMessageTimestamp(timestamp: Long) { val record = mmsSmsDatabase.getMessageForTimestamp(timestamp) ?: return val mmsRecord = record as? MmsMessageRecord - _details.value = record.run { - val slides = mmsRecord?.slideDeck?.thumbnailSlides?.toList() ?: emptyList() + _state.value = record.run { + val slides = mmsRecord?.slideDeck?.slides ?: emptyList() MessageDetailsState( - attachments = slides.map { Attachment(it, it.details) }, + attachments = slides.map(::Attachment), record = record, sent = dateSent.let(::Date).toString().let { TitledText(R.string.message_details_header__sent, it) }, received = dateReceived.let(::Date).toString().let { TitledText(R.string.message_details_header__received, it) }, @@ -50,9 +64,6 @@ class MessageDetailsViewModel @Inject constructor( } } - private var _details = MutableLiveData(MessageDetailsState()) - val details: LiveData<MessageDetailsState> = _details - private val Slide.details: List<TitledText> get() = listOfNotNull( fileName.orNull()?.let { TitledText(R.string.message_details_header__file_id, it) }, @@ -78,12 +89,38 @@ class MessageDetailsViewModel @Inject constructor( ) } + fun Attachment(slide: Slide): Attachment = + Attachment(slide.details, slide.fileName.orNull(), slide.uri, slide is ImageSlide) + + fun onClickImage(index: Int) { + val state = state.value ?: return + val mmsRecord = state.mmsRecord ?: return + val slide = mmsRecord.slideDeck.slides[index] ?: return + // only open to downloaded images + if (slide.transferState == AttachmentTransferProgress.TRANSFER_PROGRESS_FAILED) { + // Restart download here (on IO thread) + (slide.asAttachment() as? DatabaseAttachment)?.let { attachment -> + onAttachmentNeedsDownload(attachment.attachmentId.rowId, state.mmsRecord.getId()) + } + } + + if (slide.isInProgress) return + + _event.value = MediaPreviewArgs(slide, state.mmsRecord, state.thread) + } + + + fun onAttachmentNeedsDownload(attachmentId: Long, mmsId: Long) { + viewModelScope.launch(Dispatchers.IO) { + JobQueue.shared.add(AttachmentDownloadJob(attachmentId, mmsId)) + } + } } data class MessageDetailsState( val attachments: List<Attachment> = emptyList(), - val imageAttachments: List<Attachment> = attachments.filter { it.hasImage() }, - val nonImageAttachmentFileDetails: List<TitledText>? = attachments.firstOrNull { !it.hasImage() }?.fileDetails, + val imageAttachments: List<Attachment> = attachments.filter { it.hasImage }, + val nonImageAttachmentFileDetails: List<TitledText>? = attachments.firstOrNull { !it.hasImage }?.fileDetails, val record: MessageRecord? = null, val mmsRecord: MmsMessageRecord? = record as? MmsMessageRecord, val sent: TitledText? = null, @@ -97,11 +134,8 @@ data class MessageDetailsState( } data class Attachment( - val slide: Slide, - val fileDetails: List<TitledText> -) { - val fileName: String? get() = slide.fileName.orNull() - val uri get() = slide.uri - - fun hasImage() = slide is ImageSlide -} + val fileDetails: List<TitledText>, + val fileName: String?, + val uri: Uri?, + val hasImage: Boolean +)