diff --git a/TODO b/TODO index 6f40196..680bac4 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,5 @@ - Email selection --- Deleting emails +-- Show which have been selected (background? image?) -- Mark as read - Send button action - Deleting identities diff --git a/res/drawable-hdpi/ic_content_discard.png b/res/drawable-hdpi/ic_content_discard.png new file mode 100644 index 0000000..ffd19d9 Binary files /dev/null and b/res/drawable-hdpi/ic_content_discard.png differ diff --git a/res/drawable-mdpi/ic_content_discard.png b/res/drawable-mdpi/ic_content_discard.png new file mode 100644 index 0000000..a8ee5f2 Binary files /dev/null and b/res/drawable-mdpi/ic_content_discard.png differ diff --git a/res/drawable-xhdpi/ic_content_discard.png b/res/drawable-xhdpi/ic_content_discard.png new file mode 100644 index 0000000..412b333 Binary files /dev/null and b/res/drawable-xhdpi/ic_content_discard.png differ diff --git a/res/drawable/activated_background.xml b/res/drawable/folder_activated_background.xml similarity index 100% rename from res/drawable/activated_background.xml rename to res/drawable/folder_activated_background.xml diff --git a/res/layout/listitem_folder.xml b/res/layout/listitem_folder.xml index 804b949..67b0b3f 100644 --- a/res/layout/listitem_folder.xml +++ b/res/layout/listitem_folder.xml @@ -2,7 +2,7 @@ + android:background="@drawable/folder_activated_background" > + + + + + \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index 5d7575e..826ed6d 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -6,6 +6,9 @@ Send email Settings + %s selected + Delete selected emails + Open nav Close nav diff --git a/src/i2p/bote/EmailListAdapter.java b/src/i2p/bote/EmailListAdapter.java index dd8bb9e..b3d1085 100644 --- a/src/i2p/bote/EmailListAdapter.java +++ b/src/i2p/bote/EmailListAdapter.java @@ -13,6 +13,7 @@ import i2p.bote.util.BoteHelper; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Typeface; +import android.util.SparseBooleanArray; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -22,10 +23,12 @@ import android.widget.TextView; public class EmailListAdapter extends ArrayAdapter { private final LayoutInflater mInflater; + private SparseBooleanArray mSelectedEmails; public EmailListAdapter(Context context) { super(context, android.R.layout.simple_list_item_2); mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mSelectedEmails = new SparseBooleanArray(); } public void setData(List emails) { @@ -78,4 +81,29 @@ public class EmailListAdapter extends ArrayAdapter { return v; } + + public void toggleSelection(int position) { + selectView(position, !mSelectedEmails.get(position)); + } + + public void removeSelection() { + mSelectedEmails = new SparseBooleanArray(); + notifyDataSetChanged(); + } + + public void selectView(int position, boolean value) { + if (value) + mSelectedEmails.put(position, value); + else + mSelectedEmails.delete(position); + notifyDataSetChanged(); + } + + public int getSelectedCount() { + return mSelectedEmails.size(); + } + + public SparseBooleanArray getSelectedIds() { + return mSelectedEmails; + } } diff --git a/src/i2p/bote/EmailListFragment.java b/src/i2p/bote/EmailListFragment.java index 0750c6a..2ef65f3 100644 --- a/src/i2p/bote/EmailListFragment.java +++ b/src/i2p/bote/EmailListFragment.java @@ -24,12 +24,16 @@ import android.os.Bundle; import android.support.v4.app.ListFragment; import android.support.v4.app.LoaderManager; import android.support.v4.content.Loader; +import android.support.v7.app.ActionBarActivity; +import android.support.v7.view.ActionMode; +import android.util.SparseBooleanArray; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.inputmethod.InputMethodManager; +import android.widget.AdapterView; import android.widget.EditText; import android.widget.ListView; import android.widget.TextView; @@ -44,6 +48,7 @@ public class EmailListFragment extends ListFragment implements private EmailListAdapter mAdapter; private EmailFolder mFolder; + private ActionMode mMode; private EditText mPasswordInput; private TextView mPasswordError; @@ -90,6 +95,17 @@ public class EmailListFragment extends ListFragment implements setListAdapter(mAdapter); + // Set up CAB + mMode = null; + getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { + @Override + public boolean onItemLongClick(AdapterView parent, View view, + int position, long id) { + onListItemSelect(position); + return true; + } + }); + if (mFolder == null) { setEmptyText(getResources().getString( R.string.folder_does_not_exist)); @@ -216,8 +232,73 @@ public class EmailListFragment extends ListFragment implements @Override public void onListItemClick(ListView parent, View view, int pos, long id) { super.onListItemClick(parent, view, pos, id); - mCallback.onEmailSelected( - mFolder.getName(), mAdapter.getItem(pos).getMessageID()); + if (mMode == null) { + mCallback.onEmailSelected( + mFolder.getName(), mAdapter.getItem(pos).getMessageID()); + } else + onListItemSelect(pos); + } + + private void onListItemSelect(int position) { + mAdapter.toggleSelection(position); + boolean hasCheckedElement = mAdapter.getSelectedCount() > 0; + + if (hasCheckedElement && mMode == null) { + mMode = ((ActionBarActivity) getActivity()).startSupportActionMode(new ModeCallback()); + } else if (!hasCheckedElement && mMode != null) { + mMode.finish(); + } + + if (mMode != null) + mMode.setTitle(getResources().getString( + R.string.items_selected, mAdapter.getSelectedCount())); + } + + private final class ModeCallback implements ActionMode.Callback { + @Override + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + // Respond to clicks on the actions in the CAB + switch (item.getItemId()) { + case R.id.action_delete_emails: + SparseBooleanArray selected = mAdapter.getSelectedIds(); + for (int i = (selected.size() - 1); i >= 0; i--) { + if (selected.valueAt(i)) { + Email email = mAdapter.getItem(selected.keyAt(i)); + // The Loader will update mAdapter + I2PBote.getInstance().deleteEmail(mFolder, email.getMessageID()); + } + } + mode.finish(); + return true; + default: + return false; + } + } + + @Override + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + // Inflate the menu for the CAB + MenuInflater inflater = mode.getMenuInflater(); + inflater.inflate(R.menu.email_list_context, menu); + return true; + } + + @Override + public void onDestroyActionMode(ActionMode mode) { + // Here you can make any necessary updates to the activity when + // the CAB is removed. + mAdapter.removeSelection(); + + if (mode == mMode) + mMode = null; + } + + @Override + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + // Here you can perform updates to the CAB due to + // an invalidate() request + return false; + } } // LoaderManager.LoaderCallbacks>