Refactor slide out of MessageDetailsActivity

This commit is contained in:
andrew 2023-07-11 12:28:04 +09:30
parent 172f85ae4f
commit 1845b60dac
4 changed files with 74 additions and 49 deletions

View File

@ -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) {

View File

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

View File

@ -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")

View File

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