Browse Source

Multiple select actions

main
M66B 6 years ago
parent
commit
991d68112d
7 changed files with 247 additions and 203 deletions
  1. +28
    -19
      app/src/main/java/eu/faircode/email/FragmentMessages.java
  2. +10
    -0
      app/src/main/res/drawable/baseline_report_24.xml
  3. +173
    -158
      app/src/main/res/layout/fragment_messages.xml
  4. +3
    -6
      app/src/main/res/menu/action_answer.xml
  5. +4
    -8
      app/src/main/res/menu/action_compose.xml
  6. +6
    -12
      app/src/main/res/menu/action_message.xml
  7. +23
    -0
      app/src/main/res/menu/action_multiple.xml

+ 28
- 19
app/src/main/java/eu/faircode/email/FragmentMessages.java View File

@ -74,6 +74,7 @@ public class FragmentMessages extends FragmentEx {
private ImageButton ibHintActions;
private TextView tvNoEmail;
private RecyclerView rvMessage;
private BottomNavigationView multiple;
private BottomNavigationView bottom_navigation;
private ProgressBar pbWait;
private Group grpSupport;
@ -95,10 +96,9 @@ public class FragmentMessages extends FragmentEx {
private List<Long> trashes = new ArrayList<>();
private AdapterMessage.ViewType viewType;
private SelectionTracker<Long> selectionTracker = null;
private LiveData<PagedList<TupleMessageEx>> messages = null;
private SelectionTracker<Long> selectionTracker;
private int autoCount = 0;
private boolean autoExpand = true;
private List<Long> expanded = new ArrayList<>();
@ -149,6 +149,7 @@ public class FragmentMessages extends FragmentEx {
ibHintActions = view.findViewById(R.id.ibHintActions);
tvNoEmail = view.findViewById(R.id.tvNoEmail);
rvMessage = view.findViewById(R.id.rvFolder);
multiple = view.findViewById(R.id.multiple);
bottom_navigation = view.findViewById(R.id.bottom_navigation);
pbWait = view.findViewById(R.id.pbWait);
grpSupport = view.findViewById(R.id.grpSupport);
@ -233,21 +234,24 @@ public class FragmentMessages extends FragmentEx {
});
rvMessage.setAdapter(adapter);
selectionTracker = new SelectionTracker.Builder<>(
"messages-selection",
rvMessage,
new ItemKeyProviderMessage(rvMessage),
new ItemDetailsLookupMessage(rvMessage),
StorageStrategy.createLongStorage())
.withSelectionPredicate(new SelectionPredicateMessage())
.build();
adapter.setSelectionTracker(selectionTracker);
selectionTracker.addObserver(new SelectionTracker.SelectionObserver() {
@Override
public void onSelectionChanged() {
}
});
if (viewType == AdapterMessage.ViewType.FOLDER) {
selectionTracker = new SelectionTracker.Builder<>(
"messages-selection",
rvMessage,
new ItemKeyProviderMessage(rvMessage),
new ItemDetailsLookupMessage(rvMessage),
StorageStrategy.createLongStorage())
.withSelectionPredicate(new SelectionPredicateMessage())
.build();
adapter.setSelectionTracker(selectionTracker);
selectionTracker.addObserver(new SelectionTracker.SelectionObserver() {
@Override
public void onSelectionChanged() {
multiple.setVisibility(selectionTracker.hasSelection() ? View.VISIBLE : View.GONE);
}
});
}
new ItemTouchHelper(new ItemTouchHelper.Callback() {
@Override
@ -518,6 +522,7 @@ public class FragmentMessages extends FragmentEx {
// Initialize
tvNoEmail.setVisibility(View.GONE);
multiple.setVisibility(View.GONE);
bottom_navigation.setVisibility(View.GONE);
grpReady.setVisibility(View.GONE);
pbWait.setVisibility(View.VISIBLE);
@ -535,7 +540,8 @@ public class FragmentMessages extends FragmentEx {
outState.putLongArray("expanded", Helper.toLongArray(expanded));
outState.putLongArray("headers", Helper.toLongArray(headers));
outState.putLongArray("images", Helper.toLongArray(images));
selectionTracker.onSaveInstanceState(outState);
if (selectionTracker != null)
selectionTracker.onSaveInstanceState(outState);
}
@Override
@ -548,7 +554,8 @@ public class FragmentMessages extends FragmentEx {
expanded = Helper.fromLongArray(savedInstanceState.getLongArray("expanded"));
headers = Helper.fromLongArray(savedInstanceState.getLongArray("headers"));
images = Helper.fromLongArray(savedInstanceState.getLongArray("images"));
selectionTracker.onRestoreInstanceState(savedInstanceState);
if (selectionTracker != null)
selectionTracker.onRestoreInstanceState(savedInstanceState);
}
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
@ -637,6 +644,8 @@ public class FragmentMessages extends FragmentEx {
}
});
multiple.setVisibility(selectionTracker != null && selectionTracker.hasSelection() ? View.VISIBLE : View.GONE);
if (viewType == AdapterMessage.ViewType.THREAD) {
// Navigation
ViewModelMessages model = ViewModelProviders.of(getActivity()).get(ViewModelMessages.class);


+ 10
- 0
app/src/main/res/drawable/baseline_report_24.xml View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M15.73,3L8.27,3L3,8.27v7.46L8.27,21h7.46L21,15.73L21,8.27L15.73,3zM12,17.3c-0.72,0 -1.3,-0.58 -1.3,-1.3 0,-0.72 0.58,-1.3 1.3,-1.3 0.72,0 1.3,0.58 1.3,1.3 0,0.72 -0.58,1.3 -1.3,1.3zM13,13h-2L11,7h2v6z"/>
</vector>

+ 173
- 158
app/src/main/res/layout/fragment_messages.xml View File

@ -6,163 +6,169 @@
android:layout_height="match_parent"
tools:context=".ActivityView">
<androidx.constraintlayout.widget.ConstraintLayout
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tvSupport"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:padding="6dp"
android:text="@string/title_pro_support"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textColor="?android:attr/textColorPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/vSeparatorSupport"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/colorSeparator"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvSupport" />
<TextView
android:id="@+id/tvHintSupport"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minHeight="33dp"
android:padding="6dp"
android:text="@string/title_hint_support"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textColor="?android:attr/textColorPrimary"
app:layout_constraintEnd_toStartOf="@+id/ibHintSupport"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/vSeparatorSupport" />
<ImageButton
android:id="@+id/ibHintSupport"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/baseline_close_24"
app:layout_constraintBottom_toBottomOf="@id/tvHintSupport"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tvHintSupport" />
<View
android:id="@+id/vSeparatorHintSupport"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/colorSeparator"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/ibHintSupport" />
<TextView
android:id="@+id/tvHintActions"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minHeight="33dp"
android:padding="6dp"
android:text="@string/title_hint_message_actions"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textColor="?android:attr/textColorPrimary"
app:layout_constraintEnd_toStartOf="@+id/ibHintActions"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/vSeparatorHintSupport" />
<ImageButton
android:id="@+id/ibHintActions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/baseline_close_24"
app:layout_constraintBottom_toBottomOf="@id/tvHintActions"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tvHintActions" />
<View
android:id="@+id/vSeparatorHintActions"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/colorSeparator"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvHintActions" />
<TextView
android:id="@+id/tvNoEmail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_no_messages"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvFolder"
android:layout_width="0dp"
android:layout_height="0dp"
android:scrollbarStyle="outsideOverlay"
android:scrollbars="vertical"
app:layout_constraintBottom_toTopOf="@+id/bottom_navigation"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/vSeparatorHintActions" />
<ProgressBar
android:id="@+id/pbWait"
style="@style/Base.Widget.AppCompat.ProgressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_height="match_parent"
android:layout_above="@+id/multiple">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="28dp"
android:background="?attr/colorSeparator"
app:itemIconTint="@color/bottomnav_background"
app:itemTextColor="@color/bottomnav_background"
app:labelVisibilityMode="unlabeled"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="@menu/action_messages" />
<androidx.constraintlayout.widget.Group
android:id="@+id/grpSupport"
android:layout_width="0dp"
android:layout_height="0dp"
app:constraint_referenced_ids="tvSupport,vSeparatorSupport" />
<androidx.constraintlayout.widget.Group
android:id="@+id/grpHintSupport"
android:layout_width="0dp"
android:layout_height="0dp"
app:constraint_referenced_ids="tvHintSupport,ibHintSupport,vSeparatorHintSupport" />
<androidx.constraintlayout.widget.Group
android:id="@+id/grpHintActions"
android:layout_width="0dp"
android:layout_height="0dp"
app:constraint_referenced_ids="tvHintActions,ibHintActions,vSeparatorHintActions" />
<androidx.constraintlayout.widget.Group
android:id="@+id/grpReady"
android:layout_width="0dp"
android:layout_height="0dp"
app:constraint_referenced_ids="rvFolder" />
</androidx.constraintlayout.widget.ConstraintLayout>
android:layout_height="match_parent">
<TextView
android:id="@+id/tvSupport"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:padding="6dp"
android:text="@string/title_pro_support"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textColor="?android:attr/textColorPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/vSeparatorSupport"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/colorSeparator"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvSupport" />
<TextView
android:id="@+id/tvHintSupport"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minHeight="33dp"
android:padding="6dp"
android:text="@string/title_hint_support"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textColor="?android:attr/textColorPrimary"
app:layout_constraintEnd_toStartOf="@+id/ibHintSupport"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/vSeparatorSupport" />
<ImageButton
android:id="@+id/ibHintSupport"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/baseline_close_24"
app:layout_constraintBottom_toBottomOf="@id/tvHintSupport"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tvHintSupport" />
<View
android:id="@+id/vSeparatorHintSupport"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/colorSeparator"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/ibHintSupport" />
<TextView
android:id="@+id/tvHintActions"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minHeight="33dp"
android:padding="6dp"
android:text="@string/title_hint_message_actions"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textColor="?android:attr/textColorPrimary"
app:layout_constraintEnd_toStartOf="@+id/ibHintActions"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/vSeparatorHintSupport" />
<ImageButton
android:id="@+id/ibHintActions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/baseline_close_24"
app:layout_constraintBottom_toBottomOf="@id/tvHintActions"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tvHintActions" />
<View
android:id="@+id/vSeparatorHintActions"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/colorSeparator"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvHintActions" />
<TextView
android:id="@+id/tvNoEmail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_no_messages"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintBottom_toTopOf="@+id/bottom_navigation"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvFolder"
android:layout_width="0dp"
android:layout_height="0dp"
android:scrollbarStyle="outsideOverlay"
android:scrollbars="vertical"
app:layout_constraintBottom_toTopOf="@+id/bottom_navigation"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/vSeparatorHintActions" />
<ProgressBar
android:id="@+id/pbWait"
style="@style/Base.Widget.AppCompat.ProgressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
app:layout_constraintBottom_toTopOf="@+id/bottom_navigation"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="28dp"
android:background="?attr/colorSeparator"
app:itemIconTint="@color/bottomnav_background"
app:itemTextColor="@color/bottomnav_background"
app:labelVisibilityMode="unlabeled"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="@menu/action_messages" />
<androidx.constraintlayout.widget.Group
android:id="@+id/grpSupport"
android:layout_width="0dp"
android:layout_height="0dp"
app:constraint_referenced_ids="tvSupport,vSeparatorSupport" />
<androidx.constraintlayout.widget.Group
android:id="@+id/grpHintSupport"
android:layout_width="0dp"
android:layout_height="0dp"
app:constraint_referenced_ids="tvHintSupport,ibHintSupport,vSeparatorHintSupport" />
<androidx.constraintlayout.widget.Group
android:id="@+id/grpHintActions"
android:layout_width="0dp"
android:layout_height="0dp"
app:constraint_referenced_ids="tvHintActions,ibHintActions,vSeparatorHintActions" />
<androidx.constraintlayout.widget.Group
android:id="@+id/grpReady"
android:layout_width="0dp"
android:layout_height="0dp"
app:constraint_referenced_ids="rvFolder" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
@ -172,7 +178,16 @@
android:layout_margin="16dp"
android:src="@drawable/baseline_edit_24"
android:tint="@color/colorActionForeground"
app:backgroundTint="?attr/colorAccent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
app:backgroundTint="?attr/colorAccent" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/multiple"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="@color/colorPrimary"
app:itemIconTint="@color/bottomnav_background"
app:itemTextColor="@color/bottomnav_background"
app:labelVisibilityMode="labeled"
app:menu="@menu/action_multiple" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

+ 3
- 6
app/src/main/res/menu/action_answer.xml View File

@ -1,16 +1,13 @@
<?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">
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_delete"
android:icon="@drawable/baseline_delete_24"
android:title="@string/title_delete"
app:showAsAction="ifRoom" />
android:title="@string/title_delete" />
<item
android:id="@+id/action_save"
android:icon="@drawable/baseline_save_alt_24"
android:title="@string/title_save"
app:showAsAction="ifRoom" />
android:title="@string/title_save" />
</menu>

+ 4
- 8
app/src/main/res/menu/action_compose.xml View File

@ -1,22 +1,18 @@
<?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">
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_delete"
android:icon="@drawable/baseline_delete_24"
android:title="@string/title_discard"
app:showAsAction="ifRoom" />
android:title="@string/title_discard" />
<item
android:id="@+id/action_save"
android:icon="@drawable/baseline_save_alt_24"
android:title="@string/title_save"
app:showAsAction="ifRoom" />
android:title="@string/title_save" />
<item
android:id="@+id/action_send"
android:icon="@drawable/baseline_send_24"
android:title="@string/title_send"
app:showAsAction="ifRoom" />
android:title="@string/title_send" />
</menu>

+ 6
- 12
app/src/main/res/menu/action_message.xml View File

@ -1,34 +1,28 @@
<?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">
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_more"
android:icon="@drawable/baseline_more_vert_24"
android:title="@string/title_more"
app:showAsAction="ifRoom" />
android:title="@string/title_more" />
<item
android:id="@+id/action_delete"
android:icon="@drawable/baseline_delete_24"
android:title="@string/title_trash"
app:showAsAction="ifRoom" />
android:title="@string/title_trash" />
<item
android:id="@+id/action_move"
android:icon="@drawable/baseline_folder_24"
android:title="@string/title_move"
app:showAsAction="ifRoom" />
android:title="@string/title_move" />
<item
android:id="@+id/action_archive"
android:icon="@drawable/baseline_archive_24"
android:title="@string/title_archive"
app:showAsAction="ifRoom" />
android:title="@string/title_archive" />
<item
android:id="@+id/action_reply"
android:icon="@drawable/baseline_reply_24"
android:title="@string/title_reply"
app:showAsAction="ifRoom" />
android:title="@string/title_reply" />
</menu>

+ 23
- 0
app/src/main/res/menu/action_multiple.xml View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menu_junk"
android:icon="@drawable/baseline_report_24"
android:title="@string/title_spam" />
<item
android:id="@+id/action_delete"
android:icon="@drawable/baseline_delete_24"
android:title="@string/title_trash" />
<item
android:id="@+id/action_move"
android:icon="@drawable/baseline_folder_24"
android:title="@string/title_move" />
<item
android:id="@+id/action_archive"
android:icon="@drawable/baseline_archive_24"
android:title="@string/title_archive" />
</menu>

Loading…
Cancel
Save