diff --git a/res/drawable-hdpi/ic_collections_collection.png b/res/drawable-hdpi/ic_collections_collection.png
new file mode 100644
index 0000000..6f441b4
Binary files /dev/null and b/res/drawable-hdpi/ic_collections_collection.png differ
diff --git a/res/drawable-hdpi/ic_content_read.png b/res/drawable-hdpi/ic_content_read.png
new file mode 100644
index 0000000..9ef5295
Binary files /dev/null and b/res/drawable-hdpi/ic_content_read.png differ
diff --git a/res/drawable-hdpi/ic_content_unread.png b/res/drawable-hdpi/ic_content_unread.png
new file mode 100644
index 0000000..d516f77
Binary files /dev/null and b/res/drawable-hdpi/ic_content_unread.png differ
diff --git a/res/drawable-mdpi/ic_collections_collection.png b/res/drawable-mdpi/ic_collections_collection.png
new file mode 100644
index 0000000..cc81e57
Binary files /dev/null and b/res/drawable-mdpi/ic_collections_collection.png differ
diff --git a/res/drawable-mdpi/ic_content_read.png b/res/drawable-mdpi/ic_content_read.png
new file mode 100644
index 0000000..0f59a03
Binary files /dev/null and b/res/drawable-mdpi/ic_content_read.png differ
diff --git a/res/drawable-mdpi/ic_content_unread.png b/res/drawable-mdpi/ic_content_unread.png
new file mode 100644
index 0000000..eff1ba3
Binary files /dev/null and b/res/drawable-mdpi/ic_content_unread.png differ
diff --git a/res/drawable-xhdpi/ic_collections_collection.png b/res/drawable-xhdpi/ic_collections_collection.png
new file mode 100644
index 0000000..78500a9
Binary files /dev/null and b/res/drawable-xhdpi/ic_collections_collection.png differ
diff --git a/res/drawable-xhdpi/ic_content_read.png b/res/drawable-xhdpi/ic_content_read.png
new file mode 100644
index 0000000..62e3d1a
Binary files /dev/null and b/res/drawable-xhdpi/ic_content_read.png differ
diff --git a/res/drawable-xhdpi/ic_content_unread.png b/res/drawable-xhdpi/ic_content_unread.png
new file mode 100644
index 0000000..606c902
Binary files /dev/null and b/res/drawable-xhdpi/ic_content_unread.png differ
diff --git a/res/menu/email_list_context.xml b/res/menu/email_list_context.xml
index 57bcfd0..2d1c013 100644
--- a/res/menu/email_list_context.xml
+++ b/res/menu/email_list_context.xml
@@ -3,9 +3,24 @@
xmlns:i2pandroid="http://schemas.android.com/apk/res-auto" >
+
+
+
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 826ed6d..71a71e2 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -7,7 +7,10 @@
Settings
%s selected
- Delete selected emails
+ Delete
+ Mark read
+ Mark unread
+ Move to
Open nav
Close nav
diff --git a/src/i2p/bote/EmailListActivity.java b/src/i2p/bote/EmailListActivity.java
index bdc3982..eed84e8 100644
--- a/src/i2p/bote/EmailListActivity.java
+++ b/src/i2p/bote/EmailListActivity.java
@@ -3,6 +3,7 @@ package i2p.bote;
import net.i2p.client.I2PClient;
import i2p.bote.config.SettingsActivity;
import i2p.bote.folder.EmailFolder;
+import i2p.bote.util.MoveToDialogFragment;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.content.Context;
@@ -20,7 +21,8 @@ import android.widget.AdapterView;
import android.widget.ListView;
public class EmailListActivity extends ActionBarActivity implements
- EmailListFragment.OnEmailSelectedListener {
+ EmailListFragment.OnEmailSelectedListener,
+ MoveToDialogFragment.MoveToDialogListener {
private CharSequence mDrawerTitle;
private CharSequence mTitle;
private SharedPreferences mSharedPrefs;
@@ -224,4 +226,12 @@ public class EmailListActivity extends ActionBarActivity implements
detailIntent.putExtra(ViewEmailActivity.MESSAGE_ID, messageId);
startActivity(detailIntent);
}
+
+ // MoveToDialogFragment.MoveToDialogListener
+
+ @Override
+ public void onFolderSelected(EmailFolder newFolder) {
+ EmailListFragment f = (EmailListFragment) getSupportFragmentManager().findFragmentById(R.id.list_fragment);
+ f.onFolderSelected(newFolder);
+ }
}
diff --git a/src/i2p/bote/EmailListFragment.java b/src/i2p/bote/EmailListFragment.java
index 2ef65f3..11a7b30 100644
--- a/src/i2p/bote/EmailListFragment.java
+++ b/src/i2p/bote/EmailListFragment.java
@@ -13,6 +13,7 @@ import i2p.bote.folder.EmailFolder;
import i2p.bote.folder.FolderListener;
import i2p.bote.util.BetterAsyncTaskLoader;
import i2p.bote.util.BoteHelper;
+import i2p.bote.util.MoveToDialogFragment;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
@@ -21,6 +22,7 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.support.v4.app.DialogFragment;
import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
@@ -39,7 +41,8 @@ import android.widget.ListView;
import android.widget.TextView;
public class EmailListFragment extends ListFragment implements
- LoaderManager.LoaderCallbacks> {
+ LoaderManager.LoaderCallbacks>,
+ MoveToDialogFragment.MoveToDialogListener {
public static final String FOLDER_NAME = "folder_name";
private static final int EMAIL_LIST_LOADER = 1;
@@ -244,7 +247,8 @@ public class EmailListFragment extends ListFragment implements
boolean hasCheckedElement = mAdapter.getSelectedCount() > 0;
if (hasCheckedElement && mMode == null) {
- mMode = ((ActionBarActivity) getActivity()).startSupportActionMode(new ModeCallback());
+ boolean unread = mAdapter.getItem(position).isNew();
+ mMode = ((ActionBarActivity) getActivity()).startSupportActionMode(new ModeCallback(unread));
} else if (!hasCheckedElement && mMode != null) {
mMode.finish();
}
@@ -255,21 +259,53 @@ public class EmailListFragment extends ListFragment implements
}
private final class ModeCallback implements ActionMode.Callback {
+ private boolean areUnread;
+
+ public ModeCallback(boolean unread) {
+ super();
+ this.areUnread = unread;
+ }
+
@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));
+ case R.id.action_delete:
+ SparseBooleanArray toDelete = mAdapter.getSelectedIds();
+ for (int i = (toDelete.size() - 1); i >= 0; i--) {
+ if (toDelete.valueAt(i)) {
+ Email email = mAdapter.getItem(toDelete.keyAt(i));
// The Loader will update mAdapter
I2PBote.getInstance().deleteEmail(mFolder, email.getMessageID());
}
}
mode.finish();
return true;
+ case R.id.action_mark_read:
+ case R.id.action_mark_unread:
+ SparseBooleanArray selected = mAdapter.getSelectedIds();
+ for (int i = (selected.size() - 1); i >= 0; i--) {
+ if (selected.valueAt(i)) {
+ Email email = mAdapter.getItem(selected.keyAt(i));
+ try {
+ // The Loader will update mAdapter
+ mFolder.setNew(email, !areUnread);
+ } catch (PasswordException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (GeneralSecurityException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+ areUnread = !areUnread;
+ mMode.invalidate();
+ return true;
+ case R.id.action_move_to:
+ DialogFragment f = MoveToDialogFragment.newInstance(mFolder);
+ f.show(getFragmentManager(), "moveTo");
+ return true;
default:
return false;
}
@@ -297,10 +333,25 @@ public class EmailListFragment extends ListFragment implements
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// Here you can perform updates to the CAB due to
// an invalidate() request
- return false;
+ menu.findItem(R.id.action_mark_read).setVisible(areUnread);
+ menu.findItem(R.id.action_mark_unread).setVisible(!areUnread);
+ return true;
}
}
+ // Called by EmailListActivity.onFolderSelected()
+
+ public void onFolderSelected(EmailFolder newFolder) {
+ SparseBooleanArray toMove = mAdapter.getSelectedIds();
+ for (int i = (toMove.size() - 1); i >= 0; i--) {
+ if (toMove.valueAt(i)) {
+ Email email = mAdapter.getItem(toMove.keyAt(i));
+ mFolder.move(email, newFolder);
+ }
+ }
+ mMode.finish();
+ }
+
// LoaderManager.LoaderCallbacks>
public Loader> onCreateLoader(int id, Bundle args) {
@@ -345,6 +396,11 @@ public class EmailListFragment extends ListFragment implements
onContentChanged();
}
+ @Override
+ public void elementUpdated() {
+ onContentChanged();
+ }
+
@Override
public void elementRemoved() {
onContentChanged();
diff --git a/src/i2p/bote/FolderListAdapter.java b/src/i2p/bote/FolderListAdapter.java
index 1f98e1b..b381d2a 100644
--- a/src/i2p/bote/FolderListAdapter.java
+++ b/src/i2p/bote/FolderListAdapter.java
@@ -57,6 +57,11 @@ public class FolderListAdapter extends ArrayAdapter implements Fold
notifyDataSetChanged();
}
+ @Override
+ public void elementUpdated() {
+ notifyDataSetChanged();
+ }
+
@Override
public void elementRemoved() {
notifyDataSetChanged();
diff --git a/src/i2p/bote/ViewEmailActivity.java b/src/i2p/bote/ViewEmailActivity.java
index 1febbaa..328736f 100644
--- a/src/i2p/bote/ViewEmailActivity.java
+++ b/src/i2p/bote/ViewEmailActivity.java
@@ -154,6 +154,11 @@ public class ViewEmailActivity extends ActionBarActivity implements
onContentChanged();
}
+ @Override
+ public void elementUpdated() {
+ onContentChanged();
+ }
+
@Override
public void elementRemoved() {
onContentChanged();
diff --git a/src/i2p/bote/util/BoteHelper.java b/src/i2p/bote/util/BoteHelper.java
index 42a04c1..c15ed2b 100644
--- a/src/i2p/bote/util/BoteHelper.java
+++ b/src/i2p/bote/util/BoteHelper.java
@@ -10,7 +10,6 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Base64;
-import i2p.bote.I2PBote;
import i2p.bote.R;
import i2p.bote.email.EmailDestination;
import i2p.bote.email.EmailIdentity;
diff --git a/src/i2p/bote/util/MoveToDialogFragment.java b/src/i2p/bote/util/MoveToDialogFragment.java
new file mode 100644
index 0000000..ce32269
--- /dev/null
+++ b/src/i2p/bote/util/MoveToDialogFragment.java
@@ -0,0 +1,84 @@
+package i2p.bote.util;
+
+import i2p.bote.I2PBote;
+import i2p.bote.R;
+import i2p.bote.folder.EmailFolder;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.support.v4.app.DialogFragment;
+
+public class MoveToDialogFragment extends DialogFragment {
+ public static final String CURRENT_FOLDER = "current_folder";
+
+ public static MoveToDialogFragment newInstance(EmailFolder currentFolder) {
+ MoveToDialogFragment f = new MoveToDialogFragment();
+ Bundle args = new Bundle();
+ args.putString(CURRENT_FOLDER, currentFolder.getName());
+ f.setArguments(args);
+ return f;
+ }
+
+ public interface MoveToDialogListener {
+ public void onFolderSelected(EmailFolder newFolder);
+ }
+
+ MoveToDialogListener mListener;
+ List mFolders;
+ List mFolderDisplayNames;
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ try {
+ mListener = (MoveToDialogListener) activity;
+ } catch (ClassCastException e) {
+ throw new ClassCastException(activity.toString()
+ + " must implement MoveToDialogListener");
+ }
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mFolders = I2PBote.getInstance().getEmailFolders();
+ mFolderDisplayNames = new ArrayList();
+
+ String curFolder = getArguments().getString(CURRENT_FOLDER);
+ Iterator i = mFolders.iterator();
+ while (i.hasNext()) {
+ EmailFolder folder = i.next();
+ if (folder.getName().equals(curFolder))
+ i.remove();
+ else
+ mFolderDisplayNames.add(
+ BoteHelper.getFolderDisplayName(getActivity(), folder));
+ }
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle(R.string.action_move_to)
+ .setItems(mFolderDisplayNames.toArray(new String[mFolderDisplayNames.size()]),
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ mListener.onFolderSelected(mFolders.get(which));
+ }
+ })
+ .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.cancel();
+ }
+ });
+ return builder.create();
+ }
+}