kopia lustrzana https://github.com/ryukoposting/Signal-Android
162 wiersze
5.2 KiB
Kotlin
162 wiersze
5.2 KiB
Kotlin
package org.thoughtcrime.securesms.stories.viewer
|
|
|
|
import android.content.Intent
|
|
import android.widget.Toast
|
|
import androidx.activity.result.ActivityResultLauncher
|
|
import androidx.activity.result.contract.ActivityResultContracts
|
|
import androidx.annotation.CheckResult
|
|
import androidx.annotation.WorkerThread
|
|
import androidx.fragment.app.Fragment
|
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
|
import io.reactivex.rxjava3.core.Completable
|
|
import io.reactivex.rxjava3.kotlin.subscribeBy
|
|
import io.reactivex.rxjava3.subjects.CompletableSubject
|
|
import org.signal.core.util.concurrent.SignalExecutors
|
|
import org.signal.core.util.logging.Log
|
|
import org.thoughtcrime.securesms.R
|
|
import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey
|
|
import org.thoughtcrime.securesms.database.SignalDatabase
|
|
import org.thoughtcrime.securesms.database.ThreadTable
|
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
|
import org.thoughtcrime.securesms.mediasend.MediaSendActivityResult
|
|
import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionActivity
|
|
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage
|
|
import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage
|
|
import org.thoughtcrime.securesms.mms.SlideDeck
|
|
import org.thoughtcrime.securesms.recipients.Recipient
|
|
import org.thoughtcrime.securesms.recipients.RecipientId
|
|
import org.thoughtcrime.securesms.sharing.MultiShareArgs
|
|
import org.thoughtcrime.securesms.sharing.MultiShareSender
|
|
import org.thoughtcrime.securesms.sms.MessageSender
|
|
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
|
|
|
/**
|
|
* Delegate for dealing with sending stories directly to a group.
|
|
*/
|
|
class AddToGroupStoryDelegate(
|
|
private val fragment: Fragment
|
|
) {
|
|
|
|
companion object {
|
|
private val TAG = Log.tag(AddToGroupStoryDelegate::class.java)
|
|
}
|
|
|
|
private val lifecycleDisposable = LifecycleDisposable().apply {
|
|
bindTo(fragment.viewLifecycleOwner)
|
|
}
|
|
|
|
private val addToStoryLauncher: ActivityResultLauncher<Intent> = fragment.registerForActivityResult(
|
|
ActivityResultContracts.StartActivityForResult()
|
|
) { result ->
|
|
val data = result.data
|
|
if (data == null) {
|
|
Log.d(TAG, "No result data.")
|
|
} else {
|
|
Log.d(TAG, "Processing result...")
|
|
val mediaSelectionResult: MediaSendActivityResult = MediaSendActivityResult.fromData(data)
|
|
handleResult(mediaSelectionResult)
|
|
}
|
|
}
|
|
|
|
fun addToStory(recipientId: RecipientId) {
|
|
val addToStoryIntent = MediaSelectionActivity.addToGroupStory(
|
|
fragment.requireContext(),
|
|
recipientId
|
|
)
|
|
|
|
addToStoryLauncher.launch(addToStoryIntent)
|
|
}
|
|
|
|
private fun handleResult(result: MediaSendActivityResult) {
|
|
lifecycleDisposable += ResultHandler.handleResult(result)
|
|
.observeOn(AndroidSchedulers.mainThread())
|
|
.subscribeBy {
|
|
Toast.makeText(fragment.requireContext(), R.string.TextStoryPostCreationFragment__sent_story, Toast.LENGTH_SHORT).show()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Dispatches the send result on a background thread, isolated from the fragment.
|
|
*/
|
|
private object ResultHandler {
|
|
|
|
/**
|
|
* Handles the result, completing after sending the message.
|
|
*/
|
|
@CheckResult
|
|
fun handleResult(result: MediaSendActivityResult): Completable {
|
|
Log.d(TAG, "Dispatching result handler.")
|
|
val subject = CompletableSubject.create()
|
|
SignalExecutors.BOUNDED_IO.execute {
|
|
if (result.isPushPreUpload) {
|
|
sendPreUploadedMedia(result)
|
|
} else {
|
|
sendNonPreUploadedMedia(result)
|
|
}
|
|
|
|
subject.onComplete()
|
|
}
|
|
|
|
return subject
|
|
}
|
|
|
|
@WorkerThread
|
|
private fun sendPreUploadedMedia(result: MediaSendActivityResult) {
|
|
Log.d(TAG, "Sending preupload media.")
|
|
|
|
val recipient = Recipient.resolved(result.recipientId)
|
|
val secureMessage = OutgoingSecureMediaMessage(
|
|
OutgoingMediaMessage(
|
|
Recipient.resolved(result.recipientId),
|
|
SlideDeck(),
|
|
"",
|
|
System.currentTimeMillis(),
|
|
-1,
|
|
0,
|
|
false,
|
|
ThreadTable.DistributionTypes.DEFAULT,
|
|
result.storyType,
|
|
null,
|
|
false,
|
|
null,
|
|
emptyList(),
|
|
emptyList(),
|
|
result.mentions.toList(),
|
|
null
|
|
)
|
|
)
|
|
|
|
val threadId = SignalDatabase.threads.getOrCreateThreadIdFor(recipient)
|
|
if (result.body.isNotEmpty()) {
|
|
result.preUploadResults.forEach {
|
|
SignalDatabase.attachments.updateAttachmentCaption(it.attachmentId, result.body)
|
|
}
|
|
}
|
|
|
|
MessageSender.sendPushWithPreUploadedMedia(
|
|
ApplicationDependencies.getApplication(),
|
|
secureMessage,
|
|
result.preUploadResults,
|
|
threadId
|
|
) {
|
|
Log.d(TAG, "Sent.")
|
|
}
|
|
}
|
|
|
|
@WorkerThread
|
|
private fun sendNonPreUploadedMedia(result: MediaSendActivityResult) {
|
|
Log.d(TAG, "Sending non-preupload media.")
|
|
|
|
val multiShareArgs = MultiShareArgs.Builder(setOf(ContactSearchKey.RecipientSearchKey.Story(result.recipientId)))
|
|
.withMedia(result.nonUploadedMedia.toList())
|
|
.withDraftText(result.body)
|
|
.withMentions(result.mentions.toList())
|
|
.build()
|
|
|
|
val results = MultiShareSender.sendSync(multiShareArgs)
|
|
|
|
Log.d(TAG, "Sent. Failures? ${results.containsFailures()}")
|
|
}
|
|
}
|
|
}
|