Skip to content

Commit b6ceb8c

Browse files
jmartinespElementBot
andauthored
Improve UI for notification permission screen in onboarding (#2660)
* Improve UI for notification permission screen in onboarding * Update screenshots --------- Co-authored-by: ElementBot <[email protected]>
1 parent 8e2f7a3 commit b6ceb8c

File tree

9 files changed

+129
-28
lines changed

9 files changed

+129
-28
lines changed

app/src/main/kotlin/io/element/android/x/MainActivity.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package io.element.android.x
1919
import android.content.Intent
2020
import android.os.Bundle
2121
import androidx.activity.compose.setContent
22+
import androidx.activity.enableEdgeToEdge
2223
import androidx.compose.foundation.background
2324
import androidx.compose.foundation.layout.Box
2425
import androidx.compose.foundation.layout.fillMaxSize
@@ -31,7 +32,6 @@ import androidx.compose.runtime.remember
3132
import androidx.compose.ui.Modifier
3233
import androidx.compose.ui.platform.LocalUriHandler
3334
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
34-
import androidx.core.view.WindowCompat
3535
import com.bumble.appyx.core.integration.NodeHost
3636
import com.bumble.appyx.core.integrationpoint.NodeActivity
3737
import com.bumble.appyx.core.plugin.NodeReadyObserver
@@ -60,7 +60,7 @@ class MainActivity : NodeActivity() {
6060
super.onCreate(savedInstanceState)
6161
appBindings = bindings()
6262
appBindings.lockScreenService().handleSecureFlag(this)
63-
WindowCompat.setDecorFitsSystemWindows(window, false)
63+
enableEdgeToEdge()
6464
setContent {
6565
MainContent(appBindings)
6666
}

changelog.d/2581.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Improve UI for notification permission screen in onboarding.

features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import androidx.compose.foundation.layout.fillMaxSize
2626
import androidx.compose.foundation.layout.fillMaxWidth
2727
import androidx.compose.foundation.layout.height
2828
import androidx.compose.foundation.layout.padding
29-
import androidx.compose.foundation.layout.systemBarsPadding
29+
import androidx.compose.foundation.layout.statusBarsPadding
3030
import androidx.compose.foundation.shape.CircleShape
3131
import androidx.compose.foundation.shape.RoundedCornerShape
3232
import androidx.compose.runtime.Composable
@@ -40,8 +40,10 @@ import io.element.android.compound.theme.ElementTheme
4040
import io.element.android.compound.tokens.generated.CompoundIcons
4141
import io.element.android.features.ftue.impl.R
4242
import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule
43-
import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule
4443
import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage
44+
import io.element.android.libraries.designsystem.components.BigIcon
45+
import io.element.android.libraries.designsystem.components.OnboardingBackground
46+
import io.element.android.libraries.designsystem.components.PageTitle
4547
import io.element.android.libraries.designsystem.components.avatar.Avatar
4648
import io.element.android.libraries.designsystem.components.avatar.AvatarData
4749
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
@@ -62,8 +64,9 @@ fun NotificationsOptInView(
6264

6365
HeaderFooterPage(
6466
modifier = modifier
65-
.systemBarsPadding()
67+
.statusBarsPadding()
6668
.fillMaxSize(),
69+
background = { OnboardingBackground() },
6770
header = { NotificationsOptInHeader(modifier = Modifier.padding(top = 60.dp, bottom = 12.dp)) },
6871
footer = { NotificationsOptInFooter(state) },
6972
) {
@@ -75,11 +78,11 @@ fun NotificationsOptInView(
7578
private fun NotificationsOptInHeader(
7679
modifier: Modifier = Modifier,
7780
) {
78-
IconTitleSubtitleMolecule(
81+
PageTitle(
7982
modifier = modifier,
8083
title = stringResource(R.string.screen_notification_optin_title),
81-
subTitle = stringResource(R.string.screen_notification_optin_subtitle),
82-
iconImageVector = CompoundIcons.NotificationsSolid(),
84+
subtitle = stringResource(R.string.screen_notification_optin_subtitle),
85+
iconStyle = BigIcon.Style.Default(CompoundIcons.NotificationsSolid()),
8386
)
8487
}
8588

libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterPage.kt

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import io.element.android.libraries.designsystem.theme.components.Text
3434

3535
/**
3636
* @param modifier Classical modifier.
37+
* @param background optional background component.
3738
* @param topBar optional topBar.
3839
* @param header optional header.
3940
* @param footer optional footer.
@@ -42,6 +43,7 @@ import io.element.android.libraries.designsystem.theme.components.Text
4243
@Composable
4344
fun HeaderFooterPage(
4445
modifier: Modifier = Modifier,
46+
background: @Composable () -> Unit = {},
4547
topBar: @Composable () -> Unit = {},
4648
header: @Composable () -> Unit = {},
4749
footer: @Composable () -> Unit = {},
@@ -51,25 +53,28 @@ fun HeaderFooterPage(
5153
modifier = modifier,
5254
topBar = topBar,
5355
) { padding ->
54-
Column(
55-
modifier = Modifier
56-
.padding(padding)
57-
.consumeWindowInsets(padding)
58-
.padding(all = 20.dp),
59-
) {
60-
// Header
61-
header()
62-
// Content
56+
Box {
57+
background()
6358
Column(
6459
modifier = Modifier
65-
.weight(1f)
66-
.fillMaxWidth(),
60+
.padding(all = 20.dp)
61+
.padding(padding)
62+
.consumeWindowInsets(padding)
6763
) {
68-
content()
69-
}
70-
// Footer
71-
Box(modifier = Modifier.padding(horizontal = 16.dp)) {
72-
footer()
64+
// Header
65+
header()
66+
// Content
67+
Column(
68+
modifier = Modifier
69+
.weight(1f)
70+
.fillMaxWidth(),
71+
) {
72+
content()
73+
}
74+
// Footer
75+
Box(modifier = Modifier.padding(horizontal = 16.dp)) {
76+
footer()
77+
}
7378
}
7479
}
7580
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright (c) 2024 New Vector Ltd
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.element.android.libraries.designsystem.components
18+
19+
import androidx.compose.foundation.Canvas
20+
import androidx.compose.foundation.layout.Box
21+
import androidx.compose.foundation.layout.fillMaxSize
22+
import androidx.compose.foundation.layout.fillMaxWidth
23+
import androidx.compose.foundation.layout.height
24+
import androidx.compose.runtime.Composable
25+
import androidx.compose.ui.Alignment
26+
import androidx.compose.ui.Modifier
27+
import androidx.compose.ui.geometry.Offset
28+
import androidx.compose.ui.graphics.BlendMode
29+
import androidx.compose.ui.graphics.Color
30+
import androidx.compose.ui.graphics.LinearGradientShader
31+
import androidx.compose.ui.graphics.ShaderBrush
32+
import androidx.compose.ui.unit.dp
33+
import io.element.android.compound.theme.ElementTheme
34+
import io.element.android.libraries.designsystem.preview.ElementPreview
35+
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
36+
37+
/**
38+
* Gradient background for FTUE (onboarding) screens.
39+
*/
40+
@Suppress("ModifierMissing")
41+
@Composable
42+
fun OnboardingBackground() {
43+
Box(modifier = Modifier.fillMaxSize()) {
44+
val isLightTheme = ElementTheme.isLightTheme
45+
Canvas(
46+
modifier = Modifier
47+
.fillMaxWidth()
48+
.height(220.dp)
49+
.align(Alignment.BottomCenter)
50+
) {
51+
val gradientBrush = ShaderBrush(
52+
LinearGradientShader(
53+
from = Offset(0f, size.height / 2f),
54+
to = Offset(size.width, size.height / 2f),
55+
colors = listOf(
56+
Color(0xFF0DBDA8),
57+
if (isLightTheme) Color(0xC90D5CBD) else Color(0xFF0D5CBD),
58+
)
59+
)
60+
)
61+
val eraseBrush = ShaderBrush(
62+
LinearGradientShader(
63+
from = Offset(size.width / 2f, 0f),
64+
to = Offset(size.width / 2f, size.height * 2f),
65+
colors = listOf(
66+
Color(0xFF000000),
67+
Color(0x00000000),
68+
)
69+
)
70+
)
71+
drawWithLayer {
72+
drawRect(brush = gradientBrush, size = size)
73+
drawRect(brush = gradientBrush, size = size, blendMode = BlendMode.Overlay)
74+
drawRect(brush = eraseBrush, size = size, blendMode = BlendMode.DstOut)
75+
}
76+
}
77+
}
78+
}
79+
80+
@PreviewsDayNight
81+
@Composable
82+
internal fun OnboardingBackgroundPreview() {
83+
ElementPreview {
84+
OnboardingBackground()
85+
}
86+
}
Lines changed: 2 additions & 2 deletions
Loading
Lines changed: 2 additions & 2 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)