mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-27 13:13:43 +00:00
Add new bottom actionbar to the media overview.
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user