Convert some SignalServiceAttachment* classes to kotlin.
This commit is contained in:
parent
bb01c0501b
commit
8932eef991
40 changed files with 431 additions and 673 deletions
|
@ -23,7 +23,7 @@ import java.util.UUID
|
||||||
*/
|
*/
|
||||||
abstract class Attachment(
|
abstract class Attachment(
|
||||||
@JvmField
|
@JvmField
|
||||||
val contentType: String,
|
val contentType: String?,
|
||||||
@JvmField
|
@JvmField
|
||||||
val transferState: Int,
|
val transferState: Int,
|
||||||
@JvmField
|
@JvmField
|
||||||
|
|
|
@ -17,7 +17,7 @@ import java.util.UUID
|
||||||
class PointerAttachment : Attachment {
|
class PointerAttachment : Attachment {
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
constructor(
|
constructor(
|
||||||
contentType: String,
|
contentType: String?,
|
||||||
transferState: Int,
|
transferState: Int,
|
||||||
size: Long,
|
size: Long,
|
||||||
fileName: String?,
|
fileName: String?,
|
||||||
|
@ -87,15 +87,11 @@ class PointerAttachment : Attachment {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun forPointer(pointer: Optional<SignalServiceAttachment>, stickerLocator: StickerLocator? = null, fastPreflightId: String? = null, transferState: Int = AttachmentTable.TRANSFER_PROGRESS_PENDING): Optional<Attachment> {
|
fun forPointer(pointer: Optional<SignalServiceAttachment>, stickerLocator: StickerLocator? = null, fastPreflightId: String? = null, transferState: Int = AttachmentTable.TRANSFER_PROGRESS_PENDING): Optional<Attachment> {
|
||||||
if (!pointer.isPresent || !pointer.get().isPointer) {
|
if (!pointer.isPresent || !pointer.get().isPointer()) {
|
||||||
return Optional.empty()
|
return Optional.empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
val encodedKey: String? = if (pointer.get().asPointer().key != null) {
|
val encodedKey: String? = pointer.get().asPointer().key?.let { encodeWithPadding(it) }
|
||||||
encodeWithPadding(pointer.get().asPointer().key)
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
|
|
||||||
return Optional.of(
|
return Optional.of(
|
||||||
PointerAttachment(
|
PointerAttachment(
|
||||||
|
@ -143,7 +139,7 @@ class PointerAttachment : Attachment {
|
||||||
fileName = quotedAttachment.fileName,
|
fileName = quotedAttachment.fileName,
|
||||||
cdn = Cdn.fromCdnNumber(thumbnail?.asPointer()?.cdnNumber ?: 0),
|
cdn = Cdn.fromCdnNumber(thumbnail?.asPointer()?.cdnNumber ?: 0),
|
||||||
location = thumbnail?.asPointer()?.remoteId?.toString() ?: "0",
|
location = thumbnail?.asPointer()?.remoteId?.toString() ?: "0",
|
||||||
key = if (thumbnail != null && thumbnail.asPointer().key != null) encodeWithPadding(thumbnail.asPointer().key) else null,
|
key = thumbnail?.asPointer()?.key?.let { encodeWithPadding(it) },
|
||||||
digest = thumbnail?.asPointer()?.digest?.orElse(null),
|
digest = thumbnail?.asPointer()?.digest?.orElse(null),
|
||||||
incrementalDigest = thumbnail?.asPointer()?.incrementalDigest?.orElse(null),
|
incrementalDigest = thumbnail?.asPointer()?.incrementalDigest?.orElse(null),
|
||||||
incrementalMacChunkSize = thumbnail?.asPointer()?.incrementalMacChunkSize ?: 0,
|
incrementalMacChunkSize = thumbnail?.asPointer()?.incrementalMacChunkSize ?: 0,
|
||||||
|
|
|
@ -140,7 +140,7 @@ class AttachmentKeyboardMediaAdapter extends RecyclerView.Adapter<AttachmentKeyb
|
||||||
if (media.getDuration() > 0) {
|
if (media.getDuration() > 0) {
|
||||||
duration.setVisibility(View.VISIBLE);
|
duration.setVisibility(View.VISIBLE);
|
||||||
duration.setText(formatTime(media.getDuration()));
|
duration.setText(formatTime(media.getDuration()));
|
||||||
} else if (MediaUtil.isVideoType(media.getMimeType())) {
|
} else if (MediaUtil.isVideoType(media.getContentType())) {
|
||||||
videoIcon.setVisibility(View.VISIBLE);
|
videoIcon.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,11 +55,11 @@ data class MultiselectForwardFragmentArgs @JvmOverloads constructor(
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun create(context: Context, threadId: Long, mediaUri: Uri, mediaType: String, consumer: Consumer<MultiselectForwardFragmentArgs>) {
|
fun create(context: Context, threadId: Long, mediaUri: Uri, contentType: String?, consumer: Consumer<MultiselectForwardFragmentArgs>) {
|
||||||
SignalExecutors.BOUNDED.execute {
|
SignalExecutors.BOUNDED.execute {
|
||||||
val multiShareArgs = MultiShareArgs.Builder(setOf())
|
val multiShareArgs = MultiShareArgs.Builder(setOf())
|
||||||
.withDataUri(mediaUri)
|
.withDataUri(mediaUri)
|
||||||
.withDataType(mediaType)
|
.withDataType(contentType)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
val sendButtonColors: ViewColorSet? = threadId.takeIf { it > 0 }
|
val sendButtonColors: ViewColorSet? = threadId.takeIf { it > 0 }
|
||||||
|
|
|
@ -3649,12 +3649,12 @@ class ConversationFragment :
|
||||||
|
|
||||||
val slides: List<Slide> = result.nonUploadedMedia.mapNotNull {
|
val slides: List<Slide> = result.nonUploadedMedia.mapNotNull {
|
||||||
when {
|
when {
|
||||||
MediaUtil.isVideoType(it.mimeType) -> VideoSlide(requireContext(), it.uri, it.size, it.isVideoGif, it.width, it.height, it.caption.orNull(), it.transformProperties.orNull())
|
MediaUtil.isVideoType(it.contentType) -> VideoSlide(requireContext(), it.uri, it.size, it.isVideoGif, it.width, it.height, it.caption.orNull(), it.transformProperties.orNull())
|
||||||
MediaUtil.isGif(it.mimeType) -> GifSlide(requireContext(), it.uri, it.size, it.width, it.height, it.isBorderless, it.caption.orNull())
|
MediaUtil.isGif(it.contentType) -> GifSlide(requireContext(), it.uri, it.size, it.width, it.height, it.isBorderless, it.caption.orNull())
|
||||||
MediaUtil.isImageType(it.mimeType) -> ImageSlide(requireContext(), it.uri, it.mimeType, it.size, it.width, it.height, it.isBorderless, it.caption.orNull(), null, it.transformProperties.orNull())
|
MediaUtil.isImageType(it.contentType) -> ImageSlide(requireContext(), it.uri, it.contentType, it.size, it.width, it.height, it.isBorderless, it.caption.orNull(), null, it.transformProperties.orNull())
|
||||||
MediaUtil.isDocumentType(it.mimeType) -> { DocumentSlide(requireContext(), it.uri, it.mimeType, it.size, it.fileName.orNull()) }
|
MediaUtil.isDocumentType(it.contentType) -> { DocumentSlide(requireContext(), it.uri, it.contentType, it.size, it.fileName.orNull()) }
|
||||||
else -> {
|
else -> {
|
||||||
Log.w(TAG, "Asked to send an unexpected mimeType: '${it.mimeType}'. Skipping.")
|
Log.w(TAG, "Asked to send an unexpected mimeType: '${it.contentType}'. Skipping.")
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,7 +246,7 @@ class MediaTable internal constructor(context: Context?, databaseHelper: SignalD
|
||||||
val isOutgoing: Boolean
|
val isOutgoing: Boolean
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val contentType: String
|
val contentType: String?
|
||||||
get() = attachment!!.contentType
|
get() = attachment!!.contentType
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -33,7 +33,7 @@ object MediaIntentFactory {
|
||||||
val threadId: Long,
|
val threadId: Long,
|
||||||
val date: Long,
|
val date: Long,
|
||||||
val initialMediaUri: Uri,
|
val initialMediaUri: Uri,
|
||||||
val initialMediaType: String,
|
val initialMediaType: String?,
|
||||||
val initialMediaSize: Long,
|
val initialMediaSize: Long,
|
||||||
val initialCaption: String? = null,
|
val initialCaption: String? = null,
|
||||||
val leftIsRecent: Boolean = false,
|
val leftIsRecent: Boolean = false,
|
||||||
|
@ -68,13 +68,13 @@ object MediaIntentFactory {
|
||||||
return create(
|
return create(
|
||||||
context,
|
context,
|
||||||
MediaPreviewArgs(
|
MediaPreviewArgs(
|
||||||
mediaRecord.threadId,
|
threadId = mediaRecord.threadId,
|
||||||
mediaRecord.date,
|
date = mediaRecord.date,
|
||||||
attachment.uri!!,
|
initialMediaUri = attachment.uri!!,
|
||||||
attachment.contentType,
|
initialMediaType = attachment.contentType,
|
||||||
attachment.size,
|
initialMediaSize = attachment.size,
|
||||||
attachment.caption,
|
initialCaption = attachment.caption,
|
||||||
leftIsRecent,
|
leftIsRecent = leftIsRecent,
|
||||||
allMediaInRail = allMediaInRail,
|
allMediaInRail = allMediaInRail,
|
||||||
sorting = MediaTable.Sorting.Newest,
|
sorting = MediaTable.Sorting.Newest,
|
||||||
isVideoGif = attachment.videoGif,
|
isVideoGif = attachment.videoGif,
|
||||||
|
|
|
@ -50,7 +50,7 @@ class MediaPreviewPlayerControlView @JvmOverloads constructor(
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun fromString(contentType: String): MediaMode {
|
fun fromString(contentType: String?): MediaMode {
|
||||||
if (MediaUtil.isVideo(contentType)) return VIDEO
|
if (MediaUtil.isVideo(contentType)) return VIDEO
|
||||||
if (MediaUtil.isImageType(contentType)) return IMAGE
|
if (MediaUtil.isImageType(contentType)) return IMAGE
|
||||||
throw IllegalArgumentException("Unknown content type: $contentType")
|
throw IllegalArgumentException("Unknown content type: $contentType")
|
||||||
|
|
|
@ -526,10 +526,10 @@ class MediaPreviewV2Fragment : LoggingFragment(R.layout.fragment_media_preview_v
|
||||||
val uri = attachment?.uri
|
val uri = attachment?.uri
|
||||||
if (attachment != null && uri != null) {
|
if (attachment != null && uri != null) {
|
||||||
MultiselectForwardFragmentArgs.create(
|
MultiselectForwardFragmentArgs.create(
|
||||||
requireContext(),
|
context = requireContext(),
|
||||||
mediaItem.threadId,
|
threadId = mediaItem.threadId,
|
||||||
uri,
|
mediaUri = uri,
|
||||||
attachment.contentType
|
contentType = attachment.contentType
|
||||||
) { args: MultiselectForwardFragmentArgs ->
|
) { args: MultiselectForwardFragmentArgs ->
|
||||||
MultiselectForwardFragment.showBottomSheet(childFragmentManager, args)
|
MultiselectForwardFragment.showBottomSheet(childFragmentManager, args)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.database.AttachmentTable;
|
import org.thoughtcrime.securesms.database.AttachmentTable;
|
||||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||||
|
@ -21,9 +22,9 @@ public class Media implements Parcelable {
|
||||||
|
|
||||||
public static final String ALL_MEDIA_BUCKET_ID = "org.thoughtcrime.securesms.ALL_MEDIA";
|
public static final String ALL_MEDIA_BUCKET_ID = "org.thoughtcrime.securesms.ALL_MEDIA";
|
||||||
|
|
||||||
private final Uri uri;
|
private final Uri uri;
|
||||||
private final String mimeType;
|
private final String contentType;
|
||||||
private final long date;
|
private final long date;
|
||||||
private final int width;
|
private final int width;
|
||||||
private final int height;
|
private final int height;
|
||||||
private final long size;
|
private final long size;
|
||||||
|
@ -37,7 +38,7 @@ public class Media implements Parcelable {
|
||||||
private Optional<String> fileName;
|
private Optional<String> fileName;
|
||||||
|
|
||||||
public Media(@NonNull Uri uri,
|
public Media(@NonNull Uri uri,
|
||||||
@NonNull String mimeType,
|
@Nullable String contentType,
|
||||||
long date,
|
long date,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
|
@ -51,7 +52,7 @@ public class Media implements Parcelable {
|
||||||
Optional<String> fileName)
|
Optional<String> fileName)
|
||||||
{
|
{
|
||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
this.mimeType = mimeType;
|
this.contentType = contentType;
|
||||||
this.date = date;
|
this.date = date;
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
|
@ -66,9 +67,9 @@ public class Media implements Parcelable {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Media(Parcel in) {
|
protected Media(Parcel in) {
|
||||||
uri = in.readParcelable(Uri.class.getClassLoader());
|
uri = in.readParcelable(Uri.class.getClassLoader());
|
||||||
mimeType = in.readString();
|
contentType = in.readString();
|
||||||
date = in.readLong();
|
date = in.readLong();
|
||||||
width = in.readInt();
|
width = in.readInt();
|
||||||
height = in.readInt();
|
height = in.readInt();
|
||||||
size = in.readLong();
|
size = in.readLong();
|
||||||
|
@ -90,8 +91,8 @@ public class Media implements Parcelable {
|
||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getMimeType() {
|
public String getContentType() {
|
||||||
return mimeType;
|
return contentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getDate() {
|
public long getDate() {
|
||||||
|
@ -154,7 +155,7 @@ public class Media implements Parcelable {
|
||||||
@Override
|
@Override
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
dest.writeParcelable(uri, flags);
|
dest.writeParcelable(uri, flags);
|
||||||
dest.writeString(mimeType);
|
dest.writeString(contentType);
|
||||||
dest.writeLong(date);
|
dest.writeLong(date);
|
||||||
dest.writeInt(width);
|
dest.writeInt(width);
|
||||||
dest.writeInt(height);
|
dest.writeInt(height);
|
||||||
|
@ -212,10 +213,10 @@ public class Media implements Parcelable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @NonNull Media stripTransform(@NonNull Media media) {
|
public static @NonNull Media stripTransform(@NonNull Media media) {
|
||||||
Preconditions.checkArgument(MediaUtil.isImageType(media.mimeType));
|
Preconditions.checkArgument(MediaUtil.isImageType(media.contentType));
|
||||||
|
|
||||||
return new Media(media.getUri(),
|
return new Media(media.getUri(),
|
||||||
media.getMimeType(),
|
media.getContentType(),
|
||||||
media.getDate(),
|
media.getDate(),
|
||||||
media.getWidth(),
|
media.getWidth(),
|
||||||
media.getHeight(),
|
media.getHeight(),
|
||||||
|
|
|
@ -361,12 +361,12 @@ public class MediaRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (width == 0 || height == 0) {
|
if (width == 0 || height == 0) {
|
||||||
Pair<Integer, Integer> dimens = MediaUtil.getDimensions(context, media.getMimeType(), media.getUri());
|
Pair<Integer, Integer> dimens = MediaUtil.getDimensions(context, media.getContentType(), media.getUri());
|
||||||
width = dimens.first;
|
width = dimens.first;
|
||||||
height = dimens.second;
|
height = dimens.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Media(media.getUri(), media.getMimeType(), media.getDate(), width, height, size, 0, media.isBorderless(), media.isVideoGif(), media.getBucketId(), media.getCaption(), Optional.empty(), Optional.empty());
|
return new Media(media.getUri(), media.getContentType(), media.getDate(), width, height, size, 0, media.isBorderless(), media.isVideoGif(), media.getBucketId(), media.getCaption(), Optional.empty(), Optional.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Media getContentResolverPopulatedMedia(@NonNull Context context, @NonNull Media media) throws IOException {
|
private Media getContentResolverPopulatedMedia(@NonNull Context context, @NonNull Media media) throws IOException {
|
||||||
|
@ -387,20 +387,20 @@ public class MediaRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (width == 0 || height == 0) {
|
if (width == 0 || height == 0) {
|
||||||
Pair<Integer, Integer> dimens = MediaUtil.getDimensions(context, media.getMimeType(), media.getUri());
|
Pair<Integer, Integer> dimens = MediaUtil.getDimensions(context, media.getContentType(), media.getUri());
|
||||||
width = dimens.first;
|
width = dimens.first;
|
||||||
height = dimens.second;
|
height = dimens.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Media(media.getUri(), media.getMimeType(), media.getDate(), width, height, size, 0, media.isBorderless(), media.isVideoGif(), media.getBucketId(), media.getCaption(), Optional.empty(), Optional.empty());
|
return new Media(media.getUri(), media.getContentType(), media.getDate(), width, height, size, 0, media.isBorderless(), media.isVideoGif(), media.getBucketId(), media.getCaption(), Optional.empty(), Optional.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public static @NonNull Media fixMimeType(@NonNull Context context, @NonNull Media media) {
|
public static @NonNull Media fixMimeType(@NonNull Context context, @NonNull Media media) {
|
||||||
if (MediaUtil.isOctetStream(media.getMimeType())) {
|
if (MediaUtil.isOctetStream(media.getContentType())) {
|
||||||
Log.w(TAG, "Media has mimetype octet stream");
|
Log.w(TAG, "Media has mimetype octet stream");
|
||||||
String newMimeType = MediaUtil.getMimeType(context, media.getUri());
|
String newMimeType = MediaUtil.getMimeType(context, media.getUri());
|
||||||
if (newMimeType != null && !newMimeType.equals(media.getMimeType())) {
|
if (newMimeType != null && !newMimeType.equals(media.getContentType())) {
|
||||||
Log.d(TAG, "Changing mime type to '" + newMimeType + "'");
|
Log.d(TAG, "Changing mime type to '" + newMimeType + "'");
|
||||||
return Media.withMimeType(media, newMimeType);
|
return Media.withMimeType(media, newMimeType);
|
||||||
} else if (media.getSize() > 0 && media.getWidth() > 0 && media.getHeight() > 0) {
|
} else if (media.getSize() > 0 && media.getWidth() > 0 && media.getHeight() > 0) {
|
||||||
|
|
|
@ -214,16 +214,16 @@ public class MediaUploadRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @NonNull Attachment asAttachment(@NonNull Context context, @NonNull Media media) {
|
public static @NonNull Attachment asAttachment(@NonNull Context context, @NonNull Media media) {
|
||||||
if (MediaUtil.isVideoType(media.getMimeType())) {
|
if (MediaUtil.isVideoType(media.getContentType())) {
|
||||||
return new VideoSlide(context, media.getUri(), media.getSize(), media.isVideoGif(), media.getWidth(), media.getHeight(), media.getCaption().orElse(null), media.getTransformProperties().orElse(null)).asAttachment();
|
return new VideoSlide(context, media.getUri(), media.getSize(), media.isVideoGif(), media.getWidth(), media.getHeight(), media.getCaption().orElse(null), media.getTransformProperties().orElse(null)).asAttachment();
|
||||||
} else if (MediaUtil.isGif(media.getMimeType())) {
|
} else if (MediaUtil.isGif(media.getContentType())) {
|
||||||
return new GifSlide(context, media.getUri(), media.getSize(), media.getWidth(), media.getHeight(), media.isBorderless(), media.getCaption().orElse(null)).asAttachment();
|
return new GifSlide(context, media.getUri(), media.getSize(), media.getWidth(), media.getHeight(), media.isBorderless(), media.getCaption().orElse(null)).asAttachment();
|
||||||
} else if (MediaUtil.isImageType(media.getMimeType())) {
|
} else if (MediaUtil.isImageType(media.getContentType())) {
|
||||||
return new ImageSlide(context, media.getUri(), media.getMimeType(), media.getSize(), media.getWidth(), media.getHeight(), media.isBorderless(), media.getCaption().orElse(null), null, media.getTransformProperties().orElse(null)).asAttachment();
|
return new ImageSlide(context, media.getUri(), media.getContentType(), media.getSize(), media.getWidth(), media.getHeight(), media.isBorderless(), media.getCaption().orElse(null), null, media.getTransformProperties().orElse(null)).asAttachment();
|
||||||
} else if (MediaUtil.isTextType(media.getMimeType())) {
|
} else if (MediaUtil.isTextType(media.getContentType())) {
|
||||||
return new TextSlide(context, media.getUri(), null, media.getSize()).asAttachment();
|
return new TextSlide(context, media.getUri(), null, media.getSize()).asAttachment();
|
||||||
} else {
|
} else {
|
||||||
throw new AssertionError("Unexpected mimeType: " + media.getMimeType());
|
throw new AssertionError("Unexpected mimeType: " + media.getContentType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ public final class SentMediaQualityTransform implements MediaTransform {
|
||||||
@Override
|
@Override
|
||||||
public @NonNull Media transform(@NonNull Context context, @NonNull Media media) {
|
public @NonNull Media transform(@NonNull Context context, @NonNull Media media) {
|
||||||
return new Media(media.getUri(),
|
return new Media(media.getUri(),
|
||||||
media.getMimeType(),
|
media.getContentType(),
|
||||||
media.getDate(),
|
media.getDate(),
|
||||||
media.getWidth(),
|
media.getWidth(),
|
||||||
media.getHeight(),
|
media.getHeight(),
|
||||||
|
|
|
@ -12,7 +12,7 @@ class VideoTrimTransform(private val data: VideoTrimData) : MediaTransform {
|
||||||
override fun transform(context: Context, media: Media): Media {
|
override fun transform(context: Context, media: Media): Media {
|
||||||
return Media(
|
return Media(
|
||||||
media.uri,
|
media.uri,
|
||||||
media.mimeType,
|
media.contentType,
|
||||||
media.date,
|
media.date,
|
||||||
media.width,
|
media.width,
|
||||||
media.height,
|
media.height,
|
||||||
|
|
|
@ -153,7 +153,7 @@ class MediaSelectionRepository(context: Context) {
|
||||||
scheduleMessages(sendType, contacts.map { it.recipientId }, trimmedBody, updatedMedia, trimmedMentions, trimmedBodyRanges, isViewOnce, scheduledTime)
|
scheduleMessages(sendType, contacts.map { it.recipientId }, trimmedBody, updatedMedia, trimmedMentions, trimmedBodyRanges, isViewOnce, scheduledTime)
|
||||||
emitter.onComplete()
|
emitter.onComplete()
|
||||||
}
|
}
|
||||||
} else if (MediaUtil.isDocumentType(selectedMedia.first().mimeType)) {
|
} else if (MediaUtil.isDocumentType(selectedMedia.first().contentType)) {
|
||||||
Log.i(TAG, "Document. Skipping pre-upload.")
|
Log.i(TAG, "Document. Skipping pre-upload.")
|
||||||
emitter.onSuccess(
|
emitter.onSuccess(
|
||||||
MediaSendActivityResult(
|
MediaSendActivityResult(
|
||||||
|
@ -315,14 +315,14 @@ class MediaSelectionRepository(context: Context) {
|
||||||
val context: Context = AppDependencies.application
|
val context: Context = AppDependencies.application
|
||||||
|
|
||||||
for (mediaItem in nonUploadedMedia) {
|
for (mediaItem in nonUploadedMedia) {
|
||||||
if (MediaUtil.isVideoType(mediaItem.mimeType)) {
|
if (MediaUtil.isVideoType(mediaItem.contentType)) {
|
||||||
slideDeck.addSlide(VideoSlide(context, mediaItem.uri, mediaItem.size, mediaItem.isVideoGif, mediaItem.width, mediaItem.height, mediaItem.caption.orElse(null), mediaItem.transformProperties.orElse(null)))
|
slideDeck.addSlide(VideoSlide(context, mediaItem.uri, mediaItem.size, mediaItem.isVideoGif, mediaItem.width, mediaItem.height, mediaItem.caption.orElse(null), mediaItem.transformProperties.orElse(null)))
|
||||||
} else if (MediaUtil.isGif(mediaItem.mimeType)) {
|
} else if (MediaUtil.isGif(mediaItem.contentType)) {
|
||||||
slideDeck.addSlide(GifSlide(context, mediaItem.uri, mediaItem.size, mediaItem.width, mediaItem.height, mediaItem.isBorderless, mediaItem.caption.orElse(null)))
|
slideDeck.addSlide(GifSlide(context, mediaItem.uri, mediaItem.size, mediaItem.width, mediaItem.height, mediaItem.isBorderless, mediaItem.caption.orElse(null)))
|
||||||
} else if (MediaUtil.isImageType(mediaItem.mimeType)) {
|
} else if (MediaUtil.isImageType(mediaItem.contentType)) {
|
||||||
slideDeck.addSlide(ImageSlide(context, mediaItem.uri, mediaItem.mimeType, mediaItem.size, mediaItem.width, mediaItem.height, mediaItem.isBorderless, mediaItem.caption.orElse(null), null, mediaItem.transformProperties.orElse(null)))
|
slideDeck.addSlide(ImageSlide(context, mediaItem.uri, mediaItem.contentType, mediaItem.size, mediaItem.width, mediaItem.height, mediaItem.isBorderless, mediaItem.caption.orElse(null), null, mediaItem.transformProperties.orElse(null)))
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "Asked to send an unexpected mimeType: '" + mediaItem.mimeType + "'. Skipping.")
|
Log.w(TAG, "Asked to send an unexpected mimeType: '" + mediaItem.contentType + "'. Skipping.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val splitMessage = MessageUtil.getSplitMessage(context, body, sendType.calculateCharacters(body).maxPrimaryMessageSize)
|
val splitMessage = MessageUtil.getSplitMessage(context, body, sendType.calculateCharacters(body).maxPrimaryMessageSize)
|
||||||
|
|
|
@ -32,7 +32,7 @@ data class MediaSelectionState(
|
||||||
val suppressEmptyError: Boolean = true
|
val suppressEmptyError: Boolean = true
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val isVideoTrimmingVisible: Boolean = focusedMedia != null && MediaUtil.isVideoType(focusedMedia.mimeType) && MediaConstraints.isVideoTranscodeAvailable() && !focusedMedia.isVideoGif
|
val isVideoTrimmingVisible: Boolean = focusedMedia != null && MediaUtil.isVideoType(focusedMedia.contentType) && MediaConstraints.isVideoTranscodeAvailable() && !focusedMedia.isVideoGif
|
||||||
|
|
||||||
val transcodingPreset: TranscodingPreset = MediaConstraints.getPushMediaConstraints(SentMediaQuality.fromCode(quality.code)).videoTranscodingSettings
|
val transcodingPreset: TranscodingPreset = MediaConstraints.getPushMediaConstraints(SentMediaQuality.fromCode(quality.code)).videoTranscodingSettings
|
||||||
|
|
||||||
|
|
|
@ -421,7 +421,7 @@ class MediaSelectionViewModel(
|
||||||
}
|
}
|
||||||
|
|
||||||
val filteredPreUploadMedia = if (destination is MediaSelectionDestination.SingleRecipient || !Stories.isFeatureEnabled()) {
|
val filteredPreUploadMedia = if (destination is MediaSelectionDestination.SingleRecipient || !Stories.isFeatureEnabled()) {
|
||||||
media.filter { !MediaUtil.isDocumentType(it.mimeType) }
|
media.filter { !MediaUtil.isDocumentType(it.contentType) }
|
||||||
} else {
|
} else {
|
||||||
media.filter { Stories.MediaTransform.canPreUploadMedia(it) }
|
media.filter { Stories.MediaTransform.canPreUploadMedia(it) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ object MediaValidator {
|
||||||
|
|
||||||
var error: FilterError? = null
|
var error: FilterError? = null
|
||||||
if (!isAllMediaValid) {
|
if (!isAllMediaValid) {
|
||||||
error = if (media.all { MediaUtil.isImageOrVideoType(it.mimeType) || MediaUtil.isDocumentType(it.mimeType) }) {
|
error = if (media.all { MediaUtil.isImageOrVideoType(it.contentType) || MediaUtil.isDocumentType(it.contentType) }) {
|
||||||
FilterError.ItemTooLarge
|
FilterError.ItemTooLarge
|
||||||
} else {
|
} else {
|
||||||
FilterError.ItemInvalidType
|
FilterError.ItemInvalidType
|
||||||
|
@ -51,9 +51,9 @@ object MediaValidator {
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
private fun filterForValidMedia(context: Context, media: List<Media>, mediaConstraints: MediaConstraints, isStory: Boolean): List<Media> {
|
private fun filterForValidMedia(context: Context, media: List<Media>, mediaConstraints: MediaConstraints, isStory: Boolean): List<Media> {
|
||||||
return media
|
return media
|
||||||
.filter { m -> isSupportedMediaType(m.mimeType) }
|
.filter { m -> isSupportedMediaType(m.contentType) }
|
||||||
.filter { m ->
|
.filter { m ->
|
||||||
MediaUtil.isImageAndNotGif(m.mimeType) || isValidGif(context, m, mediaConstraints) || isValidVideo(context, m, mediaConstraints) || isValidDocument(context, m, mediaConstraints)
|
MediaUtil.isImageAndNotGif(m.contentType) || isValidGif(context, m, mediaConstraints) || isValidVideo(context, m, mediaConstraints) || isValidDocument(context, m, mediaConstraints)
|
||||||
}
|
}
|
||||||
.filter { m ->
|
.filter { m ->
|
||||||
!isStory || Stories.MediaTransform.getSendRequirements(m) != Stories.MediaTransform.SendRequirements.CAN_NOT_SEND
|
!isStory || Stories.MediaTransform.getSendRequirements(m) != Stories.MediaTransform.SendRequirements.CAN_NOT_SEND
|
||||||
|
@ -61,15 +61,15 @@ object MediaValidator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isValidGif(context: Context, media: Media, mediaConstraints: MediaConstraints): Boolean {
|
private fun isValidGif(context: Context, media: Media, mediaConstraints: MediaConstraints): Boolean {
|
||||||
return MediaUtil.isGif(media.mimeType) && media.size < mediaConstraints.getGifMaxSize(context)
|
return MediaUtil.isGif(media.contentType) && media.size < mediaConstraints.getGifMaxSize(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isValidVideo(context: Context, media: Media, mediaConstraints: MediaConstraints): Boolean {
|
private fun isValidVideo(context: Context, media: Media, mediaConstraints: MediaConstraints): Boolean {
|
||||||
return MediaUtil.isVideoType(media.mimeType) && media.size < mediaConstraints.getUncompressedVideoMaxSize(context)
|
return MediaUtil.isVideoType(media.contentType) && media.size < mediaConstraints.getUncompressedVideoMaxSize(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isValidDocument(context: Context, media: Media, mediaConstraints: MediaConstraints): Boolean {
|
private fun isValidDocument(context: Context, media: Media, mediaConstraints: MediaConstraints): Boolean {
|
||||||
return MediaUtil.isDocumentType(media.mimeType) && media.size < mediaConstraints.getDocumentMaxSize(context)
|
return MediaUtil.isDocumentType(media.contentType) && media.size < mediaConstraints.getDocumentMaxSize(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isSupportedMediaType(mimeType: String): Boolean {
|
private fun isSupportedMediaType(mimeType: String): Boolean {
|
||||||
|
|
|
@ -115,7 +115,7 @@ object MediaGallerySelectableItem {
|
||||||
checkView?.visible = model.isSelected
|
checkView?.visible = model.isSelected
|
||||||
checkView?.text = "${model.selectionOneBasedIndex}"
|
checkView?.text = "${model.selectionOneBasedIndex}"
|
||||||
itemView.setOnClickListener { onMediaClicked(model.media, model.isSelected) }
|
itemView.setOnClickListener { onMediaClicked(model.media, model.isSelected) }
|
||||||
playOverlay?.visible = MediaUtil.isVideo(model.media.mimeType) && !model.media.isVideoGif
|
playOverlay?.visible = MediaUtil.isVideo(model.media.contentType) && !model.media.isVideoGif
|
||||||
title?.visible = false
|
title?.visible = false
|
||||||
|
|
||||||
if (PAYLOAD_INDEX_CHANGED in payload) {
|
if (PAYLOAD_INDEX_CHANGED in payload) {
|
||||||
|
|
|
@ -42,7 +42,7 @@ object MediaGallerySelectedItem {
|
||||||
.centerCrop()
|
.centerCrop()
|
||||||
.into(imageView)
|
.into(imageView)
|
||||||
|
|
||||||
videoOverlay.visible = MediaUtil.isVideo(model.media.mimeType) && !model.media.isVideoGif
|
videoOverlay.visible = MediaUtil.isVideo(model.media.contentType) && !model.media.isVideoGif
|
||||||
itemView.setOnClickListener { onSelectedMediaClicked(model.media) }
|
itemView.setOnClickListener { onSelectedMediaClicked(model.media) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,7 @@ class AddMessageDialogFragment : KeyboardEntryDialogFragment(R.layout.v2_media_a
|
||||||
binding.content.addAMessageInput.text = null
|
binding.content.addAMessageInput.text = null
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
binding.content.viewOnceToggle.visible = state.selectedMedia.size == 1 && !state.isStory && !MediaUtil.isDocumentType(state.focusedMedia?.mimeType)
|
binding.content.viewOnceToggle.visible = state.selectedMedia.size == 1 && !state.isStory && !MediaUtil.isDocumentType(state.focusedMedia?.contentType)
|
||||||
}
|
}
|
||||||
|
|
||||||
initializeMentions()
|
initializeMentions()
|
||||||
|
|
|
@ -220,7 +220,7 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
||||||
SimpleTask.run(viewLifecycleOwner.lifecycle, {
|
SimpleTask.run(viewLifecycleOwner.lifecycle, {
|
||||||
snapshot.selectedMedia.take(2).map { media ->
|
snapshot.selectedMedia.take(2).map { media ->
|
||||||
val editorData = snapshot.editorStateMap[media.uri]
|
val editorData = snapshot.editorStateMap[media.uri]
|
||||||
if (MediaUtil.isImageType(media.mimeType) && editorData != null && editorData is ImageEditorFragment.Data) {
|
if (MediaUtil.isImageType(media.contentType) && editorData != null && editorData is ImageEditorFragment.Data) {
|
||||||
val model = editorData.readModel()
|
val model = editorData.readModel()
|
||||||
if (model != null) {
|
if (model != null) {
|
||||||
ImageEditorFragment.renderToSingleUseBlob(requireContext(), model)
|
ImageEditorFragment.renderToSingleUseBlob(requireContext(), model)
|
||||||
|
@ -388,14 +388,14 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
||||||
} else {
|
} else {
|
||||||
getString(R.string.MediaReviewFragment__video_set_to_standard_quality)
|
getString(R.string.MediaReviewFragment__video_set_to_standard_quality)
|
||||||
}
|
}
|
||||||
} else if (MediaUtil.isImageType(media.mimeType)) {
|
} else if (MediaUtil.isImageType(media.contentType)) {
|
||||||
if (state.quality == SentMediaQuality.HIGH) {
|
if (state.quality == SentMediaQuality.HIGH) {
|
||||||
getString(R.string.MediaReviewFragment__photo_set_to_high_quality)
|
getString(R.string.MediaReviewFragment__photo_set_to_high_quality)
|
||||||
} else {
|
} else {
|
||||||
getString(R.string.MediaReviewFragment__photo_set_to_standard_quality)
|
getString(R.string.MediaReviewFragment__photo_set_to_standard_quality)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.i(TAG, "Could not display quality toggle toast for attachment of type: ${media.mimeType}")
|
Log.i(TAG, "Could not display quality toggle toast for attachment of type: ${media.contentType}")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -484,7 +484,7 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
||||||
|
|
||||||
private fun presentImageQualityToggle(state: MediaSelectionState) {
|
private fun presentImageQualityToggle(state: MediaSelectionState) {
|
||||||
qualityButton.updateLayoutParams<ConstraintLayout.LayoutParams> {
|
qualityButton.updateLayoutParams<ConstraintLayout.LayoutParams> {
|
||||||
if (MediaUtil.isImageAndNotGif(state.focusedMedia?.mimeType ?: "")) {
|
if (MediaUtil.isImageAndNotGif(state.focusedMedia?.contentType ?: "")) {
|
||||||
startToStart = ConstraintLayout.LayoutParams.UNSET
|
startToStart = ConstraintLayout.LayoutParams.UNSET
|
||||||
startToEnd = cropAndRotateButton.id
|
startToEnd = cropAndRotateButton.id
|
||||||
} else {
|
} else {
|
||||||
|
@ -540,7 +540,7 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
||||||
|
|
||||||
private fun presentVideoTimeline(state: MediaSelectionState) {
|
private fun presentVideoTimeline(state: MediaSelectionState) {
|
||||||
val mediaItem = state.focusedMedia ?: return
|
val mediaItem = state.focusedMedia ?: return
|
||||||
if (!MediaUtil.isVideoType(mediaItem.mimeType) || !MediaConstraints.isVideoTranscodeAvailable()) {
|
if (!MediaUtil.isVideoType(mediaItem.contentType) || !MediaConstraints.isVideoTranscodeAvailable()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val uri = mediaItem.uri
|
val uri = mediaItem.uri
|
||||||
|
@ -659,7 +659,7 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun computeViewOnceButtonAnimators(state: MediaSelectionState): List<Animator> {
|
private fun computeViewOnceButtonAnimators(state: MediaSelectionState): List<Animator> {
|
||||||
return if (state.isTouchEnabled && state.selectedMedia.size == 1 && !state.isStory && !MediaUtil.isDocumentType(state.focusedMedia?.mimeType)) {
|
return if (state.isTouchEnabled && state.selectedMedia.size == 1 && !state.isStory && !MediaUtil.isDocumentType(state.focusedMedia?.contentType)) {
|
||||||
listOf(MediaReviewAnimatorController.getFadeInAnimator(viewOnceButton))
|
listOf(MediaReviewAnimatorController.getFadeInAnimator(viewOnceButton))
|
||||||
} else {
|
} else {
|
||||||
listOf(MediaReviewAnimatorController.getFadeOutAnimator(viewOnceButton))
|
listOf(MediaReviewAnimatorController.getFadeOutAnimator(viewOnceButton))
|
||||||
|
@ -676,7 +676,7 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
||||||
|
|
||||||
private fun computeAddMediaButtonsAnimators(state: MediaSelectionState): List<Animator> {
|
private fun computeAddMediaButtonsAnimators(state: MediaSelectionState): List<Animator> {
|
||||||
return when {
|
return when {
|
||||||
!state.isTouchEnabled || state.viewOnceToggleState == MediaSelectionState.ViewOnceToggleState.ONCE || MediaUtil.isDocumentType(state.focusedMedia?.mimeType) -> {
|
!state.isTouchEnabled || state.viewOnceToggleState == MediaSelectionState.ViewOnceToggleState.ONCE || MediaUtil.isDocumentType(state.focusedMedia?.contentType) -> {
|
||||||
listOf(
|
listOf(
|
||||||
MediaReviewAnimatorController.getFadeOutAnimator(addMediaButton),
|
MediaReviewAnimatorController.getFadeOutAnimator(addMediaButton),
|
||||||
MediaReviewAnimatorController.getFadeOutAnimator(selectionRecycler)
|
MediaReviewAnimatorController.getFadeOutAnimator(selectionRecycler)
|
||||||
|
@ -710,7 +710,7 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun computeSaveButtonAnimators(state: MediaSelectionState): List<Animator> {
|
private fun computeSaveButtonAnimators(state: MediaSelectionState): List<Animator> {
|
||||||
return if (state.isTouchEnabled && !MediaUtil.isVideo(state.focusedMedia?.mimeType) && !MediaUtil.isDocumentType(state.focusedMedia?.mimeType)) {
|
return if (state.isTouchEnabled && !MediaUtil.isVideo(state.focusedMedia?.contentType) && !MediaUtil.isDocumentType(state.focusedMedia?.contentType)) {
|
||||||
listOf(
|
listOf(
|
||||||
MediaReviewAnimatorController.getFadeInAnimator(saveButton)
|
MediaReviewAnimatorController.getFadeInAnimator(saveButton)
|
||||||
)
|
)
|
||||||
|
@ -722,7 +722,7 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun computeQualityButtonAnimators(state: MediaSelectionState): List<Animator> {
|
private fun computeQualityButtonAnimators(state: MediaSelectionState): List<Animator> {
|
||||||
return if (state.isTouchEnabled && !state.isStory && !MediaUtil.isDocumentType(state.focusedMedia?.mimeType)) {
|
return if (state.isTouchEnabled && !state.isStory && !MediaUtil.isDocumentType(state.focusedMedia?.contentType)) {
|
||||||
listOf(MediaReviewAnimatorController.getFadeInAnimator(qualityButton))
|
listOf(MediaReviewAnimatorController.getFadeInAnimator(qualityButton))
|
||||||
} else {
|
} else {
|
||||||
listOf(MediaReviewAnimatorController.getFadeOutAnimator(qualityButton))
|
listOf(MediaReviewAnimatorController.getFadeOutAnimator(qualityButton))
|
||||||
|
@ -730,7 +730,7 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun computeCropAndRotateButtonAnimators(state: MediaSelectionState): List<Animator> {
|
private fun computeCropAndRotateButtonAnimators(state: MediaSelectionState): List<Animator> {
|
||||||
return if (state.isTouchEnabled && MediaUtil.isImageAndNotGif(state.focusedMedia?.mimeType ?: "")) {
|
return if (state.isTouchEnabled && MediaUtil.isImageAndNotGif(state.focusedMedia?.contentType ?: "")) {
|
||||||
listOf(MediaReviewAnimatorController.getFadeInAnimator(cropAndRotateButton))
|
listOf(MediaReviewAnimatorController.getFadeInAnimator(cropAndRotateButton))
|
||||||
} else {
|
} else {
|
||||||
listOf(MediaReviewAnimatorController.getFadeOutAnimator(cropAndRotateButton))
|
listOf(MediaReviewAnimatorController.getFadeOutAnimator(cropAndRotateButton))
|
||||||
|
@ -738,7 +738,7 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun computeDrawToolButtonAnimators(state: MediaSelectionState): List<Animator> {
|
private fun computeDrawToolButtonAnimators(state: MediaSelectionState): List<Animator> {
|
||||||
return if (state.isTouchEnabled && MediaUtil.isImageAndNotGif(state.focusedMedia?.mimeType ?: "")) {
|
return if (state.isTouchEnabled && MediaUtil.isImageAndNotGif(state.focusedMedia?.contentType ?: "")) {
|
||||||
listOf(MediaReviewAnimatorController.getFadeInAnimator(drawToolButton))
|
listOf(MediaReviewAnimatorController.getFadeInAnimator(drawToolButton))
|
||||||
} else {
|
} else {
|
||||||
listOf(MediaReviewAnimatorController.getFadeOutAnimator(drawToolButton))
|
listOf(MediaReviewAnimatorController.getFadeOutAnimator(drawToolButton))
|
||||||
|
|
|
@ -44,12 +44,12 @@ class MediaReviewFragmentPagerAdapter(fragment: Fragment) : FragmentStateAdapter
|
||||||
val mediaItem: Media = mediaList[position]
|
val mediaItem: Media = mediaList[position]
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
MediaUtil.isGif(mediaItem.mimeType) -> MediaReviewGifPageFragment.newInstance(mediaItem.uri)
|
MediaUtil.isGif(mediaItem.contentType) -> MediaReviewGifPageFragment.newInstance(mediaItem.uri)
|
||||||
MediaUtil.isImageType(mediaItem.mimeType) -> MediaReviewImagePageFragment.newInstance(mediaItem.uri)
|
MediaUtil.isImageType(mediaItem.contentType) -> MediaReviewImagePageFragment.newInstance(mediaItem.uri)
|
||||||
MediaUtil.isVideoType(mediaItem.mimeType) -> MediaReviewVideoPageFragment.newInstance(mediaItem.uri, mediaItem.isVideoGif)
|
MediaUtil.isVideoType(mediaItem.contentType) -> MediaReviewVideoPageFragment.newInstance(mediaItem.uri, mediaItem.isVideoGif)
|
||||||
MediaUtil.isDocumentType(mediaItem.mimeType) -> MediaReviewDocumentPageFragment.newInstance(mediaItem)
|
MediaUtil.isDocumentType(mediaItem.contentType) -> MediaReviewDocumentPageFragment.newInstance(mediaItem)
|
||||||
else -> {
|
else -> {
|
||||||
throw UnsupportedOperationException("Can only render images and videos. Found mimetype: '" + mediaItem.mimeType + "'")
|
throw UnsupportedOperationException("Can only render images and videos. Found mimetype: '" + mediaItem.contentType + "'")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,7 +197,7 @@ private fun AttachmentBlock(attachment: AttachmentInfo) {
|
||||||
)
|
)
|
||||||
ClickToCopyRow(
|
ClickToCopyRow(
|
||||||
name = "Content Type",
|
name = "Content Type",
|
||||||
value = attachment.contentType
|
value = attachment.contentType ?: "null"
|
||||||
)
|
)
|
||||||
ClickToCopyRow(
|
ClickToCopyRow(
|
||||||
name = "Start Hash",
|
name = "Start Hash",
|
||||||
|
|
|
@ -62,7 +62,7 @@ class InternalMessageDetailsViewModel(val messageId: Long) : ViewModel() {
|
||||||
|
|
||||||
data class AttachmentInfo(
|
data class AttachmentInfo(
|
||||||
val id: Long,
|
val id: Long,
|
||||||
val contentType: String,
|
val contentType: String?,
|
||||||
val size: Long,
|
val size: Long,
|
||||||
val fileName: String?,
|
val fileName: String?,
|
||||||
val hashStart: String?,
|
val hashStart: String?,
|
||||||
|
|
|
@ -140,7 +140,7 @@ class EditProfileViewModel extends ViewModel {
|
||||||
|
|
||||||
internalAvatarState.postValue(InternalAvatarState.loading(data));
|
internalAvatarState.postValue(InternalAvatarState.loading(data));
|
||||||
|
|
||||||
repository.setAvatar(context, data, media.getMimeType(), result -> {
|
repository.setAvatar(context, data, media.getContentType(), result -> {
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
internalAvatarState.postValue(InternalAvatarState.loaded(data));
|
internalAvatarState.postValue(InternalAvatarState.loaded(data));
|
||||||
|
|
|
@ -35,25 +35,25 @@ object ReleaseChannel {
|
||||||
): MessageTable.InsertResult? {
|
): MessageTable.InsertResult? {
|
||||||
val attachments: Optional<List<SignalServiceAttachment>> = if (media != null) {
|
val attachments: Optional<List<SignalServiceAttachment>> = if (media != null) {
|
||||||
val attachment = SignalServiceAttachmentPointer(
|
val attachment = SignalServiceAttachmentPointer(
|
||||||
Cdn.S3.cdnNumber,
|
cdnNumber = Cdn.S3.cdnNumber,
|
||||||
SignalServiceAttachmentRemoteId.S3,
|
remoteId = SignalServiceAttachmentRemoteId.S3,
|
||||||
mediaType,
|
contentType = mediaType,
|
||||||
null,
|
key = null,
|
||||||
Optional.empty(),
|
size = Optional.empty(),
|
||||||
Optional.empty(),
|
preview = Optional.empty(),
|
||||||
mediaWidth,
|
width = mediaWidth,
|
||||||
mediaHeight,
|
height = mediaHeight,
|
||||||
Optional.empty(),
|
digest = Optional.empty(),
|
||||||
Optional.empty(),
|
incrementalDigest = Optional.empty(),
|
||||||
0,
|
incrementalMacChunkSize = 0,
|
||||||
Optional.of(media),
|
fileName = Optional.of(media),
|
||||||
false,
|
voiceNote = false,
|
||||||
false,
|
isBorderless = false,
|
||||||
MediaUtil.isVideo(mediaType),
|
isGif = MediaUtil.isVideo(mediaType),
|
||||||
Optional.empty(),
|
caption = Optional.empty(),
|
||||||
Optional.empty(),
|
blurHash = Optional.empty(),
|
||||||
System.currentTimeMillis(),
|
uploadTimestamp = System.currentTimeMillis(),
|
||||||
mediaAttachmentUuid
|
uuid = mediaAttachmentUuid
|
||||||
)
|
)
|
||||||
|
|
||||||
Optional.of(listOf(attachment))
|
Optional.of(listOf(attachment))
|
||||||
|
|
|
@ -182,7 +182,7 @@ public final class MultiShareArgs implements Parcelable {
|
||||||
}
|
}
|
||||||
|
|
||||||
return isTextStory ||
|
return isTextStory ||
|
||||||
(!media.isEmpty() && media.stream().allMatch(m -> MediaUtil.isStorySupportedType(m.getMimeType()))) ||
|
(!media.isEmpty() && media.stream().allMatch(m -> MediaUtil.isStorySupportedType(m.getContentType()))) ||
|
||||||
MediaUtil.isStorySupportedType(dataType) ||
|
MediaUtil.isStorySupportedType(dataType) ||
|
||||||
isValidForTextStoryGeneration();
|
isValidForTextStoryGeneration();
|
||||||
}
|
}
|
||||||
|
|
|
@ -437,7 +437,7 @@ public final class MultiShareSender {
|
||||||
slideDeck.addSlide(new StickerSlide(context, multiShareArgs.getDataUri(), 0, multiShareArgs.getStickerLocator(), multiShareArgs.getDataType()));
|
slideDeck.addSlide(new StickerSlide(context, multiShareArgs.getDataUri(), 0, multiShareArgs.getStickerLocator(), multiShareArgs.getDataType()));
|
||||||
} else if (!multiShareArgs.getMedia().isEmpty()) {
|
} else if (!multiShareArgs.getMedia().isEmpty()) {
|
||||||
for (Media media : multiShareArgs.getMedia()) {
|
for (Media media : multiShareArgs.getMedia()) {
|
||||||
Slide slide = SlideFactory.getSlide(context, media.getMimeType(), media.getUri(), media.getWidth(), media.getHeight(), media.getTransformProperties().orElse(null));
|
Slide slide = SlideFactory.getSlide(context, media.getContentType(), media.getUri(), media.getWidth(), media.getHeight(), media.getTransformProperties().orElse(null));
|
||||||
if (slide != null) {
|
if (slide != null) {
|
||||||
slideDeck.addSlide(slide);
|
slideDeck.addSlide(slide);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -200,7 +200,7 @@ object Stories {
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
fun canPreUploadMedia(media: Media): Boolean {
|
fun canPreUploadMedia(media: Media): Boolean {
|
||||||
return when {
|
return when {
|
||||||
MediaUtil.isVideo(media.mimeType) -> getSendRequirements(media) != SendRequirements.REQUIRES_CLIP
|
MediaUtil.isVideo(media.contentType) -> getSendRequirements(media) != SendRequirements.REQUIRES_CLIP
|
||||||
else -> true
|
else -> true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -239,11 +239,11 @@ object Stories {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun canClipMedia(media: Media): Boolean {
|
private fun canClipMedia(media: Media): Boolean {
|
||||||
return MediaUtil.isVideo(media.mimeType) && MediaConstraints.isVideoTranscodeAvailable()
|
return MediaUtil.isVideo(media.contentType) && MediaConstraints.isVideoTranscodeAvailable()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getContentDuration(media: Media): DurationResult {
|
private fun getContentDuration(media: Media): DurationResult {
|
||||||
return if (MediaUtil.isVideo(media.mimeType)) {
|
return if (MediaUtil.isVideo(media.contentType)) {
|
||||||
val mediaDuration = if (media.duration == 0L && media.transformProperties.map(TransformProperties::shouldSkipTransform).orElse(true)) {
|
val mediaDuration = if (media.duration == 0L && media.transformProperties.map(TransformProperties::shouldSkipTransform).orElse(true)) {
|
||||||
getVideoDuration(media.uri)
|
getVideoDuration(media.uri)
|
||||||
} else if (media.transformProperties.map { it.videoTrim }.orElse(false)) {
|
} else if (media.transformProperties.map { it.videoTrim }.orElse(false)) {
|
||||||
|
@ -349,7 +349,7 @@ object Stories {
|
||||||
Log.d(TAG, "Transforming media clip: ${transformProperties.videoTrimStartTimeUs.microseconds.inWholeSeconds}s to ${transformProperties.videoTrimEndTimeUs.microseconds.inWholeSeconds}s")
|
Log.d(TAG, "Transforming media clip: ${transformProperties.videoTrimStartTimeUs.microseconds.inWholeSeconds}s to ${transformProperties.videoTrimEndTimeUs.microseconds.inWholeSeconds}s")
|
||||||
return Media(
|
return Media(
|
||||||
media.uri,
|
media.uri,
|
||||||
media.mimeType,
|
media.contentType,
|
||||||
media.date,
|
media.date,
|
||||||
media.width,
|
media.width,
|
||||||
media.height,
|
media.height,
|
||||||
|
|
|
@ -73,10 +73,10 @@ public final class ImageCompressionUtil {
|
||||||
*/
|
*/
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
public static @NonNull Result compress(@NonNull Context context,
|
public static @NonNull Result compress(@NonNull Context context,
|
||||||
@NonNull String mimeType,
|
@Nullable String contentType,
|
||||||
@NonNull Object glideModel,
|
@NonNull Object glideModel,
|
||||||
int maxDimension,
|
int maxDimension,
|
||||||
@IntRange(from = 0, to = 100) int quality)
|
@IntRange(from = 0, to = 100) int quality)
|
||||||
throws BitmapDecodingException
|
throws BitmapDecodingException
|
||||||
{
|
{
|
||||||
Bitmap scaledBitmap;
|
Bitmap scaledBitmap;
|
||||||
|
@ -121,16 +121,16 @@ public final class ImageCompressionUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
Bitmap.CompressFormat format = mimeTypeToCompressFormat(mimeType);
|
Bitmap.CompressFormat format = mimeTypeToCompressFormat(contentType);
|
||||||
scaledBitmap.compress(format, quality, output);
|
scaledBitmap.compress(format, quality, output);
|
||||||
|
|
||||||
byte[] data = output.toByteArray();
|
byte[] data = output.toByteArray();
|
||||||
|
|
||||||
Log.d(TAG, "[Input] mimeType: " + mimeType + " [Output] format: " + format + ", maxDimension: " + maxDimension + ", quality: " + quality + ", size(KiB): " + new ByteSize(data.length).getInWholeKibiBytes());
|
Log.d(TAG, "[Input] mimeType: " + contentType + " [Output] format: " + format + ", maxDimension: " + maxDimension + ", quality: " + quality + ", size(KiB): " + new ByteSize(data.length).getInWholeKibiBytes());
|
||||||
return new Result(data, compressFormatToMimeType(format), scaledBitmap.getWidth(), scaledBitmap.getHeight());
|
return new Result(data, compressFormatToMimeType(format), scaledBitmap.getWidth(), scaledBitmap.getHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static @NonNull Bitmap.CompressFormat mimeTypeToCompressFormat(@NonNull String mimeType) {
|
private static @NonNull Bitmap.CompressFormat mimeTypeToCompressFormat(@Nullable String mimeType) {
|
||||||
if (MediaUtil.isJpegType(mimeType) ||
|
if (MediaUtil.isJpegType(mimeType) ||
|
||||||
MediaUtil.isHeicType(mimeType) ||
|
MediaUtil.isHeicType(mimeType) ||
|
||||||
MediaUtil.isHeifType(mimeType) ||
|
MediaUtil.isHeifType(mimeType) ||
|
||||||
|
|
|
@ -76,7 +76,7 @@ public class MediaUtil {
|
||||||
public static final String UNKNOWN = "*/*";
|
public static final String UNKNOWN = "*/*";
|
||||||
public static final String OCTET = "application/octet-stream";
|
public static final String OCTET = "application/octet-stream";
|
||||||
|
|
||||||
public static SlideType getSlideTypeFromContentType(@NonNull String contentType) {
|
public static SlideType getSlideTypeFromContentType(@Nullable String contentType) {
|
||||||
if (isGif(contentType)) {
|
if (isGif(contentType)) {
|
||||||
return SlideType.GIF;
|
return SlideType.GIF;
|
||||||
} else if (isImageType(contentType)) {
|
} else if (isImageType(contentType)) {
|
||||||
|
@ -356,7 +356,7 @@ public class MediaUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isNonGifVideo(Media media) {
|
public static boolean isNonGifVideo(Media media) {
|
||||||
return isVideo(media.getMimeType()) && !media.isVideoGif();
|
return isVideo(media.getContentType()) && !media.isVideoGif();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isImageType(String contentType) {
|
public static boolean isImageType(String contentType) {
|
||||||
|
|
|
@ -408,9 +408,12 @@ public class SaveAttachmentTask extends ProgressDialogAsyncTask<SaveAttachmentTa
|
||||||
public String contentType;
|
public String contentType;
|
||||||
public long date;
|
public long date;
|
||||||
|
|
||||||
public Attachment(@NonNull Uri uri, @NonNull String contentType,
|
public Attachment(
|
||||||
long date, @Nullable String fileName)
|
@NonNull Uri uri,
|
||||||
{
|
@Nullable String contentType,
|
||||||
|
long date,
|
||||||
|
@Nullable String fileName
|
||||||
|
) {
|
||||||
if (uri == null || contentType == null || date < 0) {
|
if (uri == null || contentType == null || date < 0) {
|
||||||
throw new AssertionError("uri, content type, and date must all be specified");
|
throw new AssertionError("uri, content type, and date must all be specified");
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ class MediaRepositoryTest {
|
||||||
val result: Media = MediaRepository.fixMimeType(context, media)
|
val result: Media = MediaRepository.fixMimeType(context, media)
|
||||||
|
|
||||||
// THEN
|
// THEN
|
||||||
assertEquals(MediaUtil.IMAGE_JPEG, result.mimeType)
|
assertEquals(MediaUtil.IMAGE_JPEG, result.contentType)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -83,7 +83,7 @@ class MediaRepositoryTest {
|
||||||
val result: Media = MediaRepository.fixMimeType(context, media)
|
val result: Media = MediaRepository.fixMimeType(context, media)
|
||||||
|
|
||||||
// THEN
|
// THEN
|
||||||
assertEquals(MediaUtil.IMAGE_JPEG, result.mimeType)
|
assertEquals(MediaUtil.IMAGE_JPEG, result.contentType)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -101,7 +101,7 @@ class MediaRepositoryTest {
|
||||||
val result: Media = MediaRepository.fixMimeType(context, media)
|
val result: Media = MediaRepository.fixMimeType(context, media)
|
||||||
|
|
||||||
// THEN
|
// THEN
|
||||||
assertEquals(MediaUtil.VIDEO_UNSPECIFIED, result.mimeType)
|
assertEquals(MediaUtil.VIDEO_UNSPECIFIED, result.contentType)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildMedia(
|
private fun buildMedia(
|
||||||
|
|
|
@ -1,194 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2023 Signal Messenger, LLC
|
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.whispersystems.signalservice.api.messages;
|
|
||||||
|
|
||||||
|
|
||||||
import org.whispersystems.signalservice.internal.push.http.CancelationSignal;
|
|
||||||
import org.whispersystems.signalservice.internal.push.http.ResumableUploadSpec;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
public abstract class SignalServiceAttachment {
|
|
||||||
|
|
||||||
private final String contentType;
|
|
||||||
|
|
||||||
protected SignalServiceAttachment(String contentType) {
|
|
||||||
this.contentType = contentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getContentType() {
|
|
||||||
return contentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract boolean isStream();
|
|
||||||
public abstract boolean isPointer();
|
|
||||||
|
|
||||||
public SignalServiceAttachmentStream asStream() {
|
|
||||||
return (SignalServiceAttachmentStream)this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SignalServiceAttachmentPointer asPointer() {
|
|
||||||
return (SignalServiceAttachmentPointer)this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Builder newStreamBuilder() {
|
|
||||||
return new Builder();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Builder {
|
|
||||||
|
|
||||||
private InputStream inputStream;
|
|
||||||
private String contentType;
|
|
||||||
private String fileName;
|
|
||||||
private long length;
|
|
||||||
private ProgressListener listener;
|
|
||||||
private CancelationSignal cancelationSignal;
|
|
||||||
private boolean voiceNote;
|
|
||||||
private boolean borderless;
|
|
||||||
private boolean gif;
|
|
||||||
private boolean faststart;
|
|
||||||
private int width;
|
|
||||||
private int height;
|
|
||||||
private String caption;
|
|
||||||
private String blurHash;
|
|
||||||
private long uploadTimestamp;
|
|
||||||
private ResumableUploadSpec resumableUploadSpec;
|
|
||||||
private UUID uuid;
|
|
||||||
|
|
||||||
private Builder() {}
|
|
||||||
|
|
||||||
public Builder withStream(InputStream inputStream) {
|
|
||||||
this.inputStream = inputStream;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder withContentType(String contentType) {
|
|
||||||
this.contentType = contentType;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder withLength(long length) {
|
|
||||||
this.length = length;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder withFileName(String fileName) {
|
|
||||||
this.fileName = fileName;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder withListener(ProgressListener listener) {
|
|
||||||
this.listener = listener;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder withCancelationSignal(CancelationSignal cancelationSignal) {
|
|
||||||
this.cancelationSignal = cancelationSignal;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder withVoiceNote(boolean voiceNote) {
|
|
||||||
this.voiceNote = voiceNote;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder withBorderless(boolean borderless) {
|
|
||||||
this.borderless = borderless;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder withGif(boolean gif) {
|
|
||||||
this.gif = gif;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder withFaststart(boolean faststart) {
|
|
||||||
this.faststart = faststart;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder withWidth(int width) {
|
|
||||||
this.width = width;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder withHeight(int height) {
|
|
||||||
this.height = height;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder withCaption(String caption) {
|
|
||||||
this.caption = caption;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder withBlurHash(String blurHash) {
|
|
||||||
this.blurHash = blurHash;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder withUploadTimestamp(long uploadTimestamp) {
|
|
||||||
this.uploadTimestamp = uploadTimestamp;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder withResumableUploadSpec(ResumableUploadSpec resumableUploadSpec) {
|
|
||||||
this.resumableUploadSpec = resumableUploadSpec;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder withUuid(@Nullable UUID uuid) {
|
|
||||||
this.uuid = uuid;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SignalServiceAttachmentStream build() {
|
|
||||||
if (inputStream == null) throw new IllegalArgumentException("Must specify stream!");
|
|
||||||
if (contentType == null) throw new IllegalArgumentException("No content type specified!");
|
|
||||||
if (length == 0) throw new IllegalArgumentException("No length specified!");
|
|
||||||
|
|
||||||
return new SignalServiceAttachmentStream(inputStream,
|
|
||||||
contentType,
|
|
||||||
length,
|
|
||||||
Optional.ofNullable(fileName),
|
|
||||||
voiceNote,
|
|
||||||
borderless,
|
|
||||||
gif,
|
|
||||||
faststart,
|
|
||||||
Optional.empty(),
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
uploadTimestamp,
|
|
||||||
Optional.ofNullable(caption),
|
|
||||||
Optional.ofNullable(blurHash),
|
|
||||||
listener,
|
|
||||||
cancelationSignal,
|
|
||||||
Optional.ofNullable(resumableUploadSpec),
|
|
||||||
uuid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An interface to receive progress information on upload/download of
|
|
||||||
* an attachment.
|
|
||||||
*/
|
|
||||||
public interface ProgressListener {
|
|
||||||
/**
|
|
||||||
* Called on a progress change event.
|
|
||||||
*
|
|
||||||
* @param total The total amount to transmit/receive in bytes.
|
|
||||||
* @param progress The amount that has been transmitted/received in bytes thus far
|
|
||||||
*/
|
|
||||||
void onAttachmentProgress(long total, long progress);
|
|
||||||
|
|
||||||
boolean shouldCancel();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,178 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023 Signal Messenger, LLC
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
package org.whispersystems.signalservice.api.messages
|
||||||
|
|
||||||
|
import org.whispersystems.signalservice.internal.push.http.CancelationSignal
|
||||||
|
import org.whispersystems.signalservice.internal.push.http.ResumableUploadSpec
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.util.Optional
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
abstract class SignalServiceAttachment protected constructor(val contentType: String?) {
|
||||||
|
abstract fun isStream(): Boolean
|
||||||
|
abstract fun isPointer(): Boolean
|
||||||
|
|
||||||
|
fun asStream(): SignalServiceAttachmentStream {
|
||||||
|
return this as SignalServiceAttachmentStream
|
||||||
|
}
|
||||||
|
|
||||||
|
fun asPointer(): SignalServiceAttachmentPointer {
|
||||||
|
return this as SignalServiceAttachmentPointer
|
||||||
|
}
|
||||||
|
|
||||||
|
class Builder {
|
||||||
|
private var inputStream: InputStream? = null
|
||||||
|
private var contentType: String? = null
|
||||||
|
private var fileName: String? = null
|
||||||
|
private var length: Long = 0
|
||||||
|
private var listener: ProgressListener? = null
|
||||||
|
private var cancelationSignal: CancelationSignal? = null
|
||||||
|
private var voiceNote = false
|
||||||
|
private var borderless = false
|
||||||
|
private var gif = false
|
||||||
|
private var faststart = false
|
||||||
|
private var width = 0
|
||||||
|
private var height = 0
|
||||||
|
private var caption: String? = null
|
||||||
|
private var blurHash: String? = null
|
||||||
|
private var uploadTimestamp: Long = 0
|
||||||
|
private var resumableUploadSpec: ResumableUploadSpec? = null
|
||||||
|
private var uuid: UUID? = null
|
||||||
|
|
||||||
|
fun withStream(inputStream: InputStream?): Builder {
|
||||||
|
this.inputStream = inputStream
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withContentType(contentType: String?): Builder {
|
||||||
|
this.contentType = contentType
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withLength(length: Long): Builder {
|
||||||
|
this.length = length
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withFileName(fileName: String?): Builder {
|
||||||
|
this.fileName = fileName
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withListener(listener: ProgressListener?): Builder {
|
||||||
|
this.listener = listener
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withCancelationSignal(cancelationSignal: CancelationSignal?): Builder {
|
||||||
|
this.cancelationSignal = cancelationSignal
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withVoiceNote(voiceNote: Boolean): Builder {
|
||||||
|
this.voiceNote = voiceNote
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withBorderless(borderless: Boolean): Builder {
|
||||||
|
this.borderless = borderless
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withGif(gif: Boolean): Builder {
|
||||||
|
this.gif = gif
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withFaststart(faststart: Boolean): Builder {
|
||||||
|
this.faststart = faststart
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withWidth(width: Int): Builder {
|
||||||
|
this.width = width
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withHeight(height: Int): Builder {
|
||||||
|
this.height = height
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withCaption(caption: String?): Builder {
|
||||||
|
this.caption = caption
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withBlurHash(blurHash: String?): Builder {
|
||||||
|
this.blurHash = blurHash
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withUploadTimestamp(uploadTimestamp: Long): Builder {
|
||||||
|
this.uploadTimestamp = uploadTimestamp
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withResumableUploadSpec(resumableUploadSpec: ResumableUploadSpec?): Builder {
|
||||||
|
this.resumableUploadSpec = resumableUploadSpec
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withUuid(uuid: UUID?): Builder {
|
||||||
|
this.uuid = uuid
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun build(): SignalServiceAttachmentStream {
|
||||||
|
requireNotNull(inputStream) { "Must specify stream!" }
|
||||||
|
require(length != 0L) { "No length specified!" }
|
||||||
|
|
||||||
|
return SignalServiceAttachmentStream(
|
||||||
|
inputStream = inputStream!!,
|
||||||
|
contentType = contentType,
|
||||||
|
length = length,
|
||||||
|
fileName = Optional.ofNullable(fileName),
|
||||||
|
voiceNote = voiceNote,
|
||||||
|
isBorderless = borderless,
|
||||||
|
isGif = gif,
|
||||||
|
isFaststart = faststart,
|
||||||
|
preview = Optional.empty(),
|
||||||
|
width = width,
|
||||||
|
height = height,
|
||||||
|
uploadTimestamp = uploadTimestamp,
|
||||||
|
caption = Optional.ofNullable(caption),
|
||||||
|
blurHash = Optional.ofNullable(blurHash),
|
||||||
|
listener = listener,
|
||||||
|
cancelationSignal = cancelationSignal,
|
||||||
|
resumableUploadSpec = Optional.ofNullable(resumableUploadSpec),
|
||||||
|
uuid = uuid
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface to receive progress information on upload/download of
|
||||||
|
* an attachment.
|
||||||
|
*/
|
||||||
|
interface ProgressListener {
|
||||||
|
/**
|
||||||
|
* Called on a progress change event.
|
||||||
|
*
|
||||||
|
* @param total The total amount to transmit/receive in bytes.
|
||||||
|
* @param progress The amount that has been transmitted/received in bytes thus far
|
||||||
|
*/
|
||||||
|
fun onAttachmentProgress(total: Long, progress: Long)
|
||||||
|
|
||||||
|
fun shouldCancel(): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
fun newStreamBuilder(): Builder {
|
||||||
|
return Builder()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,166 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2014-2017 Open Whisper Systems
|
|
||||||
*
|
|
||||||
* Licensed according to the LICENSE file in this repository.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.whispersystems.signalservice.api.messages;
|
|
||||||
|
|
||||||
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a received SignalServiceAttachment "handle." This
|
|
||||||
* is a pointer to the actual attachment content, which needs to be
|
|
||||||
* retrieved using {@link SignalServiceMessageReceiver#retrieveAttachment(SignalServiceAttachmentPointer, java.io.File, long)}
|
|
||||||
*
|
|
||||||
* @author Moxie Marlinspike
|
|
||||||
*/
|
|
||||||
public class SignalServiceAttachmentPointer extends SignalServiceAttachment {
|
|
||||||
|
|
||||||
private final int cdnNumber;
|
|
||||||
private final SignalServiceAttachmentRemoteId remoteId;
|
|
||||||
private final byte[] key;
|
|
||||||
private final Optional<Integer> size;
|
|
||||||
private final Optional<byte[]> preview;
|
|
||||||
private final Optional<byte[]> digest;
|
|
||||||
private final Optional<byte[]> incrementalDigest;
|
|
||||||
private final int incrementalMacChunkSize;
|
|
||||||
private final Optional<String> fileName;
|
|
||||||
private final boolean voiceNote;
|
|
||||||
private final boolean borderless;
|
|
||||||
private final boolean gif;
|
|
||||||
private final int width;
|
|
||||||
private final int height;
|
|
||||||
private final Optional<String> caption;
|
|
||||||
private final Optional<String> blurHash;
|
|
||||||
private final long uploadTimestamp;
|
|
||||||
private final UUID uuid;
|
|
||||||
|
|
||||||
public SignalServiceAttachmentPointer(int cdnNumber,
|
|
||||||
SignalServiceAttachmentRemoteId remoteId,
|
|
||||||
String contentType,
|
|
||||||
byte[] key,
|
|
||||||
Optional<Integer> size,
|
|
||||||
Optional<byte[]> preview,
|
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
Optional<byte[]> digest,
|
|
||||||
Optional<byte[]> incrementalDigest,
|
|
||||||
int incrementalMacChunkSize,
|
|
||||||
Optional<String> fileName,
|
|
||||||
boolean voiceNote,
|
|
||||||
boolean borderless,
|
|
||||||
boolean gif,
|
|
||||||
Optional<String> caption,
|
|
||||||
Optional<String> blurHash,
|
|
||||||
long uploadTimestamp,
|
|
||||||
@Nullable UUID uuid)
|
|
||||||
{
|
|
||||||
super(contentType);
|
|
||||||
this.cdnNumber = cdnNumber;
|
|
||||||
this.remoteId = remoteId;
|
|
||||||
this.key = key;
|
|
||||||
this.size = size;
|
|
||||||
this.preview = preview;
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
this.incrementalMacChunkSize = incrementalMacChunkSize;
|
|
||||||
this.digest = digest;
|
|
||||||
this.incrementalDigest = incrementalDigest;
|
|
||||||
this.fileName = fileName;
|
|
||||||
this.voiceNote = voiceNote;
|
|
||||||
this.borderless = borderless;
|
|
||||||
this.caption = caption;
|
|
||||||
this.blurHash = blurHash;
|
|
||||||
this.uploadTimestamp = uploadTimestamp;
|
|
||||||
this.gif = gif;
|
|
||||||
this.uuid = uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCdnNumber() {
|
|
||||||
return cdnNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SignalServiceAttachmentRemoteId getRemoteId() {
|
|
||||||
return remoteId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getKey() {
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isStream() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isPointer() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<Integer> getSize() {
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<String> getFileName() {
|
|
||||||
return fileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<byte[]> getPreview() {
|
|
||||||
return preview;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<byte[]> getDigest() {
|
|
||||||
return digest;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<byte[]> getIncrementalDigest() {
|
|
||||||
return incrementalDigest;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getVoiceNote() {
|
|
||||||
return voiceNote;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isBorderless() {
|
|
||||||
return borderless;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isGif() {
|
|
||||||
return gif;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getWidth() {
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getHeight() {
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getIncrementalMacChunkSize() {
|
|
||||||
return incrementalMacChunkSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<String> getCaption() {
|
|
||||||
return caption;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<String> getBlurHash() {
|
|
||||||
return blurHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getUploadTimestamp() {
|
|
||||||
return uploadTimestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public @Nullable UUID getUuid() {
|
|
||||||
return uuid;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2014-2017 Open Whisper Systems
|
||||||
|
*
|
||||||
|
* Licensed according to the LICENSE file in this repository.
|
||||||
|
*/
|
||||||
|
package org.whispersystems.signalservice.api.messages
|
||||||
|
|
||||||
|
import java.util.Optional
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a received SignalServiceAttachment "handle." This
|
||||||
|
* is a pointer to the actual attachment content, which needs to be
|
||||||
|
* retrieved using [SignalServiceMessageReceiver.retrieveAttachment]
|
||||||
|
*
|
||||||
|
* @author Moxie Marlinspike
|
||||||
|
*/
|
||||||
|
class SignalServiceAttachmentPointer(
|
||||||
|
val cdnNumber: Int,
|
||||||
|
val remoteId: SignalServiceAttachmentRemoteId,
|
||||||
|
contentType: String?,
|
||||||
|
val key: ByteArray?,
|
||||||
|
val size: Optional<Int>,
|
||||||
|
val preview: Optional<ByteArray>,
|
||||||
|
val width: Int,
|
||||||
|
val height: Int,
|
||||||
|
val digest: Optional<ByteArray>,
|
||||||
|
val incrementalDigest: Optional<ByteArray>,
|
||||||
|
val incrementalMacChunkSize: Int,
|
||||||
|
val fileName: Optional<String>,
|
||||||
|
val voiceNote: Boolean,
|
||||||
|
val isBorderless: Boolean,
|
||||||
|
val isGif: Boolean,
|
||||||
|
val caption: Optional<String>,
|
||||||
|
val blurHash: Optional<String>,
|
||||||
|
val uploadTimestamp: Long,
|
||||||
|
val uuid: UUID?
|
||||||
|
) : SignalServiceAttachment(contentType) {
|
||||||
|
override fun isStream() = false
|
||||||
|
override fun isPointer() = true
|
||||||
|
}
|
|
@ -1,179 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2014-2016 Open Whisper Systems
|
|
||||||
*
|
|
||||||
* Licensed according to the LICENSE file in this repository.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.whispersystems.signalservice.api.messages;
|
|
||||||
|
|
||||||
|
|
||||||
import org.whispersystems.signalservice.internal.push.http.CancelationSignal;
|
|
||||||
import org.whispersystems.signalservice.internal.push.http.ResumableUploadSpec;
|
|
||||||
|
|
||||||
import java.io.Closeable;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a local SignalServiceAttachment to be sent.
|
|
||||||
*/
|
|
||||||
public class SignalServiceAttachmentStream extends SignalServiceAttachment implements Closeable {
|
|
||||||
|
|
||||||
private final InputStream inputStream;
|
|
||||||
private final long length;
|
|
||||||
private final Optional<String> fileName;
|
|
||||||
private final ProgressListener listener;
|
|
||||||
private final CancelationSignal cancelationSignal;
|
|
||||||
private final Optional<byte[]> preview;
|
|
||||||
private final boolean voiceNote;
|
|
||||||
private final boolean borderless;
|
|
||||||
private final boolean gif;
|
|
||||||
private final boolean faststart;
|
|
||||||
private final int width;
|
|
||||||
private final int height;
|
|
||||||
private final long uploadTimestamp;
|
|
||||||
private final Optional<String> caption;
|
|
||||||
private final Optional<String> blurHash;
|
|
||||||
private final Optional<ResumableUploadSpec> resumableUploadSpec;
|
|
||||||
private final UUID uuid;
|
|
||||||
|
|
||||||
public SignalServiceAttachmentStream(InputStream inputStream,
|
|
||||||
String contentType,
|
|
||||||
long length,
|
|
||||||
Optional<String> fileName,
|
|
||||||
boolean voiceNote,
|
|
||||||
boolean borderless,
|
|
||||||
boolean gif,
|
|
||||||
boolean faststart,
|
|
||||||
ProgressListener listener,
|
|
||||||
CancelationSignal cancelationSignal)
|
|
||||||
{
|
|
||||||
this(inputStream, contentType, length, fileName, voiceNote, borderless, gif, faststart, Optional.empty(), 0, 0, System.currentTimeMillis(), Optional.empty(), Optional.empty(), listener, cancelationSignal, Optional.empty(), UUID.randomUUID());
|
|
||||||
}
|
|
||||||
|
|
||||||
public SignalServiceAttachmentStream(InputStream inputStream,
|
|
||||||
String contentType,
|
|
||||||
long length,
|
|
||||||
Optional<String> fileName,
|
|
||||||
boolean voiceNote,
|
|
||||||
boolean borderless,
|
|
||||||
boolean gif,
|
|
||||||
boolean faststart,
|
|
||||||
Optional<byte[]> preview,
|
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
long uploadTimestamp,
|
|
||||||
Optional<String> caption,
|
|
||||||
Optional<String> blurHash,
|
|
||||||
ProgressListener listener,
|
|
||||||
CancelationSignal cancelationSignal,
|
|
||||||
Optional<ResumableUploadSpec> resumableUploadSpec,
|
|
||||||
@Nullable UUID uuid)
|
|
||||||
{
|
|
||||||
super(contentType);
|
|
||||||
this.inputStream = inputStream;
|
|
||||||
this.length = length;
|
|
||||||
this.fileName = fileName;
|
|
||||||
this.listener = listener;
|
|
||||||
this.voiceNote = voiceNote;
|
|
||||||
this.borderless = borderless;
|
|
||||||
this.gif = gif;
|
|
||||||
this.preview = preview;
|
|
||||||
this.faststart = faststart;
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
this.uploadTimestamp = uploadTimestamp;
|
|
||||||
this.caption = caption;
|
|
||||||
this.blurHash = blurHash;
|
|
||||||
this.cancelationSignal = cancelationSignal;
|
|
||||||
this.resumableUploadSpec = resumableUploadSpec;
|
|
||||||
this.uuid = uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isStream() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isPointer() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputStream getInputStream() {
|
|
||||||
return inputStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getLength() {
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<String> getFileName() {
|
|
||||||
return fileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProgressListener getListener() {
|
|
||||||
return listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CancelationSignal getCancelationSignal() {
|
|
||||||
return cancelationSignal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<byte[]> getPreview() {
|
|
||||||
return preview;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getVoiceNote() {
|
|
||||||
return voiceNote;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isBorderless() {
|
|
||||||
return borderless;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isGif() {
|
|
||||||
return gif;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isFaststart() {
|
|
||||||
return faststart;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getWidth() {
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getHeight() {
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<String> getCaption() {
|
|
||||||
return caption;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<String> getBlurHash() {
|
|
||||||
return blurHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getUploadTimestamp() {
|
|
||||||
return uploadTimestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<ResumableUploadSpec> getResumableUploadSpec() {
|
|
||||||
return resumableUploadSpec;
|
|
||||||
}
|
|
||||||
|
|
||||||
public @Nullable UUID getUuid() {
|
|
||||||
return uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException {
|
|
||||||
inputStream.close();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
/**
|
||||||
|
* Copyright (C) 2014-2016 Open Whisper Systems
|
||||||
|
*
|
||||||
|
* Licensed according to the LICENSE file in this repository.
|
||||||
|
*/
|
||||||
|
package org.whispersystems.signalservice.api.messages
|
||||||
|
|
||||||
|
import org.whispersystems.signalservice.internal.push.http.CancelationSignal
|
||||||
|
import org.whispersystems.signalservice.internal.push.http.ResumableUploadSpec
|
||||||
|
import java.io.Closeable
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.util.Optional
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a local SignalServiceAttachment to be sent.
|
||||||
|
*/
|
||||||
|
class SignalServiceAttachmentStream(
|
||||||
|
val inputStream: InputStream,
|
||||||
|
contentType: String?,
|
||||||
|
val length: Long,
|
||||||
|
val fileName: Optional<String>,
|
||||||
|
val voiceNote: Boolean,
|
||||||
|
val isBorderless: Boolean,
|
||||||
|
val isGif: Boolean,
|
||||||
|
val isFaststart: Boolean,
|
||||||
|
val preview: Optional<ByteArray>,
|
||||||
|
val width: Int,
|
||||||
|
val height: Int,
|
||||||
|
val uploadTimestamp: Long,
|
||||||
|
val caption: Optional<String>,
|
||||||
|
val blurHash: Optional<String>,
|
||||||
|
val listener: ProgressListener?,
|
||||||
|
val cancelationSignal: CancelationSignal?,
|
||||||
|
val resumableUploadSpec: Optional<ResumableUploadSpec>,
|
||||||
|
val uuid: UUID?
|
||||||
|
) : SignalServiceAttachment(contentType!!), Closeable {
|
||||||
|
constructor(
|
||||||
|
inputStream: InputStream,
|
||||||
|
contentType: String?,
|
||||||
|
length: Long,
|
||||||
|
fileName: Optional<String>,
|
||||||
|
voiceNote: Boolean,
|
||||||
|
borderless: Boolean,
|
||||||
|
gif: Boolean,
|
||||||
|
faststart: Boolean,
|
||||||
|
listener: ProgressListener?,
|
||||||
|
cancelationSignal: CancelationSignal?
|
||||||
|
) : this(
|
||||||
|
inputStream = inputStream,
|
||||||
|
contentType = contentType,
|
||||||
|
length = length,
|
||||||
|
fileName = fileName,
|
||||||
|
voiceNote = voiceNote,
|
||||||
|
isBorderless = borderless,
|
||||||
|
isGif = gif,
|
||||||
|
isFaststart = faststart,
|
||||||
|
preview = Optional.empty<ByteArray>(),
|
||||||
|
width = 0,
|
||||||
|
height = 0,
|
||||||
|
uploadTimestamp = System.currentTimeMillis(),
|
||||||
|
caption = Optional.empty<String>(),
|
||||||
|
blurHash = Optional.empty<String>(),
|
||||||
|
listener = listener,
|
||||||
|
cancelationSignal = cancelationSignal,
|
||||||
|
resumableUploadSpec = Optional.empty<ResumableUploadSpec>(),
|
||||||
|
uuid = UUID.randomUUID()
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun isStream() = true
|
||||||
|
override fun isPointer() = false
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
override fun close() {
|
||||||
|
inputStream.close()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue