Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b1385fc5 authored by Michael Enoma's avatar Michael Enoma
Browse files

Add "demo" backend/fixing notifications

parent 86a53747
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@ import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.fsck.k9.Account

internal open class AuthenticationErrorNotifications(
internal open class AuthenticationErrorNotificationController(
    private val notificationHelper: NotificationHelper,
    private val actionCreator: NotificationActionCreator,
    private val resourceProvider: NotificationResourceProvider
+0 −60
Original line number Diff line number Diff line
package com.fsck.k9.notification

import android.content.Context
import androidx.core.app.NotificationCompat
import com.fsck.k9.Account
import com.fsck.k9.K9
import com.fsck.k9.K9.NotificationQuickDelete

internal abstract class BaseNotifications(
    protected val notificationHelper: NotificationHelper,
    protected val actionCreator: NotificationActionCreator,
    protected val resourceProvider: NotificationResourceProvider
) {
    protected val context: Context = notificationHelper.getContext()

    fun createBigTextStyleNotification(
        account: Account,
        holder: NotificationHolder,
        notificationId: Int
    ): NotificationCompat.Builder {
        val accountName = notificationHelper.getAccountName(account)
        val content = holder.content
        val groupKey = NotificationGroupKeys.getGroupKey(account)

        val builder = createAndInitializeNotificationBuilder(account)
            .setTicker(content.summary)
            .setGroup(groupKey)
            .setContentTitle(content.sender)
            .setContentText(content.subject)
            .setSubText(accountName)

        val style = createBigTextStyle(builder)
        style.bigText(content.preview)
        builder.setStyle(style)

        val contentIntent = actionCreator.createViewMessagePendingIntent(content.messageReference, notificationId)
        builder.setContentIntent(contentIntent)

        return builder
    }

    fun createAndInitializeNotificationBuilder(account: Account): NotificationCompat.Builder {
        return notificationHelper.createNotificationBuilder(account, NotificationChannelManager.ChannelType.MESSAGES)
            .setSmallIcon(resourceProvider.iconNewMail)
            .setColor(account.chipColor)
            .setWhen(System.currentTimeMillis())
            .setAutoCancel(true)
            .setCategory(NotificationCompat.CATEGORY_EMAIL)
    }

    fun isDeleteActionEnabled(): Boolean {
        val deleteOption = K9.notificationQuickDeleteBehaviour
        return deleteOption === NotificationQuickDelete.ALWAYS ||
            deleteOption === NotificationQuickDelete.FOR_SINGLE_MSG
    }

    protected open fun createBigTextStyle(builder: NotificationCompat.Builder?): NotificationCompat.BigTextStyle {
        return NotificationCompat.BigTextStyle(builder)
    }
}
 No newline at end of file
+2 −2
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@ import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.fsck.k9.Account

internal open class CertificateErrorNotifications(
internal open class CertificateErrorNotificationController(
    private val notificationHelper: NotificationHelper,
    private val actionCreator: NotificationActionCreator,
    private val resourceProvider: NotificationResourceProvider
+62 −15
Original line number Diff line number Diff line
@@ -6,16 +6,25 @@ import androidx.core.app.NotificationManagerCompat
import com.fsck.k9.AccountPreferenceSerializer
import java.util.concurrent.Executors
import org.koin.dsl.module

val coreNotificationModule = module {
    single { NotificationController(get(), get(), get(), get(), get()) }
    single {
        NotificationController(
            certificateErrorNotificationController = get(),
            authenticationErrorNotificationController = get(),
            syncNotificationController = get(),
            sendFailedNotificationController = get(),
            newMailNotificationController = get()
        )
    }
    single { NotificationManagerCompat.from(get()) }
    single { NotificationHelper(get(), get(), get()) }
    single { NotificationHelper(context = get(), notificationManager = get(), channelUtils = get()) }
    single {
        NotificationChannelManager(
            get(),
            Executors.newSingleThreadExecutor(),
            get<Context>().getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager,
            get()
            preferences = get(),
            backgroundExecutor = Executors.newSingleThreadExecutor(),
            notificationManager = get<Context>().getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager,
            resourceProvider = get()
        )
    }
    single {
@@ -25,15 +34,53 @@ val coreNotificationModule = module {
            serverSettingsSerializer = get()
        )
    }
    single { CertificateErrorNotifications(get(), get(), get()) }
    single { AuthenticationErrorNotifications(get(), get(), get()) }
    single { SyncNotifications(get(), get(), get()) }
    single { SendFailedNotifications(get(), get(), get()) }
    single { NewMailNotifications(get(), get(), get(), get()) }
    single { NotificationContentCreator(get(), get()) }
    single { SingleMessageNotifications(get(), get(), get(), get()) }
    single { MessageSummaryNotifications(get(), get(), get(), get(), get()) }
    single { LockScreenNotification(get(), get()) }
    single {
        CertificateErrorNotificationController(
            notificationHelper = get(),
            actionCreator = get(),
            resourceProvider = get()
        )
    }
    single {
        AuthenticationErrorNotificationController(
            notificationHelper = get(),
            actionCreator = get(),
            resourceProvider = get()
        )
    }
    single {
        SyncNotificationController(notificationHelper = get(), actionBuilder = get(), resourceProvider = get())
    }
    single {
        SendFailedNotificationController(notificationHelper = get(), actionBuilder = get(), resourceProvider = get())
    }
    single {
        NewMailNotificationController(
            notificationHelper = get(),
            contentCreator = get(),
            summaryNotificationCreator = get(),
            singleMessageNotificationCreator = get()
        )
    }
    single { NotificationContentCreator(context = get(), resourceProvider = get()) }
    single {
        SingleMessageNotificationCreator(
            notificationHelper = get(),
            actionCreator = get(),
            resourceProvider = get(),
            lockScreenNotificationCreator = get()
        )
    }
    single {
        SummaryNotificationCreator(
            notificationHelper = get(),
            actionCreator = get(),
            lockScreenNotificationCreator = get(),
            singleMessageNotificationCreator = get(),
            resourceProvider = get()
        )
    }
    single { LockScreenNotificationCreator(notificationHelper = get(), resourceProvider = get()) }
    single {
        PushNotificationManager(
            context = get(),
+0 −210
Original line number Diff line number Diff line
package com.fsck.k9.notification

import android.app.KeyguardManager
import android.app.Notification
import android.content.Context
import androidx.core.app.NotificationCompat
import com.fsck.k9.Account
import com.fsck.k9.K9
import com.fsck.k9.K9.NotificationHideSubject
import com.fsck.k9.K9.NotificationQuickDelete
import com.fsck.k9.notification.NotificationGroupKeys.getGroupKey
import com.fsck.k9.notification.NotificationIds.getNewMailSummaryNotificationId

internal open class DeviceNotifications(
    notificationHelper: NotificationHelper,
    actionCreator: NotificationActionCreator,
    private val lockScreenNotification: LockScreenNotification,
    private val wearNotifications: WearNotifications,
    resourceProvider: NotificationResourceProvider
) : BaseNotifications(notificationHelper, actionCreator, resourceProvider) {

    fun buildSummaryNotification(account: Account, notificationData: NotificationData, silent: Boolean): Notification {
        val unreadMessageCount = notificationData.unreadMessageCount

        val builder = when {
            isPrivacyModeActive -> {
                createSimpleSummaryNotification(account, unreadMessageCount)
            }
            notificationData.isSingleMessageNotification -> {
                val holder = notificationData.holderForLatestNotification
                createBigTextStyleSummaryNotification(account, holder)
            }
            else -> {
                createInboxStyleSummaryNotification(account, notificationData, unreadMessageCount)
            }
        }

        if (notificationData.containsStarredMessages()) {
            builder.priority = NotificationCompat.PRIORITY_HIGH
        }
        val notificationId = getNewMailSummaryNotificationId(account)
        val deletePendingIntent = actionCreator.createDismissAllMessagesPendingIntent(account, notificationId)
        builder.setDeleteIntent(deletePendingIntent)

        lockScreenNotification.configureLockScreenNotification(builder, notificationData)

        val notificationSetting = account.notificationSetting
        notificationHelper.configureNotification(
            builder = builder,
            ringtone = if (notificationSetting.isRingEnabled) notificationSetting.ringtone else null,
            vibrationPattern = if (notificationSetting.isVibrateEnabled) notificationSetting.vibration else null,
            ledColor = if (notificationSetting.isLedEnabled) notificationSetting.ledColor else null,
            ledSpeed = NotificationHelper.NOTIFICATION_LED_BLINK_SLOW,
            ringAndVibrate = !silent
        )

        return builder.build()
    }

    private fun createSimpleSummaryNotification(account: Account, unreadMessageCount: Int): NotificationCompat.Builder {
        val accountName = notificationHelper.getAccountName(account)
        val newMailText = resourceProvider.newMailTitle()
        val unreadMessageCountText = resourceProvider.newMailUnreadMessageCount(unreadMessageCount, accountName)
        val notificationId = getNewMailSummaryNotificationId(account)
        val contentIntent = actionCreator.createViewFolderListPendingIntent(account, notificationId)

        return createAndInitializeNotificationBuilder(account)
            .setNumber(unreadMessageCount)
            .setTicker(newMailText)
            .setContentTitle(unreadMessageCountText)
            .setContentText(newMailText)
            .setContentIntent(contentIntent)
    }

    private fun createBigTextStyleSummaryNotification(
        account: Account,
        holder: NotificationHolder
    ): NotificationCompat.Builder {
        val notificationId = getNewMailSummaryNotificationId(account)
        val builder = createBigTextStyleNotification(account, holder, notificationId)
        builder.setGroupSummary(true)

        val content = holder.content
        addReplyAction(builder, content, notificationId)
        addMarkAsReadAction(builder, content, notificationId)
        addDeleteAction(builder, content, notificationId)

        return builder
    }

    private fun createInboxStyleSummaryNotification(
        account: Account,
        notificationData: NotificationData,
        unreadMessageCount: Int
    ): NotificationCompat.Builder {
        val latestNotification = notificationData.holderForLatestNotification
        val newMessagesCount = notificationData.newMessagesCount
        val accountName = notificationHelper.getAccountName(account)
        val title = resourceProvider.newMessagesTitle(newMessagesCount)
        val summary = if (notificationData.hasSummaryOverflowMessages()) {
            resourceProvider.additionalMessages(notificationData.getSummaryOverflowMessagesCount(), accountName)
        } else {
            accountName
        }
        val groupKey = getGroupKey(account)

        val builder = createAndInitializeNotificationBuilder(account)
            .setNumber(unreadMessageCount)
            .setTicker(latestNotification.content.summary)
            .setGroup(groupKey)
            .setGroupSummary(true)
            .setContentTitle(title)
            .setSubText(accountName)

        val style = createInboxStyle(builder)
            .setBigContentTitle(title)
            .setSummaryText(summary)

        for (content in notificationData.getContentForSummaryNotification()) {
            style.addLine(content.summary)
        }
        builder.setStyle(style)
        addMarkAllAsReadAction(builder, notificationData)
        addDeleteAllAction(builder, notificationData)
        wearNotifications.addSummaryActions(builder, notificationData)
        val notificationId = getNewMailSummaryNotificationId(account)
        val messageReferences = notificationData.getAllMessageReferences()
        val contentIntent = actionCreator.createViewMessagesPendingIntent(account, messageReferences, notificationId)
        builder.setContentIntent(contentIntent)

        return builder
    }

    private fun addMarkAsReadAction(
        builder: NotificationCompat.Builder,
        content: NotificationContent,
        notificationId: Int
    ) {
        val icon = resourceProvider.iconMarkAsRead
        val title = resourceProvider.actionMarkAsRead()
        val messageReference = content.messageReference
        val action = actionCreator.createMarkMessageAsReadPendingIntent(messageReference, notificationId)

        builder.addAction(icon, title, action)
    }

    private fun addMarkAllAsReadAction(builder: NotificationCompat.Builder, notificationData: NotificationData) {
        val icon = resourceProvider.iconMarkAsRead
        val title = resourceProvider.actionMarkAsRead()
        val account = notificationData.account
        val messageReferences = notificationData.getAllMessageReferences()
        val notificationId = getNewMailSummaryNotificationId(account)
        val markAllAsReadPendingIntent =
            actionCreator.createMarkAllAsReadPendingIntent(account, messageReferences, notificationId)

        builder.addAction(icon, title, markAllAsReadPendingIntent)
    }

    private fun addDeleteAllAction(builder: NotificationCompat.Builder, notificationData: NotificationData) {
        if (K9.notificationQuickDeleteBehaviour !== NotificationQuickDelete.ALWAYS) {
            return
        }
        val icon = resourceProvider.iconDelete
        val title = resourceProvider.actionDelete()
        val account = notificationData.account
        val notificationId = getNewMailSummaryNotificationId(account)
        val messageReferences = notificationData.getAllMessageReferences()
        val action = actionCreator.createDeleteAllPendingIntent(account, messageReferences, notificationId)
        builder.addAction(icon, title, action)
    }

    private fun addDeleteAction(
        builder: NotificationCompat.Builder,
        content: NotificationContent,
        notificationId: Int
    ) {
        if (!isDeleteActionEnabled()) {
            return
        }
        val icon = resourceProvider.iconDelete
        val title = resourceProvider.actionDelete()
        val messageReference = content.messageReference
        val action = actionCreator.createDeleteMessagePendingIntent(messageReference, notificationId)

        builder.addAction(icon, title, action)
    }

    private fun addReplyAction(builder: NotificationCompat.Builder, content: NotificationContent, notificationId: Int) {
        val icon = resourceProvider.iconReply
        val title = resourceProvider.actionReply()
        val messageReference = content.messageReference
        val replyToMessagePendingIntent = actionCreator.createReplyPendingIntent(messageReference, notificationId)

        builder.addAction(icon, title, replyToMessagePendingIntent)
    }

    private val isPrivacyModeActive: Boolean
        get() {
            val keyguardService = context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
            val privacyModeAlwaysEnabled = K9.notificationHideSubject === NotificationHideSubject.ALWAYS
            val privacyModeEnabledWhenLocked = K9.notificationHideSubject === NotificationHideSubject.WHEN_LOCKED
            val screenLocked = keyguardService.inKeyguardRestrictedInputMode()
            return privacyModeAlwaysEnabled || privacyModeEnabledWhenLocked && screenLocked
        }

    protected open fun createInboxStyle(builder: NotificationCompat.Builder?): NotificationCompat.InboxStyle {
        return NotificationCompat.InboxStyle(builder)
    }
}
Loading