From 932e7b4af51f8429240a7e3a7cbab2b2ca789f61 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Tue, 19 Mar 2019 16:11:46 -0700 Subject: [PATCH] Fix button flicker when selecting single media item. --- res/layout/mediasend_activity.xml | 3 +- res/menu/mediapicker_multiselect.xml | 11 --- .../mediasend/MediaPickerItemAdapter.java | 4 + .../mediasend/MediaPickerItemFragment.java | 16 ++-- .../mediasend/MediaSendActivity.java | 7 +- .../mediasend/MediaSendFragment.java | 1 - .../mediasend/MediaSendViewModel.java | 84 ++++++++++++------- 7 files changed, 74 insertions(+), 52 deletions(-) delete mode 100644 res/menu/mediapicker_multiselect.xml diff --git a/res/layout/mediasend_activity.xml b/res/layout/mediasend_activity.xml index 8285b524c1..b2f44fb488 100644 --- a/res/layout/mediasend_activity.xml +++ b/res/layout/mediasend_activity.xml @@ -23,7 +23,8 @@ android:orientation="horizontal" android:background="@drawable/media_count_button_background" android:elevation="4dp" - tools:parentTag="android.widget.LinearLayout"> + android:visibility="gone" + tools:visibility="visible"> - - - - - diff --git a/src/org/thoughtcrime/securesms/mediasend/MediaPickerItemAdapter.java b/src/org/thoughtcrime/securesms/mediasend/MediaPickerItemAdapter.java index d718f99bb7..5a80788965 100644 --- a/src/org/thoughtcrime/securesms/mediasend/MediaPickerItemAdapter.java +++ b/src/org/thoughtcrime/securesms/mediasend/MediaPickerItemAdapter.java @@ -128,6 +128,7 @@ public class MediaPickerItemAdapter extends RecyclerView.Adapter 1) { itemView.setOnLongClickListener(v -> { selected.add(media); + eventListener.onMediaSelectionStarted(); eventListener.onMediaSelectionChanged(new ArrayList<>(selected)); return true; }); @@ -137,6 +138,7 @@ public class MediaPickerItemAdapter extends RecyclerView.Adapter { selected.remove(media); eventListener.onMediaSelectionChanged(new ArrayList<>(selected)); @@ -145,6 +147,7 @@ public class MediaPickerItemAdapter extends RecyclerView.Adapter { if (selected.size() < maxSelection) { selected.add(media); @@ -165,6 +168,7 @@ public class MediaPickerItemAdapter extends RecyclerView.Adapter media); void onMediaSelectionOverflow(int maxSelection); } diff --git a/src/org/thoughtcrime/securesms/mediasend/MediaPickerItemFragment.java b/src/org/thoughtcrime/securesms/mediasend/MediaPickerItemFragment.java index ffa3d5f615..d8eb218c9f 100644 --- a/src/org/thoughtcrime/securesms/mediasend/MediaPickerItemFragment.java +++ b/src/org/thoughtcrime/securesms/mediasend/MediaPickerItemFragment.java @@ -120,10 +120,10 @@ public class MediaPickerItemFragment extends Fragment implements MediaPickerItem @Override public void onPrepareOptionsMenu(Menu menu) { + requireActivity().getMenuInflater().inflate(R.menu.mediapicker_default, menu); + if (viewModel.getCountButtonState().getValue() != null && viewModel.getCountButtonState().getValue().isVisible()) { - requireActivity().getMenuInflater().inflate(R.menu.mediapicker_multiselect, menu); - } else { - requireActivity().getMenuInflater().inflate(R.menu.mediapicker_default, menu); + menu.findItem(R.id.mediapicker_menu_add).setVisible(false); } } @@ -146,8 +146,12 @@ public class MediaPickerItemFragment extends Fragment implements MediaPickerItem @Override public void onMediaChosen(@NonNull Media media) { - viewModel.onSelectedMediaChanged(requireContext(), Collections.singletonList(media)); - controller.onMediaSelected(bucketId); + controller.onMediaSelected(media); + } + + @Override + public void onMediaSelectionStarted() { + viewModel.onMultiSelectStarted(); } @Override @@ -188,6 +192,6 @@ public class MediaPickerItemFragment extends Fragment implements MediaPickerItem } public interface Controller { - void onMediaSelected(@NonNull String bucketId); + void onMediaSelected(@NonNull Media media); } } diff --git a/src/org/thoughtcrime/securesms/mediasend/MediaSendActivity.java b/src/org/thoughtcrime/securesms/mediasend/MediaSendActivity.java index 3bd551bdba..18f6cb5f5c 100644 --- a/src/org/thoughtcrime/securesms/mediasend/MediaSendActivity.java +++ b/src/org/thoughtcrime/securesms/mediasend/MediaSendActivity.java @@ -220,7 +220,8 @@ public class MediaSendActivity extends PassphraseRequiredActionBarActivity imple } @Override - public void onMediaSelected(@NonNull String bucketId) { + public void onMediaSelected(@NonNull Media media) { + viewModel.onSingleMediaSelected(this, media); navigateToMediaSend(recipient, transport, dynamicLanguage.getCurrentLocale()); } @@ -339,7 +340,9 @@ public class MediaSendActivity extends PassphraseRequiredActionBarActivity imple if (buttonState.getCount() > 0) { countButton.setOnClickListener(v -> navigateToMediaSend(recipient, transport, locale)); - animateButtonTextChange(countButton); + if (buttonState.isVisible()) { + animateButtonTextChange(countButton); + } } else { countButton.setOnClickListener(null); } diff --git a/src/org/thoughtcrime/securesms/mediasend/MediaSendFragment.java b/src/org/thoughtcrime/securesms/mediasend/MediaSendFragment.java index 49eb505d54..4ad6708209 100644 --- a/src/org/thoughtcrime/securesms/mediasend/MediaSendFragment.java +++ b/src/org/thoughtcrime/securesms/mediasend/MediaSendFragment.java @@ -241,7 +241,6 @@ public class MediaSendFragment extends Fragment implements ViewTreeObserver.OnGl super.onStop(); fragmentPagerAdapter.saveAllState(); viewModel.saveDrawState(fragmentPagerAdapter.getSavedState()); - viewModel.onImageEditorEnded(); } @Override diff --git a/src/org/thoughtcrime/securesms/mediasend/MediaSendViewModel.java b/src/org/thoughtcrime/securesms/mediasend/MediaSendViewModel.java index a4c674461d..7f971337c9 100644 --- a/src/org/thoughtcrime/securesms/mediasend/MediaSendViewModel.java +++ b/src/org/thoughtcrime/securesms/mediasend/MediaSendViewModel.java @@ -65,12 +65,12 @@ class MediaSendViewModel extends ViewModel { this.cameraButtonVisibility = new MutableLiveData<>(); this.error = new SingleLiveEvent<>(); this.savedDrawState = new HashMap<>(); - this.countButtonVisibility = CountButtonState.Visibility.CONDITIONAL; + this.countButtonVisibility = CountButtonState.Visibility.FORCED_OFF; this.lastImageCapture = Optional.absent(); this.body = ""; position.setValue(-1); - countButtonState.setValue(new CountButtonState(0, CountButtonState.Visibility.CONDITIONAL)); + countButtonState.setValue(new CountButtonState(0, countButtonVisibility)); cameraButtonVisibility.setValue(false); } @@ -86,33 +86,54 @@ class MediaSendViewModel extends ViewModel { void onSelectedMediaChanged(@NonNull Context context, @NonNull List newMedia) { repository.getPopulatedMedia(context, newMedia, populatedMedia -> { - List filteredMedia = getFilteredMedia(context, populatedMedia, mediaConstraints); + Util.runOnMain(() -> { - if (filteredMedia.size() != newMedia.size()) { - error.postValue(Error.ITEM_TOO_LARGE); - } else if (filteredMedia.size() > maxSelection) { - filteredMedia = filteredMedia.subList(0, maxSelection); - error.postValue(Error.TOO_MANY_ITEMS); - } + List filteredMedia = getFilteredMedia(context, populatedMedia, mediaConstraints); - if (filteredMedia.size() > 0) { - String computedId = Stream.of(filteredMedia) - .skip(1) - .reduce(filteredMedia.get(0).getBucketId().or(Media.ALL_MEDIA_BUCKET_ID), (id, m) -> { - if (Util.equals(id, m.getBucketId().or(Media.ALL_MEDIA_BUCKET_ID))) { - return id; - } else { - return Media.ALL_MEDIA_BUCKET_ID; - } - }); - bucketId.postValue(computedId); - } else { - bucketId.postValue(Media.ALL_MEDIA_BUCKET_ID); - countButtonVisibility = CountButtonState.Visibility.CONDITIONAL; - } + if (filteredMedia.size() != newMedia.size()) { + error.setValue(Error.ITEM_TOO_LARGE); + } else if (filteredMedia.size() > maxSelection) { + filteredMedia = filteredMedia.subList(0, maxSelection); + error.setValue(Error.TOO_MANY_ITEMS); + } - selectedMedia.postValue(filteredMedia); - countButtonState.postValue(new CountButtonState(filteredMedia.size(), countButtonVisibility)); + if (filteredMedia.size() > 0) { + String computedId = Stream.of(filteredMedia) + .skip(1) + .reduce(filteredMedia.get(0).getBucketId().or(Media.ALL_MEDIA_BUCKET_ID), (id, m) -> { + if (Util.equals(id, m.getBucketId().or(Media.ALL_MEDIA_BUCKET_ID))) { + return id; + } else { + return Media.ALL_MEDIA_BUCKET_ID; + } + }); + bucketId.setValue(computedId); + } else { + bucketId.setValue(Media.ALL_MEDIA_BUCKET_ID); + countButtonVisibility = CountButtonState.Visibility.CONDITIONAL; + } + + selectedMedia.setValue(filteredMedia); + countButtonState.setValue(new CountButtonState(filteredMedia.size(), countButtonVisibility)); + }); + }); + } + + void onSingleMediaSelected(@NonNull Context context, @NonNull Media media) { + repository.getPopulatedMedia(context, Collections.singletonList(media), populatedMedia -> { + Util.runOnMain(() -> { + List filteredMedia = getFilteredMedia(context, populatedMedia, mediaConstraints); + + if (filteredMedia.isEmpty()) { + error.setValue(Error.ITEM_TOO_LARGE); + } + + countButtonVisibility = CountButtonState.Visibility.FORCED_OFF; + + bucketId.setValue(filteredMedia.get(0).getBucketId().or(Media.ALL_MEDIA_BUCKET_ID)); + selectedMedia.setValue(filteredMedia); + countButtonState.setValue(new CountButtonState(filteredMedia.size(), countButtonVisibility)); + }); }); } @@ -127,20 +148,21 @@ class MediaSendViewModel extends ViewModel { cameraButtonVisibility.setValue(false); } - void onImageEditorEnded() { + void onCameraStarted() { countButtonVisibility = CountButtonState.Visibility.CONDITIONAL; countButtonState.setValue(new CountButtonState(getSelectedMediaOrDefault().size(), countButtonVisibility)); - } - - void onCameraStarted() { cameraButtonVisibility.setValue(false); } void onItemPickerStarted() { + countButtonVisibility = CountButtonState.Visibility.CONDITIONAL; + countButtonState.setValue(new CountButtonState(getSelectedMediaOrDefault().size(), countButtonVisibility)); cameraButtonVisibility.setValue(true); } void onFolderPickerStarted() { + countButtonVisibility = CountButtonState.Visibility.CONDITIONAL; + countButtonState.setValue(new CountButtonState(getSelectedMediaOrDefault().size(), countButtonVisibility)); cameraButtonVisibility.setValue(true); } @@ -175,7 +197,7 @@ class MediaSendViewModel extends ViewModel { } if (selected.size() >= maxSelection) { - error.postValue(Error.TOO_MANY_ITEMS); + error.setValue(Error.TOO_MANY_ITEMS); return; }