mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-26 11:51:10 +01:00
Implement new attachment keyboard.
Such beauty. Such grace.
This commit is contained in:
committed by
Alex Hart
parent
9f7b2e2cfd
commit
109d67956f
@@ -20,17 +20,28 @@ public class Media implements Parcelable {
|
||||
private final int width;
|
||||
private final int height;
|
||||
private final long size;
|
||||
private final long duration;
|
||||
|
||||
private Optional<String> bucketId;
|
||||
private Optional<String> caption;
|
||||
|
||||
public Media(@NonNull Uri uri, @NonNull String mimeType, long date, int width, int height, long size, Optional<String> bucketId, Optional<String> caption) {
|
||||
public Media(@NonNull Uri uri,
|
||||
@NonNull String mimeType,
|
||||
long date,
|
||||
int width,
|
||||
int height,
|
||||
long size,
|
||||
long duration,
|
||||
Optional<String> bucketId,
|
||||
Optional<String> caption)
|
||||
{
|
||||
this.uri = uri;
|
||||
this.mimeType = mimeType;
|
||||
this.date = date;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.size = size;
|
||||
this.duration = duration;
|
||||
this.bucketId = bucketId;
|
||||
this.caption = caption;
|
||||
}
|
||||
@@ -42,6 +53,7 @@ public class Media implements Parcelable {
|
||||
width = in.readInt();
|
||||
height = in.readInt();
|
||||
size = in.readLong();
|
||||
duration = in.readLong();
|
||||
bucketId = Optional.fromNullable(in.readString());
|
||||
caption = Optional.fromNullable(in.readString());
|
||||
}
|
||||
@@ -70,6 +82,10 @@ public class Media implements Parcelable {
|
||||
return size;
|
||||
}
|
||||
|
||||
public long getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public Optional<String> getBucketId() {
|
||||
return bucketId;
|
||||
}
|
||||
@@ -95,6 +111,7 @@ public class Media implements Parcelable {
|
||||
dest.writeInt(width);
|
||||
dest.writeInt(height);
|
||||
dest.writeLong(size);
|
||||
dest.writeLong(duration);
|
||||
dest.writeString(bucketId.orNull());
|
||||
dest.writeString(caption.orNull());
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ import java.util.Map;
|
||||
/**
|
||||
* Handles the retrieval of media present on the user's device.
|
||||
*/
|
||||
class MediaRepository {
|
||||
public class MediaRepository {
|
||||
|
||||
private static final String TAG = Log.tag(MediaRepository.class);
|
||||
|
||||
@@ -56,7 +56,7 @@ class MediaRepository {
|
||||
/**
|
||||
* Retrieves a list of media items (images and videos) that are present int he specified bucket.
|
||||
*/
|
||||
void getMediaInBucket(@NonNull Context context, @NonNull String bucketId, @NonNull Callback<List<Media>> callback) {
|
||||
public void getMediaInBucket(@NonNull Context context, @NonNull String bucketId, @NonNull Callback<List<Media>> callback) {
|
||||
SignalExecutors.BOUNDED.execute(() -> callback.onComplete(getMediaInBucket(context, bucketId)));
|
||||
}
|
||||
|
||||
@@ -141,9 +141,9 @@ class MediaRepository {
|
||||
long thumbnailTimestamp = 0;
|
||||
Map<String, FolderData> folders = new HashMap<>();
|
||||
|
||||
String[] projection = new String[] { Images.Media.DATA, Images.Media.BUCKET_ID, Images.Media.BUCKET_DISPLAY_NAME, Images.Media.DATE_TAKEN };
|
||||
String[] projection = new String[] { Images.Media.DATA, Images.Media.BUCKET_ID, Images.Media.BUCKET_DISPLAY_NAME, Images.Media.DATE_MODIFIED };
|
||||
String selection = Images.Media.DATA + " NOT NULL";
|
||||
String sortBy = Images.Media.BUCKET_DISPLAY_NAME + " COLLATE NOCASE ASC, " + Images.Media.DATE_TAKEN + " DESC";
|
||||
String sortBy = Images.Media.BUCKET_DISPLAY_NAME + " COLLATE NOCASE ASC, " + Images.Media.DATE_MODIFIED + " DESC";
|
||||
|
||||
try (Cursor cursor = context.getContentResolver().query(contentUri, projection, selection, null, sortBy)) {
|
||||
while (cursor != null && cursor.moveToNext()) {
|
||||
@@ -189,18 +189,18 @@ class MediaRepository {
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private @NonNull List<Media> getMediaInBucket(@NonNull Context context, @NonNull String bucketId, @NonNull Uri contentUri, boolean hasOrientation) {
|
||||
private @NonNull List<Media> getMediaInBucket(@NonNull Context context, @NonNull String bucketId, @NonNull Uri contentUri, boolean isImage) {
|
||||
List<Media> media = new LinkedList<>();
|
||||
String selection = Images.Media.BUCKET_ID + " = ? AND " + Images.Media.DATA + " NOT NULL";
|
||||
String[] selectionArgs = new String[] { bucketId };
|
||||
String sortBy = Images.Media.DATE_TAKEN + " DESC";
|
||||
String sortBy = Images.Media.DATE_MODIFIED + " DESC";
|
||||
|
||||
String[] projection;
|
||||
|
||||
if (hasOrientation) {
|
||||
projection = new String[]{Images.Media.DATA, Images.Media.MIME_TYPE, Images.Media.DATE_TAKEN, Images.Media.ORIENTATION, Images.Media.WIDTH, Images.Media.HEIGHT, Images.Media.SIZE};
|
||||
if (isImage) {
|
||||
projection = new String[]{Images.Media.DATA, Images.Media.MIME_TYPE, Images.Media.DATE_MODIFIED, Images.Media.ORIENTATION, Images.Media.WIDTH, Images.Media.HEIGHT, Images.Media.SIZE};
|
||||
} else {
|
||||
projection = new String[]{Images.Media.DATA, Images.Media.MIME_TYPE, Images.Media.DATE_TAKEN, Images.Media.WIDTH, Images.Media.HEIGHT, Images.Media.SIZE};
|
||||
projection = new String[]{Images.Media.DATA, Images.Media.MIME_TYPE, Images.Media.DATE_MODIFIED, Images.Media.WIDTH, Images.Media.HEIGHT, Images.Media.SIZE, Video.Media.DURATION};
|
||||
}
|
||||
|
||||
if (Media.ALL_MEDIA_BUCKET_ID.equals(bucketId)) {
|
||||
@@ -213,13 +213,14 @@ class MediaRepository {
|
||||
String path = cursor.getString(cursor.getColumnIndexOrThrow(projection[0]));
|
||||
Uri uri = Uri.fromFile(new File(path));
|
||||
String mimetype = cursor.getString(cursor.getColumnIndexOrThrow(Images.Media.MIME_TYPE));
|
||||
long dateTaken = cursor.getLong(cursor.getColumnIndexOrThrow(Images.Media.DATE_TAKEN));
|
||||
int orientation = hasOrientation ? cursor.getInt(cursor.getColumnIndexOrThrow(Images.Media.ORIENTATION)) : 0;
|
||||
long date = cursor.getLong(cursor.getColumnIndexOrThrow(Images.Media.DATE_MODIFIED));
|
||||
int orientation = isImage ? cursor.getInt(cursor.getColumnIndexOrThrow(Images.Media.ORIENTATION)) : 0;
|
||||
int width = cursor.getInt(cursor.getColumnIndexOrThrow(getWidthColumn(orientation)));
|
||||
int height = cursor.getInt(cursor.getColumnIndexOrThrow(getHeightColumn(orientation)));
|
||||
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, dateTaken, width, height, size, Optional.of(bucketId), Optional.absent()));
|
||||
media.add(new Media(uri, mimetype, date, width, height, size, duration, Optional.of(bucketId), Optional.absent()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,7 +269,7 @@ class MediaRepository {
|
||||
.withMimeType(MediaUtil.IMAGE_JPEG)
|
||||
.createForSingleSessionOnDisk(context);
|
||||
|
||||
Media updated = new Media(uri, MediaUtil.IMAGE_JPEG, media.getDate(), bitmap.getWidth(), bitmap.getHeight(), outputStream.size(), media.getBucketId(), media.getCaption());
|
||||
Media updated = new Media(uri, MediaUtil.IMAGE_JPEG, media.getDate(), bitmap.getWidth(), bitmap.getHeight(), outputStream.size(), 0, media.getBucketId(), media.getCaption());
|
||||
|
||||
updatedMedia.put(media, updated);
|
||||
} catch (IOException e) {
|
||||
@@ -332,7 +333,7 @@ class MediaRepository {
|
||||
height = dimens.second;
|
||||
}
|
||||
|
||||
return new Media(media.getUri(), media.getMimeType(), media.getDate(), width, height, size, media.getBucketId(), media.getCaption());
|
||||
return new Media(media.getUri(), media.getMimeType(), media.getDate(), width, height, size, 0, media.getBucketId(), media.getCaption());
|
||||
}
|
||||
|
||||
private Media getContentResolverPopulatedMedia(@NonNull Context context, @NonNull Media media) throws IOException {
|
||||
@@ -358,7 +359,7 @@ class MediaRepository {
|
||||
height = dimens.second;
|
||||
}
|
||||
|
||||
return new Media(media.getUri(), media.getMimeType(), media.getDate(), width, height, size, media.getBucketId(), media.getCaption());
|
||||
return new Media(media.getUri(), media.getMimeType(), media.getDate(), width, height, size, 0, media.getBucketId(), media.getCaption());
|
||||
}
|
||||
|
||||
private static class FolderResult {
|
||||
@@ -433,7 +434,7 @@ class MediaRepository {
|
||||
}
|
||||
}
|
||||
|
||||
interface Callback<E> {
|
||||
public interface Callback<E> {
|
||||
void onComplete(@NonNull E result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -412,6 +412,7 @@ public class MediaSendActivity extends PassphraseRequiredActionBarActivity imple
|
||||
width,
|
||||
height,
|
||||
length,
|
||||
0,
|
||||
Optional.of(Media.ALL_MEDIA_BUCKET_ID),
|
||||
Optional.absent()
|
||||
);
|
||||
|
||||
@@ -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.getBucketId(), Optional.absent()))
|
||||
.map(m -> new Media(m.getUri(), m.getMimeType(), m.getDate(), m.getWidth(), m.getHeight(), m.getSize(), m.getDuration(), m.getBucketId(), Optional.absent()))
|
||||
.toList();
|
||||
|
||||
selectedMedia.setValue(uncaptioned);
|
||||
@@ -476,7 +476,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(), Optional.absent(), Optional.absent()), recipient);
|
||||
uploadRepository.startUpload(new Media(Objects.requireNonNull(slide.getUri()), slide.getContentType(), System.currentTimeMillis(), 0, 0, slide.getFileSize(), 0, Optional.absent(), Optional.absent()), recipient);
|
||||
}
|
||||
|
||||
uploadRepository.applyMediaUpdates(oldToNew, recipient);
|
||||
|
||||
Reference in New Issue
Block a user