mirror of
https://github.com/moparisthebest/k-9
synced 2024-11-30 13:12:25 -05:00
Split message code into Local/Remote
The remote network code does not need to be aware of concepts like Accounts etc.
This commit is contained in:
parent
6f4610dd5b
commit
9fd722d7cd
@ -29,6 +29,8 @@ import com.fsck.k9.mail.Address;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.Store;
|
||||
import com.fsck.k9.mail.Folder.FolderClass;
|
||||
import com.fsck.k9.mail.store.RemoteStore;
|
||||
import com.fsck.k9.mail.store.StoreConfig;
|
||||
import com.fsck.k9.mail.store.StorageManager;
|
||||
import com.fsck.k9.mail.store.StorageManager.StorageProvider;
|
||||
import com.fsck.k9.mail.store.local.LocalStore;
|
||||
@ -48,7 +50,7 @@ import com.larswerkman.colorpicker.ColorPicker;
|
||||
* Account stores all of the settings for a single account defined by the user. It is able to save
|
||||
* and delete itself given a Preferences to work with. Each account is defined by a UUID.
|
||||
*/
|
||||
public class Account implements BaseAccount {
|
||||
public class Account implements BaseAccount, StoreConfig {
|
||||
/**
|
||||
* Default value for the inbox folder (never changes for POP3 and IMAP)
|
||||
*/
|
||||
@ -1289,11 +1291,11 @@ public class Account implements BaseAccount {
|
||||
}
|
||||
|
||||
public LocalStore getLocalStore() throws MessagingException {
|
||||
return Store.getLocalInstance(this, K9.app);
|
||||
return LocalStore.getInstance(this, K9.app);
|
||||
}
|
||||
|
||||
public Store getRemoteStore() throws MessagingException {
|
||||
return Store.getRemoteInstance(this);
|
||||
return RemoteStore.getInstance(this);
|
||||
}
|
||||
|
||||
// It'd be great if this actually went into the store implementation
|
||||
|
@ -14,6 +14,7 @@ import android.content.SharedPreferences;
|
||||
import android.util.Log;
|
||||
|
||||
import com.fsck.k9.mail.Store;
|
||||
import com.fsck.k9.mail.store.local.LocalStore;
|
||||
import com.fsck.k9.preferences.Editor;
|
||||
import com.fsck.k9.preferences.Storage;
|
||||
|
||||
@ -121,7 +122,7 @@ public class Preferences {
|
||||
accountsInOrder.remove(account);
|
||||
}
|
||||
|
||||
Store.removeAccount(account);
|
||||
LocalStore.removeAccount(account);
|
||||
|
||||
account.deleteCertificates();
|
||||
account.delete(this);
|
||||
|
@ -5,7 +5,6 @@ import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
@ -76,12 +75,11 @@ import com.fsck.k9.activity.setup.Prefs;
|
||||
import com.fsck.k9.activity.setup.WelcomeMessage;
|
||||
import com.fsck.k9.controller.MessagingController;
|
||||
import com.fsck.k9.helper.SizeFormatter;
|
||||
import com.fsck.k9.helper.Utility;
|
||||
import com.fsck.k9.mail.AuthType;
|
||||
import com.fsck.k9.mail.ServerSettings;
|
||||
import com.fsck.k9.mail.Store;
|
||||
import com.fsck.k9.mail.Transport;
|
||||
import com.fsck.k9.mail.internet.MimeUtility;
|
||||
import com.fsck.k9.mail.store.RemoteStore;
|
||||
import com.fsck.k9.mail.store.StorageManager;
|
||||
import com.fsck.k9.mail.store.WebDavStore;
|
||||
import com.fsck.k9.preferences.SettingsExporter;
|
||||
@ -771,7 +769,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
|
||||
}
|
||||
|
||||
private void show(final Accounts activity, boolean restore) {
|
||||
ServerSettings incoming = Store.decodeStoreUri(mAccount.getStoreUri());
|
||||
ServerSettings incoming = RemoteStore.decodeStoreUri(mAccount.getStoreUri());
|
||||
ServerSettings outgoing = Transport.decodeTransportUri(mAccount.getTransportUri());
|
||||
|
||||
/*
|
||||
@ -992,9 +990,9 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
|
||||
if (mIncomingPassword != null) {
|
||||
// Set incoming server password
|
||||
String storeUri = mAccount.getStoreUri();
|
||||
ServerSettings incoming = Store.decodeStoreUri(storeUri);
|
||||
ServerSettings incoming = RemoteStore.decodeStoreUri(storeUri);
|
||||
ServerSettings newIncoming = incoming.newPassword(mIncomingPassword);
|
||||
String newStoreUri = Store.createStoreUri(newIncoming);
|
||||
String newStoreUri = RemoteStore.createStoreUri(newIncoming);
|
||||
mAccount.setStoreUri(newStoreUri);
|
||||
}
|
||||
|
||||
|
@ -108,6 +108,7 @@ import com.fsck.k9.mail.internet.MimeUtility;
|
||||
import com.fsck.k9.mail.internet.TextBody;
|
||||
import com.fsck.k9.mail.internet.TextBodyBuilder;
|
||||
import com.fsck.k9.mail.store.local.LocalAttachmentBody;
|
||||
import com.fsck.k9.mail.store.local.LocalMessage;
|
||||
import com.fsck.k9.mail.store.local.TempFileBody;
|
||||
import com.fsck.k9.mail.store.local.TempFileMessageBody;
|
||||
import com.fsck.k9.view.MessageWebView;
|
||||
@ -435,14 +436,12 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
||||
* Get intent for composing a new message as a reply to the given message. If replyAll is true
|
||||
* the function is reply all instead of simply reply.
|
||||
* @param context
|
||||
* @param account
|
||||
* @param message
|
||||
* @param replyAll
|
||||
* @param messageBody optional, for decrypted messages, null if it should be grabbed from the given message
|
||||
*/
|
||||
public static Intent getActionReplyIntent(
|
||||
Context context,
|
||||
Account account,
|
||||
Message message,
|
||||
boolean replyAll,
|
||||
String messageBody) {
|
||||
@ -468,23 +467,20 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
||||
*/
|
||||
public static void actionReply(
|
||||
Context context,
|
||||
Account account,
|
||||
Message message,
|
||||
boolean replyAll,
|
||||
String messageBody) {
|
||||
context.startActivity(getActionReplyIntent(context, account, message, replyAll, messageBody));
|
||||
context.startActivity(getActionReplyIntent(context, message, replyAll, messageBody));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compose a new message as a forward of the given message.
|
||||
* @param context
|
||||
* @param account
|
||||
* @param message
|
||||
* @param messageBody optional, for decrypted messages, null if it should be grabbed from the given message
|
||||
*/
|
||||
public static void actionForward(
|
||||
Context context,
|
||||
Account account,
|
||||
Message message,
|
||||
String messageBody) {
|
||||
Intent i = new Intent(context, MessageCompose.class);
|
||||
@ -2646,7 +2642,7 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
||||
* @param message
|
||||
* The source message used to populate the various text fields.
|
||||
*/
|
||||
private void processSourceMessage(Message message) {
|
||||
private void processSourceMessage(LocalMessage message) {
|
||||
try {
|
||||
switch (mAction) {
|
||||
case REPLY:
|
||||
@ -2800,7 +2796,7 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
||||
}
|
||||
}
|
||||
|
||||
private void processDraftMessage(Message message) throws MessagingException {
|
||||
private void processDraftMessage(LocalMessage message) throws MessagingException {
|
||||
String showQuotedTextMode = "NONE";
|
||||
|
||||
mDraftId = MessagingController.getInstance(getApplication()).getId(message);
|
||||
@ -2852,7 +2848,7 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
||||
newIdentity.setSignature(k9identity.get(IdentityField.SIGNATURE));
|
||||
mSignatureChanged = true;
|
||||
} else {
|
||||
newIdentity.setSignatureUse(message.getFolder().getAccount().getSignatureUse());
|
||||
newIdentity.setSignatureUse(message.getFolder().getSignatureUse());
|
||||
newIdentity.setSignature(mIdentity.getSignature());
|
||||
}
|
||||
|
||||
@ -3437,7 +3433,7 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
||||
}
|
||||
updateMessageFormat();
|
||||
} else {
|
||||
processSourceMessage(message);
|
||||
processSourceMessage((LocalMessage) message);
|
||||
mSourceProcessed = true;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package com.fsck.k9.activity;
|
||||
|
||||
import java.util.Date;
|
||||
import com.fsck.k9.mail.Message;
|
||||
import com.fsck.k9.mail.store.local.LocalMessage;
|
||||
|
||||
public class MessageInfoHolder {
|
||||
public String date;
|
||||
@ -18,7 +19,7 @@ public class MessageInfoHolder {
|
||||
public boolean forwarded;
|
||||
public boolean flagged;
|
||||
public boolean dirty;
|
||||
public Message message;
|
||||
public LocalMessage message;
|
||||
public FolderInfoHolder folder;
|
||||
public boolean selected;
|
||||
public String account;
|
||||
@ -31,7 +32,7 @@ public class MessageInfoHolder {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof MessageInfoHolder == false) {
|
||||
if (!(o instanceof MessageInfoHolder)) {
|
||||
return false;
|
||||
}
|
||||
MessageInfoHolder other = (MessageInfoHolder)o;
|
||||
|
@ -1199,17 +1199,17 @@ public class MessageList extends K9FragmentActivity implements MessageListFragme
|
||||
|
||||
@Override
|
||||
public void onForward(Message message) {
|
||||
MessageCompose.actionForward(this, message.getFolder().getAccount(), message, null);
|
||||
MessageCompose.actionForward(this, message, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReply(Message message) {
|
||||
MessageCompose.actionReply(this, message.getFolder().getAccount(), message, false, null);
|
||||
MessageCompose.actionReply(this, message, false, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReplyAll(Message message) {
|
||||
MessageCompose.actionReply(this, message.getFolder().getAccount(), message, true, null);
|
||||
MessageCompose.actionReply(this, message, true, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1400,17 +1400,17 @@ public class MessageList extends K9FragmentActivity implements MessageListFragme
|
||||
|
||||
@Override
|
||||
public void onReply(Message message, PgpData pgpData) {
|
||||
MessageCompose.actionReply(this, mAccount, message, false, pgpData.getDecryptedData());
|
||||
MessageCompose.actionReply(this, message, false, pgpData.getDecryptedData());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReplyAll(Message message, PgpData pgpData) {
|
||||
MessageCompose.actionReply(this, mAccount, message, true, pgpData.getDecryptedData());
|
||||
MessageCompose.actionReply(this, message, true, pgpData.getDecryptedData());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onForward(Message mMessage, PgpData mPgpData) {
|
||||
MessageCompose.actionForward(this, mAccount, mMessage, mPgpData.getDecryptedData());
|
||||
MessageCompose.actionForward(this, mMessage, mPgpData.getDecryptedData());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -13,6 +13,8 @@ import com.fsck.k9.mail.Flag;
|
||||
import com.fsck.k9.mail.Folder;
|
||||
import com.fsck.k9.mail.Message;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.store.local.LocalFolder;
|
||||
import com.fsck.k9.mail.store.local.LocalMessage;
|
||||
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
@ -128,13 +130,13 @@ public class MessageReference implements Parcelable {
|
||||
'}';
|
||||
}
|
||||
|
||||
public Message restoreToLocalMessage(Context context) {
|
||||
public LocalMessage restoreToLocalMessage(Context context) {
|
||||
try {
|
||||
Account account = Preferences.getPreferences(context).getAccount(accountUuid);
|
||||
if (account != null) {
|
||||
Folder folder = account.getLocalStore().getFolder(folderName);
|
||||
LocalFolder folder = account.getLocalStore().getFolder(folderName);
|
||||
if (folder != null) {
|
||||
Message message = folder.getMessage(uid);
|
||||
LocalMessage message = folder.getMessage(uid);
|
||||
if (message != null) {
|
||||
return message;
|
||||
} else {
|
||||
|
@ -38,9 +38,9 @@ import com.fsck.k9.helper.Utility;
|
||||
import com.fsck.k9.mail.AuthType;
|
||||
import com.fsck.k9.mail.ConnectionSecurity;
|
||||
import com.fsck.k9.mail.ServerSettings;
|
||||
import com.fsck.k9.mail.Store;
|
||||
import com.fsck.k9.mail.Transport;
|
||||
import com.fsck.k9.mail.store.ImapStore;
|
||||
import com.fsck.k9.mail.store.RemoteStore;
|
||||
import com.fsck.k9.mail.transport.SmtpTransport;
|
||||
import com.fsck.k9.view.ClientCertificateSpinner;
|
||||
import com.fsck.k9.view.ClientCertificateSpinner.OnClientCertificateChangedListener;
|
||||
@ -421,7 +421,7 @@ public class AccountSetupBasics extends K9Activity
|
||||
ConnectionSecurity.SSL_TLS_REQUIRED, authenticationType, user, password, clientCertificateAlias);
|
||||
ServerSettings transportServer = new ServerSettings(SmtpTransport.TRANSPORT_TYPE, "mail." + domain, -1,
|
||||
ConnectionSecurity.SSL_TLS_REQUIRED, authenticationType, user, password, clientCertificateAlias);
|
||||
String storeUri = Store.createStoreUri(storeServer);
|
||||
String storeUri = RemoteStore.createStoreUri(storeServer);
|
||||
String transportUri = Transport.createTransportUri(transportServer);
|
||||
mAccount.setStoreUri(storeUri);
|
||||
mAccount.setTransportUri(transportUri);
|
||||
|
@ -27,6 +27,7 @@ import com.fsck.k9.mail.Store;
|
||||
import com.fsck.k9.mail.Transport;
|
||||
import com.fsck.k9.mail.store.ImapStore;
|
||||
import com.fsck.k9.mail.store.Pop3Store;
|
||||
import com.fsck.k9.mail.store.RemoteStore;
|
||||
import com.fsck.k9.mail.store.WebDavStore;
|
||||
import com.fsck.k9.mail.store.ImapStore.ImapStoreSettings;
|
||||
import com.fsck.k9.mail.store.WebDavStore.WebDavStoreSettings;
|
||||
@ -163,7 +164,7 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
|
||||
}
|
||||
|
||||
try {
|
||||
ServerSettings settings = Store.decodeStoreUri(mAccount.getStoreUri());
|
||||
ServerSettings settings = RemoteStore.decodeStoreUri(mAccount.getStoreUri());
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
// The first item is selected if settings.authenticationType is null or is not in mAuthTypeAdapter
|
||||
@ -610,7 +611,7 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
|
||||
ServerSettings settings = new ServerSettings(mStoreType, host, port,
|
||||
connectionSecurity, authType, username, password, clientCertificateAlias, extra);
|
||||
|
||||
mAccount.setStoreUri(Store.createStoreUri(settings));
|
||||
mAccount.setStoreUri(RemoteStore.createStoreUri(settings));
|
||||
|
||||
mAccount.setCompression(Account.TYPE_MOBILE, mCompressionMobile.isChecked());
|
||||
mAccount.setCompression(Account.TYPE_WIFI, mCompressionWifi.isChecked());
|
||||
|
10
src/com/fsck/k9/cache/EmailProviderCache.java
vendored
10
src/com/fsck/k9/cache/EmailProviderCache.java
vendored
@ -123,13 +123,11 @@ public class EmailProviderCache {
|
||||
}
|
||||
}
|
||||
|
||||
public void hideMessages(List<Message> messages) {
|
||||
public void hideMessages(List<LocalMessage> messages) {
|
||||
synchronized (mHiddenMessageCache) {
|
||||
for (Message message : messages) {
|
||||
LocalMessage localMessage = (LocalMessage) message;
|
||||
long messageId = localMessage.getId();
|
||||
long folderId = ((LocalFolder) localMessage.getFolder()).getId();
|
||||
mHiddenMessageCache.put(messageId, folderId);
|
||||
for (LocalMessage message : messages) {
|
||||
long messageId = message.getId();
|
||||
mHiddenMessageCache.put(messageId, message.getFolder().getId());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,10 +3,10 @@ package com.fsck.k9.controller;
|
||||
|
||||
import com.fsck.k9.mail.Message;
|
||||
|
||||
public interface MessageRetrievalListener {
|
||||
public interface MessageRetrievalListener<T extends Message> {
|
||||
public void messageStarted(String uid, int number, int ofTotal);
|
||||
|
||||
public void messageFinished(Message message, int number, int ofTotal);
|
||||
public void messageFinished(T message, int number, int ofTotal);
|
||||
|
||||
/**
|
||||
* FIXME <strong>this method is almost never invoked by various Stores! Don't rely on it unless fixed!!</strong>
|
||||
|
@ -312,7 +312,7 @@ public class MessagingController implements Runnable {
|
||||
|
||||
private static final Set<Flag> SYNC_FLAGS = EnumSet.of(Flag.SEEN, Flag.FLAGGED, Flag.ANSWERED, Flag.FORWARDED);
|
||||
|
||||
private void suppressMessages(Account account, List<Message> messages) {
|
||||
private void suppressMessages(Account account, List<LocalMessage> messages) {
|
||||
EmailProviderCache cache = EmailProviderCache.getCache(account.getUuid(),
|
||||
mApplication.getApplicationContext());
|
||||
cache.hideMessages(messages);
|
||||
@ -324,13 +324,11 @@ public class MessagingController implements Runnable {
|
||||
cache.unhideMessages(messages);
|
||||
}
|
||||
|
||||
private boolean isMessageSuppressed(Account account, Message message) {
|
||||
LocalMessage localMessage = (LocalMessage) message;
|
||||
String accountUuid = account.getUuid();
|
||||
long messageId = localMessage.getId();
|
||||
long folderId = ((LocalFolder) localMessage.getFolder()).getId();
|
||||
private boolean isMessageSuppressed(LocalMessage message) {
|
||||
long messageId = message.getId();
|
||||
long folderId = message.getFolder().getId();
|
||||
|
||||
EmailProviderCache cache = EmailProviderCache.getCache(accountUuid,
|
||||
EmailProviderCache cache = EmailProviderCache.getCache(message.getFolder().getUuid(),
|
||||
mApplication.getApplicationContext());
|
||||
return cache.isMessageHidden(messageId, folderId);
|
||||
}
|
||||
@ -690,15 +688,15 @@ public class MessagingController implements Runnable {
|
||||
}
|
||||
|
||||
// Collecting statistics of the search result
|
||||
MessageRetrievalListener retrievalListener = new MessageRetrievalListener() {
|
||||
MessageRetrievalListener retrievalListener = new MessageRetrievalListener<LocalMessage>() {
|
||||
@Override
|
||||
public void messageStarted(String message, int number, int ofTotal) {}
|
||||
@Override
|
||||
public void messagesFinished(int number) {}
|
||||
@Override
|
||||
public void messageFinished(Message message, int number, int ofTotal) {
|
||||
if (!isMessageSuppressed(message.getFolder().getAccount(), message)) {
|
||||
List<Message> messages = new ArrayList<Message>();
|
||||
public void messageFinished(LocalMessage message, int number, int ofTotal) {
|
||||
if (!isMessageSuppressed(message)) {
|
||||
List<LocalMessage> messages = new ArrayList<LocalMessage>();
|
||||
|
||||
messages.add(message);
|
||||
stats.unreadMessageCount += (!message.isSet(Flag.SEEN)) ? 1 : 0;
|
||||
@ -762,7 +760,7 @@ public class MessagingController implements Runnable {
|
||||
final Account acct = Preferences.getPreferences(mApplication.getApplicationContext()).getAccount(acctUuid);
|
||||
|
||||
if (listener != null) {
|
||||
listener.remoteSearchStarted(acct, folderName);
|
||||
listener.remoteSearchStarted(folderName);
|
||||
}
|
||||
|
||||
List<Message> extraResults = new ArrayList<Message>();
|
||||
@ -791,7 +789,7 @@ public class MessagingController implements Runnable {
|
||||
messages.clear();
|
||||
|
||||
if (listener != null) {
|
||||
listener.remoteSearchServerQueryComplete(acct, folderName, remoteMessages.size());
|
||||
listener.remoteSearchServerQueryComplete(folderName, remoteMessages.size(), acct.getRemoteSearchNumResults());
|
||||
}
|
||||
|
||||
Collections.sort(remoteMessages, new UidReverseComparator());
|
||||
@ -811,13 +809,13 @@ public class MessagingController implements Runnable {
|
||||
} else {
|
||||
Log.e(K9.LOG_TAG, "Could not complete remote search", e);
|
||||
if (listener != null) {
|
||||
listener.remoteSearchFailed(acct, null, e.getMessage());
|
||||
listener.remoteSearchFailed(null, e.getMessage());
|
||||
}
|
||||
addErrorMessage(acct, null, e);
|
||||
}
|
||||
} finally {
|
||||
if (listener != null) {
|
||||
listener.remoteSearchFinished(acct, folderName, 0, extraResults);
|
||||
listener.remoteSearchFinished(folderName, 0, acct.getRemoteSearchNumResults(), extraResults);
|
||||
}
|
||||
}
|
||||
|
||||
@ -878,7 +876,7 @@ public class MessagingController implements Runnable {
|
||||
}
|
||||
|
||||
if (listener != null) {
|
||||
listener.remoteSearchAddMessage(remoteFolder.getAccount(), remoteFolder.getName(), localMsg, i, messages.size());
|
||||
listener.remoteSearchAddMessage(remoteFolder.getName(), localMsg, i, messages.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1455,7 +1453,7 @@ public class MessagingController implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private void fetchUnsyncedMessages(final Account account, final Folder remoteFolder,
|
||||
private <T extends Message> void fetchUnsyncedMessages(final Account account, final Folder<T> remoteFolder,
|
||||
final LocalFolder localFolder,
|
||||
List<Message> unsyncedMessages,
|
||||
final List<Message> smallMessages,
|
||||
@ -1473,9 +1471,9 @@ public class MessagingController implements Runnable {
|
||||
final List<Message> chunk = new ArrayList<Message>(UNSYNC_CHUNK_SIZE);
|
||||
|
||||
remoteFolder.fetch(unsyncedMessages, fp,
|
||||
new MessageRetrievalListener() {
|
||||
new MessageRetrievalListener<T>() {
|
||||
@Override
|
||||
public void messageFinished(Message message, int number, int ofTotal) {
|
||||
public void messageFinished(T message, int number, int ofTotal) {
|
||||
try {
|
||||
String newPushState = remoteFolder.getNewPushState(localFolder.getPushState(), message);
|
||||
if (newPushState != null) {
|
||||
@ -1564,7 +1562,7 @@ public class MessagingController implements Runnable {
|
||||
localFolder.appendMessages(messages);
|
||||
|
||||
for (final Message message : messages) {
|
||||
final Message localMessage = localFolder.getMessage(message.getUid());
|
||||
final LocalMessage localMessage = localFolder.getMessage(message.getUid());
|
||||
syncFlags(localMessage, message);
|
||||
if (K9.DEBUG)
|
||||
Log.v(K9.LOG_TAG, "About to notify listeners that we got a new unsynced message "
|
||||
@ -1592,9 +1590,9 @@ public class MessagingController implements Runnable {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void downloadSmallMessages(final Account account, final Folder remoteFolder,
|
||||
private <T extends Message> void downloadSmallMessages(final Account account, final Folder<T> remoteFolder,
|
||||
final LocalFolder localFolder,
|
||||
List<Message> smallMessages,
|
||||
List<T> smallMessages,
|
||||
final AtomicInteger progress,
|
||||
final int unreadBeforeStart,
|
||||
final AtomicInteger newMessages,
|
||||
@ -1608,9 +1606,9 @@ public class MessagingController implements Runnable {
|
||||
Log.d(K9.LOG_TAG, "SYNC: Fetching small messages for folder " + folder);
|
||||
|
||||
remoteFolder.fetch(smallMessages,
|
||||
fp, new MessageRetrievalListener() {
|
||||
fp, new MessageRetrievalListener<T>() {
|
||||
@Override
|
||||
public void messageFinished(final Message message, int number, int ofTotal) {
|
||||
public void messageFinished(final T message, int number, int ofTotal) {
|
||||
try {
|
||||
|
||||
if (!shouldImportMessage(account, folder, message, progress, earliestDate)) {
|
||||
@ -1671,9 +1669,9 @@ public class MessagingController implements Runnable {
|
||||
|
||||
|
||||
|
||||
private void downloadLargeMessages(final Account account, final Folder remoteFolder,
|
||||
private <T extends Message> void downloadLargeMessages(final Account account, final Folder<T> remoteFolder,
|
||||
final LocalFolder localFolder,
|
||||
List<Message> largeMessages,
|
||||
List<T> largeMessages,
|
||||
final AtomicInteger progress,
|
||||
final int unreadBeforeStart,
|
||||
final AtomicInteger newMessages,
|
||||
@ -1821,11 +1819,11 @@ public class MessagingController implements Runnable {
|
||||
|
||||
remoteFolder.fetch(undeletedMessages, fp, null);
|
||||
for (Message remoteMessage : syncFlagMessages) {
|
||||
Message localMessage = localFolder.getMessage(remoteMessage.getUid());
|
||||
LocalMessage localMessage = localFolder.getMessage(remoteMessage.getUid());
|
||||
boolean messageChanged = syncFlags(localMessage, remoteMessage);
|
||||
if (messageChanged) {
|
||||
boolean shouldBeNotifiedOf = false;
|
||||
if (localMessage.isSet(Flag.DELETED) || isMessageSuppressed(account, localMessage)) {
|
||||
if (localMessage.isSet(Flag.DELETED) || isMessageSuppressed(localMessage)) {
|
||||
for (MessagingListener l : getListeners()) {
|
||||
l.synchronizeMailboxRemovedMessage(account, folder, localMessage);
|
||||
}
|
||||
@ -1859,13 +1857,13 @@ public class MessagingController implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean syncFlags(Message localMessage, Message remoteMessage) throws MessagingException {
|
||||
private boolean syncFlags(LocalMessage localMessage, Message remoteMessage) throws MessagingException {
|
||||
boolean messageChanged = false;
|
||||
if (localMessage == null || localMessage.isSet(Flag.DELETED)) {
|
||||
return false;
|
||||
}
|
||||
if (remoteMessage.isSet(Flag.DELETED)) {
|
||||
if (localMessage.getFolder().getAccount().syncRemoteDeletions()) {
|
||||
if (localMessage.getFolder().syncRemoteDeletions()) {
|
||||
localMessage.setFlag(Flag.DELETED, true);
|
||||
messageChanged = true;
|
||||
}
|
||||
@ -2857,7 +2855,7 @@ public class MessagingController implements Runnable {
|
||||
* @param newState
|
||||
* {@code true}, if the flag should be set. {@code false} if it should be removed.
|
||||
*/
|
||||
public void setFlag(Account account, String folderName, List<Message> messages, Flag flag,
|
||||
public void setFlag(Account account, String folderName, List<? extends Message> messages, Flag flag,
|
||||
boolean newState) {
|
||||
// TODO: Put this into the background, but right now some callers depend on the message
|
||||
// objects being modified right after this method returns.
|
||||
@ -3775,7 +3773,7 @@ public class MessagingController implements Runnable {
|
||||
}
|
||||
}
|
||||
public void moveMessages(final Account account, final String srcFolder,
|
||||
final List<Message> messages, final String destFolder,
|
||||
final List<LocalMessage> messages, final String destFolder,
|
||||
final MessagingListener listener) {
|
||||
|
||||
suppressMessages(account, messages);
|
||||
@ -3790,7 +3788,7 @@ public class MessagingController implements Runnable {
|
||||
}
|
||||
|
||||
public void moveMessagesInThread(final Account account, final String srcFolder,
|
||||
final List<Message> messages, final String destFolder) {
|
||||
final List<LocalMessage> messages, final String destFolder) {
|
||||
|
||||
suppressMessages(account, messages);
|
||||
|
||||
@ -3808,14 +3806,14 @@ public class MessagingController implements Runnable {
|
||||
});
|
||||
}
|
||||
|
||||
public void moveMessage(final Account account, final String srcFolder, final Message message,
|
||||
public void moveMessage(final Account account, final String srcFolder, final LocalMessage message,
|
||||
final String destFolder, final MessagingListener listener) {
|
||||
|
||||
moveMessages(account, srcFolder, Collections.singletonList(message), destFolder, listener);
|
||||
}
|
||||
|
||||
public void copyMessages(final Account account, final String srcFolder,
|
||||
final List<Message> messages, final String destFolder,
|
||||
final List<? extends Message> messages, final String destFolder,
|
||||
final MessagingListener listener) {
|
||||
|
||||
putBackground("copyMessages", null, new Runnable() {
|
||||
@ -3828,7 +3826,7 @@ public class MessagingController implements Runnable {
|
||||
}
|
||||
|
||||
public void copyMessagesInThread(final Account account, final String srcFolder,
|
||||
final List<Message> messages, final String destFolder) {
|
||||
final List<? extends Message> messages, final String destFolder) {
|
||||
|
||||
putBackground("copyMessagesInThread", null, new Runnable() {
|
||||
@Override
|
||||
@ -3851,7 +3849,7 @@ public class MessagingController implements Runnable {
|
||||
}
|
||||
|
||||
private void moveOrCopyMessageSynchronous(final Account account, final String srcFolder,
|
||||
final List<Message> inMessages, final String destFolder, final boolean isCopy,
|
||||
final List<? extends Message> inMessages, final String destFolder, final boolean isCopy,
|
||||
MessagingListener listener) {
|
||||
|
||||
try {
|
||||
@ -3962,7 +3960,7 @@ public class MessagingController implements Runnable {
|
||||
localFolder.open(Folder.OPEN_MODE_RW);
|
||||
String uid = localFolder.getMessageUidById(id);
|
||||
if (uid != null) {
|
||||
Message message = localFolder.getMessage(uid);
|
||||
LocalMessage message = localFolder.getMessage(uid);
|
||||
if (message != null) {
|
||||
deleteMessages(Collections.singletonList(message), null);
|
||||
}
|
||||
@ -3974,7 +3972,7 @@ public class MessagingController implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteThreads(final List<Message> messages) {
|
||||
public void deleteThreads(final List<LocalMessage> messages) {
|
||||
actOnMessages(messages, new MessageActor() {
|
||||
|
||||
@Override
|
||||
@ -4006,7 +4004,7 @@ public class MessagingController implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
public List<Message> collectMessagesInThreads(Account account, List<Message> messages)
|
||||
public List<Message> collectMessagesInThreads(Account account, List<? extends Message> messages)
|
||||
throws MessagingException {
|
||||
|
||||
LocalStore localStore = account.getLocalStore();
|
||||
@ -4025,7 +4023,7 @@ public class MessagingController implements Runnable {
|
||||
return messagesInThreads;
|
||||
}
|
||||
|
||||
public void deleteMessages(final List<Message> messages, final MessagingListener listener) {
|
||||
public void deleteMessages(final List<LocalMessage> messages, final MessagingListener listener) {
|
||||
actOnMessages(messages, new MessageActor() {
|
||||
|
||||
@Override
|
||||
@ -5685,15 +5683,15 @@ public class MessagingController implements Runnable {
|
||||
|
||||
}
|
||||
|
||||
private void actOnMessages(List<Message> messages, MessageActor actor) {
|
||||
private void actOnMessages(List<LocalMessage> messages, MessageActor actor) {
|
||||
Map<Account, Map<Folder, List<Message>>> accountMap = new HashMap<Account, Map<Folder, List<Message>>>();
|
||||
|
||||
for (Message message : messages) {
|
||||
for (LocalMessage message : messages) {
|
||||
if ( message == null) {
|
||||
continue;
|
||||
}
|
||||
Folder folder = message.getFolder();
|
||||
Account account = folder.getAccount();
|
||||
Account account = message.getAccount();
|
||||
|
||||
Map<Folder, List<Message>> folderMap = accountMap.get(account);
|
||||
if (folderMap == null) {
|
||||
|
@ -11,6 +11,7 @@ import com.fsck.k9.BaseAccount;
|
||||
import com.fsck.k9.mail.Folder;
|
||||
import com.fsck.k9.mail.Message;
|
||||
import com.fsck.k9.mail.Part;
|
||||
import com.fsck.k9.mail.store.local.LocalMessage;
|
||||
|
||||
/**
|
||||
* Defines the interface that {@link MessagingController} will use to callback to requesters.
|
||||
@ -42,10 +43,8 @@ public class MessagingListener {
|
||||
|
||||
public void listLocalMessagesStarted(Account account, String folder) {}
|
||||
|
||||
public void listLocalMessages(Account account, String folder, Message[] messages) {}
|
||||
|
||||
public void listLocalMessagesAddMessages(Account account, String folder,
|
||||
List<Message> messages) {}
|
||||
List<LocalMessage> messages) {}
|
||||
|
||||
public void listLocalMessagesUpdateMessage(Account account, String folder, Message message) {}
|
||||
|
||||
@ -156,10 +155,9 @@ public class MessagingListener {
|
||||
/**
|
||||
* Called when a remote search is started
|
||||
*
|
||||
* @param acct
|
||||
* @param folder
|
||||
*/
|
||||
public void remoteSearchStarted(Account acct, String folder) {}
|
||||
public void remoteSearchStarted(String folder) {}
|
||||
|
||||
|
||||
/**
|
||||
@ -167,35 +165,30 @@ public class MessagingListener {
|
||||
*
|
||||
* @param numResults
|
||||
*/
|
||||
public void remoteSearchServerQueryComplete(Account account, String folderName, int numResults) { }
|
||||
public void remoteSearchServerQueryComplete(String folderName, int numResults, int maxResults) { }
|
||||
|
||||
|
||||
/**
|
||||
* Called when a new result message is available for a remote search
|
||||
* Can assume headers have been downloaded, but potentially not body.
|
||||
* @param account
|
||||
* @param folder
|
||||
* @param message
|
||||
*/
|
||||
public void remoteSearchAddMessage(Account account, String folder, Message message, int numDone, int numTotal) { }
|
||||
public void remoteSearchAddMessage(String folder, Message message, int numDone, int numTotal) { }
|
||||
|
||||
/**
|
||||
* Called when Remote Search is fully complete
|
||||
*
|
||||
* @param acct
|
||||
* @param folder
|
||||
* @param numResults
|
||||
*/
|
||||
public void remoteSearchFinished(Account acct, String folder, int numResults, List<Message> extraResults) {}
|
||||
public void remoteSearchFinished(String folder, int numResults, int maxResults, List<Message> extraResults) {}
|
||||
|
||||
/**
|
||||
* Called when there was a problem with a remote search operation.
|
||||
*
|
||||
* @param acct
|
||||
* @param folder
|
||||
* @param err
|
||||
*/
|
||||
public void remoteSearchFailed(Account acct, String folder, String err) { }
|
||||
public void remoteSearchFailed(String folder, String err) { }
|
||||
|
||||
/**
|
||||
* General notification messages subclasses can override to be notified that the controller
|
||||
|
@ -89,6 +89,7 @@ import com.fsck.k9.mail.Folder;
|
||||
import com.fsck.k9.mail.Message;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.store.local.LocalFolder;
|
||||
import com.fsck.k9.mail.store.local.LocalMessage;
|
||||
import com.fsck.k9.mail.store.local.LocalStore;
|
||||
import com.fsck.k9.provider.EmailProvider;
|
||||
import com.fsck.k9.provider.EmailProvider.MessageColumns;
|
||||
@ -427,7 +428,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
* Relevant messages for the current context when we have to remember the chosen messages
|
||||
* between user interactions (e.g. selecting a folder for move operation).
|
||||
*/
|
||||
private List<Message> mActiveMessages;
|
||||
private List<LocalMessage> mActiveMessages;
|
||||
|
||||
/* package visibility for faster inner class access */
|
||||
MessageHelper mMessageHelper;
|
||||
@ -1035,7 +1036,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
return null;
|
||||
}
|
||||
|
||||
private Folder getFolderById(Account account, long folderId) {
|
||||
private LocalFolder getFolderById(Account account, long folderId) {
|
||||
try {
|
||||
LocalStore localStore = account.getLocalStore();
|
||||
LocalFolder localFolder = localStore.getFolderById(folderId);
|
||||
@ -1309,11 +1310,11 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
changeSort(sorts[curIndex]);
|
||||
}
|
||||
|
||||
private void onDelete(Message message) {
|
||||
private void onDelete(LocalMessage message) {
|
||||
onDelete(Collections.singletonList(message));
|
||||
}
|
||||
|
||||
private void onDelete(List<Message> messages) {
|
||||
private void onDelete(List<LocalMessage> messages) {
|
||||
if (K9.confirmDelete()) {
|
||||
// remember the message selection for #onCreateDialog(int)
|
||||
mActiveMessages = messages;
|
||||
@ -1323,7 +1324,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
}
|
||||
}
|
||||
|
||||
private void onDeleteConfirmed(List<Message> messages) {
|
||||
private void onDeleteConfirmed(List<LocalMessage> messages) {
|
||||
if (mThreadedList) {
|
||||
mController.deleteThreads(messages);
|
||||
} else {
|
||||
@ -1345,15 +1346,14 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
}
|
||||
|
||||
final String destFolderName = data.getStringExtra(ChooseFolder.EXTRA_NEW_FOLDER);
|
||||
final List<Message> messages = mActiveMessages;
|
||||
final List<LocalMessage> messages = mActiveMessages;
|
||||
|
||||
if (destFolderName != null) {
|
||||
|
||||
mActiveMessages = null; // don't need it any more
|
||||
|
||||
if (messages.size() > 0) {
|
||||
Account account = messages.get(0).getFolder().getAccount();
|
||||
account.setLastSelectedFolderName(destFolderName);
|
||||
messages.get(0).getFolder().setLastSelectedFolderName(destFolderName);
|
||||
}
|
||||
|
||||
switch (requestCode) {
|
||||
@ -1539,7 +1539,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
break;
|
||||
}
|
||||
case R.id.delete: {
|
||||
Message message = getMessageAtPosition(adapterPosition);
|
||||
LocalMessage message = getMessageAtPosition(adapterPosition);
|
||||
onDelete(message);
|
||||
break;
|
||||
}
|
||||
@ -1562,23 +1562,19 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
|
||||
// only if the account supports this
|
||||
case R.id.archive: {
|
||||
Message message = getMessageAtPosition(adapterPosition);
|
||||
onArchive(message);
|
||||
onArchive(getMessageAtPosition(adapterPosition));
|
||||
break;
|
||||
}
|
||||
case R.id.spam: {
|
||||
Message message = getMessageAtPosition(adapterPosition);
|
||||
onSpam(message);
|
||||
onSpam(getMessageAtPosition(adapterPosition));
|
||||
break;
|
||||
}
|
||||
case R.id.move: {
|
||||
Message message = getMessageAtPosition(adapterPosition);
|
||||
onMove(message);
|
||||
onMove(getMessageAtPosition(adapterPosition));
|
||||
break;
|
||||
}
|
||||
case R.id.copy: {
|
||||
Message message = getMessageAtPosition(adapterPosition);
|
||||
onCopy(message);
|
||||
onCopy(getMessageAtPosition(adapterPosition));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1711,7 +1707,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
|
||||
class MessageListActivityListener extends ActivityListener {
|
||||
@Override
|
||||
public void remoteSearchFailed(Account acct, String folder, final String err) {
|
||||
public void remoteSearchFailed(String folder, final String err) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -1725,7 +1721,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remoteSearchStarted(Account acct, String folder) {
|
||||
public void remoteSearchStarted(String folder) {
|
||||
mHandler.progress(true);
|
||||
mHandler.updateFooter(mContext.getString(R.string.remote_search_sending_query));
|
||||
}
|
||||
@ -1736,12 +1732,12 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remoteSearchFinished(Account acct, String folder, int numResults, List<Message> extraResults) {
|
||||
public void remoteSearchFinished(String folder, int numResults, int maxResults, List<Message> extraResults) {
|
||||
mHandler.progress(false);
|
||||
mHandler.remoteSearchFinished();
|
||||
mExtraSearchResults = extraResults;
|
||||
if (extraResults != null && extraResults.size() > 0) {
|
||||
mHandler.updateFooter(String.format(mContext.getString(R.string.load_more_messages_fmt), acct.getRemoteSearchNumResults()));
|
||||
mHandler.updateFooter(String.format(mContext.getString(R.string.load_more_messages_fmt), maxResults));
|
||||
} else {
|
||||
mHandler.updateFooter("");
|
||||
}
|
||||
@ -1750,11 +1746,11 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remoteSearchServerQueryComplete(Account account, String folderName, int numResults) {
|
||||
public void remoteSearchServerQueryComplete(String folderName, int numResults, int maxResults) {
|
||||
mHandler.progress(true);
|
||||
if (account != null && account.getRemoteSearchNumResults() != 0 && numResults > account.getRemoteSearchNumResults()) {
|
||||
if (maxResults != 0 && numResults > maxResults) {
|
||||
mHandler.updateFooter(mContext.getString(R.string.remote_search_downloading_limited,
|
||||
account.getRemoteSearchNumResults(), numResults));
|
||||
maxResults, numResults));
|
||||
} else {
|
||||
mHandler.updateFooter(mContext.getString(R.string.remote_search_downloading, numResults));
|
||||
}
|
||||
@ -2416,7 +2412,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
computeBatchDirection();
|
||||
}
|
||||
|
||||
private void onMove(Message message) {
|
||||
private void onMove(LocalMessage message) {
|
||||
onMove(Collections.singletonList(message));
|
||||
}
|
||||
|
||||
@ -2426,7 +2422,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
* @param messages
|
||||
* Never {@code null}.
|
||||
*/
|
||||
private void onMove(List<Message> messages) {
|
||||
private void onMove(List<LocalMessage> messages) {
|
||||
if (!checkCopyOrMovePossible(messages, FolderOperation.MOVE)) {
|
||||
return;
|
||||
}
|
||||
@ -2440,12 +2436,13 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
folder = null;
|
||||
}
|
||||
|
||||
Account account = messages.get(0).getFolder().getAccount();
|
||||
|
||||
displayFolderChoice(ACTIVITY_CHOOSE_FOLDER_MOVE, account, folder, messages);
|
||||
displayFolderChoice(ACTIVITY_CHOOSE_FOLDER_MOVE, folder,
|
||||
messages.get(0).getFolder().getUuid(), null,
|
||||
messages);
|
||||
}
|
||||
|
||||
private void onCopy(Message message) {
|
||||
private void onCopy(LocalMessage message) {
|
||||
onCopy(Collections.singletonList(message));
|
||||
}
|
||||
|
||||
@ -2455,7 +2452,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
* @param messages
|
||||
* Never {@code null}.
|
||||
*/
|
||||
private void onCopy(List<Message> messages) {
|
||||
private void onCopy(List<LocalMessage> messages) {
|
||||
if (!checkCopyOrMovePossible(messages, FolderOperation.COPY)) {
|
||||
return;
|
||||
}
|
||||
@ -2469,7 +2466,10 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
folder = null;
|
||||
}
|
||||
|
||||
displayFolderChoice(ACTIVITY_CHOOSE_FOLDER_COPY, mAccount, folder, messages);
|
||||
displayFolderChoice(ACTIVITY_CHOOSE_FOLDER_COPY, folder,
|
||||
messages.get(0).getFolder().getUuid(),
|
||||
null,
|
||||
messages);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2486,12 +2486,13 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
*
|
||||
* @see #startActivityForResult(Intent, int)
|
||||
*/
|
||||
private void displayFolderChoice(int requestCode, Account account, Folder folder,
|
||||
List<Message> messages) {
|
||||
private void displayFolderChoice(int requestCode, Folder folder,
|
||||
String accountId, String lastSelectedFolderName,
|
||||
List<LocalMessage> messages) {
|
||||
|
||||
Intent intent = new Intent(getActivity(), ChooseFolder.class);
|
||||
intent.putExtra(ChooseFolder.EXTRA_ACCOUNT, account.getUuid());
|
||||
intent.putExtra(ChooseFolder.EXTRA_SEL_FOLDER, account.getLastSelectedFolderName());
|
||||
intent.putExtra(ChooseFolder.EXTRA_ACCOUNT, accountId);
|
||||
intent.putExtra(ChooseFolder.EXTRA_SEL_FOLDER, lastSelectedFolderName);
|
||||
|
||||
if (folder == null) {
|
||||
intent.putExtra(ChooseFolder.EXTRA_SHOW_CURRENT, "yes");
|
||||
@ -2504,14 +2505,14 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
startActivityForResult(intent, requestCode);
|
||||
}
|
||||
|
||||
private void onArchive(final Message message) {
|
||||
private void onArchive(final LocalMessage message) {
|
||||
onArchive(Collections.singletonList(message));
|
||||
}
|
||||
|
||||
private void onArchive(final List<Message> messages) {
|
||||
Map<Account, List<Message>> messagesByAccount = groupMessagesByAccount(messages);
|
||||
private void onArchive(final List<LocalMessage> messages) {
|
||||
Map<Account, List<LocalMessage>> messagesByAccount = groupMessagesByAccount(messages);
|
||||
|
||||
for (Entry<Account, List<Message>> entry : messagesByAccount.entrySet()) {
|
||||
for (Entry<Account, List<LocalMessage>> entry : messagesByAccount.entrySet()) {
|
||||
Account account = entry.getKey();
|
||||
String archiveFolder = account.getArchiveFolderName();
|
||||
|
||||
@ -2521,14 +2522,14 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
}
|
||||
}
|
||||
|
||||
private Map<Account, List<Message>> groupMessagesByAccount(final List<Message> messages) {
|
||||
Map<Account, List<Message>> messagesByAccount = new HashMap<Account, List<Message>>();
|
||||
for (Message message : messages) {
|
||||
Account account = message.getFolder().getAccount();
|
||||
private Map<Account, List<LocalMessage>> groupMessagesByAccount(final List<LocalMessage> messages) {
|
||||
Map<Account, List<LocalMessage>> messagesByAccount = new HashMap<Account, List<LocalMessage>>();
|
||||
for (LocalMessage message : messages) {
|
||||
Account account = message.getAccount();
|
||||
|
||||
List<Message> msgList = messagesByAccount.get(account);
|
||||
List<LocalMessage> msgList = messagesByAccount.get(account);
|
||||
if (msgList == null) {
|
||||
msgList = new ArrayList<Message>();
|
||||
msgList = new ArrayList<LocalMessage>();
|
||||
messagesByAccount.put(account, msgList);
|
||||
}
|
||||
|
||||
@ -2537,7 +2538,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
return messagesByAccount;
|
||||
}
|
||||
|
||||
private void onSpam(Message message) {
|
||||
private void onSpam(LocalMessage message) {
|
||||
onSpam(Collections.singletonList(message));
|
||||
}
|
||||
|
||||
@ -2547,7 +2548,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
* @param messages
|
||||
* The messages to move to the spam folder. Never {@code null}.
|
||||
*/
|
||||
private void onSpam(List<Message> messages) {
|
||||
private void onSpam(List<LocalMessage> messages) {
|
||||
if (K9.confirmSpam()) {
|
||||
// remember the message selection for #onCreateDialog(int)
|
||||
mActiveMessages = messages;
|
||||
@ -2557,10 +2558,10 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
}
|
||||
}
|
||||
|
||||
private void onSpamConfirmed(List<Message> messages) {
|
||||
Map<Account, List<Message>> messagesByAccount = groupMessagesByAccount(messages);
|
||||
private void onSpamConfirmed(List<LocalMessage> messages) {
|
||||
Map<Account, List<LocalMessage>> messagesByAccount = groupMessagesByAccount(messages);
|
||||
|
||||
for (Entry<Account, List<Message>> entry : messagesByAccount.entrySet()) {
|
||||
for (Entry<Account, List<LocalMessage>> entry : messagesByAccount.entrySet()) {
|
||||
Account account = entry.getKey();
|
||||
String spamFolder = account.getSpamFolderName();
|
||||
|
||||
@ -2584,7 +2585,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
*
|
||||
* @return {@code true}, if operation is possible.
|
||||
*/
|
||||
private boolean checkCopyOrMovePossible(final List<Message> messages,
|
||||
private boolean checkCopyOrMovePossible(final List<LocalMessage> messages,
|
||||
final FolderOperation operation) {
|
||||
|
||||
if (messages.isEmpty()) {
|
||||
@ -2592,11 +2593,11 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
}
|
||||
|
||||
boolean first = true;
|
||||
for (final Message message : messages) {
|
||||
for (final LocalMessage message : messages) {
|
||||
if (first) {
|
||||
first = false;
|
||||
// account check
|
||||
final Account account = message.getFolder().getAccount();
|
||||
final Account account = message.getAccount();
|
||||
if ((operation == FolderOperation.MOVE && !mController.isMoveCapable(account)) ||
|
||||
(operation == FolderOperation.COPY && !mController.isCopyCapable(account))) {
|
||||
return false;
|
||||
@ -2622,7 +2623,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
* @param destination
|
||||
* The name of the destination folder. Never {@code null}.
|
||||
*/
|
||||
private void copy(List<Message> messages, final String destination) {
|
||||
private void copy(List<LocalMessage> messages, final String destination) {
|
||||
copyOrMove(messages, destination, FolderOperation.COPY);
|
||||
}
|
||||
|
||||
@ -2634,7 +2635,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
* @param destination
|
||||
* The name of the destination folder. Never {@code null}.
|
||||
*/
|
||||
private void move(List<Message> messages, final String destination) {
|
||||
private void move(List<LocalMessage> messages, final String destination) {
|
||||
copyOrMove(messages, destination, FolderOperation.MOVE);
|
||||
}
|
||||
|
||||
@ -2650,12 +2651,12 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
* @param operation
|
||||
* Specifies what operation to perform. Never {@code null}.
|
||||
*/
|
||||
private void copyOrMove(List<Message> messages, final String destination,
|
||||
private void copyOrMove(List<LocalMessage> messages, final String destination,
|
||||
final FolderOperation operation) {
|
||||
|
||||
Map<String, List<Message>> folderMap = new HashMap<String, List<Message>>();
|
||||
Map<String, List<LocalMessage>> folderMap = new HashMap<String, List<LocalMessage>>();
|
||||
|
||||
for (Message message : messages) {
|
||||
for (LocalMessage message : messages) {
|
||||
if ((operation == FolderOperation.MOVE && !mController.isMoveCapable(message)) ||
|
||||
(operation == FolderOperation.COPY && !mController.isCopyCapable(message))) {
|
||||
|
||||
@ -2674,19 +2675,19 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
continue;
|
||||
}
|
||||
|
||||
List<Message> outMessages = folderMap.get(folderName);
|
||||
List<LocalMessage> outMessages = folderMap.get(folderName);
|
||||
if (outMessages == null) {
|
||||
outMessages = new ArrayList<Message>();
|
||||
outMessages = new ArrayList<LocalMessage>();
|
||||
folderMap.put(folderName, outMessages);
|
||||
}
|
||||
|
||||
outMessages.add(message);
|
||||
}
|
||||
|
||||
for (Map.Entry<String, List<Message>> entry : folderMap.entrySet()) {
|
||||
for (Map.Entry<String, List<LocalMessage>> entry : folderMap.entrySet()) {
|
||||
String folderName = entry.getKey();
|
||||
List<Message> outMessages = entry.getValue();
|
||||
Account account = outMessages.get(0).getFolder().getAccount();
|
||||
List<LocalMessage> outMessages = entry.getValue();
|
||||
Account account = outMessages.get(0).getAccount();
|
||||
|
||||
if (operation == FolderOperation.MOVE) {
|
||||
if (mThreadedList) {
|
||||
@ -2859,7 +2860,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
*/
|
||||
switch (item.getItemId()) {
|
||||
case R.id.delete: {
|
||||
List<Message> messages = getCheckedMessages();
|
||||
List<LocalMessage> messages = getCheckedMessages();
|
||||
onDelete(messages);
|
||||
mSelectedCount = 0;
|
||||
break;
|
||||
@ -2887,26 +2888,22 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
|
||||
// only if the account supports this
|
||||
case R.id.archive: {
|
||||
List<Message> messages = getCheckedMessages();
|
||||
onArchive(messages);
|
||||
onArchive(getCheckedMessages());
|
||||
mSelectedCount = 0;
|
||||
break;
|
||||
}
|
||||
case R.id.spam: {
|
||||
List<Message> messages = getCheckedMessages();
|
||||
onSpam(messages);
|
||||
onSpam(getCheckedMessages());
|
||||
mSelectedCount = 0;
|
||||
break;
|
||||
}
|
||||
case R.id.move: {
|
||||
List<Message> messages = getCheckedMessages();
|
||||
onMove(messages);
|
||||
onMove(getCheckedMessages());
|
||||
mSelectedCount = 0;
|
||||
break;
|
||||
}
|
||||
case R.id.copy: {
|
||||
List<Message> messages = getCheckedMessages();
|
||||
onCopy(messages);
|
||||
onCopy(getCheckedMessages());
|
||||
mSelectedCount = 0;
|
||||
break;
|
||||
}
|
||||
@ -2987,7 +2984,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
final Folder remoteFolder = mCurrentFolder.folder;
|
||||
remoteFolder.close();
|
||||
// Send a remoteSearchFinished() message for good measure.
|
||||
mListener.remoteSearchFinished(searchAccount, mCurrentFolder.name, 0, null);
|
||||
mListener.remoteSearchFinished(mCurrentFolder.name, 0, searchAccount.getRemoteSearchNumResults(), null);
|
||||
} catch (Exception e) {
|
||||
// Since the user is going back, log and squash any exceptions.
|
||||
Log.e(K9.LOG_TAG, "Could not abort remote search before going back", e);
|
||||
@ -3135,7 +3132,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
changeSort(mSortType);
|
||||
}
|
||||
|
||||
private Message getSelectedMessage() {
|
||||
private LocalMessage getSelectedMessage() {
|
||||
int listViewPosition = mListView.getSelectedItemPosition();
|
||||
int adapterPosition = listViewToAdapterPosition(listViewPosition);
|
||||
|
||||
@ -3158,7 +3155,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
return AdapterView.INVALID_POSITION;
|
||||
}
|
||||
|
||||
private Message getMessageAtPosition(int adapterPosition) {
|
||||
private LocalMessage getMessageAtPosition(int adapterPosition) {
|
||||
if (adapterPosition == AdapterView.INVALID_POSITION) {
|
||||
return null;
|
||||
}
|
||||
@ -3168,7 +3165,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
|
||||
Account account = getAccountFromCursor(cursor);
|
||||
long folderId = cursor.getLong(FOLDER_ID_COLUMN);
|
||||
Folder folder = getFolderById(account, folderId);
|
||||
LocalFolder folder = getFolderById(account, folderId);
|
||||
|
||||
try {
|
||||
return folder.getMessage(uid);
|
||||
@ -3179,14 +3176,14 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<Message> getCheckedMessages() {
|
||||
List<Message> messages = new ArrayList<Message>(mSelected.size());
|
||||
private List<LocalMessage> getCheckedMessages() {
|
||||
List<LocalMessage> messages = new ArrayList<LocalMessage>(mSelected.size());
|
||||
for (int position = 0, end = mAdapter.getCount(); position < end; position++) {
|
||||
Cursor cursor = (Cursor) mAdapter.getItem(position);
|
||||
long uniqueId = cursor.getLong(mUniqueIdColumn);
|
||||
|
||||
if (mSelected.contains(uniqueId)) {
|
||||
Message message = getMessageAtPosition(position);
|
||||
LocalMessage message = getMessageAtPosition(position);
|
||||
if (message != null) {
|
||||
messages.add(message);
|
||||
}
|
||||
@ -3197,7 +3194,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
}
|
||||
|
||||
public void onDelete() {
|
||||
Message message = getSelectedMessage();
|
||||
LocalMessage message = getSelectedMessage();
|
||||
if (message != null) {
|
||||
onDelete(Collections.singletonList(message));
|
||||
}
|
||||
@ -3227,21 +3224,21 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
||||
}
|
||||
|
||||
public void onMove() {
|
||||
Message message = getSelectedMessage();
|
||||
LocalMessage message = getSelectedMessage();
|
||||
if (message != null) {
|
||||
onMove(message);
|
||||
}
|
||||
}
|
||||
|
||||
public void onArchive() {
|
||||
Message message = getSelectedMessage();
|
||||
LocalMessage message = getSelectedMessage();
|
||||
if (message != null) {
|
||||
onArchive(message);
|
||||
}
|
||||
}
|
||||
|
||||
public void onCopy() {
|
||||
Message message = getSelectedMessage();
|
||||
LocalMessage message = getSelectedMessage();
|
||||
if (message != null) {
|
||||
onCopy(message);
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ public class MessageViewFragment extends Fragment implements OnClickListener,
|
||||
private PgpData mPgpData;
|
||||
private Account mAccount;
|
||||
private MessageReference mMessageReference;
|
||||
private Message mMessage;
|
||||
private LocalMessage mMessage;
|
||||
private MessagingController mController;
|
||||
private Listener mListener = new Listener();
|
||||
private MessageViewHandler mHandler = new MessageViewHandler();
|
||||
@ -311,7 +311,7 @@ public class MessageViewFragment extends Fragment implements OnClickListener,
|
||||
// Disable the delete button after it's tapped (to try to prevent
|
||||
// accidental clicks)
|
||||
mFragmentListener.disableDeleteAction();
|
||||
Message messageToDelete = mMessage;
|
||||
LocalMessage messageToDelete = mMessage;
|
||||
mFragmentListener.showNextMessageOrReturn();
|
||||
mController.deleteMessages(Collections.singletonList(messageToDelete), null);
|
||||
}
|
||||
@ -341,7 +341,7 @@ public class MessageViewFragment extends Fragment implements OnClickListener,
|
||||
|
||||
private void refileMessage(String dstFolder) {
|
||||
String srcFolder = mMessageReference.folderName;
|
||||
Message messageToMove = mMessage;
|
||||
LocalMessage messageToMove = mMessage;
|
||||
mFragmentListener.showNextMessageOrReturn();
|
||||
mController.moveMessage(mAccount, srcFolder, messageToMove, dstFolder, null);
|
||||
}
|
||||
@ -576,7 +576,8 @@ public class MessageViewFragment extends Fragment implements OnClickListener,
|
||||
@Override
|
||||
public void loadMessageForViewBodyAvailable(final Account account, String folder,
|
||||
String uid, final Message message) {
|
||||
if (!mMessageReference.uid.equals(uid) ||
|
||||
if (!(message instanceof LocalMessage) ||
|
||||
!mMessageReference.uid.equals(uid) ||
|
||||
!mMessageReference.folderName.equals(folder) ||
|
||||
!mMessageReference.accountUuid.equals(account.getUuid())) {
|
||||
return;
|
||||
@ -586,7 +587,7 @@ public class MessageViewFragment extends Fragment implements OnClickListener,
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
mMessage = message;
|
||||
mMessage = (LocalMessage) message;
|
||||
mMessageView.setMessage(account, (LocalMessage) message, mPgpData,
|
||||
mController, mListener);
|
||||
mFragmentListener.updateMenu();
|
||||
|
@ -14,6 +14,7 @@ import com.fsck.k9.mail.Flag;
|
||||
import com.fsck.k9.mail.Message;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.Message.RecipientType;
|
||||
import com.fsck.k9.mail.store.local.LocalMessage;
|
||||
|
||||
public class MessageHelper {
|
||||
|
||||
@ -32,8 +33,10 @@ public class MessageHelper {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public void populate(final MessageInfoHolder target, final Message message,
|
||||
final FolderInfoHolder folder, final Account account) {
|
||||
public void populate(final MessageInfoHolder target,
|
||||
final LocalMessage message,
|
||||
final FolderInfoHolder folder,
|
||||
Account account) {
|
||||
final Contacts contactHelper = K9.showContactName() ? Contacts.getInstance(mContext) : null;
|
||||
try {
|
||||
target.message = message;
|
||||
@ -68,14 +71,9 @@ public class MessageHelper {
|
||||
target.senderAddress = target.compareCounterparty;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
target.uid = message.getUid();
|
||||
|
||||
target.account = account.getUuid();
|
||||
target.uri = "email://messages/" + account.getAccountNumber() + "/" + message.getFolder().getName() + "/" + message.getUid();
|
||||
|
||||
target.account = message.getFolder().getUuid();
|
||||
target.uri = message.getUri();
|
||||
} catch (MessagingException me) {
|
||||
Log.w(K9.LOG_TAG, "Unable to load message info", me);
|
||||
}
|
||||
|
@ -1,21 +1,17 @@
|
||||
package com.fsck.k9.mail;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import android.util.Log;
|
||||
import com.fsck.k9.Account;
|
||||
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.Preferences;
|
||||
import com.fsck.k9.controller.MessageRetrievalListener;
|
||||
|
||||
|
||||
public abstract class Folder {
|
||||
protected final Account mAccount;
|
||||
|
||||
public abstract class Folder<T extends Message> {
|
||||
private String status = null;
|
||||
private long lastChecked = 0;
|
||||
private long lastPush = 0;
|
||||
@ -32,10 +28,6 @@ public abstract class Folder {
|
||||
HOLDS_FOLDERS, HOLDS_MESSAGES,
|
||||
}
|
||||
|
||||
protected Folder(Account account) {
|
||||
mAccount = account;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces an open of the MailProvider. If the provider is already open this
|
||||
* function returns without doing anything.
|
||||
@ -83,7 +75,7 @@ public abstract class Folder {
|
||||
public abstract int getUnreadMessageCount() throws MessagingException;
|
||||
public abstract int getFlaggedMessageCount() throws MessagingException;
|
||||
|
||||
public abstract Message getMessage(String uid) throws MessagingException;
|
||||
public abstract T getMessage(String uid) throws MessagingException;
|
||||
|
||||
/**
|
||||
* Fetch the shells of messages between a range of UIDs and after a given date.
|
||||
@ -94,7 +86,7 @@ public abstract class Folder {
|
||||
* @return List of messages
|
||||
* @throws MessagingException
|
||||
*/
|
||||
public abstract List<? extends Message> getMessages(int start, int end, Date earliestDate, MessageRetrievalListener listener) throws MessagingException;
|
||||
public abstract List<T> getMessages(int start, int end, Date earliestDate, MessageRetrievalListener<T> listener) throws MessagingException;
|
||||
|
||||
/**
|
||||
* Fetches the given list of messages. The specified listener is notified as
|
||||
@ -104,13 +96,13 @@ public abstract class Folder {
|
||||
* @param listener Listener to notify as we download messages.
|
||||
* @return List of messages
|
||||
*/
|
||||
public abstract List<? extends Message> getMessages(MessageRetrievalListener listener) throws MessagingException;
|
||||
public abstract List<T> getMessages(MessageRetrievalListener<T> listener) throws MessagingException;
|
||||
|
||||
public List<? extends Message> getMessages(MessageRetrievalListener listener, boolean includeDeleted) throws MessagingException {
|
||||
public List<T> getMessages(MessageRetrievalListener<T> listener, boolean includeDeleted) throws MessagingException {
|
||||
return getMessages(listener);
|
||||
}
|
||||
|
||||
public abstract List<? extends Message> getMessages(String[] uids, MessageRetrievalListener listener)
|
||||
public abstract List<T> getMessages(String[] uids, MessageRetrievalListener<T> listener)
|
||||
throws MessagingException;
|
||||
|
||||
public abstract Map<String, String> appendMessages(List<? extends Message> messages) throws MessagingException;
|
||||
@ -149,10 +141,10 @@ public abstract class Folder {
|
||||
* @throws MessagingException
|
||||
*/
|
||||
public abstract void fetch(List<? extends Message> messages, FetchProfile fp,
|
||||
MessageRetrievalListener listener) throws MessagingException;
|
||||
MessageRetrievalListener<T> listener) throws MessagingException;
|
||||
|
||||
public void fetchPart(Message message, Part part,
|
||||
MessageRetrievalListener listener) throws MessagingException {
|
||||
MessageRetrievalListener<T> listener) throws MessagingException {
|
||||
// This is causing trouble. Disabled for now. See issue 1733
|
||||
//throw new RuntimeException("fetchPart() not implemented.");
|
||||
|
||||
@ -241,10 +233,6 @@ public abstract class Folder {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Account getAccount() {
|
||||
return mAccount;
|
||||
}
|
||||
|
||||
public List<Message> search(String queryString, final Set<Flag> requiredFlags, final Set<Flag> forbiddenFlags)
|
||||
throws MessagingException {
|
||||
throw new MessagingException("K-9 does not support searches on this folder type");
|
||||
|
@ -19,8 +19,8 @@ import com.fsck.k9.mail.store.UnavailableStorageException;
|
||||
|
||||
|
||||
public abstract class Message implements Part, CompositeBody {
|
||||
protected MessageReference mReference;
|
||||
|
||||
private MessageReference mReference = null;
|
||||
|
||||
public enum RecipientType {
|
||||
TO, CC, BCC,
|
||||
@ -55,8 +55,7 @@ public abstract class Message implements Part, CompositeBody {
|
||||
}
|
||||
Message other = (Message)o;
|
||||
return (mUid.equals(other.getUid())
|
||||
&& mFolder.getName().equals(other.getFolder().getName())
|
||||
&& mFolder.getAccount().getUuid().equals(other.getFolder().getAccount().getUuid()));
|
||||
&& mFolder.getName().equals(other.getFolder().getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -65,7 +64,6 @@ public abstract class Message implements Part, CompositeBody {
|
||||
|
||||
int result = 1;
|
||||
result = MULTIPLIER * result + mFolder.getName().hashCode();
|
||||
result = MULTIPLIER * result + mFolder.getAccount().getUuid().hashCode();
|
||||
result = MULTIPLIER * result + mUid.hashCode();
|
||||
return result;
|
||||
}
|
||||
@ -75,7 +73,7 @@ public abstract class Message implements Part, CompositeBody {
|
||||
}
|
||||
|
||||
public void setUid(String uid) {
|
||||
mReference = null;
|
||||
this.mReference = null;
|
||||
this.mUid = uid;
|
||||
}
|
||||
|
||||
@ -249,14 +247,13 @@ public abstract class Message implements Part, CompositeBody {
|
||||
public void destroy() throws MessagingException {}
|
||||
|
||||
@Override
|
||||
public abstract void setEncoding(String encoding) throws UnavailableStorageException, MessagingException;
|
||||
public abstract void setEncoding(String encoding) throws MessagingException;
|
||||
|
||||
public abstract void setCharset(String charset) throws MessagingException;
|
||||
|
||||
public MessageReference makeMessageReference() {
|
||||
if (mReference == null) {
|
||||
mReference = new MessageReference();
|
||||
mReference.accountUuid = getFolder().getAccount().getUuid();
|
||||
mReference.folderName = getFolder().getName();
|
||||
mReference.uid = mUid;
|
||||
}
|
||||
|
@ -1,24 +1,7 @@
|
||||
|
||||
package com.fsck.k9.mail;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.mail.store.ImapStore;
|
||||
import com.fsck.k9.mail.store.Pop3Store;
|
||||
import com.fsck.k9.mail.store.StorageManager.StorageProvider;
|
||||
import com.fsck.k9.mail.store.local.LocalStore;
|
||||
import com.fsck.k9.mail.store.UnavailableStorageException;
|
||||
import com.fsck.k9.mail.store.WebDavStore;
|
||||
|
||||
/**
|
||||
* Store is the access point for an email message store. It's location can be
|
||||
@ -29,191 +12,6 @@ import com.fsck.k9.mail.store.WebDavStore;
|
||||
* making as few network connections as possible.
|
||||
*/
|
||||
public abstract class Store {
|
||||
protected static final int SOCKET_CONNECT_TIMEOUT = 30000;
|
||||
protected static final int SOCKET_READ_TIMEOUT = 60000;
|
||||
|
||||
/**
|
||||
* Remote stores indexed by Uri.
|
||||
*/
|
||||
private static Map<String, Store> sStores = new HashMap<String, Store>();
|
||||
|
||||
/**
|
||||
* Local stores indexed by UUID because the Uri may change due to migration to/from SD-card.
|
||||
*/
|
||||
private static ConcurrentMap<String, Store> sLocalStores = new ConcurrentHashMap<String, Store>();
|
||||
|
||||
/**
|
||||
* Lock objects indexed by account UUID.
|
||||
*
|
||||
* @see #getLocalInstance(Account, Application)
|
||||
*/
|
||||
private static ConcurrentMap<String, Object> sAccountLocks = new ConcurrentHashMap<String, Object>();
|
||||
|
||||
/**
|
||||
* Get an instance of a remote mail store.
|
||||
*/
|
||||
public synchronized static Store getRemoteInstance(Account account) throws MessagingException {
|
||||
String uri = account.getStoreUri();
|
||||
|
||||
if (uri.startsWith("local")) {
|
||||
throw new RuntimeException("Asked to get non-local Store object but given LocalStore URI");
|
||||
}
|
||||
|
||||
Store store = sStores.get(uri);
|
||||
if (store == null) {
|
||||
if (uri.startsWith("imap")) {
|
||||
store = new ImapStore(account);
|
||||
} else if (uri.startsWith("pop3")) {
|
||||
store = new Pop3Store(account);
|
||||
} else if (uri.startsWith("webdav")) {
|
||||
store = new WebDavStore(account);
|
||||
}
|
||||
|
||||
if (store != null) {
|
||||
sStores.put(uri, store);
|
||||
}
|
||||
}
|
||||
|
||||
if (store == null) {
|
||||
throw new MessagingException("Unable to locate an applicable Store for " + uri);
|
||||
}
|
||||
|
||||
return store;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an instance of a local mail store.
|
||||
*
|
||||
* @throws UnavailableStorageException
|
||||
* if not {@link StorageProvider#isReady(Context)}
|
||||
*/
|
||||
public static LocalStore getLocalInstance(Account account, Application application)
|
||||
throws MessagingException {
|
||||
|
||||
String accountUuid = account.getUuid();
|
||||
|
||||
// Create new per-account lock object if necessary
|
||||
sAccountLocks.putIfAbsent(accountUuid, new Object());
|
||||
|
||||
// Get the account's lock object
|
||||
Object lock = sAccountLocks.get(accountUuid);
|
||||
|
||||
// Use per-account locks so DatabaseUpgradeService always knows which account database is
|
||||
// currently upgraded.
|
||||
synchronized (lock) {
|
||||
Store store = sLocalStores.get(accountUuid);
|
||||
|
||||
if (store == null) {
|
||||
// Creating a LocalStore instance will create or upgrade the database if
|
||||
// necessary. This could take some time.
|
||||
store = new LocalStore(account, application);
|
||||
|
||||
sLocalStores.put(accountUuid, store);
|
||||
}
|
||||
|
||||
return (LocalStore) store;
|
||||
}
|
||||
}
|
||||
|
||||
public static void removeAccount(Account account) {
|
||||
try {
|
||||
removeRemoteInstance(account);
|
||||
} catch (Exception e) {
|
||||
Log.e(K9.LOG_TAG, "Failed to reset remote store for account " + account.getUuid(), e);
|
||||
}
|
||||
|
||||
try {
|
||||
removeLocalInstance(account);
|
||||
} catch (Exception e) {
|
||||
Log.e(K9.LOG_TAG, "Failed to reset local store for account " + account.getUuid(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Release reference to a local mail store instance.
|
||||
*
|
||||
* @param account
|
||||
* {@link Account} instance that is used to get the local mail store instance.
|
||||
*/
|
||||
private static void removeLocalInstance(Account account) {
|
||||
String accountUuid = account.getUuid();
|
||||
sLocalStores.remove(accountUuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Release reference to a remote mail store instance.
|
||||
*
|
||||
* @param account
|
||||
* {@link Account} instance that is used to get the remote mail store instance.
|
||||
*/
|
||||
private synchronized static void removeRemoteInstance(Account account) {
|
||||
String uri = account.getStoreUri();
|
||||
|
||||
if (uri.startsWith("local")) {
|
||||
throw new RuntimeException("Asked to get non-local Store object but given " +
|
||||
"LocalStore URI");
|
||||
}
|
||||
|
||||
sStores.remove(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the contents of store-specific URIs and puts them into a {@link ServerSettings}
|
||||
* object.
|
||||
*
|
||||
* @param uri
|
||||
* the store-specific URI to decode
|
||||
*
|
||||
* @return A {@link ServerSettings} object holding the settings contained in the URI.
|
||||
*
|
||||
* @see ImapStore#decodeUri(String)
|
||||
* @see Pop3Store#decodeUri(String)
|
||||
* @see WebDavStore#decodeUri(String)
|
||||
*/
|
||||
public static ServerSettings decodeStoreUri(String uri) {
|
||||
if (uri.startsWith("imap")) {
|
||||
return ImapStore.decodeUri(uri);
|
||||
} else if (uri.startsWith("pop3")) {
|
||||
return Pop3Store.decodeUri(uri);
|
||||
} else if (uri.startsWith("webdav")) {
|
||||
return WebDavStore.decodeUri(uri);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Not a valid store URI");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a store URI from the information supplied in the {@link ServerSettings} object.
|
||||
*
|
||||
* @param server
|
||||
* The {@link ServerSettings} object that holds the server settings.
|
||||
*
|
||||
* @return A store URI that holds the same information as the {@code server} parameter.
|
||||
*
|
||||
* @see ImapStore#createUri(ServerSettings)
|
||||
* @see Pop3Store#createUri(ServerSettings)
|
||||
* @see WebDavStore#createUri(ServerSettings)
|
||||
*/
|
||||
public static String createStoreUri(ServerSettings server) {
|
||||
if (ImapStore.STORE_TYPE.equals(server.type)) {
|
||||
return ImapStore.createUri(server);
|
||||
} else if (Pop3Store.STORE_TYPE.equals(server.type)) {
|
||||
return Pop3Store.createUri(server);
|
||||
} else if (WebDavStore.STORE_TYPE.equals(server.type)) {
|
||||
return WebDavStore.createUri(server);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Not a valid store URI");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected final Account mAccount;
|
||||
|
||||
|
||||
protected Store(Account account) {
|
||||
mAccount = account;
|
||||
}
|
||||
|
||||
public abstract Folder getFolder(String name);
|
||||
|
||||
public abstract List <? extends Folder > getPersonalNamespaces(boolean forceListAll) throws MessagingException;
|
||||
@ -244,14 +42,9 @@ public abstract class Store {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void sendMessages(List<? extends Message> messages) throws MessagingException {
|
||||
}
|
||||
public void sendMessages(List<? extends Message> messages) throws MessagingException { }
|
||||
|
||||
public Pusher getPusher(PushReceiver receiver) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Account getAccount() {
|
||||
return mAccount;
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
public class ImapResponseParser {
|
||||
class ImapResponseParser {
|
||||
private static final SimpleDateFormat mDateTimeFormat = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss Z", Locale.US);
|
||||
private static final SimpleDateFormat badDateTimeFormat = new SimpleDateFormat("dd MMM yyyy HH:mm:ss Z", Locale.US);
|
||||
private static final SimpleDateFormat badDateTimeFormat2 = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss Z", Locale.US);
|
||||
|
@ -55,7 +55,6 @@ import android.os.PowerManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.controller.MessageRetrievalListener;
|
||||
@ -78,7 +77,6 @@ import com.fsck.k9.mail.Part;
|
||||
import com.fsck.k9.mail.PushReceiver;
|
||||
import com.fsck.k9.mail.Pusher;
|
||||
import com.fsck.k9.mail.ServerSettings;
|
||||
import com.fsck.k9.mail.Store;
|
||||
import com.fsck.k9.mail.filter.Base64;
|
||||
import com.fsck.k9.mail.filter.EOLConvertingOutputStream;
|
||||
import com.fsck.k9.mail.filter.FixedLengthInputStream;
|
||||
@ -105,7 +103,7 @@ import org.apache.commons.io.IOUtils;
|
||||
* TODO Need a default response handler for things like folder updates
|
||||
* </pre>
|
||||
*/
|
||||
public class ImapStore extends Store {
|
||||
public class ImapStore extends RemoteStore {
|
||||
public static final String STORE_TYPE = "IMAP";
|
||||
|
||||
private static final int IDLE_READ_TIMEOUT_INCREMENT = 5 * 60 * 1000;
|
||||
@ -113,7 +111,7 @@ public class ImapStore extends Store {
|
||||
private static int MAX_DELAY_TIME = 5 * 60 * 1000; // 5 minutes
|
||||
private static int NORMAL_DELAY_TIME = 5000;
|
||||
|
||||
private static int FETCH_WINDOW_SIZE = 100;
|
||||
private static final int FETCH_WINDOW_SIZE = 100;
|
||||
|
||||
private Set<Flag> mPermanentFlagsIndex = EnumSet.noneOf(Flag.class);
|
||||
|
||||
@ -387,7 +385,7 @@ public class ImapStore extends Store {
|
||||
|
||||
@Override
|
||||
public boolean useCompression(final int type) {
|
||||
return mAccount.useCompression(type);
|
||||
return mStoreConfig.useCompression(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -439,12 +437,12 @@ public class ImapStore extends Store {
|
||||
*/
|
||||
private final Map<String, ImapFolder> mFolderCache = new HashMap<String, ImapFolder>();
|
||||
|
||||
public ImapStore(Account account) throws MessagingException {
|
||||
super(account);
|
||||
public ImapStore(StoreConfig storeConfig) throws MessagingException {
|
||||
super(storeConfig);
|
||||
|
||||
ImapStoreSettings settings;
|
||||
try {
|
||||
settings = decodeUri(mAccount.getStoreUri());
|
||||
settings = decodeUri(storeConfig.getStoreUri());
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new MessagingException("Error while decoding store URI", e);
|
||||
}
|
||||
@ -502,7 +500,7 @@ public class ImapStore extends Store {
|
||||
ImapConnection connection = getConnection();
|
||||
try {
|
||||
List <? extends Folder > allFolders = listFolders(connection, false);
|
||||
if (forceListAll || !mAccount.subscribedFoldersOnly()) {
|
||||
if (forceListAll || !mStoreConfig.subscribedFoldersOnly()) {
|
||||
return allFolders;
|
||||
} else {
|
||||
List<Folder> resultFolders = new LinkedList<Folder>();
|
||||
@ -570,9 +568,9 @@ public class ImapStore extends Store {
|
||||
mCombinedPrefix = null;
|
||||
}
|
||||
|
||||
if (folder.equalsIgnoreCase(mAccount.getInboxFolderName())) {
|
||||
if (folder.equalsIgnoreCase(mStoreConfig.getInboxFolderName())) {
|
||||
continue;
|
||||
} else if (folder.equals(mAccount.getOutboxFolderName())) {
|
||||
} else if (folder.equals(mStoreConfig.getOutboxFolderName())) {
|
||||
/*
|
||||
* There is a folder on the server with the same name as our local
|
||||
* outbox. Until we have a good plan to deal with this situation
|
||||
@ -604,7 +602,7 @@ public class ImapStore extends Store {
|
||||
}
|
||||
}
|
||||
}
|
||||
folders.add(getFolder(mAccount.getInboxFolderName()));
|
||||
folders.add(getFolder(mStoreConfig.getInboxFolderName()));
|
||||
return folders;
|
||||
|
||||
}
|
||||
@ -661,17 +659,17 @@ public class ImapStore extends Store {
|
||||
for (int i = 0, count = attributes.size(); i < count; i++) {
|
||||
String attribute = attributes.getString(i);
|
||||
if (attribute.equals("\\Drafts")) {
|
||||
mAccount.setDraftsFolderName(decodedFolderName);
|
||||
mStoreConfig.setDraftsFolderName(decodedFolderName);
|
||||
if (K9.DEBUG) Log.d(K9.LOG_TAG, "Folder auto-configuration detected draft folder: " + decodedFolderName);
|
||||
} else if (attribute.equals("\\Sent")) {
|
||||
mAccount.setSentFolderName(decodedFolderName);
|
||||
mStoreConfig.setSentFolderName(decodedFolderName);
|
||||
if (K9.DEBUG) Log.d(K9.LOG_TAG, "Folder auto-configuration detected sent folder: " + decodedFolderName);
|
||||
} else if (attribute.equals("\\Spam") || attribute.equals("\\Junk")) {
|
||||
//rfc6154 just mentions \Junk
|
||||
mAccount.setSpamFolderName(decodedFolderName);
|
||||
mStoreConfig.setSpamFolderName(decodedFolderName);
|
||||
if (K9.DEBUG) Log.d(K9.LOG_TAG, "Folder auto-configuration detected spam folder: " + decodedFolderName);
|
||||
} else if (attribute.equals("\\Trash")) {
|
||||
mAccount.setTrashFolderName(decodedFolderName);
|
||||
mStoreConfig.setTrashFolderName(decodedFolderName);
|
||||
if (K9.DEBUG) Log.d(K9.LOG_TAG, "Folder auto-configuration detected trash folder: " + decodedFolderName);
|
||||
}
|
||||
}
|
||||
@ -777,7 +775,7 @@ public class ImapStore extends Store {
|
||||
}
|
||||
|
||||
|
||||
class ImapFolder extends Folder {
|
||||
class ImapFolder extends Folder<ImapMessage> {
|
||||
private String mName;
|
||||
protected volatile int mMessageCount = -1;
|
||||
protected volatile long uidNext = -1L;
|
||||
@ -789,14 +787,14 @@ public class ImapStore extends Store {
|
||||
private boolean mInSearch = false;
|
||||
|
||||
public ImapFolder(ImapStore nStore, String name) {
|
||||
super(nStore.getAccount());
|
||||
super();
|
||||
store = nStore;
|
||||
this.mName = name;
|
||||
}
|
||||
|
||||
public String getPrefixedName() throws MessagingException {
|
||||
String prefixedName = "";
|
||||
if (!mAccount.getInboxFolderName().equalsIgnoreCase(mName)) {
|
||||
if (!mStoreConfig.getInboxFolderName().equalsIgnoreCase(mName)) {
|
||||
ImapConnection connection = null;
|
||||
synchronized (this) {
|
||||
if (mConnection == null) {
|
||||
@ -1293,7 +1291,7 @@ public class ImapStore extends Store {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message getMessage(String uid) throws MessagingException {
|
||||
public ImapMessage getMessage(String uid) throws MessagingException {
|
||||
return new ImapMessage(uid, this);
|
||||
}
|
||||
|
||||
@ -1351,7 +1349,7 @@ public class ImapStore extends Store {
|
||||
return search(searcher, listener);
|
||||
}
|
||||
|
||||
private List<Message> search(ImapSearcher searcher, MessageRetrievalListener listener) throws MessagingException {
|
||||
private List<Message> search(ImapSearcher searcher, MessageRetrievalListener<ImapMessage> listener) throws MessagingException {
|
||||
|
||||
checkOpen(); //only need READ access
|
||||
List<Message> messages = new ArrayList<Message>();
|
||||
@ -1432,7 +1430,7 @@ public class ImapStore extends Store {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetch(List<? extends Message> messages, FetchProfile fp, MessageRetrievalListener listener)
|
||||
public void fetch(List<? extends Message> messages, FetchProfile fp, MessageRetrievalListener<ImapMessage> listener)
|
||||
throws MessagingException {
|
||||
if (messages == null || messages.isEmpty()) {
|
||||
return;
|
||||
@ -1468,8 +1466,8 @@ public class ImapStore extends Store {
|
||||
}
|
||||
if (fp.contains(FetchProfile.Item.BODY_SANE)) {
|
||||
// If the user wants to download unlimited-size messages, don't go only for the truncated body
|
||||
if (mAccount.getMaximumAutoDownloadMessageSize() > 0) {
|
||||
fetchFields.add(String.format(Locale.US, "BODY.PEEK[]<0.%d>", mAccount.getMaximumAutoDownloadMessageSize()));
|
||||
if (mStoreConfig.getMaximumAutoDownloadMessageSize() > 0) {
|
||||
fetchFields.add(String.format(Locale.US, "BODY.PEEK[]<0.%d>", mStoreConfig.getMaximumAutoDownloadMessageSize()));
|
||||
} else {
|
||||
fetchFields.add("BODY.PEEK[]");
|
||||
}
|
||||
@ -1544,7 +1542,7 @@ public class ImapStore extends Store {
|
||||
}
|
||||
|
||||
if (listener != null) {
|
||||
listener.messageFinished(message, messageNumber, messageMap.size());
|
||||
listener.messageFinished(imapMessage, messageNumber, messageMap.size());
|
||||
}
|
||||
} else {
|
||||
handleUntaggedResponse(response);
|
||||
@ -1572,7 +1570,7 @@ public class ImapStore extends Store {
|
||||
String partId = parts[0];
|
||||
if ("TEXT".equalsIgnoreCase(partId)) {
|
||||
fetch = String.format(Locale.US, "BODY.PEEK[TEXT]<0.%d>",
|
||||
mAccount.getMaximumAutoDownloadMessageSize());
|
||||
mStoreConfig.getMaximumAutoDownloadMessageSize());
|
||||
} else {
|
||||
fetch = String.format("BODY.PEEK[%s]", partId);
|
||||
}
|
||||
@ -2194,7 +2192,7 @@ public class ImapStore extends Store {
|
||||
}
|
||||
|
||||
protected String getLogId() {
|
||||
String id = getAccount().getDescription() + ":" + getName() + "/" + Thread.currentThread().getName();
|
||||
String id = mStoreConfig.toString() + ":" + getName() + "/" + Thread.currentThread().getName();
|
||||
if (mConnection != null) {
|
||||
id += "/" + mConnection.getLogId();
|
||||
}
|
||||
@ -2213,7 +2211,7 @@ public class ImapStore extends Store {
|
||||
public List<Message> search(final String queryString, final Set<Flag> requiredFlags, final Set<Flag> forbiddenFlags)
|
||||
throws MessagingException {
|
||||
|
||||
if (!mAccount.allowRemoteSearch()) {
|
||||
if (!mStoreConfig.allowRemoteSearch()) {
|
||||
throw new MessagingException("Your settings do not allow remote searching of this account");
|
||||
}
|
||||
|
||||
@ -2287,7 +2285,7 @@ public class ImapStore extends Store {
|
||||
}
|
||||
}
|
||||
final String encodedQry = encodeString(queryString);
|
||||
if (mAccount.isRemoteSearchFullText()) {
|
||||
if (mStoreConfig.isRemoteSearchFullText()) {
|
||||
imapQuery += "TEXT " + encodedQry;
|
||||
} else {
|
||||
imapQuery += "OR SUBJECT " + encodedQry + " FROM " + encodedQry;
|
||||
@ -2424,7 +2422,7 @@ public class ImapStore extends Store {
|
||||
}
|
||||
}
|
||||
|
||||
setReadTimeout(Store.SOCKET_READ_TIMEOUT);
|
||||
setReadTimeout(SOCKET_READ_TIMEOUT);
|
||||
|
||||
mIn = new PeekableInputStream(new BufferedInputStream(mSocket.getInputStream(),
|
||||
1024));
|
||||
@ -2458,7 +2456,7 @@ public class ImapStore extends Store {
|
||||
mSocket = TrustedSocketFactory.createSocket(mSocket,
|
||||
mSettings.getHost(), mSettings.getPort(),
|
||||
mSettings.getClientCertificateAlias());
|
||||
mSocket.setSoTimeout(Store.SOCKET_READ_TIMEOUT);
|
||||
mSocket.setSoTimeout(SOCKET_READ_TIMEOUT);
|
||||
mIn = new PeekableInputStream(new BufferedInputStream(mSocket
|
||||
.getInputStream(), 1024));
|
||||
mParser = new ImapResponseParser(mIn);
|
||||
@ -2953,7 +2951,7 @@ public class ImapStore extends Store {
|
||||
super(store, name);
|
||||
receiver = nReceiver;
|
||||
TracingPowerManager pm = TracingPowerManager.getPowerManager(receiver.getContext());
|
||||
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ImapFolderPusher " + store.getAccount().getDescription() + ":" + getName());
|
||||
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ImapFolderPusher " + mStoreConfig.toString() + ":" + getName());
|
||||
wakeLock.setReferenceCounted(false);
|
||||
|
||||
}
|
||||
@ -2968,7 +2966,7 @@ public class ImapStore extends Store {
|
||||
if (doneSent.compareAndSet(false, true)) {
|
||||
ImapConnection conn = mConnection;
|
||||
if (conn != null) {
|
||||
conn.setReadTimeout(Store.SOCKET_READ_TIMEOUT);
|
||||
conn.setReadTimeout(SOCKET_READ_TIMEOUT);
|
||||
sendContinuation("DONE");
|
||||
}
|
||||
|
||||
@ -3030,7 +3028,7 @@ public class ImapStore extends Store {
|
||||
throw new MessagingException("IMAP server is not IDLE capable:" + conn.toString());
|
||||
}
|
||||
|
||||
if (!stop.get() && mAccount.isPushPollOnConnect() && (conn != oldConnection || needsPoll.getAndSet(false))) {
|
||||
if (!stop.get() && mStoreConfig.isPushPollOnConnect() && (conn != oldConnection || needsPoll.getAndSet(false))) {
|
||||
List<ImapResponse> untaggedResponses = new ArrayList<ImapResponse>(storedUntaggedResponses);
|
||||
storedUntaggedResponses.clear();
|
||||
processUntaggedResponses(untaggedResponses);
|
||||
@ -3061,8 +3059,8 @@ public class ImapStore extends Store {
|
||||
}
|
||||
}
|
||||
|
||||
if (startUid < newUidNext - mAccount.getDisplayCount()) {
|
||||
startUid = newUidNext - mAccount.getDisplayCount();
|
||||
if (startUid < newUidNext - mStoreConfig.getDisplayCount()) {
|
||||
startUid = newUidNext - mStoreConfig.getDisplayCount();
|
||||
}
|
||||
if (startUid < 1) {
|
||||
startUid = 1;
|
||||
@ -3099,7 +3097,7 @@ public class ImapStore extends Store {
|
||||
idling.set(true);
|
||||
doneSent.set(false);
|
||||
|
||||
conn.setReadTimeout((getAccount().getIdleRefreshMinutes() * 60 * 1000) + IDLE_READ_TIMEOUT_INCREMENT);
|
||||
conn.setReadTimeout((mStoreConfig.getIdleRefreshMinutes() * 60 * 1000) + IDLE_READ_TIMEOUT_INCREMENT);
|
||||
untaggedResponses = executeSimpleCommand(COMMAND_IDLE, false, ImapFolderPusher.this);
|
||||
idling.set(false);
|
||||
delayTime.set(NORMAL_DELAY_TIME);
|
||||
@ -3495,7 +3493,7 @@ public class ImapStore extends Store {
|
||||
|
||||
@Override
|
||||
public int getRefreshInterval() {
|
||||
return (getAccount().getIdleRefreshMinutes() * 60 * 1000);
|
||||
return (mStoreConfig.getIdleRefreshMinutes() * 60 * 1000);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -3,7 +3,6 @@ package com.fsck.k9.mail.store;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.controller.MessageRetrievalListener;
|
||||
@ -24,7 +23,6 @@ import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
@ -35,7 +33,7 @@ import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class Pop3Store extends Store {
|
||||
public class Pop3Store extends RemoteStore {
|
||||
public static final String STORE_TYPE = "POP3";
|
||||
|
||||
private static final String STLS_COMMAND = "STLS";
|
||||
@ -209,12 +207,12 @@ public class Pop3Store extends Store {
|
||||
private boolean mTopNotSupported;
|
||||
|
||||
|
||||
public Pop3Store(Account account) throws MessagingException {
|
||||
super(account);
|
||||
public Pop3Store(StoreConfig storeConfig) throws MessagingException {
|
||||
super(storeConfig);
|
||||
|
||||
ServerSettings settings;
|
||||
try {
|
||||
settings = decodeUri(mAccount.getStoreUri());
|
||||
settings = decodeUri(storeConfig.getStoreUri());
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new MessagingException("Error while decoding store URI", e);
|
||||
}
|
||||
@ -243,13 +241,13 @@ public class Pop3Store extends Store {
|
||||
@Override
|
||||
public List <? extends Folder > getPersonalNamespaces(boolean forceListAll) throws MessagingException {
|
||||
List<Folder> folders = new LinkedList<Folder>();
|
||||
folders.add(getFolder(mAccount.getInboxFolderName()));
|
||||
folders.add(getFolder(mStoreConfig.getInboxFolderName()));
|
||||
return folders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkSettings() throws MessagingException {
|
||||
Pop3Folder folder = new Pop3Folder(mAccount.getInboxFolderName());
|
||||
Pop3Folder folder = new Pop3Folder(mStoreConfig.getInboxFolderName());
|
||||
folder.open(Folder.OPEN_MODE_RW);
|
||||
if (!mCapabilities.uidl) {
|
||||
/*
|
||||
@ -272,7 +270,7 @@ public class Pop3Store extends Store {
|
||||
return false;
|
||||
}
|
||||
|
||||
class Pop3Folder extends Folder {
|
||||
class Pop3Folder extends Folder<Pop3Message> {
|
||||
private Socket mSocket;
|
||||
private InputStream mIn;
|
||||
private OutputStream mOut;
|
||||
@ -283,11 +281,11 @@ public class Pop3Store extends Store {
|
||||
private int mMessageCount;
|
||||
|
||||
public Pop3Folder(String name) {
|
||||
super(Pop3Store.this.mAccount);
|
||||
super();
|
||||
this.mName = name;
|
||||
|
||||
if (mName.equalsIgnoreCase(mAccount.getInboxFolderName())) {
|
||||
mName = mAccount.getInboxFolderName();
|
||||
if (mName.equalsIgnoreCase(mStoreConfig.getInboxFolderName())) {
|
||||
mName = mStoreConfig.getInboxFolderName();
|
||||
}
|
||||
}
|
||||
|
||||
@ -297,7 +295,7 @@ public class Pop3Store extends Store {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mName.equalsIgnoreCase(mAccount.getInboxFolderName())) {
|
||||
if (!mName.equalsIgnoreCase(mStoreConfig.getInboxFolderName())) {
|
||||
throw new MessagingException("Folder does not exist");
|
||||
}
|
||||
|
||||
@ -313,7 +311,7 @@ public class Pop3Store extends Store {
|
||||
mIn = new BufferedInputStream(mSocket.getInputStream(), 1024);
|
||||
mOut = new BufferedOutputStream(mSocket.getOutputStream(), 512);
|
||||
|
||||
mSocket.setSoTimeout(Store.SOCKET_READ_TIMEOUT);
|
||||
mSocket.setSoTimeout(SOCKET_READ_TIMEOUT);
|
||||
if (!isOpen()) {
|
||||
throw new MessagingException("Unable to connect socket");
|
||||
}
|
||||
@ -328,7 +326,7 @@ public class Pop3Store extends Store {
|
||||
|
||||
mSocket = TrustedSocketFactory.createSocket(mSocket, mHost, mPort,
|
||||
mClientCertificateAlias);
|
||||
mSocket.setSoTimeout(Store.SOCKET_READ_TIMEOUT);
|
||||
mSocket.setSoTimeout(SOCKET_READ_TIMEOUT);
|
||||
mIn = new BufferedInputStream(mSocket.getInputStream(), 1024);
|
||||
mOut = new BufferedOutputStream(mSocket.getOutputStream(), 512);
|
||||
if (!isOpen()) {
|
||||
@ -541,7 +539,7 @@ public class Pop3Store extends Store {
|
||||
|
||||
@Override
|
||||
public boolean exists() throws MessagingException {
|
||||
return mName.equalsIgnoreCase(mAccount.getInboxFolderName());
|
||||
return mName.equalsIgnoreCase(mStoreConfig.getInboxFolderName());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -559,7 +557,7 @@ public class Pop3Store extends Store {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message getMessage(String uid) throws MessagingException {
|
||||
public Pop3Message getMessage(String uid) throws MessagingException {
|
||||
Pop3Message message = mUidToMsgMap.get(uid);
|
||||
if (message == null) {
|
||||
message = new Pop3Message(uid, this);
|
||||
@ -761,7 +759,7 @@ public class Pop3Store extends Store {
|
||||
* @throws MessagingException
|
||||
*/
|
||||
@Override
|
||||
public void fetch(List<? extends Message> messages, FetchProfile fp, MessageRetrievalListener listener)
|
||||
public void fetch(List<? extends Message> messages, FetchProfile fp, MessageRetrievalListener<Pop3Message> listener)
|
||||
throws MessagingException {
|
||||
if (messages == null || messages.isEmpty()) {
|
||||
return;
|
||||
@ -805,9 +803,9 @@ public class Pop3Store extends Store {
|
||||
* To convert the suggested download size we take the size
|
||||
* divided by the maximum line size (76).
|
||||
*/
|
||||
if (mAccount.getMaximumAutoDownloadMessageSize() > 0) {
|
||||
if (mStoreConfig.getMaximumAutoDownloadMessageSize() > 0) {
|
||||
fetchBody(pop3Message,
|
||||
(mAccount.getMaximumAutoDownloadMessageSize() / 76));
|
||||
(mStoreConfig.getMaximumAutoDownloadMessageSize() / 76));
|
||||
} else {
|
||||
fetchBody(pop3Message, -1);
|
||||
}
|
||||
@ -819,7 +817,7 @@ public class Pop3Store extends Store {
|
||||
pop3Message.setBody(null);
|
||||
}
|
||||
if (listener != null && !(fp.contains(FetchProfile.Item.ENVELOPE) && fp.size() == 1)) {
|
||||
listener.messageFinished(message, i, count);
|
||||
listener.messageFinished(pop3Message, i, count);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
throw new MessagingException("Unable to fetch message", ioe);
|
||||
|
122
src/com/fsck/k9/mail/store/RemoteStore.java
Normal file
122
src/com/fsck/k9/mail/store/RemoteStore.java
Normal file
@ -0,0 +1,122 @@
|
||||
package com.fsck.k9.mail.store;
|
||||
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.ServerSettings;
|
||||
import com.fsck.k9.mail.Store;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class RemoteStore extends Store {
|
||||
protected static final int SOCKET_CONNECT_TIMEOUT = 30000;
|
||||
protected static final int SOCKET_READ_TIMEOUT = 60000;
|
||||
|
||||
protected StoreConfig mStoreConfig;
|
||||
|
||||
/**
|
||||
* Remote stores indexed by Uri.
|
||||
*/
|
||||
private static Map<String, Store> sStores = new HashMap<String, Store>();
|
||||
|
||||
|
||||
public RemoteStore(StoreConfig storeConfig) {
|
||||
mStoreConfig = storeConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an instance of a remote mail store.
|
||||
*/
|
||||
public synchronized static Store getInstance(StoreConfig storeConfig) throws MessagingException {
|
||||
String uri = storeConfig.getStoreUri();
|
||||
|
||||
if (uri.startsWith("local")) {
|
||||
throw new RuntimeException("Asked to get non-local Store object but given LocalStore URI");
|
||||
}
|
||||
|
||||
Store store = sStores.get(uri);
|
||||
if (store == null) {
|
||||
if (uri.startsWith("imap")) {
|
||||
store = new ImapStore(storeConfig);
|
||||
} else if (uri.startsWith("pop3")) {
|
||||
store = new Pop3Store(storeConfig);
|
||||
} else if (uri.startsWith("webdav")) {
|
||||
store = new WebDavStore(storeConfig);
|
||||
}
|
||||
|
||||
if (store != null) {
|
||||
sStores.put(uri, store);
|
||||
}
|
||||
}
|
||||
|
||||
if (store == null) {
|
||||
throw new MessagingException("Unable to locate an applicable Store for " + uri);
|
||||
}
|
||||
|
||||
return store;
|
||||
}
|
||||
|
||||
/**
|
||||
* Release reference to a remote mail store instance.
|
||||
*
|
||||
* @param storeConfig {@link com.fsck.k9.mail.store.StoreConfig} instance that is used to get the remote mail store instance.
|
||||
*/
|
||||
public static void removeInstance(StoreConfig storeConfig) {
|
||||
String uri = storeConfig.getStoreUri();
|
||||
|
||||
if (uri.startsWith("local")) {
|
||||
throw new RuntimeException("Asked to get non-local Store object but given " +
|
||||
"LocalStore URI");
|
||||
}
|
||||
|
||||
sStores.remove(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the contents of store-specific URIs and puts them into a {@link com.fsck.k9.mail.ServerSettings}
|
||||
* object.
|
||||
*
|
||||
* @param uri
|
||||
* the store-specific URI to decode
|
||||
*
|
||||
* @return A {@link com.fsck.k9.mail.ServerSettings} object holding the settings contained in the URI.
|
||||
*
|
||||
* @see com.fsck.k9.mail.store.ImapStore#decodeUri(String)
|
||||
* @see com.fsck.k9.mail.store.Pop3Store#decodeUri(String)
|
||||
* @see com.fsck.k9.mail.store.WebDavStore#decodeUri(String)
|
||||
*/
|
||||
public static ServerSettings decodeStoreUri(String uri) {
|
||||
if (uri.startsWith("imap")) {
|
||||
return ImapStore.decodeUri(uri);
|
||||
} else if (uri.startsWith("pop3")) {
|
||||
return Pop3Store.decodeUri(uri);
|
||||
} else if (uri.startsWith("webdav")) {
|
||||
return WebDavStore.decodeUri(uri);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Not a valid store URI");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a store URI from the information supplied in the {@link com.fsck.k9.mail.ServerSettings} object.
|
||||
*
|
||||
* @param server
|
||||
* The {@link com.fsck.k9.mail.ServerSettings} object that holds the server settings.
|
||||
*
|
||||
* @return A store URI that holds the same information as the {@code server} parameter.
|
||||
*
|
||||
* @see com.fsck.k9.mail.store.ImapStore#createUri(com.fsck.k9.mail.ServerSettings)
|
||||
* @see com.fsck.k9.mail.store.Pop3Store#createUri(com.fsck.k9.mail.ServerSettings)
|
||||
* @see com.fsck.k9.mail.store.WebDavStore#createUri(com.fsck.k9.mail.ServerSettings)
|
||||
*/
|
||||
public static String createStoreUri(ServerSettings server) {
|
||||
if (ImapStore.STORE_TYPE.equals(server.type)) {
|
||||
return ImapStore.createUri(server);
|
||||
} else if (Pop3Store.STORE_TYPE.equals(server.type)) {
|
||||
return Pop3Store.createUri(server);
|
||||
} else if (WebDavStore.STORE_TYPE.equals(server.type)) {
|
||||
return WebDavStore.createUri(server);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Not a valid store URI");
|
||||
}
|
||||
}
|
||||
}
|
32
src/com/fsck/k9/mail/store/StoreConfig.java
Normal file
32
src/com/fsck/k9/mail/store/StoreConfig.java
Normal file
@ -0,0 +1,32 @@
|
||||
package com.fsck.k9.mail.store;
|
||||
|
||||
public interface StoreConfig {
|
||||
String getUuid();
|
||||
String getStoreUri();
|
||||
String getTransportUri();
|
||||
|
||||
boolean subscribedFoldersOnly();
|
||||
boolean useCompression(int type);
|
||||
|
||||
String getInboxFolderName();
|
||||
String getOutboxFolderName();
|
||||
String getDraftsFolderName();
|
||||
|
||||
void setInboxFolderName(String folderName);
|
||||
void setDraftsFolderName(String decodedFolderName);
|
||||
void setTrashFolderName(String decodedFolderName);
|
||||
void setSpamFolderName(String decodedFolderName);
|
||||
void setSentFolderName(String decodedFolderName);
|
||||
void setAutoExpandFolderName(String folderName);
|
||||
|
||||
int getMaximumAutoDownloadMessageSize();
|
||||
|
||||
boolean allowRemoteSearch();
|
||||
boolean isRemoteSearchFullText();
|
||||
|
||||
boolean isPushPollOnConnect();
|
||||
|
||||
int getDisplayCount();
|
||||
|
||||
int getIdleRefreshMinutes();
|
||||
}
|
@ -2,7 +2,6 @@ package com.fsck.k9.mail.store;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.controller.MessageRetrievalListener;
|
||||
|
||||
@ -55,7 +54,7 @@ import java.util.zip.GZIPInputStream;
|
||||
* and email information.
|
||||
* </pre>
|
||||
*/
|
||||
public class WebDavStore extends Store {
|
||||
public class WebDavStore extends RemoteStore {
|
||||
public static final String STORE_TYPE = "WebDAV";
|
||||
|
||||
// Authentication types
|
||||
@ -294,12 +293,12 @@ public class WebDavStore extends Store {
|
||||
private Map<String, WebDavFolder> mFolderList = new HashMap<String, WebDavFolder>();
|
||||
|
||||
|
||||
public WebDavStore(Account account) throws MessagingException {
|
||||
super(account);
|
||||
public WebDavStore(StoreConfig storeConfig) throws MessagingException {
|
||||
super(storeConfig);
|
||||
|
||||
WebDavStoreSettings settings;
|
||||
try {
|
||||
settings = decodeUri(mAccount.getStoreUri());
|
||||
settings = decodeUri(storeConfig.getStoreUri());
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new MessagingException("Error while decoding store URI", e);
|
||||
}
|
||||
@ -380,21 +379,21 @@ public class WebDavStore extends Store {
|
||||
Map<String, String> specialFoldersMap = dataset.getSpecialFolderToUrl();
|
||||
String folderName = getFolderName(specialFoldersMap.get(DAV_MAIL_INBOX_FOLDER));
|
||||
if (folderName != null) {
|
||||
mAccount.setAutoExpandFolderName(folderName);
|
||||
mAccount.setInboxFolderName(folderName);
|
||||
mStoreConfig.setAutoExpandFolderName(folderName);
|
||||
mStoreConfig.setInboxFolderName(folderName);
|
||||
}
|
||||
|
||||
folderName = getFolderName(specialFoldersMap.get(DAV_MAIL_DRAFTS_FOLDER));
|
||||
if (folderName != null)
|
||||
mAccount.setDraftsFolderName(folderName);
|
||||
mStoreConfig.setDraftsFolderName(folderName);
|
||||
|
||||
folderName = getFolderName(specialFoldersMap.get(DAV_MAIL_TRASH_FOLDER));
|
||||
if (folderName != null)
|
||||
mAccount.setTrashFolderName(folderName);
|
||||
mStoreConfig.setTrashFolderName(folderName);
|
||||
|
||||
folderName = getFolderName(specialFoldersMap.get(DAV_MAIL_SPAM_FOLDER));
|
||||
if (folderName != null)
|
||||
mAccount.setSpamFolderName(folderName);
|
||||
mStoreConfig.setSpamFolderName(folderName);
|
||||
|
||||
// K-9 Mail's outbox is a special local folder and different from Exchange/WebDAV's outbox.
|
||||
/*
|
||||
@ -405,7 +404,7 @@ public class WebDavStore extends Store {
|
||||
|
||||
folderName = getFolderName(specialFoldersMap.get(DAV_MAIL_SENT_FOLDER));
|
||||
if (folderName != null)
|
||||
mAccount.setSentFolderName(folderName);
|
||||
mStoreConfig.setSentFolderName(folderName);
|
||||
|
||||
/**
|
||||
* Next we get all the folders (including "special" ones)
|
||||
@ -1196,7 +1195,7 @@ public class WebDavStore extends Store {
|
||||
|
||||
@Override
|
||||
public void sendMessages(List<? extends Message> messages) throws MessagingException {
|
||||
WebDavFolder tmpFolder = (WebDavStore.WebDavFolder) getFolder(mAccount.getDraftsFolderName());
|
||||
WebDavFolder tmpFolder = (WebDavStore.WebDavFolder) getFolder(mStoreConfig.getDraftsFolderName());
|
||||
try {
|
||||
tmpFolder.open(Folder.OPEN_MODE_RW);
|
||||
List<? extends Message> retMessages = tmpFolder.appendWebDavMessages(messages);
|
||||
@ -1216,7 +1215,7 @@ public class WebDavStore extends Store {
|
||||
/**
|
||||
* A WebDav Folder
|
||||
*/
|
||||
class WebDavFolder extends Folder {
|
||||
class WebDavFolder extends Folder<WebDavMessage> {
|
||||
private String mName;
|
||||
private String mFolderUrl;
|
||||
private boolean mIsOpen = false;
|
||||
@ -1229,7 +1228,7 @@ public class WebDavStore extends Store {
|
||||
}
|
||||
|
||||
public WebDavFolder(WebDavStore nStore, String name) {
|
||||
super(nStore.getAccount());
|
||||
super();
|
||||
store = nStore;
|
||||
this.mName = name;
|
||||
|
||||
@ -1397,7 +1396,7 @@ public class WebDavStore extends Store {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message getMessage(String uid) throws MessagingException {
|
||||
public WebDavMessage getMessage(String uid) throws MessagingException {
|
||||
return new WebDavMessage(uid, this);
|
||||
}
|
||||
|
||||
@ -1498,7 +1497,7 @@ public class WebDavStore extends Store {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetch(List<? extends Message> messages, FetchProfile fp, MessageRetrievalListener listener)
|
||||
public void fetch(List<? extends Message> messages, FetchProfile fp, MessageRetrievalListener<WebDavMessage> listener)
|
||||
throws MessagingException {
|
||||
if (messages == null ||
|
||||
messages.isEmpty()) {
|
||||
@ -1519,8 +1518,8 @@ public class WebDavStore extends Store {
|
||||
}
|
||||
|
||||
if (fp.contains(FetchProfile.Item.BODY_SANE)) {
|
||||
if (mAccount.getMaximumAutoDownloadMessageSize() > 0) {
|
||||
fetchMessages(messages, listener, (mAccount.getMaximumAutoDownloadMessageSize() / 76));
|
||||
if (mStoreConfig.getMaximumAutoDownloadMessageSize() > 0) {
|
||||
fetchMessages(messages, listener, (mStoreConfig.getMaximumAutoDownloadMessageSize() / 76));
|
||||
} else {
|
||||
fetchMessages(messages, listener, -1);
|
||||
}
|
||||
@ -1533,7 +1532,7 @@ public class WebDavStore extends Store {
|
||||
/**
|
||||
* Fetches the full messages or up to lines lines and passes them to the message parser.
|
||||
*/
|
||||
private void fetchMessages(List<? extends Message> messages, MessageRetrievalListener listener, int lines)
|
||||
private void fetchMessages(List<? extends Message> messages, MessageRetrievalListener<WebDavMessage> listener, int lines)
|
||||
throws MessagingException {
|
||||
WebDavHttpClient httpclient;
|
||||
httpclient = getHttpClient();
|
||||
@ -1594,8 +1593,8 @@ public class WebDavStore extends Store {
|
||||
if (entity != null) {
|
||||
InputStream istream = null;
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
String tempText = "";
|
||||
String resultText = "";
|
||||
String tempText;
|
||||
String resultText;
|
||||
BufferedReader reader = null;
|
||||
int currentLines = 0;
|
||||
|
||||
|
@ -28,6 +28,7 @@ import android.database.sqlite.SQLiteDatabase;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.Account.MessageFormat;
|
||||
import com.fsck.k9.activity.Search;
|
||||
@ -58,7 +59,7 @@ import com.fsck.k9.mail.store.local.LockableDatabase.DbCallback;
|
||||
import com.fsck.k9.mail.store.local.LockableDatabase.WrappedException;
|
||||
import com.fsck.k9.provider.AttachmentProvider;
|
||||
|
||||
public class LocalFolder extends Folder implements Serializable {
|
||||
public class LocalFolder extends Folder<LocalMessage> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -1973296520918624767L;
|
||||
|
||||
@ -80,22 +81,19 @@ public class LocalFolder extends Folder implements Serializable {
|
||||
private Integer mLastUid = null;
|
||||
|
||||
public LocalFolder(LocalStore localStore, String name) {
|
||||
super(localStore.getAccount());
|
||||
super();
|
||||
this.localStore = localStore;
|
||||
this.mName = name;
|
||||
|
||||
if (this.localStore.getAccount().getInboxFolderName().equals(getName())) {
|
||||
|
||||
if (getAccount().getInboxFolderName().equals(getName())) {
|
||||
mSyncClass = FolderClass.FIRST_CLASS;
|
||||
mPushClass = FolderClass.FIRST_CLASS;
|
||||
mInTopGroup = true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public LocalFolder(LocalStore localStore, long id) {
|
||||
super(localStore.getAccount());
|
||||
super();
|
||||
this.localStore = localStore;
|
||||
this.mFolderId = id;
|
||||
}
|
||||
@ -104,6 +102,25 @@ public class LocalFolder extends Folder implements Serializable {
|
||||
return mFolderId;
|
||||
}
|
||||
|
||||
public String getUuid()
|
||||
{
|
||||
return getAccount().getUuid();
|
||||
}
|
||||
|
||||
public boolean getSignatureUse() {
|
||||
return getAccount().getSignatureUse();
|
||||
}
|
||||
|
||||
public void setLastSelectedFolderName(String destFolderName) {
|
||||
getAccount().setLastSelectedFolderName(destFolderName);
|
||||
}
|
||||
|
||||
public boolean syncRemoteDeletions() {
|
||||
return getAccount().syncRemoteDeletions();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void open(final int mode) throws MessagingException {
|
||||
|
||||
@ -216,7 +233,7 @@ public class LocalFolder extends Folder implements Serializable {
|
||||
|
||||
@Override
|
||||
public boolean create(FolderType type) throws MessagingException {
|
||||
return create(type, mAccount.getDisplayCount());
|
||||
return create(type, getAccount().getDisplayCount());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -517,25 +534,25 @@ public class LocalFolder extends Folder implements Serializable {
|
||||
String id = getPrefId();
|
||||
|
||||
// there can be a lot of folders. For the defaults, let's not save prefs, saving space, except for INBOX
|
||||
if (mDisplayClass == FolderClass.NO_CLASS && !mAccount.getInboxFolderName().equals(getName())) {
|
||||
if (mDisplayClass == FolderClass.NO_CLASS && !getAccount().getInboxFolderName().equals(getName())) {
|
||||
editor.remove(id + ".displayMode");
|
||||
} else {
|
||||
editor.putString(id + ".displayMode", mDisplayClass.name());
|
||||
}
|
||||
|
||||
if (mSyncClass == FolderClass.INHERITED && !mAccount.getInboxFolderName().equals(getName())) {
|
||||
if (mSyncClass == FolderClass.INHERITED && !getAccount().getInboxFolderName().equals(getName())) {
|
||||
editor.remove(id + ".syncMode");
|
||||
} else {
|
||||
editor.putString(id + ".syncMode", mSyncClass.name());
|
||||
}
|
||||
|
||||
if (mNotifyClass == FolderClass.INHERITED && !mAccount.getInboxFolderName().equals(getName())) {
|
||||
if (mNotifyClass == FolderClass.INHERITED && !getAccount().getInboxFolderName().equals(getName())) {
|
||||
editor.remove(id + ".notifyMode");
|
||||
} else {
|
||||
editor.putString(id + ".notifyMode", mNotifyClass.name());
|
||||
}
|
||||
|
||||
if (mPushClass == FolderClass.SECOND_CLASS && !mAccount.getInboxFolderName().equals(getName())) {
|
||||
if (mPushClass == FolderClass.SECOND_CLASS && !getAccount().getInboxFolderName().equals(getName())) {
|
||||
editor.remove(id + ".pushMode");
|
||||
} else {
|
||||
editor.putString(id + ".pushMode", mPushClass.name());
|
||||
@ -597,7 +614,7 @@ public class LocalFolder extends Folder implements Serializable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetch(final List<? extends Message> messages, final FetchProfile fp, final MessageRetrievalListener listener)
|
||||
public void fetch(final List<? extends Message> messages, final FetchProfile fp, final MessageRetrievalListener<LocalMessage> listener)
|
||||
throws MessagingException {
|
||||
try {
|
||||
this.localStore.database.execute(false, new DbCallback<Void>() {
|
||||
@ -614,7 +631,7 @@ public class LocalFolder extends Folder implements Serializable {
|
||||
try {
|
||||
cursor = db.rawQuery("SELECT html_content, text_content, mime_type FROM messages "
|
||||
+ "WHERE id = ?",
|
||||
new String[] { Long.toString(localMessage.mId) });
|
||||
new String[] { Long.toString(localMessage.getId()) });
|
||||
cursor.moveToNext();
|
||||
String htmlContent = cursor.getString(0);
|
||||
String textContent = cursor.getString(1);
|
||||
@ -629,7 +646,7 @@ public class LocalFolder extends Folder implements Serializable {
|
||||
mp.addBodyPart(bp);
|
||||
}
|
||||
|
||||
if (mAccount.getMessageFormat() != MessageFormat.TEXT) {
|
||||
if (getAccount().getMessageFormat() != MessageFormat.TEXT) {
|
||||
if (htmlContent != null) {
|
||||
TextBody body = new TextBody(htmlContent);
|
||||
MimeBodyPart bp = new MimeBodyPart(body, "text/html");
|
||||
@ -700,7 +717,7 @@ public class LocalFolder extends Folder implements Serializable {
|
||||
"content_disposition"
|
||||
},
|
||||
"message_id = ?",
|
||||
new String[] { Long.toString(localMessage.mId) },
|
||||
new String[] { Long.toString(localMessage.getId()) },
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
@ -1439,12 +1456,12 @@ public class LocalFolder extends Folder implements Serializable {
|
||||
message.isSet(Flag.FLAGGED) ? 1 : 0,
|
||||
message.isSet(Flag.ANSWERED) ? 1 : 0,
|
||||
message.isSet(Flag.FORWARDED) ? 1 : 0,
|
||||
message.mId
|
||||
message.getId()
|
||||
});
|
||||
|
||||
for (int i = 0, count = attachments.size(); i < count; i++) {
|
||||
Part attachment = attachments.get(i);
|
||||
saveAttachment(message.mId, attachment, false);
|
||||
saveAttachment(message.getId(), attachment, false);
|
||||
}
|
||||
saveHeaders(message.getId(), message);
|
||||
} catch (Exception e) {
|
||||
@ -1637,7 +1654,7 @@ public class LocalFolder extends Folder implements Serializable {
|
||||
File attachmentFile = new File(attachmentDirectory, Long.toString(attachmentId));
|
||||
tempAttachmentFile.renameTo(attachmentFile);
|
||||
contentUri = AttachmentProvider.getAttachmentUri(
|
||||
mAccount,
|
||||
getAccount(),
|
||||
attachmentId);
|
||||
if (MimeUtil.isMessage(attachment.getMimeType())) {
|
||||
attachment.setBody(new LocalAttachmentMessageBody(
|
||||
@ -1712,7 +1729,7 @@ public class LocalFolder extends Folder implements Serializable {
|
||||
@Override
|
||||
public Void doDbWork(final SQLiteDatabase db) throws WrappedException, UnavailableStorageException {
|
||||
db.update("messages", cv, "id = ?", new String[]
|
||||
{ Long.toString(message.mId) });
|
||||
{ Long.toString(message.getId()) });
|
||||
return null;
|
||||
}
|
||||
});
|
||||
@ -1829,7 +1846,7 @@ public class LocalFolder extends Folder implements Serializable {
|
||||
setPushState(null);
|
||||
setLastPush(0);
|
||||
setLastChecked(0);
|
||||
setVisibleLimit(mAccount.getDisplayCount());
|
||||
setVisibleLimit(getAccount().getDisplayCount());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1878,7 +1895,7 @@ public class LocalFolder extends Folder implements Serializable {
|
||||
public Void doDbWork(final SQLiteDatabase db) throws WrappedException, UnavailableStorageException {
|
||||
Cursor attachmentsCursor = null;
|
||||
try {
|
||||
String accountUuid = mAccount.getUuid();
|
||||
String accountUuid = getUuid();
|
||||
Context context = LocalFolder.this.localStore.mApplication;
|
||||
|
||||
// Get attachment IDs
|
||||
@ -2039,7 +2056,7 @@ public class LocalFolder extends Folder implements Serializable {
|
||||
|
||||
// Append the first message ID from the "In-Reply-To" header line
|
||||
String[] inReplyToArray = message.getHeader("In-Reply-To");
|
||||
String inReplyTo = null;
|
||||
String inReplyTo;
|
||||
if (inReplyToArray != null && inReplyToArray.length > 0) {
|
||||
inReplyTo = Utility.extractMessageId(inReplyToArray[0]);
|
||||
if (inReplyTo != null) {
|
||||
@ -2194,4 +2211,8 @@ public class LocalFolder extends Folder implements Serializable {
|
||||
throw(MessagingException) e.getCause();
|
||||
}
|
||||
}
|
||||
|
||||
private Account getAccount() {
|
||||
return localStore.getAccount();
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,9 @@ import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.util.Log;
|
||||
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.activity.MessageReference;
|
||||
import com.fsck.k9.mail.Address;
|
||||
import com.fsck.k9.mail.Flag;
|
||||
import com.fsck.k9.mail.Folder;
|
||||
@ -28,7 +30,7 @@ public class LocalMessage extends MimeMessage {
|
||||
|
||||
private final LocalStore localStore;
|
||||
|
||||
long mId;
|
||||
private long mId;
|
||||
private int mAttachmentCount;
|
||||
private String mSubject;
|
||||
|
||||
@ -557,4 +559,43 @@ public class LocalMessage extends MimeMessage {
|
||||
public long getRootId() {
|
||||
return mRootId;
|
||||
}
|
||||
|
||||
public Account getAccount() {
|
||||
return localStore.getAccount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageReference makeMessageReference() {
|
||||
if (mReference == null) {
|
||||
mReference = super.makeMessageReference();
|
||||
mReference.accountUuid = getFolder().getUuid();
|
||||
}
|
||||
return mReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalFolder getFolder() {
|
||||
return (LocalFolder) super.getFolder();
|
||||
}
|
||||
|
||||
public String getUri() {
|
||||
return "email://messages/" + getAccount().getAccountNumber() + "/" + getFolder().getName() + "/" + getUid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
|
||||
LocalMessage that = (LocalMessage) o;
|
||||
return !(getUid() != null ? !getUid().equals(that.getUid()) : that.getUid() != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + (getUid() != null ? getUid().hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
@ -10,6 +10,8 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.ContentResolver;
|
||||
@ -32,6 +34,8 @@ import com.fsck.k9.mail.Flag;
|
||||
import com.fsck.k9.mail.Folder;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.Store;
|
||||
import com.fsck.k9.mail.store.RemoteStore;
|
||||
import com.fsck.k9.mail.store.StoreConfig;
|
||||
import com.fsck.k9.mail.store.local.LockableDatabase.DbCallback;
|
||||
import com.fsck.k9.mail.store.local.LockableDatabase.WrappedException;
|
||||
import com.fsck.k9.mail.store.StorageManager;
|
||||
@ -56,6 +60,18 @@ public class LocalStore extends Store implements Serializable {
|
||||
static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||
static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
|
||||
|
||||
/**
|
||||
* Lock objects indexed by account UUID.
|
||||
*
|
||||
* @see #getInstance(Account, Application)
|
||||
*/
|
||||
private static ConcurrentMap<String, Object> sAccountLocks = new ConcurrentHashMap<String, Object>();
|
||||
|
||||
/**
|
||||
* Local stores indexed by UUID because the Uri may change due to migration to/from SD-card.
|
||||
*/
|
||||
private static ConcurrentMap<String, Store> sLocalStores = new ConcurrentHashMap<String, Store>();
|
||||
|
||||
/*
|
||||
* a String containing the columns getMessages expects to work with
|
||||
* in the correct order.
|
||||
@ -138,6 +154,7 @@ public class LocalStore extends Store implements Serializable {
|
||||
LockableDatabase database;
|
||||
|
||||
private ContentResolver mContentResolver;
|
||||
private final Account mAccount;
|
||||
|
||||
/**
|
||||
* local://localhost/path/to/database/uuid.db
|
||||
@ -147,7 +164,7 @@ public class LocalStore extends Store implements Serializable {
|
||||
* @throws UnavailableStorageException if not {@link StorageProvider#isReady(Context)}
|
||||
*/
|
||||
public LocalStore(final Account account, final Application application) throws MessagingException {
|
||||
super(account);
|
||||
mAccount = account;
|
||||
database = new LockableDatabase(application, account.getUuid(), new StoreSchemaDefinition(this));
|
||||
|
||||
mApplication = application;
|
||||
@ -158,10 +175,73 @@ public class LocalStore extends Store implements Serializable {
|
||||
database.open();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an instance of a local mail store.
|
||||
*
|
||||
* @throws UnavailableStorageException
|
||||
* if not {@link StorageProvider#isReady(Context)}
|
||||
*/
|
||||
public static LocalStore getInstance(Account account, Application application)
|
||||
throws MessagingException {
|
||||
|
||||
String accountUuid = account.getUuid();
|
||||
|
||||
// Create new per-account lock object if necessary
|
||||
sAccountLocks.putIfAbsent(accountUuid, new Object());
|
||||
|
||||
// Get the account's lock object
|
||||
Object lock = sAccountLocks.get(accountUuid);
|
||||
|
||||
// Use per-account locks so DatabaseUpgradeService always knows which account database is
|
||||
// currently upgraded.
|
||||
synchronized (lock) {
|
||||
Store store = sLocalStores.get(accountUuid);
|
||||
|
||||
if (store == null) {
|
||||
// Creating a LocalStore instance will create or upgrade the database if
|
||||
// necessary. This could take some time.
|
||||
store = new LocalStore(account, application);
|
||||
|
||||
sLocalStores.put(accountUuid, store);
|
||||
}
|
||||
|
||||
return (LocalStore) store;
|
||||
}
|
||||
}
|
||||
|
||||
public static void removeAccount(StoreConfig storeConfig) {
|
||||
try {
|
||||
RemoteStore.removeInstance(storeConfig);
|
||||
} catch (Exception e) {
|
||||
Log.e(K9.LOG_TAG, "Failed to reset remote store for account " + storeConfig.getUuid(), e);
|
||||
}
|
||||
|
||||
try {
|
||||
removeInstance(storeConfig);
|
||||
} catch (Exception e) {
|
||||
Log.e(K9.LOG_TAG, "Failed to reset local store for account " + storeConfig.getUuid(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Release reference to a local mail store instance.
|
||||
*
|
||||
* @param account
|
||||
* {@link Account} instance that is used to get the local mail store instance.
|
||||
*/
|
||||
private static void removeInstance(StoreConfig account) {
|
||||
String accountUuid = account.getUuid();
|
||||
sLocalStores.remove(accountUuid);
|
||||
}
|
||||
|
||||
public void switchLocalStorage(final String newStorageProviderId) throws MessagingException {
|
||||
database.switchProvider(newStorageProviderId);
|
||||
}
|
||||
|
||||
protected Account getAccount() {
|
||||
return mAccount;
|
||||
}
|
||||
|
||||
protected SharedPreferences getPreferences() {
|
||||
return Preferences.getPreferences(mApplication).getPreferences();
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import com.fsck.k9.mail.filter.LineWrapOutputStream;
|
||||
import com.fsck.k9.mail.filter.PeekableInputStream;
|
||||
import com.fsck.k9.mail.filter.SmtpDataStuffing;
|
||||
import com.fsck.k9.mail.internet.MimeUtility;
|
||||
import com.fsck.k9.mail.store.StoreConfig;
|
||||
import com.fsck.k9.mail.store.local.LocalMessage;
|
||||
import com.fsck.k9.net.ssl.TrustedSocketFactory;
|
||||
|
||||
@ -183,7 +184,7 @@ public class SmtpTransport extends Transport {
|
||||
private boolean m8bitEncodingAllowed;
|
||||
private int mLargestAcceptableMessage;
|
||||
|
||||
public SmtpTransport(Account account) throws MessagingException {
|
||||
public SmtpTransport(StoreConfig account) throws MessagingException {
|
||||
ServerSettings settings;
|
||||
try {
|
||||
settings = decodeUri(account.getTransportUri());
|
||||
|
@ -3,12 +3,12 @@ package com.fsck.k9.mail.transport;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.mail.Message;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.ServerSettings;
|
||||
import com.fsck.k9.mail.Transport;
|
||||
import com.fsck.k9.mail.store.StoreConfig;
|
||||
import com.fsck.k9.mail.store.WebDavStore;
|
||||
|
||||
import java.util.Collections;
|
||||
@ -43,12 +43,8 @@ public class WebDavTransport extends Transport {
|
||||
|
||||
private WebDavStore store;
|
||||
|
||||
public WebDavTransport(Account account) throws MessagingException {
|
||||
if (account.getRemoteStore() instanceof WebDavStore) {
|
||||
store = (WebDavStore) account.getRemoteStore();
|
||||
} else {
|
||||
store = new WebDavStore(account);
|
||||
}
|
||||
public WebDavTransport(StoreConfig configInterface) throws MessagingException {
|
||||
store = new WebDavStore(configInterface);
|
||||
|
||||
if (K9.DEBUG)
|
||||
Log.d(K9.LOG_TAG, ">>> New WebDavTransport creation complete");
|
||||
|
@ -25,9 +25,9 @@ import android.util.Xml;
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.Preferences;
|
||||
import com.fsck.k9.mail.Store;
|
||||
import com.fsck.k9.mail.ServerSettings;
|
||||
import com.fsck.k9.mail.Transport;
|
||||
import com.fsck.k9.mail.store.RemoteStore;
|
||||
import com.fsck.k9.preferences.Settings.InvalidSettingValueException;
|
||||
import com.fsck.k9.preferences.Settings.SettingsDescription;
|
||||
|
||||
@ -223,7 +223,7 @@ public class SettingsExporter {
|
||||
|
||||
|
||||
// Write incoming server settings
|
||||
ServerSettings incoming = Store.decodeStoreUri(account.getStoreUri());
|
||||
ServerSettings incoming = RemoteStore.decodeStoreUri(account.getStoreUri());
|
||||
serializer.startTag(null, INCOMING_SERVER_ELEMENT);
|
||||
serializer.attribute(null, TYPE_ATTRIBUTE, incoming.type);
|
||||
|
||||
|
@ -26,8 +26,8 @@ import com.fsck.k9.helper.Utility;
|
||||
import com.fsck.k9.mail.AuthType;
|
||||
import com.fsck.k9.mail.ConnectionSecurity;
|
||||
import com.fsck.k9.mail.ServerSettings;
|
||||
import com.fsck.k9.mail.Store;
|
||||
import com.fsck.k9.mail.Transport;
|
||||
import com.fsck.k9.mail.store.RemoteStore;
|
||||
import com.fsck.k9.mail.store.WebDavStore;
|
||||
import com.fsck.k9.preferences.Settings.InvalidSettingValueException;
|
||||
|
||||
@ -376,7 +376,7 @@ public class SettingsImporter {
|
||||
|
||||
// Write incoming server settings (storeUri)
|
||||
ServerSettings incoming = new ImportedServerSettings(account.incoming);
|
||||
String storeUri = Store.createStoreUri(incoming);
|
||||
String storeUri = RemoteStore.createStoreUri(incoming);
|
||||
putString(editor, accountKeyPrefix + Account.STORE_URI_KEY, Utility.base64Encode(storeUri));
|
||||
|
||||
// Mark account as disabled if the AuthType isn't EXTERNAL and the
|
||||
|
@ -215,7 +215,7 @@ public class AttachmentProvider extends ContentProvider {
|
||||
final AttachmentInfo attachmentInfo;
|
||||
try {
|
||||
final Account account = Preferences.getPreferences(getContext()).getAccount(dbName);
|
||||
attachmentInfo = LocalStore.getLocalInstance(account, K9.app).getAttachmentInfo(id);
|
||||
attachmentInfo = LocalStore.getInstance(account, K9.app).getAttachmentInfo(id);
|
||||
} catch (MessagingException e) {
|
||||
Log.e(K9.LOG_TAG, "Unable to retrieve attachment info from local store for ID: " + id, e);
|
||||
return null;
|
||||
@ -269,7 +269,7 @@ public class AttachmentProvider extends ContentProvider {
|
||||
final Account account = Preferences.getPreferences(getContext()).getAccount(dbName);
|
||||
|
||||
try {
|
||||
final LocalStore localStore = LocalStore.getLocalInstance(account, K9.app);
|
||||
final LocalStore localStore = LocalStore.getInstance(account, K9.app);
|
||||
|
||||
AttachmentInfo attachmentInfo = localStore.getAttachmentInfo(id);
|
||||
if (FORMAT_VIEW.equals(format) && mimeType != null) {
|
||||
|
@ -32,6 +32,7 @@ import com.fsck.k9.mail.Flag;
|
||||
import com.fsck.k9.mail.Folder;
|
||||
import com.fsck.k9.mail.Message;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.store.local.LocalFolder;
|
||||
import com.fsck.k9.mail.store.local.LocalMessage;
|
||||
import com.fsck.k9.mail.store.local.LocalStore;
|
||||
import com.fsck.k9.search.SearchAccount;
|
||||
@ -200,9 +201,9 @@ public class MessageProvider extends ContentProvider {
|
||||
public static class DeleteUriExtractor implements FieldExtractor<MessageInfoHolder, String> {
|
||||
@Override
|
||||
public String getField(final MessageInfoHolder source) {
|
||||
final Message message = source.message;
|
||||
final LocalMessage message = source.message;
|
||||
return CONTENT_URI + "/delete_message/"
|
||||
+ message.getFolder().getAccount().getAccountNumber() + "/"
|
||||
+ message.getAccount().getAccountNumber() + "/"
|
||||
+ message.getFolder().getName() + "/" + message.getUid();
|
||||
}
|
||||
}
|
||||
@ -221,21 +222,21 @@ public class MessageProvider extends ContentProvider {
|
||||
public static class AccountExtractor implements FieldExtractor<MessageInfoHolder, String> {
|
||||
@Override
|
||||
public String getField(final MessageInfoHolder source) {
|
||||
return source.message.getFolder().getAccount().getDescription();
|
||||
return source.message.getAccount().getDescription();
|
||||
}
|
||||
}
|
||||
|
||||
public static class AccountColorExtractor implements FieldExtractor<MessageInfoHolder, Integer> {
|
||||
@Override
|
||||
public Integer getField(final MessageInfoHolder source) {
|
||||
return source.message.getFolder().getAccount().getChipColor();
|
||||
return source.message.getAccount().getChipColor();
|
||||
}
|
||||
}
|
||||
|
||||
public static class AccountNumberExtractor implements FieldExtractor<MessageInfoHolder, Integer> {
|
||||
@Override
|
||||
public Integer getField(final MessageInfoHolder source) {
|
||||
return source.message.getFolder().getAccount().getAccountNumber();
|
||||
return source.message.getAccount().getAccountNumber();
|
||||
}
|
||||
}
|
||||
|
||||
@ -910,18 +911,18 @@ public class MessageProvider extends ContentProvider {
|
||||
|
||||
@Override
|
||||
public void listLocalMessagesAddMessages(final Account account,
|
||||
final String folderName, final List<Message> messages) {
|
||||
final String folderName, final List<LocalMessage> messages) {
|
||||
// cache fields into local variables for faster access on JVM without JIT
|
||||
final MessageHelper helper = mMessageHelper;
|
||||
final List<MessageInfoHolder> holders = mHolders;
|
||||
|
||||
final Context context = getContext();
|
||||
|
||||
for (final Message message : messages) {
|
||||
for (final LocalMessage message : messages) {
|
||||
final MessageInfoHolder messageInfoHolder = new MessageInfoHolder();
|
||||
final Folder messageFolder = message.getFolder();
|
||||
final Account messageAccount = messageFolder.getAccount();
|
||||
|
||||
final Account messageAccount = messageInfoHolder.message.getAccount();
|
||||
helper.populate(messageInfoHolder, message, new FolderInfoHolder(context,
|
||||
messageFolder, messageAccount), messageAccount);
|
||||
|
||||
@ -1038,9 +1039,9 @@ public class MessageProvider extends ContentProvider {
|
||||
}
|
||||
|
||||
// get localstore parameter
|
||||
Message msg = null;
|
||||
LocalMessage msg = null;
|
||||
try {
|
||||
Folder lf = LocalStore.getLocalInstance(myAccount, K9.app).getFolder(folderName);
|
||||
LocalFolder lf = LocalStore.getInstance(myAccount, K9.app).getFolder(folderName);
|
||||
int msgCount = lf.getMessageCount();
|
||||
if (K9.DEBUG) {
|
||||
Log.d(K9.LOG_TAG, "folder msg count = " + msgCount);
|
||||
|
@ -10,9 +10,9 @@ import com.fsck.k9.Preferences;
|
||||
import com.fsck.k9.activity.MessageCompose;
|
||||
import com.fsck.k9.activity.MessageReference;
|
||||
import com.fsck.k9.controller.MessagingController;
|
||||
import com.fsck.k9.helper.Utility;
|
||||
import com.fsck.k9.mail.Flag;
|
||||
import com.fsck.k9.mail.Message;
|
||||
import com.fsck.k9.mail.store.local.LocalMessage;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
@ -89,10 +89,10 @@ public class NotificationActionService extends CoreService {
|
||||
|
||||
List<MessageReference> refs =
|
||||
intent.getParcelableArrayListExtra(EXTRA_MESSAGE_LIST);
|
||||
List<Message> messages = new ArrayList<Message>();
|
||||
List<LocalMessage> messages = new ArrayList<LocalMessage>();
|
||||
|
||||
for (MessageReference ref : refs) {
|
||||
Message m = ref.restoreToLocalMessage(this);
|
||||
LocalMessage m = ref.restoreToLocalMessage(this);
|
||||
if (m != null) {
|
||||
messages.add(m);
|
||||
}
|
||||
@ -106,7 +106,7 @@ public class NotificationActionService extends CoreService {
|
||||
MessageReference ref = (MessageReference) intent.getParcelableExtra(EXTRA_MESSAGE);
|
||||
Message message = ref.restoreToLocalMessage(this);
|
||||
if (message != null) {
|
||||
Intent i = MessageCompose.getActionReplyIntent(this, account, message, false, null);
|
||||
Intent i = MessageCompose.getActionReplyIntent(this, message, false, null);
|
||||
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(i);
|
||||
} else {
|
||||
|
@ -6,14 +6,13 @@ import java.util.Map;
|
||||
import com.fsck.k9.mail.AuthType;
|
||||
import com.fsck.k9.mail.ConnectionSecurity;
|
||||
import com.fsck.k9.mail.ServerSettings;
|
||||
import com.fsck.k9.mail.Store;
|
||||
import com.fsck.k9.mail.store.ImapStore;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class ImapStoreUriTest extends TestCase {
|
||||
public void testDecodeStoreUriImapAllExtras() {
|
||||
String uri = "imap://PLAIN:user:pass@server:143/0%7CcustomPathPrefix";
|
||||
ServerSettings settings = Store.decodeStoreUri(uri);
|
||||
ServerSettings settings = RemoteStore.decodeStoreUri(uri);
|
||||
|
||||
assertEquals(AuthType.PLAIN, settings.authenticationType);
|
||||
assertEquals("user", settings.username);
|
||||
@ -26,7 +25,7 @@ public class ImapStoreUriTest extends TestCase {
|
||||
|
||||
public void testDecodeStoreUriImapNoExtras() {
|
||||
String uri = "imap://PLAIN:user:pass@server:143/";
|
||||
ServerSettings settings = Store.decodeStoreUri(uri);
|
||||
ServerSettings settings = RemoteStore.decodeStoreUri(uri);
|
||||
|
||||
assertEquals(AuthType.PLAIN, settings.authenticationType);
|
||||
assertEquals("user", settings.username);
|
||||
@ -38,7 +37,7 @@ public class ImapStoreUriTest extends TestCase {
|
||||
|
||||
public void testDecodeStoreUriImapPrefixOnly() {
|
||||
String uri = "imap://PLAIN:user:pass@server:143/customPathPrefix";
|
||||
ServerSettings settings = Store.decodeStoreUri(uri);
|
||||
ServerSettings settings = RemoteStore.decodeStoreUri(uri);
|
||||
|
||||
assertEquals(AuthType.PLAIN, settings.authenticationType);
|
||||
assertEquals("user", settings.username);
|
||||
@ -51,7 +50,7 @@ public class ImapStoreUriTest extends TestCase {
|
||||
|
||||
public void testDecodeStoreUriImapEmptyPrefix() {
|
||||
String uri = "imap://PLAIN:user:pass@server:143/0%7C";
|
||||
ServerSettings settings = Store.decodeStoreUri(uri);
|
||||
ServerSettings settings = RemoteStore.decodeStoreUri(uri);
|
||||
|
||||
assertEquals(AuthType.PLAIN, settings.authenticationType);
|
||||
assertEquals("user", settings.username);
|
||||
@ -64,7 +63,7 @@ public class ImapStoreUriTest extends TestCase {
|
||||
|
||||
public void testDecodeStoreUriImapAutodetectAndPrefix() {
|
||||
String uri = "imap://PLAIN:user:pass@server:143/1%7CcustomPathPrefix";
|
||||
ServerSettings settings = Store.decodeStoreUri(uri);
|
||||
ServerSettings settings = RemoteStore.decodeStoreUri(uri);
|
||||
|
||||
assertEquals(AuthType.PLAIN, settings.authenticationType);
|
||||
assertEquals("user", settings.username);
|
||||
@ -84,7 +83,7 @@ public class ImapStoreUriTest extends TestCase {
|
||||
ServerSettings settings = new ServerSettings(ImapStore.STORE_TYPE, "server", 143,
|
||||
ConnectionSecurity.NONE, AuthType.PLAIN, "user", "pass", null, extra);
|
||||
|
||||
String uri = Store.createStoreUri(settings);
|
||||
String uri = RemoteStore.createStoreUri(settings);
|
||||
|
||||
assertEquals("imap://PLAIN:user:pass@server:143/0%7CcustomPathPrefix", uri);
|
||||
}
|
||||
@ -97,7 +96,7 @@ public class ImapStoreUriTest extends TestCase {
|
||||
ServerSettings settings = new ServerSettings(ImapStore.STORE_TYPE, "server", 143,
|
||||
ConnectionSecurity.NONE, AuthType.PLAIN, "user", "pass", null, extra);
|
||||
|
||||
String uri = Store.createStoreUri(settings);
|
||||
String uri = RemoteStore.createStoreUri(settings);
|
||||
|
||||
assertEquals("imap://PLAIN:user:pass@server:143/0%7C", uri);
|
||||
}
|
||||
@ -106,7 +105,7 @@ public class ImapStoreUriTest extends TestCase {
|
||||
ServerSettings settings = new ServerSettings(ImapStore.STORE_TYPE, "server", 143,
|
||||
ConnectionSecurity.NONE, AuthType.PLAIN, "user", "pass", null);
|
||||
|
||||
String uri = Store.createStoreUri(settings);
|
||||
String uri = RemoteStore.createStoreUri(settings);
|
||||
|
||||
assertEquals("imap://PLAIN:user:pass@server:143/1%7C", uri);
|
||||
}
|
||||
@ -118,7 +117,7 @@ public class ImapStoreUriTest extends TestCase {
|
||||
ServerSettings settings = new ServerSettings(ImapStore.STORE_TYPE, "server", 143,
|
||||
ConnectionSecurity.NONE, AuthType.PLAIN, "user", "pass", null, extra);
|
||||
|
||||
String uri = Store.createStoreUri(settings);
|
||||
String uri = RemoteStore.createStoreUri(settings);
|
||||
|
||||
assertEquals("imap://PLAIN:user:pass@server:143/1%7C", uri);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user