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
+)