package com.fsck.k9.notification;
import android.app.Notification;
import android.support.v4.app.NotificationManagerCompat;
import android.util.SparseArray;
import com.fsck.k9.Account;
import com.fsck.k9.K9;
import com.fsck.k9.K9.NotificationHideSubject;
import com.fsck.k9.activity.MessageReference;
import com.fsck.k9.mailstore.LocalMessage;
/**
* Handle notifications for new messages.
* <p>
* We call the notification shown on the device <em>summary notification</em>, even when there's only one new message.
* Notifications on an Android Wear device are displayed as a stack of cards and that's why we call them <em>stacked
* notifications</em>. We have to keep track of stacked notifications individually and recreate/update the summary
* notification when one or more of the stacked notifications are added/removed.<br>
* {@link NotificationData} keeps track of all data required to (re)create the actual system notifications.
* </p>
*/
class NewMailNotifications {
private final NotificationController controller;
private final NotificationContentCreator contentCreator;
private final DeviceNotifications deviceNotifications;
private final WearNotifications wearNotifications;
private final SparseArray<NotificationData> notifications = new SparseArray<NotificationData>();
private final Object lock = new Object();
NewMailNotifications(NotificationController controller, NotificationContentCreator contentCreator,
DeviceNotifications deviceNotifications, WearNotifications wearNotifications) {
this.controller = controller;
this.deviceNotifications = deviceNotifications;
this.wearNotifications = wearNotifications;
this.contentCreator = contentCreator;
}
public static NewMailNotifications newInstance(NotificationController controller,
NotificationActionCreator actionCreator) {
NotificationContentCreator contentCreator = new NotificationContentCreator(controller.getContext());
WearNotifications wearNotifications = new WearNotifications(controller, actionCreator);
DeviceNotifications deviceNotifications = DeviceNotifications.newInstance(
controller, actionCreator, wearNotifications);
return new NewMailNotifications(controller, contentCreator, deviceNotifications, wearNotifications);
}
public void addNewMailNotification(Account account, LocalMessage message, int unreadMessageCount) {
NotificationContent content = contentCreator.createFromMessage(account, message);
synchronized (lock) {
NotificationData notificationData = getOrCreateNotificationData(account, unreadMessageCount);
AddNotificationResult result = notificationData.addNotificationContent(content);
if (result.shouldCancelNotification()) {
int notificationId = result.getNotificationId();
cancelNotification(notificationId);
}
createStackedNotification(account, result.getNotificationHolder());
createSummaryNotification(account, notificationData, false);
}
}
public void removeNewMailNotification(Account account, MessageReference messageReference) {
synchronized (lock) {
NotificationData notificationData = getNotificationData(account);
if (notificationData == null) {
return;
}
RemoveNotificationResult result = notificationData.removeNotificationForMessage(messageReference);
if (result.isUnknownNotification()) {
return;
}
cancelNotification(result.getNotificationId());
if (result.shouldCreateNotification()) {
createStackedNotification(account, result.getNotificationHolder());
}
updateSummaryNotification(account, notificationData);
}
}
public void clearNewMailNotifications(Account account) {
NotificationData notificationData;
synchronized (lock) {
notificationData = removeNotificationData(account);
}
if (notificationData == null) {
return;
}
for (int notificationId : notificationData.getActiveNotificationIds()) {
cancelNotification(notificationId);
}
int notificationId = NotificationIds.getNewMailSummaryNotificationId(account);
cancelNotification(notificationId);
}
private NotificationData getOrCreateNotificationData(Account account, int unreadMessageCount) {
NotificationData notificationData = getNotificationData(account);
if (notificationData != null) {
return notificationData;
}
int accountNumber = account.getAccountNumber();
NotificationData newNotificationHolder = createNotificationData(account, unreadMessageCount);
notifications.put(accountNumber, newNotificationHolder);
return newNotificationHolder;
}
private NotificationData getNotificationData(Account account) {
int accountNumber = account.getAccountNumber();
return notifications.get(accountNumber);
}
private NotificationData removeNotificationData(Account account) {
int accountNumber = account.getAccountNumber();
NotificationData notificationData = notifications.get(accountNumber);
notifications.remove(accountNumber);
return notificationData;
}
NotificationData createNotificationData(Account account, int unreadMessageCount) {
NotificationData notificationData = new NotificationData(account);
notificationData.setUnreadMessageCount(unreadMessageCount);
return notificationData;
}
private void cancelNotification(int notificationId) {
getNotificationManager().cancel(notificationId);
}
private void updateSummaryNotification(Account account, NotificationData notificationData) {
if (notificationData.getNewMessagesCount() == 0) {
clearNewMailNotifications(account);
} else {
createSummaryNotification(account, notificationData, true);
}
}
private void createSummaryNotification(Account account, NotificationData notificationData, boolean silent) {
Notification notification = deviceNotifications.buildSummaryNotification(account, notificationData, silent);
int notificationId = NotificationIds.getNewMailSummaryNotificationId(account);
getNotificationManager().notify(notificationId, notification);
}
private void createStackedNotification(Account account, NotificationHolder holder) {
if (isPrivacyModeEnabled()) {
return;
}
Notification notification = wearNotifications.buildStackedNotification(account, holder);
int notificationId = holder.notificationId;
getNotificationManager().notify(notificationId, notification);
}
private boolean isPrivacyModeEnabled() {
return K9.getNotificationHideSubject() != NotificationHideSubject.NEVER;
}
private NotificationManagerCompat getNotificationManager() {
return controller.getNotificationManager();
}
}