diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 0818eec46..76911e44f 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -59,6 +59,11 @@ android:label="@string/account_setup_names_title" > + + + + + + diff --git a/res/values/arrays.xml b/res/values/arrays.xml index 21a3a1d5b..48c06297d 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -90,6 +90,20 @@ NOT_SECOND_CLASS + + @string/account_settings_folder_target_mode_all + @string/account_settings_folder_target_mode_first_class + @string/account_settings_folder_target_mode_first_and_second_class + @string/account_settings_folder_target_mode_not_second_class + + + + ALL + FIRST_CLASS + FIRST_AND_SECOND_CLASS + NOT_SECOND_CLASS + + @string/folder_settings_folder_display_mode_normal @string/folder_settings_folder_display_mode_first_class diff --git a/res/values/strings.xml b/res/values/strings.xml index e1f5bb036..9a1b1cdc0 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -14,6 +14,7 @@ Your accounts Compose Debug + Choose Folder Next @@ -50,6 +51,8 @@ Flag Unflag + Move + Copy Mark as unread Move to @@ -294,6 +297,8 @@ Welcome to K-9 Mail setup. K-9 is an open source email client for Android based 25 Messages 50 Messages 100 Messages + + Cannot copy or move a message that is not synchronized with the server Setup could not finish Username or password incorrect.\n(%s) @@ -335,6 +340,12 @@ Welcome to K-9 Mail setup. K-9 is an open source email client for Android based Only 1st Class folders 1st and 2nd Class folders All except 2nd Class folders + + Move/copy destination folders + All + Only 1st Class folders + 1st and 2nd Class folders + All except 2nd Class folders Folder settings Folder display class @@ -414,9 +425,9 @@ Welcome to K-9 Mail setup. K-9 is an open source email client for Android based Del (or D) - Delete\u000AR - Reply\u000AA - Reply All\u000AF - Forward\u000AJ or P - Previous - Message\u000AK, N - Next Message\u000AZ - Zoom Out\u000AShift-Z - + Message\u000AK, N - Next Message\u000AM - Move\u000AY - Copy\u000AZ - Zoom Out\u000AShift-Z - Zoom In\u000aG - Flag Del (or D) - Delete\u000AR - - Reply\u000AA - Reply All\u000AC - Compose\u000AF - Forward\u000aG - Flag\u000AO - Sort type\u000AI - Sort order\u000AQ + Reply\u000AA - Reply All\u000AC - Compose\u000AF - Forward\u000aM - Move\u000AY - Copy\u000AG - Flag\u000AO - Sort type\u000AI - Sort order\u000AQ - Return to Accounts diff --git a/res/xml/account_settings_preferences.xml b/res/xml/account_settings_preferences.xml index 26af99bf9..0ddfec7d5 100644 --- a/res/xml/account_settings_preferences.xml +++ b/res/xml/account_settings_preferences.xml @@ -69,7 +69,15 @@ android:title="@string/account_settings_folder_sync_mode_label" android:entries="@array/account_settings_folder_sync_mode_entries" android:entryValues="@array/account_settings_folder_sync_mode_values" - android:dialogTitle="@string/account_settings_folder_sync_mode_label" /> + android:dialogTitle="@string/account_settings_folder_sync_mode_label" /> + + + adapter; + private ChooseFolderHandler mHandler = new ChooseFolderHandler(); + String heldInbox = null; + + public static final String EXTRA_ACCOUNT = "com.android.email.ChooseFolder_account"; + public static final String EXTRA_CUR_FOLDER = "com.android.email.ChooseFolder_curfolder"; + public static final String EXTRA_NEW_FOLDER = "com.android.email.ChooseFolder_newfolder"; + public static final String EXTRA_MESSAGE_UID = "com.android.email.ChooseFolder_messageuid"; + + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); + + getListView().setTextFilterEnabled(true); + getListView().setItemsCanFocus(false); + getListView().setChoiceMode(ListView.CHOICE_MODE_NONE); + Intent intent = getIntent(); + mAccount = (Account) intent.getSerializableExtra(EXTRA_ACCOUNT); + mUID = intent.getStringExtra(EXTRA_MESSAGE_UID); + mFolder = intent.getStringExtra(EXTRA_CUR_FOLDER); + if(mFolder == null) + mFolder = ""; + + adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1); + + setListAdapter(adapter); + + new Thread() + { + public void run() + { + Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); + MessagingController.getInstance(getApplication()).listFolders(mAccount, + false, mListener); + + } + }.start(); + + this.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() { + public void onItemClick(AdapterView adapterview, View view, int i, long l) + { + Intent intent = new Intent(); + intent.putExtra(EXTRA_CUR_FOLDER, mFolder); + String destFolderName = (String)((TextView)view).getText(); + if (heldInbox != null && getString(R.string.special_mailbox_name_inbox).equals(destFolderName)) + { + destFolderName = heldInbox; + } + + intent.putExtra(EXTRA_NEW_FOLDER, destFolderName); + + intent.putExtra(EXTRA_MESSAGE_UID, mUID); + setResult(RESULT_OK, intent); + finish(); + } + }); + + } + + class ChooseFolderHandler extends Handler + { + + private static final int MSG_PROGRESS = 2; + + private static final int MSG_DATA_CHANGED = 3; + + public void handleMessage(android.os.Message msg) + { + switch (msg.what) + { + case MSG_PROGRESS: + setProgressBarIndeterminateVisibility(msg.arg1 != 0); + break; + case MSG_DATA_CHANGED: + adapter.notifyDataSetChanged(); + } + } + + public void progress(boolean progress) + { + android.os.Message msg = new android.os.Message(); + msg.what = MSG_PROGRESS; + msg.arg1 = progress ? 1 : 0; + sendMessage(msg); + } + + public void dataChanged() + { + sendEmptyMessage(MSG_DATA_CHANGED); + } + } + + private MessagingListener mListener = new MessagingListener() + { + public void listFoldersStarted(Account account) + { + if (!account.equals(mAccount)) + { + return; + } + mHandler.progress(true); + } + + @Override + public void listFoldersFailed(Account account, String message) + { + if (!account.equals(mAccount)) + { + return; + } + // mHandler.progress(false); + } + + @Override + public void listFoldersFinished(Account account) + { + if (!account.equals(mAccount)) + { + return; + } + // mHandler.progress(false); + } + @Override + public void listFolders(Account account, Folder[] folders) + { + if (!account.equals(mAccount)) + { + return; + } + Account.FolderMode aMode = account.getFolderTargetMode(); + Preferences prefs = Preferences.getPreferences(getApplication().getApplicationContext()); + ArrayList localFolders = new ArrayList(); + + for (Folder folder : folders) + { + String name = folder.getName(); + + // Inbox needs to be compared case-insensitively + if(name.equals(mFolder) || (Email.INBOX.equalsIgnoreCase(mFolder) && Email.INBOX.equalsIgnoreCase(name))) { + continue; + } + try + { + folder.refresh(prefs); + Folder.FolderClass fMode = folder.getDisplayClass(); + + if ((aMode == Account.FolderMode.FIRST_CLASS && fMode != Folder.FolderClass.FIRST_CLASS) + || (aMode == Account.FolderMode.FIRST_AND_SECOND_CLASS && + fMode != Folder.FolderClass.FIRST_CLASS && + fMode != Folder.FolderClass.SECOND_CLASS) + || (aMode == Account.FolderMode.NOT_SECOND_CLASS && fMode == Folder.FolderClass.SECOND_CLASS)) + { + continue; + } + } + catch (MessagingException me) + { + Log.e(Email.LOG_TAG, "Couldn't get prefs to check for displayability of folder " + folder.getName(), me); + } + + localFolders.add(folder.getName()); + + } + + Collections.sort(localFolders, new Comparator() { + public int compare(String aName, String bName) + { + if (Email.INBOX.equalsIgnoreCase(aName)) + { + return -1; + } + if (Email.INBOX.equalsIgnoreCase(bName)) + { + return 1; + } + return aName.compareToIgnoreCase(bName); + } + }); + adapter.setNotifyOnChange(false); + adapter.clear(); + for (String name : localFolders) { + if (Email.INBOX.equalsIgnoreCase(name)) + { + adapter.add(getString(R.string.special_mailbox_name_inbox)); + heldInbox = name; + } + else { + adapter.add(name); + } + } + mHandler.dataChanged(); + } + }; +} diff --git a/src/com/android/email/activity/FolderMessageList.java b/src/com/android/email/activity/FolderMessageList.java index fc5831f1a..e0b3b4871 100644 --- a/src/com/android/email/activity/FolderMessageList.java +++ b/src/com/android/email/activity/FolderMessageList.java @@ -86,6 +86,12 @@ public class FolderMessageList extends ExpandableListActivity { private static final String INTENT_DATA_PATH_SUFFIX = "/accounts"; + + private static final int ACTIVITY_CHOOSE_FOLDER_MOVE = 1; + + private static final int ACTIVITY_CHOOSE_FOLDER_COPY = 2; + + private static final String EXTRA_ACCOUNT = "account"; private static final String EXTRA_CLEAR_NOTIFICATION = "clearNotification"; @@ -723,6 +729,8 @@ public class FolderMessageList extends ExpandableListActivity case KeyEvent.KEYCODE_A: { onReplyAll(message); return true; } case KeyEvent.KEYCODE_R: { onReply(message); return true; } case KeyEvent.KEYCODE_G: { onToggleFlag(message); return true; } + case KeyEvent.KEYCODE_M: { onMove(message); return true; } + case KeyEvent.KEYCODE_Y: { onCopy(message); return true; } } } } @@ -913,6 +921,137 @@ public class FolderMessageList extends ExpandableListActivity } + + private void onMove(MessageInfoHolder holder) + { + if (MessagingController.getInstance(getApplication()).isMoveCapable(mAccount) == false) + { + return; + } + if (MessagingController.getInstance(getApplication()).isMoveCapable(holder.message) == false) + { + Toast toast = Toast.makeText(this, R.string.move_copy_cannot_copy_unsynced_message, Toast.LENGTH_LONG); + toast.show(); + return; + } + Intent intent = new Intent(this, ChooseFolder.class); + intent.putExtra(ChooseFolder.EXTRA_ACCOUNT, mAccount); + intent.putExtra(ChooseFolder.EXTRA_CUR_FOLDER, holder.folder.name); + intent.putExtra(ChooseFolder.EXTRA_MESSAGE_UID, holder.message.getUid()); + startActivityForResult(intent, ACTIVITY_CHOOSE_FOLDER_MOVE); + } + + private void onCopy(MessageInfoHolder holder) + { + if (MessagingController.getInstance(getApplication()).isCopyCapable(mAccount) == false) + { + return; + } + if (MessagingController.getInstance(getApplication()).isMoveCapable(holder.message) == false) + { + Toast toast = Toast.makeText(this, R.string.move_copy_cannot_copy_unsynced_message, Toast.LENGTH_LONG); + toast.show(); + return; + } + Intent intent = new Intent(this, ChooseFolder.class); + intent.putExtra(ChooseFolder.EXTRA_ACCOUNT, mAccount); + intent.putExtra(ChooseFolder.EXTRA_CUR_FOLDER, holder.folder.name); + intent.putExtra(ChooseFolder.EXTRA_MESSAGE_UID, holder.message.getUid()); + startActivityForResult(intent, ACTIVITY_CHOOSE_FOLDER_COPY); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if(resultCode != RESULT_OK) + return; + + switch(requestCode) { + case ACTIVITY_CHOOSE_FOLDER_MOVE: + case ACTIVITY_CHOOSE_FOLDER_COPY: + if (data == null) + return; + String destFolderName = data.getStringExtra(ChooseFolder.EXTRA_NEW_FOLDER); + String srcFolderName = data.getStringExtra(ChooseFolder.EXTRA_CUR_FOLDER); + String uid = data.getStringExtra(ChooseFolder.EXTRA_MESSAGE_UID); + + FolderInfoHolder srcHolder = mAdapter.getFolder(srcFolderName); + FolderInfoHolder destHolder = mAdapter.getFolder(destFolderName); + if (srcHolder != null && destHolder != null) { + MessageInfoHolder m = mAdapter.getMessage(srcHolder, uid); + if (m != null) { + switch (requestCode) { + case ACTIVITY_CHOOSE_FOLDER_MOVE: + onMoveChosen(m, destHolder); + break; + case ACTIVITY_CHOOSE_FOLDER_COPY: + onCopyChosen(m, destHolder); + break; + } + } + } + } + } + + + private void onMoveChosen(MessageInfoHolder holder, FolderInfoHolder folder) + { + if (MessagingController.getInstance(getApplication()).isMoveCapable(mAccount) == false) + { + return; + } + String destFolderName = folder.name; + FolderInfoHolder destHolder = mAdapter.getFolder(destFolderName); + + if (destHolder == null) { + return; + } + + if (holder.read == false && holder.folder.unreadMessageCount > 0) + { + holder.folder.unreadMessageCount--; + destHolder.unreadMessageCount++; + } + + if (destHolder != null) + { + destHolder.needsRefresh = true; + } + + mAdapter.removeMessage(holder.message.getFolder().getName(), holder.uid); + + MessagingController.getInstance(getApplication()).moveMessage(mAccount, + holder.message.getFolder().getName(), holder.message, destFolderName, null); + + } + + + private void onCopyChosen(MessageInfoHolder holder, FolderInfoHolder folder) + { + if (MessagingController.getInstance(getApplication()).isCopyCapable(mAccount) == false) + { + return; + } + String destFolderName = folder.name; + FolderInfoHolder destHolder = mAdapter.getFolder(destFolderName); + + if (destHolder == null) { + return; + } + + if (holder.read == false && holder.folder.unreadMessageCount > 0) + { + destHolder.unreadMessageCount++; + } + + if (destHolder != null) + { + destHolder.needsRefresh = true; + } + + MessagingController.getInstance(getApplication()).copyMessage(mAccount, + holder.message.getFolder().getName(), holder.message, destFolderName, null); + } + private void onReply(MessageInfoHolder holder) { MessageCompose.actionReply(this, mAccount, holder.message, false); @@ -1096,6 +1235,12 @@ public class FolderMessageList extends ExpandableListActivity case R.id.flag: onToggleFlag(holder); break; + case R.id.move: + onMove(holder); + break; + case R.id.copy: + onCopy(holder); + break; case R.id.send_alternate: onSendAlternate(mAccount, holder); break; @@ -1177,6 +1322,14 @@ public class FolderMessageList extends ExpandableListActivity menu.findItem(R.id.flag).setTitle( R.string.unflag_action); } + if (MessagingController.getInstance(getApplication()).isCopyCapable(mAccount) == false) + { + menu.findItem(R.id.copy).setVisible(false); + } + if (MessagingController.getInstance(getApplication()).isMoveCapable(mAccount) == false) + { + menu.findItem(R.id.move).setVisible(false); + } } } else if (ExpandableListView.getPackedPositionType(info.packedPosition) == ExpandableListView.PACKED_POSITION_TYPE_GROUP) { diff --git a/src/com/android/email/activity/MessageView.java b/src/com/android/email/activity/MessageView.java index 8ed680062..8cf05d663 100644 --- a/src/com/android/email/activity/MessageView.java +++ b/src/com/android/email/activity/MessageView.java @@ -56,6 +56,8 @@ import com.android.email.MessagingController; import com.android.email.MessagingListener; import com.android.email.R; import com.android.email.Utility; +import com.android.email.activity.FolderMessageList.FolderMessageListAdapter.FolderInfoHolder; +import com.android.email.activity.FolderMessageList.FolderMessageListAdapter.MessageInfoHolder; import com.android.email.mail.Address; import com.android.email.mail.Flag; import com.android.email.mail.Message; @@ -78,6 +80,11 @@ public class MessageView extends Activity private static final String EXTRA_FOLDER_UIDS = "com.android.email.MessageView_folderUids"; private static final String EXTRA_NEXT = "com.android.email.MessageView_next"; + + private static final int ACTIVITY_CHOOSE_FOLDER_MOVE = 1; + + private static final int ACTIVITY_CHOOSE_FOLDER_COPY = 2; + private TextView mFromView; private TextView mDateView; private TextView mToView; @@ -149,6 +156,9 @@ public class MessageView extends Activity case KeyEvent.KEYCODE_A: { onReplyAll(); return true; } case KeyEvent.KEYCODE_R: { onReply(); return true; } case KeyEvent.KEYCODE_G: { onFlag(); return true; } + + case KeyEvent.KEYCODE_M: { onMove(); return true; } + case KeyEvent.KEYCODE_Y: { onCopy(); return true; } case KeyEvent.KEYCODE_J: case KeyEvent.KEYCODE_P: { onPrevious(); return true; } @@ -583,6 +593,68 @@ public class MessageView extends Activity } } } + + private void onMove() + { + if (MessagingController.getInstance(getApplication()).isMoveCapable(mMessage) == false) + { + Toast toast = Toast.makeText(this, R.string.move_copy_cannot_copy_unsynced_message, Toast.LENGTH_LONG); + toast.show(); + return; + } + Intent intent = new Intent(this, ChooseFolder.class); + intent.putExtra(ChooseFolder.EXTRA_ACCOUNT, mAccount); + intent.putExtra(ChooseFolder.EXTRA_CUR_FOLDER, mFolder); + intent.putExtra(ChooseFolder.EXTRA_MESSAGE_UID, mMessageUid); + startActivityForResult(intent, ACTIVITY_CHOOSE_FOLDER_MOVE); + } + + private void onCopy() + { + if (MessagingController.getInstance(getApplication()).isMoveCapable(mMessage) == false) + { + Toast toast = Toast.makeText(this, R.string.move_copy_cannot_copy_unsynced_message, Toast.LENGTH_LONG); + toast.show(); + return; + } + Intent intent = new Intent(this, ChooseFolder.class); + + intent.putExtra(ChooseFolder.EXTRA_ACCOUNT, mAccount); + intent.putExtra(ChooseFolder.EXTRA_CUR_FOLDER, mFolder); + intent.putExtra(ChooseFolder.EXTRA_MESSAGE_UID, mMessageUid); + startActivityForResult(intent, ACTIVITY_CHOOSE_FOLDER_COPY); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if(resultCode != RESULT_OK) + return; + + switch(requestCode) { + case ACTIVITY_CHOOSE_FOLDER_MOVE: + case ACTIVITY_CHOOSE_FOLDER_COPY: + if (data == null) + return; + String destFolderName = data.getStringExtra(ChooseFolder.EXTRA_NEW_FOLDER); + String srcFolderName = data.getStringExtra(ChooseFolder.EXTRA_CUR_FOLDER); + String uid = data.getStringExtra(ChooseFolder.EXTRA_MESSAGE_UID); + + if (uid.equals(mMessageUid) && srcFolderName.equals(mFolder)) + { + + switch (requestCode) { + case ACTIVITY_CHOOSE_FOLDER_MOVE: + MessagingController.getInstance(getApplication()).moveMessage(mAccount, + srcFolderName, mMessage, destFolderName, null); + break; + case ACTIVITY_CHOOSE_FOLDER_COPY: + MessagingController.getInstance(getApplication()).copyMessage(mAccount, + srcFolderName, mMessage, destFolderName, null); + break; + } + } + } + } private void onSendAlternate() { @@ -760,6 +832,12 @@ public class MessageView extends Activity case R.id.flag: onFlag(); break; + case R.id.move: + onMove(); + break; + case R.id.copy: + onCopy(); + break; default: return super.onOptionsItemSelected(item); } @@ -771,6 +849,14 @@ public class MessageView extends Activity getMenuInflater().inflate(R.menu.message_view_option, menu); optionsMenu = menu; setMenuFlag(); + if (MessagingController.getInstance(getApplication()).isCopyCapable(mAccount) == false) + { + menu.findItem(R.id.copy).setVisible(false); + } + if (MessagingController.getInstance(getApplication()).isMoveCapable(mAccount) == false) + { + menu.findItem(R.id.move).setVisible(false); + } return true; } diff --git a/src/com/android/email/activity/setup/AccountSettings.java b/src/com/android/email/activity/setup/AccountSettings.java index a2e2ecabb..dc1c933fa 100644 --- a/src/com/android/email/activity/setup/AccountSettings.java +++ b/src/com/android/email/activity/setup/AccountSettings.java @@ -36,6 +36,7 @@ public class AccountSettings extends PreferenceActivity { private static final String PREFERENCE_OUTGOING = "outgoing"; private static final String PREFERENCE_DISPLAY_MODE = "folder_display_mode"; private static final String PREFERENCE_SYNC_MODE = "folder_sync_mode"; + private static final String PREFERENCE_TARGET_MODE = "folder_target_mode"; private static final String PREFERENCE_DELETE_POLICY = "delete_policy"; private Account mAccount; @@ -51,6 +52,7 @@ public class AccountSettings extends PreferenceActivity { private RingtonePreference mAccountRingtone; private ListPreference mDisplayMode; private ListPreference mSyncMode; + private ListPreference mTargetMode; private ListPreference mDeletePolicy; public static void actionSettings(Context context, Account account) { @@ -122,6 +124,19 @@ public class AccountSettings extends PreferenceActivity { } }); + mTargetMode = (ListPreference) findPreference(PREFERENCE_TARGET_MODE); + mTargetMode.setValue(mAccount.getFolderTargetMode().name()); + mTargetMode.setSummary(mTargetMode.getEntry()); + mTargetMode.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + public boolean onPreferenceChange(Preference preference, Object newValue) { + final String summary = newValue.toString(); + int index = mTargetMode.findIndexOfValue(summary); + mTargetMode.setSummary(mTargetMode.getEntries()[index]); + mTargetMode.setValue(summary); + return false; + } + }); + mDeletePolicy = (ListPreference) findPreference(PREFERENCE_DELETE_POLICY); mDeletePolicy.setValue("" + mAccount.getDeletePolicy()); mDeletePolicy.setSummary(mDeletePolicy.getEntry()); @@ -225,6 +240,7 @@ public class AccountSettings extends PreferenceActivity { mAccount.setVibrate(mAccountVibrate.isChecked()); mAccount.setFolderDisplayMode(Account.FolderMode.valueOf(mDisplayMode.getValue())); mAccount.setFolderSyncMode(Account.FolderMode.valueOf(mSyncMode.getValue())); + mAccount.setFolderTargetMode(Account.FolderMode.valueOf(mTargetMode.getValue())); mAccount.setDeletePolicy(Integer.parseInt(mDeletePolicy.getValue())); SharedPreferences prefs = mAccountRingtone.getPreferenceManager().getSharedPreferences(); mAccount.setRingtone(prefs.getString(PREFERENCE_RINGTONE, null)); diff --git a/src/com/android/email/mail/Folder.java b/src/com/android/email/mail/Folder.java index f77e5661c..80cabc884 100644 --- a/src/com/android/email/mail/Folder.java +++ b/src/com/android/email/mail/Folder.java @@ -88,7 +88,9 @@ public abstract class Folder { public abstract void appendMessages(Message[] messages) throws MessagingException; - public abstract void copyMessages(Message[] msgs, Folder folder) throws MessagingException; + public void copyMessages(Message[] msgs, Folder folder) throws MessagingException {} ; + + public void moveMessages(Message[] msgs, Folder folder) throws MessagingException {} ; public abstract void setFlags(Message[] messages, Flag[] flags, boolean value) throws MessagingException; diff --git a/src/com/android/email/mail/Store.java b/src/com/android/email/mail/Store.java index 18afe5781..85edd7ceb 100644 --- a/src/com/android/email/mail/Store.java +++ b/src/com/android/email/mail/Store.java @@ -77,4 +77,12 @@ public abstract class Store { public abstract Folder[] getPersonalNamespaces() throws MessagingException; public abstract void checkSettings() throws MessagingException; + + public boolean isCopyCapable() { + return false; + } + public boolean isMoveCapable() { + return false; + } + } diff --git a/src/com/android/email/mail/store/ImapStore.java b/src/com/android/email/mail/store/ImapStore.java index 2004531f6..cc42f8fa9 100644 --- a/src/com/android/email/mail/store/ImapStore.java +++ b/src/com/android/email/mail/store/ImapStore.java @@ -25,6 +25,7 @@ import java.util.HashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; +import java.util.UUID; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; @@ -54,6 +55,8 @@ import com.android.email.mail.internet.MimeMultipart; import com.android.email.mail.internet.MimeUtility; import com.android.email.mail.store.ImapResponseParser.ImapList; import com.android.email.mail.store.ImapResponseParser.ImapResponse; +import com.android.email.mail.store.LocalStore.LocalFolder; +import com.android.email.mail.store.LocalStore.LocalMessage; import com.android.email.mail.transport.CountingOutputStream; import com.android.email.mail.transport.EOLConvertingOutputStream; import com.beetstra.jutf7.CharsetProvider; @@ -306,6 +309,17 @@ public class ImapStore extends Store { throw new RuntimeException("Unable to decode folder name: " + name, uee); } } + + @Override + public boolean isMoveCapable() { + return true; + } + + @Override + public boolean isCopyCapable() + { + return true; + } class ImapFolder extends Folder { private String mName; @@ -517,6 +531,12 @@ public class ImapStore extends Store { throw ioExceptionHandler(mConnection, ioe); } } + + @Override + public void moveMessages(Message[] messages, Folder folder) throws MessagingException { + copyMessages(messages, folder); + setFlags(messages, new Flag[] { Flag.DELETED }, true); + } @Override public int getMessageCount() { @@ -1351,11 +1371,19 @@ public class ImapStore extends Store { } public ImapResponse readResponse() throws IOException, MessagingException { + try { return mParser.readResponse(); + } + catch (IOException ioe) + { + close(); + throw ioe; + } } public String sendCommand(String command, boolean sensitive) throws MessagingException, IOException { + try { open(); String tag = Integer.toString(mNextCommandTag++); String commandToSend = tag + " " + command; @@ -1374,6 +1402,22 @@ public class ImapStore extends Store { } } return tag; + } + catch (IOException ioe) + { + close(); + throw ioe; + } + catch (ImapException ie) + { + close(); + throw ie; + } + catch (MessagingException me) + { + close(); + throw me; + } } public List executeSimpleCommand(String command) throws IOException, diff --git a/src/com/android/email/mail/store/LocalStore.java b/src/com/android/email/mail/store/LocalStore.java index 3e818d912..b10cbb75d 100644 --- a/src/com/android/email/mail/store/LocalStore.java +++ b/src/com/android/email/mail/store/LocalStore.java @@ -448,6 +448,15 @@ public class LocalStore extends Store implements Serializable { return sb.toString(); } } + + public boolean isMoveCapable() { + return true; + } + public boolean isCopyCapable() { + return true; + } + + public class LocalFolder extends Folder implements Serializable { private String mName; @@ -968,6 +977,32 @@ public class LocalStore extends Store implements Serializable { } ((LocalFolder) folder).appendMessages(msgs, true); } + + @Override + public void moveMessages(Message[] msgs, Folder destFolder) throws MessagingException { + if (!(destFolder instanceof LocalFolder)) { + throw new MessagingException("copyMessages called with incorrect Folder"); + } + + LocalFolder lDestFolder = (LocalFolder)destFolder; + for (Message message : msgs) + { + LocalMessage lMessage = (LocalMessage)message; + + if (!message.isSet(Flag.SEEN)) { + setUnreadMessageCount(getUnreadMessageCount() - 1); + lDestFolder.setUnreadMessageCount(destFolder.getUnreadMessageCount() + 1); + } + + message.setUid("Local" + UUID.randomUUID().toString()); + + mDb.execSQL("UPDATE messages " + "SET folder_id = ?, uid = ? " + "WHERE id = ?", new Object[] { + lDestFolder.getId(), + message.getUid(), + lMessage.getId() }); + } + + } /** * The method differs slightly from the contract; If an incoming message already has a uid diff --git a/src/com/android/email/mail/store/WebDavStore.java b/src/com/android/email/mail/store/WebDavStore.java index 1a119ecf5..57cc40f5e 100644 --- a/src/com/android/email/mail/store/WebDavStore.java +++ b/src/com/android/email/mail/store/WebDavStore.java @@ -1469,12 +1469,6 @@ public class WebDavStore extends Store { Log.e(Email.LOG_TAG, "appendMessages() not implmented"); } - - @Override - public void copyMessages(Message[] msgs, Folder folder) throws MessagingException { - Log.e(Email.LOG_TAG, "copyMessages() not implemented"); - } - @Override public Message[] expunge() throws MessagingException { /** Do nothing, deletes occur as soon as the call is made rather than flags on the message */