From 21bd8a308ba2c02d066bbe445a65dc9f8a74aff4 Mon Sep 17 00:00:00 2001 From: Nicholas Date: Mon, 28 Nov 2022 11:56:59 -0500 Subject: [PATCH] Add jump to message shortcut for media viewer. --- .../mediapreview/MediaPreviewRepository.kt | 16 ++++++++++ .../mediapreview/MediaPreviewV2Fragment.kt | 31 +++++++++++++++++-- .../mediapreview/MediaPreviewV2ViewModel.kt | 6 ++++ app/src/main/res/values/strings.xml | 1 + 4 files changed, 52 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediapreview/MediaPreviewRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/mediapreview/MediaPreviewRepository.kt index 1dbf25c06..0951a564d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediapreview/MediaPreviewRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/mediapreview/MediaPreviewRepository.kt @@ -1,6 +1,8 @@ package org.thoughtcrime.securesms.mediapreview import android.content.Context +import android.content.Intent +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.core.Completable import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.core.Single @@ -9,9 +11,11 @@ import org.signal.core.util.logging.Log import org.signal.core.util.requireLong import org.thoughtcrime.securesms.attachments.AttachmentId import org.thoughtcrime.securesms.attachments.DatabaseAttachment +import org.thoughtcrime.securesms.conversation.ConversationIntents import org.thoughtcrime.securesms.database.AttachmentDatabase import org.thoughtcrime.securesms.database.MediaDatabase import org.thoughtcrime.securesms.database.MediaDatabase.Sorting +import org.thoughtcrime.securesms.database.SignalDatabase import org.thoughtcrime.securesms.database.SignalDatabase.Companion.media import org.thoughtcrime.securesms.sms.MessageSender import org.thoughtcrime.securesms.util.AttachmentUtil @@ -81,5 +85,17 @@ class MediaPreviewRepository { }.subscribeOn(Schedulers.io()) } + fun getMessagePositionIntent(context: Context, messageId: Long): Single { + return Single.fromCallable { + val messageRecord = SignalDatabase.mms.getMessageRecord(messageId) + val messagePosition = SignalDatabase.mmsSms.getMessagePositionInConversation(messageRecord.threadId, messageRecord.dateReceived) + ConversationIntents.createBuilder(context, messageRecord.recipient.id, messageRecord.threadId) + .withStartingPosition(messagePosition) + .build() + } + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + } + data class Result(val initialPosition: Int, val records: List) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediapreview/MediaPreviewV2Fragment.kt b/app/src/main/java/org/thoughtcrime/securesms/mediapreview/MediaPreviewV2Fragment.kt index d72ef162b..777f107c9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediapreview/MediaPreviewV2Fragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/mediapreview/MediaPreviewV2Fragment.kt @@ -6,8 +6,11 @@ import android.content.ActivityNotFoundException import android.content.Context import android.content.DialogInterface import android.content.Intent +import android.graphics.PorterDuff +import android.graphics.PorterDuffColorFilter import android.os.Build import android.os.Bundle +import android.text.SpannableStringBuilder import android.view.LayoutInflater import android.view.Menu import android.view.View @@ -19,6 +22,7 @@ import android.view.animation.PathInterpolator import android.widget.Toast import androidx.appcompat.view.menu.MenuBuilder import androidx.core.app.ShareCompat +import androidx.core.content.ContextCompat import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import androidx.core.view.isVisible @@ -54,6 +58,7 @@ import org.thoughtcrime.securesms.mms.GlideApp import org.thoughtcrime.securesms.mms.PartAuthority import org.thoughtcrime.securesms.permissions.Permissions import org.thoughtcrime.securesms.recipients.Recipient +import org.thoughtcrime.securesms.util.ContextUtil import org.thoughtcrime.securesms.util.DateUtils import org.thoughtcrime.securesms.util.Debouncer import org.thoughtcrime.securesms.util.FullscreenHelper @@ -61,6 +66,7 @@ import org.thoughtcrime.securesms.util.LifecycleDisposable import org.thoughtcrime.securesms.util.MediaUtil import org.thoughtcrime.securesms.util.RemoteDeleteUtil import org.thoughtcrime.securesms.util.SaveAttachmentTask +import org.thoughtcrime.securesms.util.SpanUtil import org.thoughtcrime.securesms.util.StorageUtil import org.thoughtcrime.securesms.util.ViewUtil import org.thoughtcrime.securesms.util.visible @@ -232,6 +238,18 @@ class MediaPreviewV2Fragment : Fragment(R.layout.fragment_media_preview_v2), Med private fun bindTextViews(currentItem: MediaDatabase.MediaRecord, showThread: Boolean) { binding.toolbar.title = getTitleText(currentItem, showThread) binding.toolbar.subtitle = getSubTitleText(currentItem) + val messageId: Long? = currentItem.attachment?.mmsId + if (messageId != null) { + binding.toolbar.setOnClickListener { v -> + viewModel.jumpToFragment(v.context, messageId).subscribeBy( + onSuccess = { startActivity(it) }, + onError = { + Log.e(TAG, "Could not find message position for message ID: $messageId", it) + Toast.makeText(v.context, R.string.MediaPreviewActivity_error_finding_message, Toast.LENGTH_LONG).show() + } + ) + } + } val caption = currentItem.attachment?.caption binding.mediaPreviewCaption.text = caption @@ -366,12 +384,21 @@ class MediaPreviewV2Fragment : Fragment(R.layout.fragment_media_preview_v2), Med } } - private fun getSubTitleText(mediaRecord: MediaDatabase.MediaRecord): String = - if (mediaRecord.date > 0) { + private fun getSubTitleText(mediaRecord: MediaDatabase.MediaRecord): CharSequence { + val text = if (mediaRecord.date > 0) { DateUtils.getExtendedRelativeTimeSpanString(requireContext(), Locale.getDefault(), mediaRecord.date) } else { getString(R.string.MediaPreviewActivity_draft) } + val builder = SpannableStringBuilder(text) + + val onSurfaceColor = ContextCompat.getColor(requireContext(), R.color.signal_colorOnSurface) + val chevron = ContextUtil.requireDrawable(requireContext(), R.drawable.ic_chevron_end_24) + chevron.colorFilter = PorterDuffColorFilter(onSurfaceColor, PorterDuff.Mode.SRC_IN) + + SpanUtil.appendCenteredImageSpan(builder, chevron, 10, 10) + return builder + } private fun anchorMarginsToBottomInsets(viewToAnchor: View) { ViewCompat.setOnApplyWindowInsetsListener(viewToAnchor) { view: View, windowInsetsCompat: WindowInsetsCompat -> diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediapreview/MediaPreviewV2ViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/mediapreview/MediaPreviewV2ViewModel.kt index 8cfd61fef..44dba41de 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediapreview/MediaPreviewV2ViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/mediapreview/MediaPreviewV2ViewModel.kt @@ -1,10 +1,12 @@ package org.thoughtcrime.securesms.mediapreview import android.content.Context +import android.content.Intent import androidx.lifecycle.ViewModel import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.core.Completable import io.reactivex.rxjava3.core.Flowable +import io.reactivex.rxjava3.core.Single import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.kotlin.plusAssign import io.reactivex.rxjava3.schedulers.Schedulers @@ -82,6 +84,10 @@ class MediaPreviewV2ViewModel : ViewModel() { return repository.localDelete(context, attachment).subscribeOn(Schedulers.io()) } + fun jumpToFragment(context: Context, messageId: Long): Single { + return repository.getMessagePositionIntent(context, messageId) + } + override fun onCleared() { disposables.dispose() store.dispose() diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8b667b677..d3644a475 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2076,6 +2076,7 @@ %1$s to you Media no longer available. + Error finding message. Can\'t find an app able to share this media. Close Media Error