Skip to content

FTUE - Personalisation complete #5389

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Mar 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/5389.wip
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Introduces FTUE personalisation complete screen along with confetti celebration
51 changes: 51 additions & 0 deletions vector/src/main/java/im/vector/app/core/animations/Konfetti.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (c) 2022 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 im.vector.app.core.animations

import android.content.Context
import androidx.annotation.ColorInt
import androidx.core.content.ContextCompat
import im.vector.app.R
import nl.dionsegijn.konfetti.KonfettiView
import nl.dionsegijn.konfetti.models.Shape
import nl.dionsegijn.konfetti.models.Size

fun KonfettiView.play() {
val confettiColors = listOf(
R.color.palette_azure,
R.color.palette_grape,
R.color.palette_verde,
R.color.palette_polly,
R.color.palette_melon,
R.color.palette_aqua,
R.color.palette_prune,
R.color.palette_kiwi
)
build()
.addColors(confettiColors.toColorInt(context))
.setDirection(0.0, 359.0)
.setSpeed(2f, 5f)
.setFadeOutEnabled(true)
.setTimeToLive(2000L)
.addShapes(Shape.Square, Shape.Circle)
.addSizes(Size(12))
.setPosition(-50f, width + 50f, -50f, -50f)
.streamFor(150, 3000L)
}

