Loading app/core/src/main/java/com/fsck/k9/notification/BaseNotificationDataCreator.kt 0 → 100644 +52 −0 Original line number Diff line number Diff line package com.fsck.k9.notification import com.fsck.k9.Account import com.fsck.k9.K9 import com.fsck.k9.K9.LockScreenNotificationVisibility private const val MAX_NUMBER_OF_SENDERS_IN_LOCK_SCREEN_NOTIFICATION = 5 internal class BaseNotificationDataCreator { fun createBaseNotificationData(notificationData: NotificationData): BaseNotificationData { val account = notificationData.account return BaseNotificationData( account = account, groupKey = NotificationGroupKeys.getGroupKey(account), accountName = getAccountName(account), color = account.chipColor, newMessagesCount = notificationData.newMessagesCount, lockScreenNotificationData = createLockScreenNotificationData(notificationData), appearance = createNotificationAppearance(account) ) } private fun getAccountName(account: Account): String { val accountDescription = account.description?.takeIf { it.isNotEmpty() } return accountDescription ?: account.email } private fun createLockScreenNotificationData(data: NotificationData): LockScreenNotificationData { return when (K9.lockScreenNotificationVisibility) { LockScreenNotificationVisibility.NOTHING -> LockScreenNotificationData.None LockScreenNotificationVisibility.APP_NAME -> LockScreenNotificationData.AppName LockScreenNotificationVisibility.EVERYTHING -> LockScreenNotificationData.Public LockScreenNotificationVisibility.MESSAGE_COUNT -> LockScreenNotificationData.MessageCount LockScreenNotificationVisibility.SENDERS -> LockScreenNotificationData.SenderNames(getSenderNames(data)) } } private fun getSenderNames(data: NotificationData): String { return data.getContentForSummaryNotification().asSequence() .map { it.sender } .distinct() .take(MAX_NUMBER_OF_SENDERS_IN_LOCK_SCREEN_NOTIFICATION) .joinToString() } private fun createNotificationAppearance(account: Account): NotificationAppearance { return with(account.notificationSetting) { NotificationAppearance(ringtone = ringtone, vibrationPattern = vibration, ledColor = ledColor) } } } app/core/src/main/java/com/fsck/k9/notification/CoreKoinModule.kt +21 −7 Original line number Diff line number Diff line Loading @@ -56,31 +56,45 @@ val coreNotificationModule = module { } single { NewMailNotificationController( notificationHelper = get(), contentCreator = get(), notificationManager = get(), newMailNotificationManager = get(), summaryNotificationCreator = get(), singleMessageNotificationCreator = get() ) } single { NotificationContentCreator(context = get(), resourceProvider = get()) } single { NewMailNotificationManager( contentCreator = get(), baseNotificationDataCreator = get(), singleMessageNotificationDataCreator = get(), summaryNotificationDataCreator = get(), clock = get() ) } factory { NotificationContentCreator(context = get(), resourceProvider = get()) } factory { BaseNotificationDataCreator() } factory { SingleMessageNotificationDataCreator() } factory { SummaryNotificationDataCreator(singleMessageNotificationDataCreator = get()) } factory { SingleMessageNotificationCreator( notificationHelper = get(), actionCreator = get(), resourceProvider = get(), lockScreenNotificationCreator = get() lockScreenNotificationCreator = get(), notificationManager = get() ) } single { factory { SummaryNotificationCreator( notificationHelper = get(), actionCreator = get(), lockScreenNotificationCreator = get(), singleMessageNotificationCreator = get(), resourceProvider = get() resourceProvider = get(), notificationManager = get() ) } single { LockScreenNotificationCreator(notificationHelper = get(), resourceProvider = get()) } factory { LockScreenNotificationCreator(notificationHelper = get(), resourceProvider = get()) } single { PushNotificationManager( context = get(), Loading app/core/src/main/java/com/fsck/k9/notification/LockScreenNotificationCreator.kt +25 −48 Original line number Diff line number Diff line Loading @@ -2,82 +2,59 @@ package com.fsck.k9.notification import android.app.Notification import androidx.core.app.NotificationCompat import com.fsck.k9.K9 import com.fsck.k9.K9.LockScreenNotificationVisibility internal class LockScreenNotificationCreator( private val notificationHelper: NotificationHelper, private val resourceProvider: NotificationResourceProvider ) { fun configureLockScreenNotification(builder: NotificationCompat.Builder, notificationData: NotificationData) { when (K9.lockScreenNotificationVisibility) { LockScreenNotificationVisibility.NOTHING -> { fun configureLockScreenNotification( builder: NotificationCompat.Builder, baseNotificationData: BaseNotificationData ) { when (baseNotificationData.lockScreenNotificationData) { LockScreenNotificationData.None -> { builder.setVisibility(NotificationCompat.VISIBILITY_SECRET) } LockScreenNotificationVisibility.APP_NAME -> { LockScreenNotificationData.AppName -> { builder.setVisibility(NotificationCompat.VISIBILITY_PRIVATE) } LockScreenNotificationVisibility.EVERYTHING -> { LockScreenNotificationData.Public -> { builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC) } LockScreenNotificationVisibility.SENDERS -> { val publicNotification = createPublicNotificationWithSenderList(notificationData) is LockScreenNotificationData.SenderNames -> { val publicNotification = createPublicNotificationWithSenderList(baseNotificationData) builder.setPublicVersion(publicNotification) } LockScreenNotificationVisibility.MESSAGE_COUNT -> { val publicNotification = createPublicNotificationWithNewMessagesCount(notificationData) LockScreenNotificationData.MessageCount -> { val publicNotification = createPublicNotificationWithNewMessagesCount(baseNotificationData) builder.setPublicVersion(publicNotification) } } } private fun createPublicNotificationWithSenderList(notificationData: NotificationData): Notification { val builder = createPublicNotification(notificationData) val newMessages = notificationData.newMessagesCount if (newMessages == 1) { val holder = notificationData.holderForLatestNotification builder.setContentText(holder.content.sender) } else { val contents = notificationData.getContentForSummaryNotification() val senderList = createCommaSeparatedListOfSenders(contents) builder.setContentText(senderList) private fun createPublicNotificationWithSenderList(baseNotificationData: BaseNotificationData): Notification { val notificationData = baseNotificationData.lockScreenNotificationData as LockScreenNotificationData.SenderNames return createPublicNotification(baseNotificationData) .setContentText(notificationData.senderNames) .build() } return builder.build() } private fun createPublicNotificationWithNewMessagesCount(notificationData: NotificationData): Notification { val builder = createPublicNotification(notificationData) val account = notificationData.account val accountName = notificationHelper.getAccountName(account) builder.setContentText(accountName) return builder.build() private fun createPublicNotificationWithNewMessagesCount(baseNotificationData: BaseNotificationData): Notification { return createPublicNotification(baseNotificationData) .setContentText(baseNotificationData.accountName) .build() } private fun createPublicNotification(notificationData: NotificationData): NotificationCompat.Builder { val account = notificationData.account val newMessagesCount = notificationData.newMessagesCount private fun createPublicNotification(baseNotificationData: BaseNotificationData): NotificationCompat.Builder { val account = baseNotificationData.account val newMessagesCount = baseNotificationData.newMessagesCount val title = resourceProvider.newMessagesTitle(newMessagesCount) return notificationHelper.createNotificationBuilder(account, NotificationChannelManager.ChannelType.MESSAGES) .setSmallIcon(resourceProvider.iconNewMail) .setColor(account.chipColor) .setColor(baseNotificationData.color) .setNumber(newMessagesCount) .setContentTitle(title) .setCategory(NotificationCompat.CATEGORY_EMAIL) } fun createCommaSeparatedListOfSenders(contents: List<NotificationContent>): String { return contents.asSequence() .map { it.sender } .distinct() .take(MAX_NUMBER_OF_SENDERS_IN_LOCK_SCREEN_NOTIFICATION) .joinToString() } companion object { const val MAX_NUMBER_OF_SENDERS_IN_LOCK_SCREEN_NOTIFICATION = 5 } } app/core/src/main/java/com/fsck/k9/notification/NewMailNotificationController.kt +30 −105 Original line number Diff line number Diff line package com.fsck.k9.notification import android.util.SparseArray import androidx.core.app.NotificationManagerCompat import com.fsck.k9.Account import com.fsck.k9.controller.MessageReference Loading @@ -9,135 +8,61 @@ import com.fsck.k9.mailstore.LocalMessage /** * Handle notifications for new messages. */ internal open class NewMailNotificationController( private val notificationHelper: NotificationHelper, private val contentCreator: NotificationContentCreator, internal class NewMailNotificationController( private val notificationManager: NotificationManagerCompat, private val newMailNotificationManager: NewMailNotificationManager, private val summaryNotificationCreator: SummaryNotificationCreator, private val singleMessageNotificationCreator: SingleMessageNotificationCreator ) { private val notifications = SparseArray<NotificationData>() private val lock = Any() fun addNewMailNotification(account: Account, message: LocalMessage, silent: Boolean) { val content = contentCreator.createFromMessage(account, message) synchronized(lock) { val notificationData = getOrCreateNotificationData(account) val result = notificationData.addNotificationContent(content) if (result.shouldCancelNotification) { val notificationId = result.notificationId cancelNotification(notificationId) } if (notificationData.isSingleMessageNotification) { createSingleMessageNotificationWithLockScreenNotification(account, notificationData) } else { createSingleMessageNotification(account, result.notificationHolder) } val notificationData = newMailNotificationManager.addNewMailNotification(account, message, silent) createSummaryNotification(account, notificationData, silent) } processNewMailNotificationData(notificationData) } fun removeNewMailNotification(account: Account, messageReference: MessageReference) { synchronized(lock) { val notificationData = getNotificationData(account) ?: return val result = notificationData.removeNotificationForMessage(messageReference) if (result.isUnknownNotification) return cancelNotification(result.notificationId) val notificationData = newMailNotificationManager.removeNewMailNotification(account, messageReference) if (notificationData.isSingleMessageNotification) { createSingleMessageNotificationWithLockScreenNotification(account, notificationData) } else if (result.shouldCreateNotification) { createSingleMessageNotification(account, result.notificationHolder) } updateSummaryNotification(account, notificationData) if (notificationData != null) { processNewMailNotificationData(notificationData) } } fun clearNewMailNotifications(account: Account) { val notificationData = synchronized(lock) { removeNotificationData(account) } ?: return for (notificationId in notificationData.getActiveNotificationIds()) { cancelNotification(notificationId) } val cancelNotificationIds = newMailNotificationManager.clearNewMailNotifications(account) val notificationId = NotificationIds.getNewMailSummaryNotificationId(account) cancelNotification(notificationId) cancelNotifications(cancelNotificationIds) } private fun getOrCreateNotificationData(account: Account): NotificationData { val notificationData = getNotificationData(account) if (notificationData != null) return notificationData val accountNumber = account.accountNumber val newNotificationHolder = createNotificationData(account) notifications.put(accountNumber, newNotificationHolder) return newNotificationHolder } private fun processNewMailNotificationData(notificationData: NewMailNotificationData) { cancelNotifications(notificationData.cancelNotificationIds) private fun getNotificationData(account: Account): NotificationData? { val accountNumber = account.accountNumber return notifications[accountNumber] for (singleNotificationData in notificationData.singleNotificationData) { createSingleNotification(notificationData.baseNotificationData, singleNotificationData) } private fun removeNotificationData(account: Account): NotificationData? { val accountNumber = account.accountNumber val notificationData = notifications[accountNumber] notifications.remove(accountNumber) return notificationData notificationData.summaryNotificationData?.let { summaryNotificationData -> createSummaryNotification(notificationData.baseNotificationData, summaryNotificationData) } protected open fun createNotificationData(account: Account): NotificationData { return NotificationData(account) } private fun cancelNotification(notificationId: Int) { private fun cancelNotifications(notificationIds: List<Int>) { for (notificationId in notificationIds) { notificationManager.cancel(notificationId) } private fun updateSummaryNotification(account: Account, notificationData: NotificationData) { if (notificationData.newMessagesCount == 0) { clearNewMailNotifications(account) } else { createSummaryNotification(account, notificationData, silent = true) } } private fun createSummaryNotification(account: Account, notificationData: NotificationData, silent: Boolean) { val notification = summaryNotificationCreator.buildSummaryNotification(account, notificationData, silent) val notificationId = NotificationIds.getNewMailSummaryNotificationId(account) notificationManager.notify(notificationId, notification) } private fun createSingleMessageNotification(account: Account, holder: NotificationHolder) { val notification = singleMessageNotificationCreator.buildSingleMessageNotification(account, holder) val notificationId = holder.notificationId notificationManager.notify(notificationId, notification) private fun createSingleNotification( baseNotificationData: BaseNotificationData, singleNotificationData: SingleNotificationData ) { singleMessageNotificationCreator.createSingleNotification(baseNotificationData, singleNotificationData) } // When there's only one notification the "public version" of the notification that might be displayed on a secure // lockscreen isn't taken from the summary notification, but from the single "grouped" notification. private fun createSingleMessageNotificationWithLockScreenNotification( account: Account, notificationData: NotificationData private fun createSummaryNotification( baseNotificationData: BaseNotificationData, summaryNotificationData: SummaryNotificationData ) { val holder = notificationData.holderForLatestNotification val notification = singleMessageNotificationCreator.buildSingleMessageNotificationWithLockScreenNotification( account, holder, notificationData ) val notificationId = holder.notificationId notificationManager.notify(notificationId, notification) summaryNotificationCreator.createSummaryNotification(baseNotificationData, summaryNotificationData) } private val notificationManager: NotificationManagerCompat get() = notificationHelper.getNotificationManager() } app/core/src/main/java/com/fsck/k9/notification/NewMailNotificationData.kt 0 → 100644 +87 −0 Original line number Diff line number Diff line package com.fsck.k9.notification import com.fsck.k9.Account import com.fsck.k9.controller.MessageReference internal data class NewMailNotificationData( val cancelNotificationIds: List<Int>, val baseNotificationData: BaseNotificationData, val singleNotificationData: List<SingleNotificationData>, val summaryNotificationData: SummaryNotificationData? ) internal data class BaseNotificationData( val account: Account, val accountName: String, val groupKey: String, val color: Int, val newMessagesCount: Int, val lockScreenNotificationData: LockScreenNotificationData, val appearance: NotificationAppearance ) internal sealed interface LockScreenNotificationData { object None : LockScreenNotificationData object AppName : LockScreenNotificationData object Public : LockScreenNotificationData object MessageCount : LockScreenNotificationData data class SenderNames(val senderNames: String) : LockScreenNotificationData } internal data class NotificationAppearance( val ringtone: String?, val vibrationPattern: LongArray?, val ledColor: Int? ) internal data class SingleNotificationData( val notificationId: Int, val isSilent: Boolean, val timestamp: Long, val content: NotificationContent, val actions: List<NotificationAction>, val wearActions: List<WearNotificationAction>, val addLockScreenNotification: Boolean ) internal sealed interface SummaryNotificationData internal data class SummarySingleNotificationData( val singleNotificationData: SingleNotificationData ) : SummaryNotificationData internal data class SummaryInboxNotificationData( val notificationId: Int, val isSilent: Boolean, val timestamp: Long, val content: List<CharSequence>, val additionalMessagesCount: Int, val messageReferences: List<MessageReference>, val actions: List<SummaryNotificationAction>, val wearActions: List<SummaryWearNotificationAction> ) : SummaryNotificationData internal enum class NotificationAction { Reply, MarkAsRead, Delete } internal enum class WearNotificationAction { Reply, MarkAsRead, Delete, Archive, Spam } internal enum class SummaryNotificationAction { MarkAsRead, Delete } internal enum class SummaryWearNotificationAction { MarkAsRead, Delete, Archive } Loading
app/core/src/main/java/com/fsck/k9/notification/BaseNotificationDataCreator.kt 0 → 100644 +52 −0 Original line number Diff line number Diff line package com.fsck.k9.notification import com.fsck.k9.Account import com.fsck.k9.K9 import com.fsck.k9.K9.LockScreenNotificationVisibility private const val MAX_NUMBER_OF_SENDERS_IN_LOCK_SCREEN_NOTIFICATION = 5 internal class BaseNotificationDataCreator { fun createBaseNotificationData(notificationData: NotificationData): BaseNotificationData { val account = notificationData.account return BaseNotificationData( account = account, groupKey = NotificationGroupKeys.getGroupKey(account), accountName = getAccountName(account), color = account.chipColor, newMessagesCount = notificationData.newMessagesCount, lockScreenNotificationData = createLockScreenNotificationData(notificationData), appearance = createNotificationAppearance(account) ) } private fun getAccountName(account: Account): String { val accountDescription = account.description?.takeIf { it.isNotEmpty() } return accountDescription ?: account.email } private fun createLockScreenNotificationData(data: NotificationData): LockScreenNotificationData { return when (K9.lockScreenNotificationVisibility) { LockScreenNotificationVisibility.NOTHING -> LockScreenNotificationData.None LockScreenNotificationVisibility.APP_NAME -> LockScreenNotificationData.AppName LockScreenNotificationVisibility.EVERYTHING -> LockScreenNotificationData.Public LockScreenNotificationVisibility.MESSAGE_COUNT -> LockScreenNotificationData.MessageCount LockScreenNotificationVisibility.SENDERS -> LockScreenNotificationData.SenderNames(getSenderNames(data)) } } private fun getSenderNames(data: NotificationData): String { return data.getContentForSummaryNotification().asSequence() .map { it.sender } .distinct() .take(MAX_NUMBER_OF_SENDERS_IN_LOCK_SCREEN_NOTIFICATION) .joinToString() } private fun createNotificationAppearance(account: Account): NotificationAppearance { return with(account.notificationSetting) { NotificationAppearance(ringtone = ringtone, vibrationPattern = vibration, ledColor = ledColor) } } }
app/core/src/main/java/com/fsck/k9/notification/CoreKoinModule.kt +21 −7 Original line number Diff line number Diff line Loading @@ -56,31 +56,45 @@ val coreNotificationModule = module { } single { NewMailNotificationController( notificationHelper = get(), contentCreator = get(), notificationManager = get(), newMailNotificationManager = get(), summaryNotificationCreator = get(), singleMessageNotificationCreator = get() ) } single { NotificationContentCreator(context = get(), resourceProvider = get()) } single { NewMailNotificationManager( contentCreator = get(), baseNotificationDataCreator = get(), singleMessageNotificationDataCreator = get(), summaryNotificationDataCreator = get(), clock = get() ) } factory { NotificationContentCreator(context = get(), resourceProvider = get()) } factory { BaseNotificationDataCreator() } factory { SingleMessageNotificationDataCreator() } factory { SummaryNotificationDataCreator(singleMessageNotificationDataCreator = get()) } factory { SingleMessageNotificationCreator( notificationHelper = get(), actionCreator = get(), resourceProvider = get(), lockScreenNotificationCreator = get() lockScreenNotificationCreator = get(), notificationManager = get() ) } single { factory { SummaryNotificationCreator( notificationHelper = get(), actionCreator = get(), lockScreenNotificationCreator = get(), singleMessageNotificationCreator = get(), resourceProvider = get() resourceProvider = get(), notificationManager = get() ) } single { LockScreenNotificationCreator(notificationHelper = get(), resourceProvider = get()) } factory { LockScreenNotificationCreator(notificationHelper = get(), resourceProvider = get()) } single { PushNotificationManager( context = get(), Loading
app/core/src/main/java/com/fsck/k9/notification/LockScreenNotificationCreator.kt +25 −48 Original line number Diff line number Diff line Loading @@ -2,82 +2,59 @@ package com.fsck.k9.notification import android.app.Notification import androidx.core.app.NotificationCompat import com.fsck.k9.K9 import com.fsck.k9.K9.LockScreenNotificationVisibility internal class LockScreenNotificationCreator( private val notificationHelper: NotificationHelper, private val resourceProvider: NotificationResourceProvider ) { fun configureLockScreenNotification(builder: NotificationCompat.Builder, notificationData: NotificationData) { when (K9.lockScreenNotificationVisibility) { LockScreenNotificationVisibility.NOTHING -> { fun configureLockScreenNotification( builder: NotificationCompat.Builder, baseNotificationData: BaseNotificationData ) { when (baseNotificationData.lockScreenNotificationData) { LockScreenNotificationData.None -> { builder.setVisibility(NotificationCompat.VISIBILITY_SECRET) } LockScreenNotificationVisibility.APP_NAME -> { LockScreenNotificationData.AppName -> { builder.setVisibility(NotificationCompat.VISIBILITY_PRIVATE) } LockScreenNotificationVisibility.EVERYTHING -> { LockScreenNotificationData.Public -> { builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC) } LockScreenNotificationVisibility.SENDERS -> { val publicNotification = createPublicNotificationWithSenderList(notificationData) is LockScreenNotificationData.SenderNames -> { val publicNotification = createPublicNotificationWithSenderList(baseNotificationData) builder.setPublicVersion(publicNotification) } LockScreenNotificationVisibility.MESSAGE_COUNT -> { val publicNotification = createPublicNotificationWithNewMessagesCount(notificationData) LockScreenNotificationData.MessageCount -> { val publicNotification = createPublicNotificationWithNewMessagesCount(baseNotificationData) builder.setPublicVersion(publicNotification) } } } private fun createPublicNotificationWithSenderList(notificationData: NotificationData): Notification { val builder = createPublicNotification(notificationData) val newMessages = notificationData.newMessagesCount if (newMessages == 1) { val holder = notificationData.holderForLatestNotification builder.setContentText(holder.content.sender) } else { val contents = notificationData.getContentForSummaryNotification() val senderList = createCommaSeparatedListOfSenders(contents) builder.setContentText(senderList) private fun createPublicNotificationWithSenderList(baseNotificationData: BaseNotificationData): Notification { val notificationData = baseNotificationData.lockScreenNotificationData as LockScreenNotificationData.SenderNames return createPublicNotification(baseNotificationData) .setContentText(notificationData.senderNames) .build() } return builder.build() } private fun createPublicNotificationWithNewMessagesCount(notificationData: NotificationData): Notification { val builder = createPublicNotification(notificationData) val account = notificationData.account val accountName = notificationHelper.getAccountName(account) builder.setContentText(accountName) return builder.build() private fun createPublicNotificationWithNewMessagesCount(baseNotificationData: BaseNotificationData): Notification { return createPublicNotification(baseNotificationData) .setContentText(baseNotificationData.accountName) .build() } private fun createPublicNotification(notificationData: NotificationData): NotificationCompat.Builder { val account = notificationData.account val newMessagesCount = notificationData.newMessagesCount private fun createPublicNotification(baseNotificationData: BaseNotificationData): NotificationCompat.Builder { val account = baseNotificationData.account val newMessagesCount = baseNotificationData.newMessagesCount val title = resourceProvider.newMessagesTitle(newMessagesCount) return notificationHelper.createNotificationBuilder(account, NotificationChannelManager.ChannelType.MESSAGES) .setSmallIcon(resourceProvider.iconNewMail) .setColor(account.chipColor) .setColor(baseNotificationData.color) .setNumber(newMessagesCount) .setContentTitle(title) .setCategory(NotificationCompat.CATEGORY_EMAIL) } fun createCommaSeparatedListOfSenders(contents: List<NotificationContent>): String { return contents.asSequence() .map { it.sender } .distinct() .take(MAX_NUMBER_OF_SENDERS_IN_LOCK_SCREEN_NOTIFICATION) .joinToString() } companion object { const val MAX_NUMBER_OF_SENDERS_IN_LOCK_SCREEN_NOTIFICATION = 5 } }
app/core/src/main/java/com/fsck/k9/notification/NewMailNotificationController.kt +30 −105 Original line number Diff line number Diff line package com.fsck.k9.notification import android.util.SparseArray import androidx.core.app.NotificationManagerCompat import com.fsck.k9.Account import com.fsck.k9.controller.MessageReference Loading @@ -9,135 +8,61 @@ import com.fsck.k9.mailstore.LocalMessage /** * Handle notifications for new messages. */ internal open class NewMailNotificationController( private val notificationHelper: NotificationHelper, private val contentCreator: NotificationContentCreator, internal class NewMailNotificationController( private val notificationManager: NotificationManagerCompat, private val newMailNotificationManager: NewMailNotificationManager, private val summaryNotificationCreator: SummaryNotificationCreator, private val singleMessageNotificationCreator: SingleMessageNotificationCreator ) { private val notifications = SparseArray<NotificationData>() private val lock = Any() fun addNewMailNotification(account: Account, message: LocalMessage, silent: Boolean) { val content = contentCreator.createFromMessage(account, message) synchronized(lock) { val notificationData = getOrCreateNotificationData(account) val result = notificationData.addNotificationContent(content) if (result.shouldCancelNotification) { val notificationId = result.notificationId cancelNotification(notificationId) } if (notificationData.isSingleMessageNotification) { createSingleMessageNotificationWithLockScreenNotification(account, notificationData) } else { createSingleMessageNotification(account, result.notificationHolder) } val notificationData = newMailNotificationManager.addNewMailNotification(account, message, silent) createSummaryNotification(account, notificationData, silent) } processNewMailNotificationData(notificationData) } fun removeNewMailNotification(account: Account, messageReference: MessageReference) { synchronized(lock) { val notificationData = getNotificationData(account) ?: return val result = notificationData.removeNotificationForMessage(messageReference) if (result.isUnknownNotification) return cancelNotification(result.notificationId) val notificationData = newMailNotificationManager.removeNewMailNotification(account, messageReference) if (notificationData.isSingleMessageNotification) { createSingleMessageNotificationWithLockScreenNotification(account, notificationData) } else if (result.shouldCreateNotification) { createSingleMessageNotification(account, result.notificationHolder) } updateSummaryNotification(account, notificationData) if (notificationData != null) { processNewMailNotificationData(notificationData) } } fun clearNewMailNotifications(account: Account) { val notificationData = synchronized(lock) { removeNotificationData(account) } ?: return for (notificationId in notificationData.getActiveNotificationIds()) { cancelNotification(notificationId) } val cancelNotificationIds = newMailNotificationManager.clearNewMailNotifications(account) val notificationId = NotificationIds.getNewMailSummaryNotificationId(account) cancelNotification(notificationId) cancelNotifications(cancelNotificationIds) } private fun getOrCreateNotificationData(account: Account): NotificationData { val notificationData = getNotificationData(account) if (notificationData != null) return notificationData val accountNumber = account.accountNumber val newNotificationHolder = createNotificationData(account) notifications.put(accountNumber, newNotificationHolder) return newNotificationHolder } private fun processNewMailNotificationData(notificationData: NewMailNotificationData) { cancelNotifications(notificationData.cancelNotificationIds) private fun getNotificationData(account: Account): NotificationData? { val accountNumber = account.accountNumber return notifications[accountNumber] for (singleNotificationData in notificationData.singleNotificationData) { createSingleNotification(notificationData.baseNotificationData, singleNotificationData) } private fun removeNotificationData(account: Account): NotificationData? { val accountNumber = account.accountNumber val notificationData = notifications[accountNumber] notifications.remove(accountNumber) return notificationData notificationData.summaryNotificationData?.let { summaryNotificationData -> createSummaryNotification(notificationData.baseNotificationData, summaryNotificationData) } protected open fun createNotificationData(account: Account): NotificationData { return NotificationData(account) } private fun cancelNotification(notificationId: Int) { private fun cancelNotifications(notificationIds: List<Int>) { for (notificationId in notificationIds) { notificationManager.cancel(notificationId) } private fun updateSummaryNotification(account: Account, notificationData: NotificationData) { if (notificationData.newMessagesCount == 0) { clearNewMailNotifications(account) } else { createSummaryNotification(account, notificationData, silent = true) } } private fun createSummaryNotification(account: Account, notificationData: NotificationData, silent: Boolean) { val notification = summaryNotificationCreator.buildSummaryNotification(account, notificationData, silent) val notificationId = NotificationIds.getNewMailSummaryNotificationId(account) notificationManager.notify(notificationId, notification) } private fun createSingleMessageNotification(account: Account, holder: NotificationHolder) { val notification = singleMessageNotificationCreator.buildSingleMessageNotification(account, holder) val notificationId = holder.notificationId notificationManager.notify(notificationId, notification) private fun createSingleNotification( baseNotificationData: BaseNotificationData, singleNotificationData: SingleNotificationData ) { singleMessageNotificationCreator.createSingleNotification(baseNotificationData, singleNotificationData) } // When there's only one notification the "public version" of the notification that might be displayed on a secure // lockscreen isn't taken from the summary notification, but from the single "grouped" notification. private fun createSingleMessageNotificationWithLockScreenNotification( account: Account, notificationData: NotificationData private fun createSummaryNotification( baseNotificationData: BaseNotificationData, summaryNotificationData: SummaryNotificationData ) { val holder = notificationData.holderForLatestNotification val notification = singleMessageNotificationCreator.buildSingleMessageNotificationWithLockScreenNotification( account, holder, notificationData ) val notificationId = holder.notificationId notificationManager.notify(notificationId, notification) summaryNotificationCreator.createSummaryNotification(baseNotificationData, summaryNotificationData) } private val notificationManager: NotificationManagerCompat get() = notificationHelper.getNotificationManager() }
app/core/src/main/java/com/fsck/k9/notification/NewMailNotificationData.kt 0 → 100644 +87 −0 Original line number Diff line number Diff line package com.fsck.k9.notification import com.fsck.k9.Account import com.fsck.k9.controller.MessageReference internal data class NewMailNotificationData( val cancelNotificationIds: List<Int>, val baseNotificationData: BaseNotificationData, val singleNotificationData: List<SingleNotificationData>, val summaryNotificationData: SummaryNotificationData? ) internal data class BaseNotificationData( val account: Account, val accountName: String, val groupKey: String, val color: Int, val newMessagesCount: Int, val lockScreenNotificationData: LockScreenNotificationData, val appearance: NotificationAppearance ) internal sealed interface LockScreenNotificationData { object None : LockScreenNotificationData object AppName : LockScreenNotificationData object Public : LockScreenNotificationData object MessageCount : LockScreenNotificationData data class SenderNames(val senderNames: String) : LockScreenNotificationData } internal data class NotificationAppearance( val ringtone: String?, val vibrationPattern: LongArray?, val ledColor: Int? ) internal data class SingleNotificationData( val notificationId: Int, val isSilent: Boolean, val timestamp: Long, val content: NotificationContent, val actions: List<NotificationAction>, val wearActions: List<WearNotificationAction>, val addLockScreenNotification: Boolean ) internal sealed interface SummaryNotificationData internal data class SummarySingleNotificationData( val singleNotificationData: SingleNotificationData ) : SummaryNotificationData internal data class SummaryInboxNotificationData( val notificationId: Int, val isSilent: Boolean, val timestamp: Long, val content: List<CharSequence>, val additionalMessagesCount: Int, val messageReferences: List<MessageReference>, val actions: List<SummaryNotificationAction>, val wearActions: List<SummaryWearNotificationAction> ) : SummaryNotificationData internal enum class NotificationAction { Reply, MarkAsRead, Delete } internal enum class WearNotificationAction { Reply, MarkAsRead, Delete, Archive, Spam } internal enum class SummaryNotificationAction { MarkAsRead, Delete } internal enum class SummaryWearNotificationAction { MarkAsRead, Delete, Archive }