Skip to content

Commit 9e6c3f8

Browse files
Merge pull request #9660 from rafaeltonholo/feat/9312/in-app-notification-message-list-integration
feat(notifications): in-app notifications with Message List integration
2 parents cba07d2 + a86115b commit 9e6c3f8

File tree

33 files changed

+452
-73
lines changed

33 files changed

+452
-73
lines changed

feature/debug-settings/src/main/kotlin/net/thunderbird/feature/debug/settings/notification/DebugNotificationSectionViewModel.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,20 +201,26 @@ internal class DebugNotificationSectionViewModel(
201201
state: State,
202202
): Notification? = when (notificationType) {
203203
AuthenticationErrorNotification::class -> AuthenticationErrorNotification(
204+
isIncomingServerError = true,
204205
accountUuid = selectedAccount.uuid,
205206
accountDisplayName = accountDisplay,
207+
accountNumber = 0,
206208
)
207209

208210
CertificateErrorNotification::class -> CertificateErrorNotification(
211+
isIncomingServerError = true,
209212
accountUuid = selectedAccount.uuid,
210213
accountDisplayName = accountDisplay,
214+
accountNumber = 0,
211215
)
212216

213217
FailedToCreateNotification::class -> FailedToCreateNotification(
214218
accountUuid = selectedAccount.uuid,
215219
failedNotification = AuthenticationErrorNotification(
220+
isIncomingServerError = true,
216221
accountUuid = selectedAccount.uuid,
217222
accountDisplayName = accountDisplay,
223+
accountNumber = 0,
218224
),
219225
)
220226

feature/notification/api/src/androidMain/kotlin/net/thunderbird/feature/notification/api/ui/InAppNotificationHost.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ fun InAppNotificationHost(
100100

101101
val state by hostStateHolder.currentInAppNotificationHostState.collectAsState()
102102

103-
LaunchedEffect(inAppNotificationEvents) {
103+
LaunchedEffect(inAppNotificationEvents, eventFilter) {
104104
val event = inAppNotificationEvents
105105
if (event != null && eventFilter(event)) {
106106
when (event) {

feature/notification/api/src/androidMain/kotlin/net/thunderbird/feature/notification/api/ui/layout/InAppNotificationHostLayout.kt

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import androidx.compose.ui.layout.Placeable
1515
import androidx.compose.ui.layout.SubcomposeLayout
1616
import androidx.compose.ui.layout.SubcomposeMeasureScope
1717
import androidx.compose.ui.unit.Constraints
18+
import androidx.compose.ui.unit.constrainHeight
1819
import androidx.compose.ui.util.fastForEach
1920
import androidx.compose.ui.util.fastMap
2021
import androidx.compose.ui.util.fastMaxBy
@@ -73,10 +74,17 @@ internal fun InAppNotificationHostLayout(
7374
// In case the maxHeight is not defined (for example when no content is passed to the content lambda),
7475
// we manually calculate the layout height to avoid a crash caused by the pre-condition check
7576
// of the layout function.
76-
val layoutHeight = if (constraints.maxHeight == Constraints.Infinity) {
77-
bannerGlobalHeight + bannerInlineListHeight.roundToInt() + mainContentHeight
78-
} else {
79-
constraints.maxHeight
77+
val layoutHeight = when {
78+
constraints.minHeight == 0 ||
79+
constraints.maxHeight == Constraints.Infinity -> {
80+
constraints.constrainHeight(
81+
bannerGlobalHeight + bannerInlineListHeight.roundToInt() + mainContentHeight,
82+
)
83+
}
84+
85+
else -> {
86+
constraints.maxHeight
87+
}
8088
}
8189

8290
layout(layoutWidth, layoutHeight) {

feature/notification/api/src/commonMain/composeResources/values/strings.xml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,23 @@
1515
<string name="notification_notify_error_text">An error has occurred while trying to create a system notification for a new message. The reason is most likely a missing notification sound.\n\nTap to open notification settings.</string>
1616

1717
<string name="notification_authentication_error_title">Authentication failed</string>
18-
<string name="notification_authentication_error_text">Authentication failed for %s. Update your server settings.</string>
18+
<string name="notification_authentication_error_text">Authentication failed for %1$s. Update your server settings.</string>
1919

2020
<string name="notification_certificate_error_public">Certificate error</string>
21-
<string name="notification_certificate_error_title">Certificate error for %s</string>
21+
<string name="notification_certificate_error_title">Certificate error for %1$s</string>
2222
<string name="notification_certificate_error_text">Check your server settings</string>
2323

2424
<string name="notification_bg_sync_ticker">Checking mail: %1$s: %2$s</string>
2525
<string name="notification_bg_sync_title">Checking mail</string>
2626
<string name="notification_bg_sync_text">%1$s: %2$s</string>
27-
<string name="notification_bg_send_ticker">Sending mail: %s</string>
27+
<string name="notification_bg_send_ticker">Sending mail: %1$s</string>
2828
<string name="notification_bg_send_title">Sending mail</string>
2929

3030
<string name="send_failure_subject">Failed to send some messages</string>
3131

3232
<plurals name="notification_new_messages_title">
33-
<item quantity="one">%d new message</item>
34-
<item quantity="other">%d new messages</item>
33+
<item quantity="one">%1$d new message</item>
34+
<item quantity="other">%1$d new messages</item>
3535
</plurals>
3636
<string name="notification_additional_messages">+ %1$d more on %2$s</string>
3737

feature/notification/api/src/commonMain/kotlin/net/thunderbird/feature/notification/api/content/AppNotification.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import net.thunderbird.feature.notification.api.ui.style.SystemNotificationStyle
3030
* @see AppNotification
3131
*/
3232
sealed interface Notification {
33+
val accountUuid: String?
3334
val title: String
3435
val accessibilityText: String
3536
val contentText: String?

feature/notification/api/src/commonMain/kotlin/net/thunderbird/feature/notification/api/content/AuthenticationErrorNotification.kt

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import net.thunderbird.feature.notification.api.ui.action.NotificationAction
66
import net.thunderbird.feature.notification.api.ui.icon.AuthenticationError
77
import net.thunderbird.feature.notification.api.ui.icon.NotificationIcon
88
import net.thunderbird.feature.notification.api.ui.icon.NotificationIcons
9+
import net.thunderbird.feature.notification.api.ui.style.inAppNotificationStyle
910
import net.thunderbird.feature.notification.resources.api.Res
1011
import net.thunderbird.feature.notification.resources.api.notification_authentication_error_text
1112
import net.thunderbird.feature.notification.resources.api.notification_authentication_error_title
@@ -18,16 +19,25 @@ import org.jetbrains.compose.resources.getString
1819
*/
1920
@ConsistentCopyVisibility
2021
data class AuthenticationErrorNotification private constructor(
22+
val isIncomingServerError: Boolean,
23+
override val accountUuid: String,
24+
val accountNumber: Int,
2125
override val title: String,
2226
override val contentText: String?,
2327
override val channel: NotificationChannel,
2428
override val icon: NotificationIcon = NotificationIcons.AuthenticationError,
2529
) : AppNotification(), SystemNotification, InAppNotification {
2630
override val severity: NotificationSeverity = NotificationSeverity.Fatal
27-
override val actions: Set<NotificationAction> = setOf(
28-
NotificationAction.Retry,
29-
NotificationAction.UpdateServerSettings,
30-
)
31+
override val actions: Set<NotificationAction> = buildSet {
32+
val action = if (isIncomingServerError) {
33+
NotificationAction.UpdateIncomingServerSettings(accountUuid, accountNumber)
34+
} else {
35+
NotificationAction.UpdateOutgoingServerSettings(accountUuid, accountNumber)
36+
}
37+
add(action)
38+
add(NotificationAction.Tap(override = action))
39+
}
40+
override val inAppNotificationStyle = inAppNotificationStyle { bannerInline() }
3141

3242
override fun asLockscreenNotification(): SystemNotification.LockscreenNotification =
3343
SystemNotification.LockscreenNotification(
@@ -45,12 +55,17 @@ data class AuthenticationErrorNotification private constructor(
4555
suspend operator fun invoke(
4656
accountUuid: String,
4757
accountDisplayName: String,
58+
accountNumber: Int,
59+
isIncomingServerError: Boolean,
4860
): AuthenticationErrorNotification = AuthenticationErrorNotification(
49-
title = getString(
50-
resource = Res.string.notification_authentication_error_title,
61+
isIncomingServerError = isIncomingServerError,
62+
accountUuid = accountUuid,
63+
accountNumber = accountNumber,
64+
title = getString(resource = Res.string.notification_authentication_error_title),
65+
contentText = getString(
66+
resource = Res.string.notification_authentication_error_text,
5167
accountDisplayName,
5268
),
53-
contentText = getString(resource = Res.string.notification_authentication_error_text),
5469
channel = NotificationChannel.Miscellaneous(accountUuid = accountUuid),
5570
)
5671
}

feature/notification/api/src/commonMain/kotlin/net/thunderbird/feature/notification/api/content/CertificateErrorNotification.kt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,23 @@ import org.jetbrains.compose.resources.getString
2020
*/
2121
@ConsistentCopyVisibility
2222
data class CertificateErrorNotification private constructor(
23+
val isIncomingServerError: Boolean,
24+
override val accountUuid: String,
25+
val accountNumber: Int,
2326
override val title: String,
2427
override val contentText: String,
2528
val lockScreenTitle: String,
2629
override val channel: NotificationChannel,
2730
override val icon: NotificationIcon = NotificationIcons.CertificateError,
2831
) : AppNotification(), SystemNotification, InAppNotification {
2932
override val severity: NotificationSeverity = NotificationSeverity.Fatal
30-
override val actions: Set<NotificationAction> = setOf(NotificationAction.UpdateServerSettings)
33+
override val actions: Set<NotificationAction> = setOf(
34+
if (isIncomingServerError) {
35+
NotificationAction.UpdateIncomingServerSettings(accountUuid, accountNumber)
36+
} else {
37+
NotificationAction.UpdateOutgoingServerSettings(accountUuid, accountNumber)
38+
},
39+
)
3140

3241
override fun asLockscreenNotification(): SystemNotification.LockscreenNotification =
3342
SystemNotification.LockscreenNotification(
@@ -45,7 +54,12 @@ data class CertificateErrorNotification private constructor(
4554
suspend operator fun invoke(
4655
accountUuid: String,
4756
accountDisplayName: String,
57+
accountNumber: Int,
58+
isIncomingServerError: Boolean,
4859
): CertificateErrorNotification = CertificateErrorNotification(
60+
isIncomingServerError = isIncomingServerError,
61+
accountUuid = accountUuid,
62+
accountNumber = accountNumber,
4963
title = getString(resource = Res.string.notification_certificate_error_title, accountDisplayName),
5064
lockScreenTitle = getString(resource = Res.string.notification_certificate_error_public),
5165
contentText = getString(resource = Res.string.notification_certificate_error_text),

feature/notification/api/src/commonMain/kotlin/net/thunderbird/feature/notification/api/content/FailedToCreateNotification.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import org.jetbrains.compose.resources.getString
1818
*/
1919
@ConsistentCopyVisibility
2020
data class FailedToCreateNotification private constructor(
21+
override val accountUuid: String,
2122
override val title: String,
2223
override val contentText: String?,
2324
override val channel: NotificationChannel,
@@ -38,6 +39,7 @@ data class FailedToCreateNotification private constructor(
3839
accountUuid: String,
3940
failedNotification: AppNotification,
4041
): FailedToCreateNotification = FailedToCreateNotification(
42+
accountUuid = accountUuid,
4143
title = getString(resource = Res.string.notification_notify_error_title),
4244
contentText = getString(resource = Res.string.notification_notify_error_text),
4345
channel = NotificationChannel.Miscellaneous(accountUuid = accountUuid),

feature/notification/api/src/commonMain/kotlin/net/thunderbird/feature/notification/api/content/MailNotification.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ sealed class MailNotification : AppNotification(), SystemNotification {
3434
override val severity: NotificationSeverity = NotificationSeverity.Information
3535

3636
data class Fetching(
37+
override val accountUuid: String,
3738
override val title: String,
3839
override val accessibilityText: String,
3940
override val contentText: String?,
@@ -61,6 +62,7 @@ sealed class MailNotification : AppNotification(), SystemNotification {
6162
): Fetching {
6263
val title = getString(resource = Res.string.notification_bg_sync_title)
6364
return Fetching(
65+
accountUuid = accountUuid,
6466
title = title,
6567
accessibilityText = folderName?.let { folderName ->
6668
getString(
@@ -83,6 +85,7 @@ sealed class MailNotification : AppNotification(), SystemNotification {
8385
}
8486

8587
data class Sending(
88+
override val accountUuid: String,
8689
override val title: String,
8790
override val accessibilityText: String,
8891
override val contentText: String?,
@@ -106,6 +109,7 @@ sealed class MailNotification : AppNotification(), SystemNotification {
106109
accountUuid: String,
107110
accountDisplayName: String,
108111
): Sending = Sending(
112+
accountUuid = accountUuid,
109113
title = getString(resource = Res.string.notification_bg_send_title),
110114
accessibilityText = getString(
111115
resource = Res.string.notification_bg_send_ticker,
@@ -118,6 +122,7 @@ sealed class MailNotification : AppNotification(), SystemNotification {
118122
}
119123

120124
data class SendFailed(
125+
override val accountUuid: String,
121126
override val title: String,
122127
override val contentText: String?,
123128
override val channel: NotificationChannel,
@@ -143,6 +148,7 @@ sealed class MailNotification : AppNotification(), SystemNotification {
143148
accountUuid: String,
144149
exception: Exception,
145150
): SendFailed = SendFailed(
151+
accountUuid = accountUuid,
146152
title = getString(resource = Res.string.send_failure_subject),
147153
contentText = exception.rootCauseMassage,
148154
channel = NotificationChannel.Miscellaneous(accountUuid = accountUuid),
@@ -163,7 +169,7 @@ sealed class MailNotification : AppNotification(), SystemNotification {
163169
* @property group The notification group this notification belongs to, if any.
164170
*/
165171
data class NewMailSingleMail(
166-
val accountUuid: String,
172+
override val accountUuid: String,
167173
val accountName: String,
168174
val messagesNotificationChannelSuffix: String,
169175
val summary: String,
@@ -208,7 +214,7 @@ sealed class MailNotification : AppNotification(), SystemNotification {
208214
*/
209215
@ConsistentCopyVisibility
210216
data class NewMailSummaryMail private constructor(
211-
val accountUuid: String,
217+
override val accountUuid: String,
212218
val accountName: String,
213219
val messagesNotificationChannelSuffix: String,
214220
override val title: String,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package net.thunderbird.feature.notification.api.content
2+
3+
import androidx.annotation.Discouraged
4+
import kotlinx.coroutines.runBlocking
5+
6+
object NotificationFactoryCoroutineCompat {
7+
@JvmStatic
8+
@Discouraged("Should not be used outside a Java class.")
9+
fun <T> create(builder: suspend () -> T): T = runBlocking { builder() }
10+
}

0 commit comments

Comments
 (0)