-
Notifications
You must be signed in to change notification settings - Fork 862
FTUE - Server selection #5691
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
FTUE - Server selection #5691
Changes from all commits
c3cf221
7f90dda
985dbfe
51c294a
f34df39
1e52012
e9f5003
8b2e2a1
c022a38
89f182a
1d92b42
2ba3bd3
0ce2012
21102a2
db50225
f70d613
6304d5d
05a7d40
a2bcbfb
5f9d3e1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| Adds a new homeserver selection screen when creating an account |
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| /* | ||
| * 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.features.onboarding | ||
|
|
||
| import im.vector.app.R | ||
| import im.vector.app.core.extensions.containsAllItems | ||
| import im.vector.app.core.resources.StringProvider | ||
| import im.vector.app.core.utils.ensureTrailingSlash | ||
| import im.vector.app.features.login.LoginMode | ||
| import org.matrix.android.sdk.api.auth.AuthenticationService | ||
| import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig | ||
| import org.matrix.android.sdk.api.auth.data.LoginFlowResult | ||
| import org.matrix.android.sdk.api.auth.data.LoginFlowTypes | ||
| import javax.inject.Inject | ||
|
|
||
| class StartAuthenticationFlowUseCase @Inject constructor( | ||
| private val authenticationService: AuthenticationService, | ||
| private val stringProvider: StringProvider | ||
| ) { | ||
|
|
||
| suspend fun execute(config: HomeServerConnectionConfig): StartAuthenticationResult { | ||
| authenticationService.cancelPendingLoginOrRegistration() | ||
| val authFlow = authenticationService.getLoginFlow(config) | ||
| val preferredLoginMode = authFlow.findPreferredLoginMode() | ||
| val selection = createSelectedHomeserver(authFlow, config, preferredLoginMode) | ||
| val isOutdated = (preferredLoginMode == LoginMode.Password && !authFlow.isLoginAndRegistrationSupported) || authFlow.isOutdatedHomeserver | ||
| return StartAuthenticationResult(isOutdated, selection) | ||
| } | ||
|
|
||
| private fun createSelectedHomeserver( | ||
| authFlow: LoginFlowResult, | ||
| config: HomeServerConnectionConfig, | ||
| preferredLoginMode: LoginMode | ||
| ) = SelectedHomeserverState( | ||
| description = when (config.homeServerUri.toString()) { | ||
| matrixOrgUrl() -> stringProvider.getString(R.string.ftue_auth_create_account_matrix_dot_org_server_description) | ||
| else -> null | ||
| }, | ||
| userFacingUrl = config.homeServerUri.toString(), | ||
| upstreamUrl = authFlow.homeServerUrl, | ||
| preferredLoginMode = preferredLoginMode, | ||
| supportedLoginTypes = authFlow.supportedLoginTypes | ||
| ) | ||
|
|
||
| private fun matrixOrgUrl() = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash() | ||
|
|
||
| private fun LoginFlowResult.findPreferredLoginMode() = when { | ||
| supportedLoginTypes.containsAllItems(LoginFlowTypes.SSO, LoginFlowTypes.PASSWORD) -> LoginMode.SsoAndPassword(ssoIdentityProviders) | ||
| supportedLoginTypes.contains(LoginFlowTypes.SSO) -> LoginMode.Sso(ssoIdentityProviders) | ||
| supportedLoginTypes.contains(LoginFlowTypes.PASSWORD) -> LoginMode.Password | ||
| else -> LoginMode.Unsupported | ||
| } | ||
|
|
||
| data class StartAuthenticationResult( | ||
| val isHomeserverOutdated: Boolean, | ||
| val selectedHomeserver: SelectedHomeserverState | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| /* | ||
| * 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.features.onboarding.ftueauth | ||
|
|
||
| import android.os.Bundle | ||
| import android.view.LayoutInflater | ||
| import android.view.View | ||
| import android.view.ViewGroup | ||
| import android.view.inputmethod.EditorInfo | ||
| import im.vector.app.R | ||
| import im.vector.app.core.extensions.content | ||
| import im.vector.app.core.extensions.editText | ||
| import im.vector.app.core.extensions.realignPercentagesToParent | ||
| import im.vector.app.core.extensions.toReducedUrl | ||
| import im.vector.app.core.utils.ensureProtocol | ||
| import im.vector.app.core.utils.ensureTrailingSlash | ||
| import im.vector.app.core.utils.openUrlInExternalBrowser | ||
| import im.vector.app.databinding.FragmentFtueServerSelectionCombinedBinding | ||
| import im.vector.app.features.onboarding.OnboardingAction | ||
| import im.vector.app.features.onboarding.OnboardingViewEvents | ||
| import im.vector.app.features.onboarding.OnboardingViewState | ||
| import javax.inject.Inject | ||
|
|
||
| class FtueAuthCombinedServerSelectionFragment @Inject constructor() : AbstractFtueAuthFragment<FragmentFtueServerSelectionCombinedBinding>() { | ||
|
|
||
| override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentFtueServerSelectionCombinedBinding { | ||
| return FragmentFtueServerSelectionCombinedBinding.inflate(inflater, container, false) | ||
| } | ||
|
|
||
| override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor, I would have created some more methods instead of having all the login in
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks! |
||
| super.onViewCreated(view, savedInstanceState) | ||
| setupViews() | ||
| } | ||
|
|
||
| private fun setupViews() { | ||
| views.chooseServerRoot.realignPercentagesToParent() | ||
| views.chooseServerToolbar.setNavigationOnClickListener { | ||
| viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.OnBack)) | ||
| } | ||
| views.chooseServerInput.editText?.setOnEditorActionListener { _, actionId, _ -> | ||
| when (actionId) { | ||
| EditorInfo.IME_ACTION_DONE -> { | ||
| updateServerUrl() | ||
| } | ||
| } | ||
| false | ||
| } | ||
| views.chooseServerGetInTouch.debouncedClicks { openUrlInExternalBrowser(requireContext(), getString(R.string.ftue_ems_url)) } | ||
| views.chooseServerSubmit.debouncedClicks { updateServerUrl() } | ||
| } | ||
|
|
||
| private fun updateServerUrl() { | ||
| viewModel.handle(OnboardingAction.HomeServerChange.EditHomeServer(views.chooseServerInput.content().ensureProtocol().ensureTrailingSlash())) | ||
| } | ||
|
|
||
| override fun resetViewModel() { | ||
| // do nothing | ||
| } | ||
|
|
||
| override fun updateWithState(state: OnboardingViewState) { | ||
| if (views.chooseServerInput.content().isEmpty()) { | ||
| val userUrlInput = state.selectedHomeserver.userFacingUrl?.toReducedUrlKeepingSchemaIfInsecure() | ||
| views.chooseServerInput.editText().setText(userUrlInput) | ||
| } | ||
| } | ||
|
|
||
| private fun String.toReducedUrlKeepingSchemaIfInsecure() = toReducedUrl(keepSchema = this.startsWith("http://")) | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the individual homeserver state has been bundled into a single
SelectedHomeserverState, this object is created/updated when starting the authentication flow (by selecting or editing a homeserver url) through a single entry point StartAuthenticationFlowUseCase.kt