diff --git a/app/src/main/kotlin/io/element/android/x/MainActivity.kt b/app/src/main/kotlin/io/element/android/x/MainActivity.kt index 99d940c5f5..ee277a40cf 100644 --- a/app/src/main/kotlin/io/element/android/x/MainActivity.kt +++ b/app/src/main/kotlin/io/element/android/x/MainActivity.kt @@ -19,6 +19,7 @@ package io.element.android.x import android.content.Intent import android.os.Bundle import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize @@ -31,7 +32,6 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalUriHandler import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen -import androidx.core.view.WindowCompat import com.bumble.appyx.core.integration.NodeHost import com.bumble.appyx.core.integrationpoint.NodeActivity import com.bumble.appyx.core.plugin.NodeReadyObserver @@ -60,7 +60,7 @@ class MainActivity : NodeActivity() { super.onCreate(savedInstanceState) appBindings = bindings() appBindings.lockScreenService().handleSecureFlag(this) - WindowCompat.setDecorFitsSystemWindows(window, false) + enableEdgeToEdge() setContent { MainContent(appBindings) } diff --git a/changelog.d/2581.misc b/changelog.d/2581.misc new file mode 100644 index 0000000000..6d38fdb682 --- /dev/null +++ b/changelog.d/2581.misc @@ -0,0 +1 @@ +Improve UI for notification permission screen in onboarding. diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt index 924824a2ec..b9f902202b 100644 --- a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt @@ -26,7 +26,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.systemBarsPadding +import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable @@ -40,8 +40,10 @@ import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.ftue.impl.R import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule -import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage +import io.element.android.libraries.designsystem.components.BigIcon +import io.element.android.libraries.designsystem.components.OnboardingBackground +import io.element.android.libraries.designsystem.components.PageTitle import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize @@ -62,8 +64,9 @@ fun NotificationsOptInView( HeaderFooterPage( modifier = modifier - .systemBarsPadding() + .statusBarsPadding() .fillMaxSize(), + background = { OnboardingBackground() }, header = { NotificationsOptInHeader(modifier = Modifier.padding(top = 60.dp, bottom = 12.dp)) }, footer = { NotificationsOptInFooter(state) }, ) { @@ -75,11 +78,11 @@ fun NotificationsOptInView( private fun NotificationsOptInHeader( modifier: Modifier = Modifier, ) { - IconTitleSubtitleMolecule( + PageTitle( modifier = modifier, title = stringResource(R.string.screen_notification_optin_title), - subTitle = stringResource(R.string.screen_notification_optin_subtitle), - iconImageVector = CompoundIcons.NotificationsSolid(), + subtitle = stringResource(R.string.screen_notification_optin_subtitle), + iconStyle = BigIcon.Style.Default(CompoundIcons.NotificationsSolid()), ) } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterPage.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterPage.kt index 6b99537dc9..b2cf88b8bc 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterPage.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterPage.kt @@ -34,6 +34,7 @@ import io.element.android.libraries.designsystem.theme.components.Text /** * @param modifier Classical modifier. + * @param background optional background component. * @param topBar optional topBar. * @param header optional header. * @param footer optional footer. @@ -42,6 +43,7 @@ import io.element.android.libraries.designsystem.theme.components.Text @Composable fun HeaderFooterPage( modifier: Modifier = Modifier, + background: @Composable () -> Unit = {}, topBar: @Composable () -> Unit = {}, header: @Composable () -> Unit = {}, footer: @Composable () -> Unit = {}, @@ -51,25 +53,28 @@ fun HeaderFooterPage( modifier = modifier, topBar = topBar, ) { padding -> - Column( - modifier = Modifier - .padding(padding) - .consumeWindowInsets(padding) - .padding(all = 20.dp), - ) { - // Header - header() - // Content + Box { + background() Column( modifier = Modifier - .weight(1f) - .fillMaxWidth(), + .padding(all = 20.dp) + .padding(padding) + .consumeWindowInsets(padding) ) { - content() - } - // Footer - Box(modifier = Modifier.padding(horizontal = 16.dp)) { - footer() + // Header + header() + // Content + Column( + modifier = Modifier + .weight(1f) + .fillMaxWidth(), + ) { + content() + } + // Footer + Box(modifier = Modifier.padding(horizontal = 16.dp)) { + footer() + } } } } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/OnboardingBackground.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/OnboardingBackground.kt new file mode 100644 index 0000000000..5dbced7417 --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/OnboardingBackground.kt @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.designsystem.components + +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.BlendMode +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.LinearGradientShader +import androidx.compose.ui.graphics.ShaderBrush +import androidx.compose.ui.unit.dp +import io.element.android.compound.theme.ElementTheme +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight + +/** + * Gradient background for FTUE (onboarding) screens. + */ +@Suppress("ModifierMissing") +@Composable +fun OnboardingBackground() { + Box(modifier = Modifier.fillMaxSize()) { + val isLightTheme = ElementTheme.isLightTheme + Canvas( + modifier = Modifier + .fillMaxWidth() + .height(220.dp) + .align(Alignment.BottomCenter) + ) { + val gradientBrush = ShaderBrush( + LinearGradientShader( + from = Offset(0f, size.height / 2f), + to = Offset(size.width, size.height / 2f), + colors = listOf( + Color(0xFF0DBDA8), + if (isLightTheme) Color(0xC90D5CBD) else Color(0xFF0D5CBD), + ) + ) + ) + val eraseBrush = ShaderBrush( + LinearGradientShader( + from = Offset(size.width / 2f, 0f), + to = Offset(size.width / 2f, size.height * 2f), + colors = listOf( + Color(0xFF000000), + Color(0x00000000), + ) + ) + ) + drawWithLayer { + drawRect(brush = gradientBrush, size = size) + drawRect(brush = gradientBrush, size = size, blendMode = BlendMode.Overlay) + drawRect(brush = eraseBrush, size = size, blendMode = BlendMode.DstOut) + } + } + } +} + +@PreviewsDayNight +@Composable +internal fun OnboardingBackgroundPreview() { + ElementPreview { + OnboardingBackground() + } +} diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.ftue.impl.notifications_NotificationsOptInView_null_NotificationsOptInView-Day-0_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.ftue.impl.notifications_NotificationsOptInView_null_NotificationsOptInView-Day-0_1_null_0,NEXUS_5,1.0,en].png index 72a7b12e96..62cab21d5f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.ftue.impl.notifications_NotificationsOptInView_null_NotificationsOptInView-Day-0_1_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.ftue.impl.notifications_NotificationsOptInView_null_NotificationsOptInView-Day-0_1_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bdc15ae26f55ce303a0eb02be9533d96f843bc0173560e487f601dd1a7c80670 -size 37180 +oid sha256:c769d9116f4173b7e97b9ecb73f14166e8ae21b968c13df779aaa4d4a12c7d8b +size 74024 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.ftue.impl.notifications_NotificationsOptInView_null_NotificationsOptInView-Night-0_2_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.ftue.impl.notifications_NotificationsOptInView_null_NotificationsOptInView-Night-0_2_null_0,NEXUS_5,1.0,en].png index eeafd919fa..63d4e3e7d8 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.ftue.impl.notifications_NotificationsOptInView_null_NotificationsOptInView-Night-0_2_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.ftue.impl.notifications_NotificationsOptInView_null_NotificationsOptInView-Night-0_2_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:56b977a2c064e7753d8af2739055b89f19fd5031e5e7df92d348e8ec5e8f2c29 -size 33718 +oid sha256:2c9c2253982480ccf9558f2a1b6eaac478ddb3f7b178b39648871eb74aa877b1 +size 66490 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_OnboardingBackground_null_OnboardingBackground-Day_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_OnboardingBackground_null_OnboardingBackground-Day_0_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..89932eb28e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_OnboardingBackground_null_OnboardingBackground-Day_0_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4df7164831cfda683ae0f312130f5e1222439000df456975e6c16567dbd4888d +size 56615 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_OnboardingBackground_null_OnboardingBackground-Night_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_OnboardingBackground_null_OnboardingBackground-Night_1_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..17cb751284 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_OnboardingBackground_null_OnboardingBackground-Night_1_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:070dd4ea130ee33d04b1d2e83facbc36be3126b21abfff5c78446fe6120f175b +size 51628