Extract Media and TransformProperties to core/util/models.

This commit is contained in:
Alex Hart
2026-01-20 15:21:27 -04:00
committed by GitHub
parent f505d48d80
commit 471b214b4a
124 changed files with 413 additions and 302 deletions

View File

@@ -525,6 +525,7 @@ dependencies {
implementation(project(":lib:photoview"))
implementation(project(":core:ui"))
implementation(project(":core:models"))
implementation(project(":core:models-jvm"))
implementation(libs.androidx.fragment.ktx)
implementation(libs.androidx.appcompat) {

View File

@@ -20,6 +20,7 @@ import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.signal.core.models.backup.MediaName
import org.signal.core.models.media.TransformProperties
import org.signal.core.util.Base64
import org.signal.core.util.Base64.decodeBase64OrThrow
import org.signal.core.util.copyTo
@@ -82,7 +83,7 @@ class AttachmentTableTest {
val blob = BlobProvider.getInstance().forData(byteArrayOf(1, 2, 3, 4, 5)).createForSingleSessionInMemory()
val highQualityProperties = createHighQualityTransformProperties()
val highQualityImage = createAttachment(1, blob, highQualityProperties)
val lowQualityImage = createAttachment(1, blob, AttachmentTable.TransformProperties.empty())
val lowQualityImage = createAttachment(1, blob, TransformProperties.empty())
val attachment = SignalDatabase.attachments.insertAttachmentForPreUpload(highQualityImage)
val attachment2 = SignalDatabase.attachments.insertAttachmentForPreUpload(lowQualityImage)
@@ -144,13 +145,13 @@ class AttachmentTableTest {
val blobUncompressed = BlobProvider.getInstance().forData(uncompressData).createForSingleSessionInMemory()
val previousAttachment = createAttachment(1, BlobProvider.getInstance().forData(compressedData).createForSingleSessionInMemory(), AttachmentTable.TransformProperties.empty())
val previousAttachment = createAttachment(1, BlobProvider.getInstance().forData(compressedData).createForSingleSessionInMemory(), TransformProperties.empty())
val previousDatabaseAttachmentId: AttachmentId = SignalDatabase.attachments.insertAttachmentsForMessage(1, listOf(previousAttachment), emptyList()).values.first()
val standardQualityPreUpload = createAttachment(1, blobUncompressed, AttachmentTable.TransformProperties.empty())
val standardQualityPreUpload = createAttachment(1, blobUncompressed, TransformProperties.empty())
val standardDatabaseAttachment = SignalDatabase.attachments.insertAttachmentForPreUpload(standardQualityPreUpload)
val highQualityPreUpload = createAttachment(1, blobUncompressed, AttachmentTable.TransformProperties.forSentMediaQuality(Optional.empty(), SentMediaQuality.HIGH))
val highQualityPreUpload = createAttachment(1, blobUncompressed, transformPropertiesForSentMediaQuality(Optional.empty(), SentMediaQuality.HIGH))
val highDatabaseAttachment = SignalDatabase.attachments.insertAttachmentForPreUpload(highQualityPreUpload)
// WHEN
@@ -179,14 +180,14 @@ class AttachmentTableTest {
val uncompressData = byteArrayOf(1, 2, 3, 4, 5)
val blobUncompressed = BlobProvider.getInstance().forData(uncompressData).createForSingleSessionInMemory()
val standardQualityPreUpload = createAttachment(1, blobUncompressed, AttachmentTable.TransformProperties.empty())
val standardQualityPreUpload = createAttachment(1, blobUncompressed, TransformProperties.empty())
val standardDatabaseAttachment = SignalDatabase.attachments.insertAttachmentForPreUpload(standardQualityPreUpload)
// WHEN
val highQualityPreUpload = createAttachment(1, blobUncompressed, AttachmentTable.TransformProperties.forSentMediaQuality(Optional.empty(), SentMediaQuality.HIGH))
val highQualityPreUpload = createAttachment(1, blobUncompressed, transformPropertiesForSentMediaQuality(Optional.empty(), SentMediaQuality.HIGH))
val highDatabaseAttachment = SignalDatabase.attachments.insertAttachmentForPreUpload(highQualityPreUpload)
val secondHighQualityPreUpload = createAttachment(1, blobUncompressed, AttachmentTable.TransformProperties.forSentMediaQuality(Optional.empty(), SentMediaQuality.HIGH))
val secondHighQualityPreUpload = createAttachment(1, blobUncompressed, transformPropertiesForSentMediaQuality(Optional.empty(), SentMediaQuality.HIGH))
val secondHighDatabaseAttachment = SignalDatabase.attachments.insertAttachmentForPreUpload(secondHighQualityPreUpload)
// THEN
@@ -204,7 +205,7 @@ class AttachmentTableTest {
fun resetArchiveTransferStateByPlaintextHashAndRemoteKey_singleMatch() {
// Given an attachment with some plaintextHash+remoteKey
val blob = BlobProvider.getInstance().forData(byteArrayOf(1, 2, 3, 4, 5)).createForSingleSessionInMemory()
val attachment = createAttachment(1, blob, AttachmentTable.TransformProperties.empty())
val attachment = createAttachment(1, blob, TransformProperties.empty())
val attachmentId = SignalDatabase.attachments.insertAttachmentsForMessage(-1L, listOf(attachment), emptyList()).values.first()
SignalDatabase.attachments.finalizeAttachmentAfterUpload(attachmentId, AttachmentTableTestUtil.createUploadResult(attachmentId))
SignalDatabase.attachments.setArchiveTransferState(attachmentId, AttachmentTable.ArchiveTransferState.FINISHED)
@@ -259,7 +260,7 @@ class AttachmentTableTest {
// GIVEN
val uncompressData = byteArrayOf(1, 2, 3, 4, 5)
val blobUncompressed = BlobProvider.getInstance().forData(uncompressData).createForSingleSessionInMemory()
val attachment = createAttachment(1, blobUncompressed, AttachmentTable.TransformProperties.empty())
val attachment = createAttachment(1, blobUncompressed, TransformProperties.empty())
val message = createIncomingMessage(serverTime = 0.days, attachment = attachment, expiresIn = 5.minutes)
val messageId = SignalDatabase.messages.insertMessageInbox(message).map { it.messageId }.get()
SignalDatabase.attachments.setArchiveTransferState(AttachmentId(1L), AttachmentTable.ArchiveTransferState.NONE)
@@ -278,7 +279,7 @@ class AttachmentTableTest {
// GIVEN
val uncompressData = byteArrayOf(1, 2, 3, 4, 5)
val blobUncompressed = BlobProvider.getInstance().forData(uncompressData).createForSingleSessionInMemory()
val attachment = createAttachment(1, blobUncompressed, AttachmentTable.TransformProperties.empty())
val attachment = createAttachment(1, blobUncompressed, TransformProperties.empty())
val message = createIncomingMessage(serverTime = 0.days, attachment = attachment, expiresIn = 5.days)
val messageId = SignalDatabase.messages.insertMessageInbox(message).map { it.messageId }.get()
SignalDatabase.attachments.setArchiveTransferState(AttachmentId(1L), AttachmentTable.ArchiveTransferState.NONE)
@@ -297,7 +298,7 @@ class AttachmentTableTest {
// GIVEN
val uncompressData = byteArrayOf(1, 2, 3, 4, 5)
val blobUncompressed = BlobProvider.getInstance().forData(uncompressData).createForSingleSessionInMemory()
val attachment = createAttachment(1, blobUncompressed, AttachmentTable.TransformProperties.empty())
val attachment = createAttachment(1, blobUncompressed, TransformProperties.empty())
val message = createIncomingMessage(serverTime = 0.days, attachment = attachment, expiresIn = 5.days)
val messageId = SignalDatabase.messages.insertMessageInbox(message).map { it.messageId }.get()
SignalDatabase.messages.markExpireStarted(messageId)
@@ -317,7 +318,7 @@ class AttachmentTableTest {
// GIVEN
val uncompressData = byteArrayOf(1, 2, 3, 4, 5)
val blobUncompressed = BlobProvider.getInstance().forData(uncompressData).createForSingleSessionInMemory()
val attachment = createAttachment(1, blobUncompressed, AttachmentTable.TransformProperties.empty(), contentType = MediaUtil.LONG_TEXT)
val attachment = createAttachment(1, blobUncompressed, TransformProperties.empty(), contentType = MediaUtil.LONG_TEXT)
val message = createIncomingMessage(serverTime = 0.days, attachment = attachment)
val messageId = SignalDatabase.messages.insertMessageInbox(message).map { it.messageId }.get()
SignalDatabase.attachments.setArchiveTransferState(AttachmentId(1L), AttachmentTable.ArchiveTransferState.NONE)
@@ -612,7 +613,7 @@ class AttachmentTableTest {
)
}
private fun createAttachment(id: Long, uri: Uri, transformProperties: AttachmentTable.TransformProperties, contentType: String = MediaUtil.IMAGE_JPEG): UriAttachment {
private fun createAttachment(id: Long, uri: Uri, transformProperties: TransformProperties, contentType: String = MediaUtil.IMAGE_JPEG): UriAttachment {
return UriAttachmentBuilder.build(
id,
uri = uri,
@@ -621,8 +622,8 @@ class AttachmentTableTest {
)
}
private fun createHighQualityTransformProperties(): AttachmentTable.TransformProperties {
return AttachmentTable.TransformProperties.forSentMediaQuality(Optional.empty(), SentMediaQuality.HIGH)
private fun createHighQualityTransformProperties(): TransformProperties {
return transformPropertiesForSentMediaQuality(Optional.empty(), SentMediaQuality.HIGH)
}
private fun createMediaStream(byteArray: ByteArray): MediaStream {

View File

@@ -12,6 +12,7 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.signal.core.models.ServiceId
import org.signal.core.models.media.TransformProperties
import org.signal.core.util.Base64
import org.signal.core.util.readFully
import org.signal.core.util.stream.LimitedInputStream
@@ -19,7 +20,6 @@ import org.signal.core.util.update
import org.thoughtcrime.securesms.attachments.AttachmentId
import org.thoughtcrime.securesms.attachments.Cdn
import org.thoughtcrime.securesms.attachments.PointerAttachment
import org.thoughtcrime.securesms.database.AttachmentTable.TransformProperties
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.mms.MediaStream
import org.thoughtcrime.securesms.mms.OutgoingMessage

View File

@@ -1,6 +1,7 @@
package org.thoughtcrime.securesms.database
import android.net.Uri
import org.signal.core.models.media.TransformProperties
import org.thoughtcrime.securesms.attachments.UriAttachment
import org.thoughtcrime.securesms.audio.AudioHash
import org.thoughtcrime.securesms.blurhash.BlurHash
@@ -24,7 +25,7 @@ object UriAttachmentBuilder {
stickerLocator: StickerLocator? = null,
blurHash: BlurHash? = null,
audioHash: AudioHash? = null,
transformProperties: AttachmentTable.TransformProperties? = null,
transformProperties: TransformProperties? = null,
uuid: UUID? = UUID.randomUUID()
): UriAttachment {
return UriAttachment(

View File

@@ -13,11 +13,12 @@ import assertk.assertions.isTrue
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.signal.core.models.media.TransformProperties
import org.signal.core.util.StreamUtil
import org.thoughtcrime.securesms.attachments.UriAttachment
import org.thoughtcrime.securesms.database.AttachmentTable
import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.database.UriAttachmentBuilder
import org.thoughtcrime.securesms.database.transformPropertiesForSentMediaQuality
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.jobmanager.Job
import org.thoughtcrime.securesms.mms.SentMediaQuality
@@ -41,7 +42,7 @@ class AttachmentCompressionJobTest {
val blob = BlobProvider.getInstance().forData(imageBytes).createForSingleSessionOnDisk(AppDependencies.application)
val firstPreUpload = createAttachment(1, blob, AttachmentTable.TransformProperties.empty())
val firstPreUpload = createAttachment(1, blob, TransformProperties.empty())
val firstDatabaseAttachment = SignalDatabase.attachments.insertAttachmentForPreUpload(firstPreUpload)
val firstCompressionJob: AttachmentCompressionJob = AttachmentCompressionJob.fromAttachment(firstDatabaseAttachment, false, -1)
@@ -62,7 +63,7 @@ class AttachmentCompressionJobTest {
}
jobThread.start()
val secondPreUpload = createAttachment(1, blob, AttachmentTable.TransformProperties.forSentMediaQuality(Optional.empty(), SentMediaQuality.HIGH))
val secondPreUpload = createAttachment(1, blob, transformPropertiesForSentMediaQuality(Optional.empty(), SentMediaQuality.HIGH))
val secondDatabaseAttachment = SignalDatabase.attachments.insertAttachmentForPreUpload(secondPreUpload)
secondCompressionJob = AttachmentCompressionJob.fromAttachment(secondDatabaseAttachment, false, -1)
@@ -74,7 +75,7 @@ class AttachmentCompressionJobTest {
assertThat(secondJobResult!!.isSuccess).isTrue()
}
private fun createAttachment(id: Long, uri: Uri, transformProperties: AttachmentTable.TransformProperties): UriAttachment {
private fun createAttachment(id: Long, uri: Uri, transformProperties: TransformProperties): UriAttachment {
return UriAttachmentBuilder.build(
id,
uri = uri,

View File

@@ -10,9 +10,9 @@ import io.mockk.every
import io.mockk.mockkStatic
import io.mockk.slot
import io.mockk.unmockkStatic
import org.signal.core.models.media.TransformProperties
import org.thoughtcrime.securesms.attachments.Attachment
import org.thoughtcrime.securesms.attachments.UriAttachment
import org.thoughtcrime.securesms.database.AttachmentTable
import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.database.UriAttachmentBuilder
import org.thoughtcrime.securesms.database.model.GroupsV2UpdateMessageConverter
@@ -126,7 +126,7 @@ class MessageHelper(private val harness: SignalActivityRule, var startTime: Long
id = Random.nextLong(),
uri = uri,
contentType = MediaUtil.IMAGE_JPEG,
transformProperties = AttachmentTable.TransformProperties(),
transformProperties = TransformProperties(),
uuid = uuid
)

View File

@@ -8,11 +8,11 @@ import android.net.Uri
import android.os.Parcel
import android.os.Parcelable
import androidx.core.os.ParcelCompat
import org.signal.core.models.media.TransformProperties
import org.signal.core.util.UuidUtil
import org.thoughtcrime.securesms.audio.AudioHash
import org.thoughtcrime.securesms.blurhash.BlurHash
import org.thoughtcrime.securesms.database.AttachmentTable
import org.thoughtcrime.securesms.database.AttachmentTable.TransformProperties
import org.thoughtcrime.securesms.stickers.StickerLocator
import org.thoughtcrime.securesms.util.ParcelUtil
import java.util.UUID

View File

@@ -3,10 +3,10 @@ package org.thoughtcrime.securesms.attachments
import android.net.Uri
import android.os.Parcel
import androidx.core.os.ParcelCompat
import org.signal.core.models.media.TransformProperties
import org.thoughtcrime.securesms.audio.AudioHash
import org.thoughtcrime.securesms.blurhash.BlurHash
import org.thoughtcrime.securesms.database.AttachmentTable
import org.thoughtcrime.securesms.database.AttachmentTable.TransformProperties
import org.thoughtcrime.securesms.mms.PartAuthority
import org.thoughtcrime.securesms.stickers.StickerLocator
import org.thoughtcrime.securesms.util.ParcelUtil

View File

@@ -3,9 +3,9 @@ package org.thoughtcrime.securesms.attachments
import android.net.Uri
import android.os.Parcel
import androidx.core.os.ParcelCompat
import org.signal.core.models.media.TransformProperties
import org.thoughtcrime.securesms.audio.AudioHash
import org.thoughtcrime.securesms.blurhash.BlurHash
import org.thoughtcrime.securesms.database.AttachmentTable.TransformProperties
import org.thoughtcrime.securesms.stickers.StickerLocator
import java.util.Objects
import java.util.UUID

View File

@@ -6,8 +6,8 @@
package org.thoughtcrime.securesms.attachments
import android.os.Parcel
import org.signal.core.models.media.TransformProperties
import org.thoughtcrime.securesms.database.AttachmentTable
import org.thoughtcrime.securesms.database.AttachmentTable.TransformProperties
import org.thoughtcrime.securesms.util.MediaUtil
/**

View File

@@ -3,8 +3,8 @@ package org.thoughtcrime.securesms.avatar
import android.content.Context
import android.net.Uri
import android.webkit.MimeTypeMap
import org.signal.core.models.media.Media
import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mms.PartAuthority
import org.thoughtcrime.securesms.util.MediaUtil
import org.thoughtcrime.securesms.util.storage.FileStorage

View File

@@ -9,8 +9,8 @@ import android.net.Uri
import androidx.annotation.MainThread
import androidx.appcompat.content.res.AppCompatResources
import com.airbnb.lottie.SimpleColorFilter
import org.signal.core.models.media.Media
import org.signal.core.util.concurrent.SignalExecutors
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mms.PartAuthority
import org.thoughtcrime.securesms.profiles.AvatarHelper
import org.thoughtcrime.securesms.providers.BlobProvider

View File

@@ -16,6 +16,7 @@ import androidx.fragment.app.setFragmentResultListener
import androidx.fragment.app.viewModels
import androidx.navigation.Navigation
import androidx.recyclerview.widget.RecyclerView
import org.signal.core.models.media.Media
import org.signal.core.util.ThreadUtil
import org.signal.core.util.getParcelableExtraCompat
import org.thoughtcrime.securesms.R
@@ -28,7 +29,6 @@ import org.thoughtcrime.securesms.avatar.vector.VectorAvatarCreationFragment
import org.thoughtcrime.securesms.components.ButtonStripItemView
import org.thoughtcrime.securesms.components.recyclerview.GridDividerDecoration
import org.thoughtcrime.securesms.mediasend.AvatarSelectionActivity
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mediasend.camerax.CameraXUtil
import org.thoughtcrime.securesms.permissions.Permissions
import org.thoughtcrime.securesms.util.ViewUtil

View File

@@ -4,6 +4,7 @@ import android.content.Context
import android.net.Uri
import android.widget.Toast
import io.reactivex.rxjava3.core.Single
import org.signal.core.models.media.Media
import org.signal.core.util.StreamUtil
import org.signal.core.util.ThreadUtil
import org.signal.core.util.concurrent.SignalExecutors
@@ -16,7 +17,6 @@ import org.thoughtcrime.securesms.avatar.Avatars
import org.thoughtcrime.securesms.conversation.colors.AvatarColor
import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.groups.GroupId
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.profiles.AvatarHelper
import org.thoughtcrime.securesms.providers.BlobProvider
import org.thoughtcrime.securesms.recipients.Recipient

View File

@@ -6,9 +6,9 @@ import androidx.lifecycle.ViewModelProvider
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.schedulers.Schedulers
import org.signal.core.models.media.Media
import org.thoughtcrime.securesms.avatar.Avatar
import org.thoughtcrime.securesms.groups.GroupId
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.util.livedata.Store
sealed class AvatarPickerViewModel(private val repository: AvatarPickerRepository) : ViewModel() {

View File

@@ -13,8 +13,8 @@ import android.view.WindowManager
import androidx.activity.result.contract.ActivityResultContract
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import org.signal.core.models.media.Media
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mediasend.v2.gallery.MediaGalleryFragment
/**

View File

@@ -22,7 +22,7 @@ import com.google.android.material.button.MaterialButton;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.animation.AnimationCompleteListener;
import org.thoughtcrime.securesms.components.InputAwareLayout;
import org.thoughtcrime.securesms.mediasend.Media;
import org.signal.core.models.media.Media;
import org.thoughtcrime.securesms.util.StorageUtil;
import java.util.Arrays;

View File

@@ -12,7 +12,7 @@ import com.bumptech.glide.RequestManager;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.ThumbnailView;
import org.thoughtcrime.securesms.mediasend.Media;
import org.signal.core.models.media.Media;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.adapter.StableIdGenerator;

View File

@@ -9,10 +9,10 @@ import android.os.Parcelable
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
import kotlinx.serialization.Serializable
import org.signal.core.models.media.Media
import org.thoughtcrime.securesms.badges.models.Badge
import org.thoughtcrime.securesms.conversation.ConversationIntents.ConversationScreenType
import org.thoughtcrime.securesms.conversation.colors.ChatColors
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mms.SlideFactory
import org.thoughtcrime.securesms.recipients.Recipient.Companion.resolved
import org.thoughtcrime.securesms.recipients.RecipientId

View File

@@ -14,7 +14,7 @@ import org.thoughtcrime.securesms.badges.models.Badge;
import org.thoughtcrime.securesms.conversation.v2.ConversationActivity;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.database.ThreadTable;
import org.thoughtcrime.securesms.mediasend.Media;
import org.signal.core.models.media.Media;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.stickers.StickerLocator;

View File

@@ -6,6 +6,7 @@ import android.text.Spannable
import android.text.SpannableString
import io.reactivex.rxjava3.core.Maybe
import io.reactivex.rxjava3.schedulers.Schedulers
import org.signal.core.models.media.Media
import org.signal.core.util.Base64
import org.signal.core.util.StreamUtil
import org.signal.core.util.concurrent.MaybeCompat
@@ -31,7 +32,6 @@ import org.thoughtcrime.securesms.database.model.MmsMessageRecord
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.keyboard.KeyboardUtil
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mms.GifSlide
import org.thoughtcrime.securesms.mms.ImageSlide
import org.thoughtcrime.securesms.mms.PartAuthority

View File

@@ -7,6 +7,7 @@ import androidx.annotation.ColorInt
import androidx.annotation.StringRes
import androidx.annotation.WorkerThread
import kotlinx.parcelize.Parcelize
import org.signal.core.models.media.Media
import org.signal.core.util.StreamUtil
import org.signal.core.util.ThreadUtil
import org.signal.core.util.concurrent.SignalExecutors
@@ -18,7 +19,6 @@ import org.thoughtcrime.securesms.conversation.MessageStyler
import org.thoughtcrime.securesms.conversation.mutiselect.MultiselectPart
import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mms.PartAuthority
import org.thoughtcrime.securesms.sharing.MultiShareArgs
import org.thoughtcrime.securesms.stories.Stories

View File

@@ -16,6 +16,7 @@ import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContract
import androidx.core.content.IntentCompat
import androidx.fragment.app.Fragment
import org.signal.core.models.media.Media
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.location.SignalPlace
@@ -26,7 +27,6 @@ import org.thoughtcrime.securesms.conversation.colors.ChatColors
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityResultContracts.Callbacks
import org.thoughtcrime.securesms.giph.ui.GiphyActivity
import org.thoughtcrime.securesms.maps.PlacePickerActivity
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mediasend.MediaSendActivityResult
import org.thoughtcrime.securesms.mediasend.camerax.CameraXUtil
import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionActivity

View File

@@ -100,6 +100,8 @@ import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import org.signal.core.models.media.Media
import org.signal.core.models.media.TransformProperties
import org.signal.core.util.ByteLimitInputFilter
import org.signal.core.util.PendingIntentFlags
import org.signal.core.util.Result
@@ -228,7 +230,6 @@ import org.thoughtcrime.securesms.conversation.v2.groups.ConversationGroupViewMo
import org.thoughtcrime.securesms.conversation.v2.items.ChatColorsDrawable
import org.thoughtcrime.securesms.conversation.v2.items.InteractiveConversationElement
import org.thoughtcrime.securesms.conversation.v2.keyboard.AttachmentKeyboardFragment
import org.thoughtcrime.securesms.database.AttachmentTable
import org.thoughtcrime.securesms.database.DraftTable
import org.thoughtcrime.securesms.database.model.IdentityRecord
import org.thoughtcrime.securesms.database.model.InMemoryMessageRecord
@@ -279,7 +280,6 @@ import org.thoughtcrime.securesms.main.MainSnackbarHostKey
import org.thoughtcrime.securesms.mediaoverview.MediaOverviewActivity
import org.thoughtcrime.securesms.mediapreview.MediaIntentFactory
import org.thoughtcrime.securesms.mediapreview.MediaPreviewV2Activity
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mediasend.MediaSendActivityResult
import org.thoughtcrime.securesms.messagedetails.MessageDetailsFragment
import org.thoughtcrime.securesms.messagerequests.MessageRequestRepository
@@ -1487,7 +1487,7 @@ class ConversationFragment :
isVideoGif = videoGif,
bucketId = null,
caption = null,
transformProperties = AttachmentTable.TransformProperties.forSentMediaQuality(SignalStore.settings.sentMediaQuality.code),
transformProperties = TransformProperties.forSentMediaQuality(SignalStore.settings.sentMediaQuality.code),
fileName = null
)
conversationActivityResultContracts.launchMediaEditor(listOf(media), recipientId, composeText.textTrimmed)

View File

@@ -14,6 +14,7 @@ import androidx.fragment.app.viewModels
import androidx.lifecycle.ViewModelProvider
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.kotlin.subscribeBy
import org.signal.core.models.media.Media
import org.signal.core.util.concurrent.LifecycleDisposable
import org.signal.core.util.concurrent.addTo
import org.thoughtcrime.securesms.LoggingFragment
@@ -23,7 +24,6 @@ import org.thoughtcrime.securesms.conversation.AttachmentKeyboardButton
import org.thoughtcrime.securesms.conversation.ManageContextMenu
import org.thoughtcrime.securesms.conversation.v2.ConversationViewModel
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.permissions.PermissionCompat
import org.thoughtcrime.securesms.permissions.Permissions
import org.thoughtcrime.securesms.recipients.Recipient

View File

@@ -9,7 +9,7 @@ import androidx.lifecycle.ViewModel
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.subjects.BehaviorSubject
import org.thoughtcrime.securesms.mediasend.Media
import org.signal.core.models.media.Media
import org.thoughtcrime.securesms.mediasend.MediaRepository
class AttachmentKeyboardViewModel(

View File

@@ -20,21 +20,17 @@ import android.content.ContentValues
import android.content.Context
import android.database.Cursor
import android.media.MediaDataSource
import android.os.Parcelable
import android.text.TextUtils
import androidx.annotation.VisibleForTesting
import androidx.annotation.WorkerThread
import androidx.core.content.contentValuesOf
import com.bumptech.glide.Glide
import com.fasterxml.jackson.annotation.JsonProperty
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
import kotlinx.serialization.Serializable
import okio.ByteString.Companion.toByteString
import org.json.JSONArray
import org.json.JSONException
import org.signal.core.models.backup.MediaId
import org.signal.core.models.backup.MediaName
import org.signal.core.models.media.TransformProperties
import org.signal.core.util.Base64
import org.signal.core.util.SqlUtil
import org.signal.core.util.ThreadUtil
@@ -110,7 +106,6 @@ import org.thoughtcrime.securesms.mms.DecryptableUri
import org.thoughtcrime.securesms.mms.MediaStream
import org.thoughtcrime.securesms.mms.MmsException
import org.thoughtcrime.securesms.mms.PartAuthority
import org.thoughtcrime.securesms.mms.SentMediaQuality
import org.thoughtcrime.securesms.stickers.StickerLocator
import org.thoughtcrime.securesms.util.BitmapDecodingException
import org.thoughtcrime.securesms.util.FileUtils
@@ -124,7 +119,6 @@ import org.thoughtcrime.securesms.video.EncryptedMediaDataSource
import org.whispersystems.signalservice.api.attachment.AttachmentUploadResult
import org.whispersystems.signalservice.api.crypto.AttachmentCipherStreamUtil
import org.whispersystems.signalservice.internal.crypto.PaddingInputStream
import org.whispersystems.signalservice.internal.util.JsonUtil
import java.io.ByteArrayInputStream
import java.io.File
import java.io.FileNotFoundException
@@ -134,7 +128,6 @@ import java.security.DigestInputStream
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
import java.util.LinkedList
import java.util.Optional
import java.util.UUID
import kotlin.text.appendLine
import kotlin.time.Duration
@@ -2256,7 +2249,7 @@ class AttachmentTable(
.where("$ID = ?", attachmentId.id)
.run()
.readToSingleObject {
TransformProperties.parse(it.requireString(TRANSFORM_PROPERTIES))
parseTransformProperties(it.requireString(TRANSFORM_PROPERTIES))
}
}
@@ -2323,7 +2316,7 @@ class AttachmentTable(
},
blurHash = if (MediaUtil.isAudioType(contentType)) null else BlurHash.parseOrNull(jsonObject.getString(BLUR_HASH)),
audioHash = if (MediaUtil.isAudioType(contentType)) AudioHash.parseOrNull(jsonObject.getString(BLUR_HASH)) else null,
transformProperties = TransformProperties.parse(jsonObject.getString(TRANSFORM_PROPERTIES)),
transformProperties = parseTransformProperties(jsonObject.getString(TRANSFORM_PROPERTIES)),
displayOrder = jsonObject.getInt(DISPLAY_ORDER),
uploadTimestamp = jsonObject.getLong(UPLOAD_TIMESTAMP),
dataHash = jsonObject.getString(DATA_HASH_END),
@@ -3369,7 +3362,7 @@ class AttachmentTable(
stickerLocator = cursor.readStickerLocator(),
blurHash = if (MediaUtil.isAudioType(contentType)) null else BlurHash.parseOrNull(cursor.requireString(BLUR_HASH)),
audioHash = if (MediaUtil.isAudioType(contentType)) AudioHash.parseOrNull(cursor.requireString(BLUR_HASH)) else null,
transformProperties = TransformProperties.parse(cursor.requireString(TRANSFORM_PROPERTIES)),
transformProperties = parseTransformProperties(cursor.requireString(TRANSFORM_PROPERTIES)),
displayOrder = cursor.requireInt(DISPLAY_ORDER),
uploadTimestamp = cursor.requireLong(UPLOAD_TIMESTAMP),
dataHash = cursor.requireString(DATA_HASH_END),
@@ -3400,7 +3393,7 @@ class AttachmentTable(
random = random,
hashStart = this.requireString(DATA_HASH_START),
hashEnd = this.requireString(DATA_HASH_END),
transformProperties = TransformProperties.parse(this.requireString(TRANSFORM_PROPERTIES)),
transformProperties = parseTransformProperties(this.requireString(TRANSFORM_PROPERTIES)),
uploadTimestamp = this.requireLong(UPLOAD_TIMESTAMP),
archiveCdn = this.requireIntOrNull(ARCHIVE_CDN),
archiveTransferState = this.requireInt(ARCHIVE_TRANSFER_STATE),
@@ -3545,7 +3538,9 @@ class AttachmentTable(
.readToSingleLong(0)
}
val uniqueEligibleMediaNamesWithThumbnailsCount = readableDatabase.query("SELECT COUNT(*) FROM (SELECT DISTINCT $DATA_HASH_END, $REMOTE_KEY FROM $TABLE_NAME WHERE $DATA_HASH_END NOT NULL AND $REMOTE_KEY NOT NULL AND $THUMBNAIL_FILE NOT NULL AND $QUOTE = 0 AND $MESSAGE_ID != $WALLPAPER_MESSAGE_ID)").readToSingleLong(-1L)
val uniqueEligibleMediaNamesWithThumbnailsCount =
readableDatabase.query("SELECT COUNT(*) FROM (SELECT DISTINCT $DATA_HASH_END, $REMOTE_KEY FROM $TABLE_NAME WHERE $DATA_HASH_END NOT NULL AND $REMOTE_KEY NOT NULL AND $THUMBNAIL_FILE NOT NULL AND $QUOTE = 0 AND $MESSAGE_ID != $WALLPAPER_MESSAGE_ID)")
.readToSingleLong(-1L)
val archiveStatusMediaNameThumbnailCounts: Map<ArchiveTransferState, Long> = ArchiveTransferState.entries.associateWith { state ->
readableDatabase.query(
"""
@@ -3802,119 +3797,6 @@ class AttachmentTable(
val random: ByteArray
)
@Serializable
@Parcelize
data class TransformProperties(
@JsonProperty("skipTransform")
@JvmField
val skipTransform: Boolean = false,
@JsonProperty("videoTrim")
@JvmField
val videoTrim: Boolean = false,
@JsonProperty("videoTrimStartTimeUs")
@JvmField
val videoTrimStartTimeUs: Long = 0,
@JsonProperty("videoTrimEndTimeUs")
@JvmField
val videoTrimEndTimeUs: Long = 0,
@JsonProperty("sentMediaQuality")
@JvmField
val sentMediaQuality: Int = SentMediaQuality.STANDARD.code,
@JsonProperty("mp4Faststart")
@JvmField
val mp4FastStart: Boolean = false
) : Parcelable {
fun shouldSkipTransform(): Boolean {
return skipTransform
}
@IgnoredOnParcel
@JsonProperty("videoEdited")
val videoEdited: Boolean = videoTrim
fun withSkipTransform(): TransformProperties {
return this.copy(
skipTransform = true
)
}
fun withMp4FastStart(): TransformProperties {
return this.copy(mp4FastStart = true)
}
fun serialize(): String {
return JsonUtil.toJson(this)
}
companion object {
private val DEFAULT_MEDIA_QUALITY = SentMediaQuality.STANDARD.code
@JvmStatic
fun empty(): TransformProperties {
return TransformProperties(
skipTransform = false,
videoTrim = false,
videoTrimStartTimeUs = 0,
videoTrimEndTimeUs = 0,
sentMediaQuality = DEFAULT_MEDIA_QUALITY,
mp4FastStart = false
)
}
fun forSkipTransform(): TransformProperties {
return TransformProperties(
skipTransform = true,
videoTrim = false,
videoTrimStartTimeUs = 0,
videoTrimEndTimeUs = 0,
sentMediaQuality = DEFAULT_MEDIA_QUALITY,
mp4FastStart = false
)
}
fun forVideoTrim(videoTrimStartTimeUs: Long, videoTrimEndTimeUs: Long): TransformProperties {
return TransformProperties(
skipTransform = false,
videoTrim = true,
videoTrimStartTimeUs = videoTrimStartTimeUs,
videoTrimEndTimeUs = videoTrimEndTimeUs,
sentMediaQuality = DEFAULT_MEDIA_QUALITY,
mp4FastStart = false
)
}
@JvmStatic
fun forSentMediaQuality(currentProperties: Optional<TransformProperties>, sentMediaQuality: SentMediaQuality): TransformProperties {
val existing = currentProperties.orElse(empty())
return existing.copy(sentMediaQuality = sentMediaQuality.code)
}
@JvmStatic
fun forSentMediaQuality(sentMediaQuality: Int): TransformProperties {
return TransformProperties(sentMediaQuality = sentMediaQuality)
}
@JvmStatic
fun parse(serialized: String?): TransformProperties {
return if (serialized == null) {
empty()
} else {
try {
JsonUtil.fromJson(serialized, TransformProperties::class.java)
} catch (e: IOException) {
Log.w(TAG, "Failed to parse TransformProperties!", e)
empty()
}
}
}
}
}
enum class ThumbnailRestoreState(val value: Int) {
/** No thumbnail downloaded. */
NONE(0),

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2025 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.database
import org.signal.core.models.media.TransformProperties
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.mms.SentMediaQuality
import org.whispersystems.signalservice.internal.util.JsonUtil
import java.io.IOException
import java.util.Optional
private val TAG = Log.tag(TransformProperties::class.java)
/**
* Serializes the TransformProperties to a JSON string using Jackson.
*/
fun TransformProperties.serialize(): String {
return JsonUtil.toJson(this)
}
/**
* Parses a JSON string to create a TransformProperties instance.
*/
fun parseTransformProperties(serialized: String?): TransformProperties {
return if (serialized == null) {
TransformProperties.empty()
} else {
try {
JsonUtil.fromJson(serialized, TransformProperties::class.java)
} catch (e: IOException) {
Log.w(TAG, "Failed to parse TransformProperties!", e)
TransformProperties.empty()
}
}
}
/**
* Creates TransformProperties for the given media quality, preserving existing properties.
*/
fun transformPropertiesForSentMediaQuality(currentProperties: Optional<TransformProperties>, sentMediaQuality: SentMediaQuality): TransformProperties {
val existing = currentProperties.orElse(TransformProperties.empty())
return existing.copy(sentMediaQuality = sentMediaQuality.code)
}

View File

@@ -19,7 +19,7 @@ import org.thoughtcrime.securesms.giph.mp4.GiphyMp4Fragment;
import org.thoughtcrime.securesms.giph.mp4.GiphyMp4SaveResult;
import org.thoughtcrime.securesms.giph.mp4.GiphyMp4ViewModel;
import org.thoughtcrime.securesms.keyboard.emoji.KeyboardPageSearchView;
import org.thoughtcrime.securesms.mediasend.Media;
import org.signal.core.models.media.Media;
import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionActivity;
import org.thoughtcrime.securesms.mms.SlideFactory;
import org.thoughtcrime.securesms.providers.BlobProvider;

View File

@@ -38,7 +38,7 @@ import org.thoughtcrime.securesms.avatar.picker.AvatarPickerFragment;
import org.thoughtcrime.securesms.components.settings.app.privacy.expire.ExpireTimerSettingsFragment;
import org.thoughtcrime.securesms.groups.ui.GroupMemberListView;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.mediasend.Media;
import org.signal.core.models.media.Media;
import org.thoughtcrime.securesms.mms.DecryptableUri;
import org.thoughtcrime.securesms.profiles.AvatarHelper;
import org.thoughtcrime.securesms.recipients.Recipient;

View File

@@ -15,7 +15,7 @@ import com.annimon.stream.Stream;
import org.thoughtcrime.securesms.groups.ui.GroupMemberEntry;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.mediasend.Media;
import org.signal.core.models.media.Media;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.DefaultValueLiveData;
import org.thoughtcrime.securesms.util.SingleLiveEvent;

View File

@@ -19,6 +19,7 @@ import org.thoughtcrime.securesms.crypto.AttachmentSecret;
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider;
import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream;
import org.thoughtcrime.securesms.crypto.ModernEncryptingPartOutputStream;
import org.signal.core.models.media.TransformProperties;
import org.thoughtcrime.securesms.database.AttachmentTable;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.events.PartProgressEvent;
@@ -149,11 +150,11 @@ public final class AttachmentCompressionJob extends BaseJob {
throw new UndeliverableMessageException("Cannot find the specified attachment.");
}
AttachmentTable.TransformProperties transformProperties = databaseAttachment.transformProperties;
TransformProperties transformProperties = databaseAttachment.transformProperties;
if (transformProperties == null) {
Log.i(TAG, "TransformProperties were null! Using empty TransformProperties.");
transformProperties = AttachmentTable.TransformProperties.empty();
transformProperties = TransformProperties.empty();
}
if (transformProperties.shouldSkipTransform()) {
@@ -227,7 +228,7 @@ public final class AttachmentCompressionJob extends BaseJob {
throw new UndeliverableMessageException("Job is canceled!");
}
AttachmentTable.TransformProperties transformProperties = attachment.transformProperties;
TransformProperties transformProperties = attachment.transformProperties;
boolean allowSkipOnFailure = false;

View File

@@ -3,11 +3,11 @@ package org.thoughtcrime.securesms.mediapreview
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import androidx.viewpager2.adapter.FragmentStateAdapter
import org.signal.core.models.media.Media
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.attachments.Attachment
import org.thoughtcrime.securesms.attachments.DatabaseAttachment
import org.thoughtcrime.securesms.jobs.AttachmentDownloadJob
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.util.MediaUtil
import org.thoughtcrime.securesms.util.adapter.StableIdGenerator

View File

@@ -40,6 +40,7 @@ import io.reactivex.rxjava3.kotlin.subscribeBy
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import org.signal.core.models.media.Media
import org.signal.core.util.concurrent.LifecycleDisposable
import org.signal.core.util.concurrent.addTo
import org.signal.core.util.logging.Log
@@ -61,7 +62,6 @@ import org.thoughtcrime.securesms.mediapreview.caption.ExpandingCaptionView
import org.thoughtcrime.securesms.mediapreview.mediarail.CenterDecoration
import org.thoughtcrime.securesms.mediapreview.mediarail.MediaRailAdapter
import org.thoughtcrime.securesms.mediapreview.mediarail.MediaRailAdapter.ImageLoadingListener
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionActivity
import org.thoughtcrime.securesms.mms.PartAuthority
import org.thoughtcrime.securesms.recipients.Recipient

View File

@@ -1,8 +1,8 @@
package org.thoughtcrime.securesms.mediapreview
import android.text.SpannableString
import org.signal.core.models.media.Media
import org.thoughtcrime.securesms.database.MediaTable
import org.thoughtcrime.securesms.mediasend.Media
data class MediaPreviewV2State(
val mediaRecords: List<MediaTable.MediaRecord> = emptyList(),

View File

@@ -18,6 +18,7 @@ import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import io.reactivex.rxjava3.schedulers.Schedulers
import org.signal.core.models.media.Media
import org.signal.core.util.PendingIntentFlags
import org.signal.core.util.concurrent.SignalExecutors
import org.signal.core.util.logging.Log
@@ -28,7 +29,6 @@ import org.thoughtcrime.securesms.database.MediaTable
import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.logsubmit.SubmitDebugLogActivity
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mms.PartUriParser
import org.thoughtcrime.securesms.notifications.NotificationChannels
import org.thoughtcrime.securesms.notifications.NotificationIds

View File

@@ -8,9 +8,9 @@ import com.bumptech.glide.RequestManager
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.request.target.Target
import org.signal.core.models.media.Media
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.ThumbnailView
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
import org.thoughtcrime.securesms.util.adapter.mapping.MappingModel
import org.thoughtcrime.securesms.util.adapter.mapping.MappingViewHolder

View File

@@ -15,6 +15,7 @@ import androidx.appcompat.app.AppCompatDelegate;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import org.signal.core.models.media.Media;
import org.signal.imageeditor.core.model.EditorModel;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.mediasend.v2.gallery.MediaGalleryFragment;

View File

@@ -42,6 +42,7 @@ import com.google.android.material.card.MaterialCardView;
import org.signal.core.util.Stopwatch;
import org.signal.core.util.logging.Log;
import org.signal.core.models.media.Media;
import org.thoughtcrime.securesms.LoggingFragment;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.animation.AnimationCompleteListener;

View File

@@ -8,6 +8,7 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import org.signal.core.models.media.Media;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.mediasend.camerax.CameraXUtil;
import org.thoughtcrime.securesms.mms.MediaConstraints;

View File

@@ -48,6 +48,7 @@ import com.google.common.util.concurrent.ListenableFuture;
import org.signal.core.util.Stopwatch;
import org.signal.core.util.concurrent.SimpleTask;
import org.signal.core.util.logging.Log;
import org.signal.core.models.media.Media;
import org.signal.qr.QrProcessor;
import org.thoughtcrime.securesms.LoggingFragment;
import org.thoughtcrime.securesms.R;

View File

@@ -4,6 +4,8 @@ import android.content.Context;
import androidx.annotation.NonNull;
import org.signal.core.models.media.Media;
/**
* Allow multiple transforms to operate on {@link Media}. Care should
* be taken on the order and implementation of combined transformers to prevent

View File

@@ -11,6 +11,7 @@ import androidx.annotation.WorkerThread;
import org.signal.core.util.StreamUtil;
import org.signal.core.util.logging.Log;
import org.signal.core.models.media.Media;
import org.signal.imageeditor.core.model.EditorModel;
import org.thoughtcrime.securesms.fonts.FontTypefaceProvider;
import org.thoughtcrime.securesms.providers.BlobProvider;

View File

@@ -21,6 +21,8 @@ import com.annimon.stream.Stream;
import org.signal.core.util.concurrent.SignalExecutors;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.R;
import org.signal.core.models.media.Media;
import org.signal.core.models.media.TransformProperties;
import org.thoughtcrime.securesms.database.AttachmentTable;
import org.thoughtcrime.securesms.dependencies.AppDependencies;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
@@ -277,7 +279,7 @@ public class MediaRepository {
long size = cursor.getLong(cursor.getColumnIndexOrThrow(Images.Media.SIZE));
long duration = !isImage ? cursor.getInt(cursor.getColumnIndexOrThrow(Video.Media.DURATION)) : 0;
media.add(fixMimeType(context, new Media(uri, mimetype, date, width, height, size, duration, false, false, bucketId, null, AttachmentTable.TransformProperties.forSentMediaQuality(SignalStore.settings().getSentMediaQuality().getCode()), null)));
media.add(fixMimeType(context, new Media(uri, mimetype, date, width, height, size, duration, false, false, bucketId, null, TransformProperties.forSentMediaQuality(SignalStore.settings().getSentMediaQuality().getCode()), null)));
}
}

View File

@@ -6,6 +6,7 @@ import android.os.Parcelable
import kotlinx.parcelize.Parceler
import kotlinx.parcelize.Parcelize
import kotlinx.parcelize.TypeParceler
import org.signal.core.models.media.Media
import org.signal.core.util.getParcelableExtraCompat
import org.thoughtcrime.securesms.conversation.MessageSendType
import org.thoughtcrime.securesms.database.model.Mention

View File

@@ -8,6 +8,7 @@ import android.view.View
import android.widget.TextView
import android.widget.Toast
import androidx.fragment.app.Fragment
import org.signal.core.models.media.Media
import org.signal.core.util.bytes
import org.signal.core.util.getParcelableCompat
import org.signal.core.util.logging.Log

View File

@@ -5,6 +5,8 @@ import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.WorkerThread;
import org.signal.core.models.media.Media;
public interface MediaTransform {
@WorkerThread

View File

@@ -14,7 +14,8 @@ import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.AttachmentId;
import org.thoughtcrime.securesms.database.AttachmentTable;
import org.thoughtcrime.securesms.database.AttachmentTable.TransformProperties;
import org.signal.core.models.media.Media;
import org.signal.core.models.media.TransformProperties;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.dependencies.AppDependencies;
import org.thoughtcrime.securesms.jobmanager.JobManager;

View File

@@ -5,14 +5,17 @@ import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.WorkerThread;
import org.thoughtcrime.securesms.database.AttachmentTable;
import org.signal.core.models.media.Media;
import org.signal.core.models.media.TransformProperties;
import org.thoughtcrime.securesms.mms.SentMediaQuality;
import java.util.Optional;
import static org.thoughtcrime.securesms.database.TransformPropertiesUtilKt.transformPropertiesForSentMediaQuality;
/**
* Add a {@link SentMediaQuality} value for {@link AttachmentTable.TransformProperties#getSentMediaQuality()} on the
* Add a {@link SentMediaQuality} value for {@link TransformProperties#getSentMediaQuality()} on the
* transformed media. Safe to use in a pipeline with other transforms.
*/
public final class SentMediaQualityTransform implements MediaTransform {
@@ -37,7 +40,7 @@ public final class SentMediaQualityTransform implements MediaTransform {
media.isVideoGif(),
media.getBucketId(),
media.getCaption(),
AttachmentTable.TransformProperties.forSentMediaQuality(Optional.ofNullable(media.getTransformProperties()), sentMediaQuality),
transformPropertiesForSentMediaQuality(Optional.ofNullable(media.getTransformProperties()), sentMediaQuality),
media.getFileName());
}
}

View File

@@ -2,7 +2,8 @@ package org.thoughtcrime.securesms.mediasend
import android.content.Context
import androidx.annotation.WorkerThread
import org.thoughtcrime.securesms.database.AttachmentTable.TransformProperties
import org.signal.core.models.media.Media
import org.signal.core.models.media.TransformProperties
import org.thoughtcrime.securesms.mediasend.v2.videos.VideoTrimData
import org.thoughtcrime.securesms.mms.SentMediaQuality

View File

@@ -1,9 +1,9 @@
package org.thoughtcrime.securesms.mediasend.v2
import android.net.Uri
import org.signal.core.models.media.Media
import org.signal.core.models.media.TransformProperties
import org.signal.core.util.orNull
import org.thoughtcrime.securesms.database.AttachmentTable
import org.thoughtcrime.securesms.mediasend.Media
import java.util.Optional
object MediaBuilder {
@@ -19,7 +19,7 @@ object MediaBuilder {
videoGif: Boolean = false,
bucketId: Optional<String> = Optional.empty(),
caption: Optional<String> = Optional.empty(),
transformProperties: Optional<AttachmentTable.TransformProperties> = Optional.empty(),
transformProperties: Optional<TransformProperties> = Optional.empty(),
fileName: Optional<String> = Optional.empty()
) = Media(uri, mimeType, date, width, height, size, duration, borderless, videoGif, bucketId.orNull(), caption.orNull(), transformProperties.orNull(), fileName.orNull())
}

View File

@@ -23,6 +23,7 @@ import androidx.transition.AutoTransition
import androidx.transition.TransitionManager
import com.google.android.material.animation.ArgbEvaluatorCompat
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import org.signal.core.models.media.Media
import org.signal.core.util.BreakIteratorCompat
import org.signal.core.util.OVERRIDE_TRANSITION_CLOSE_COMPAT
import org.signal.core.util.concurrent.LifecycleDisposable
@@ -39,7 +40,6 @@ import org.thoughtcrime.securesms.keyboard.emoji.EmojiKeyboardPageFragment
import org.thoughtcrime.securesms.keyboard.emoji.search.EmojiSearchFragment
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil
import org.thoughtcrime.securesms.mediasend.CameraDisplay
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mediasend.MediaSendActivityResult
import org.thoughtcrime.securesms.mediasend.v2.review.MediaReviewFragment
import org.thoughtcrime.securesms.mediasend.v2.text.TextStoryPostCreationViewModel

View File

@@ -7,13 +7,14 @@ import io.reactivex.rxjava3.core.Maybe
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.schedulers.Schedulers
import org.signal.core.models.media.Media
import org.signal.core.models.media.TransformProperties
import org.signal.core.util.BreakIteratorCompat
import org.signal.core.util.ThreadUtil
import org.signal.core.util.logging.Log
import org.signal.imageeditor.core.model.EditorModel
import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey
import org.thoughtcrime.securesms.conversation.MessageSendType
import org.thoughtcrime.securesms.database.AttachmentTable.TransformProperties
import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.database.model.Mention
import org.thoughtcrime.securesms.database.model.StoryType
@@ -23,7 +24,6 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.keyvalue.StorySend
import org.thoughtcrime.securesms.mediasend.CompositeMediaTransform
import org.thoughtcrime.securesms.mediasend.ImageEditorModelRenderMediaTransform
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mediasend.MediaRepository
import org.thoughtcrime.securesms.mediasend.MediaSendActivityResult
import org.thoughtcrime.securesms.mediasend.MediaTransform

View File

@@ -1,9 +1,9 @@
package org.thoughtcrime.securesms.mediasend.v2
import android.net.Uri
import org.signal.core.models.media.Media
import org.thoughtcrime.securesms.conversation.MessageSendType
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mediasend.v2.videos.VideoTrimData
import org.thoughtcrime.securesms.mms.MediaConstraints
import org.thoughtcrime.securesms.mms.SentMediaQuality

View File

@@ -22,6 +22,7 @@ import io.reactivex.rxjava3.schedulers.Schedulers
import io.reactivex.rxjava3.subjects.BehaviorSubject
import io.reactivex.rxjava3.subjects.PublishSubject
import io.reactivex.rxjava3.subjects.Subject
import org.signal.core.models.media.Media
import org.signal.core.util.BreakIteratorCompat
import org.signal.core.util.getParcelableArrayListCompat
import org.signal.core.util.getParcelableCompat
@@ -30,7 +31,6 @@ import org.thoughtcrime.securesms.components.mention.MentionAnnotation
import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey
import org.thoughtcrime.securesms.conversation.MessageSendType
import org.thoughtcrime.securesms.conversation.MessageStyler
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mediasend.MediaSendActivityResult
import org.thoughtcrime.securesms.mediasend.v2.review.AddMessageCharacterCount
import org.thoughtcrime.securesms.mediasend.v2.videos.VideoTrimData

View File

@@ -2,7 +2,7 @@ package org.thoughtcrime.securesms.mediasend.v2
import android.content.Context
import androidx.annotation.WorkerThread
import org.thoughtcrime.securesms.mediasend.Media
import org.signal.core.models.media.Media
import org.thoughtcrime.securesms.mms.MediaConstraints
import org.thoughtcrime.securesms.stories.Stories
import org.thoughtcrime.securesms.util.MediaUtil

View File

@@ -1,6 +1,6 @@
package org.thoughtcrime.securesms.mediasend.v2.capture
import org.thoughtcrime.securesms.mediasend.Media
import org.signal.core.models.media.Media
import org.thoughtcrime.securesms.recipients.Recipient
sealed interface MediaCaptureEvent {

View File

@@ -9,12 +9,12 @@ import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import io.reactivex.rxjava3.core.Flowable
import org.signal.core.models.media.Media
import org.signal.core.util.concurrent.LifecycleDisposable
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity
import org.thoughtcrime.securesms.mediasend.CameraFragment
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mediasend.v2.HudCommand
import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionNavigator
import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionViewModel

View File

@@ -7,10 +7,10 @@ import android.net.Uri
import android.os.Build
import android.provider.MediaStore
import androidx.annotation.WorkerThread
import org.signal.core.models.media.Media
import org.signal.core.util.CursorUtil
import org.signal.core.util.concurrent.SignalExecutors
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mediasend.MediaRepository
import org.thoughtcrime.securesms.providers.BlobProvider
import org.thoughtcrime.securesms.util.MediaUtil

View File

@@ -1,6 +1,6 @@
package org.thoughtcrime.securesms.mediasend.v2.capture
import org.thoughtcrime.securesms.mediasend.Media
import org.signal.core.models.media.Media
data class MediaCaptureState(
val mostRecentMedia: Media? = null

View File

@@ -10,9 +10,9 @@ import io.reactivex.rxjava3.kotlin.plusAssign
import io.reactivex.rxjava3.schedulers.Schedulers
import io.reactivex.rxjava3.subjects.PublishSubject
import io.reactivex.rxjava3.subjects.Subject
import org.signal.core.models.media.Media
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.profiles.manage.UsernameRepository
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.registration.data.QuickRegistrationRepository

View File

@@ -4,9 +4,9 @@ import android.os.Bundle
import android.view.View
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import org.signal.core.models.media.Media
import org.signal.core.util.getParcelableCompat
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mediasend.MediaSendDocumentFragment
import org.thoughtcrime.securesms.mediasend.v2.HudCommand
import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionViewModel

View File

@@ -15,12 +15,12 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.map
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.ItemTouchHelper
import org.signal.core.models.media.Media
import org.signal.core.util.Stopwatch
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.recyclerview.GridDividerDecoration
import org.thoughtcrime.securesms.conversation.ManageContextMenu
import org.thoughtcrime.securesms.databinding.V2MediaGalleryFragmentBinding
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mediasend.MediaRepository
import org.thoughtcrime.securesms.mediasend.camerax.CameraXUtil
import org.thoughtcrime.securesms.mediasend.v2.review.MediaGalleryGridItemTouchListener

View File

@@ -1,7 +1,7 @@
package org.thoughtcrime.securesms.mediasend.v2.gallery
import android.content.Context
import org.thoughtcrime.securesms.mediasend.Media
import org.signal.core.models.media.Media
import org.thoughtcrime.securesms.mediasend.MediaFolder
import org.thoughtcrime.securesms.mediasend.MediaRepository

View File

@@ -14,10 +14,10 @@ import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target
import com.google.android.material.imageview.ShapeableImageView
import org.signal.core.models.media.Media
import org.signal.core.util.DimensionUnit
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mediasend.MediaFolder
import org.thoughtcrime.securesms.mediasend.v2.review.MediaGalleryGridItemTouchListener
import org.thoughtcrime.securesms.mms.DecryptableUri

View File

@@ -3,8 +3,8 @@ package org.thoughtcrime.securesms.mediasend.v2.gallery
import android.view.View
import android.widget.ImageView
import com.bumptech.glide.Glide
import org.signal.core.models.media.Media
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mms.DecryptableUri
import org.thoughtcrime.securesms.util.MediaUtil
import org.thoughtcrime.securesms.util.adapter.mapping.LayoutFactory

View File

@@ -8,9 +8,9 @@ import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.ItemTouchHelper
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import org.signal.core.models.media.Media
import org.signal.core.util.concurrent.LifecycleDisposable
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionNavigator
import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionNavigator.Companion.requestPermissionsForCamera
import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionViewModel

View File

@@ -31,6 +31,7 @@ import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.imageview.ShapeableImageView
import org.signal.core.models.media.Media
import org.signal.core.util.bytes
import org.signal.core.util.concurrent.LifecycleDisposable
import org.signal.core.util.concurrent.SimpleTask
@@ -44,7 +45,6 @@ import org.thoughtcrime.securesms.conversation.ScheduleMessageTimePickerBottomSh
import org.thoughtcrime.securesms.conversation.mutiselect.forward.MultiselectForwardActivity
import org.thoughtcrime.securesms.conversation.mutiselect.forward.MultiselectForwardFragmentArgs
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mediasend.MediaSendActivityResult
import org.thoughtcrime.securesms.mediasend.v2.HudCommand
import org.thoughtcrime.securesms.mediasend.v2.MediaAnimations

View File

@@ -4,7 +4,7 @@ import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.adapter.FragmentStateAdapter
import org.thoughtcrime.securesms.mediasend.Media
import org.signal.core.models.media.Media
import org.thoughtcrime.securesms.mediasend.v2.documents.MediaReviewDocumentPageFragment
import org.thoughtcrime.securesms.mediasend.v2.gif.MediaReviewGifPageFragment
import org.thoughtcrime.securesms.mediasend.v2.images.MediaReviewImagePageFragment

View File

@@ -3,8 +3,8 @@ package org.thoughtcrime.securesms.mediasend.v2.review
import android.view.View
import android.widget.ImageView
import com.bumptech.glide.Glide
import org.signal.core.models.media.Media
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mms.DecryptableUri
import org.thoughtcrime.securesms.util.MediaUtil
import org.thoughtcrime.securesms.util.adapter.mapping.LayoutFactory

View File

@@ -28,7 +28,7 @@ import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.blurhash.BlurHash;
import org.thoughtcrime.securesms.database.AttachmentTable.TransformProperties;
import org.signal.core.models.media.TransformProperties;
import org.thoughtcrime.securesms.util.MediaUtil;
public class ImageSlide extends Slide {

View File

@@ -16,6 +16,7 @@ import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.AttachmentId;
import org.thoughtcrime.securesms.avatar.AvatarPickerStorage;
import org.signal.core.models.media.TransformProperties;
import org.thoughtcrime.securesms.database.AttachmentTable;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.emoji.EmojiFiles;
@@ -160,7 +161,7 @@ public class PartAuthority {
}
}
public static @Nullable AttachmentTable.TransformProperties getAttachmentTransformProperties(@NonNull Uri uri) {
public static @Nullable TransformProperties getAttachmentTransformProperties(@NonNull Uri uri) {
int match = uriMatcher.match(uri);
switch (match) {
case PART_ROW:

View File

@@ -29,6 +29,7 @@ import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.UriAttachment;
import org.thoughtcrime.securesms.audio.AudioHash;
import org.thoughtcrime.securesms.blurhash.BlurHash;
import org.signal.core.models.media.TransformProperties;
import org.thoughtcrime.securesms.database.AttachmentTable;
import org.thoughtcrime.securesms.stickers.StickerLocator;
import org.thoughtcrime.securesms.util.MediaUtil;
@@ -211,7 +212,7 @@ public abstract class Slide {
boolean borderless,
boolean gif,
boolean quote,
@Nullable AttachmentTable.TransformProperties transformProperties)
@Nullable TransformProperties transformProperties)
{
String resolvedType = Optional.ofNullable(MediaUtil.getMimeType(context, uri)).orElse(defaultMime);
String fastPreflightId = String.valueOf(new SecureRandom().nextLong());

View File

@@ -12,6 +12,7 @@ import androidx.annotation.Nullable;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.blurhash.BlurHash;
import org.signal.core.models.media.TransformProperties;
import org.thoughtcrime.securesms.database.AttachmentTable;
import org.thoughtcrime.securesms.util.MediaUtil;
@@ -41,7 +42,7 @@ public final class SlideFactory {
*
* @return A Slide with all the information we can gather about it.
*/
public static @Nullable Slide getSlide(@NonNull Context context, @Nullable String contentType, @NonNull Uri uri, int width, int height, @Nullable AttachmentTable.TransformProperties transformProperties) {
public static @Nullable Slide getSlide(@NonNull Context context, @Nullable String contentType, @NonNull Uri uri, int width, int height, @Nullable TransformProperties transformProperties) {
MediaType mediaType = MediaType.from(contentType);
try {
@@ -65,7 +66,7 @@ public final class SlideFactory {
@NonNull Uri uri,
int width,
int height,
@Nullable AttachmentTable.TransformProperties transformProperties
@Nullable TransformProperties transformProperties
) {
long start = System.currentTimeMillis();
@@ -99,7 +100,7 @@ public final class SlideFactory {
@NonNull Uri uri,
int width,
int height,
@Nullable AttachmentTable.TransformProperties transformProperties
@Nullable TransformProperties transformProperties
) throws IOException
{
long start = System.currentTimeMillis();
@@ -162,7 +163,7 @@ public final class SlideFactory {
int width,
int height,
boolean gif,
@Nullable AttachmentTable.TransformProperties transformProperties)
@Nullable TransformProperties transformProperties)
{
if (mimeType == null) {
mimeType = "application/octet-stream";
@@ -172,7 +173,7 @@ public final class SlideFactory {
case IMAGE: return new ImageSlide(context, uri, mimeType, dataSize, width, height, false, null, blurHash, transformProperties);
case GIF: return new GifSlide(context, uri, dataSize, width, height);
case AUDIO: return new AudioSlide(context, uri, dataSize, false);
case VIDEO: return new VideoSlide(context, uri, dataSize, gif, null, AttachmentTable.TransformProperties.forSentMediaQuality(transformProperties != null ? transformProperties.sentMediaQuality : SentMediaQuality.STANDARD.getCode()));
case VIDEO: return new VideoSlide(context, uri, dataSize, gif, null, TransformProperties.forSentMediaQuality(transformProperties != null ? transformProperties.sentMediaQuality : SentMediaQuality.STANDARD.getCode()));
case VCARD:
case DOCUMENT: return new DocumentSlide(context, uri, mimeType, dataSize, fileName);
default: throw new AssertionError("unrecognized enum");

View File

@@ -26,6 +26,7 @@ import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.signal.core.models.media.TransformProperties;
import org.thoughtcrime.securesms.database.AttachmentTable;
import org.thoughtcrime.securesms.giph.mp4.GiphyMp4PlaybackPolicy;
import org.thoughtcrime.securesms.util.MediaUtil;
@@ -36,11 +37,11 @@ public class VideoSlide extends Slide {
this(context, uri, dataSize, gif, null, null);
}
public VideoSlide(Context context, Uri uri, long dataSize, boolean gif, @Nullable String caption, @Nullable AttachmentTable.TransformProperties transformProperties) {
public VideoSlide(Context context, Uri uri, long dataSize, boolean gif, @Nullable String caption, @Nullable TransformProperties transformProperties) {
super(constructAttachmentFromUri(context, uri, MediaUtil.VIDEO_UNSPECIFIED, dataSize, 0, 0, MediaUtil.hasVideoThumbnail(context, uri), null, caption, null, null, null, false, false, gif, false, transformProperties));
}
public VideoSlide(Context context, Uri uri, long dataSize, boolean gif, int width, int height, @Nullable String caption, @Nullable AttachmentTable.TransformProperties transformProperties) {
public VideoSlide(Context context, Uri uri, long dataSize, boolean gif, int width, int height, @Nullable String caption, @Nullable TransformProperties transformProperties) {
super(constructAttachmentFromUri(context, uri, MediaUtil.VIDEO_UNSPECIFIED, dataSize, width, height, MediaUtil.hasVideoThumbnail(context, uri), null, caption, null, null, null, false, false, gif, false, transformProperties));
}

View File

@@ -34,7 +34,7 @@ import org.thoughtcrime.securesms.databinding.CreateProfileFragmentBinding;
import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.keyvalue.PhoneNumberPrivacyValues;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.mediasend.Media;
import org.signal.core.models.media.Media;
import org.thoughtcrime.securesms.profiles.edit.pnp.WhoCanFindMeByPhoneNumberFragment;
import org.thoughtcrime.securesms.profiles.manage.EditProfileNameFragment;
import org.thoughtcrime.securesms.providers.BlobProvider;

View File

@@ -15,7 +15,7 @@ import org.thoughtcrime.securesms.conversation.colors.AvatarColor;
import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.keyvalue.PhoneNumberPrivacyValues.PhoneNumberDiscoverabilityMode;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.mediasend.Media;
import org.signal.core.models.media.Media;
import org.thoughtcrime.securesms.profiles.ProfileName;
import org.thoughtcrime.securesms.profiles.edit.EditProfileRepository.UploadResult;
import org.thoughtcrime.securesms.util.SingleLiveEvent;

View File

@@ -22,6 +22,7 @@ import com.airbnb.lottie.SimpleColorFilter
import com.bumptech.glide.Glide
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
import org.signal.core.models.media.Media
import org.signal.core.util.concurrent.LifecycleDisposable
import org.signal.core.util.getParcelableCompat
import org.thoughtcrime.securesms.AvatarPreviewActivity
@@ -36,7 +37,6 @@ import org.thoughtcrime.securesms.components.emoji.EmojiUtil
import org.thoughtcrime.securesms.databinding.EditProfileFragmentBinding
import org.thoughtcrime.securesms.keyvalue.AccountValues
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.profiles.ProfileName
import org.thoughtcrime.securesms.profiles.manage.EditProfileViewModel.AvatarState
import org.thoughtcrime.securesms.profiles.manage.UsernameRepository.UsernameDeleteResult

View File

@@ -17,7 +17,7 @@ import org.thoughtcrime.securesms.badges.models.Badge;
import org.thoughtcrime.securesms.dependencies.AppDependencies;
import org.thoughtcrime.securesms.jobs.RefreshOwnProfileJob;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.mediasend.Media;
import org.signal.core.models.media.Media;
import org.thoughtcrime.securesms.profiles.AvatarHelper;
import org.thoughtcrime.securesms.profiles.ProfileName;
import org.thoughtcrime.securesms.providers.BlobProvider;

View File

@@ -5,25 +5,7 @@
package org.thoughtcrime.securesms.serialization
import android.net.Uri
import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
/**
* Kotlinx Serialization serializer for Android [Uri] objects.
* Typealias to the core UriSerializer class for backward compatibility.
*/
class UriSerializer : KSerializer<Uri> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Uri", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: Uri) {
encoder.encodeString(value.toString())
}
override fun deserialize(decoder: Decoder): Uri {
return Uri.parse(decoder.decodeString())
}
}
typealias UriSerializer = org.signal.core.models.UriSerializer

View File

@@ -17,7 +17,7 @@ import org.thoughtcrime.securesms.contactshare.Contact;
import org.thoughtcrime.securesms.database.model.Mention;
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList;
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
import org.thoughtcrime.securesms.mediasend.Media;
import org.signal.core.models.media.Media;
import org.thoughtcrime.securesms.stickers.StickerLocator;
import org.thoughtcrime.securesms.stories.Stories;
import org.thoughtcrime.securesms.util.MediaUtil;

View File

@@ -22,6 +22,7 @@ import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey;
import org.thoughtcrime.securesms.contactshare.Contact;
import org.thoughtcrime.securesms.conversation.MessageSendType;
import org.thoughtcrime.securesms.conversation.colors.ChatColors;
import org.signal.core.models.media.TransformProperties;
import org.thoughtcrime.securesms.database.AttachmentTable;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.database.model.Mention;
@@ -31,7 +32,7 @@ import org.thoughtcrime.securesms.dependencies.AppDependencies;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.keyvalue.StorySend;
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
import org.thoughtcrime.securesms.mediasend.Media;
import org.signal.core.models.media.Media;
import org.thoughtcrime.securesms.mediasend.v2.text.TextStoryBackgroundColors;
import org.thoughtcrime.securesms.mms.ImageSlide;
import org.thoughtcrime.securesms.mms.OutgoingMessage;
@@ -352,7 +353,7 @@ public final class MultiShareSender {
private static Slide ensureDefaultQuality(@NonNull Context context, @NonNull ImageSlide imageSlide) {
Attachment attachment = imageSlide.asAttachment();
final AttachmentTable.TransformProperties transformProperties = attachment.transformProperties;
final TransformProperties transformProperties = attachment.transformProperties;
if (transformProperties != null && transformProperties.sentMediaQuality == SentMediaQuality.HIGH.getCode()) {
return new ImageSlide(
context,
@@ -364,7 +365,7 @@ public final class MultiShareSender {
attachment.borderless,
attachment.caption,
attachment.blurHash,
AttachmentTable.TransformProperties.empty()
TransformProperties.empty()
);
} else {
return imageSlide;

View File

@@ -25,7 +25,7 @@ sealed class ResolvedShareData {
}
data class Media(
val media: List<org.thoughtcrime.securesms.mediasend.Media>,
val media: List<org.signal.core.models.media.Media>,
val text: CharSequence?
) : ResolvedShareData() {
override fun toMultiShareArgs(): MultiShareArgs {

View File

@@ -16,6 +16,7 @@ import androidx.core.text.buildSpannedString
import com.google.android.material.appbar.MaterialToolbar
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.kotlin.subscribeBy
import org.signal.core.models.media.Media
import org.signal.core.util.Result
import org.signal.core.util.concurrent.LifecycleDisposable
import org.signal.core.util.concurrent.addTo
@@ -33,7 +34,6 @@ import org.thoughtcrime.securesms.conversation.MessageSendType
import org.thoughtcrime.securesms.conversation.mutiselect.forward.MultiselectForwardFragment
import org.thoughtcrime.securesms.conversation.mutiselect.forward.MultiselectForwardFragmentArgs
import org.thoughtcrime.securesms.conversation.mutiselect.forward.MultiselectForwardFullScreenDialogFragment
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionActivity.Companion.share
import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.sharing.MultiShareDialogs

View File

@@ -7,8 +7,8 @@ import androidx.annotation.NonNull
import androidx.annotation.WorkerThread
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.schedulers.Schedulers
import org.signal.core.models.media.Media
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.providers.BlobProvider
import org.thoughtcrime.securesms.util.MediaUtil
import org.thoughtcrime.securesms.util.RemoteConfig

View File

@@ -59,7 +59,7 @@ import org.thoughtcrime.securesms.jobs.PushGroupSendJob;
import org.thoughtcrime.securesms.jobs.ReactionSendJob;
import org.thoughtcrime.securesms.jobs.RemoteDeleteSendJob;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.mediasend.Media;
import org.signal.core.models.media.Media;
import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.OutgoingMessage;
import org.thoughtcrime.securesms.recipients.Recipient;

View File

@@ -1,12 +1,11 @@
package org.thoughtcrime.securesms.sms
import androidx.annotation.WorkerThread
import org.signal.core.models.media.TransformProperties
import org.thoughtcrime.securesms.attachments.Attachment
import org.thoughtcrime.securesms.attachments.AttachmentId
import org.thoughtcrime.securesms.attachments.DatabaseAttachment
import org.thoughtcrime.securesms.attachments.UriAttachment
import org.thoughtcrime.securesms.database.AttachmentTable
import org.thoughtcrime.securesms.database.AttachmentTable.TransformProperties
import org.thoughtcrime.securesms.jobmanager.Job
import org.thoughtcrime.securesms.jobmanager.JobManager
import org.thoughtcrime.securesms.jobs.AttachmentCompressionJob
@@ -44,7 +43,7 @@ class UploadDependencyGraph private constructor(
*/
private data class AttachmentKey<A : Attachment>(
val attachment: A,
private val transformProperties: AttachmentTable.TransformProperties = attachment.transformProperties ?: AttachmentTable.TransformProperties.empty()
private val transformProperties: TransformProperties = attachment.transformProperties ?: TransformProperties.empty()
)
private var hasConsumedJobQueue = false

View File

@@ -10,20 +10,19 @@ import androidx.media3.common.Player
import androidx.media3.exoplayer.ExoPlayer
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.schedulers.Schedulers
import org.signal.core.models.media.Media
import org.signal.core.models.media.TransformProperties
import org.signal.core.util.ThreadUtil
import org.signal.core.util.logging.Log
import org.signal.core.util.orNull
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.contacts.HeaderAction
import org.thoughtcrime.securesms.database.AttachmentTable
import org.thoughtcrime.securesms.database.AttachmentTable.TransformProperties
import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.database.model.DistributionListId
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.jobs.AttachmentDownloadJob
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mediasend.v2.stories.ChooseStoryTypeBottomSheet
import org.thoughtcrime.securesms.mms.MediaConstraints
import org.thoughtcrime.securesms.mms.OutgoingMessage
@@ -243,11 +242,12 @@ object Stories {
}
private fun getContentDuration(media: Media): DurationResult {
val transforms = media.transformProperties
return if (MediaUtil.isVideo(media.contentType)) {
val mediaDuration = if (media.duration == 0L && media.transformProperties?.shouldSkipTransform() ?: true) {
val mediaDuration = if (media.duration == 0L && transforms?.shouldSkipTransform() ?: true) {
getVideoDuration(media.uri)
} else if (media.transformProperties?.videoTrim ?: false) {
TimeUnit.MICROSECONDS.toMillis(media.transformProperties.videoTrimEndTimeUs - media.transformProperties.videoTrimStartTimeUs)
} else if (transforms?.videoTrim ?: false) {
TimeUnit.MICROSECONDS.toMillis(transforms.videoTrimEndTimeUs - transforms.videoTrimStartTimeUs)
} else {
media.duration
}
@@ -341,11 +341,11 @@ object Stories {
error("Illegal clip: $startTimeUs > $endTimeUs for clip $clipIndex")
}
AttachmentTable.TransformProperties(false, true, startTimeUs, endTimeUs, SentMediaQuality.STANDARD.code, false)
TransformProperties(false, true, startTimeUs, endTimeUs, SentMediaQuality.STANDARD.code, false)
}.map { transformMedia(media, it) }
}
private fun transformMedia(media: Media, transformProperties: AttachmentTable.TransformProperties): Media {
private fun transformMedia(media: Media, transformProperties: TransformProperties): Media {
Log.d(TAG, "Transforming media clip: ${transformProperties.videoTrimStartTimeUs.microseconds.inWholeSeconds}s to ${transformProperties.videoTrimEndTimeUs.microseconds.inWholeSeconds}s")
return Media(
uri = media.uri,

View File

@@ -30,7 +30,7 @@ import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.AttachmentId;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.mediasend.Media;
import org.signal.core.models.media.Media;
import org.thoughtcrime.securesms.mms.AudioSlide;
import org.thoughtcrime.securesms.mms.DecryptableUri;
import org.thoughtcrime.securesms.mms.DocumentSlide;

View File

@@ -11,7 +11,7 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.mediasend.Media;
import org.signal.core.models.media.Media;
import org.thoughtcrime.securesms.mediasend.v2.gallery.MediaGalleryFragment;
import org.thoughtcrime.securesms.recipients.RecipientId;

View File

@@ -51,7 +51,7 @@
<argument
android:name="group_avatar_media"
app:argType="org.thoughtcrime.securesms.mediasend.Media"
app:argType="org.signal.core.models.media.Media"
app:nullable="true" />
</fragment>

View File

@@ -36,7 +36,7 @@
<argument
android:name="group_avatar_media"
app:argType="org.thoughtcrime.securesms.mediasend.Media"
app:argType="org.signal.core.models.media.Media"
app:nullable="true" />
</action>

View File

@@ -25,7 +25,7 @@
<argument
android:name="group_avatar_media"
app:argType="org.thoughtcrime.securesms.mediasend.Media"
app:argType="org.signal.core.models.media.Media"
app:nullable="true" />
</action>

View File

@@ -50,7 +50,7 @@
<argument
android:name="group_avatar_media"
app:argType="org.thoughtcrime.securesms.mediasend.Media"
app:argType="org.signal.core.models.media.Media"
app:nullable="true" />
</action>

View File

@@ -1,28 +1,31 @@
package org.thoughtcrime.securesms.database;
import org.junit.Test;
import org.signal.core.models.media.TransformProperties;
import org.thoughtcrime.securesms.mms.SentMediaQuality;
import static org.junit.Assert.assertEquals;
import static org.thoughtcrime.securesms.database.TransformPropertiesUtilKt.parseTransformProperties;
import static org.thoughtcrime.securesms.database.TransformPropertiesUtilKt.serialize;
public class AttachmentDatabaseTransformPropertiesTest {
@Test
public void transformProperties_verifyStructure() {
AttachmentTable.TransformProperties properties = AttachmentTable.TransformProperties.empty();
TransformProperties properties = TransformProperties.empty();
assertEquals("Added transform property, need to confirm default behavior for pre-existing payloads in database",
"{\"skipTransform\":false,\"videoTrim\":false,\"videoTrimStartTimeUs\":0,\"videoTrimEndTimeUs\":0,\"sentMediaQuality\":0,\"mp4Faststart\":false,\"videoEdited\":false}",
properties.serialize());
serialize(properties));
}
@Test
public void transformProperties_verifyMissingSentMediaQualityDefaultBehavior() {
String json = "{\"skipTransform\":false,\"videoTrim\":false,\"videoTrimStartTimeUs\":0,\"videoTrimEndTimeUs\":0,\"videoEdited\":false,\"mp4Faststart\":false}";
AttachmentTable.TransformProperties properties = AttachmentTable.TransformProperties.parse(json);
TransformProperties properties = parseTransformProperties(json);
assertEquals(0, properties.sentMediaQuality);
assertEquals(SentMediaQuality.STANDARD, SentMediaQuality.fromCode(properties.sentMediaQuality));
}
}
}

View File

@@ -12,8 +12,9 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import org.signal.core.models.media.Media
import org.signal.core.models.media.TransformProperties
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.database.AttachmentTable.TransformProperties
import org.thoughtcrime.securesms.testutil.EmptyLogger
import org.thoughtcrime.securesms.util.MediaUtil

View File

@@ -9,6 +9,7 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import org.signal.core.models.media.TransformProperties
import org.thoughtcrime.securesms.attachments.Attachment
import org.thoughtcrime.securesms.attachments.AttachmentId
import org.thoughtcrime.securesms.attachments.DatabaseAttachment
@@ -80,7 +81,7 @@ class UploadDependencyGraphTest {
UriAttachmentBuilder.build(
id = 10,
contentType = MediaUtil.IMAGE_JPEG,
transformProperties = AttachmentTable.TransformProperties(false, true, increment, increment + 1, SentMediaQuality.STANDARD.code, false)
transformProperties = TransformProperties(false, true, increment, increment + 1, SentMediaQuality.STANDARD.code, false)
)
}
@@ -122,7 +123,7 @@ class UploadDependencyGraphTest {
UriAttachmentBuilder.build(
id = 10,
contentType = MediaUtil.IMAGE_JPEG,
transformProperties = if (it != 1) AttachmentTable.TransformProperties(false, true, 1, 2, SentMediaQuality.STANDARD.code, false) else null
transformProperties = if (it != 1) TransformProperties(false, true, 1, 2, SentMediaQuality.STANDARD.code, false) else null
)
}
@@ -182,7 +183,7 @@ class UploadDependencyGraphTest {
UriAttachmentBuilder.build(
1L,
contentType = MediaUtil.IMAGE_JPEG,
transformProperties = AttachmentTable.TransformProperties.forVideoTrim(it.toLong(), it.toLong() + 1)
transformProperties = TransformProperties.forVideoTrim(it.toLong(), it.toLong() + 1)
)
}

View File

@@ -1,6 +1,7 @@
package org.thoughtcrime.securesms.testutil
import android.net.Uri
import org.signal.core.models.media.TransformProperties
import org.thoughtcrime.securesms.attachments.UriAttachment
import org.thoughtcrime.securesms.audio.AudioHash
import org.thoughtcrime.securesms.blurhash.BlurHash
@@ -24,7 +25,7 @@ object UriAttachmentBuilder {
stickerLocator: StickerLocator? = null,
blurHash: BlurHash? = null,
audioHash: AudioHash? = null,
transformProperties: AttachmentTable.TransformProperties? = null
transformProperties: TransformProperties? = null
): UriAttachment {
return UriAttachment(
uri,

View File

@@ -1,5 +1,6 @@
package org.thoughtcrime.securesms.database
import org.signal.core.models.media.TransformProperties
import org.thoughtcrime.securesms.attachments.AttachmentId
import org.thoughtcrime.securesms.attachments.Cdn
import org.thoughtcrime.securesms.attachments.DatabaseAttachment
@@ -56,7 +57,7 @@ object FakeMessageRecords {
stickerLocator: StickerLocator? = null,
blurHash: BlurHash? = null,
audioHash: AudioHash? = null,
transformProperties: AttachmentTable.TransformProperties? = null,
transformProperties: TransformProperties? = null,
displayOrder: Int = 0,
uploadTimestamp: Long = 200,
dataHash: String? = null,

View File

@@ -0,0 +1,27 @@
/*
* Copyright 2025 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
plugins {
id("java-library")
id("org.jetbrains.kotlin.jvm")
id("ktlint")
}
java {
sourceCompatibility = JavaVersion.toVersion(libs.versions.javaVersion.get())
targetCompatibility = JavaVersion.toVersion(libs.versions.javaVersion.get())
}
kotlin {
jvmToolchain {
languageVersion = JavaLanguageVersion.of(libs.versions.kotlinJvmTarget.get())
}
}
dependencies {
implementation(libs.libsignal.client)
implementation(libs.square.okio)
implementation(project(":core:util-jvm"))
}

Some files were not shown because too many files have changed in this diff Show More