mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-26 19:56:02 +01:00
Add support for borderless images.
Added support for 'borderless' images. Basically images that we'd like to render as if they were stickers, even though they're not stickers. On iOS, this will be stuff like memoji and bitmoji. On Android, in my initial pass, I've just added support for Giphy stickers. However, we can also detect bitmoji and keyboard stickers in the future. This is kind of a 'best effort' thing, so as long as we support receiving, we can just add sending support for more things as we go.
This commit is contained in:
@@ -85,6 +85,7 @@ public class AvatarSelectionActivity extends AppCompatActivity implements Camera
|
||||
height,
|
||||
data.length,
|
||||
0,
|
||||
false,
|
||||
Optional.of(Media.ALL_MEDIA_BUCKET_ID),
|
||||
Optional.absent(),
|
||||
Optional.absent()));
|
||||
|
||||
@@ -49,7 +49,7 @@ public final class ImageEditorModelRenderMediaTransform implements MediaTransfor
|
||||
.withMimeType(MediaUtil.IMAGE_JPEG)
|
||||
.createForSingleSessionOnDisk(context);
|
||||
|
||||
return new Media(uri, MediaUtil.IMAGE_JPEG, media.getDate(), bitmap.getWidth(), bitmap.getHeight(), outputStream.size(), 0, media.getBucketId(), media.getCaption(), Optional.absent());
|
||||
return new Media(uri, MediaUtil.IMAGE_JPEG, media.getDate(), bitmap.getWidth(), bitmap.getHeight(), outputStream.size(), 0, false, media.getBucketId(), media.getCaption(), Optional.absent());
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, "Failed to render image. Using base image.");
|
||||
return media;
|
||||
|
||||
@@ -19,13 +19,14 @@ public class Media implements Parcelable {
|
||||
|
||||
public static final String ALL_MEDIA_BUCKET_ID = "org.thoughtcrime.securesms.ALL_MEDIA";
|
||||
|
||||
private final Uri uri;
|
||||
private final String mimeType;
|
||||
private final long date;
|
||||
private final int width;
|
||||
private final int height;
|
||||
private final long size;
|
||||
private final long duration;
|
||||
private final Uri uri;
|
||||
private final String mimeType;
|
||||
private final long date;
|
||||
private final int width;
|
||||
private final int height;
|
||||
private final long size;
|
||||
private final long duration;
|
||||
private final boolean borderless;
|
||||
|
||||
private Optional<String> bucketId;
|
||||
private Optional<String> caption;
|
||||
@@ -38,6 +39,7 @@ public class Media implements Parcelable {
|
||||
int height,
|
||||
long size,
|
||||
long duration,
|
||||
boolean borderless,
|
||||
Optional<String> bucketId,
|
||||
Optional<String> caption,
|
||||
Optional<AttachmentDatabase.TransformProperties> transformProperties)
|
||||
@@ -49,21 +51,23 @@ public class Media implements Parcelable {
|
||||
this.height = height;
|
||||
this.size = size;
|
||||
this.duration = duration;
|
||||
this.borderless = borderless;
|
||||
this.bucketId = bucketId;
|
||||
this.caption = caption;
|
||||
this.transformProperties = transformProperties;
|
||||
}
|
||||
|
||||
protected Media(Parcel in) {
|
||||
uri = in.readParcelable(Uri.class.getClassLoader());
|
||||
mimeType = in.readString();
|
||||
date = in.readLong();
|
||||
width = in.readInt();
|
||||
height = in.readInt();
|
||||
size = in.readLong();
|
||||
duration = in.readLong();
|
||||
bucketId = Optional.fromNullable(in.readString());
|
||||
caption = Optional.fromNullable(in.readString());
|
||||
uri = in.readParcelable(Uri.class.getClassLoader());
|
||||
mimeType = in.readString();
|
||||
date = in.readLong();
|
||||
width = in.readInt();
|
||||
height = in.readInt();
|
||||
size = in.readLong();
|
||||
duration = in.readLong();
|
||||
borderless = in.readInt() == 1;
|
||||
bucketId = Optional.fromNullable(in.readString());
|
||||
caption = Optional.fromNullable(in.readString());
|
||||
try {
|
||||
String json = in.readString();
|
||||
transformProperties = json == null ? Optional.absent() : Optional.fromNullable(JsonUtil.fromJson(json, AttachmentDatabase.TransformProperties.class));
|
||||
@@ -100,6 +104,10 @@ public class Media implements Parcelable {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public boolean isBorderless() {
|
||||
return borderless;
|
||||
}
|
||||
|
||||
public Optional<String> getBucketId() {
|
||||
return bucketId;
|
||||
}
|
||||
@@ -130,6 +138,7 @@ public class Media implements Parcelable {
|
||||
dest.writeInt(height);
|
||||
dest.writeLong(size);
|
||||
dest.writeLong(duration);
|
||||
dest.writeInt(borderless ? 1 : 0);
|
||||
dest.writeString(bucketId.orNull());
|
||||
dest.writeString(caption.orNull());
|
||||
dest.writeString(transformProperties.transform(JsonUtil::toJson).orNull());
|
||||
|
||||
@@ -217,7 +217,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(new Media(uri, mimetype, date, width, height, size, duration, Optional.of(bucketId), Optional.absent(), Optional.absent()));
|
||||
media.add(new Media(uri, mimetype, date, width, height, size, duration, false, Optional.of(bucketId), Optional.absent(), Optional.absent()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ public class MediaRepository {
|
||||
height = dimens.second;
|
||||
}
|
||||
|
||||
return new Media(media.getUri(), media.getMimeType(), media.getDate(), width, height, size, 0, media.getBucketId(), media.getCaption(), Optional.absent());
|
||||
return new Media(media.getUri(), media.getMimeType(), media.getDate(), width, height, size, 0, media.isBorderless(), media.getBucketId(), media.getCaption(), Optional.absent());
|
||||
}
|
||||
|
||||
private Media getContentResolverPopulatedMedia(@NonNull Context context, @NonNull Media media) throws IOException {
|
||||
@@ -337,7 +337,7 @@ public class MediaRepository {
|
||||
height = dimens.second;
|
||||
}
|
||||
|
||||
return new Media(media.getUri(), media.getMimeType(), media.getDate(), width, height, size, 0, media.getBucketId(), media.getCaption(), Optional.absent());
|
||||
return new Media(media.getUri(), media.getMimeType(), media.getDate(), width, height, size, 0, media.isBorderless(), media.getBucketId(), media.getCaption(), Optional.absent());
|
||||
}
|
||||
|
||||
private static class FolderResult {
|
||||
|
||||
@@ -411,21 +411,20 @@ public class MediaSendActivity extends PassphraseRequiredActivity implements Med
|
||||
long length = getLength.apply(data);
|
||||
|
||||
Uri uri = createBlobBuilder.apply(BlobProvider.getInstance(), data, length)
|
||||
.withMimeType(mimeType)
|
||||
.createForSingleSessionOnDisk(this);
|
||||
.withMimeType(mimeType)
|
||||
.createForSingleSessionOnDisk(this);
|
||||
|
||||
return new Media(
|
||||
uri,
|
||||
mimeType,
|
||||
System.currentTimeMillis(),
|
||||
width,
|
||||
height,
|
||||
length,
|
||||
0,
|
||||
Optional.of(Media.ALL_MEDIA_BUCKET_ID),
|
||||
Optional.absent(),
|
||||
Optional.absent()
|
||||
);
|
||||
return new Media(uri,
|
||||
mimeType,
|
||||
System.currentTimeMillis(),
|
||||
width,
|
||||
height,
|
||||
length,
|
||||
0,
|
||||
false,
|
||||
Optional.of(Media.ALL_MEDIA_BUCKET_ID),
|
||||
Optional.absent(),
|
||||
Optional.absent());
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -303,7 +303,7 @@ class MediaSendViewModel extends ViewModel {
|
||||
captionVisible = false;
|
||||
|
||||
List<Media> uncaptioned = Stream.of(getSelectedMediaOrDefault())
|
||||
.map(m -> new Media(m.getUri(), m.getMimeType(), m.getDate(), m.getWidth(), m.getHeight(), m.getSize(), m.getDuration(), m.getBucketId(), Optional.absent(), Optional.absent()))
|
||||
.map(m -> new Media(m.getUri(), m.getMimeType(), m.getDate(), m.getWidth(), m.getHeight(), m.getSize(), m.getDuration(), m.isBorderless(), m.getBucketId(), Optional.absent(), Optional.absent()))
|
||||
.toList();
|
||||
|
||||
selectedMedia.setValue(uncaptioned);
|
||||
@@ -406,7 +406,7 @@ class MediaSendViewModel extends ViewModel {
|
||||
}
|
||||
|
||||
void onVideoBeginEdit(@NonNull Uri uri) {
|
||||
cancelUpload(new Media(uri, "", 0, 0, 0, 0, 0, Optional.absent(), Optional.absent(), Optional.absent()));
|
||||
cancelUpload(new Media(uri, "", 0, 0, 0, 0, 0, false, Optional.absent(), Optional.absent(), Optional.absent()));
|
||||
}
|
||||
|
||||
void onMediaCaptured(@NonNull Media media) {
|
||||
@@ -485,7 +485,7 @@ class MediaSendViewModel extends ViewModel {
|
||||
|
||||
if (splitMessage.getTextSlide().isPresent()) {
|
||||
Slide slide = splitMessage.getTextSlide().get();
|
||||
uploadRepository.startUpload(new Media(Objects.requireNonNull(slide.getUri()), slide.getContentType(), System.currentTimeMillis(), 0, 0, slide.getFileSize(), 0, Optional.absent(), Optional.absent(), Optional.absent()), recipient);
|
||||
uploadRepository.startUpload(new Media(Objects.requireNonNull(slide.getUri()), slide.getContentType(), System.currentTimeMillis(), 0, 0, slide.getFileSize(), 0, slide.isBorderless(), Optional.absent(), Optional.absent(), Optional.absent()), recipient);
|
||||
}
|
||||
|
||||
uploadRepository.applyMediaUpdates(oldToNew, recipient);
|
||||
|
||||
@@ -193,9 +193,9 @@ class MediaUploadRepository {
|
||||
if (MediaUtil.isVideoType(media.getMimeType())) {
|
||||
return new VideoSlide(context, media.getUri(), 0, media.getCaption().orNull(), media.getTransformProperties().orNull()).asAttachment();
|
||||
} else if (MediaUtil.isGif(media.getMimeType())) {
|
||||
return new GifSlide(context, media.getUri(), 0, media.getWidth(), media.getHeight(), media.getCaption().orNull()).asAttachment();
|
||||
return new GifSlide(context, media.getUri(), 0, media.getWidth(), media.getHeight(), media.isBorderless(), media.getCaption().orNull()).asAttachment();
|
||||
} else if (MediaUtil.isImageType(media.getMimeType())) {
|
||||
return new ImageSlide(context, media.getUri(), 0, media.getWidth(), media.getHeight(), media.getCaption().orNull(), null).asAttachment();
|
||||
return new ImageSlide(context, media.getUri(), 0, media.getWidth(), media.getHeight(), media.isBorderless(), media.getCaption().orNull(), null).asAttachment();
|
||||
} else if (MediaUtil.isTextType(media.getMimeType())) {
|
||||
return new TextSlide(context, media.getUri(), null, media.getSize()).asAttachment();
|
||||
} else {
|
||||
|
||||
@@ -26,6 +26,7 @@ public final class VideoTrimTransform implements MediaTransform {
|
||||
media.getHeight(),
|
||||
media.getSize(),
|
||||
media.getDuration(),
|
||||
media.isBorderless(),
|
||||
media.getBucketId(),
|
||||
media.getCaption(),
|
||||
Optional.of(new AttachmentDatabase.TransformProperties(false, data.durationEdited, data.startTimeUs, data.endTimeUs)));
|
||||
|
||||
Reference in New Issue
Block a user