From f7d33becbc0d9b29e9440bb710f28d357191cc1b Mon Sep 17 00:00:00 2001 From: str4d Date: Tue, 15 Apr 2014 02:51:43 +0000 Subject: [PATCH] Email deletion --- TODO | 2 +- res/drawable-hdpi/ic_content_discard.png | Bin 0 -> 1611 bytes res/drawable-mdpi/ic_content_discard.png | Bin 0 -> 1358 bytes res/drawable-xhdpi/ic_content_discard.png | Bin 0 -> 1824 bytes ...nd.xml => folder_activated_background.xml} | 0 res/layout/listitem_folder.xml | 2 +- res/menu/email_list_context.xml | 11 +++ res/values/strings.xml | 3 + src/i2p/bote/EmailListAdapter.java | 28 ++++++ src/i2p/bote/EmailListFragment.java | 85 +++++++++++++++++- 10 files changed, 127 insertions(+), 4 deletions(-) create mode 100644 res/drawable-hdpi/ic_content_discard.png create mode 100644 res/drawable-mdpi/ic_content_discard.png create mode 100644 res/drawable-xhdpi/ic_content_discard.png rename res/drawable/{activated_background.xml => folder_activated_background.xml} (100%) create mode 100644 res/menu/email_list_context.xml 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 0000000000000000000000000000000000000000..ffd19d9e80b07c6fdf216f2b728a9337e438d1c4 GIT binary patch literal 1611 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%qp275hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|8hm3bwJ6}oxF$}kgLQj3#|G7CyF^YauyCMG83 zmzLNn0bL65LT&-v*t}wBFaZNhzap_f-%!s00+w{G(#^lGsVi)*~rk%+1S<8$-vFf(ACh=#L&{!#L3yw z&D7A`#K{n**Cju>G&eP`1g19ytk=TX(Za+Lr(RHE$SnZc?2=lPS(cjOR+OKs0QR(1 zCT_Pl<1`PdHwCL(!2WQ-saGH97=2LGB1JV!2$+6AOnAZta^OinH4m8Hi+~Ax_NSC; z1_q|Ro-U3d6}R5ZjQ19GlsHyi)<2I+TTnztb;AoS-#^X*68FllPJeMI@3Zm`!B2}$ zFY3P_-tj{3qKL~y1+S*APcKf!oWE&o+kE~|fyMEXv~zE~tUok2pFX$m{F&eB_X0gM zn?KtedN8No$wBc!y?8*8ML5g5M#c$qHYA*W5G=>))4*D=@@(6ugT z1GX1zi+Vr4x@n^EypUZ;Y9I46$2FWQn6S< zt9D%C>|Ix=e#lI3+AhDD)=ORFnzSOA&L3>|%%>3`{oP$bstt}e(f~YY53RoV9rdrXH4v&H=~_{ub%sV zt+S;#w3h2e`GndpfzRh0-FhnXxIWtkZE>qdbMCRI^f8CcnwRIxDq~^ex177^L9oM8 z=ExO~f*W2q*l^8fdS&x{$F0WL%Ug1^7F;YTOx0E}vyHmVQ83p{I&#N^ZYPPfhfXhd zuPamd6x+%CZDZ0llYelb#{Ni?uWQ|IJ&xn-(=TK<5f7DoCcXLWylc+4*#kb# k{{>7-3j`*-{Gok-LH)?F>j~0pmV=6SPgg&ebxsLQ0FuvZE&u=k literal 0 HcmV?d00001 diff --git a/res/drawable-mdpi/ic_content_discard.png b/res/drawable-mdpi/ic_content_discard.png new file mode 100644 index 0000000000000000000000000000000000000000..a8ee5f253f83e715845337278cb7d08ebd623dfa GIT binary patch literal 1358 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%qp275hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|8hm3bwJ6}oxF$}kgLQj3#|G7CyF^YauyCMG83 zmzLNn0bL65LT&-v*t}wBFaZNhzap_f-%!s00+w{G(#^lGsVi)*}~b;!oG&eP`1g19yq1P3sUQlAlEdbi=l3J8mmYU*Ll%J~r_Ow+dZnrq$ zG!Lpb1-DzAaq86vIz}H9wMbD769T3m5EGtofgE_!Pt60S_ab1zKDm-XlYxQpfTxRN zNX4x;(|3C@JBqYzzFE;3$l@rVKf_HxH0RBga)D~WjUVQ+)G`TbTW`E@>DVo$IA<4u zmX!RHX@A)N9WZd&WNoe3YWd;drkOMUKA&U!+($;yC2zvC^Sn3On7G)A#SWSkZ22y? zgR!@c+k&zEfiy?zT+ITOyx+PDShOB6{1Dm5=jVIPSWqGMKFdO(Hij(+JYF3Yy3)wG zfqB~jqll&AHmaRVCn)`3S^t35rlGp;w8{gXH%(?8JBxq5(Mo2yFZzOY`lELT3a<&| zGK>Ao}C=DMV}IPaOv4u)u>YTN8 zUzlwg-9Mx{AJCY=eqK{}56>!|_+{ zrd0FbF3x8zORpcF%+(?JSmR`q*NrB7Kd)DLH?DN~UDA79n3u+=boAWU3!KqRe^@qN z|J|DJ?eKiga#4XBdjwnAn4D%ay<)Qr*siHyAdq0nGA~gmN;n|3Q1Z2*`gy}oejoBa zdzG!d^3C!ad-!WsLtE9|4^^K>?40ycb(@diLVzp;%>fc6h>)tqGh`RYgk+b^LIP9E5n&M2 zDr!aXplT~xq_je@W2#UK1ZSx zk3>tuMq<$?Av=+x2m}NT1_Q^yrvxqWj#j51X%pQr(5NIpm;+f$8g-P*|KC-sedn#GqOte+ z{wJ|skw#!(G^WQ>NEJP}_<7b)1R^0ZC54j;98VhUVpJkd;rc|J038MdG`W`DD6KfTNmY^d`F;bn1pP2osK?GFa7?}tEIM{Bf-$imoeXFl z?Y~AnYNGXH-M$kpeRwB*Oh@aTq=oI#^plXjFNHFxNMUU6J0RD%h(7qm@SRMfsyeS& zn4cc4kXB^hZ!}p#LH7OYU=(=RJUmhQk}_ZD%YCiKS?rm+!IGlDkA%3-|Z0b|ehb7!#W^7=9nXWYsmz%##Jb6e- z96Yjmd9WB7-&q+|J&)zQFlcgXc4^KqyC&e#tWWxFnP|^9rVwYFD)D+@HwHQAQca9s z154Z{g~ZlZy5t`}y(y-8D6=Sht&7EW=*$*RznbZU;917{ZkEj?qq}+i7p=<)^MwM9;NZD(p0h6t>n6E@!|1$M~{}YjFsq2Rnk>A2XEfo!pBUrstE}_@zJrEb(*}H zM`LCw^Eb0Rx&{gvuTrsqBFLqqVSAgmoil0SBciI@7t?(*&oAZu9-gs(S(SXE^VQ_N zw;SuHsx^0z{-Ek@Sj&C{=6YtfM2_!^t-n^B`)XC)HK9Xp(2e8|KlTdJ@(z2IPjvq4 zczu1nH@bFLHDkc0;{kQOEA{MyqYU2XWhFJ=znn^(zWQXwz8Z7EIK?7PR{n}D2=QC$ zv#h*5M~?5*XQTwRPK>IyOsKLcJLhhz6^IfpmiRgpJrAi7F%_G@DbXBz;KT*F!;H)5 z+Q@#}jhRlO5W9Kg3IRJKjtoeAJU16jsP@h@yRYqusC(F8QN$Mx_YU=E1$psmgJ*A- z{jtL2U_mQ}dRD_Z_OFHTDjy|f+}*a){`PQ)-Q?Pst3HO#HrqP)NhX`xu3bL>14E9F ztLM9P-ZNjQy|m-e6mx*vV3I>gLGWESfZH5os&n<|iZH%t(xgN;pHsc=t+?Zq&K$WG eC5GmWOk2jR-Z%JyzJ*^~|5>uoNNKrvQ}*Aa1;Oe7 literal 0 HcmV?d00001 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>