(R.id.adapter_item_policy_title)
+ }
+}
diff --git a/vector/src/main/java/im/vector/riotx/features/login/terms/UrlAndName.kt b/vector/src/main/java/im/vector/riotx/features/login/terms/UrlAndName.kt
new file mode 100644
index 0000000000..1ccb7cac49
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotx/features/login/terms/UrlAndName.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2019 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.riotx.features.login.terms
+
+data class UrlAndName(
+ val url: String,
+ val name: String
+)
diff --git a/vector/src/main/java/im/vector/riotx/features/login/terms/converter.kt b/vector/src/main/java/im/vector/riotx/features/login/terms/converter.kt
new file mode 100644
index 0000000000..c9e6dcf3fd
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotx/features/login/terms/converter.kt
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2019 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.riotx.features.login.terms
+
+import im.vector.matrix.android.api.auth.registration.TermPolicies
+import org.matrix.androidsdk.rest.model.login.LocalizedFlowDataLoginTerms
+
+/**
+ * This method extract the policies from the login terms parameter, regarding the user language.
+ * For each policy, if user language is not found, the default language is used and if not found, the first url and name are used (not predictable)
+ *
+ * Example of Data:
+ *
+ * "m.login.terms": {
+ * "policies": {
+ * "privacy_policy": {
+ * "version": "1.0",
+ * "en": {
+ * "url": "http:\/\/matrix.org\/_matrix\/consent?v=1.0",
+ * "name": "Terms and Conditions"
+ * }
+ * }
+ * }
+ * }
+ *
+ *
+ * @param userLanguage the user language
+ * @param defaultLanguage the default language to use if the user language is not found for a policy in registrationFlowResponse
+ */
+fun TermPolicies.toLocalizedLoginTerms(userLanguage: String,
+ defaultLanguage: String = "en"): List {
+ val result = ArrayList()
+
+ val policies = get("policies")
+ if (policies is Map<*, *>) {
+ policies.keys.forEach { policyName ->
+ val localizedFlowDataLoginTerms = LocalizedFlowDataLoginTerms()
+ localizedFlowDataLoginTerms.policyName = policyName as String
+
+ val policy = policies[policyName]
+
+ // Enter this policy
+ if (policy is Map<*, *>) {
+ // Version
+ localizedFlowDataLoginTerms.version = policy["version"] as String?
+
+ var userLanguageUrlAndName: UrlAndName? = null
+ var defaultLanguageUrlAndName: UrlAndName? = null
+ var firstUrlAndName: UrlAndName? = null
+
+ // Search for language
+ policy.keys.forEach { policyKey ->
+ when (policyKey) {
+ "version" -> Unit // Ignore
+ userLanguage -> {
+ // We found the data for the user language
+ userLanguageUrlAndName = extractUrlAndName(policy[policyKey])
+ }
+ defaultLanguage -> {
+ // We found default language
+ defaultLanguageUrlAndName = extractUrlAndName(policy[policyKey])
+ }
+ else -> {
+ if (firstUrlAndName == null) {
+ // Get at least some data
+ firstUrlAndName = extractUrlAndName(policy[policyKey])
+ }
+ }
+ }
+ }
+
+ // Copy found language data by priority
+ when {
+ userLanguageUrlAndName != null -> {
+ localizedFlowDataLoginTerms.localizedUrl = userLanguageUrlAndName!!.url
+ localizedFlowDataLoginTerms.localizedName = userLanguageUrlAndName!!.name
+ }
+ defaultLanguageUrlAndName != null -> {
+ localizedFlowDataLoginTerms.localizedUrl = defaultLanguageUrlAndName!!.url
+ localizedFlowDataLoginTerms.localizedName = defaultLanguageUrlAndName!!.name
+ }
+ firstUrlAndName != null -> {
+ localizedFlowDataLoginTerms.localizedUrl = firstUrlAndName!!.url
+ localizedFlowDataLoginTerms.localizedName = firstUrlAndName!!.name
+ }
+ }
+ }
+
+ result.add(localizedFlowDataLoginTerms)
+ }
+ }
+
+ return result
+}
+
+private fun extractUrlAndName(policyData: Any?): UrlAndName? {
+ if (policyData is Map<*, *>) {
+ val url = policyData["url"] as String?
+ val name = policyData["name"] as String?
+
+ if (url != null && name != null) {
+ return UrlAndName(url, name)
+ }
+ }
+ return null
+}
diff --git a/vector/src/main/res/layout/fragment_login_terms.xml b/vector/src/main/res/layout/fragment_login_terms.xml
new file mode 100644
index 0000000000..98f773e284
--- /dev/null
+++ b/vector/src/main/res/layout/fragment_login_terms.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vector/src/main/res/layout/item_policy.xml b/vector/src/main/res/layout/item_policy.xml
new file mode 100644
index 0000000000..f28beef73d
--- /dev/null
+++ b/vector/src/main/res/layout/item_policy.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
From 9aa270c7ad8aa97f1a2d72e232b1d633b8d88ea8 Mon Sep 17 00:00:00 2001
From: Benoit Marty
Date: Tue, 19 Nov 2019 14:51:51 +0100
Subject: [PATCH 038/189] Login screens: Perform dummy action when user does
not want to enter an email -> account created!
---
.../auth/registration/RegistrationWizard.kt | 2 +
.../registration/DefaultRegistrationWizard.kt | 15 +++++++
.../riotx/features/login/LoginAction.kt | 1 +
.../LoginGenericTextInputFormFragment.kt | 19 ++++++++-
.../riotx/features/login/LoginViewModel.kt | 39 +++++++++++++++++--
5 files changed, 72 insertions(+), 4 deletions(-)
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/registration/RegistrationWizard.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/registration/RegistrationWizard.kt
index 85ac0d0aae..6e967fc235 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/registration/RegistrationWizard.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/registration/RegistrationWizard.kt
@@ -29,5 +29,7 @@ interface RegistrationWizard {
fun acceptTerms(callback: MatrixCallback): Cancelable
+ fun dummy(callback: MatrixCallback): Cancelable
+
// TODO Add other method here
}
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/registration/DefaultRegistrationWizard.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/registration/DefaultRegistrationWizard.kt
index c81c6221ea..ef3e8d1c30 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/registration/DefaultRegistrationWizard.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/registration/DefaultRegistrationWizard.kt
@@ -90,6 +90,21 @@ internal class DefaultRegistrationWizard(private val homeServerConnectionConfig:
), callback)
}
+ override fun dummy(callback: MatrixCallback): Cancelable {
+ val safeSession = currentSession ?: run {
+ callback.onFailure(IllegalStateException("developer error, call createAccount() method first"))
+ return NoOpCancellable
+ }
+
+ return performRegistrationRequest(
+ RegistrationParams(
+ auth = AuthParams(
+ type = LoginFlowTypes.DUMMY,
+ session = safeSession
+ )
+ ), callback)
+ }
+
private fun performRegistrationRequest(registrationParams: RegistrationParams, callback: MatrixCallback): Cancelable {
val job = GlobalScope.launch(coroutineDispatchers.main) {
val result = runCatching {
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginAction.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginAction.kt
index ec6ae9ea88..2367b273ea 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginAction.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginAction.kt
@@ -37,6 +37,7 @@ sealed class LoginAction : VectorViewModelAction {
data class ConfirmMsisdn(val code: String) : RegisterAction()
data class CaptchaDone(val captchaResponse: String) : RegisterAction()
object AcceptTerms : RegisterAction()
+ object RegisterDummy : RegisterAction()
// Reset actions
open class ResetAction : LoginAction()
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginGenericTextInputFormFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginGenericTextInputFormFragment.kt
index 4e25769740..4ffd149620 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginGenericTextInputFormFragment.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginGenericTextInputFormFragment.kt
@@ -94,7 +94,24 @@ class LoginGenericTextInputFormFragment @Inject constructor() : AbstractLoginFra
@OnClick(R.id.loginGenericTextInputFormSubmit)
fun onSubmitClicked() {
- // TODO
+ val text = loginGenericTextInputFormTextInput.text.toString()
+
+ if (text.isEmpty()) {
+ // Perform dummy action
+ loginViewModel.handle(LoginAction.RegisterDummy)
+ } else {
+ when (params.mode) {
+ TextInputFormFragmentMode.SetEmail -> {
+ // TODO
+ }
+ TextInputFormFragmentMode.SetMsisdn -> {
+ // TODO
+ }
+ TextInputFormFragmentMode.ConfirmMsisdn -> {
+ // TODO
+ }
+ }
+ }
}
private fun setupSubmitButton() {
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginViewModel.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginViewModel.kt
index 8fa78da496..1dd445ca20 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginViewModel.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginViewModel.kt
@@ -101,9 +101,10 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
private fun handleRegisterAction(action: LoginAction.RegisterAction) {
when (action) {
- is LoginAction.RegisterWith -> handleRegisterWith(action)
- is LoginAction.CaptchaDone -> handleCaptchaDone(action)
- is LoginAction.AcceptTerms -> handleAcceptTerms()
+ is LoginAction.RegisterWith -> handleRegisterWith(action)
+ is LoginAction.CaptchaDone -> handleCaptchaDone(action)
+ is LoginAction.AcceptTerms -> handleAcceptTerms()
+ is LoginAction.RegisterDummy -> handleRegisterDummy()
// TODO Add other actions here
}
}
@@ -140,6 +141,38 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
})
}
+ private fun handleRegisterDummy() {
+ setState {
+ copy(
+ asyncRegistration = Loading()
+ )
+ }
+
+ currentTask = registrationWizard?.dummy(object : MatrixCallback {
+ override fun onSuccess(data: RegistrationResult) {
+ setState {
+ copy(
+ asyncRegistration = Success(data)
+ )
+ }
+
+ when (data) {
+ is RegistrationResult.Success -> onSessionCreated(data.session)
+ is RegistrationResult.FlowResponse -> onFlowResponse(data.flowResult)
+ }
+ }
+
+ override fun onFailure(failure: Throwable) {
+ // TODO Handled JobCancellationException
+ setState {
+ copy(
+ asyncRegistration = Fail(failure)
+ )
+ }
+ }
+ })
+ }
+
private fun handleRegisterWith(action: LoginAction.RegisterWith) {
setState {
copy(
From 1c03163a33b3911409c93e9efb6ec6491dff0775 Mon Sep 17 00:00:00 2001
From: Benoit Marty
Date: Tue, 19 Nov 2019 15:13:50 +0100
Subject: [PATCH 039/189] Login screens: prepare email and msisdn
---
.../auth/registration/RegistrationWizard.kt | 7 +-
.../registration/DefaultRegistrationWizard.kt | 43 +++++++-
.../LoginGenericTextInputFormFragment.kt | 6 +-
.../riotx/features/login/LoginViewModel.kt | 100 +++++++++++++++++-
4 files changed, 150 insertions(+), 6 deletions(-)
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/registration/RegistrationWizard.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/registration/RegistrationWizard.kt
index 6e967fc235..b17c8c9dfa 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/registration/RegistrationWizard.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/registration/RegistrationWizard.kt
@@ -31,5 +31,10 @@ interface RegistrationWizard {
fun dummy(callback: MatrixCallback): Cancelable
- // TODO Add other method here
+ fun addEmail(email: String, callback: MatrixCallback): Cancelable
+
+ fun addMsisdn(msisdn: String, callback: MatrixCallback): Cancelable
+
+ fun confirmMsisdn(code: String, callback: MatrixCallback): Cancelable
+
}
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/registration/DefaultRegistrationWizard.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/registration/DefaultRegistrationWizard.kt
index ef3e8d1c30..8d1bd8d393 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/registration/DefaultRegistrationWizard.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/registration/DefaultRegistrationWizard.kt
@@ -42,7 +42,6 @@ internal class DefaultRegistrationWizard(private val homeServerConnectionConfig:
private val coroutineDispatchers: MatrixCoroutineDispatchers,
private val sessionParamsStore: SessionParamsStore,
private val sessionManager: SessionManager) : RegistrationWizard {
-
private var currentSession: String? = null
private val authAPI = buildAuthAPI()
@@ -90,6 +89,48 @@ internal class DefaultRegistrationWizard(private val homeServerConnectionConfig:
), callback)
}
+ override fun addEmail(email: String, callback: MatrixCallback): Cancelable {
+ val safeSession = currentSession ?: run {
+ callback.onFailure(IllegalStateException("developer error, call createAccount() method first"))
+ return NoOpCancellable
+ }
+
+ // TODO
+ return performRegistrationRequest(
+ RegistrationParams(
+ // TODO
+ auth = AuthParams.createForEmailIdentity(safeSession, ThreePidCredentials(email))
+ ), callback)
+ }
+
+ override fun addMsisdn(msisdn: String, callback: MatrixCallback): Cancelable {
+ val safeSession = currentSession ?: run {
+ callback.onFailure(IllegalStateException("developer error, call createAccount() method first"))
+ return NoOpCancellable
+ }
+
+ // TODO
+ return performRegistrationRequest(
+ RegistrationParams(
+ // TODO
+ auth = AuthParams.createForEmailIdentity(safeSession, ThreePidCredentials(msisdn))
+ ), callback)
+ }
+
+ override fun confirmMsisdn(code: String, callback: MatrixCallback): Cancelable {
+ val safeSession = currentSession ?: run {
+ callback.onFailure(IllegalStateException("developer error, call createAccount() method first"))
+ return NoOpCancellable
+ }
+
+ // TODO
+ return performRegistrationRequest(
+ RegistrationParams(
+ // TODO
+ auth = AuthParams.createForEmailIdentity(safeSession, ThreePidCredentials(code))
+ ), callback)
+ }
+
override fun dummy(callback: MatrixCallback): Cancelable {
val safeSession = currentSession ?: run {
callback.onFailure(IllegalStateException("developer error, call createAccount() method first"))
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginGenericTextInputFormFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginGenericTextInputFormFragment.kt
index 4ffd149620..a2b5feb1b1 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginGenericTextInputFormFragment.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginGenericTextInputFormFragment.kt
@@ -102,13 +102,13 @@ class LoginGenericTextInputFormFragment @Inject constructor() : AbstractLoginFra
} else {
when (params.mode) {
TextInputFormFragmentMode.SetEmail -> {
- // TODO
+ loginViewModel.handle(LoginAction.AddEmail(text))
}
TextInputFormFragmentMode.SetMsisdn -> {
- // TODO
+ loginViewModel.handle(LoginAction.AddMsisdn(text))
}
TextInputFormFragmentMode.ConfirmMsisdn -> {
- // TODO
+ loginViewModel.handle(LoginAction.ConfirmMsisdn(text))
}
}
}
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginViewModel.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginViewModel.kt
index 1dd445ca20..6cc73233a7 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginViewModel.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginViewModel.kt
@@ -105,10 +105,108 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
is LoginAction.CaptchaDone -> handleCaptchaDone(action)
is LoginAction.AcceptTerms -> handleAcceptTerms()
is LoginAction.RegisterDummy -> handleRegisterDummy()
- // TODO Add other actions here
+ is LoginAction.AddEmail -> handleAddEmail(action)
+ is LoginAction.AddMsisdn -> handleAddMsisdn(action)
+ is LoginAction.ConfirmMsisdn -> handleConfirmMsisdn(action)
}
}
+ private fun handleConfirmMsisdn(action: LoginAction.ConfirmMsisdn) {
+ setState {
+ copy(
+ asyncRegistration = Loading()
+ )
+ }
+
+ currentTask = registrationWizard?.confirmMsisdn(action.code, object : MatrixCallback {
+ override fun onSuccess(data: RegistrationResult) {
+ setState {
+ copy(
+ asyncRegistration = Success(data)
+ )
+ }
+
+ when (data) {
+ is RegistrationResult.Success -> onSessionCreated(data.session)
+ is RegistrationResult.FlowResponse -> onFlowResponse(data.flowResult)
+ }
+ }
+
+ override fun onFailure(failure: Throwable) {
+ // TODO Handled JobCancellationException
+ setState {
+ copy(
+ asyncRegistration = Fail(failure)
+ )
+ }
+ }
+ })
+ }
+
+ private fun handleAddMsisdn(action: LoginAction.AddMsisdn) {
+ setState {
+ copy(
+ asyncRegistration = Loading()
+ )
+ }
+
+ currentTask = registrationWizard?.addMsisdn(action.msisdn, object : MatrixCallback {
+ override fun onSuccess(data: RegistrationResult) {
+ setState {
+ copy(
+ asyncRegistration = Success(data)
+ )
+ }
+
+ when (data) {
+ is RegistrationResult.Success -> onSessionCreated(data.session)
+ is RegistrationResult.FlowResponse -> onFlowResponse(data.flowResult)
+ }
+ }
+
+ override fun onFailure(failure: Throwable) {
+ // TODO Handled JobCancellationException
+ setState {
+ copy(
+ asyncRegistration = Fail(failure)
+ )
+ }
+ }
+ })
+ }
+
+ private fun handleAddEmail(action: LoginAction.AddEmail) {
+ setState {
+ copy(
+ asyncRegistration = Loading()
+ )
+ }
+
+ currentTask = registrationWizard?.addEmail(action.email, object : MatrixCallback {
+ override fun onSuccess(data: RegistrationResult) {
+ setState {
+ copy(
+ asyncRegistration = Success(data)
+ )
+ }
+
+ when (data) {
+ is RegistrationResult.Success -> onSessionCreated(data.session)
+ is RegistrationResult.FlowResponse -> onFlowResponse(data.flowResult)
+ }
+ }
+
+ override fun onFailure(failure: Throwable) {
+ // TODO Handled JobCancellationException
+ setState {
+ copy(
+ asyncRegistration = Fail(failure)
+ )
+ }
+ }
+ })
+ }
+
private fun handleAcceptTerms() {
setState {
copy(
From 1dc7dfc896e5b917084abf3d91535db525ffa9bc Mon Sep 17 00:00:00 2001
From: Benoit Marty
Date: Tue, 19 Nov 2019 16:04:57 +0100
Subject: [PATCH 040/189] Login screens: registration fallback
---
.../android/api/auth/data/Credentials.kt | 1 +
vector/src/main/assets/onLogin.js | 1 +
vector/src/main/assets/onRegistered.js | 1 +
vector/src/main/assets/sendObject.js | 1 +
.../features/login/JavascriptResponse.kt | 39 +++++++++
.../riotx/features/login/LoginActivity.kt | 19 ++++-
.../features/login/LoginCaptchaFragment.kt | 10 ---
.../riotx/features/login/LoginWebFragment.kt | 79 ++++---------------
.../riotx/features/login/SupportedStage.kt | 30 +++++++
vector/src/main/res/values/strings_riotX.xml | 1 +
10 files changed, 105 insertions(+), 77 deletions(-)
create mode 100644 vector/src/main/assets/onLogin.js
create mode 100644 vector/src/main/assets/onRegistered.js
create mode 100644 vector/src/main/assets/sendObject.js
create mode 100644 vector/src/main/java/im/vector/riotx/features/login/JavascriptResponse.kt
create mode 100644 vector/src/main/java/im/vector/riotx/features/login/SupportedStage.kt
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/data/Credentials.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/data/Credentials.kt
index 089129967b..082ffe8f1a 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/data/Credentials.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/data/Credentials.kt
@@ -31,4 +31,5 @@ data class Credentials(
@Json(name = "access_token") val accessToken: String,
@Json(name = "refresh_token") val refreshToken: String?,
@Json(name = "device_id") val deviceId: String?
+ // TODO Add Wellknown
)
diff --git a/vector/src/main/assets/onLogin.js b/vector/src/main/assets/onLogin.js
new file mode 100644
index 0000000000..dd33227e40
--- /dev/null
+++ b/vector/src/main/assets/onLogin.js
@@ -0,0 +1 @@
+javascript:window.matrixLogin.onLogin = function(response) { sendObjectMessage({ 'action': 'onLogin', 'credentials': response }); };
\ No newline at end of file
diff --git a/vector/src/main/assets/onRegistered.js b/vector/src/main/assets/onRegistered.js
new file mode 100644
index 0000000000..67aca7b79e
--- /dev/null
+++ b/vector/src/main/assets/onRegistered.js
@@ -0,0 +1 @@
+javascript:window.matrixRegistration.onRegistered = function(homeserverUrl, userId, accessToken) { sendObjectMessage({ 'action': 'onRegistered', 'homeServer': homeserverUrl, 'userId': userId, 'accessToken': accessToken }); }
\ No newline at end of file
diff --git a/vector/src/main/assets/sendObject.js b/vector/src/main/assets/sendObject.js
new file mode 100644
index 0000000000..ebde72b58d
--- /dev/null
+++ b/vector/src/main/assets/sendObject.js
@@ -0,0 +1 @@
+javascript:window.sendObjectMessage = function(parameters) { var iframe = document.createElement('iframe'); iframe.setAttribute('src', 'js:' + JSON.stringify(parameters)); document.documentElement.appendChild(iframe); iframe.parentNode.removeChild(iframe); iframe = null;};
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotx/features/login/JavascriptResponse.kt b/vector/src/main/java/im/vector/riotx/features/login/JavascriptResponse.kt
new file mode 100644
index 0000000000..4d88cf6097
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotx/features/login/JavascriptResponse.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019 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.riotx.features.login
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import im.vector.matrix.android.api.auth.data.Credentials
+
+@JsonClass(generateAdapter = true)
+data class JavascriptResponse(
+ @Json(name = "action")
+ val action: String? = null,
+
+ /**
+ * Use for captcha result
+ */
+ @Json(name = "response")
+ val response: String? = null,
+
+ /**
+ * Used for login/registration result
+ */
+ @Json(name = "credentials")
+ val credentials: Credentials? = null
+)
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt
index 6644b2c193..95206afefe 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt
@@ -103,9 +103,9 @@ class LoginActivity : VectorBaseActivity() {
when (loginViewEvents) {
is LoginViewEvents.RegistrationFlowResult -> {
// Check that all flows are supported by the application
- if (loginViewEvents.flowResult.missingStages.any { it is Stage.Other }) {
+ if (loginViewEvents.flowResult.missingStages.any { !it.isSupported() }) {
// Display a popup to propose use web fallback
- // TODO
+ onRegistrationStageNotSupported()
} else {
// Go on with registration flow
// loginSharedActionViewModel.post(LoginNavigation.OnSignModeSelected)
@@ -159,7 +159,9 @@ class LoginActivity : VectorBaseActivity() {
private fun onSignModeSelected() {
when (loginViewModel.signMode) {
SignMode.Unknown -> error("Sign mode has to be set before calling this method")
- SignMode.SignUp -> addFragmentToBackstack(R.id.loginFragmentContainer, LoginFragment::class.java)
+ SignMode.SignUp -> {
+ // This is managed by the LoginViewEvents
+ }
SignMode.SignIn -> {
// It depends on the LoginMode
withState(loginViewModel) {
@@ -174,6 +176,17 @@ class LoginActivity : VectorBaseActivity() {
}
}
+ private fun onRegistrationStageNotSupported() {
+ AlertDialog.Builder(this)
+ .setTitle(R.string.app_name)
+ .setMessage(getString(R.string.login_registration_not_supported))
+ .setPositiveButton(R.string.yes) { _, _ ->
+ addFragmentToBackstack(R.id.loginFragmentContainer, LoginWebFragment::class.java)
+ }
+ .setNegativeButton(R.string.no, null)
+ .show()
+ }
+
private fun onLoginModeNotSupported(unsupportedLoginMode: LoginMode.Unsupported) {
AlertDialog.Builder(this)
.setTitle(R.string.app_name)
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginCaptchaFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginCaptchaFragment.kt
index b7a4ced8a3..a3dc9b4d9a 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginCaptchaFragment.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginCaptchaFragment.kt
@@ -27,8 +27,6 @@ import android.view.View
import android.webkit.*
import androidx.appcompat.app.AlertDialog
import com.airbnb.mvrx.args
-import com.squareup.moshi.Json
-import com.squareup.moshi.JsonClass
import im.vector.matrix.android.internal.di.MoshiProvider
import im.vector.riotx.R
import im.vector.riotx.core.utils.AssetReader
@@ -44,14 +42,6 @@ data class LoginCaptchaFragmentArgument(
val siteKey: String
) : Parcelable
-@JsonClass(generateAdapter = true)
-data class JavascriptResponse(
- @Json(name = "action")
- val action: String? = null,
- @Json(name = "response")
- val response: String? = null
-)
-
/**
* In this screen, the user is asked to confirm he is not a robot
*/
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginWebFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginWebFragment.kt
index d7230f0075..5b0fe743cf 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginWebFragment.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginWebFragment.kt
@@ -30,10 +30,9 @@ import android.webkit.SslErrorHandler
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.appcompat.app.AlertDialog
-import im.vector.matrix.android.api.auth.data.Credentials
-import im.vector.matrix.android.api.util.JsonDict
import im.vector.matrix.android.internal.di.MoshiProvider
import im.vector.riotx.R
+import im.vector.riotx.core.utils.AssetReader
import kotlinx.android.synthetic.main.fragment_login_web.*
import timber.log.Timber
import java.net.URLDecoder
@@ -43,7 +42,7 @@ import javax.inject.Inject
* This screen is displayed for SSO login and also when the application does not support login flow or registration flow
* of the homeserfver, as a fallback to login or to create an account
*/
-class LoginWebFragment @Inject constructor() : AbstractLoginFragment() {
+class LoginWebFragment @Inject constructor(private val assetReader: AssetReader) : AbstractLoginFragment() {
private lateinit var homeServerUrl: String
private lateinit var signMode: SignMode
@@ -151,33 +150,17 @@ class LoginWebFragment @Inject constructor() : AbstractLoginFragment() {
// avoid infinite onPageFinished call
if (url.startsWith("http")) {
// Generic method to make a bridge between JS and the UIWebView
- val mxcJavascriptSendObjectMessage = "javascript:window.sendObjectMessage = function(parameters) {" +
- " var iframe = document.createElement('iframe');" +
- " iframe.setAttribute('src', 'js:' + JSON.stringify(parameters));" +
- " document.documentElement.appendChild(iframe);" +
- " iframe.parentNode.removeChild(iframe); iframe = null;" +
- " };"
-
+ val mxcJavascriptSendObjectMessage = assetReader.readAssetFile("sendObject.js")
view.loadUrl(mxcJavascriptSendObjectMessage)
if (signMode == SignMode.SignIn) {
// The function the fallback page calls when the login is complete
- val mxcJavascriptOnRegistered = "javascript:window.matrixLogin.onLogin = function(response) {" +
- " sendObjectMessage({ 'action': 'onLogin', 'credentials': response });" +
- " };"
-
- view.loadUrl(mxcJavascriptOnRegistered)
+ val mxcJavascriptOnLogin = assetReader.readAssetFile("onLogin.js")
+ view.loadUrl(mxcJavascriptOnLogin)
} else {
// MODE_REGISTER
// The function the fallback page calls when the registration is complete
- val mxcJavascriptOnRegistered = "javascript:window.matrixRegistration.onRegistered" +
- " = function(homeserverUrl, userId, accessToken) {" +
- " sendObjectMessage({ 'action': 'onRegistered'," +
- " 'homeServer': homeserverUrl," +
- " 'userId': userId," +
- " 'accessToken': accessToken });" +
- " };"
-
+ val mxcJavascriptOnRegistered = assetReader.readAssetFile("onRegistered.js")
view.loadUrl(mxcJavascriptOnRegistered)
}
}
@@ -209,46 +192,27 @@ class LoginWebFragment @Inject constructor() : AbstractLoginFragment() {
override fun shouldOverrideUrlLoading(view: WebView, url: String?): Boolean {
if (null != url && url.startsWith("js:")) {
var json = url.substring(3)
- var parameters: Map? = null
+ var parameters: JavascriptResponse? = null
try {
// URL decode
json = URLDecoder.decode(json, "UTF-8")
-
- val adapter = MoshiProvider.providesMoshi().adapter(Map::class.java)
-
- @Suppress("UNCHECKED_CAST")
- parameters = adapter.fromJson(json) as JsonDict?
+ val adapter = MoshiProvider.providesMoshi().adapter(JavascriptResponse::class.java)
+ parameters = adapter.fromJson(json)
} catch (e: Exception) {
Timber.e(e, "## shouldOverrideUrlLoading() : fromJson failed")
}
// succeeds to parse parameters
if (parameters != null) {
- val action = parameters["action"] as String
+ val action = parameters.action
if (signMode == SignMode.SignIn) {
try {
if (action == "onLogin") {
- @Suppress("UNCHECKED_CAST")
- val credentials = parameters["credentials"] as Map
-
- val userId = credentials["user_id"]
- val accessToken = credentials["access_token"]
- val homeServer = credentials["home_server"]
- val deviceId = credentials["device_id"]
-
- // check if the parameters are defined
- if (null != homeServer && null != userId && null != accessToken) {
- val safeCredentials = Credentials(
- userId = userId,
- accessToken = accessToken,
- homeServer = homeServer,
- deviceId = deviceId,
- refreshToken = null
- )
-
- loginViewModel.handle(LoginAction.WebLoginSuccess(safeCredentials))
+ val credentials = parameters.credentials
+ if (credentials != null) {
+ loginViewModel.handle(LoginAction.WebLoginSuccess(credentials))
}
}
} catch (e: Exception) {
@@ -258,21 +222,8 @@ class LoginWebFragment @Inject constructor() : AbstractLoginFragment() {
// MODE_REGISTER
// check the required parameters
if (action == "onRegistered") {
- // TODO The keys are very strange, this code comes from Riot-Android...
- if (parameters.containsKey("homeServer")
- && parameters.containsKey("userId")
- && parameters.containsKey("accessToken")) {
- // We cannot parse Credentials here because of https://github.com/matrix-org/synapse/issues/4756
- // Build on object manually
- val credentials = Credentials(
- userId = parameters["userId"] as String,
- accessToken = parameters["accessToken"] as String,
- homeServer = parameters["homeServer"] as String,
- // TODO We need deviceId on RiotX...
- deviceId = "TODO",
- refreshToken = null
- )
-
+ val credentials = parameters.credentials
+ if (credentials != null) {
loginViewModel.handle(LoginAction.WebLoginSuccess(credentials))
}
}
diff --git a/vector/src/main/java/im/vector/riotx/features/login/SupportedStage.kt b/vector/src/main/java/im/vector/riotx/features/login/SupportedStage.kt
new file mode 100644
index 0000000000..5fd4505b00
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotx/features/login/SupportedStage.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2019 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.riotx.features.login
+
+import im.vector.matrix.android.api.auth.registration.Stage
+
+/**
+ * Stage.Other is not supported, as well as any other new stage added to the SDK before it is added to the list below
+ */
+fun Stage.isSupported(): Boolean {
+ return this is Stage.ReCaptcha
+ || this is Stage.Dummy
+ || this is Stage.Msisdn
+ || this is Stage.Terms
+ || this is Stage.Email
+}
diff --git a/vector/src/main/res/values/strings_riotX.xml b/vector/src/main/res/values/strings_riotX.xml
index abd44dc54c..6db6c1a2d1 100644
--- a/vector/src/main/res/values/strings_riotX.xml
+++ b/vector/src/main/res/values/strings_riotX.xml
@@ -56,6 +56,7 @@
An error occurred when loading the page: %1$s (%2$d)
The application is not able to signin to this homeserver. The homeserver supports the following signin type(s): %1$s.\n\nDo you want to signin using a web client?
+ The application is not able to create an account on this homeserver.\n\nDo you want to signup using a web client?
Reset password on %1$s
From c18c140ec9a00ecaaa1a308ece7312ace971d47c Mon Sep 17 00:00:00 2001
From: Benoit Marty
Date: Tue, 19 Nov 2019 17:25:33 +0100
Subject: [PATCH 041/189] Login screens: Animate the logo in screen transition
---
.../java/im/vector/riotx/core/extensions/Activity.kt | 8 +++++++-
.../im/vector/riotx/features/login/LoginActivity.kt | 10 +++++++++-
.../features/login/LoginServerSelectionFragment.kt | 10 ++++++++++
.../res/layout/fragment_login_server_selection.xml | 1 +
vector/src/main/res/layout/fragment_login_splash.xml | 1 +
5 files changed, 28 insertions(+), 2 deletions(-)
diff --git a/vector/src/main/java/im/vector/riotx/core/extensions/Activity.kt b/vector/src/main/java/im/vector/riotx/core/extensions/Activity.kt
index 6d7c3d39e6..f9f5d3b3d2 100644
--- a/vector/src/main/java/im/vector/riotx/core/extensions/Activity.kt
+++ b/vector/src/main/java/im/vector/riotx/core/extensions/Activity.kt
@@ -18,6 +18,7 @@ package im.vector.riotx.core.extensions
import android.os.Parcelable
import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentTransaction
import im.vector.riotx.core.platform.VectorBaseActivity
fun VectorBaseActivity.addFragment(frameId: Int, fragment: Fragment) {
@@ -44,8 +45,13 @@ fun VectorBaseActivity.addFragmentToBackstack(frameId: Int, fragment: Fragment,
supportFragmentManager.commitTransaction { replace(frameId, fragment).addToBackStack(tag) }
}
-fun VectorBaseActivity.addFragmentToBackstack(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null) {
+fun VectorBaseActivity.addFragmentToBackstack(frameId: Int,
+ fragmentClass: Class,
+ params: Parcelable? = null,
+ tag: String? = null,
+ option: ((FragmentTransaction) -> Unit)? = null) {
supportFragmentManager.commitTransaction {
+ option?.invoke(this)
replace(frameId, fragmentClass, params.toMvRxBundle(), tag).addToBackStack(tag)
}
}
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt
index 95206afefe..79d6eb874d 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt
@@ -18,7 +18,9 @@ package im.vector.riotx.features.login
import android.content.Context
import android.content.Intent
+import android.view.View
import androidx.appcompat.app.AlertDialog
+import androidx.core.view.ViewCompat
import androidx.core.view.isVisible
import androidx.fragment.app.FragmentManager
import com.airbnb.mvrx.viewModel
@@ -70,7 +72,13 @@ class LoginActivity : VectorBaseActivity() {
loginSharedActionViewModel.observe()
.subscribe {
when (it) {
- is LoginNavigation.OpenServerSelection -> addFragmentToBackstack(R.id.loginFragmentContainer, LoginServerSelectionFragment::class.java)
+ is LoginNavigation.OpenServerSelection -> addFragmentToBackstack(R.id.loginFragmentContainer, LoginServerSelectionFragment::class.java,
+ option = { ft ->
+ val view = findViewById(R.id.loginSplashLogo)
+ if (view != null) {
+ ft.addSharedElement(view, ViewCompat.getTransitionName(view) ?: "")
+ }
+ })
is LoginNavigation.OnServerSelectionDone -> onServerSelectionDone()
is LoginNavigation.OnSignModeSelected -> onSignModeSelected()
is LoginNavigation.OnLoginFlowRetrieved -> onLoginFlowRetrieved()
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginServerSelectionFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginServerSelectionFragment.kt
index e819389b9c..b08c46e335 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginServerSelectionFragment.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginServerSelectionFragment.kt
@@ -16,8 +16,10 @@
package im.vector.riotx.features.login
+import android.os.Build
import android.os.Bundle
import android.view.View
+import androidx.transition.TransitionInflater
import butterknife.OnClick
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Success
@@ -35,6 +37,14 @@ class LoginServerSelectionFragment @Inject constructor() : AbstractLoginFragment
override fun getLayoutResId() = R.layout.fragment_login_server_selection
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ sharedElementEnterTransition = TransitionInflater.from(context).inflateTransition(android.R.transition.move)
+ }
+ }
+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
diff --git a/vector/src/main/res/layout/fragment_login_server_selection.xml b/vector/src/main/res/layout/fragment_login_server_selection.xml
index 570272e392..d380cc39c9 100644
--- a/vector/src/main/res/layout/fragment_login_server_selection.xml
+++ b/vector/src/main/res/layout/fragment_login_server_selection.xml
@@ -16,6 +16,7 @@
diff --git a/vector/src/main/res/layout/fragment_login_splash.xml b/vector/src/main/res/layout/fragment_login_splash.xml
index f19e2e6603..c0d9a7c2c6 100644
--- a/vector/src/main/res/layout/fragment_login_splash.xml
+++ b/vector/src/main/res/layout/fragment_login_splash.xml
@@ -14,6 +14,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/riotx_logo"
+ android:transitionName="loginLogoTransition"
app:layout_constraintBottom_toTopOf="@+id/loginSplashTitle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
From 6d8e5b892e56d4c96da251e3ca323cdb1d25af08 Mon Sep 17 00:00:00 2001
From: Benoit Marty
Date: Tue, 19 Nov 2019 17:28:39 +0100
Subject: [PATCH 042/189] Login screens: Show disclaimer dialog only in
HomeActivity, now that RiotX supports registration
---
.../java/im/vector/riotx/features/login/LoginActivity.kt | 7 -------
1 file changed, 7 deletions(-)
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt
index 79d6eb874d..3c7148b802 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt
@@ -32,7 +32,6 @@ import im.vector.riotx.core.di.ScreenComponent
import im.vector.riotx.core.extensions.addFragment
import im.vector.riotx.core.extensions.addFragmentToBackstack
import im.vector.riotx.core.platform.VectorBaseActivity
-import im.vector.riotx.features.disclaimer.showDisclaimerDialog
import im.vector.riotx.features.home.HomeActivity
import im.vector.riotx.features.login.terms.LoginTermsFragment
import im.vector.riotx.features.login.terms.LoginTermsFragmentArgument
@@ -242,12 +241,6 @@ class LoginActivity : VectorBaseActivity() {
}
}
- override fun onResume() {
- super.onResume()
-
- showDisclaimerDialog(this)
- }
-
companion object {
private const val EXTRA_CONFIG = "EXTRA_CONFIG"
From 375833482445f494a39ac41d5eabb964daecedaa Mon Sep 17 00:00:00 2001
From: Benoit Marty
Date: Tue, 19 Nov 2019 18:09:05 +0100
Subject: [PATCH 043/189] Login screens: cleanup the Fragment stack after
completing stage
---
.../riotx/features/login/LoginActivity.kt | 24 ++++++++++++-------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt
index 3c7148b802..a0b718f134 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt
@@ -222,26 +222,34 @@ class LoginActivity : VectorBaseActivity() {
}
}
- // TODO Unstack fragment when stage is complete
private fun doStage(stage: Stage) {
+ // Ensure there is no fragment for registration stage in the backstack
+ supportFragmentManager.popBackStack(FRAGMENT_REGISTRATION_STAGE_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE)
+
when (stage) {
is Stage.ReCaptcha -> addFragmentToBackstack(R.id.loginFragmentContainer,
- LoginCaptchaFragment::class.java, LoginCaptchaFragmentArgument(stage.publicKey))
+ LoginCaptchaFragment::class.java,
+ LoginCaptchaFragmentArgument(stage.publicKey),
+ tag = FRAGMENT_REGISTRATION_STAGE_TAG)
is Stage.Email -> addFragmentToBackstack(R.id.loginFragmentContainer,
LoginGenericTextInputFormFragment::class.java,
- LoginGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.SetEmail, stage.mandatory))
- is Stage.Msisdn
- -> addFragmentToBackstack(R.id.loginFragmentContainer,
+ LoginGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.SetEmail, stage.mandatory),
+ tag = FRAGMENT_REGISTRATION_STAGE_TAG)
+ is Stage.Msisdn -> addFragmentToBackstack(R.id.loginFragmentContainer,
LoginGenericTextInputFormFragment::class.java,
- LoginGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.SetMsisdn, stage.mandatory))
+ LoginGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.SetMsisdn, stage.mandatory),
+ tag = FRAGMENT_REGISTRATION_STAGE_TAG)
is Stage.Terms -> addFragmentToBackstack(R.id.loginFragmentContainer,
LoginTermsFragment::class.java,
- LoginTermsFragmentArgument(stage.policies.toLocalizedLoginTerms(getString(R.string.resources_language))))
- else -> TODO()
+ LoginTermsFragmentArgument(stage.policies.toLocalizedLoginTerms(getString(R.string.resources_language))),
+ tag = FRAGMENT_REGISTRATION_STAGE_TAG)
+ else -> Unit // Should not happen
}
}
companion object {
+ private const val FRAGMENT_REGISTRATION_STAGE_TAG = "FRAGMENT_REGISTRATION_STAGE_TAG"
+
private const val EXTRA_CONFIG = "EXTRA_CONFIG"
fun newIntent(context: Context, loginConfig: LoginConfig?): Intent {
From 8ae9544b48a792a13412240186d1589b66aab305 Mon Sep 17 00:00:00 2001
From: Benoit Marty
Date: Tue, 19 Nov 2019 18:23:33 +0100
Subject: [PATCH 044/189] Login screens: Loading on Captcha step
---
.../features/login/LoginCaptchaFragment.kt | 12 +++-
.../res/layout/fragment_login_captcha.xml | 62 ++++++++++---------
2 files changed, 45 insertions(+), 29 deletions(-)
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginCaptchaFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginCaptchaFragment.kt
index a3dc9b4d9a..7728d4eaac 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginCaptchaFragment.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginCaptchaFragment.kt
@@ -18,6 +18,7 @@ package im.vector.riotx.features.login
import android.annotation.SuppressLint
import android.content.DialogInterface
+import android.graphics.Bitmap
import android.net.http.SslError
import android.os.Build
import android.os.Bundle
@@ -26,6 +27,7 @@ import android.view.KeyEvent
import android.view.View
import android.webkit.*
import androidx.appcompat.app.AlertDialog
+import androidx.core.view.isVisible
import com.airbnb.mvrx.args
import im.vector.matrix.android.internal.di.MoshiProvider
import im.vector.riotx.R
@@ -72,10 +74,18 @@ class LoginCaptchaFragment @Inject constructor(private val assetReader: AssetRea
loginCaptchaWevView.requestLayout()
loginCaptchaWevView.webViewClient = object : WebViewClient() {
+ override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
+ super.onPageStarted(view, url, favicon)
+
+ // Show loader
+ loginCaptchaProgress.isVisible = true
+ }
+
override fun onPageFinished(view: WebView, url: String) {
super.onPageFinished(view, url)
- // TODO Hide loader
+ // Hide loader
+ loginCaptchaProgress.isVisible = false
}
override fun onReceivedSslError(view: WebView, handler: SslErrorHandler, error: SslError) {
diff --git a/vector/src/main/res/layout/fragment_login_captcha.xml b/vector/src/main/res/layout/fragment_login_captcha.xml
index 8dec490a14..2dfc37871a 100644
--- a/vector/src/main/res/layout/fragment_login_captcha.xml
+++ b/vector/src/main/res/layout/fragment_login_captcha.xml
@@ -2,41 +2,47 @@
+ android:layout_height="match_parent"
+ android:paddingStart="16dp"
+ android:paddingTop="32dp"
+ android:paddingEnd="16dp"
+ android:paddingBottom="16dp">
-
+ app:layout_constraintTop_toTopOf="parent" />
-
+
-
+
-
-
+
From a8f24e5c39b7a6388295ae3bf2a676412c4c76b7 Mon Sep 17 00:00:00 2001
From: Benoit Marty
Date: Tue, 19 Nov 2019 18:44:11 +0100
Subject: [PATCH 045/189] Login screens: a11y
---
vector/src/main/res/layout/fragment_loading.xml | 3 ++-
vector/src/main/res/layout/fragment_login.xml | 3 ++-
vector/src/main/res/layout/fragment_login_captcha.xml | 4 +++-
.../res/layout/fragment_login_generic_text_input_form.xml | 3 ++-
.../src/main/res/layout/fragment_login_reset_password.xml | 3 ++-
.../res/layout/fragment_login_reset_password_success.xml | 3 ++-
.../src/main/res/layout/fragment_login_server_selection.xml | 6 ++++++
.../src/main/res/layout/fragment_login_server_url_form.xml | 4 +++-
.../res/layout/fragment_login_signup_signin_selection.xml | 1 +
vector/src/main/res/layout/fragment_login_splash.xml | 3 +++
vector/src/main/res/layout/fragment_login_terms.xml | 1 +
vector/src/main/res/layout/item_policy.xml | 5 +----
vector/src/main/res/values/strings_riotX.xml | 5 +++++
13 files changed, 33 insertions(+), 11 deletions(-)
diff --git a/vector/src/main/res/layout/fragment_loading.xml b/vector/src/main/res/layout/fragment_loading.xml
index 96bafda319..ae605097cd 100644
--- a/vector/src/main/res/layout/fragment_loading.xml
+++ b/vector/src/main/res/layout/fragment_loading.xml
@@ -4,12 +4,13 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
-
+
+ android:layout_gravity="center_horizontal"
+ android:importantForAccessibility="no" />
@@ -26,15 +27,16 @@
android:text="@string/auth_recaptcha_message"
app:layout_constraintTop_toBottomOf="@+id/logoImageView" />
+
-
+ android:layout_gravity="center_horizontal"
+ android:importantForAccessibility="no" />
+ android:layout_gravity="center_horizontal"
+ android:importantForAccessibility="no" />
+ android:layout_gravity="center_horizontal"
+ android:importantForAccessibility="no" />
+ android:layout_marginBottom="130dp"
+ android:importantForAccessibility="no" />
diff --git a/vector/src/main/res/layout/item_policy.xml b/vector/src/main/res/layout/item_policy.xml
index f28beef73d..ae68e33598 100644
--- a/vector/src/main/res/layout/item_policy.xml
+++ b/vector/src/main/res/layout/item_policy.xml
@@ -10,8 +10,6 @@
android:id="@+id/adapter_item_policy_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
- android:layout_marginLeft="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
@@ -37,8 +35,7 @@
android:id="@+id/adapter_item_policy_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginEnd="16dp"
- android:layout_marginRight="16dp"
+ android:importantForAccessibility="no"
android:rotationY="@integer/rtl_mirror_flip"
android:src="@drawable/ic_material_chevron_right_black"
app:layout_constraintBottom_toBottomOf="parent"
diff --git a/vector/src/main/res/values/strings_riotX.xml b/vector/src/main/res/values/strings_riotX.xml
index 6db6c1a2d1..bf8f22e59a 100644
--- a/vector/src/main/res/values/strings_riotX.xml
+++ b/vector/src/main/res/values/strings_riotX.xml
@@ -96,4 +96,9 @@
Next
That username is taken
+ Select matrix.org
+ Select modular
+ Select a custom homeserver
+ Please perform the captcha challenge
+
From 20f969d563f66ac43fef5645fa945adc20f71d78 Mon Sep 17 00:00:00 2001
From: Benoit Marty
Date: Tue, 19 Nov 2019 19:16:34 +0100
Subject: [PATCH 046/189] Login screens: fix issue on terms
---
.../login/terms/LoginTermsFragment.kt | 19 +++++++-----
.../features/login/terms/PolicyController.kt | 7 +++--
.../terms/{PolicyModel.kt => PolicyItem.kt} | 7 ++++-
.../src/main/res/color/login_button_tint.xml | 7 +++++
.../main/res/layout/fragment_login_terms.xml | 13 ++++++--
vector/src/main/res/layout/item_policy.xml | 31 ++++++++++++++-----
vector/src/main/res/values/strings_riotX.xml | 1 +
7 files changed, 65 insertions(+), 20 deletions(-)
rename vector/src/main/java/im/vector/riotx/features/login/terms/{PolicyModel.kt => PolicyItem.kt} (89%)
create mode 100644 vector/src/main/res/color/login_button_tint.xml
diff --git a/vector/src/main/java/im/vector/riotx/features/login/terms/LoginTermsFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/terms/LoginTermsFragment.kt
index 3e202b5245..4b98563503 100755
--- a/vector/src/main/java/im/vector/riotx/features/login/terms/LoginTermsFragment.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/terms/LoginTermsFragment.kt
@@ -51,6 +51,7 @@ class LoginTermsFragment @Inject constructor(private val policyController: Polic
super.onViewCreated(view, savedInstanceState)
loginTermsPolicyList.setController(policyController)
+ policyController.homeServer = loginViewModel.getHomeServerUrlSimple()
policyController.listener = this
val list = ArrayList()
@@ -83,14 +84,18 @@ class LoginTermsFragment @Inject constructor(private val policyController: Polic
}
override fun openPolicy(localizedFlowDataLoginTerms: LocalizedFlowDataLoginTerms) {
- openUrlInExternalBrowser(requireContext(), localizedFlowDataLoginTerms.localizedUrl!!)
+ localizedFlowDataLoginTerms.localizedUrl
+ ?.takeIf { it.isNotBlank() }
+ ?.let {
+ openUrlInExternalBrowser(requireContext(), it)
- // This code crashed, because user is not authenticated yet
- //val intent = VectorWebViewActivity.getIntent(requireContext(),
- // localizedFlowDataLoginTerms.localizedUrl!!,
- // localizedFlowDataLoginTerms.localizedName!!,
- // WebViewMode.DEFAULT)
- //startActivity(intent)
+ // This code crashed, because user is not authenticated yet
+ //val intent = VectorWebViewActivity.getIntent(requireContext(),
+ // localizedFlowDataLoginTerms.localizedUrl!!,
+ // localizedFlowDataLoginTerms.localizedName!!,
+ // WebViewMode.DEFAULT)
+ //startActivity(intent)
+ }
}
@OnClick(R.id.loginTermsSubmit)
diff --git a/vector/src/main/java/im/vector/riotx/features/login/terms/PolicyController.kt b/vector/src/main/java/im/vector/riotx/features/login/terms/PolicyController.kt
index 6e86d40e3d..c301463c2a 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/terms/PolicyController.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/terms/PolicyController.kt
@@ -25,12 +25,15 @@ class PolicyController @Inject constructor() : TypedEpoxyController) {
data.forEach { entry ->
- policy {
+ policyItem {
id(entry.localizedFlowDataLoginTerms.policyName)
checked(entry.checked)
- title(entry.localizedFlowDataLoginTerms.localizedName!!)
+ title(entry.localizedFlowDataLoginTerms.localizedName)
+ subtitle(homeServer)
clickListener(View.OnClickListener { listener?.openPolicy(entry.localizedFlowDataLoginTerms) })
checkChangeListener { _, isChecked ->
diff --git a/vector/src/main/java/im/vector/riotx/features/login/terms/PolicyModel.kt b/vector/src/main/java/im/vector/riotx/features/login/terms/PolicyItem.kt
similarity index 89%
rename from vector/src/main/java/im/vector/riotx/features/login/terms/PolicyModel.kt
rename to vector/src/main/java/im/vector/riotx/features/login/terms/PolicyItem.kt
index 85b7c80dd0..9931d33068 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/terms/PolicyModel.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/terms/PolicyItem.kt
@@ -27,13 +27,16 @@ import im.vector.riotx.R
import im.vector.riotx.core.epoxy.VectorEpoxyHolder
@EpoxyModelClass(layout = R.layout.item_policy)
-abstract class PolicyModel : EpoxyModelWithHolder() {
+abstract class PolicyItem : EpoxyModelWithHolder() {
@EpoxyAttribute
var checked: Boolean = false
@EpoxyAttribute
var title: String? = null
+ @EpoxyAttribute
+ var subtitle: String? = null
+
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
var checkChangeListener: CompoundButton.OnCheckedChangeListener? = null
@@ -45,6 +48,7 @@ abstract class PolicyModel : EpoxyModelWithHolder() {
it.checkbox.isChecked = checked
it.checkbox.setOnCheckedChangeListener(checkChangeListener)
it.title.text = title
+ it.subtitle.text = subtitle
it.view.setOnClickListener(clickListener)
}
}
@@ -58,5 +62,6 @@ abstract class PolicyModel : EpoxyModelWithHolder() {
class Holder : VectorEpoxyHolder() {
val checkbox by bind(R.id.adapter_item_policy_checkbox)
val title by bind(R.id.adapter_item_policy_title)
+ val subtitle by bind(R.id.adapter_item_policy_subtitle)
}
}
diff --git a/vector/src/main/res/color/login_button_tint.xml b/vector/src/main/res/color/login_button_tint.xml
new file mode 100644
index 0000000000..719335766c
--- /dev/null
+++ b/vector/src/main/res/color/login_button_tint.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vector/src/main/res/layout/fragment_login_terms.xml b/vector/src/main/res/layout/fragment_login_terms.xml
index c595587a5d..e44139e18b 100644
--- a/vector/src/main/res/layout/fragment_login_terms.xml
+++ b/vector/src/main/res/layout/fragment_login_terms.xml
@@ -14,14 +14,23 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
+
+
+ app:layout_constraintTop_toBottomOf="@+id/loginTermsTitle" />
+ android:foreground="?attr/selectableItemBackground"
+ android:minHeight="72dp">
-
+
+
diff --git a/vector/src/main/res/values/strings_riotX.xml b/vector/src/main/res/values/strings_riotX.xml
index bf8f22e59a..8a013a255b 100644
--- a/vector/src/main/res/values/strings_riotX.xml
+++ b/vector/src/main/res/values/strings_riotX.xml
@@ -100,5 +100,6 @@
Select modular
Select a custom homeserver
Please perform the captcha challenge
+ Accept terms to continue
From 7caa8ce3bc4c34d887979f2281cd0dde75b83ed0 Mon Sep 17 00:00:00 2001
From: Benoit Marty
Date: Wed, 20 Nov 2019 10:18:14 +0100
Subject: [PATCH 047/189] Login screens: disabled registration
---
.../vector/riotx/core/error/ErrorFormatter.kt | 24 ++++++++++++-----
.../riotx/features/login/LoginActivity.kt | 27 +++++++++++++++++++
.../riotx/features/login/LoginViewEvents.kt | 1 +
.../riotx/features/login/LoginViewModel.kt | 12 +++++++++
vector/src/main/res/values/strings_riotX.xml | 2 ++
5 files changed, 59 insertions(+), 7 deletions(-)
diff --git a/vector/src/main/java/im/vector/riotx/core/error/ErrorFormatter.kt b/vector/src/main/java/im/vector/riotx/core/error/ErrorFormatter.kt
index 29506cf880..c943a86fbc 100644
--- a/vector/src/main/java/im/vector/riotx/core/error/ErrorFormatter.kt
+++ b/vector/src/main/java/im/vector/riotx/core/error/ErrorFormatter.kt
@@ -35,13 +35,14 @@ class ErrorFormatter @Inject constructor(private val stringProvider: StringProvi
return when (throwable) {
null -> null
is Failure.NetworkConnection -> {
- if (throwable.ioException is SocketTimeoutException) {
- stringProvider.getString(R.string.error_network_timeout)
- } else if (throwable.ioException is UnknownHostException) {
- // Invalid homeserver?
- stringProvider.getString(R.string.login_error_unknown_host)
- } else {
- stringProvider.getString(R.string.error_no_network)
+ when {
+ throwable.ioException is SocketTimeoutException ->
+ stringProvider.getString(R.string.error_network_timeout)
+ throwable.ioException is UnknownHostException ->
+ // Invalid homeserver?
+ stringProvider.getString(R.string.login_error_unknown_host)
+ else ->
+ stringProvider.getString(R.string.error_no_network)
}
}
is Failure.ServerError -> {
@@ -57,6 +58,15 @@ class ErrorFormatter @Inject constructor(private val stringProvider: StringProvi
throwable.error.code == MatrixError.USER_IN_USE -> {
stringProvider.getString(R.string.login_signup_error_user_in_use)
}
+ throwable.error.code == MatrixError.BAD_JSON -> {
+ stringProvider.getString(R.string.login_error_bad_json)
+ }
+ throwable.error.code == MatrixError.NOT_JSON -> {
+ stringProvider.getString(R.string.login_error_not_json)
+ }
+ throwable.error.code == MatrixError.LIMIT_EXCEEDED -> {
+ stringProvider.getString(R.string.login_error_limit_exceeded)
+ }
else -> {
throwable.error.message.takeIf { it.isNotEmpty() }
?: throwable.error.code.takeIf { it.isNotEmpty() }
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt
index a0b718f134..e7cb90f5df 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt
@@ -27,8 +27,11 @@ import com.airbnb.mvrx.viewModel
import com.airbnb.mvrx.withState
import im.vector.matrix.android.api.auth.registration.FlowResult
import im.vector.matrix.android.api.auth.registration.Stage
+import im.vector.matrix.android.api.failure.Failure
+import im.vector.matrix.android.api.failure.MatrixError
import im.vector.riotx.R
import im.vector.riotx.core.di.ScreenComponent
+import im.vector.riotx.core.error.ErrorFormatter
import im.vector.riotx.core.extensions.addFragment
import im.vector.riotx.core.extensions.addFragmentToBackstack
import im.vector.riotx.core.platform.VectorBaseActivity
@@ -38,6 +41,7 @@ import im.vector.riotx.features.login.terms.LoginTermsFragmentArgument
import im.vector.riotx.features.login.terms.toLocalizedLoginTerms
import kotlinx.android.synthetic.main.activity_login.*
import javax.inject.Inject
+import javax.net.ssl.HttpsURLConnection
/**
* The LoginActivity manages the fragment navigation and also display the loading View
@@ -48,6 +52,7 @@ class LoginActivity : VectorBaseActivity() {
private lateinit var loginSharedActionViewModel: LoginSharedActionViewModel
@Inject lateinit var loginViewModelFactory: LoginViewModel.Factory
+ @Inject lateinit var errorFormatter: ErrorFormatter
override fun injectWith(injector: ScreenComponent) {
injector.inject(this)
@@ -124,9 +129,31 @@ class LoginActivity : VectorBaseActivity() {
}
}
}
+ is LoginViewEvents.RegistrationError -> displayRegistrationError(loginViewEvents.throwable)
}
}
+ private fun displayRegistrationError(throwable: Throwable) {
+ val message = when(throwable) {
+ is Failure.ServerError -> {
+ if(throwable.error.code == MatrixError.FORBIDDEN
+ && throwable.httpCode == HttpsURLConnection.HTTP_FORBIDDEN /* 403 */) {
+ getString(R.string.login_registration_disabled)
+ } else {
+ null
+ }
+ }
+ else -> null
+ }
+ ?: errorFormatter.toHumanReadable(throwable)
+
+ AlertDialog.Builder(this)
+ .setTitle(R.string.dialog_title_error)
+ .setMessage(message)
+ .setPositiveButton(R.string.ok, null)
+ .show()
+ }
+
private fun onLoginFlowRetrieved() {
addFragmentToBackstack(R.id.loginFragmentContainer, LoginSignUpSignInSelectionFragment::class.java)
}
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginViewEvents.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginViewEvents.kt
index b8b7965c77..b7351feead 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginViewEvents.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginViewEvents.kt
@@ -24,4 +24,5 @@ import im.vector.matrix.android.api.auth.registration.FlowResult
*/
sealed class LoginViewEvents {
data class RegistrationFlowResult(val flowResult: FlowResult) : LoginViewEvents()
+ data class RegistrationError(val throwable: Throwable) : LoginViewEvents()
}
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginViewModel.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginViewModel.kt
index 6cc73233a7..49676b4a35 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginViewModel.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginViewModel.kt
@@ -489,7 +489,16 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
registrationWizard = registrationService.getOrCreateRegistrationWizard(homeServerConnectionConfigFinal)
currentTask = registrationWizard?.getRegistrationFlow(object : MatrixCallback {
+
override fun onSuccess(data: RegistrationResult) {
+ /*
+ // Simulate registration disabled
+ onFailure(Failure.ServerError(MatrixError(
+ code = MatrixError.FORBIDDEN,
+ message = "Registration is disabled"
+ ), 403))
+ */
+
setState {
copy(
asyncRegistration = Success(data)
@@ -503,6 +512,9 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
}
override fun onFailure(failure: Throwable) {
+ // Notify the user
+ _viewEvents.post(LoginViewEvents.RegistrationError(failure))
+
// TODO Handled JobCancellationException
setState {
copy(
diff --git a/vector/src/main/res/values/strings_riotX.xml b/vector/src/main/res/values/strings_riotX.xml
index 8a013a255b..958ebec6cc 100644
--- a/vector/src/main/res/values/strings_riotX.xml
+++ b/vector/src/main/res/values/strings_riotX.xml
@@ -46,6 +46,7 @@
Sign in to %1$s
Sign Up
Sign In
+ Sign In with SSO
Modular Address
Address
@@ -56,6 +57,7 @@
An error occurred when loading the page: %1$s (%2$d)
The application is not able to signin to this homeserver. The homeserver supports the following signin type(s): %1$s.\n\nDo you want to signin using a web client?
+ Sorry, the homeserver does not accept new account creation.
The application is not able to create an account on this homeserver.\n\nDo you want to signup using a web client?
From f12e6c941d9d8f5b3d30d080400b6ad1fe514154 Mon Sep 17 00:00:00 2001
From: Benoit Marty
Date: Wed, 20 Nov 2019 10:38:27 +0100
Subject: [PATCH 048/189] Login screens: sigin button for SSO
---
.../LoginSignUpSignInSelectionFragment.kt | 36 +++++++++++--------
...fragment_login_signup_signin_selection.xml | 12 ++++---
2 files changed, 30 insertions(+), 18 deletions(-)
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginSignUpSignInSelectionFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginSignUpSignInSelectionFragment.kt
index 4425632fd1..bcbef9e807 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginSignUpSignInSelectionFragment.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginSignUpSignInSelectionFragment.kt
@@ -20,7 +20,6 @@ import android.os.Bundle
import android.view.View
import androidx.core.view.isVisible
import butterknife.OnClick
-import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.withState
import im.vector.riotx.R
import kotlinx.android.synthetic.main.fragment_login_signup_signin_selection.*
@@ -33,10 +32,15 @@ class LoginSignUpSignInSelectionFragment @Inject constructor() : AbstractLoginFr
override fun getLayoutResId() = R.layout.fragment_login_signup_signin_selection
+ private var isSsoSignIn: Boolean = false
+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
+ isSsoSignIn = withState(loginViewModel) { it.asyncHomeServerLoginFlowRequest.invoke() } == LoginMode.Sso
+
setupUi()
+ setupButtons()
}
private fun setupUi() {
@@ -62,9 +66,24 @@ class LoginSignUpSignInSelectionFragment @Inject constructor() : AbstractLoginFr
}
}
- @OnClick(R.id.loginSignupSigninSignUp)
+ private fun setupButtons() {
+ if (isSsoSignIn) {
+ loginSignupSigninSubmit.text = getString(R.string.login_signin_sso)
+ loginSignupSigninSignIn.isVisible = false
+ } else {
+ loginSignupSigninSubmit.text = getString(R.string.login_signup)
+ loginSignupSigninSignIn.isVisible = true
+ }
+ }
+
+
+ @OnClick(R.id.loginSignupSigninSubmit)
fun signUp() {
- loginViewModel.handle(LoginAction.UpdateSignMode(SignMode.SignUp))
+ if (isSsoSignIn) {
+ signIn()
+ } else {
+ loginViewModel.handle(LoginAction.UpdateSignMode(SignMode.SignUp))
+ }
}
@OnClick(R.id.loginSignupSigninSignIn)
@@ -76,15 +95,4 @@ class LoginSignUpSignInSelectionFragment @Inject constructor() : AbstractLoginFr
override fun resetViewModel() {
loginViewModel.handle(LoginAction.ResetSignMode)
}
-
- override fun invalidate() = withState(loginViewModel) {
- when (it.asyncRegistration) {
- is Fail -> {
- // TODO Registration disabled, (move to Activity?)
- when (it.asyncRegistration.error) {
-
- }
- }
- }
- }
}
diff --git a/vector/src/main/res/layout/fragment_login_signup_signin_selection.xml b/vector/src/main/res/layout/fragment_login_signup_signin_selection.xml
index e58a986b14..de9a7e403c 100644
--- a/vector/src/main/res/layout/fragment_login_signup_signin_selection.xml
+++ b/vector/src/main/res/layout/fragment_login_signup_signin_selection.xml
@@ -56,17 +56,19 @@
app:layout_constraintTop_toBottomOf="@+id/loginSignupSigninTitle"
tools:text="@string/login_server_matrix_org_text" />
+
+ app:layout_constraintTop_toBottomOf="@+id/loginSignupSigninText"
+ tools:text="@string/login_signup" />
+
+ app:layout_constraintTop_toBottomOf="@+id/loginSignupSigninSubmit"
+ tools:visibility="visible" />