@ColorInt
private fun List<Int>.toColorInt(context: Context) = map { ContextCompat.getColor(context, it) }
6 changes: 6 additions & 0 deletions vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ import im.vector.app.features.onboarding.ftueauth.FtueAuthChooseDisplayNameFragm
import im.vector.app.features.onboarding.ftueauth.FtueAuthChooseProfilePictureFragment
import im.vector.app.features.onboarding.ftueauth.FtueAuthGenericTextInputFormFragment
import im.vector.app.features.onboarding.ftueauth.FtueAuthLoginFragment
import im.vector.app.features.onboarding.ftueauth.FtueAuthPersonalizationCompleteFragment
import im.vector.app.features.onboarding.ftueauth.FtueAuthResetPasswordFragment
import im.vector.app.features.onboarding.ftueauth.FtueAuthResetPasswordMailConfirmationFragment
import im.vector.app.features.onboarding.ftueauth.FtueAuthResetPasswordSuccessFragment
Expand Down Expand Up @@ -491,6 +492,11 @@ interface FragmentModule {
@FragmentKey(FtueAuthChooseProfilePictureFragment::class)
fun bindFtueAuthChooseProfilePictureFragment(fragment: FtueAuthChooseProfilePictureFragment): Fragment

@Binds
@IntoMap
@FragmentKey(FtueAuthPersonalizationCompleteFragment::class)
fun bindFtueAuthPersonalizationCompleteFragment(fragment: FtueAuthPersonalizationCompleteFragment): Fragment

@Binds
@IntoMap
@FragmentKey(UserListFragment::class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.content.res.Configuration
import android.graphics.Color
import android.net.Uri
import android.os.Build
import android.os.Bundle
Expand Down Expand Up @@ -68,6 +67,7 @@ import com.airbnb.mvrx.withState
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.vanniktech.emoji.EmojiPopup
import im.vector.app.R
import im.vector.app.core.animations.play
import im.vector.app.core.dialogs.ConfirmationDialogBuilder
import im.vector.app.core.dialogs.GalleryOrCameraDialogHelper
import im.vector.app.core.epoxy.LayoutManagerStateRestorer
Expand Down Expand Up @@ -203,8 +203,6 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import nl.dionsegijn.konfetti.models.Shape
import nl.dionsegijn.konfetti.models.Size
import org.billcarsonfr.jsonviewer.JSonViewerDialog
import org.commonmark.parser.Parser
import org.matrix.android.sdk.api.session.Session
Expand Down Expand Up @@ -562,16 +560,7 @@ class TimelineFragment @Inject constructor(
when (chatEffect) {
ChatEffect.CONFETTI -> {
views.viewKonfetti.isVisible = true
views.viewKonfetti.build()
.addColors(Color.YELLOW, Color.GREEN, Color.MAGENTA)
.setDirection(0.0, 359.0)
.setSpeed(2f, 5f)
.setFadeOutEnabled(true)
.setTimeToLive(2000L)
.addShapes(Shape.Square, Shape.Circle)
.addSizes(Size(12))
.setPosition(-50f, views.viewKonfetti.width + 50f, -50f, -50f)
.streamFor(150, 3000L)
views.viewKonfetti.play()
}
ChatEffect.SNOWFALL -> {
views.viewSnowFall.isVisible = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
import im.vector.app.R
import im.vector.app.core.animations.play
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.databinding.FragmentFtueAccountCreatedBinding
import im.vector.app.features.onboarding.OnboardingAction
Expand All @@ -33,6 +34,8 @@ class FtueAuthAccountCreatedFragment @Inject constructor(
private val activeSessionHolder: ActiveSessionHolder
) : AbstractFtueAuthFragment<FragmentFtueAccountCreatedBinding>() {

private var hasPlayedConfetti = false

override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentFtueAccountCreatedBinding {
return FragmentFtueAccountCreatedBinding.inflate(inflater, container, false)
}
Expand All @@ -53,6 +56,12 @@ class FtueAuthAccountCreatedFragment @Inject constructor(
val canPersonalize = state.personalizationState.supportsPersonalization()
views.personalizeButtonGroup.isVisible = canPersonalize
views.takeMeHomeButtonGroup.isVisible = !canPersonalize

if (!hasPlayedConfetti && !canPersonalize) {
hasPlayedConfetti = true
views.viewKonfetti.isVisible = true
views.viewKonfetti.play()
}
}

override fun resetViewModel() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright (c) 2021 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 im.vector.app.features.onboarding.ftueauth

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
import im.vector.app.core.animations.play
import im.vector.app.databinding.FragmentFtuePersonalizationCompleteBinding
import im.vector.app.features.onboarding.OnboardingAction
import im.vector.app.features.onboarding.OnboardingViewEvents
import javax.inject.Inject

class FtueAuthPersonalizationCompleteFragment @Inject constructor() : AbstractFtueAuthFragment<FragmentFtuePersonalizationCompleteBinding>() {

private var hasPlayedConfetti = false

override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentFtuePersonalizationCompleteBinding {
return FragmentFtuePersonalizationCompleteBinding.inflate(inflater, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupViews()
}

private fun setupViews() {
views.personalizationCompleteCta.debouncedClicks { viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.OnTakeMeHome)) }

if (!hasPlayedConfetti) {
hasPlayedConfetti = true
views.viewKonfetti.isVisible = true
views.viewKonfetti.play()
}
}

override fun resetViewModel() {
// Nothing to do
}

override fun onBackPressed(toolbarButton: Boolean): Boolean {
viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.OnTakeMeHome))
return true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ class FtueAuthVariant(
OnboardingViewEvents.OnChooseDisplayName -> onChooseDisplayName()
OnboardingViewEvents.OnTakeMeHome -> navigateToHome(createdAccount = true)
OnboardingViewEvents.OnChooseProfilePicture -> onChooseProfilePicture()
OnboardingViewEvents.OnPersonalizationComplete -> navigateToHome(createdAccount = true)
OnboardingViewEvents.OnPersonalizationComplete -> onPersonalizationComplete()
OnboardingViewEvents.OnBack -> activity.popBackstack()
}.exhaustive
}
Expand Down Expand Up @@ -393,7 +393,8 @@ class FtueAuthVariant(
activity.supportFragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
activity.replaceFragment(
views.loginFragmentContainer,
FtueAuthAccountCreatedFragment::class.java
FtueAuthAccountCreatedFragment::class.java,
useCustomAnimation = true
)
}

Expand All @@ -416,4 +417,13 @@ class FtueAuthVariant(
option = commonOption
)
}

private fun onPersonalizationComplete() {
activity.supportFragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
activity.replaceFragment(
views.loginFragmentContainer,
FtueAuthPersonalizationCompleteFragment::class.java,
useCustomAnimation = true
)
}
}
18 changes: 18 additions & 0 deletions vector/src/main/res/drawable/ic_celebration.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="70dp"
android:height="70dp"
android:viewportWidth="70"
android:viewportHeight="70">
<path
android:pathData="M21,23L19,27L23,25L27,27L25,23L27,19L23,21L19,19L21,23Z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#FF0000"
android:strokeColor="#FF0000"/>
<path
android:pathData="M35.653,41.423L38.538,50.076L41.422,41.423L50.076,38.538L41.422,35.654L38.538,27L35.653,35.654L27,38.538L35.653,41.423Z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#FF0000"
android:strokeColor="#FF0000"/>
</vector>
10 changes: 10 additions & 0 deletions vector/src/main/res/drawable/ic_user_fg.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="70dp"
android:height="70dp"
android:viewportWidth="70"
android:viewportHeight="70">
<path
android:pathData="M35,36.742C40.771,36.742 45.45,31.673 45.45,25.421C45.45,19.169 40.771,14.1 35,14.1C29.229,14.1 24.55,19.169 24.55,25.421C24.55,31.673 29.229,36.742 35,36.742ZM35,62.867C42.531,62.867 49.364,59.879 54.379,55.025C51.278,47.368 43.77,41.967 35,41.967C26.23,41.967 18.722,47.368 15.621,55.025C20.636,59.879 27.469,62.867 35,62.867Z"
android:fillColor="#FF0000"
android:fillType="evenOdd"/>
</vector>
14 changes: 11 additions & 3 deletions vector/src/main/res/layout/fragment_ftue_account_created.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
android:layout_height="match_parent"
android:background="?colorSecondary">

<nl.dionsegijn.konfetti.KonfettiView
android:id="@+id/viewKonfetti"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />

<androidx.constraintlayout.widget.Guideline
android:id="@+id/ftueAuthGutterStart"
android:layout_width="wrap_content"
Expand Down Expand Up @@ -34,14 +40,16 @@
android:layout_width="wrap_content"
android:layout_height="0dp"
android:adjustViewBounds="true"
android:background="@drawable/circle"
android:backgroundTint="@color/element_background_light"
android:importantForAccessibility="no"
android:src="@drawable/ic_user_round"
android:src="@drawable/ic_user_fg"
app:layout_constraintBottom_toTopOf="@id/accountCreatedSpace2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.15"
app:layout_constraintHeight_percent="0.12"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/accountCreatedSpace1"
app:tint="@color/element_background_light" />
app:tint="?colorSecondary" />

<Space
android:id="@+id/accountCreatedSpace2"
Expand Down
8 changes: 5 additions & 3 deletions vector/src/main/res/layout/fragment_ftue_display_name.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@
android:layout_height="0dp"
android:adjustViewBounds="true"
android:contentDescription="@null"
android:src="@drawable/ic_user_round"
android:background="@drawable/circle"
android:backgroundTint="?colorSecondary"
android:src="@drawable/ic_user_fg"
app:layout_constraintBottom_toTopOf="@id/displayNameHeaderTitle"
app:layout_constraintEnd_toEndOf="@id/displayNameGutterEnd"
app:layout_constraintHeight_percent="0.15"
app:layout_constraintHeight_percent="0.12"
app:layout_constraintStart_toStartOf="@id/displayNameGutterStart"
app:layout_constraintTop_toTopOf="parent"
app:tint="?colorSecondary" />
app:tint="@color/palette_white" />

<TextView
android:id="@+id/displayNameHeaderTitle"
Expand Down
Loading