Add new bottom actionbar to the media overview.

This commit is contained in:
Greyson Parrelli
2021-10-21 15:30:34 -04:00
parent 68655194a6
commit d88999d6d4
6 changed files with 83 additions and 93 deletions

View File

@@ -10,6 +10,8 @@ import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.MediaDatabase;
import org.thoughtcrime.securesms.permissions.Permissions;
@@ -59,11 +61,9 @@ final class MediaActions {
recordCount,
recordCount);
AlertDialog.Builder builder = new AlertDialog.Builder(context)
.setIcon(R.drawable.ic_warning)
.setTitle(confirmTitle)
.setMessage(confirmMessage)
.setCancelable(true);
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(context).setTitle(confirmTitle)
.setMessage(confirmMessage)
.setCancelable(true);
builder.setPositiveButton(R.string.delete, (dialogInterface, i) ->
new ProgressDialogAsyncTask<MediaDatabase.MediaRecord, Void, Void>(context,

View File

@@ -33,6 +33,8 @@ import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.MediaPreviewActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
import org.thoughtcrime.securesms.components.menu.ActionItem;
import org.thoughtcrime.securesms.components.menu.SignalBottomActionBar;
import org.thoughtcrime.securesms.components.voice.VoiceNoteMediaController;
import org.thoughtcrime.securesms.components.voice.VoiceNotePlaybackState;
import org.thoughtcrime.securesms.database.MediaDatabase;
@@ -45,6 +47,8 @@ import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.WindowUtil;
import java.util.Arrays;
public final class MediaOverviewPageFragment extends Fragment
implements MediaGalleryAllAdapter.ItemClickListener,
MediaGalleryAllAdapter.AudioItemListener,
@@ -69,6 +73,7 @@ public final class MediaOverviewPageFragment extends Fragment
private MediaGalleryAllAdapter adapter;
private GridMode gridMode;
private VoiceNoteMediaController voiceNoteMediaController;
private SignalBottomActionBar bottomActionBar;
public static @NonNull Fragment newInstance(long threadId,
@NonNull MediaLoader.MediaType mediaType,
@@ -112,9 +117,10 @@ public final class MediaOverviewPageFragment extends Fragment
View view = inflater.inflate(R.layout.media_overview_page_fragment, container, false);
int spans = getResources().getInteger(R.integer.media_overview_cols);
this.recyclerView = view.findViewById(R.id.media_grid);
this.noMedia = view.findViewById(R.id.no_images);
this.gridManager = new StickyHeaderGridLayoutManager(spans);
this.recyclerView = view.findViewById(R.id.media_grid);
this.noMedia = view.findViewById(R.id.no_images);
this.bottomActionBar = view.findViewById(R.id.media_overview_bottom_action_bar);
this.gridManager = new StickyHeaderGridLayoutManager(spans);
this.adapter = new MediaGalleryAllAdapter(context,
GlideApp.with(this),
@@ -136,7 +142,7 @@ public final class MediaOverviewPageFragment extends Fragment
this.sorting = sorting;
adapter.setShowFileSizes(sorting.isRelatedToFileSize());
LoaderManager.getInstance(this).restartLoader(0, null, this);
refreshActionModeTitle();
updateMultiSelect();
}
});
@@ -154,7 +160,7 @@ public final class MediaOverviewPageFragment extends Fragment
this.detail = detail;
adapter.setDetailView(detail);
refreshLayoutManager();
refreshActionModeTitle();
updateMultiSelect();
}
@Override
@@ -214,7 +220,7 @@ public final class MediaOverviewPageFragment extends Fragment
if (adapter.getSelectedMediaCount() == 0) {
actionMode.finish();
} else {
refreshActionModeTitle();
updateMultiSelect();
}
}
@@ -275,33 +281,18 @@ public final class MediaOverviewPageFragment extends Fragment
private void handleSelectAllMedia() {
getListAdapter().selectAllMedia();
refreshActionModeTitle();
}
private void refreshActionModeTitle() {
if (actionMode != null) {
actionMode.setTitle(getActionModeTitle());
}
updateMultiSelect();
}
private String getActionModeTitle() {
MediaGalleryAllAdapter adapter = getListAdapter();
int mediaCount = adapter.getSelectedMediaCount();
boolean showTotalFileSize = detail ||
mediaType != MediaLoader.MediaType.GALLERY ||
sorting == MediaDatabase.Sorting.Largest;
MediaGalleryAllAdapter adapter = getListAdapter();
int mediaCount = adapter.getSelectedMediaCount();
long totalFileSize = adapter.getSelectedMediaTotalFileSize();
if (showTotalFileSize) {
long totalFileSize = adapter.getSelectedMediaTotalFileSize();
return getResources().getQuantityString(R.plurals.MediaOverviewActivity_d_items_s,
mediaCount,
mediaCount,
Util.getPrettyFileSize(totalFileSize));
} else {
return getResources().getQuantityString(R.plurals.MediaOverviewActivity_d_items,
mediaCount,
mediaCount);
}
return getResources().getQuantityString(R.plurals.MediaOverviewActivity_d_selected_s,
mediaCount,
mediaCount,
Util.getPrettyFileSize(totalFileSize));
}
private MediaGalleryAllAdapter getListAdapter() {
@@ -312,8 +303,35 @@ public final class MediaOverviewPageFragment extends Fragment
FragmentActivity activity = requireActivity();
actionMode = ((AppCompatActivity) activity).startSupportActionMode(actionModeCallback);
((MediaOverviewActivity) activity).onEnterMultiSelect();
ViewUtil.fadeIn(bottomActionBar, 250);
bottomActionBar.setItems(Arrays.asList(
new ActionItem(R.drawable.ic_save_24, R.string.MediaOverviewActivity_save, () -> {
MediaActions.handleSaveMedia(MediaOverviewPageFragment.this,
getListAdapter().getSelectedMedia(),
this::exitMultiSelect);
}),
new ActionItem(R.drawable.ic_select_24, R.string.MediaOverviewActivity_select_all, this::handleSelectAllMedia),
new ActionItem(R.drawable.ic_delete_24, R.string.MediaOverviewActivity_delete, () -> {
MediaActions.handleDeleteMedia(requireContext(), getListAdapter().getSelectedMedia());
exitMultiSelect();
})
));
}
private void exitMultiSelect() {
actionMode.finish();
actionMode = null;
ViewUtil.fadeOut(bottomActionBar, 250);
}
private void updateMultiSelect() {
if (actionMode != null) {
actionMode.setTitle(getActionModeTitle());
}
}
@Override
public void onPlay(@NonNull Uri audioUri, double progress, long messageId) {
voiceNoteMediaController.startSinglePlayback(audioUri, messageId, progress);
@@ -346,18 +364,9 @@ public final class MediaOverviewPageFragment extends Fragment
private class ActionModeCallback implements ActionMode.Callback {
private int originalStatusBarColor;
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.getMenuInflater().inflate(R.menu.media_overview_context, menu);
mode.setTitle(getActionModeTitle());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = requireActivity().getWindow();
originalStatusBarColor = window.getStatusBarColor();
WindowUtil.setStatusBarColor(requireActivity().getWindow(), getResources().getColor(R.color.action_mode_status_bar));
}
return true;
}
@@ -368,33 +377,17 @@ public final class MediaOverviewPageFragment extends Fragment
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.save:
MediaActions.handleSaveMedia(MediaOverviewPageFragment.this,
getListAdapter().getSelectedMedia(),
() -> actionMode.finish());
return true;
case R.id.delete:
MediaActions.handleDeleteMedia(requireContext(), getListAdapter().getSelectedMedia());
actionMode.finish();
return true;
case R.id.select_all:
handleSelectAllMedia();
return true;
}
return false;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
actionMode = null;
getListAdapter().clearSelection();
FragmentActivity activity = requireActivity();
((MediaOverviewActivity) activity).onExitMultiSelect();
WindowUtil.setStatusBarColor(requireActivity().getWindow(), originalStatusBarColor);
exitMultiSelect();
}
}

