diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml
index 0c9bac61a1..5f1687c9c9 100644
--- a/vector/src/main/AndroidManifest.xml
+++ b/vector/src/main/AndroidManifest.xml
@@ -33,7 +33,9 @@
-
+
addFragmentToBackstack(R.id.simpleFragmentContainer, LoginSignUpSignInSelectionFragment::class.java)
ServerType.Modular,
- ServerType.Other -> Unit // TODO addFragmentToBackstack(R.id.simpleFragmentContainer, LoginEnterHomeServerFragment::class.java)
+ ServerType.Other -> addFragmentToBackstack(R.id.simpleFragmentContainer, LoginServerUrlFormFragment::class.java)
+ }
+ }
+
+ private fun onSignModeSelected() = withState(loginViewModel) {
+ when (it.signMode) {
+ SignMode.SignUp -> Unit // TODO addFragmentToBackstack(R.id.simpleFragmentContainer, SignUpFragment::class.java)
+ SignMode.SignIn -> addFragmentToBackstack(R.id.simpleFragmentContainer, LoginFragment::class.java)
}
}
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginFragment.kt
index 4f918baa8a..582567aba5 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginFragment.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginFragment.kt
@@ -18,20 +18,15 @@ package im.vector.riotx.features.login
import android.os.Bundle
import android.view.View
-import android.view.inputmethod.EditorInfo
import android.widget.Toast
import androidx.core.view.isVisible
import androidx.transition.TransitionManager
import com.airbnb.mvrx.*
-import com.jakewharton.rxbinding3.view.focusChanges
import com.jakewharton.rxbinding3.widget.textChanges
import im.vector.riotx.R
-import im.vector.riotx.core.extensions.setTextWithColoredPart
import im.vector.riotx.core.extensions.showPassword
-import im.vector.riotx.core.utils.openUrlInExternalBrowser
-import im.vector.riotx.features.homeserver.ServerUrlsRepository
import io.reactivex.Observable
-import io.reactivex.functions.Function3
+import io.reactivex.functions.BiFunction
import io.reactivex.rxkotlin.subscribeBy
import kotlinx.android.synthetic.main.fragment_login.*
import javax.inject.Inject
@@ -49,41 +44,8 @@ class LoginFragment @Inject constructor() : AbstractLoginFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- setupNotice()
- setupAuthButton()
+ setupLoginButton()
setupPasswordReveal()
-
- homeServerField.focusChanges()
- .subscribe {
- if (!it) {
- viewModel.handle(LoginAction.UpdateHomeServer(homeServerField.text.toString()))
- }
- }
- .disposeOnDestroyView()
-
- homeServerField.setOnEditorActionListener { _, actionId, _ ->
- if (actionId == EditorInfo.IME_ACTION_DONE) {
- viewModel.handle(LoginAction.UpdateHomeServer(homeServerField.text.toString()))
- return@setOnEditorActionListener true
- }
- return@setOnEditorActionListener false
- }
-
- val initHsUrl = viewModel.getInitialHomeServerUrl()
- if (initHsUrl != null) {
- homeServerField.setText(initHsUrl)
- } else {
- homeServerField.setText(ServerUrlsRepository.getDefaultHomeServerUrl(requireContext()))
- }
- viewModel.handle(LoginAction.UpdateHomeServer(homeServerField.text.toString()))
- }
-
- private fun setupNotice() {
- riotx_no_registration_notice.setTextWithColoredPart(R.string.riotx_no_registration_notice, R.string.riotx_no_registration_notice_colored_part)
-
- riotx_no_registration_notice.setOnClickListener {
- openUrlInExternalBrowser(requireActivity(), "https://about.riot.im/downloads")
- }
}
private fun authenticate() {
@@ -93,23 +55,21 @@ class LoginFragment @Inject constructor() : AbstractLoginFragment() {
viewModel.handle(LoginAction.Login(login, password))
}
- private fun setupAuthButton() {
+ private fun setupLoginButton() {
Observable
.combineLatest(
loginField.textChanges().map { it.trim().isNotEmpty() },
passwordField.textChanges().map { it.trim().isNotEmpty() },
- homeServerField.textChanges().map { it.trim().isNotEmpty() },
- Function3 { isLoginNotEmpty, isPasswordNotEmpty, isHomeServerNotEmpty ->
- isLoginNotEmpty && isPasswordNotEmpty && isHomeServerNotEmpty
+ BiFunction { isLoginNotEmpty, isPasswordNotEmpty ->
+ isLoginNotEmpty && isPasswordNotEmpty
}
)
.subscribeBy { authenticateButton.isEnabled = it }
.disposeOnDestroyView()
authenticateButton.setOnClickListener { authenticate() }
-
- authenticateButtonSso.setOnClickListener { openSso() }
}
+ // TODO Move to server selection screen
private fun openSso() {
loginSharedActionViewModel.post(LoginNavigation.OpenSsoLoginFallback)
}
@@ -148,7 +108,6 @@ class LoginFragment @Inject constructor() : AbstractLoginFragment() {
loginField.isVisible = false
passwordContainer.isVisible = false
authenticateButton.isVisible = false
- authenticateButtonSso.isVisible = false
passwordShown = false
renderPasswordField()
}
@@ -158,7 +117,6 @@ class LoginFragment @Inject constructor() : AbstractLoginFragment() {
loginField.isVisible = false
passwordContainer.isVisible = false
authenticateButton.isVisible = false
- authenticateButtonSso.isVisible = false
Toast.makeText(requireActivity(), "Authenticate failure: ${state.asyncHomeServerLoginFlowRequest.error}", Toast.LENGTH_LONG).show()
}
is Success -> {
@@ -170,7 +128,6 @@ class LoginFragment @Inject constructor() : AbstractLoginFragment() {
loginField.isVisible = true
passwordContainer.isVisible = true
authenticateButton.isVisible = true
- authenticateButtonSso.isVisible = false
if (loginField.text.isNullOrBlank() && passwordField.text.isNullOrBlank()) {
// Jump focus to login
loginField.requestFocus()
@@ -180,13 +137,11 @@ class LoginFragment @Inject constructor() : AbstractLoginFragment() {
loginField.isVisible = false
passwordContainer.isVisible = false
authenticateButton.isVisible = false
- authenticateButtonSso.isVisible = true
}
LoginMode.Unsupported -> {
loginField.isVisible = false
passwordContainer.isVisible = false
authenticateButton.isVisible = false
- authenticateButtonSso.isVisible = false
Toast.makeText(requireActivity(), "None of the homeserver login mode is supported by RiotX", Toast.LENGTH_LONG).show()
}
}
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 011100a6f5..7be5223ac7 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
@@ -21,6 +21,7 @@ import android.view.View
import butterknife.OnClick
import com.airbnb.mvrx.withState
import im.vector.riotx.R
+import im.vector.riotx.core.utils.openUrlInExternalBrowser
import kotlinx.android.synthetic.main.fragment_login_server_selection.*
import me.gujun.android.span.span
import javax.inject.Inject
@@ -50,6 +51,7 @@ class LoginServerSelectionFragment @Inject constructor() : AbstractLoginFragment
textDecorationLine = "underline"
onClick = {
// TODO
+ openUrlInExternalBrowser(requireActivity(), "https://example.org")
}
}
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginServerUrlFormFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginServerUrlFormFragment.kt
new file mode 100644
index 0000000000..bf5a6b9866
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginServerUrlFormFragment.kt
@@ -0,0 +1,94 @@
+/*
+ * 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 android.os.Bundle
+import android.view.View
+import android.view.inputmethod.EditorInfo
+import androidx.core.view.isVisible
+import butterknife.OnClick
+import com.airbnb.mvrx.withState
+import com.jakewharton.rxbinding3.widget.textChanges
+import im.vector.riotx.R
+import im.vector.riotx.core.utils.openUrlInExternalBrowser
+import kotlinx.android.synthetic.main.fragment_login_server_url_form.*
+import javax.inject.Inject
+
+/**
+ *
+ */
+class LoginServerUrlFormFragment @Inject constructor() : AbstractLoginFragment() {
+
+ override fun getLayoutResId() = R.layout.fragment_login_server_url_form
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ // TODO Import code from Riot to clear error on TIL
+ loginServerUrlFormHomeServerUrl.textChanges()
+ .subscribe(
+ {
+ loginServerUrlFormHomeServerUrlTil.error = null
+ },
+ {
+ // Ignore error
+ })
+ .disposeOnDestroy()
+
+ loginServerUrlFormHomeServerUrl.setOnEditorActionListener { _, actionId, _ ->
+ if (actionId == EditorInfo.IME_ACTION_DONE) {
+ submit()
+ return@setOnEditorActionListener true
+ }
+ return@setOnEditorActionListener false
+ }
+ }
+
+ @OnClick(R.id.loginServerUrlFormLearnMore)
+ fun learMore() {
+ // TODO
+ openUrlInExternalBrowser(requireActivity(), "https://example.org")
+ }
+
+ @OnClick(R.id.loginServerUrlFormSubmit)
+ fun submit() {
+ // TODO Static check of homeserver url, empty, malformed, etc.
+ viewModel.handle(LoginAction.InitWith(LoginConfig(loginServerUrlFormHomeServerUrl.text.toString(), null)))
+ }
+
+ override fun invalidate() = withState(viewModel) { state ->
+ when (state.serverType) {
+ ServerType.Modular -> {
+ loginServerUrlFormIcon.isVisible = true
+ loginServerUrlFormTitle.text = getString(R.string.login_connect_to_modular)
+ loginServerUrlFormText.text = getString(R.string.login_server_url_form_modular_text)
+ loginServerUrlFormLearnMore.isVisible = true
+ loginServerUrlFormHomeServerUrlTil.hint = getText(R.string.login_server_url_form_modular_hint)
+ loginServerUrlFormNotice.text = getString(R.string.login_server_url_form_modular_notice)
+ }
+ ServerType.Other -> {
+ loginServerUrlFormIcon.isVisible = false
+ loginServerUrlFormTitle.text = getString(R.string.login_server_other_title)
+ loginServerUrlFormText.text = getString(R.string.login_connect_to_a_custom_server)
+ loginServerUrlFormLearnMore.isVisible = false
+ loginServerUrlFormHomeServerUrlTil.hint = getText(R.string.login_server_url_form_other_hint)
+ loginServerUrlFormNotice.text = getString(R.string.login_server_url_form_other_notice)
+ }
+ else -> error("This fragment should not be display in matrix.org mode")
+ }
+ }
+}
diff --git a/vector/src/main/res/layout/fragment_login.xml b/vector/src/main/res/layout/fragment_login.xml
index 3dde5e1748..94340cb97c 100644
--- a/vector/src/main/res/layout/fragment_login.xml
+++ b/vector/src/main/res/layout/fragment_login.xml
@@ -1,3 +1,4 @@
+
-
+ style="@style/LoginTopIcon"
+ android:layout_gravity="center_horizontal" />
+ android:layout_marginTop="84dp"
+ android:textAppearance="@style/TextAppearance.Vector.Login.Title"
+ tools:text="@string/login_signin_to" />
+
+
+ android:layout_marginTop="32dp"
+ android:hint="@string/auth_user_name_placeholder"
+ app:errorEnabled="true">
+ android:hint="@string/auth_password_placeholder"
+ app:errorEnabled="true">
-
+ android:layout_marginTop="22dp"
+ android:orientation="horizontal">
-
+ android:layout_gravity="start"
+ android:text="@string/auth_forgot_password" />
-
+
-
-
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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 21835a864c..240e8866f3 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
@@ -1,3 +1,4 @@
+
-
-
-
https://matrix.org
- https://matrix.org
https://piwik.riot.im
https://riot.im/bugreports/submit
diff --git a/vector/src/main/res/values/strings_riotX.xml b/vector/src/main/res/values/strings_riotX.xml
index 36318ec52d..cfd1b6721c 100644
--- a/vector/src/main/res/values/strings_riotX.xml
+++ b/vector/src/main/res/values/strings_riotX.xml
@@ -36,10 +36,20 @@
Learn more
Other
Custom & advanced settings
- Continue
+ Continue
Connect to %1$s
+ Connect to Modular
+ Connect to a custom server
+ Sign in to %1$s
Sign Up
Sign In
+ Modular Address
+ Address
+ Premium hosting for organisations
+
+ Enter the address of the Modular Riot or Server you want to use
+ Enter the address of a server or a Riot you want to connect to
+
diff --git a/vector/src/main/res/values/styles_login.xml b/vector/src/main/res/values/styles_login.xml
index cac4351c3f..81964377bd 100644
--- a/vector/src/main/res/values/styles_login.xml
+++ b/vector/src/main/res/values/styles_login.xml
@@ -8,10 +8,12 @@