dynamically switching the onboarding flow based on the capabilities of the homeserver
- when avatars can't be changed we complete the personlisation flow
This commit is contained in:
parent
46be481eda
commit
716928d9d2
@ -75,6 +75,7 @@ sealed class OnboardingAction : VectorViewModelAction {
|
|||||||
|
|
||||||
data class UserAcceptCertificate(val fingerprint: Fingerprint) : OnboardingAction()
|
data class UserAcceptCertificate(val fingerprint: Fingerprint) : OnboardingAction()
|
||||||
|
|
||||||
|
object PersonalizeProfile : OnboardingAction()
|
||||||
data class UpdateDisplayName(val displayName: String) : OnboardingAction()
|
data class UpdateDisplayName(val displayName: String) : OnboardingAction()
|
||||||
object UpdateDisplayNameSkipped : OnboardingAction()
|
object UpdateDisplayNameSkipped : OnboardingAction()
|
||||||
data class ProfilePictureSelected(val uri: Uri) : OnboardingAction()
|
data class ProfilePictureSelected(val uri: Uri) : OnboardingAction()
|
||||||
|
@ -51,9 +51,8 @@ sealed class OnboardingViewEvents : VectorViewEvents {
|
|||||||
object OnAccountCreated : OnboardingViewEvents()
|
object OnAccountCreated : OnboardingViewEvents()
|
||||||
object OnAccountSignedIn : OnboardingViewEvents()
|
object OnAccountSignedIn : OnboardingViewEvents()
|
||||||
object OnTakeMeHome : OnboardingViewEvents()
|
object OnTakeMeHome : OnboardingViewEvents()
|
||||||
object OnPersonalizeProfile : OnboardingViewEvents()
|
object OnChooseDisplayName : OnboardingViewEvents()
|
||||||
object OnDisplayNameUpdated : OnboardingViewEvents()
|
object OnChooseProfilePicture : OnboardingViewEvents()
|
||||||
object OnDisplayNameSkipped : OnboardingViewEvents()
|
|
||||||
object OnPersonalizationComplete : OnboardingViewEvents()
|
object OnPersonalizationComplete : OnboardingViewEvents()
|
||||||
object OnBack : OnboardingViewEvents()
|
object OnBack : OnboardingViewEvents()
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,6 @@ class OnboardingViewModel @AssistedInject constructor(
|
|||||||
private val stringProvider: StringProvider,
|
private val stringProvider: StringProvider,
|
||||||
private val homeServerHistoryService: HomeServerHistoryService,
|
private val homeServerHistoryService: HomeServerHistoryService,
|
||||||
private val vectorFeatures: VectorFeatures,
|
private val vectorFeatures: VectorFeatures,
|
||||||
private val vectorOverrides: VectorOverrides,
|
|
||||||
private val analyticsTracker: AnalyticsTracker,
|
private val analyticsTracker: AnalyticsTracker,
|
||||||
private val uriFilenameResolver: UriFilenameResolver,
|
private val uriFilenameResolver: UriFilenameResolver,
|
||||||
private val vectorOverrides: VectorOverrides
|
private val vectorOverrides: VectorOverrides
|
||||||
@ -158,12 +157,13 @@ class OnboardingViewModel @AssistedInject constructor(
|
|||||||
is OnboardingAction.ResetAction -> handleResetAction(action)
|
is OnboardingAction.ResetAction -> handleResetAction(action)
|
||||||
is OnboardingAction.UserAcceptCertificate -> handleUserAcceptCertificate(action)
|
is OnboardingAction.UserAcceptCertificate -> handleUserAcceptCertificate(action)
|
||||||
OnboardingAction.ClearHomeServerHistory -> handleClearHomeServerHistory()
|
OnboardingAction.ClearHomeServerHistory -> handleClearHomeServerHistory()
|
||||||
is OnboardingAction.PostViewEvent -> _viewEvents.post(action.viewEvent)
|
|
||||||
is OnboardingAction.UpdateDisplayName -> updateDisplayName(action.displayName)
|
is OnboardingAction.UpdateDisplayName -> updateDisplayName(action.displayName)
|
||||||
OnboardingAction.UpdateDisplayNameSkipped -> _viewEvents.post(OnboardingViewEvents.OnDisplayNameSkipped)
|
OnboardingAction.UpdateDisplayNameSkipped -> handleDisplayNameStepComplete()
|
||||||
OnboardingAction.UpdateProfilePictureSkipped -> _viewEvents.post(OnboardingViewEvents.OnPersonalizationComplete)
|
OnboardingAction.UpdateProfilePictureSkipped -> _viewEvents.post(OnboardingViewEvents.OnPersonalizationComplete)
|
||||||
|
OnboardingAction.PersonalizeProfile -> handlePersonalizeProfile()
|
||||||
is OnboardingAction.ProfilePictureSelected -> handleProfilePictureSelected(action)
|
is OnboardingAction.ProfilePictureSelected -> handleProfilePictureSelected(action)
|
||||||
OnboardingAction.SaveSelectedProfilePicture -> updateProfilePicture()
|
OnboardingAction.SaveSelectedProfilePicture -> updateProfilePicture()
|
||||||
|
is OnboardingAction.PostViewEvent -> _viewEvents.post(action.viewEvent)
|
||||||
}.exhaustive
|
}.exhaustive
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -921,7 +921,7 @@ class OnboardingViewModel @AssistedInject constructor(
|
|||||||
personalizationState = personalizationState.copy(displayName = displayName)
|
personalizationState = personalizationState.copy(displayName = displayName)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_viewEvents.post(OnboardingViewEvents.OnDisplayNameUpdated)
|
handleDisplayNameStepComplete()
|
||||||
} catch (error: Throwable) {
|
} catch (error: Throwable) {
|
||||||
setState { copy(asyncDisplayName = Fail(error)) }
|
setState { copy(asyncDisplayName = Fail(error)) }
|
||||||
_viewEvents.post(OnboardingViewEvents.Failure(error))
|
_viewEvents.post(OnboardingViewEvents.Failure(error))
|
||||||
@ -929,12 +929,35 @@ class OnboardingViewModel @AssistedInject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun handlePersonalizeProfile() {
|
||||||
|
withPersonalisationState {
|
||||||
|
when {
|
||||||
|
it.supportsChangingDisplayName -> _viewEvents.post(OnboardingViewEvents.OnChooseDisplayName)
|
||||||
|
it.supportsChangingProfilePicture -> _viewEvents.post(OnboardingViewEvents.OnChooseDisplayName)
|
||||||
|
else -> throw IllegalStateException("It should not be possible to personalize without supporting display name or avatar changing")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleDisplayNameStepComplete() {
|
||||||
|
withPersonalisationState {
|
||||||
|
when {
|
||||||
|
it.supportsChangingProfilePicture -> _viewEvents.post(OnboardingViewEvents.OnChooseProfilePicture)
|
||||||
|
else -> _viewEvents.post(OnboardingViewEvents.OnPersonalizationComplete)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleProfilePictureSelected(action: OnboardingAction.ProfilePictureSelected) {
|
private fun handleProfilePictureSelected(action: OnboardingAction.ProfilePictureSelected) {
|
||||||
setState {
|
setState {
|
||||||
copy(personalizationState = personalizationState.copy(selectedPictureUri = action.uri))
|
copy(personalizationState = personalizationState.copy(selectedPictureUri = action.uri))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun withPersonalisationState(block: (PersonalizationState) -> Unit) {
|
||||||
|
withState { block(it.personalizationState) }
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateProfilePicture() {
|
private fun updateProfilePicture() {
|
||||||
withState { state ->
|
withState { state ->
|
||||||
when (val pictureUri = state.personalizationState.selectedPictureUri) {
|
when (val pictureUri = state.personalizationState.selectedPictureUri) {
|
||||||
|
@ -44,7 +44,7 @@ class FtueAuthAccountCreatedFragment @Inject constructor(
|
|||||||
|
|
||||||
private fun setupViews() {
|
private fun setupViews() {
|
||||||
views.accountCreatedSubtitle.text = getString(R.string.ftue_account_created_subtitle, activeSessionHolder.getActiveSession().myUserId)
|
views.accountCreatedSubtitle.text = getString(R.string.ftue_account_created_subtitle, activeSessionHolder.getActiveSession().myUserId)
|
||||||
views.accountCreatedPersonalize.debouncedClicks { viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.OnPersonalizeProfile)) }
|
views.accountCreatedPersonalize.debouncedClicks { viewModel.handle(OnboardingAction.PersonalizeProfile) }
|
||||||
views.accountCreatedTakeMeHome.debouncedClicks { viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.OnTakeMeHome)) }
|
views.accountCreatedTakeMeHome.debouncedClicks { viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.OnTakeMeHome)) }
|
||||||
views.accountCreatedTakeMeHomeCta.debouncedClicks { viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.OnTakeMeHome)) }
|
views.accountCreatedTakeMeHomeCta.debouncedClicks { viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.OnTakeMeHome)) }
|
||||||
}
|
}
|
||||||
|
@ -232,10 +232,9 @@ class FtueAuthVariant(
|
|||||||
}
|
}
|
||||||
is OnboardingViewEvents.OnAccountCreated -> onAccountCreated()
|
is OnboardingViewEvents.OnAccountCreated -> onAccountCreated()
|
||||||
OnboardingViewEvents.OnAccountSignedIn -> onAccountSignedIn()
|
OnboardingViewEvents.OnAccountSignedIn -> onAccountSignedIn()
|
||||||
OnboardingViewEvents.OnPersonalizeProfile -> onPersonalizeProfile()
|
OnboardingViewEvents.OnChooseDisplayName -> onChooseDisplayName()
|
||||||
OnboardingViewEvents.OnTakeMeHome -> navigateToHome(createdAccount = true)
|
OnboardingViewEvents.OnTakeMeHome -> navigateToHome(createdAccount = true)
|
||||||
OnboardingViewEvents.OnDisplayNameUpdated -> onDisplayNameUpdated()
|
OnboardingViewEvents.OnChooseProfilePicture -> onChooseProfilePicture()
|
||||||
OnboardingViewEvents.OnDisplayNameSkipped -> onDisplayNameUpdated()
|
|
||||||
OnboardingViewEvents.OnPersonalizationComplete -> navigateToHome(createdAccount = true)
|
OnboardingViewEvents.OnPersonalizationComplete -> navigateToHome(createdAccount = true)
|
||||||
OnboardingViewEvents.OnBack -> activity.popBackstack()
|
OnboardingViewEvents.OnBack -> activity.popBackstack()
|
||||||
}.exhaustive
|
}.exhaustive
|
||||||
@ -412,14 +411,14 @@ class FtueAuthVariant(
|
|||||||
activity.finish()
|
activity.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onPersonalizeProfile() {
|
private fun onChooseDisplayName() {
|
||||||
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
FtueAuthChooseDisplayNameFragment::class.java,
|
FtueAuthChooseDisplayNameFragment::class.java,
|
||||||
option = commonOption
|
option = commonOption
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onDisplayNameUpdated() {
|
private fun onChooseProfilePicture() {
|
||||||
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
FtueAuthChooseProfilePictureFragment::class.java,
|
FtueAuthChooseProfilePictureFragment::class.java,
|
||||||
option = commonOption
|
option = commonOption
|
||||||
|
@ -36,7 +36,6 @@ import im.vector.app.test.fakes.FakeStringProvider
|
|||||||
import im.vector.app.test.fakes.FakeUri
|
import im.vector.app.test.fakes.FakeUri
|
||||||
import im.vector.app.test.fakes.FakeUriFilenameResolver
|
import im.vector.app.test.fakes.FakeUriFilenameResolver
|
||||||
import im.vector.app.test.fakes.FakeVectorFeatures
|
import im.vector.app.test.fakes.FakeVectorFeatures
|
||||||
import im.vector.app.test.fakes.FakeVectorOverrides
|
|
||||||
import im.vector.app.test.test
|
import im.vector.app.test.test
|
||||||
import kotlinx.coroutines.test.runBlockingTest
|
import kotlinx.coroutines.test.runBlockingTest
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@ -111,21 +110,31 @@ class OnboardingViewModelTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `when handling display name update then updates upstream user display name`() = runBlockingTest {
|
fun `given changing profile picture is supported when updating display name then updates upstream user display name and moves to choose profile picture`() = runBlockingTest {
|
||||||
|
val personalisedInitialState = initialState.copy(personalizationState = PersonalizationState(supportsChangingProfilePicture = true))
|
||||||
|
viewModel = createViewModel(personalisedInitialState)
|
||||||
val test = viewModel.test(this)
|
val test = viewModel.test(this)
|
||||||
|
|
||||||
viewModel.handle(OnboardingAction.UpdateDisplayName(A_DISPLAY_NAME))
|
viewModel.handle(OnboardingAction.UpdateDisplayName(A_DISPLAY_NAME))
|
||||||
|
|
||||||
test
|
test
|
||||||
.assertStates(
|
.assertStates(expectedSuccessfulDisplayNameUpdateStates(personalisedInitialState))
|
||||||
initialState,
|
.assertEvents(OnboardingViewEvents.OnChooseProfilePicture)
|
||||||
initialState.copy(asyncDisplayName = Loading()),
|
.finish()
|
||||||
initialState.copy(
|
fakeSession.fakeProfileService.verifyUpdatedName(fakeSession.myUserId, A_DISPLAY_NAME)
|
||||||
asyncDisplayName = Success(Unit),
|
}
|
||||||
personalizationState = initialState.personalizationState.copy(displayName = A_DISPLAY_NAME)
|
|
||||||
)
|
@Test
|
||||||
)
|
fun `given changing profile picture is not supported when updating display name then updates upstream user display name and completes personalization`() = runBlockingTest {
|
||||||
.assertEvents(OnboardingViewEvents.OnDisplayNameUpdated)
|
val personalisedInitialState = initialState.copy(personalizationState = PersonalizationState(supportsChangingProfilePicture = false))
|
||||||
|
viewModel = createViewModel(personalisedInitialState)
|
||||||
|
val test = viewModel.test(this)
|
||||||
|
|
||||||
|
viewModel.handle(OnboardingAction.UpdateDisplayName(A_DISPLAY_NAME))
|
||||||
|
|
||||||
|
test
|
||||||
|
.assertStates(expectedSuccessfulDisplayNameUpdateStates(personalisedInitialState))
|
||||||
|
.assertEvents(OnboardingViewEvents.OnPersonalizationComplete)
|
||||||
.finish()
|
.finish()
|
||||||
fakeSession.fakeProfileService.verifyUpdatedName(fakeSession.myUserId, A_DISPLAY_NAME)
|
fakeSession.fakeProfileService.verifyUpdatedName(fakeSession.myUserId, A_DISPLAY_NAME)
|
||||||
}
|
}
|
||||||
@ -227,7 +236,6 @@ class OnboardingViewModelTest {
|
|||||||
FakeStringProvider().instance,
|
FakeStringProvider().instance,
|
||||||
FakeHomeServerHistoryService(),
|
FakeHomeServerHistoryService(),
|
||||||
FakeVectorFeatures(),
|
FakeVectorFeatures(),
|
||||||
FakeVectorOverrides(),
|
|
||||||
FakeAnalyticsTracker(),
|
FakeAnalyticsTracker(),
|
||||||
fakeUriFilenameResolver.instance,
|
fakeUriFilenameResolver.instance,
|
||||||
DefaultVectorOverrides()
|
DefaultVectorOverrides()
|
||||||
@ -259,4 +267,15 @@ class OnboardingViewModelTest {
|
|||||||
fakeAuthenticationService.expectReset()
|
fakeAuthenticationService.expectReset()
|
||||||
fakeSession.expectStartsSyncing()
|
fakeSession.expectStartsSyncing()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun expectedSuccessfulDisplayNameUpdateStates(personalisedInitialState: OnboardingViewState): List<OnboardingViewState> {
|
||||||
|
return listOf(
|
||||||
|
personalisedInitialState,
|
||||||
|
personalisedInitialState.copy(asyncDisplayName = Loading()),
|
||||||
|
personalisedInitialState.copy(
|
||||||
|
asyncDisplayName = Success(Unit),
|
||||||
|
personalizationState = personalisedInitialState.personalizationState.copy(displayName = A_DISPLAY_NAME)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user