diff --git a/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/atom/text/TextBodyMedium.kt b/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/atom/text/TextBodyMedium.kt
index e7bbc1b37da..65a89395c4a 100644
--- a/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/atom/text/TextBodyMedium.kt
+++ b/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/atom/text/TextBodyMedium.kt
@@ -4,6 +4,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import app.k9mail.core.ui.compose.theme2.MainTheme
@@ -17,6 +18,7 @@ fun TextBodyMedium(
textAlign: TextAlign? = null,
overflow: TextOverflow = TextOverflow.Clip,
maxLines: Int = Int.MAX_VALUE,
+ onTextLayout: (TextLayoutResult) -> Unit = {},
) {
Material3Text(
text = text,
@@ -26,6 +28,7 @@ fun TextBodyMedium(
overflow = overflow,
maxLines = maxLines,
style = MainTheme.typography.bodyMedium,
+ onTextLayout = onTextLayout,
)
}
@@ -37,6 +40,7 @@ fun TextBodyMedium(
textAlign: TextAlign? = null,
overflow: TextOverflow = TextOverflow.Clip,
maxLines: Int = Int.MAX_VALUE,
+ onTextLayout: (TextLayoutResult) -> Unit = {},
) {
Material3Text(
text = text,
@@ -46,5 +50,6 @@ fun TextBodyMedium(
overflow = overflow,
maxLines = maxLines,
style = MainTheme.typography.bodyMedium,
+ onTextLayout = onTextLayout,
)
}
diff --git a/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/organism/banner/inline/BannerInlineNotificationCard.kt b/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/organism/banner/inline/BannerInlineNotificationCard.kt
index 7995435ce55..921bb431022 100644
--- a/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/organism/banner/inline/BannerInlineNotificationCard.kt
+++ b/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/organism/banner/inline/BannerInlineNotificationCard.kt
@@ -14,6 +14,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.style.TextOverflow
import app.k9mail.core.ui.compose.designsystem.atom.card.CardColors
import app.k9mail.core.ui.compose.designsystem.atom.card.CardOutlined
@@ -54,6 +55,7 @@ internal fun BannerInlineNotificationCard(
border: BorderStroke = BannerNotificationCardDefaults.errorCardBorder(),
shape: Shape = BannerNotificationCardDefaults.bannerInlineShape,
behaviour: BannerInlineNotificationCardBehaviour = BannerNotificationCardDefaults.bannerInlineBehaviour,
+ onSupportingTextOverflow: (hasVisualOverflow: Boolean) -> Unit = {},
) {
val maxLines = when (behaviour) {
BannerInlineNotificationCardBehaviour.Clipped -> 2
@@ -74,6 +76,11 @@ internal fun BannerInlineNotificationCard(
supportingText = supportingText,
behaviour = behaviour,
maxLines = maxLines,
+ onTextOverflow = { hasVisualOverflow ->
+ if (behaviour == BannerInlineNotificationCardBehaviour.Clipped) {
+ onSupportingTextOverflow(hasVisualOverflow)
+ }
+ },
)
},
actions = actions,
@@ -186,11 +193,12 @@ private fun BannerInlineNotificationTitle(
}
@Composable
-fun BannerInlineNotificationSupportingText(
+private fun BannerInlineNotificationSupportingText(
supportingText: CharSequence,
behaviour: BannerInlineNotificationCardBehaviour,
maxLines: Int,
modifier: Modifier = Modifier,
+ onTextOverflow: (hasVisualOverflow: Boolean) -> Unit = {},
) {
val clippedSupportingText = remember(supportingText, behaviour) {
when (behaviour) {
@@ -200,12 +208,16 @@ fun BannerInlineNotificationSupportingText(
else -> supportingText
}
}
+ val onTextLayout = remember<(TextLayoutResult) -> Unit>(onTextOverflow) {
+ { textLayoutResult -> onTextOverflow(textLayoutResult.hasVisualOverflow) }
+ }
when (clippedSupportingText) {
is String -> TextBodyMedium(
text = clippedSupportingText,
maxLines = maxLines,
overflow = TextOverflow.Ellipsis,
modifier = modifier,
+ onTextLayout = onTextLayout,
)
is AnnotatedString -> TextBodyMedium(
@@ -213,6 +225,7 @@ fun BannerInlineNotificationSupportingText(
maxLines = maxLines,
overflow = TextOverflow.Ellipsis,
modifier = modifier,
+ onTextLayout = onTextLayout,
)
else -> TextBodyMedium(
@@ -220,6 +233,7 @@ fun BannerInlineNotificationSupportingText(
maxLines = maxLines,
overflow = TextOverflow.Ellipsis,
modifier = modifier,
+ onTextLayout = onTextLayout,
)
}
}
diff --git a/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/organism/banner/inline/ErrorBannerInlineNotificationCard.kt b/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/organism/banner/inline/ErrorBannerInlineNotificationCard.kt
index 25bb7da9a3f..ec31b098099 100644
--- a/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/organism/banner/inline/ErrorBannerInlineNotificationCard.kt
+++ b/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/organism/banner/inline/ErrorBannerInlineNotificationCard.kt
@@ -25,6 +25,7 @@ fun ErrorBannerInlineNotificationCard(
actions: @Composable RowScope.() -> Unit,
modifier: Modifier = Modifier,
behaviour: BannerInlineNotificationCardBehaviour = BannerNotificationCardDefaults.bannerInlineBehaviour,
+ onSupportingTextOverflow: (hasVisualOverflow: Boolean) -> Unit = {},
) {
BannerInlineNotificationCard(
icon = { Icon(imageVector = Icons.Outlined.Report) },
@@ -35,5 +36,6 @@ fun ErrorBannerInlineNotificationCard(
behaviour = behaviour,
colors = BannerNotificationCardDefaults.errorCardColors(),
border = BannerNotificationCardDefaults.errorCardBorder(),
+ onSupportingTextOverflow = onSupportingTextOverflow,
)
}
diff --git a/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/organism/banner/inline/InfoBannerInlineNotificationCard.kt b/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/organism/banner/inline/InfoBannerInlineNotificationCard.kt
index e835d7d18c8..4a536bfd563 100644
--- a/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/organism/banner/inline/InfoBannerInlineNotificationCard.kt
+++ b/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/organism/banner/inline/InfoBannerInlineNotificationCard.kt
@@ -25,6 +25,7 @@ fun InfoBannerInlineNotificationCard(
actions: @Composable RowScope.() -> Unit,
modifier: Modifier = Modifier,
behaviour: BannerInlineNotificationCardBehaviour = BannerNotificationCardDefaults.bannerInlineBehaviour,
+ onSupportingTextOverflow: (hasVisualOverflow: Boolean) -> Unit = {},
) {
BannerInlineNotificationCard(
icon = { Icon(imageVector = Icons.Outlined.Info) },
@@ -35,5 +36,6 @@ fun InfoBannerInlineNotificationCard(
behaviour = behaviour,
colors = BannerNotificationCardDefaults.infoCardColors(),
border = BannerNotificationCardDefaults.infoCardBorder(),
+ onSupportingTextOverflow = onSupportingTextOverflow,
)
}
diff --git a/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/organism/banner/inline/SuccessBannerInlineNotificationCard.kt b/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/organism/banner/inline/SuccessBannerInlineNotificationCard.kt
index 102c7c253d7..597bb929551 100644
--- a/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/organism/banner/inline/SuccessBannerInlineNotificationCard.kt
+++ b/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/organism/banner/inline/SuccessBannerInlineNotificationCard.kt
@@ -25,6 +25,7 @@ fun SuccessBannerInlineNotificationCard(
actions: @Composable RowScope.() -> Unit,
modifier: Modifier = Modifier,
behaviour: BannerInlineNotificationCardBehaviour = BannerNotificationCardDefaults.bannerInlineBehaviour,
+ onSupportingTextOverflow: (hasVisualOverflow: Boolean) -> Unit = {},
) {
BannerInlineNotificationCard(
icon = { Icon(imageVector = Icons.Outlined.CheckCircle) },
@@ -35,5 +36,6 @@ fun SuccessBannerInlineNotificationCard(
behaviour = behaviour,
colors = BannerNotificationCardDefaults.successCardColors(),
border = BannerNotificationCardDefaults.successCardBorder(),
+ onSupportingTextOverflow = onSupportingTextOverflow,
)
}
diff --git a/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/organism/banner/inline/WarningBannerInlineNotificationCard.kt b/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/organism/banner/inline/WarningBannerInlineNotificationCard.kt
index 24cded285b5..253456f35ad 100644
--- a/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/organism/banner/inline/WarningBannerInlineNotificationCard.kt
+++ b/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/organism/banner/inline/WarningBannerInlineNotificationCard.kt
@@ -26,6 +26,7 @@ fun WarningBannerInlineNotificationCard(
actions: @Composable RowScope.() -> Unit,
modifier: Modifier = Modifier,
behaviour: BannerInlineNotificationCardBehaviour = BannerNotificationCardDefaults.bannerInlineBehaviour,
+ onSupportingTextOverflow: (hasVisualOverflow: Boolean) -> Unit = {},
) {
BannerInlineNotificationCard(
icon = { Icon(imageVector = Icons.Outlined.Warning) },
@@ -36,5 +37,6 @@ fun WarningBannerInlineNotificationCard(
behaviour = behaviour,
colors = BannerNotificationCardDefaults.warningCardColors(),
border = BannerNotificationCardDefaults.warningCardBorder(),
+ onSupportingTextOverflow = onSupportingTextOverflow,
)
}
diff --git a/feature/notification/api/src/androidMain/kotlin/net/thunderbird/feature/notification/api/ui/BannerInlineNotificationListHost.kt b/feature/notification/api/src/androidMain/kotlin/net/thunderbird/feature/notification/api/ui/BannerInlineNotificationListHost.kt
index 24c23c79cf6..57fabfeba66 100644
--- a/feature/notification/api/src/androidMain/kotlin/net/thunderbird/feature/notification/api/ui/BannerInlineNotificationListHost.kt
+++ b/feature/notification/api/src/androidMain/kotlin/net/thunderbird/feature/notification/api/ui/BannerInlineNotificationListHost.kt
@@ -9,7 +9,9 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import app.k9mail.core.ui.compose.designsystem.molecule.notification.NotificationActionButton
import app.k9mail.core.ui.compose.designsystem.organism.banner.inline.BannerInlineNotificationCardBehaviour
@@ -21,6 +23,7 @@ import net.thunderbird.feature.notification.api.ui.BannerInlineNotificationListH
import net.thunderbird.feature.notification.api.ui.BannerInlineNotificationListHostDefaults.TEST_TAG_CHECK_ERROR_NOTIFICATIONS
import net.thunderbird.feature.notification.api.ui.BannerInlineNotificationListHostDefaults.TEST_TAG_CHECK_ERROR_NOTIFICATIONS_ACTION
import net.thunderbird.feature.notification.api.ui.BannerInlineNotificationListHostDefaults.TEST_TAG_HOST_PARENT
+import net.thunderbird.feature.notification.api.ui.BannerInlineNotificationListHostDefaults.TEST_TAG_LEARN_MORE_ACTION
import net.thunderbird.feature.notification.api.ui.action.NotificationAction
import net.thunderbird.feature.notification.api.ui.action.ResolvedNotificationActionButton
import net.thunderbird.feature.notification.api.ui.animation.bannerSlideInSlideOutAnimationSpec
@@ -28,6 +31,7 @@ import net.thunderbird.feature.notification.api.ui.host.InAppNotificationHostSta
import net.thunderbird.feature.notification.api.ui.host.visual.BannerInlineVisual
import net.thunderbird.feature.notification.resources.api.Res
import net.thunderbird.feature.notification.resources.api.banner_inline_notification_check_error_notifications
+import net.thunderbird.feature.notification.resources.api.banner_inline_notification_learn_more
import net.thunderbird.feature.notification.resources.api.banner_inline_notification_open_notifications
import net.thunderbird.feature.notification.resources.api.banner_inline_notification_some_messages_need_attention
import org.jetbrains.compose.resources.stringResource
@@ -105,25 +109,11 @@ private fun BannerInlineNotificationListHostLayout(
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.half),
) {
displayableNotifications.forEachIndexed { index, banner ->
- ErrorBannerInlineNotificationCard(
- title = banner.title,
- supportingText = banner.supportingText,
- actions = {
- banner.actions.forEachIndexed { actionIndex, action ->
- ResolvedNotificationActionButton(
- action = action,
- onActionClick = onActionClick,
- modifier = Modifier.testTagAsResourceId(
- tag = BannerInlineNotificationListHostDefaults.testTagBannerInlineListItemAction(
- index = index,
- actionIndex = actionIndex,
- ),
- ),
- )
- }
- },
- behaviour = BannerInlineNotificationCardBehaviour.Clipped,
- modifier = Modifier.animateContentSize(),
+ BannerInlineItem(
+ index = index,
+ banner = banner,
+ onActionClick = onActionClick,
+ onOpenErrorNotificationsClick = onOpenErrorNotificationsClick,
)
}
@@ -150,11 +140,53 @@ private fun BannerInlineNotificationListHostLayout(
}
}
+@Composable
+private fun BannerInlineItem(
+ index: Int,
+ banner: BannerInlineVisual,
+ onActionClick: (NotificationAction) -> Unit,
+ onOpenErrorNotificationsClick: () -> Unit,
+ modifier: Modifier = Modifier,
+) {
+ var hasSupportingTextOverflowed by remember { mutableStateOf(false) }
+ ErrorBannerInlineNotificationCard(
+ title = banner.title,
+ supportingText = banner.supportingText,
+ actions = {
+ if (hasSupportingTextOverflowed) {
+ NotificationActionButton(
+ text = stringResource(
+ resource = Res.string.banner_inline_notification_learn_more,
+ ),
+ onClick = onOpenErrorNotificationsClick,
+ modifier = Modifier.testTagAsResourceId(TEST_TAG_LEARN_MORE_ACTION),
+ )
+ }
+ banner.actions.forEachIndexed { actionIndex, action ->
+ ResolvedNotificationActionButton(
+ action = action,
+ onActionClick = onActionClick,
+ modifier = Modifier.testTagAsResourceId(
+ tag = BannerInlineNotificationListHostDefaults.testTagBannerInlineListItemAction(
+ index = index,
+ actionIndex = actionIndex,
+ ),
+ ),
+ )
+ }
+ },
+ behaviour = BannerInlineNotificationCardBehaviour.Clipped,
+ modifier = modifier.animateContentSize(),
+ onSupportingTextOverflow = { hasSupportingTextOverflowed = it },
+ )
+}
+
object BannerInlineNotificationListHostDefaults {
internal const val TEST_TAG_HOST_PARENT = "banner_inline_notification_host"
internal const val TEST_TAG_BANNER_INLINE_LIST = "banner_inline_notification_list"
internal const val TEST_TAG_CHECK_ERROR_NOTIFICATIONS = "check_notifications_composable"
internal const val TEST_TAG_CHECK_ERROR_NOTIFICATIONS_ACTION = "check_notifications_action"
+ internal const val TEST_TAG_LEARN_MORE_ACTION = "learn_more_action"
internal fun testTagBannerInlineListItemAction(index: Int, actionIndex: Int) =
"banner_inline_notification_list_item_action_${index}_$actionIndex"
diff --git a/feature/notification/api/src/commonMain/composeResources/values/strings.xml b/feature/notification/api/src/commonMain/composeResources/values/strings.xml
index d07dac24ffb..b7f17ab9b2f 100644
--- a/feature/notification/api/src/commonMain/composeResources/values/strings.xml
+++ b/feature/notification/api/src/commonMain/composeResources/values/strings.xml
@@ -60,5 +60,6 @@
Check Error Notifications
Some messages need your attention.
Open notifications
+ Learn more
View support article