mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-22 20:18:36 +00:00
Add media send support to CFV2.
This commit is contained in:
committed by
Nicholas Tinsley
parent
53673be5cb
commit
09d17659b9
@@ -110,6 +110,7 @@ import org.thoughtcrime.securesms.components.mention.MentionAnnotation
|
|||||||
import org.thoughtcrime.securesms.components.menu.ActionItem
|
import org.thoughtcrime.securesms.components.menu.ActionItem
|
||||||
import org.thoughtcrime.securesms.components.menu.SignalBottomActionBar
|
import org.thoughtcrime.securesms.components.menu.SignalBottomActionBar
|
||||||
import org.thoughtcrime.securesms.components.recyclerview.SmoothScrollingLinearLayoutManager
|
import org.thoughtcrime.securesms.components.recyclerview.SmoothScrollingLinearLayoutManager
|
||||||
|
import org.thoughtcrime.securesms.components.reminder.ExpiredBuildReminder
|
||||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.DonateToSignalFragment
|
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.DonateToSignalFragment
|
||||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.DonateToSignalType
|
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.DonateToSignalType
|
||||||
import org.thoughtcrime.securesms.components.settings.conversation.ConversationSettingsActivity
|
import org.thoughtcrime.securesms.components.settings.conversation.ConversationSettingsActivity
|
||||||
@@ -199,19 +200,21 @@ import org.thoughtcrime.securesms.mediapreview.MediaIntentFactory.create
|
|||||||
import org.thoughtcrime.securesms.mediapreview.MediaPreviewV2Activity
|
import org.thoughtcrime.securesms.mediapreview.MediaPreviewV2Activity
|
||||||
import org.thoughtcrime.securesms.mediasend.Media
|
import org.thoughtcrime.securesms.mediasend.Media
|
||||||
import org.thoughtcrime.securesms.mediasend.MediaSendActivityResult
|
import org.thoughtcrime.securesms.mediasend.MediaSendActivityResult
|
||||||
import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionActivity
|
|
||||||
import org.thoughtcrime.securesms.messagedetails.MessageDetailsFragment
|
import org.thoughtcrime.securesms.messagedetails.MessageDetailsFragment
|
||||||
import org.thoughtcrime.securesms.messagerequests.MessageRequestRepository
|
import org.thoughtcrime.securesms.messagerequests.MessageRequestRepository
|
||||||
import org.thoughtcrime.securesms.messagerequests.MessageRequestState
|
import org.thoughtcrime.securesms.messagerequests.MessageRequestState
|
||||||
import org.thoughtcrime.securesms.mms.AttachmentManager
|
import org.thoughtcrime.securesms.mms.AttachmentManager
|
||||||
import org.thoughtcrime.securesms.mms.AudioSlide
|
import org.thoughtcrime.securesms.mms.AudioSlide
|
||||||
|
import org.thoughtcrime.securesms.mms.GifSlide
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp
|
import org.thoughtcrime.securesms.mms.GlideApp
|
||||||
|
import org.thoughtcrime.securesms.mms.ImageSlide
|
||||||
import org.thoughtcrime.securesms.mms.MediaConstraints
|
import org.thoughtcrime.securesms.mms.MediaConstraints
|
||||||
import org.thoughtcrime.securesms.mms.QuoteModel
|
import org.thoughtcrime.securesms.mms.QuoteModel
|
||||||
import org.thoughtcrime.securesms.mms.Slide
|
import org.thoughtcrime.securesms.mms.Slide
|
||||||
import org.thoughtcrime.securesms.mms.SlideDeck
|
import org.thoughtcrime.securesms.mms.SlideDeck
|
||||||
import org.thoughtcrime.securesms.mms.SlideFactory
|
import org.thoughtcrime.securesms.mms.SlideFactory
|
||||||
import org.thoughtcrime.securesms.mms.StickerSlide
|
import org.thoughtcrime.securesms.mms.StickerSlide
|
||||||
|
import org.thoughtcrime.securesms.mms.VideoSlide
|
||||||
import org.thoughtcrime.securesms.notifications.v2.ConversationId
|
import org.thoughtcrime.securesms.notifications.v2.ConversationId
|
||||||
import org.thoughtcrime.securesms.payments.preferences.PaymentsActivity
|
import org.thoughtcrime.securesms.payments.preferences.PaymentsActivity
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions
|
import org.thoughtcrime.securesms.permissions.Permissions
|
||||||
@@ -229,6 +232,7 @@ import org.thoughtcrime.securesms.registration.RegistrationNavigationActivity
|
|||||||
import org.thoughtcrime.securesms.revealable.ViewOnceMessageActivity
|
import org.thoughtcrime.securesms.revealable.ViewOnceMessageActivity
|
||||||
import org.thoughtcrime.securesms.revealable.ViewOnceUtil
|
import org.thoughtcrime.securesms.revealable.ViewOnceUtil
|
||||||
import org.thoughtcrime.securesms.safety.SafetyNumberBottomSheet
|
import org.thoughtcrime.securesms.safety.SafetyNumberBottomSheet
|
||||||
|
import org.thoughtcrime.securesms.sms.MessageSender
|
||||||
import org.thoughtcrime.securesms.stickers.StickerLocator
|
import org.thoughtcrime.securesms.stickers.StickerLocator
|
||||||
import org.thoughtcrime.securesms.stickers.StickerPackInstallEvent
|
import org.thoughtcrime.securesms.stickers.StickerPackInstallEvent
|
||||||
import org.thoughtcrime.securesms.stickers.StickerPackPreviewActivity
|
import org.thoughtcrime.securesms.stickers.StickerPackPreviewActivity
|
||||||
@@ -240,6 +244,7 @@ import org.thoughtcrime.securesms.util.CommunicationActions
|
|||||||
import org.thoughtcrime.securesms.util.ContextUtil
|
import org.thoughtcrime.securesms.util.ContextUtil
|
||||||
import org.thoughtcrime.securesms.util.Debouncer
|
import org.thoughtcrime.securesms.util.Debouncer
|
||||||
import org.thoughtcrime.securesms.util.DeleteDialog
|
import org.thoughtcrime.securesms.util.DeleteDialog
|
||||||
|
import org.thoughtcrime.securesms.util.Dialogs
|
||||||
import org.thoughtcrime.securesms.util.DrawableUtil
|
import org.thoughtcrime.securesms.util.DrawableUtil
|
||||||
import org.thoughtcrime.securesms.util.FeatureFlags
|
import org.thoughtcrime.securesms.util.FeatureFlags
|
||||||
import org.thoughtcrime.securesms.util.FullscreenHelper
|
import org.thoughtcrime.securesms.util.FullscreenHelper
|
||||||
@@ -1190,7 +1195,9 @@ class ConversationFragment :
|
|||||||
slideDeck: SlideDeck? = if (attachmentManager.isAttachmentPresent) attachmentManager.buildSlideDeck() else null,
|
slideDeck: SlideDeck? = if (attachmentManager.isAttachmentPresent) attachmentManager.buildSlideDeck() else null,
|
||||||
contacts: List<Contact> = emptyList(),
|
contacts: List<Contact> = emptyList(),
|
||||||
clearCompose: Boolean = true,
|
clearCompose: Boolean = true,
|
||||||
linkPreviews: List<LinkPreview> = linkPreviewViewModel.onSend()
|
linkPreviews: List<LinkPreview> = linkPreviewViewModel.onSend(),
|
||||||
|
preUploadResults: List<MessageSender.PreUploadResult> = emptyList(),
|
||||||
|
afterSendComplete: () -> Unit = {}
|
||||||
) {
|
) {
|
||||||
val metricId = viewModel.recipientSnapshot?.let { if (it.isGroup == true) SignalLocalMetrics.GroupMessageSend.start() else SignalLocalMetrics.IndividualMessageSend.start() }
|
val metricId = viewModel.recipientSnapshot?.let { if (it.isGroup == true) SignalLocalMetrics.GroupMessageSend.start() else SignalLocalMetrics.IndividualMessageSend.start() }
|
||||||
|
|
||||||
@@ -1204,7 +1211,8 @@ class ConversationFragment :
|
|||||||
mentions = mentions,
|
mentions = mentions,
|
||||||
bodyRanges = bodyRanges,
|
bodyRanges = bodyRanges,
|
||||||
contacts = contacts,
|
contacts = contacts,
|
||||||
linkPreviews = linkPreviews
|
linkPreviews = linkPreviews,
|
||||||
|
preUploadResults = preUploadResults
|
||||||
)
|
)
|
||||||
|
|
||||||
disposables += send
|
disposables += send
|
||||||
@@ -1222,7 +1230,10 @@ class ConversationFragment :
|
|||||||
is RecipientFormattingException -> toast(R.string.ConversationActivity_recipient_is_not_a_valid_sms_or_email_address_exclamation, Toast.LENGTH_LONG)
|
is RecipientFormattingException -> toast(R.string.ConversationActivity_recipient_is_not_a_valid_sms_or_email_address_exclamation, Toast.LENGTH_LONG)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onComplete = this::onSendComplete
|
onComplete = {
|
||||||
|
onSendComplete()
|
||||||
|
afterSendComplete()
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2501,7 +2512,70 @@ class ConversationFragment :
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onMediaSend(result: MediaSendActivityResult) {
|
override fun onMediaSend(result: MediaSendActivityResult) {
|
||||||
// TODO [cfv2] media send
|
val recipientSnapshot = viewModel.recipientSnapshot
|
||||||
|
if (result.recipientId != recipientSnapshot?.id) {
|
||||||
|
Log.w(TAG, "Result's recipientId did not match ours! Result: " + result.recipientId + ", Ours: " + recipientSnapshot?.id)
|
||||||
|
toast(R.string.ConversationActivity_error_sending_media)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.isPushPreUpload) {
|
||||||
|
sendPreUploadMediaMessage(result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val slides: List<Slide> = result.nonUploadedMedia.mapNotNull {
|
||||||
|
when {
|
||||||
|
MediaUtil.isVideoType(it.mimeType) -> VideoSlide(requireContext(), it.uri, it.size, it.isVideoGif, it.width, it.height, it.caption.orNull(), it.transformProperties.orNull())
|
||||||
|
MediaUtil.isGif(it.mimeType) -> GifSlide(requireContext(), it.uri, it.size, it.width, it.height, it.isBorderless, it.caption.orNull())
|
||||||
|
MediaUtil.isImageType(it.mimeType) -> ImageSlide(requireContext(), it.uri, it.mimeType, it.size, it.width, it.height, it.isBorderless, it.caption.orNull(), null, it.transformProperties.orNull())
|
||||||
|
else -> {
|
||||||
|
Log.w(TAG, "Asked to send an unexpected mimeType: '${it.mimeType}'. Skipping.")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sendMessage(
|
||||||
|
body = result.body,
|
||||||
|
mentions = result.mentions,
|
||||||
|
bodyRanges = result.bodyRanges,
|
||||||
|
messageToEdit = null,
|
||||||
|
quote = if (result.isViewOnce) null else inputPanel.quote.orNull(),
|
||||||
|
scheduledDate = result.scheduledTime,
|
||||||
|
slideDeck = SlideDeck().apply { slides.forEach { addSlide(it) } },
|
||||||
|
contacts = emptyList(),
|
||||||
|
clearCompose = true,
|
||||||
|
linkPreviews = emptyList()
|
||||||
|
) {
|
||||||
|
viewModel.deleteSlideData(slides)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendPreUploadMediaMessage(result: MediaSendActivityResult) {
|
||||||
|
if (ExpiredBuildReminder.isEligible()) {
|
||||||
|
/* TODO [cfv2] -- Show expired dialog */
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SignalStore.uiHints().hasNotSeenTextFormattingAlert() && result.bodyRanges != null && result.bodyRanges.rangesCount > 0) {
|
||||||
|
Dialogs.showFormattedTextDialog(requireContext()) { sendPreUploadMediaMessage(result) }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sendMessage(
|
||||||
|
body = result.body,
|
||||||
|
mentions = result.mentions,
|
||||||
|
bodyRanges = result.bodyRanges,
|
||||||
|
messageToEdit = null,
|
||||||
|
quote = if (result.isViewOnce) null else inputPanel.quote.orNull(),
|
||||||
|
scheduledDate = result.scheduledTime,
|
||||||
|
slideDeck = null,
|
||||||
|
contacts = emptyList(),
|
||||||
|
clearCompose = true,
|
||||||
|
linkPreviews = emptyList(),
|
||||||
|
preUploadResults = result.preUploadResults
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2951,7 +3025,7 @@ class ConversationFragment :
|
|||||||
AttachmentKeyboardButton.PAYMENT -> AttachmentManager.selectPayment(this@ConversationFragment, viewModel.recipientSnapshot!!)
|
AttachmentKeyboardButton.PAYMENT -> AttachmentManager.selectPayment(this@ConversationFragment, viewModel.recipientSnapshot!!)
|
||||||
}
|
}
|
||||||
} else if (media != null) {
|
} else if (media != null) {
|
||||||
startActivityForResult(MediaSelectionActivity.editor(requireActivity(), sendButton.selectedSendType, listOf(media), viewModel.recipientSnapshot!!.id, composeText.textTrimmed), 12)
|
conversationActivityResultContracts.launchMediaEditor(listOf(media), viewModel.recipientSnapshot!!.id, composeText.textTrimmed)
|
||||||
}
|
}
|
||||||
|
|
||||||
container.hideInput()
|
container.hideInput()
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ import org.thoughtcrime.securesms.mms.GlideRequests
|
|||||||
import org.thoughtcrime.securesms.mms.OutgoingMessage
|
import org.thoughtcrime.securesms.mms.OutgoingMessage
|
||||||
import org.thoughtcrime.securesms.mms.PartAuthority
|
import org.thoughtcrime.securesms.mms.PartAuthority
|
||||||
import org.thoughtcrime.securesms.mms.QuoteModel
|
import org.thoughtcrime.securesms.mms.QuoteModel
|
||||||
|
import org.thoughtcrime.securesms.mms.Slide
|
||||||
import org.thoughtcrime.securesms.mms.SlideDeck
|
import org.thoughtcrime.securesms.mms.SlideDeck
|
||||||
import org.thoughtcrime.securesms.profiles.spoofing.ReviewUtil
|
import org.thoughtcrime.securesms.profiles.spoofing.ReviewUtil
|
||||||
import org.thoughtcrime.securesms.providers.BlobProvider
|
import org.thoughtcrime.securesms.providers.BlobProvider
|
||||||
@@ -87,6 +88,7 @@ import org.thoughtcrime.securesms.recipients.RecipientFormattingException
|
|||||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||||
import org.thoughtcrime.securesms.search.MessageResult
|
import org.thoughtcrime.securesms.search.MessageResult
|
||||||
import org.thoughtcrime.securesms.sms.MessageSender
|
import org.thoughtcrime.securesms.sms.MessageSender
|
||||||
|
import org.thoughtcrime.securesms.sms.MessageSender.PreUploadResult
|
||||||
import org.thoughtcrime.securesms.util.BitmapUtil
|
import org.thoughtcrime.securesms.util.BitmapUtil
|
||||||
import org.thoughtcrime.securesms.util.DrawableUtil
|
import org.thoughtcrime.securesms.util.DrawableUtil
|
||||||
import org.thoughtcrime.securesms.util.MediaUtil
|
import org.thoughtcrime.securesms.util.MediaUtil
|
||||||
@@ -196,10 +198,11 @@ class ConversationRepository(
|
|||||||
mentions: List<Mention>,
|
mentions: List<Mention>,
|
||||||
bodyRanges: BodyRangeList?,
|
bodyRanges: BodyRangeList?,
|
||||||
contacts: List<Contact>,
|
contacts: List<Contact>,
|
||||||
linkPreviews: List<LinkPreview>
|
linkPreviews: List<LinkPreview>,
|
||||||
|
preUploadResults: List<PreUploadResult>
|
||||||
): Completable {
|
): Completable {
|
||||||
val sendCompletable = Completable.create { emitter ->
|
val sendCompletable = Completable.create { emitter ->
|
||||||
if (body.isEmpty() && slideDeck?.containsMediaSlide() != true) {
|
if (body.isEmpty() && slideDeck?.containsMediaSlide() != true && preUploadResults.isEmpty()) {
|
||||||
emitter.onError(InvalidMessageException("Message is empty!"))
|
emitter.onError(InvalidMessageException("Message is empty!"))
|
||||||
return@create
|
return@create
|
||||||
}
|
}
|
||||||
@@ -225,14 +228,25 @@ class ConversationRepository(
|
|||||||
linkPreviews = linkPreviews
|
linkPreviews = linkPreviews
|
||||||
)
|
)
|
||||||
|
|
||||||
MessageSender.send(
|
if (preUploadResults.isEmpty()) {
|
||||||
ApplicationDependencies.getApplication(),
|
MessageSender.send(
|
||||||
message,
|
ApplicationDependencies.getApplication(),
|
||||||
threadId,
|
message,
|
||||||
MessageSender.SendType.SIGNAL,
|
threadId,
|
||||||
metricId
|
MessageSender.SendType.SIGNAL,
|
||||||
) {
|
metricId
|
||||||
emitter.onComplete()
|
) {
|
||||||
|
emitter.onComplete()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
MessageSender.sendPushWithPreUploadedMedia(
|
||||||
|
ApplicationDependencies.getApplication(),
|
||||||
|
message,
|
||||||
|
preUploadResults,
|
||||||
|
threadId
|
||||||
|
) {
|
||||||
|
emitter.onComplete()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -526,6 +540,17 @@ class ConversationRepository(
|
|||||||
return oldConversationRepository.resolveMessageToEdit(conversationMessage)
|
return oldConversationRepository.resolveMessageToEdit(conversationMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun deleteSlideData(slides: List<Slide>) {
|
||||||
|
SignalExecutors.BOUNDED_IO.execute {
|
||||||
|
slides
|
||||||
|
.mapNotNull(Slide::getUri)
|
||||||
|
.filter(BlobProvider::isAuthority)
|
||||||
|
.forEach {
|
||||||
|
BlobProvider.getInstance().delete(applicationContext, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Glide target for a contact photo which expects an error drawable, and publishes
|
* Glide target for a contact photo which expects an error drawable, and publishes
|
||||||
* the result to the given emitter.
|
* the result to the given emitter.
|
||||||
|
|||||||
@@ -51,10 +51,12 @@ import org.thoughtcrime.securesms.messagerequests.MessageRequestRepository
|
|||||||
import org.thoughtcrime.securesms.messagerequests.MessageRequestState
|
import org.thoughtcrime.securesms.messagerequests.MessageRequestState
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||||
import org.thoughtcrime.securesms.mms.QuoteModel
|
import org.thoughtcrime.securesms.mms.QuoteModel
|
||||||
|
import org.thoughtcrime.securesms.mms.Slide
|
||||||
import org.thoughtcrime.securesms.mms.SlideDeck
|
import org.thoughtcrime.securesms.mms.SlideDeck
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient
|
import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||||
import org.thoughtcrime.securesms.search.MessageResult
|
import org.thoughtcrime.securesms.search.MessageResult
|
||||||
|
import org.thoughtcrime.securesms.sms.MessageSender
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
import org.thoughtcrime.securesms.util.hasGiftBadge
|
import org.thoughtcrime.securesms.util.hasGiftBadge
|
||||||
import org.thoughtcrime.securesms.util.rx.RxStore
|
import org.thoughtcrime.securesms.util.rx.RxStore
|
||||||
@@ -299,7 +301,8 @@ class ConversationViewModel(
|
|||||||
mentions: List<Mention>,
|
mentions: List<Mention>,
|
||||||
bodyRanges: BodyRangeList?,
|
bodyRanges: BodyRangeList?,
|
||||||
contacts: List<Contact>,
|
contacts: List<Contact>,
|
||||||
linkPreviews: List<LinkPreview>
|
linkPreviews: List<LinkPreview>,
|
||||||
|
preUploadResults: List<MessageSender.PreUploadResult>
|
||||||
): Completable {
|
): Completable {
|
||||||
return repository.sendMessage(
|
return repository.sendMessage(
|
||||||
threadId = threadId,
|
threadId = threadId,
|
||||||
@@ -313,7 +316,8 @@ class ConversationViewModel(
|
|||||||
mentions = mentions,
|
mentions = mentions,
|
||||||
bodyRanges = bodyRanges,
|
bodyRanges = bodyRanges,
|
||||||
contacts = contacts,
|
contacts = contacts,
|
||||||
linkPreviews = linkPreviews
|
linkPreviews = linkPreviews,
|
||||||
|
preUploadResults = preUploadResults
|
||||||
).observeOn(AndroidSchedulers.mainThread())
|
).observeOn(AndroidSchedulers.mainThread())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,4 +358,8 @@ class ConversationViewModel(
|
|||||||
fun resolveMessageToEdit(conversationMessage: ConversationMessage): Single<ConversationMessage> {
|
fun resolveMessageToEdit(conversationMessage: ConversationMessage): Single<ConversationMessage> {
|
||||||
return repository.resolveMessageToEdit(conversationMessage)
|
return repository.resolveMessageToEdit(conversationMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun deleteSlideData(slides: List<Slide>) {
|
||||||
|
repository.deleteSlideData(slides)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user