Properly check attachment size during media send.
Prevent users from trying to send videos that exceed the size limit. Also, this commit properly populates height/width on media shared into the app. Fixes #8573
This commit is contained in:
parent
a3768c7d74
commit
6896f8ea15
10 changed files with 169 additions and 25 deletions
|
@ -454,6 +454,7 @@
|
|||
|
||||
<!-- MediaSendActivity -->
|
||||
<string name="MediaSendActivity_add_a_caption">Add a caption...</string>
|
||||
<string name="MediaSendActivity_an_item_was_removed_because_it_exceeded_the_size_limit">An item was removed because it exceeded the size limit</string>
|
||||
|
||||
<!-- MediaRepository -->
|
||||
<string name="MediaRepository_all_media">All media</string>
|
||||
|
|
|
@ -1723,7 +1723,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||
openContactShareEditor(uri);
|
||||
return new SettableFuture<>(false);
|
||||
} else if (MediaType.IMAGE.equals(mediaType) || MediaType.GIF.equals(mediaType) || MediaType.VIDEO.equals(mediaType)) {
|
||||
Media media = new Media(uri, MediaUtil.getMimeType(this, uri), 0, width, height, Optional.absent(), Optional.absent());
|
||||
Media media = new Media(uri, MediaUtil.getMimeType(this, uri), 0, width, height, 0, Optional.absent(), Optional.absent());
|
||||
startActivityForResult(MediaSendActivity.getIntent(ConversationActivity.this, Collections.singletonList(media), recipient, composeText.getTextTrimmed(), sendButton.getSelectedTransport()), MEDIA_SENDER);
|
||||
return new SettableFuture<>(false);
|
||||
} else {
|
||||
|
@ -2368,7 +2368,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||
@Override
|
||||
public void onQuickAttachment(Uri uri, String mimeType, String bucketId, long dateTaken, int width, int height) {
|
||||
linkPreviewViewModel.onUserCancel();
|
||||
Media media = new Media(uri, mimeType, dateTaken, width, height, Optional.of(Media.ALL_MEDIA_BUCKET_ID), Optional.absent());
|
||||
// TODO: Carry over size?
|
||||
Media media = new Media(uri, mimeType, dateTaken, width, height, 0, Optional.of(Media.ALL_MEDIA_BUCKET_ID), Optional.absent());
|
||||
startActivityForResult(MediaSendActivity.getIntent(ConversationActivity.this, Collections.singletonList(media), recipient, composeText.getTextTrimmed(), sendButton.getSelectedTransport()), MEDIA_SENDER);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -537,6 +537,7 @@ public class ConversationFragment extends Fragment
|
|||
System.currentTimeMillis(),
|
||||
attachment.getWidth(),
|
||||
attachment.getHeight(),
|
||||
attachment.getSize(),
|
||||
Optional.absent(),
|
||||
Optional.fromNullable(attachment.getCaption())));
|
||||
}
|
||||
|
|
|
@ -105,6 +105,7 @@ public class MediaPreviewViewModel extends ViewModel {
|
|||
mediaRecord.getDate(),
|
||||
mediaRecord.getAttachment().getWidth(),
|
||||
mediaRecord.getAttachment().getHeight(),
|
||||
mediaRecord.getAttachment().getSize(),
|
||||
Optional.absent(),
|
||||
Optional.fromNullable(mediaRecord.getAttachment().getCaption()));
|
||||
}
|
||||
|
|
|
@ -19,16 +19,18 @@ public class Media implements Parcelable {
|
|||
private final long date;
|
||||
private final int width;
|
||||
private final int height;
|
||||
private final long size;
|
||||
|
||||
private Optional<String> bucketId;
|
||||
private Optional<String> caption;
|
||||
|
||||
public Media(@NonNull Uri uri, @NonNull String mimeType, long date, int width, int height, Optional<String> bucketId, 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) {
|
||||
this.uri = uri;
|
||||
this.mimeType = mimeType;
|
||||
this.date = date;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.size = size;
|
||||
this.bucketId = bucketId;
|
||||
this.caption = caption;
|
||||
}
|
||||
|
@ -39,6 +41,7 @@ public class Media implements Parcelable {
|
|||
date = in.readLong();
|
||||
width = in.readInt();
|
||||
height = in.readInt();
|
||||
size = in.readLong();
|
||||
bucketId = Optional.fromNullable(in.readString());
|
||||
caption = Optional.fromNullable(in.readString());
|
||||
}
|
||||
|
@ -63,6 +66,10 @@ public class Media implements Parcelable {
|
|||
return height;
|
||||
}
|
||||
|
||||
public long getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public Optional<String> getBucketId() {
|
||||
return bucketId;
|
||||
}
|
||||
|
@ -87,6 +94,7 @@ public class Media implements Parcelable {
|
|||
dest.writeLong(date);
|
||||
dest.writeInt(width);
|
||||
dest.writeInt(height);
|
||||
dest.writeLong(size);
|
||||
dest.writeString(bucketId.orNull());
|
||||
dest.writeString(caption.orNull());
|
||||
}
|
||||
|
|
|
@ -149,7 +149,7 @@ public class MediaPickerItemFragment extends Fragment implements MediaPickerItem
|
|||
@Override
|
||||
public void onMediaChosen(@NonNull Media media) {
|
||||
controller.onMediaSelected(bucketId, Collections.singleton(media));
|
||||
viewModel.onSelectedMediaChanged(Collections.singletonList(media));
|
||||
viewModel.onSelectedMediaChanged(requireContext(), Collections.singletonList(media));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -165,7 +165,7 @@ public class MediaPickerItemFragment extends Fragment implements MediaPickerItem
|
|||
actionMode.setTitle(String.valueOf(selected.size()));
|
||||
}
|
||||
|
||||
viewModel.onSelectedMediaChanged(selected);
|
||||
viewModel.onSelectedMediaChanged(requireContext(), selected);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -221,7 +221,7 @@ public class MediaPickerItemFragment extends Fragment implements MediaPickerItem
|
|||
if (menuItem.getItemId() == R.id.mediapicker_menu_confirm) {
|
||||
List<Media> selected = new ArrayList<>(adapter.getSelected());
|
||||
actionMode.finish();
|
||||
viewModel.onSelectedMediaChanged(selected);
|
||||
viewModel.onSelectedMediaChanged(requireContext(), selected);
|
||||
controller.onMediaSelected(bucketId, selected);
|
||||
return true;
|
||||
}
|
||||
|
@ -232,7 +232,7 @@ public class MediaPickerItemFragment extends Fragment implements MediaPickerItem
|
|||
public void onDestroyActionMode(ActionMode mode) {
|
||||
actionMode = null;
|
||||
adapter.setSelected(Collections.emptySet());
|
||||
viewModel.onSelectedMediaChanged(Collections.emptyList());
|
||||
viewModel.onSelectedMediaChanged(requireContext(), Collections.emptyList());
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
requireActivity().getWindow().setStatusBarColor(statusBarColor);
|
||||
|
|
|
@ -7,20 +7,24 @@ import android.net.Uri;
|
|||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.provider.MediaStore;
|
||||
import android.provider.MediaStore.Images;
|
||||
import android.provider.MediaStore.Video;
|
||||
import android.provider.OpenableColumns;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.WorkerThread;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -47,6 +51,19 @@ class MediaRepository {
|
|||
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> callback.onComplete(getMediaInBucket(context, bucketId)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an existing list of {@link Media}, this will ensure that the media is populate with as
|
||||
* much data as we have, like width/height.
|
||||
*/
|
||||
void getPopulatedMedia(@NonNull Context context, @NonNull List<Media> media, @NonNull Callback<List<Media>> callback) {
|
||||
if (Stream.of(media).allMatch(this::isPopulated)) {
|
||||
callback.onComplete(media);
|
||||
return;
|
||||
}
|
||||
|
||||
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> callback.onComplete(getPopulatedMedia(context, media)));
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private @NonNull List<MediaFolder> getFolders(@NonNull Context context) {
|
||||
FolderResult imageFolders = getFolders(context, Images.Media.EXTERNAL_CONTENT_URI);
|
||||
|
@ -151,11 +168,11 @@ class MediaRepository {
|
|||
String[] projection;
|
||||
|
||||
if (hasOrienation) {
|
||||
projection = Build.VERSION.SDK_INT >= 16 ? new String[]{Images.Media._ID, Images.Media.MIME_TYPE, Images.Media.DATE_TAKEN, Images.Media.ORIENTATION, Images.Media.WIDTH, Images.Media.HEIGHT}
|
||||
: new String[]{Images.Media._ID, Images.Media.MIME_TYPE, Images.Media.DATE_TAKEN, Images.Media.ORIENTATION};
|
||||
projection = Build.VERSION.SDK_INT >= 16 ? new String[]{Images.Media._ID, Images.Media.MIME_TYPE, Images.Media.DATE_TAKEN, Images.Media.ORIENTATION, Images.Media.WIDTH, Images.Media.HEIGHT, Images.Media.SIZE}
|
||||
: new String[]{Images.Media._ID, Images.Media.MIME_TYPE, Images.Media.DATE_TAKEN, Images.Media.ORIENTATION, Images.Media.SIZE};
|
||||
} else {
|
||||
projection = Build.VERSION.SDK_INT >= 16 ? new String[]{Images.Media._ID, Images.Media.MIME_TYPE, Images.Media.DATE_TAKEN, Images.Media.WIDTH, Images.Media.HEIGHT}
|
||||
: new String[]{Images.Media._ID, Images.Media.MIME_TYPE, Images.Media.DATE_TAKEN };
|
||||
projection = Build.VERSION.SDK_INT >= 16 ? new String[]{Images.Media._ID, Images.Media.MIME_TYPE, Images.Media.DATE_TAKEN, Images.Media.WIDTH, Images.Media.HEIGHT, Images.Media.SIZE}
|
||||
: new String[]{Images.Media._ID, Images.Media.MIME_TYPE, Images.Media.DATE_TAKEN, Images.Media.SIZE};
|
||||
}
|
||||
|
||||
if (Media.ALL_MEDIA_BUCKET_ID.equals(bucketId)) {
|
||||
|
@ -171,19 +188,36 @@ class MediaRepository {
|
|||
int orientation = hasOrienation ? cursor.getInt(cursor.getColumnIndexOrThrow(Images.Media.ORIENTATION)) : 0;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
long size = cursor.getLong(cursor.getColumnIndexOrThrow(Images.Media.SIZE));
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 16) {
|
||||
width = cursor.getInt(cursor.getColumnIndexOrThrow(getWidthColumn(orientation)));
|
||||
height = cursor.getInt(cursor.getColumnIndexOrThrow(getHeightColumn(orientation)));
|
||||
}
|
||||
|
||||
media.add(new Media(uri, mimetype, dateTaken, width, height, Optional.of(bucketId), Optional.absent()));
|
||||
media.add(new Media(uri, mimetype, dateTaken, width, height, size, Optional.of(bucketId), Optional.absent()));
|
||||
}
|
||||
}
|
||||
|
||||
return media;
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private List<Media> getPopulatedMedia(@NonNull Context context, @NonNull List<Media> media) {
|
||||
return Stream.of(media).map(m -> {
|
||||
try {
|
||||
if (isPopulated(m)) {
|
||||
return m;
|
||||
} else if (PartAuthority.isLocalUri(m.getUri())) {
|
||||
return getLocallyPopulatedMedia(context, m);
|
||||
} else {
|
||||
return getContentResolverPopulatedMedia(context, m);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
return m;
|
||||
}
|
||||
}).toList();
|
||||
}
|
||||
|
||||
@TargetApi(16)
|
||||
@SuppressWarnings("SuspiciousNameCombination")
|
||||
|
@ -199,6 +233,59 @@ class MediaRepository {
|
|||
else return Images.Media.WIDTH;
|
||||
}
|
||||
|
||||
private boolean isPopulated(@NonNull Media media) {
|
||||
return media.getWidth() > 0 && media.getHeight() > 0 && media.getSize() > 0;
|
||||
}
|
||||
|
||||
private Media getLocallyPopulatedMedia(@NonNull Context context, @NonNull Media media) throws IOException {
|
||||
int width = media.getWidth();
|
||||
int height = media.getHeight();
|
||||
long size = media.getSize();
|
||||
|
||||
if (size <= 0) {
|
||||
Optional<Long> optionalSize = Optional.fromNullable(PartAuthority.getAttachmentSize(context, media.getUri()));
|
||||
size = optionalSize.isPresent() ? optionalSize.get() : 0;
|
||||
}
|
||||
|
||||
if (size <= 0) {
|
||||
size = MediaUtil.getMediaSize(context, media.getUri());
|
||||
}
|
||||
|
||||
if (width == 0 || height == 0) {
|
||||
Pair<Integer, Integer> dimens = MediaUtil.getDimensions(context, media.getMimeType(), media.getUri());
|
||||
width = dimens.first;
|
||||
height = dimens.second;
|
||||
}
|
||||
|
||||
return new Media(media.getUri(), media.getMimeType(), media.getDate(), width, height, size, media.getBucketId(), media.getCaption());
|
||||
}
|
||||
|
||||
private Media getContentResolverPopulatedMedia(@NonNull Context context, @NonNull Media media) throws IOException {
|
||||
int width = media.getWidth();
|
||||
int height = media.getHeight();
|
||||
long size = media.getSize();
|
||||
|
||||
if (size <= 0) {
|
||||
try (Cursor cursor = context.getContentResolver().query(media.getUri(), null, null, null, null)) {
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
size = cursor.getLong(cursor.getColumnIndexOrThrow(OpenableColumns.SIZE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (size <= 0) {
|
||||
size = MediaUtil.getMediaSize(context, media.getUri());
|
||||
}
|
||||
|
||||
if (width == 0 || height == 0) {
|
||||
Pair<Integer, Integer> dimens = MediaUtil.getDimensions(context, media.getMimeType(), media.getUri());
|
||||
width = dimens.first;
|
||||
height = dimens.second;
|
||||
}
|
||||
|
||||
return new Media(media.getUri(), media.getMimeType(), media.getDate(), width, height, size, media.getBucketId(), media.getCaption());
|
||||
}
|
||||
|
||||
private static class FolderResult {
|
||||
private final String cameraBucketId;
|
||||
private final Uri thumbnail;
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity;
|
|||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.TransportOption;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.mms.MediaConstraints;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.scribbles.ScribbleFragment;
|
||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||
|
@ -105,6 +106,9 @@ public class MediaSendActivity extends PassphraseRequiredActionBarActivity imple
|
|||
body = getIntent().getStringExtra(KEY_BODY);
|
||||
transport = getIntent().getParcelableExtra(KEY_TRANSPORT);
|
||||
|
||||
viewModel.setMediaConstraints(transport.isSms() ? MediaConstraints.getMmsMediaConstraints(transport.getSimSubscriptionId().or(-1))
|
||||
: MediaConstraints.getPushMediaConstraints());
|
||||
|
||||
List<Media> media = getIntent().getParcelableArrayListExtra(KEY_MEDIA);
|
||||
|
||||
if (!Util.isEmpty(media)) {
|
||||
|
@ -211,7 +215,7 @@ public class MediaSendActivity extends PassphraseRequiredActionBarActivity imple
|
|||
}
|
||||
|
||||
private void navigateToMediaSend(List<Media> media, String body, TransportOption transport) {
|
||||
viewModel.setInitialSelectedMedia(media);
|
||||
viewModel.setInitialSelectedMedia(this, media);
|
||||
|
||||
MediaSendFragment sendFragment = MediaSendFragment.newInstance(body, transport, dynamicLanguage.getCurrentLocale());
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
|
|
|
@ -27,6 +27,7 @@ import android.view.ViewGroup;
|
|||
import android.view.ViewTreeObserver;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.TransportOption;
|
||||
|
@ -334,6 +335,12 @@ public class MediaSendFragment extends Fragment implements ViewTreeObserver.OnGl
|
|||
addButton.setOnClickListener(v -> controller.onAddMediaClicked(bucketId.get()));
|
||||
}
|
||||
});
|
||||
|
||||
viewModel.getError().observe(this, error -> {
|
||||
if (error == MediaSendViewModel.Error.ITEM_TOO_LARGE) {
|
||||
Toast.makeText(requireContext(), R.string.MediaSendActivity_an_item_was_removed_because_it_exceeded_the_size_limit, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private EmojiEditText getActiveInputField() {
|
||||
|
@ -428,7 +435,7 @@ public class MediaSendFragment extends Fragment implements ViewTreeObserver.OnGl
|
|||
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, baos);
|
||||
|
||||
Uri uri = PersistentBlobProvider.getInstance(context).create(context, baos.toByteArray(), MediaUtil.IMAGE_JPEG, null);
|
||||
Media updated = new Media(uri, MediaUtil.IMAGE_JPEG, media.getDate(), bitmap.getWidth(), bitmap.getHeight(), media.getBucketId(), media.getCaption());
|
||||
Media updated = new Media(uri, MediaUtil.IMAGE_JPEG, media.getDate(), bitmap.getWidth(), bitmap.getHeight(), baos.size(), media.getBucketId(), media.getCaption());
|
||||
|
||||
updatedMedia.add(updated);
|
||||
renderTimer.split("item");
|
||||
|
|
|
@ -11,7 +11,9 @@ import android.text.TextUtils;
|
|||
|
||||
import com.annimon.stream.Stream;
|
||||
|
||||
import org.thoughtcrime.securesms.mms.MediaConstraints;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.SingleLiveEvent;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
|
@ -31,8 +33,11 @@ class MediaSendViewModel extends ViewModel {
|
|||
private final MutableLiveData<Integer> position;
|
||||
private final MutableLiveData<Optional<String>> bucketId;
|
||||
private final MutableLiveData<List<MediaFolder>> folders;
|
||||
private final SingleLiveEvent<Error> error;
|
||||
private final Map<Uri, Object> savedDrawState;
|
||||
|
||||
private MediaConstraints mediaConstraints;
|
||||
|
||||
private MediaSendViewModel(@NonNull MediaRepository repository) {
|
||||
this.repository = repository;
|
||||
this.selectedMedia = new MutableLiveData<>();
|
||||
|
@ -40,21 +45,37 @@ class MediaSendViewModel extends ViewModel {
|
|||
this.position = new MutableLiveData<>();
|
||||
this.bucketId = new MutableLiveData<>();
|
||||
this.folders = new MutableLiveData<>();
|
||||
this.error = new SingleLiveEvent<>();
|
||||
this.savedDrawState = new HashMap<>();
|
||||
|
||||
position.setValue(-1);
|
||||
}
|
||||
|
||||
void setInitialSelectedMedia(@NonNull List<Media> newMedia) {
|
||||
List<Media> filteredMedia = getFilteredMedia(newMedia);
|
||||
boolean allBucketsPopulated = Stream.of(filteredMedia).reduce(true, (populated, m) -> populated && m.getBucketId().isPresent());
|
||||
|
||||
selectedMedia.setValue(filteredMedia);
|
||||
bucketId.setValue(allBucketsPopulated ? computeBucketId(filteredMedia) : Optional.absent());
|
||||
void setMediaConstraints(@NonNull MediaConstraints mediaConstraints) {
|
||||
this.mediaConstraints = mediaConstraints;
|
||||
}
|
||||
|
||||
void onSelectedMediaChanged(@NonNull List<Media> newMedia) {
|
||||
List<Media> filteredMedia = getFilteredMedia(newMedia);
|
||||
void setInitialSelectedMedia(@NonNull Context context, @NonNull List<Media> newMedia) {
|
||||
repository.getPopulatedMedia(context, newMedia, populatedMedia -> {
|
||||
List<Media> filteredMedia = getFilteredMedia(context, populatedMedia, mediaConstraints);
|
||||
|
||||
if (filteredMedia.size() != newMedia.size()) {
|
||||
error.postValue(Error.ITEM_TOO_LARGE);
|
||||
}
|
||||
|
||||
boolean allBucketsPopulated = Stream.of(filteredMedia).reduce(true, (populated, m) -> populated && m.getBucketId().isPresent());
|
||||
|
||||
selectedMedia.postValue(filteredMedia);
|
||||
bucketId.postValue(allBucketsPopulated ? computeBucketId(filteredMedia) : Optional.absent());
|
||||
});
|
||||
}
|
||||
|
||||
void onSelectedMediaChanged(@NonNull Context context, @NonNull List<Media> newMedia) {
|
||||
List<Media> filteredMedia = getFilteredMedia(context, newMedia, mediaConstraints);
|
||||
|
||||
if (filteredMedia.size() != newMedia.size()) {
|
||||
error.setValue(Error.ITEM_TOO_LARGE);
|
||||
}
|
||||
|
||||
selectedMedia.setValue(filteredMedia);
|
||||
position.setValue(filteredMedia.isEmpty() ? -1 : 0);
|
||||
|
@ -111,6 +132,10 @@ class MediaSendViewModel extends ViewModel {
|
|||
return bucketId;
|
||||
}
|
||||
|
||||
LiveData<Error> getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
private Optional<String> computeBucketId(@NonNull List<Media> media) {
|
||||
if (media.isEmpty() || !media.get(0).getBucketId().isPresent()) return Optional.absent();
|
||||
|
||||
|
@ -124,13 +149,22 @@ class MediaSendViewModel extends ViewModel {
|
|||
return Optional.of(candidate);
|
||||
}
|
||||
|
||||
private @NonNull List<Media> getFilteredMedia(@NonNull List<Media> media) {
|
||||
private @NonNull List<Media> getFilteredMedia(@NonNull Context context, @NonNull List<Media> media, @NonNull MediaConstraints mediaConstraints) {
|
||||
return Stream.of(media).filter(m -> MediaUtil.isGif(m.getMimeType()) ||
|
||||
MediaUtil.isImageType(m.getMimeType()) ||
|
||||
MediaUtil.isVideoType(m.getMimeType())).toList();
|
||||
MediaUtil.isVideoType(m.getMimeType()))
|
||||
.filter(m -> {
|
||||
return (MediaUtil.isImageType(m.getMimeType()) && !MediaUtil.isGif(m.getMimeType())) ||
|
||||
(MediaUtil.isGif(m.getMimeType()) && m.getSize() < mediaConstraints.getGifMaxSize(context)) ||
|
||||
(MediaUtil.isVideoType(m.getMimeType()) && m.getSize() < mediaConstraints.getVideoMaxSize(context));
|
||||
}).toList();
|
||||
|
||||
}
|
||||
|
||||
enum Error {
|
||||
ITEM_TOO_LARGE
|
||||
}
|
||||
|
||||
static class Factory extends ViewModelProvider.NewInstanceFactory {
|
||||
|
||||
private final MediaRepository repository;
|
||||
|
|
Loading…
Add table
Reference in a new issue