View File

@@ -1,5 +1,9 @@
<vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FFFFFFFF" android:pathData="M22,10v9a3,3 0,0 1,-3 3L5,22a3,3 0,0 1,-3 -3L2,10A3,3 0,0 1,5 7L9.75,7L9.75,8.5L5,8.5A1.5,1.5 0,0 0,3.5 10v9A1.5,1.5 0,0 0,5 20.5L19,20.5A1.5,1.5 0,0 0,20.5 19L20.5,10A1.5,1.5 0,0 0,19 8.5L14.25,8.5L14.25,7L19,7A3,3 0,0 1,22 10ZM15.419,11.47L13.586,13.3l-0.82,1.148L12.766,2h-1.5L11.266,14.45l-0.742,-1.039L8.581,11.485 7.525,12.55 12.012,17l4.467,-4.468Z"/>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M22,10V19C22,19.7956 21.6839,20.5587 21.1213,21.1213C20.5587,21.6839 19.7956,22 19,22H5C4.2043,22 3.4413,21.6839 2.8787,21.1213C2.3161,20.5587 2,19.7956 2,19V10C2,9.2044 2.3161,8.4413 2.8787,7.8787C3.4413,7.3161 4.2043,7 5,7H9.75V8.5H5C4.6022,8.5 4.2206,8.658 3.9393,8.9393C3.658,9.2206 3.5,9.6022 3.5,10V19C3.5,19.3978 3.658,19.7794 3.9393,20.0607C4.2206,20.342 4.6022,20.5 5,20.5H19C19.3978,20.5 19.7794,20.342 20.0607,20.0607C20.342,19.7794 20.5,19.3978 20.5,19V10C20.5,9.6022 20.342,9.2206 20.0607,8.9393C19.7794,8.658 19.3978,8.5 19,8.5H14.25V7H19C19.7956,7 20.5587,7.3161 21.1213,7.8787C21.6839,8.4413 22,9.2044 22,10ZM15.419,11.47L13.586,13.3L12.766,14.448V2H11.266V14.45L10.524,13.411L8.581,11.485L7.525,12.55L12.012,17L16.479,12.532L15.419,11.47Z"
android:fillColor="@color/signal_icon_tint_action"/>
</vector>

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
@@ -18,4 +20,16 @@
android:textSize="24sp"
android:visibility="gone" />
</RelativeLayout>
<org.thoughtcrime.securesms.components.menu.SignalBottomActionBar
android:id="@+id/media_overview_bottom_action_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="36dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/save"
android:title="@string/save"
android:icon="@drawable/ic_download_filled_white_24"
app:iconTint="@color/signal_icon_tint_primary"
app:showAsAction="always"/>
<item android:id="@+id/delete"
android:title="@string/delete"
android:icon="@drawable/ic_trash_24"
app:iconTint="@color/signal_icon_tint_primary"
app:showAsAction="always"/>
<item android:id="@+id/select_all"
android:title="@string/MediaOverviewActivity_Select_all"
android:icon="@drawable/ic_select_all_white_24dp"
app:iconTint="@color/signal_icon_tint_primary"
app:showAsAction="always"/>
</menu>

View File

@@ -944,14 +944,13 @@
<string name="MediaOverviewActivity_Grid_view_description">Grid view</string>
<string name="MediaOverviewActivity_List_view_description">List view</string>
<string name="MediaOverviewActivity_Selected_description">Selected</string>
<string name="MediaOverviewActivity_save">Save</string>
<string name="MediaOverviewActivity_select_all">Select all</string>
<string name="MediaOverviewActivity_delete">Delete</string>
<plurals name="MediaOverviewActivity_d_items_s">
<item quantity="one">%1$d item %2$s</item>
<item quantity="other">%1$d items %2$s</item>
</plurals>
<plurals name="MediaOverviewActivity_d_items">
<item quantity="one">%1$d item</item>
<item quantity="other">%1$d items</item>
<plurals name="MediaOverviewActivity_d_selected_s">
<item quantity="one">%1$d selected (%2$s)</item>
<item quantity="other">%1$d selected (%2$s)</item>
</plurals>
<string name="MediaOverviewActivity_file">File</string>
<string name="MediaOverviewActivity_audio">Audio</string>