diff --git a/.idea/dictionaries/shared.xml b/.idea/dictionaries/shared.xml
index 216a8cbd20..7c04ccd5e7 100644
--- a/.idea/dictionaries/shared.xml
+++ b/.idea/dictionaries/shared.xml
@@ -2,6 +2,8 @@
backstack
+ kover
+ onboarding
textfields
diff --git a/.maestro/tests/account/login.yaml b/.maestro/tests/account/login.yaml
index 3733b2b047..59cc0980e4 100644
--- a/.maestro/tests/account/login.yaml
+++ b/.maestro/tests/account/login.yaml
@@ -1,6 +1,6 @@
appId: ${APP_ID}
---
-- tapOn: "Get started"
+- tapOn: "Sign in manually"
- runFlow: ../assertions/assertLoginDisplayed.yaml
- takeScreenshot: build/maestro/100-SignIn
- runFlow: changeServer.yaml
diff --git a/.maestro/tests/assertions/assertInitDisplayed.yaml b/.maestro/tests/assertions/assertInitDisplayed.yaml
index 0bcef846c6..b68412be84 100644
--- a/.maestro/tests/assertions/assertInitDisplayed.yaml
+++ b/.maestro/tests/assertions/assertInitDisplayed.yaml
@@ -1,5 +1,5 @@
appId: ${APP_ID}
---
- extendedWaitUntil:
- visible: "Own your conversations."
+ visible: "Communicate and collaborate securely"
timeout: 10_000
diff --git a/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt
index 5447327152..78c39f93e6 100644
--- a/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt
+++ b/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt
@@ -93,10 +93,10 @@ class RootFlowNode @AssistedInject constructor(
if (isLoggedIn) {
tryToRestoreLatestSession(
onSuccess = { switchToLoggedInFlow(it) },
- onFailure = { switchToLogoutFlow() }
+ onFailure = { switchToNotLoggedInFlow() }
)
} else {
- switchToLogoutFlow()
+ switchToNotLoggedInFlow()
}
}
.launchIn(lifecycleScope)
@@ -106,7 +106,7 @@ class RootFlowNode @AssistedInject constructor(
backstack.safeRoot(NavTarget.LoggedInFlow(sessionId))
}
- private fun switchToLogoutFlow() {
+ private fun switchToNotLoggedInFlow() {
matrixClientsHolder.removeAll()
backstack.safeRoot(NavTarget.NotLoggedInFlow)
}
diff --git a/build.gradle.kts b/build.gradle.kts
index 8657aa7b4c..3fe16b498d 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -203,6 +203,8 @@ koverMerged {
includes += "*Presenter"
excludes += "*Fake*Presenter"
excludes += "io.element.android.appnav.loggedin.LoggedInPresenter$*"
+ // Too small presenter, cannot reach the threshold.
+ excludes += "io.element.android.features.onboarding.impl.OnBoardingPresenter"
}
bound {
minValue = 90
diff --git a/features/onboarding/impl/build.gradle.kts b/features/onboarding/impl/build.gradle.kts
index 22480bfd1b..86b4d1ede9 100644
--- a/features/onboarding/impl/build.gradle.kts
+++ b/features/onboarding/impl/build.gradle.kts
@@ -40,8 +40,6 @@ dependencies {
implementation(projects.libraries.testtags)
implementation(projects.libraries.uiStrings)
implementation(projects.libraries.androidutils)
- implementation(libs.accompanist.pager)
- implementation(libs.accompanist.pagerindicator)
api(projects.features.onboarding.api)
ksp(libs.showkase.processor)
diff --git a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/SplashCarouselData.kt b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingConfig.kt
similarity index 67%
rename from features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/SplashCarouselData.kt
rename to features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingConfig.kt
index c4674b3ead..de164386b3 100644
--- a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/SplashCarouselData.kt
+++ b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingConfig.kt
@@ -16,16 +16,7 @@
package io.element.android.features.onboarding.impl
-import androidx.annotation.DrawableRes
-import androidx.annotation.StringRes
-
-data class SplashCarouselData(
- val items: List-
-) {
- data class Item(
- @StringRes val title: Int,
- @StringRes val body: Int,
- @DrawableRes val image: Int,
- @DrawableRes val pageBackground: Int
- )
+object OnBoardingConfig {
+ const val canLoginWithQrCode = false
+ const val canCreateAccount = false
}
diff --git a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingNode.kt b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingNode.kt
index a6cb0a3b49..a081c0b7ab 100644
--- a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingNode.kt
+++ b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingNode.kt
@@ -32,6 +32,7 @@ import io.element.android.libraries.di.AppScope
class OnBoardingNode @AssistedInject constructor(
@Assisted buildContext: BuildContext,
@Assisted plugins: List,
+ private val presenter: OnBoardingPresenter,
) : Node(
buildContext = buildContext,
plugins = plugins
@@ -47,10 +48,11 @@ class OnBoardingNode @AssistedInject constructor(
@Composable
override fun View(modifier: Modifier) {
- OnBoardingScreen(
+ val state = presenter.present()
+ OnBoardingView(
+ state = state,
modifier = modifier,
- onSignIn = this::onSignIn,
- onSignUp = this::onSignUp
+ onSignIn = ::onSignIn,
)
}
}
diff --git a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenter.kt b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenter.kt
new file mode 100644
index 0000000000..48a360e6c9
--- /dev/null
+++ b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenter.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2023 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.features.onboarding.impl
+
+import androidx.compose.runtime.Composable
+import io.element.android.libraries.architecture.Presenter
+import javax.inject.Inject
+
+/**
+ * Note: this Presenter is ignored regarding code coverage because it cannot reach the coverage threshold.
+ * When this presenter get more code in it, please remove the ignore rule in the kover configuration.
+ */
+class OnBoardingPresenter @Inject constructor(
+) : Presenter {
+ @Composable
+ override fun present(): OnBoardingState {
+ return OnBoardingState(
+ canLoginWithQrCode = OnBoardingConfig.canLoginWithQrCode,
+ canCreateAccount = OnBoardingConfig.canCreateAccount,
+ )
+ }
+}
diff --git a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingScreen.kt b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingScreen.kt
deleted file mode 100644
index 8694865938..0000000000
--- a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingScreen.kt
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (c) 2023 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.features.onboarding.impl
-
-import androidx.compose.foundation.Image
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.systemBarsPadding
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.runtime.snapshotFlow
-import androidx.compose.ui.Alignment.Companion.CenterHorizontally
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.res.painterResource
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.text.style.TextAlign
-import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.unit.sp
-import com.google.accompanist.pager.HorizontalPager
-import com.google.accompanist.pager.HorizontalPagerIndicator
-import com.google.accompanist.pager.rememberPagerState
-import io.element.android.libraries.designsystem.preview.ElementPreviewDark
-import io.element.android.libraries.designsystem.preview.ElementPreviewLight
-import io.element.android.libraries.designsystem.theme.components.Button
-import io.element.android.libraries.designsystem.theme.components.Text
-import io.element.android.libraries.testtags.TestTags
-import io.element.android.libraries.testtags.testTag
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.launch
-
-@Composable
-fun OnBoardingScreen(
- modifier: Modifier = Modifier,
- onPageChanged: (Int) -> Unit = {},
- onSignUp: () -> Unit = {},
- onSignIn: () -> Unit = {},
-) {
- val carrouselData = remember { SplashCarouselDataFactory().create() }
- val nbOfPages = carrouselData.items.size
- var key by remember { mutableStateOf(false) }
- Box(
- modifier = modifier
- .fillMaxSize()
- .systemBarsPadding()
- .padding(vertical = 16.dp)
- ) {
- Column(
- modifier = Modifier.fillMaxSize(),
- ) {
- val pagerState = rememberPagerState()
- LaunchedEffect(key) {
- launch {
- delay(3_000)
- pagerState.animateScrollToPage((pagerState.currentPage + 1) % nbOfPages)
- // https://stackoverflow.com/questions/73714228/accompanist-pager-animatescrolltopage-doesnt-scroll-to-next-page-correctly
- key = !key
- }
- }
- LaunchedEffect(pagerState) {
- // Collect from the pager state a snapshotFlow reading the currentPage
- snapshotFlow { pagerState.currentPage }.collect { page ->
- onPageChanged(page)
- }
- }
- HorizontalPager(
- modifier = Modifier.weight(1f),
- count = nbOfPages,
- state = pagerState,
- ) { page ->
- // Our page content
- OnBoardingPage(carrouselData.items[page])
- }
- HorizontalPagerIndicator(
- pagerState = pagerState,
- modifier = Modifier
- .align(CenterHorizontally)
- .padding(16.dp),
- )
- Button(
- onClick = {
- onSignIn()
- },
- enabled = true,
- modifier = Modifier
- .align(CenterHorizontally)
- .testTag(TestTags.onBoardingSignIn)
- .padding(top = 16.dp)
- ) {
- Text(text = stringResource(id = R.string.login_splash_submit))
- }
- }
- }
-}
-
-@Composable
-fun OnBoardingPage(
- item: SplashCarouselData.Item,
- modifier: Modifier = Modifier,
-) {
- Box(
- modifier = modifier,
- ) {
- /*
- Image(
- painterResource(id = item.pageBackground),
- contentDescription = null,
- modifier = Modifier.fillMaxSize()
- )
- */
- Column(
- modifier = Modifier.padding(vertical = 16.dp, horizontal = 32.dp)
- ) {
- Image(
- painterResource(id = item.image),
- contentDescription = null,
- modifier = Modifier
- .align(CenterHorizontally)
- .size(192.dp)
- .padding(16.dp)
- )
- Text(
- text = stringResource(id = item.title),
- modifier = Modifier
- .fillMaxWidth()
- .align(CenterHorizontally)
- .padding(8.dp),
- textAlign = TextAlign.Center,
- fontWeight = FontWeight.Bold,
- color = MaterialTheme.colorScheme.primary,
- fontSize = 24.sp,
- )
- Text(
- text = stringResource(id = item.body),
- modifier = Modifier
- .fillMaxWidth()
- .align(CenterHorizontally),
- textAlign = TextAlign.Center,
- color = MaterialTheme.colorScheme.primary,
- )
- }
- }
-}
-
-@Preview
-@Composable
-internal fun OnBoardingScreenLightPreview() =
- ElementPreviewLight { ContentToPreview() }
-
-@Preview
-@Composable
-internal fun OnBoardingScreenDarkPreview() =
- ElementPreviewDark { ContentToPreview() }
-
-@Composable
-private fun ContentToPreview() {
- OnBoardingScreen()
-}
diff --git a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingState.kt b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingState.kt
new file mode 100644
index 0000000000..88215c0c1e
--- /dev/null
+++ b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingState.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2023 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.features.onboarding.impl
+
+data class OnBoardingState(
+ val canLoginWithQrCode: Boolean,
+ val canCreateAccount: Boolean,
+)
diff --git a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingStateProvider.kt b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingStateProvider.kt
new file mode 100644
index 0000000000..1c60a56018
--- /dev/null
+++ b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingStateProvider.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2023 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.features.onboarding.impl
+
+import androidx.compose.ui.tooling.preview.PreviewParameterProvider
+
+open class OnBoardingStateProvider : PreviewParameterProvider {
+ override val values: Sequence
+ get() = sequenceOf(
+ anOnBoardingState(),
+ anOnBoardingState(canLoginWithQrCode = true),
+ anOnBoardingState(canCreateAccount = true),
+ anOnBoardingState(canLoginWithQrCode = true, canCreateAccount = true),
+ )
+}
+
+fun anOnBoardingState(
+ canLoginWithQrCode: Boolean = false,
+ canCreateAccount: Boolean = false
+) = OnBoardingState(
+ canLoginWithQrCode = canLoginWithQrCode,
+ canCreateAccount = canCreateAccount
+)
diff --git a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingView.kt b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingView.kt
new file mode 100644
index 0000000000..fd736dc0e5
--- /dev/null
+++ b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingView.kt
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2023 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.features.onboarding.impl
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.width
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.QrCode
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment.Companion.CenterHorizontally
+import androidx.compose.ui.BiasAlignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.ColorFilter
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.tooling.preview.PreviewParameter
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import io.element.android.libraries.designsystem.atomic.pages.OnBoardingPage
+import io.element.android.libraries.designsystem.preview.ElementPreviewDark
+import io.element.android.libraries.designsystem.preview.ElementPreviewLight
+import io.element.android.libraries.designsystem.theme.components.Button
+import io.element.android.libraries.designsystem.theme.components.Icon
+import io.element.android.libraries.designsystem.theme.components.OutlinedButton
+import io.element.android.libraries.designsystem.theme.components.Text
+import io.element.android.libraries.testtags.TestTags
+import io.element.android.libraries.testtags.testTag
+
+// Ref: https://www.figma.com/file/o9p34zmiuEpZRyvZXJZAYL/FTUE?type=design&node-id=133-5427&t=5SHVppfYzjvkEywR-0
+@Composable
+fun OnBoardingView(
+ state: OnBoardingState,
+ modifier: Modifier = Modifier,
+ onSignInWithQrCode: () -> Unit = {},
+ onSignIn: () -> Unit = {},
+ onCreateAccount: () -> Unit = {},
+) {
+ OnBoardingPage(
+ modifier = modifier,
+ footer = {
+ OnBoardingButtons(
+ state = state,
+ onSignInWithQrCode = onSignInWithQrCode,
+ onSignIn = onSignIn,
+ onCreateAccount = onCreateAccount,
+ )
+ }
+ ) {
+ OnBoardingContent()
+ }
+}
+
+@Composable
+private fun OnBoardingContent(modifier: Modifier = Modifier) {
+ Box(
+ modifier = modifier.fillMaxSize(),
+ contentAlignment = BiasAlignment(
+ horizontalBias = 0f,
+ verticalBias = -0.2f
+ )
+ ) {
+ Column(
+ modifier = Modifier
+ .fillMaxWidth(),
+ horizontalAlignment = CenterHorizontally,
+ ) {
+ Image(
+ painter = painterResource(id = R.drawable.element_logo),
+ contentDescription = null,
+ )
+ Image(
+ modifier = Modifier.padding(top = 14.dp),
+ painter = painterResource(id = R.drawable.element),
+ colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.primary),
+ contentDescription = null,
+ )
+ Text(
+ modifier = Modifier.padding(top = 24.dp),
+ text = stringResource(id = R.string.screen_onboarding_subtitle),
+ color = MaterialTheme.colorScheme.secondary,
+ fontSize = 20.sp,
+ textAlign = TextAlign.Center
+ )
+ }
+ }
+}
+
+@Composable
+private fun OnBoardingButtons(
+ state: OnBoardingState,
+ onSignInWithQrCode: () -> Unit,
+ onSignIn: () -> Unit,
+ onCreateAccount: () -> Unit,
+ modifier: Modifier = Modifier,
+) {
+ Column(
+ modifier = modifier
+ .fillMaxWidth(),
+ horizontalAlignment = CenterHorizontally,
+ verticalArrangement = Arrangement.spacedBy(16.dp)
+ ) {
+ if (state.canLoginWithQrCode) {
+ Button(
+ onClick = {
+ onSignInWithQrCode()
+ },
+ enabled = true,
+ modifier = Modifier
+ .fillMaxWidth()
+ ) {
+ Icon(
+ imageVector = Icons.Default.QrCode, contentDescription = null,
+ tint = MaterialTheme.colorScheme.onPrimary
+ )
+ Spacer(Modifier.width(14.dp))
+ Text(text = stringResource(id = R.string.screen_onboarding_sign_in_with_qr_code))
+ }
+ }
+ Button(
+ onClick = {
+ onSignIn()
+ },
+ enabled = true,
+ modifier = Modifier
+ .fillMaxWidth()
+ .testTag(TestTags.onBoardingSignIn)
+ ) {
+ Text(text = stringResource(id = R.string.screen_onboarding_sign_in_manually))
+ }
+ if (state.canCreateAccount) {
+ OutlinedButton(
+ onClick = {
+ onCreateAccount()
+ },
+ enabled = true,
+ modifier = Modifier
+ .fillMaxWidth()
+ ) {
+ Text(text = stringResource(id = R.string.screen_onboarding_sign_up))
+ }
+ }
+ }
+}
+
+@Preview
+@Composable
+internal fun OnBoardingScreenLightPreview(@PreviewParameter(OnBoardingStateProvider::class) state: OnBoardingState) =
+ ElementPreviewLight { ContentToPreview(state) }
+
+@Preview
+@Composable
+internal fun OnBoardingScreenDarkPreview(@PreviewParameter(OnBoardingStateProvider::class) state: OnBoardingState) =
+ ElementPreviewDark { ContentToPreview(state) }
+
+@Composable
+private fun ContentToPreview(state: OnBoardingState) {
+ OnBoardingView(state)
+}
diff --git a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/SplashCarouselDataFactory.kt b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/SplashCarouselDataFactory.kt
deleted file mode 100644
index 5068bda82b..0000000000
--- a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/SplashCarouselDataFactory.kt
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2023 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.features.onboarding.impl
-
-import androidx.annotation.DrawableRes
-
-class SplashCarouselDataFactory {
- fun create(): SplashCarouselData {
- val lightTheme = true
-
- fun background(@DrawableRes lightDrawable: Int) =
- if (lightTheme) lightDrawable else R.drawable.bg_color_background
-
- fun hero(@DrawableRes lightDrawable: Int, @DrawableRes darkDrawable: Int) =
- if (lightTheme) lightDrawable else darkDrawable
-
- return SplashCarouselData(
- listOf(
- SplashCarouselData.Item(
- R.string.ftue_auth_carousel_secure_title,
- R.string.ftue_auth_carousel_secure_body,
- hero(
- R.drawable.ic_splash_conversations,
- R.drawable.ic_splash_conversations_dark
- ),
- background(R.drawable.bg_carousel_page_1)
- ),
- SplashCarouselData.Item(
- R.string.ftue_auth_carousel_control_title,
- R.string.ftue_auth_carousel_control_body,
- hero(R.drawable.ic_splash_control, R.drawable.ic_splash_control_dark),
- background(R.drawable.bg_carousel_page_2)
- ),
- SplashCarouselData.Item(
- R.string.ftue_auth_carousel_encrypted_title,
- R.string.ftue_auth_carousel_encrypted_body,
- hero(R.drawable.ic_splash_secure, R.drawable.ic_splash_secure_dark),
- background(R.drawable.bg_carousel_page_3)
- ),
- SplashCarouselData.Item(
- collaborationTitle(),
- R.string.ftue_auth_carousel_workplace_body,
- hero(
- R.drawable.ic_splash_collaboration,
- R.drawable.ic_splash_collaboration_dark
- ),
- background(R.drawable.bg_carousel_page_4)
- )
- )
- )
- }
-
- private fun collaborationTitle(): Int {
- return when {
- true -> R.string.cut_the_slack_from_teams
- else -> R.string.ftue_auth_carousel_workplace_title
- }
- }
-}
diff --git a/features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_collaboration.webp b/features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_collaboration.webp
deleted file mode 100644
index 7042e030d0..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_collaboration.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_collaboration_dark.webp b/features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_collaboration_dark.webp
deleted file mode 100644
index 6e4297183a..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_collaboration_dark.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_control.webp b/features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_control.webp
deleted file mode 100644
index 82c04e402b..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_control.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_control_dark.webp b/features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_control_dark.webp
deleted file mode 100644
index 0d0c6ad78b..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_control_dark.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_conversations.webp b/features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_conversations.webp
deleted file mode 100644
index ee9604c1f1..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_conversations.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_conversations_dark.webp b/features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_conversations_dark.webp
deleted file mode 100644
index c5cdf4e6fe..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_conversations_dark.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_secure.webp b/features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_secure.webp
deleted file mode 100644
index a880031ada..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_secure.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_secure_dark.webp b/features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_secure_dark.webp
deleted file mode 100644
index 65ef9f35ff..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_secure_dark.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_collaboration.webp b/features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_collaboration.webp
deleted file mode 100644
index d32d9f6026..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_collaboration.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_collaboration_dark.webp b/features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_collaboration_dark.webp
deleted file mode 100644
index 04af9e2db4..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_collaboration_dark.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_control.webp b/features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_control.webp
deleted file mode 100644
index 972d91d5d0..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_control.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_control_dark.webp b/features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_control_dark.webp
deleted file mode 100644
index cbbea1ae87..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_control_dark.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_conversations.webp b/features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_conversations.webp
deleted file mode 100644
index 4057edfc66..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_conversations.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_conversations_dark.webp b/features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_conversations_dark.webp
deleted file mode 100644
index e3b7f22c1a..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_conversations_dark.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_secure.webp b/features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_secure.webp
deleted file mode 100644
index b8c772bde2..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_secure.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_secure_dark.webp b/features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_secure_dark.webp
deleted file mode 100644
index d4c1f97652..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_secure_dark.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_collaboration.webp b/features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_collaboration.webp
deleted file mode 100644
index 8feed1f9f9..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_collaboration.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_collaboration_dark.webp b/features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_collaboration_dark.webp
deleted file mode 100644
index 02e44fbf44..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_collaboration_dark.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_control.webp b/features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_control.webp
deleted file mode 100644
index 99d4c4049d..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_control.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_control_dark.webp b/features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_control_dark.webp
deleted file mode 100644
index 9afa384f27..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_control_dark.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_conversations.webp b/features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_conversations.webp
deleted file mode 100644
index 99a4c0c6f5..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_conversations.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_conversations_dark.webp b/features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_conversations_dark.webp
deleted file mode 100644
index 361981eec7..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_conversations_dark.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_secure.webp b/features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_secure.webp
deleted file mode 100644
index 114421453e..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_secure.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_secure_dark.webp b/features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_secure_dark.webp
deleted file mode 100644
index 737bcbdf17..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_secure_dark.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_collaboration.webp b/features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_collaboration.webp
deleted file mode 100644
index 1dc31f6447..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_collaboration.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_collaboration_dark.webp b/features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_collaboration_dark.webp
deleted file mode 100644
index 943f2b9ba8..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_collaboration_dark.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_control.webp b/features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_control.webp
deleted file mode 100644
index 9375475513..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_control.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_control_dark.webp b/features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_control_dark.webp
deleted file mode 100644
index 905851dc26..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_control_dark.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_conversations.webp b/features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_conversations.webp
deleted file mode 100644
index 0d669312f5..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_conversations.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_conversations_dark.webp b/features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_conversations_dark.webp
deleted file mode 100644
index c5c4b2ccdd..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_conversations_dark.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_secure.webp b/features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_secure.webp
deleted file mode 100644
index 6a2a3fda56..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_secure.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_secure_dark.webp b/features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_secure_dark.webp
deleted file mode 100644
index b792cb16ea..0000000000
Binary files a/features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_secure_dark.webp and /dev/null differ
diff --git a/features/onboarding/impl/src/main/res/drawable/bg_carousel_page_1.xml b/features/onboarding/impl/src/main/res/drawable/bg_carousel_page_1.xml
deleted file mode 100644
index 03414760f5..0000000000
--- a/features/onboarding/impl/src/main/res/drawable/bg_carousel_page_1.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
-
diff --git a/features/onboarding/impl/src/main/res/drawable/bg_carousel_page_2.xml b/features/onboarding/impl/src/main/res/drawable/bg_carousel_page_2.xml
deleted file mode 100644
index 216f37c056..0000000000
--- a/features/onboarding/impl/src/main/res/drawable/bg_carousel_page_2.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
-
diff --git a/features/onboarding/impl/src/main/res/drawable/bg_carousel_page_3.xml b/features/onboarding/impl/src/main/res/drawable/bg_carousel_page_3.xml
deleted file mode 100644
index b206670820..0000000000
--- a/features/onboarding/impl/src/main/res/drawable/bg_carousel_page_3.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
-
diff --git a/features/onboarding/impl/src/main/res/drawable/bg_carousel_page_4.xml b/features/onboarding/impl/src/main/res/drawable/bg_carousel_page_4.xml
deleted file mode 100644
index 8eca5f922f..0000000000
--- a/features/onboarding/impl/src/main/res/drawable/bg_carousel_page_4.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
-
diff --git a/features/onboarding/impl/src/main/res/drawable/bg_color_background.xml b/features/onboarding/impl/src/main/res/drawable/bg_color_background.xml
deleted file mode 100644
index df950fd479..0000000000
--- a/features/onboarding/impl/src/main/res/drawable/bg_color_background.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
diff --git a/features/onboarding/impl/src/main/res/drawable/element.xml b/features/onboarding/impl/src/main/res/drawable/element.xml
new file mode 100644
index 0000000000..96a86d0db5
--- /dev/null
+++ b/features/onboarding/impl/src/main/res/drawable/element.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
diff --git a/features/onboarding/impl/src/main/res/drawable/element_logo.xml b/features/onboarding/impl/src/main/res/drawable/element_logo.xml
new file mode 100644
index 0000000000..9601fe3d06
--- /dev/null
+++ b/features/onboarding/impl/src/main/res/drawable/element_logo.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
diff --git a/features/onboarding/impl/src/main/res/values/strings.xml b/features/onboarding/impl/src/main/res/values/strings.xml
deleted file mode 100644
index d325d6ad1c..0000000000
--- a/features/onboarding/impl/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
-
-
-
- Cut the slack from teams.
-
- Get started
-
- Own your conversations.
- You\'re in control.
- Secure messaging.
- Messaging for your team.
-
- Secure and independent communication that gives you the same level of privacy as a face-to-face conversation in your own home.
- Choose where your conversations are kept, giving you control and independence. Connected via Matrix.
- End-to-end encrypted and no phone number required. No ads or datamining.
-
- Element is also great for the workplace. It’s trusted by the world’s most secure organisations.
-
-
-
diff --git a/features/onboarding/impl/src/test/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenterTest.kt b/features/onboarding/impl/src/test/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenterTest.kt
new file mode 100644
index 0000000000..f415cd795f
--- /dev/null
+++ b/features/onboarding/impl/src/test/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenterTest.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2023 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.features.onboarding.impl
+
+import app.cash.molecule.RecompositionClock
+import app.cash.molecule.moleculeFlow
+import app.cash.turbine.test
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+
+class OnBoardingPresenterTest {
+ @Test
+ fun `present - initial state`() = runTest {
+ val presenter = OnBoardingPresenter()
+ moleculeFlow(RecompositionClock.Immediate) {
+ presenter.present()
+ }.test {
+ val initialState = awaitItem()
+ assertThat(initialState.canLoginWithQrCode).isFalse()
+ assertThat(initialState.canCreateAccount).isFalse()
+ }
+ }
+}
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 2f84422fce..cce55faaca 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -96,8 +96,6 @@ accompanist_permission = { module = "com.google.accompanist:accompanist-permissi
accompanist_material = { module = "com.google.accompanist:accompanist-navigation-material", version.ref = "accompanist" }
accompanist_systemui = { module = "com.google.accompanist:accompanist-systemuicontroller", version.ref = "accompanist" }
accompanist_placeholder = { module = "com.google.accompanist:accompanist-placeholder-material", version.ref = "accompanist" }
-accompanist_pager = { module = "com.google.accompanist:accompanist-pager", version.ref = "accompanist" }
-accompanist_pagerindicator = { module = "com.google.accompanist:accompanist-pager-indicators", version.ref = "accompanist" }
accompanist_flowlayout = { module = "com.google.accompanist:accompanist-flowlayout", version.ref = "accompanist" }
# Libraries
diff --git a/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/NodeFactories.kt b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/NodeFactories.kt
index 82ec21667b..6073b45351 100644
--- a/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/NodeFactories.kt
+++ b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/NodeFactories.kt
@@ -34,6 +34,8 @@ inline fun Context.createNode(context: BuildContext, plugi
inline fun NodeFactoriesBindings.createNode(context: BuildContext, plugins: List = emptyList()): NODE {
val nodeClass = NODE::class.java
val nodeFactoryMap = nodeFactories()
+ // Note to developers: If you got the error below, make sure to build again after
+ // clearing the cache (sometimes several times) to let Dagger generate the NodeFactory.
val nodeFactory = nodeFactoryMap[nodeClass] ?: error("Cannot find NodeFactory for ${nodeClass.name}.")
@Suppress("UNCHECKED_CAST")
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/OnBoardingPage.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/OnBoardingPage.kt
new file mode 100644
index 0000000000..0e0292957b
--- /dev/null
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/OnBoardingPage.kt
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2023 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.atomic.pages
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.systemBarsPadding
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import io.element.android.libraries.designsystem.R
+import io.element.android.libraries.designsystem.preview.ElementPreviewDark
+import io.element.android.libraries.designsystem.preview.ElementPreviewLight
+import io.element.android.libraries.designsystem.theme.components.Text
+
+/**
+ * Page for onboarding screens, with content and optional footer.
+ *
+ * Ref: https://www.figma.com/file/o9p34zmiuEpZRyvZXJZAYL/FTUE?type=design&node-id=133-5427&t=5SHVppfYzjvkEywR-0
+ * @param modifier Classical modifier.
+ * @param footer optional footer.
+ * @param content main content.
+ */
+@Composable
+fun OnBoardingPage(
+ modifier: Modifier = Modifier,
+ footer: @Composable () -> Unit = {},
+ content: @Composable () -> Unit = {},
+) {
+ Box(
+ modifier = modifier
+ .fillMaxSize()
+ ) {
+ // BG
+ Image(
+ modifier = Modifier
+ .fillMaxSize(),
+ painter = painterResource(id = R.drawable.onboarding_bg),
+ contentScale = ContentScale.Crop,
+ contentDescription = null,
+ )
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .systemBarsPadding()
+ .padding(vertical = 16.dp),
+ ) {
+ // Content
+ Column(
+ modifier = Modifier
+ .weight(1f)
+ .padding(horizontal = 24.dp)
+ .fillMaxWidth(),
+ ) {
+ content()
+ }
+ // Footer
+ Box(modifier = Modifier.padding(horizontal = 16.dp)) {
+ footer()
+ }
+ }
+ }
+}
+
+@Preview
+@Composable
+internal fun OnBoardingPageLightPreview() =
+ ElementPreviewLight { ContentToPreview() }
+
+@Preview
+@Composable
+internal fun OnBoardingPageDarkPreview() =
+ ElementPreviewDark { ContentToPreview() }
+
+@Composable
+private fun ContentToPreview() {
+ OnBoardingPage(
+ content = {
+ Box(
+ Modifier
+ .fillMaxSize(),
+ contentAlignment = Alignment.Center
+ ) {
+ Text(
+ text = "Content",
+ fontSize = 40.sp
+ )
+ }
+ },
+ footer = {
+ Box(
+ Modifier
+ .fillMaxWidth(),
+ contentAlignment = Alignment.Center
+ ) {
+ Text(
+ text = "Footer",
+ fontSize = 40.sp
+ )
+ }
+ }
+ )
+}
diff --git a/libraries/designsystem/src/main/res/drawable/onboarding_bg.png b/libraries/designsystem/src/main/res/drawable/onboarding_bg.png
new file mode 100644
index 0000000000..61e2264ced
Binary files /dev/null and b/libraries/designsystem/src/main/res/drawable/onboarding_bg.png differ
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.oidc_null_DefaultGroup_OidcViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.oidc_null_DefaultGroup_OidcViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
deleted file mode 100644
index 94817469d3..0000000000
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.oidc_null_DefaultGroup_OidcViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:49e2768b2a111af737a30038913481113f759a20d3cf5df0166964c75926ec1f
-size 6545
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.oidc_null_DefaultGroup_OidcViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.oidc_null_DefaultGroup_OidcViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
deleted file mode 100644
index 40f9c06277..0000000000
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.oidc_null_DefaultGroup_OidcViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:eac9030993d92ef7f57ae5e622d566cd88555a60c462c0299f2a16a0c3e5daa8
-size 6853
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.oidc_null_DefaultGroup_OidcViewLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.oidc_null_DefaultGroup_OidcViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
deleted file mode 100644
index 94817469d3..0000000000
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.oidc_null_DefaultGroup_OidcViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:49e2768b2a111af737a30038913481113f759a20d3cf5df0166964c75926ec1f
-size 6545
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.oidc_null_DefaultGroup_OidcViewLightPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.oidc_null_DefaultGroup_OidcViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
deleted file mode 100644
index 7ae58a8744..0000000000
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.oidc_null_DefaultGroup_OidcViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:74a1a3ac6ae62c3573ce5834f5ae17952049ee77a8be76bfcb99e78b8fc6cb97
-size 6675
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenDarkPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenDarkPreview_0_null,NEXUS_5,1.0,en].png
deleted file mode 100644
index b1f708d57c..0000000000
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenDarkPreview_0_null,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:b53d55b5085673ac3a0a7663f7ff68e7d510fe352f3931b49c7e75e4c3767b93
-size 60007
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenDarkPreview_0_null_0,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..d8bebb7201
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0e7ee7df10cd863d2ec989fa4dc6621d38464de9ce640947a392c2397f53eb8c
+size 254906
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenDarkPreview_0_null_1,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..d930025396
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenDarkPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5e22509b6b519792ec8927c543373abe3976335aab96c72d99d40c8f924b410d
+size 244289
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenDarkPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenDarkPreview_0_null_2,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..4a4853308a
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenDarkPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3661424e8a5268b0606e5d70ea4cf6e42133c03d8ad88190669b887e9a3197d4
+size 254282
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenDarkPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenDarkPreview_0_null_3,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..12155debdf
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenDarkPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b9efc0ec64518c059d10edbfa4b1136237330a5bd9a1000a444a18df9044e788
+size 241109
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenLightPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenLightPreview_0_null,NEXUS_5,1.0,en].png
deleted file mode 100644
index d020b1e521..0000000000
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenLightPreview_0_null,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:a761318f3dfbc2ce6e777cfabc19eeb2f89100ae7631660f4b4d7550cd947c84
-size 57580
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenLightPreview_0_null_0,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..16881ad056
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:75045402335b2f02962c64cb0884b7e6132b8314bcfc225b6c71ebf303e13675
+size 241702
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenLightPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenLightPreview_0_null_1,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..62c0cafdec
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenLightPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f9fb6b0905faf223fd0505197060ff2838329435a2588a44c200277a5ed34083
+size 231701
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenLightPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenLightPreview_0_null_2,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..1fcf7d32aa
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenLightPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:96d3d1147d02b49eb206cd0f051882cdb7ce7f66088e1d01b62f30cf9469d5a1
+size 241589
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenLightPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenLightPreview_0_null_3,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..29d66a93e6
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenLightPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ec6523d971baf66b6946334927069491c7203345aeda820cac35e168d95779bf
+size 227789
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.pages_null_DefaultGroup_OnBoardingPageDarkPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.pages_null_DefaultGroup_OnBoardingPageDarkPreview_0_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..8ac535e6c0
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.pages_null_DefaultGroup_OnBoardingPageDarkPreview_0_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:237bf6506435a954985cccc4f40333a02f8d74a11b57671414442f09706aa6c1
+size 253095
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.pages_null_DefaultGroup_OnBoardingPageLightPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.pages_null_DefaultGroup_OnBoardingPageLightPreview_0_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..269a829676
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.pages_null_DefaultGroup_OnBoardingPageLightPreview_0_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:7b9e801ae788e63a0737d4ae043cfdbeebbda9de07f925d15ceebb0ba1467795
+size 241513