package com.fsck.k9.notification;
import java.util.List;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.TaskStackBuilder;
import android.text.TextUtils;
import com.fsck.k9.Account;
import com.fsck.k9.K9;
import com.fsck.k9.Preferences;
import com.fsck.k9.activity.Accounts;
import com.fsck.k9.activity.FolderList;
import com.fsck.k9.activity.MessageList;
import com.fsck.k9.activity.MessageReference;
import com.fsck.k9.activity.NotificationDeleteConfirmation;
import com.fsck.k9.activity.compose.MessageActions;
import com.fsck.k9.search.LocalSearch;
/**
* This class contains methods to create the {@link PendingIntent}s for the actions of new mail notifications.
* <p/>
* <strong>Note:</strong>
* We need to take special care to ensure the {@code PendingIntent}s are unique as defined in the documentation of
* {@link PendingIntent}. Otherwise selecting a notification action might perform the action on the wrong message.
* <p/>
* We use the notification ID as {@code requestCode} argument to ensure each notification/action pair gets a unique
* {@code PendingIntent}.
*/
class NotificationActionCreator {
private final Context context;
public NotificationActionCreator(Context context) {
this.context = context;
}
public PendingIntent createViewMessagePendingIntent(MessageReference messageReference, int notificationId) {
TaskStackBuilder stack = buildMessageViewBackStack(messageReference);
return stack.getPendingIntent(notificationId, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
}
public PendingIntent createViewFolderPendingIntent(Account account, String folderName, int notificationId) {
TaskStackBuilder stack = buildMessageListBackStack(account, folderName);
return stack.getPendingIntent(notificationId, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
}
public PendingIntent createViewMessagesPendingIntent(Account account, List<MessageReference> messageReferences,
int notificationId) {
TaskStackBuilder stack;
if (account.goToUnreadMessageSearch()) {
stack = buildUnreadBackStack(account);
} else {
String folderName = getFolderNameOfAllMessages(messageReferences);
if (folderName == null) {
stack = buildFolderListBackStack(account);
} else {
stack = buildMessageListBackStack(account, folderName);
}
}
return stack.getPendingIntent(notificationId, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
}
public PendingIntent createViewFolderListPendingIntent(Account account, int notificationId) {
TaskStackBuilder stack = buildFolderListBackStack(account);
return stack.getPendingIntent(notificationId, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
}
public PendingIntent createDismissAllMessagesPendingIntent(Account account, int notificationId) {
Intent intent = NotificationActionService.createDismissAllMessagesIntent(context, account);
return PendingIntent.getService(context, notificationId, intent,
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
}
public PendingIntent createDismissMessagePendingIntent(Context context, MessageReference messageReference,
int notificationId) {
Intent intent = NotificationActionService.createDismissMessageIntent(context, messageReference);
return PendingIntent.getService(context, notificationId, intent,
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
}
public PendingIntent createReplyPendingIntent(MessageReference messageReference, int notificationId) {
Intent intent = MessageActions.getActionReplyIntent(context, messageReference);
return PendingIntent.getActivity(context, notificationId, intent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT);
}
public PendingIntent createMarkMessageAsReadPendingIntent(MessageReference messageReference, int notificationId) {
Intent intent = NotificationActionService.createMarkMessageAsReadIntent(context, messageReference);
return PendingIntent.getService(context, notificationId, intent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT);
}
public PendingIntent createMarkAllAsReadPendingIntent(Account account, List<MessageReference> messageReferences,
int notificationId) {
return getMarkAsReadPendingIntent(account, messageReferences, notificationId, context,
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
}
public PendingIntent getMarkAllAsReadPendingIntent(Account account, List<MessageReference> messageReferences,
int notificationId) {
return getMarkAsReadPendingIntent(account, messageReferences, notificationId, context,
PendingIntent.FLAG_NO_CREATE);
}
private PendingIntent getMarkAsReadPendingIntent(Account account, List<MessageReference> messageReferences,
int notificationId, Context context, int flags) {
String accountUuid = account.getUuid();
Intent intent = NotificationActionService.createMarkAllAsReadIntent(context, accountUuid, messageReferences);
return PendingIntent.getService(context, notificationId, intent, flags);
}
public PendingIntent createDeleteMessagePendingIntent(MessageReference messageReference, int notificationId) {
if (K9.confirmDeleteFromNotification()) {
return createDeleteConfirmationPendingIntent(messageReference, notificationId);
} else {
return createDeleteServicePendingIntent(messageReference, notificationId);
}
}
private PendingIntent createDeleteServicePendingIntent(MessageReference messageReference, int notificationId) {
Intent intent = NotificationActionService.createDeleteMessageIntent(context, messageReference);
return PendingIntent.getService(context, notificationId, intent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT);
}
private PendingIntent createDeleteConfirmationPendingIntent(MessageReference messageReference, int notificationId) {
Intent intent = NotificationDeleteConfirmation.getIntent(context, messageReference);
return PendingIntent.getActivity(context, notificationId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
public PendingIntent createDeleteAllPendingIntent(Account account, List<MessageReference> messageReferences,
int notificationId) {
if (K9.confirmDeleteFromNotification()) {
return getDeleteAllConfirmationPendingIntent(messageReferences, notificationId,
PendingIntent.FLAG_CANCEL_CURRENT);
} else {
return getDeleteAllServicePendingIntent(account, messageReferences, notificationId,
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
}
}
public PendingIntent getDeleteAllPendingIntent(Account account, List<MessageReference> messageReferences,
int notificationId) {
if (K9.confirmDeleteFromNotification()) {
return getDeleteAllConfirmationPendingIntent(messageReferences, notificationId,
PendingIntent.FLAG_NO_CREATE);
} else {
return getDeleteAllServicePendingIntent(account, messageReferences, notificationId,
PendingIntent.FLAG_NO_CREATE);
}
}
private PendingIntent getDeleteAllConfirmationPendingIntent(List<MessageReference> messageReferences,
int notificationId, int flags) {
Intent intent = NotificationDeleteConfirmation.getIntent(context, messageReferences);
return PendingIntent.getActivity(context, notificationId, intent, flags);
}
private PendingIntent getDeleteAllServicePendingIntent(Account account, List<MessageReference> messageReferences,
int notificationId, int flags) {
String accountUuid = account.getUuid();
Intent intent = NotificationActionService.createDeleteAllMessagesIntent(
context, accountUuid, messageReferences);
return PendingIntent.getService(context, notificationId, intent, flags);
}
public PendingIntent createArchiveMessagePendingIntent(MessageReference messageReference, int notificationId) {
Intent intent = NotificationActionService.createArchiveMessageIntent(context, messageReference);
return PendingIntent.getService(context, notificationId, intent,
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
}
public PendingIntent createArchiveAllPendingIntent(Account account, List<MessageReference> messageReferences,
int notificationId) {
Intent intent = NotificationActionService.createArchiveAllIntent(context, account, messageReferences);
return PendingIntent.getService(context, notificationId, intent,
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
}
public PendingIntent createMarkMessageAsSpamPendingIntent(MessageReference messageReference, int notificationId) {
Intent intent = NotificationActionService.createMarkMessageAsSpamIntent(context, messageReference);
return PendingIntent.getService(context, notificationId, intent,
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
}
private TaskStackBuilder buildAccountsBackStack() {
TaskStackBuilder stack = TaskStackBuilder.create(context);
if (!skipAccountsInBackStack()) {
Intent intent = new Intent(context, Accounts.class);
intent.putExtra(Accounts.EXTRA_STARTUP, false);
stack.addNextIntent(intent);
}
return stack;
}
private TaskStackBuilder buildFolderListBackStack(Account account) {
TaskStackBuilder stack = buildAccountsBackStack();
Intent intent = FolderList.actionHandleAccountIntent(context, account, false);
stack.addNextIntent(intent);
return stack;
}
private TaskStackBuilder buildUnreadBackStack(final Account account) {
TaskStackBuilder stack = buildAccountsBackStack();
LocalSearch search = Accounts.createUnreadSearch(context, account);
Intent intent = MessageList.intentDisplaySearch(context, search, true, false, false);
stack.addNextIntent(intent);
return stack;
}
private TaskStackBuilder buildMessageListBackStack(Account account, String folderName) {
TaskStackBuilder stack = skipFolderListInBackStack(account, folderName) ?
buildAccountsBackStack() : buildFolderListBackStack(account);
LocalSearch search = new LocalSearch(folderName);
search.addAllowedFolder(folderName);
search.addAccountUuid(account.getUuid());
Intent intent = MessageList.intentDisplaySearch(context, search, false, true, true);
stack.addNextIntent(intent);
return stack;
}
private TaskStackBuilder buildMessageViewBackStack(MessageReference message) {
Account account = Preferences.getPreferences(context).getAccount(message.getAccountUuid());
String folderName = message.getFolderName();
TaskStackBuilder stack = buildMessageListBackStack(account, folderName);
Intent intent = MessageList.actionDisplayMessageIntent(context, message);
stack.addNextIntent(intent);
return stack;
}
private String getFolderNameOfAllMessages(List<MessageReference> messageReferences) {
MessageReference firstMessage = messageReferences.get(0);
String folderName = firstMessage.getFolderName();
for (MessageReference messageReference : messageReferences) {
if (!TextUtils.equals(folderName, messageReference.getFolderName())) {
return null;
}
}
return folderName;
}
private boolean skipFolderListInBackStack(Account account, String folderName) {
return folderName != null && folderName.equals(account.getAutoExpandFolderName());
}
private boolean skipAccountsInBackStack() {
return Preferences.getPreferences(context).getAccounts().size() == 1;
}
}