Preclude cancelation of pre-uploaded video attachments.
Addresses ##10225.
This commit is contained in:
parent
2b1bbdda15
commit
d683b8a321
13 changed files with 137 additions and 56 deletions
|
@ -1941,6 +1941,10 @@ class ConversationFragment :
|
|||
onComplete = {
|
||||
onSendComplete()
|
||||
afterSendComplete()
|
||||
},
|
||||
onError = {
|
||||
Log.w(TAG, "Error received during send!", it)
|
||||
toast(R.string.ConversationActivity_error_sending_media)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -225,7 +225,7 @@ class ConversationRepository(
|
|||
emitter.onComplete()
|
||||
}
|
||||
} else {
|
||||
MessageSender.sendPushWithPreUploadedMedia(
|
||||
val sendSuccessful = MessageSender.sendPushWithPreUploadedMedia(
|
||||
AppDependencies.application,
|
||||
message,
|
||||
preUploadResults,
|
||||
|
@ -233,6 +233,10 @@ class ConversationRepository(
|
|||
) {
|
||||
emitter.onComplete()
|
||||
}
|
||||
|
||||
if (!sendSuccessful) {
|
||||
emitter.tryOnError(IllegalStateException("Could not send pre-uploaded attachments because they did not exist!"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.signal.core.util.Base64
|
|||
import org.signal.core.util.SqlUtil
|
||||
import org.signal.core.util.StreamUtil
|
||||
import org.signal.core.util.ThreadUtil
|
||||
import org.signal.core.util.count
|
||||
import org.signal.core.util.delete
|
||||
import org.signal.core.util.deleteAll
|
||||
import org.signal.core.util.drain
|
||||
|
@ -45,6 +46,7 @@ import org.signal.core.util.groupBy
|
|||
import org.signal.core.util.isNull
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.core.util.readToList
|
||||
import org.signal.core.util.readToSingleInt
|
||||
import org.signal.core.util.readToSingleLong
|
||||
import org.signal.core.util.readToSingleObject
|
||||
import org.signal.core.util.requireBlob
|
||||
|
@ -433,6 +435,20 @@ class AttachmentTable(
|
|||
.run()
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a list of attachment IDs and confirms they exist in the database.
|
||||
*/
|
||||
fun hasAttachments(ids: List<AttachmentId>): Boolean {
|
||||
return ids.size == SqlUtil.buildCollectionQuery(ID, ids.map { it.id }).sumOf { query ->
|
||||
readableDatabase
|
||||
.count()
|
||||
.from(TABLE_NAME)
|
||||
.where(query.where, query.whereArgs)
|
||||
.run()
|
||||
.readToSingleInt(defaultValue = 0)
|
||||
}
|
||||
}
|
||||
|
||||
fun getPendingAttachments(): List<DatabaseAttachment> {
|
||||
return readableDatabase
|
||||
.select(*PROJECTION)
|
||||
|
@ -1103,7 +1119,7 @@ class AttachmentTable(
|
|||
|
||||
@Throws(MmsException::class)
|
||||
fun insertAttachmentForPreUpload(attachment: Attachment): DatabaseAttachment {
|
||||
Log.d(TAG, "Inserting attachment $attachment for pre-upload.")
|
||||
Log.d(TAG, "Inserting attachment ${attachment.uri} for pre-upload.")
|
||||
val result = insertAttachmentsForMessage(PREUPLOAD_MESSAGE_ID, listOf(attachment), emptyList())
|
||||
|
||||
if (result.values.isEmpty()) {
|
||||
|
|
|
@ -227,12 +227,17 @@ public final class AttachmentCompressionJob extends BaseJob {
|
|||
@NonNull TranscoderCancelationSignal cancelationSignal)
|
||||
throws UndeliverableMessageException
|
||||
{
|
||||
|
||||
if (cancelationSignal.isCanceled()) {
|
||||
throw new UndeliverableMessageException("Job is canceled!");
|
||||
}
|
||||
|
||||
AttachmentTable.TransformProperties transformProperties = attachment.transformProperties;
|
||||
|
||||
boolean allowSkipOnFailure = false;
|
||||
|
||||
if (!MediaConstraints.isVideoTranscodeAvailable()) {
|
||||
if (transformProperties.getVideoEdited()) {
|
||||
if (transformProperties != null && transformProperties.getVideoEdited()) {
|
||||
throw new UndeliverableMessageException("Video edited, but transcode is not available");
|
||||
}
|
||||
return attachment;
|
||||
|
@ -284,6 +289,9 @@ public final class AttachmentCompressionJob extends BaseJob {
|
|||
PartProgressEvent.Type.COMPRESSION,
|
||||
100,
|
||||
100));
|
||||
if (cancelationSignal.isCanceled()) {
|
||||
throw new UndeliverableMessageException("Job is canceled!");
|
||||
}
|
||||
|
||||
final Mp4FaststartPostProcessor postProcessor = new Mp4FaststartPostProcessor(() -> {
|
||||
try {
|
||||
|
@ -355,7 +363,7 @@ public final class AttachmentCompressionJob extends BaseJob {
|
|||
}
|
||||
}
|
||||
} catch (VideoSourceException | EncodingException | MemoryFileException e) {
|
||||
if (attachment.size > constraints.getVideoMaxSize(context)) {
|
||||
if (attachment.size > constraints.getVideoMaxSize()) {
|
||||
throw new UndeliverableMessageException("Duration not found, attachment too large to skip transcode", e);
|
||||
} else {
|
||||
if (allowSkipOnFailure) {
|
||||
|
|
|
@ -166,7 +166,7 @@ public class MediaUploadRepository {
|
|||
PreUploadResult result = uploadResults.get(media);
|
||||
|
||||
if (result != null) {
|
||||
Log.d(TAG, "Canceling upload jobs for " + result.getJobIds().size() + " media items.");
|
||||
Log.d(TAG, "Canceling attachment upload job for " + result.getAttachmentId());
|
||||
Stream.of(result.getJobIds()).forEach(jobManager::cancel);
|
||||
uploadResults.remove(media);
|
||||
SignalDatabase.attachments().deleteAttachment(result.getAttachmentId());
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.thoughtcrime.securesms.stories.Stories
|
|||
import org.thoughtcrime.securesms.util.MediaUtil
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
import org.thoughtcrime.securesms.video.TranscodingPreset
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
data class MediaSelectionState(
|
||||
val sendType: MessageSendType,
|
||||
|
@ -44,6 +45,14 @@ data class MediaSelectionState(
|
|||
return editorStateMap[uri] as? VideoTrimData ?: VideoTrimData()
|
||||
}
|
||||
|
||||
fun calculateMaxVideoDurationUs(maxFileSize: Long): Long {
|
||||
return if (isStory && !MediaConstraints.isVideoTranscodeAvailable()) {
|
||||
Stories.MAX_VIDEO_DURATION_MILLIS
|
||||
} else {
|
||||
transcodingPreset.calculateMaxVideoUploadDurationInSeconds(maxFileSize).seconds.inWholeMicroseconds
|
||||
}
|
||||
}
|
||||
|
||||
enum class ViewOnceToggleState(val code: Int) {
|
||||
INFINITE(0),
|
||||
ONCE(1);
|
||||
|
|
|
@ -46,7 +46,6 @@ import org.thoughtcrime.securesms.util.livedata.Store
|
|||
import java.util.Collections
|
||||
import kotlin.math.max
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
/**
|
||||
* ViewModel which maintains the list of selected media and other shared values.
|
||||
|
@ -127,7 +126,7 @@ class MediaSelectionViewModel(
|
|||
}
|
||||
|
||||
if (initialMedia.isNotEmpty()) {
|
||||
addMedia(initialMedia)
|
||||
addMedia(initialMedia.toSet())
|
||||
}
|
||||
|
||||
disposables += selectedMediaSubject
|
||||
|
@ -165,7 +164,7 @@ class MediaSelectionViewModel(
|
|||
}
|
||||
|
||||
fun addMedia(media: Media) {
|
||||
addMedia(listOf(media))
|
||||
addMedia(setOf(media))
|
||||
}
|
||||
|
||||
fun isStory(): Boolean {
|
||||
|
@ -176,7 +175,7 @@ class MediaSelectionViewModel(
|
|||
return store.state.storySendRequirements
|
||||
}
|
||||
|
||||
private fun addMedia(media: List<Media>) {
|
||||
private fun addMedia(media: Set<Media>) {
|
||||
val newSelectionList: List<Media> = linkedSetOf<Media>().apply {
|
||||
addAll(store.state.selectedMedia)
|
||||
addAll(media)
|
||||
|
@ -188,11 +187,16 @@ class MediaSelectionViewModel(
|
|||
.subscribe { filterResult ->
|
||||
if (filterResult.filteredMedia.isNotEmpty()) {
|
||||
store.update {
|
||||
val maxDuration = it.calculateMaxVideoDurationUs(getMediaConstraints().getVideoMaxSize())
|
||||
val initializedVideoEditorStates = filterResult.filteredMedia.filterNot { media -> it.editorStateMap.containsKey(media.uri) }
|
||||
.filter { media -> MediaUtil.isNonGifVideo(media) }
|
||||
.associate { video: Media ->
|
||||
val duration = video.duration.milliseconds.inWholeMicroseconds
|
||||
video.uri to VideoTrimData(false, duration, 0, duration)
|
||||
if (duration < maxDuration) {
|
||||
video.uri to VideoTrimData(false, duration, 0, duration)
|
||||
} else {
|
||||
video.uri to VideoTrimData(true, duration, 0, maxDuration)
|
||||
}
|
||||
}
|
||||
it.copy(
|
||||
selectedMedia = filterResult.filteredMedia,
|
||||
|
@ -341,7 +345,7 @@ class MediaSelectionViewModel(
|
|||
store.update { it.copy(viewOnceToggleState = it.viewOnceToggleState.next()) }
|
||||
}
|
||||
|
||||
fun onEditVideoDuration(context: Context, totalDurationUs: Long, startTimeUs: Long, endTimeUs: Long, touchEnabled: Boolean) {
|
||||
fun onEditVideoDuration(totalDurationUs: Long, startTimeUs: Long, endTimeUs: Long, touchEnabled: Boolean) {
|
||||
store.update {
|
||||
val uri = it.focusedMedia?.uri ?: return@update it
|
||||
val data = it.getOrCreateVideoTrimData(uri)
|
||||
|
@ -351,27 +355,30 @@ class MediaSelectionViewModel(
|
|||
val durationEdited = clampedStartTime > 0 || endTimeUs < totalDurationUs
|
||||
val isEntireDuration = startTimeUs == 0L && endTimeUs == totalDurationUs
|
||||
val endMoved = !isEntireDuration && data.endTimeUs != endTimeUs
|
||||
val maxVideoDurationUs: Long = if (it.isStory && !MediaConstraints.isVideoTranscodeAvailable()) {
|
||||
Stories.MAX_VIDEO_DURATION_MILLIS
|
||||
} else {
|
||||
it.transcodingPreset.calculateMaxVideoUploadDurationInSeconds(getMediaConstraints().getVideoMaxSize(context)).seconds.inWholeMicroseconds
|
||||
}
|
||||
val maxVideoDurationUs: Long = it.calculateMaxVideoDurationUs(getMediaConstraints().getVideoMaxSize())
|
||||
val preserveStartTime = unedited || !endMoved
|
||||
val videoTrimData = VideoTrimData(durationEdited, totalDurationUs, clampedStartTime, endTimeUs)
|
||||
val updatedData = clampToMaxClipDuration(videoTrimData, maxVideoDurationUs, preserveStartTime)
|
||||
|
||||
if (updatedData != videoTrimData) {
|
||||
Log.d(TAG, "Video trim clamped from ${videoTrimData.startTimeUs}, ${videoTrimData.endTimeUs} to ${updatedData.startTimeUs}, ${updatedData.endTimeUs}")
|
||||
Log.d(TAG, "Video attachment trim clamped from ${videoTrimData.startTimeUs}, ${videoTrimData.endTimeUs} to ${updatedData.startTimeUs}, ${updatedData.endTimeUs}")
|
||||
}
|
||||
|
||||
if (unedited && durationEdited) {
|
||||
Log.d(TAG, "Canceling upload because the duration has been edited for the first time..")
|
||||
Log.d(TAG, "Canceling attachment upload because the duration has been edited for the first time..")
|
||||
cancelUpload(MediaBuilder.buildMedia(uri))
|
||||
}
|
||||
it.copy(
|
||||
isTouchEnabled = touchEnabled,
|
||||
editorStateMap = it.editorStateMap + (uri to updatedData)
|
||||
)
|
||||
|
||||
if (updatedData != data) {
|
||||
Log.d(TAG, "Updating video attachment trim data for $uri")
|
||||
it.copy(
|
||||
isTouchEnabled = touchEnabled,
|
||||
editorStateMap = it.editorStateMap + (uri to updatedData)
|
||||
)
|
||||
} else {
|
||||
Log.d(TAG, "Preserving video attachment trim data for $uri")
|
||||
it.copy(isTouchEnabled = touchEnabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -114,8 +114,8 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
|||
private var disposables: LifecycleDisposable = LifecycleDisposable()
|
||||
private var sentMediaQuality: SentMediaQuality = SignalStore.settings.sentMediaQuality
|
||||
private var viewOnceToggleState: MediaSelectionState.ViewOnceToggleState = MediaSelectionState.ViewOnceToggleState.default
|
||||
|
||||
private var scheduledSendTime: Long? = null
|
||||
private var readyToSend = true
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
postponeEnterTransition()
|
||||
|
@ -202,6 +202,14 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
|||
}
|
||||
|
||||
sendButton.setOnClickListener {
|
||||
if (!readyToSend) {
|
||||
Log.d(TAG, "Attachment send button not currently enabled. Ignoring click event.")
|
||||
return@setOnClickListener
|
||||
} else {
|
||||
Log.d(TAG, "Attachment send button enabled. Processing click event.")
|
||||
readyToSend = false
|
||||
}
|
||||
|
||||
val viewOnce: Boolean = sharedViewModel.state.value?.viewOnceToggleState == MediaSelectionState.ViewOnceToggleState.ONCE
|
||||
|
||||
if (sharedViewModel.isContactSelectionRequired) {
|
||||
|
@ -216,7 +224,7 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
|||
val snapshot = sharedViewModel.state.value
|
||||
|
||||
if (snapshot != null) {
|
||||
sendButton.isEnabled = false
|
||||
readyToSend = false
|
||||
SimpleTask.run(viewLifecycleOwner.lifecycle, {
|
||||
snapshot.selectedMedia.take(2).map { media ->
|
||||
val editorData = snapshot.editorStateMap[media.uri]
|
||||
|
@ -232,7 +240,6 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
|||
}
|
||||
}
|
||||
}, {
|
||||
sendButton.isEnabled = true
|
||||
storiesLauncher.launch(StoriesMultiselectForwardActivity.Args(args, it))
|
||||
})
|
||||
} else {
|
||||
|
@ -249,7 +256,15 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
|||
Log.d(TAG, "Performing send add to group story dialog.")
|
||||
performSend()
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ -> }
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ ->
|
||||
readyToSend = true
|
||||
}
|
||||
.setOnCancelListener {
|
||||
readyToSend = true
|
||||
}
|
||||
.setOnDismissListener {
|
||||
readyToSend = true
|
||||
}
|
||||
.show()
|
||||
scheduledSendTime = null
|
||||
} else {
|
||||
|
@ -325,7 +340,7 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
|||
state.selectedMedia.map { MediaReviewSelectedItem.Model(it, state.focusedMedia == it) } + MediaReviewAddItem.Model
|
||||
)
|
||||
|
||||
presentSendButton(state.sendType, state.recipient)
|
||||
presentSendButton(readyToSend, state.sendType, state.recipient)
|
||||
presentPager(state)
|
||||
presentAddMessageEntry(state.viewOnceToggleState, state.message)
|
||||
presentImageQualityToggle(state)
|
||||
|
@ -449,6 +464,8 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
|||
}
|
||||
|
||||
private fun performSend(selection: List<ContactSearchKey> = listOf()) {
|
||||
Log.d(TAG, "Performing attachment send.")
|
||||
readyToSend = false
|
||||
progressWrapper.visible = true
|
||||
progressWrapper.animate()
|
||||
.setStartDelay(300)
|
||||
|
@ -456,11 +473,20 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
|||
.alpha(1f)
|
||||
|
||||
disposables += sharedViewModel
|
||||
.send(selection.filterIsInstance(ContactSearchKey.RecipientSearchKey::class.java), scheduledSendTime)
|
||||
.send(selection.filterIsInstance<ContactSearchKey.RecipientSearchKey>(), scheduledSendTime)
|
||||
.subscribe(
|
||||
{ result -> callback.onSentWithResult(result) },
|
||||
{ error -> callback.onSendError(error) },
|
||||
{ callback.onSentWithoutResult() }
|
||||
{ result ->
|
||||
callback.onSentWithResult(result)
|
||||
readyToSend = true
|
||||
},
|
||||
{ error ->
|
||||
callback.onSendError(error)
|
||||
readyToSend = true
|
||||
},
|
||||
{
|
||||
callback.onSentWithoutResult()
|
||||
readyToSend = true
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -500,8 +526,9 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
|||
)
|
||||
}
|
||||
|
||||
private fun presentSendButton(sendType: MessageSendType, recipient: Recipient?) {
|
||||
private fun presentSendButton(enabled: Boolean, sendType: MessageSendType, recipient: Recipient?) {
|
||||
val sendButtonBackgroundTint = when {
|
||||
!enabled -> ContextCompat.getColor(requireContext(), R.color.core_grey_50)
|
||||
recipient != null -> recipient.chatColors.asSingleColor()
|
||||
sendType.usesSignalTransport -> ContextCompat.getColor(requireContext(), R.color.signal_colorOnSecondaryContainer)
|
||||
else -> ContextCompat.getColor(requireContext(), R.color.core_grey_50)
|
||||
|
@ -513,6 +540,7 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
|||
}
|
||||
|
||||
val sendButtonForegroundTint = when {
|
||||
!enabled -> ContextCompat.getColor(requireContext(), R.color.signal_colorSecondaryContainer)
|
||||
recipient != null -> ContextCompat.getColor(requireContext(), R.color.signal_colorOnCustom)
|
||||
else -> ContextCompat.getColor(requireContext(), R.color.signal_colorSecondaryContainer)
|
||||
}
|
||||
|
@ -549,7 +577,7 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
|||
videoTimeLine.unregisterDragListener()
|
||||
}
|
||||
val size: Long = tryGetUriSize(requireContext(), uri, Long.MAX_VALUE)
|
||||
val maxSend = sharedViewModel.getMediaConstraints().getVideoMaxSize(requireContext())
|
||||
val maxSend = sharedViewModel.getMediaConstraints().getVideoMaxSize()
|
||||
if (size > maxSend) {
|
||||
videoTimeLine.setTimeLimit(state.transcodingPreset.calculateMaxVideoUploadDurationInSeconds(maxSend), TimeUnit.SECONDS)
|
||||
}
|
||||
|
@ -791,6 +819,6 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
|||
}
|
||||
|
||||
override fun onRangeDrag(minValue: Long, maxValue: Long, duration: Long, end: Boolean) {
|
||||
sharedViewModel.onEditVideoDuration(context = requireContext(), totalDurationUs = duration, startTimeUs = minValue, endTimeUs = maxValue, touchEnabled = end)
|
||||
sharedViewModel.onEditVideoDuration(totalDurationUs = duration, startTimeUs = minValue, endTimeUs = maxValue, touchEnabled = end)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ class MediaReviewVideoPageFragment : Fragment(R.layout.fragment_container), Vide
|
|||
}
|
||||
|
||||
private fun requireUri(): Uri = requireNotNull(requireArguments().getParcelableCompat(ARG_URI, Uri::class.java))
|
||||
private fun requireMaxAttachmentSize(): Long = sharedViewModel.getMediaConstraints().getVideoMaxSize(requireContext())
|
||||
private fun requireMaxAttachmentSize(): Long = sharedViewModel.getMediaConstraints().getVideoMaxSize()
|
||||
private fun requireIsVideoGif(): Boolean = requireNotNull(requireArguments().getBoolean(ARG_IS_VIDEO_GIF))
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -49,18 +49,18 @@ public abstract class MediaConstraints {
|
|||
public abstract int[] getImageDimensionTargets(Context context);
|
||||
|
||||
public abstract long getGifMaxSize(Context context);
|
||||
public abstract long getVideoMaxSize(Context context);
|
||||
public abstract long getVideoMaxSize();
|
||||
|
||||
public @IntRange(from = 0, to = 100) int getImageCompressionQualitySetting(@NonNull Context context) {
|
||||
return 70;
|
||||
}
|
||||
|
||||
public long getUncompressedVideoMaxSize(Context context) {
|
||||
return getVideoMaxSize(context);
|
||||
return getVideoMaxSize();
|
||||
}
|
||||
|
||||
public long getCompressedVideoMaxSize(Context context) {
|
||||
return getVideoMaxSize(context);
|
||||
return getVideoMaxSize();
|
||||
}
|
||||
|
||||
public abstract long getAudioMaxSize(Context context);
|
||||
|
@ -79,7 +79,7 @@ public abstract class MediaConstraints {
|
|||
return (MediaUtil.isGif(attachment) && size <= getGifMaxSize(context) && isWithinBounds(context, attachment.getUri())) ||
|
||||
(MediaUtil.isImage(attachment) && size <= getImageMaxSize(context) && isWithinBounds(context, attachment.getUri())) ||
|
||||
(MediaUtil.isAudio(attachment) && size <= getAudioMaxSize(context)) ||
|
||||
(MediaUtil.isVideo(attachment) && size <= getVideoMaxSize(context)) ||
|
||||
(MediaUtil.isVideo(attachment) && size <= getVideoMaxSize()) ||
|
||||
(MediaUtil.isFile(attachment) && size <= getDocumentMaxSize(context));
|
||||
} catch (IOException ioe) {
|
||||
Log.w(TAG, "Failed to determine if media's constraints are satisfied.", ioe);
|
||||
|
@ -95,7 +95,7 @@ public abstract class MediaConstraints {
|
|||
return (MediaUtil.isGif(contentType) && size <= getGifMaxSize(context) && isWithinBounds(context, uri)) ||
|
||||
(MediaUtil.isImageType(contentType) && size <= getImageMaxSize(context) && isWithinBounds(context, uri)) ||
|
||||
(MediaUtil.isAudioType(contentType) && size <= getAudioMaxSize(context)) ||
|
||||
(MediaUtil.isVideoType(contentType) && size <= getVideoMaxSize(context)) ||
|
||||
(MediaUtil.isVideoType(contentType) && size <= getVideoMaxSize()) ||
|
||||
size <= getDocumentMaxSize(context);
|
||||
} catch (IOException ioe) {
|
||||
Log.w(TAG, "Failed to determine if media's constraints are satisfied.", ioe);
|
||||
|
|
|
@ -53,14 +53,14 @@ public class PushMediaConstraints extends MediaConstraints {
|
|||
}
|
||||
|
||||
@Override
|
||||
public long getVideoMaxSize(Context context) {
|
||||
public long getVideoMaxSize() {
|
||||
return getMaxAttachmentSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getUncompressedVideoMaxSize(Context context) {
|
||||
return isVideoTranscodeAvailable() ? RemoteConfig.maxSourceTranscodeVideoSizeBytes()
|
||||
: getVideoMaxSize(context);
|
||||
: getVideoMaxSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -32,7 +32,7 @@ public class ProfileMediaConstraints extends MediaConstraints {
|
|||
}
|
||||
|
||||
@Override
|
||||
public long getVideoMaxSize(Context context) {
|
||||
public long getVideoMaxSize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -52,10 +52,10 @@ import org.thoughtcrime.securesms.jobs.AttachmentCompressionJob;
|
|||
import org.thoughtcrime.securesms.jobs.AttachmentCopyJob;
|
||||
import org.thoughtcrime.securesms.jobs.AttachmentMarkUploadedJob;
|
||||
import org.thoughtcrime.securesms.jobs.AttachmentUploadJob;
|
||||
import org.thoughtcrime.securesms.jobs.IndividualSendJob;
|
||||
import org.thoughtcrime.securesms.jobs.ProfileKeySendJob;
|
||||
import org.thoughtcrime.securesms.jobs.PushDistributionListSendJob;
|
||||
import org.thoughtcrime.securesms.jobs.PushGroupSendJob;
|
||||
import org.thoughtcrime.securesms.jobs.IndividualSendJob;
|
||||
import org.thoughtcrime.securesms.jobs.ReactionSendJob;
|
||||
import org.thoughtcrime.securesms.jobs.RemoteDeleteSendJob;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
|
@ -251,12 +251,11 @@ public class MessageSender {
|
|||
}
|
||||
}
|
||||
|
||||
public static long sendPushWithPreUploadedMedia(final Context context,
|
||||
final OutgoingMessage message,
|
||||
final Collection<PreUploadResult> preUploadResults,
|
||||
final long threadId,
|
||||
final MessageTable.InsertListener insertListener)
|
||||
{
|
||||
public static boolean sendPushWithPreUploadedMedia(final Context context,
|
||||
final OutgoingMessage message,
|
||||
final Collection<PreUploadResult> preUploadResults,
|
||||
final long threadId,
|
||||
final MessageTable.InsertListener insertListener) {
|
||||
Log.i(TAG, "Sending media message with pre-uploads to " + message.getThreadRecipient().getId() + ", thread: " + threadId + ", pre-uploads: " + preUploadResults);
|
||||
Preconditions.checkArgument(message.getAttachments().isEmpty(), "If the media is pre-uploaded, there should be no attachments on the message.");
|
||||
|
||||
|
@ -267,24 +266,30 @@ public class MessageSender {
|
|||
|
||||
Recipient recipient = message.getThreadRecipient();
|
||||
long allocatedThreadId = threadTable.getOrCreateValidThreadId(message.getThreadRecipient(), threadId);
|
||||
long messageId = mmsDatabase.insertMessageOutbox(applyUniversalExpireTimerIfNecessary(context, recipient, message, allocatedThreadId),
|
||||
allocatedThreadId,
|
||||
false,
|
||||
insertListener);
|
||||
|
||||
List<AttachmentId> attachmentIds = Stream.of(preUploadResults).map(PreUploadResult::getAttachmentId).toList();
|
||||
List<String> jobIds = Stream.of(preUploadResults).map(PreUploadResult::getJobIds).flatMap(Stream::of).toList();
|
||||
|
||||
if (!attachmentDatabase.hasAttachments(attachmentIds)) {
|
||||
Log.w(TAG, "Attachments not found in database for " + message.getThreadRecipient().getId() + ", thread: " + threadId + ", pre-uploads: " + preUploadResults);
|
||||
return false;
|
||||
}
|
||||
|
||||
long messageId = mmsDatabase.insertMessageOutbox(applyUniversalExpireTimerIfNecessary(context, recipient, message, allocatedThreadId),
|
||||
allocatedThreadId,
|
||||
false,
|
||||
insertListener);
|
||||
|
||||
attachmentDatabase.updateMessageId(attachmentIds, messageId, message.getStoryType().isStory());
|
||||
|
||||
sendMessageInternal(context, recipient, SendType.SIGNAL, messageId, jobIds, false);
|
||||
onMessageSent();
|
||||
threadTable.update(allocatedThreadId, true, true);
|
||||
|
||||
return allocatedThreadId;
|
||||
return true;
|
||||
} catch (MmsException e) {
|
||||
Log.w(TAG, e);
|
||||
return threadId;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue