Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package com.fsck.k9.notification

import android.content.Context
import android.graphics.Bitmap
import app.k9mail.core.ui.legacy.designsystem.atom.icon.Icons
import com.fsck.k9.activity.misc.ContactPicture
import com.fsck.k9.mail.Address
import com.fsck.k9.ui.R
import com.fsck.k9.view.RecipientSelectView
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

class K9NotificationResourceProvider(private val context: Context) : NotificationResourceProvider {
override val iconWarning: Int = Icons.Outlined.Warning
Expand Down Expand Up @@ -38,6 +44,10 @@ class K9NotificationResourceProvider(private val context: Context) : Notificatio
override fun authenticationErrorBody(accountName: String): String =
context.getString(R.string.notification_authentication_error_text, accountName)

override suspend fun avatar(address: Address): Bitmap? = withContext(Dispatchers.IO) {
ContactPicture.getContactPictureLoader().getContactPicture(RecipientSelectView.Recipient(address))
}

override fun notifyErrorTitle(): String = context.getString(R.string.notification_notify_error_title)

override fun notifyErrorText(): String = context.getString(R.string.notification_notify_error_text)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ val coreNotificationModule = module {
actionCreator = get(),
resourceProvider = get(),
lockScreenNotificationCreator = get(),
application = get(),
)
}
factory {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.fsck.k9.notification

import app.k9mail.legacy.message.controller.MessageReference
import com.fsck.k9.mail.Address

internal data class NotificationContent(
val messageReference: MessageReference,
val sender: String,
val sender: Address,
val subject: String,
val preview: CharSequence,
val summary: CharSequence,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.text.SpannableStringBuilder
import app.k9mail.core.android.common.contact.ContactRepository
import app.k9mail.legacy.message.extractors.PreviewResult.PreviewType
import com.fsck.k9.helper.MessageHelper
import com.fsck.k9.mail.Address
import com.fsck.k9.mail.Message
import com.fsck.k9.mailstore.LocalMessage
import net.thunderbird.core.android.account.LegacyAccount
Expand All @@ -19,10 +20,10 @@ internal class NotificationContentCreator(

return NotificationContent(
messageReference = message.makeMessageReference(),
sender = getMessageSenderForDisplay(sender),
sender = sender,
subject = getMessageSubject(message),
preview = getMessagePreview(message),
summary = buildMessageSummary(sender, getMessageSubject(message)),
summary = buildMessageSummary(sender.personal, getMessageSubject(message)),
)
}

Expand Down Expand Up @@ -70,7 +71,7 @@ internal class NotificationContentCreator(
}

@Suppress("ReturnCount")
private fun getMessageSender(account: LegacyAccount, message: Message): String? {
private fun getMessageSender(account: LegacyAccount, message: Message): Address {
val localContactRepository =
if (generalSettingsManager.getConfig().display.isShowContactName) contactRepository else null
var isSelf = false
Expand All @@ -79,33 +80,33 @@ internal class NotificationContentCreator(
if (!fromAddresses.isNullOrEmpty()) {
isSelf = account.isAnIdentity(fromAddresses)
if (!isSelf) {
return MessageHelper.toFriendly(
fromAddresses.first(),
val firstFrom = fromAddresses.first()
val personal = MessageHelper.toFriendly(
firstFrom,
generalSettingsManager.getConfig().display.isShowCorrespondentNames,
generalSettingsManager.getConfig().display.isChangeContactNameColor,
localContactRepository,
).toString()
return Address(firstFrom.address, personal)
}
}

if (isSelf) {
// show To: if the message was sent from me
val recipients = message.getRecipients(Message.RecipientType.TO)
if (!recipients.isNullOrEmpty()) {
val firstRecipient = recipients.first()
val recipientDisplayName = MessageHelper.toFriendly(
address = recipients.first(),
address = firstRecipient,
isShowCorrespondentNames = generalSettingsManager.getConfig().display.isShowCorrespondentNames,
isChangeContactNameColor = generalSettingsManager.getConfig().display.isChangeContactNameColor,
contactRepository = localContactRepository,
).toString()
return resourceProvider.recipientDisplayName(recipientDisplayName)
val personal = resourceProvider.recipientDisplayName(recipientDisplayName)
return Address(firstRecipient.address, personal)
}
}

return null
}

private fun getMessageSenderForDisplay(sender: String?): String {
return sender ?: resourceProvider.noSender()
return Address("no.sender@example.com", resourceProvider.noSender())
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.fsck.k9.notification

import android.graphics.Bitmap
import com.fsck.k9.mail.Address

interface NotificationResourceProvider {
val iconWarning: Int
val iconMarkAsRead: Int
Expand All @@ -25,6 +28,8 @@ interface NotificationResourceProvider {
fun authenticationErrorTitle(): String
fun authenticationErrorBody(accountName: String): String

suspend fun avatar(address: Address): Bitmap?

fun notifyErrorTitle(): String
fun notifyErrorText(): String

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package com.fsck.k9.notification

import android.app.Application
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationCompat.WearableExtender
import androidx.core.graphics.drawable.IconCompat
import com.fsck.k9.notification.NotificationChannelManager.ChannelType
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import net.thunderbird.core.logging.legacy.Log
import androidx.core.app.NotificationCompat.Builder as NotificationBuilder

Expand All @@ -11,12 +17,15 @@ internal class SingleMessageNotificationCreator(
private val actionCreator: NotificationActionCreator,
private val resourceProvider: NotificationResourceProvider,
private val lockScreenNotificationCreator: LockScreenNotificationCreator,
private val application: Application,
) {
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)

fun createSingleNotification(
baseNotificationData: BaseNotificationData,
singleNotificationData: SingleNotificationData,
isGroupSummary: Boolean = false,
) {
) = scope.launch {
val account = baseNotificationData.account
val notificationId = singleNotificationData.notificationId
val content = singleNotificationData.content
Expand All @@ -27,10 +36,11 @@ internal class SingleMessageNotificationCreator(
.setGroupSummary(isGroupSummary)
.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY)
.setSmallIcon(resourceProvider.iconNewMail)
.setAvatar(singleNotificationData.content)
.setColor(baseNotificationData.color)
.setWhen(singleNotificationData.timestamp)
.setTicker(content.summary)
.setContentTitle(content.sender)
.setContentTitle(content.sender.personal)
.setContentText(content.subject)
.setSubText(baseNotificationData.accountName)
.setBigText(content.preview)
Expand All @@ -52,6 +62,12 @@ internal class SingleMessageNotificationCreator(
notificationHelper.notify(account, notificationId, notification)
}

private suspend fun NotificationBuilder.setAvatar(content: NotificationContent) = apply {
resourceProvider.avatar(content.sender)?.let {
setLargeIcon(IconCompat.createWithAdaptiveBitmap(it).toIcon(application))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be called on minSdk 23, the current is 21. We have to bump the minSdk or update

@WorkerThread
fun getContactPicture(recipient: Recipient): Bitmap? {
val contactPictureUri = recipient.photoThumbnailUri
val address = recipient.address
return if (contactPictureUri != null) {
getContactPicture(contactPictureUri)
} else {
getFallbackPicture(address)
}
}

to accept a Transformation for CircleCrop for avatars.

}
}

private fun NotificationBuilder.setBigText(text: CharSequence) = apply {
setStyle(NotificationCompat.BigTextStyle().bigText(text))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import assertk.assertions.isNotNull
import assertk.assertions.isSameInstanceAs
import com.fsck.k9.K9
import com.fsck.k9.K9.LockScreenNotificationVisibility
import com.fsck.k9.mail.Address
import net.thunderbird.core.android.account.Identity
import net.thunderbird.core.android.account.LegacyAccount
import net.thunderbird.feature.notification.NotificationLight
Expand Down Expand Up @@ -129,7 +130,8 @@ class BaseNotificationDataCreatorTest {

assertThat(result.lockScreenNotificationData).isInstanceOf<LockScreenNotificationData.SenderNames>()
val senderNamesData = result.lockScreenNotificationData as LockScreenNotificationData.SenderNames
assertThat(senderNamesData.senderNames).isEqualTo("Sender One, Sender Two, Sender Three")
assertThat(senderNamesData.senderNames)
.isEqualTo("Sender One <irrelevant>, Sender Two <irrelevant>, Sender Three <irrelevant>")
}

@Test
Expand Down Expand Up @@ -201,7 +203,7 @@ class BaseNotificationDataCreatorTest {
timestamp = 0L,
content = NotificationContent(
messageReference = mock(),
sender = sender,
sender = Address("irrelevant", sender),
preview = "irrelevant",
summary = "irrelevant",
subject = "irrelevant",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import assertk.assertions.isInstanceOf
import assertk.assertions.isNotNull
import assertk.assertions.isNull
import assertk.assertions.isTrue
import com.fsck.k9.mail.Address
import com.fsck.k9.mailstore.LocalMessage
import com.fsck.k9.mailstore.LocalStore
import com.fsck.k9.mailstore.LocalStoreProvider
Expand Down Expand Up @@ -106,7 +107,7 @@ class NewMailNotificationManagerTest {
assertThat(result.singleNotificationData.first().content).isEqualTo(
NotificationContent(
messageReference = createMessageReference("msg-1"),
sender = "sender",
sender = Address("irrelevant", "sender"),
subject = "subject",
preview = "preview",
summary = "summary",
Expand Down Expand Up @@ -143,7 +144,7 @@ class NewMailNotificationManagerTest {
assertThat(result.singleNotificationData.first().content).isEqualTo(
NotificationContent(
messageReference = createMessageReference("msg-2"),
sender = "Zoe",
sender = Address("irrelevant", "Zoe"),
subject = "Meeting",
preview = "We need to talk",
summary = "Zoe Meeting",
Expand Down Expand Up @@ -310,7 +311,7 @@ class NewMailNotificationManagerTest {
assertThat(singleNotificationData.content).isEqualTo(
NotificationContent(
messageReference = createMessageReference("msg-restore"),
sender = "Alice",
sender = Address("irrelevant", "Alice"),
subject = "Another one",
preview = "Are you tired of me yet?",
summary = "Alice Another one",
Expand Down Expand Up @@ -352,7 +353,7 @@ class NewMailNotificationManagerTest {
assertThat(singleNotificationData.content).isEqualTo(
NotificationContent(
messageReference = createMessageReference("uid-1"),
sender = "Sender",
sender = Address("irrelevant", "Sender"),
subject = "Subject",
preview = "Preview",
summary = "Summary",
Expand All @@ -365,7 +366,7 @@ class NewMailNotificationManagerTest {
assertThat(summaryNotificationData.singleNotificationData.content).isEqualTo(
NotificationContent(
messageReference = createMessageReference("uid-1"),
sender = "Sender",
sender = Address("irrelevant", "Sender"),
subject = "Subject",
preview = "Preview",
summary = "Summary",
Expand Down Expand Up @@ -435,7 +436,7 @@ class NewMailNotificationManagerTest {
on { createFromMessage(account, message) } doReturn
NotificationContent(
messageReference = createMessageReference(messageUid),
sender,
sender = Address("irrelevant", sender),
subject,
preview,
summary,
Expand Down Expand Up @@ -463,7 +464,7 @@ class NewMailNotificationManagerTest {
on { createFromMessage(account, message) } doReturn
NotificationContent(
messageReference = createMessageReference(messageUid),
sender,
Address("irrelevant", sender),
subject,
preview,
summary,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class NotificationContentCreatorTest : RobolectricTest() {
val content = contentCreator.createFromMessage(account, message)

assertThat(content.messageReference).isEqualTo(messageReference)
assertThat(content.sender).isEqualTo(SENDER_NAME)
assertThat(content.sender.personal).isEqualTo(SENDER_NAME)
assertThat(content.subject).isEqualTo(SUBJECT)
assertThat(content.preview.toString()).isEqualTo("$SUBJECT\n$PREVIEW")
assertThat(content.summary.toString()).isEqualTo("$SENDER_NAME $SUBJECT")
Expand Down Expand Up @@ -110,8 +110,8 @@ class NotificationContentCreatorTest : RobolectricTest() {

val content = contentCreator.createFromMessage(account, message)

assertThat(content.sender).isEqualTo("No sender")
assertThat(content.summary.toString()).isEqualTo(SUBJECT)
assertThat(content.sender.personal).isEqualTo("No sender")
assertThat(content.summary.toString()).isEqualTo("No sender $SUBJECT")
}

@Test
Expand All @@ -122,7 +122,7 @@ class NotificationContentCreatorTest : RobolectricTest() {

val content = contentCreator.createFromMessage(account, message)

assertThat(content.sender).isEqualTo("To:Bob")
assertThat(content.sender.personal).isEqualTo("To:Bob")
assertThat(content.summary.toString()).isEqualTo("To:Bob $SUBJECT")
}

Expand All @@ -137,10 +137,10 @@ class NotificationContentCreatorTest : RobolectricTest() {

val content = contentCreator.createFromMessage(account, message)

assertThat(content.sender).isEqualTo("No sender")
assertThat(content.sender.personal).isEqualTo("No sender")
assertThat(content.subject).isEqualTo("(No subject)")
assertThat(content.preview.toString()).isEqualTo("(No subject)")
assertThat(content.summary.toString()).isEqualTo("(No subject)")
assertThat(content.summary.toString()).isEqualTo("No sender (No subject)")
}

private fun createNotificationContentCreator(): NotificationContentCreator {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import assertk.assertions.isNotNull
import assertk.assertions.isNull
import assertk.assertions.isSameInstanceAs
import assertk.assertions.isTrue
import com.fsck.k9.mail.Address
import kotlin.test.assertNotNull
import net.thunderbird.core.android.account.LegacyAccount
import net.thunderbird.core.android.testing.RobolectricTest
Expand Down Expand Up @@ -247,7 +248,7 @@ class NotificationDataStoreTest : RobolectricTest() {
private fun createNotificationContent(messageReference: MessageReference): NotificationContent {
return NotificationContent(
messageReference = messageReference,
sender = "irrelevant",
sender = Address("irrelevant", "irrelevant"),
subject = "irrelevant",
preview = "irrelevant",
summary = "irrelevant",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import assertk.assertions.isFalse
import assertk.assertions.isTrue
import com.fsck.k9.K9
import com.fsck.k9.K9.NotificationQuickDelete
import com.fsck.k9.mail.Address
import net.thunderbird.core.android.account.LegacyAccount
import org.junit.Test

Expand Down Expand Up @@ -265,7 +266,7 @@ class SingleMessageNotificationDataCreatorTest {

private fun createNotificationContent() = NotificationContent(
messageReference = MessageReference("irrelevant", 1, "irrelevant"),
sender = "irrelevant",
sender = Address("irrelevant", "irrelevant"),
subject = "irrelevant",
preview = "irrelevant",
summary = "irrelevant",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import assertk.assertions.isFalse
import assertk.assertions.isInstanceOf
import assertk.assertions.isTrue
import com.fsck.k9.K9
import com.fsck.k9.mail.Address
import java.util.Calendar
import kotlin.time.Clock
import kotlin.time.ExperimentalTime
Expand Down Expand Up @@ -296,7 +297,7 @@ class SummaryNotificationDataCreatorTest {

private fun createNotificationContent() = NotificationContent(
messageReference = MessageReference("irrelevant", 1, "irrelevant"),
sender = "irrelevant",
sender = Address("irrelevant", "irrelevant"),
subject = "irrelevant",
preview = "irrelevant",
summary = "irrelevant",
Expand Down
Loading
Loading