Add separate host in login form to login to VULCAN adfslight (#704)

This commit is contained in:
Mikołaj Pich 2020-02-29 10:30:20 +01:00 committed by GitHub
parent 565114a2d2
commit f294e3d57c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 219 additions and 63 deletions

View File

@ -29,7 +29,7 @@ class StudentRepository @Inject constructor(
} }
} }
fun getStudentsScrapper(email: String, password: String, endpoint: String, symbol: String = ""): Single<List<Student>> { fun getStudentsScrapper(email: String, password: String, endpoint: String, symbol: String): Single<List<Student>> {
return ReactiveNetwork.checkInternetConnectivity(settings).flatMap { return ReactiveNetwork.checkInternetConnectivity(settings).flatMap {
if (it) remote.getStudentsScrapper(email, password, endpoint, symbol) if (it) remote.getStudentsScrapper(email, password, endpoint, symbol)
else Single.error(UnknownHostException("No internet connection")) else Single.error(UnknownHostException("No internet connection"))

View File

@ -6,9 +6,7 @@ import android.view.View
import android.view.View.GONE import android.view.View.GONE
import android.view.View.VISIBLE import android.view.View.VISIBLE
import android.view.ViewGroup import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import androidx.appcompat.widget.AppCompatEditText
import androidx.core.widget.doOnTextChanged import androidx.core.widget.doOnTextChanged
import io.github.wulkanowy.R import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Student
@ -17,6 +15,7 @@ import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.login.LoginActivity import io.github.wulkanowy.ui.modules.login.LoginActivity
import io.github.wulkanowy.ui.modules.login.form.LoginSymbolAdapter import io.github.wulkanowy.ui.modules.login.form.LoginSymbolAdapter
import io.github.wulkanowy.utils.hideSoftInput import io.github.wulkanowy.utils.hideSoftInput
import io.github.wulkanowy.utils.setOnEditorDoneSignIn
import io.github.wulkanowy.utils.showSoftInput import io.github.wulkanowy.utils.showSoftInput
import kotlinx.android.synthetic.main.fragment_login_advanced.* import kotlinx.android.synthetic.main.fragment_login_advanced.*
import javax.inject.Inject import javax.inject.Inject
@ -47,9 +46,14 @@ class LoginAdvancedFragment : BaseFragment(), LoginAdvancedView {
private lateinit var hostValues: Array<String> private lateinit var hostValues: Array<String>
private lateinit var hostSymbols: Array<String>
override val formHostValue: String override val formHostValue: String
get() = hostValues.getOrNull(hostKeys.indexOf(loginFormHost.text.toString())).orEmpty() get() = hostValues.getOrNull(hostKeys.indexOf(loginFormHost.text.toString())).orEmpty()
override val formHostSymbol: String
get() = hostSymbols.getOrNull(hostKeys.indexOf(loginFormHost.text.toString())).orEmpty()
override val formPinValue: String override val formPinValue: String
get() = loginFormPin.text.toString().trim() get() = loginFormPin.text.toString().trim()
@ -77,6 +81,7 @@ class LoginAdvancedFragment : BaseFragment(), LoginAdvancedView {
override fun initView() { override fun initView() {
hostKeys = resources.getStringArray(R.array.hosts_keys) hostKeys = resources.getStringArray(R.array.hosts_keys)
hostValues = resources.getStringArray(R.array.hosts_values) hostValues = resources.getStringArray(R.array.hosts_values)
hostSymbols = resources.getStringArray(R.array.hosts_symbols)
loginFormUsername.doOnTextChanged { _, _, _, _ -> presenter.onUsernameTextChanged() } loginFormUsername.doOnTextChanged { _, _, _, _ -> presenter.onUsernameTextChanged() }
loginFormPass.doOnTextChanged { _, _, _, _ -> presenter.onPassTextChanged() } loginFormPass.doOnTextChanged { _, _, _, _ -> presenter.onPassTextChanged() }
@ -94,8 +99,8 @@ class LoginAdvancedFragment : BaseFragment(), LoginAdvancedView {
}) })
} }
loginFormPin.setOnEditorDoneSignIn() loginFormPin.setOnEditorDoneSignIn { loginFormSignIn.callOnClick() }
loginFormPass.setOnEditorDoneSignIn() loginFormPass.setOnEditorDoneSignIn { loginFormSignIn.callOnClick() }
loginFormSymbol.setAdapter(ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, resources.getStringArray(R.array.symbols_values))) loginFormSymbol.setAdapter(ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, resources.getStringArray(R.array.symbols_values)))
@ -106,12 +111,6 @@ class LoginAdvancedFragment : BaseFragment(), LoginAdvancedView {
} }
} }
private fun AppCompatEditText.setOnEditorDoneSignIn() {
setOnEditorActionListener { _, id, _ ->
if (id == EditorInfo.IME_ACTION_DONE || id == EditorInfo.IME_NULL) loginFormSignIn.callOnClick() else false
}
}
override fun setDefaultCredentials(username: String, pass: String, symbol: String, token: String, pin: String) { override fun setDefaultCredentials(username: String, pass: String, symbol: String, token: String, pin: String) {
loginFormUsername.setText(username) loginFormUsername.setText(username)
loginFormPass.setText(pass) loginFormPass.setText(pass)
@ -124,6 +123,10 @@ class LoginAdvancedFragment : BaseFragment(), LoginAdvancedView {
loginFormUsernameLayout.hint = label loginFormUsernameLayout.hint = label
} }
override fun setSymbol(symbol: String) {
loginFormSymbol.setText(symbol)
}
override fun setErrorUsernameRequired() { override fun setErrorUsernameRequired() {
with(loginFormUsernameLayout) { with(loginFormUsernameLayout) {
requestFocus() requestFocus()

View File

@ -78,6 +78,7 @@ class LoginAdvancedPresenter @Inject constructor(
if (formHostValue.contains("fakelog")) { if (formHostValue.contains("fakelog")) {
setDefaultCredentials("jan@fakelog.cf", "jan123", "powiatwulkanowy", "FK100000", "999999") setDefaultCredentials("jan@fakelog.cf", "jan123", "powiatwulkanowy", "FK100000", "999999")
} }
setSymbol(formHostSymbol)
updateUsernameLabel() updateUsernameLabel()
} }
} }

View File

@ -11,6 +11,8 @@ interface LoginAdvancedView : BaseView {
val formHostValue: String val formHostValue: String
val formHostSymbol: String
val formLoginType: String val formLoginType: String
val formPinValue: String val formPinValue: String
@ -29,6 +31,8 @@ interface LoginAdvancedView : BaseView {
fun setUsernameLabel(label: String) fun setUsernameLabel(label: String)
fun setSymbol(symbol: String)
fun setErrorUsernameRequired() fun setErrorUsernameRequired()
fun setErrorPassRequired(focus: Boolean) fun setErrorPassRequired(focus: Boolean)

View File

@ -7,8 +7,7 @@ import android.view.View
import android.view.View.GONE import android.view.View.GONE
import android.view.View.VISIBLE import android.view.View.VISIBLE
import android.view.ViewGroup import android.view.ViewGroup
import android.view.inputmethod.EditorInfo.IME_ACTION_DONE import android.widget.ArrayAdapter
import android.view.inputmethod.EditorInfo.IME_NULL
import androidx.core.widget.doOnTextChanged import androidx.core.widget.doOnTextChanged
import io.github.wulkanowy.R import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Student
@ -18,6 +17,7 @@ import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.hideSoftInput import io.github.wulkanowy.utils.hideSoftInput
import io.github.wulkanowy.utils.openEmailClient import io.github.wulkanowy.utils.openEmailClient
import io.github.wulkanowy.utils.openInternetBrowser import io.github.wulkanowy.utils.openInternetBrowser
import io.github.wulkanowy.utils.setOnEditorDoneSignIn
import io.github.wulkanowy.utils.showSoftInput import io.github.wulkanowy.utils.showSoftInput
import kotlinx.android.synthetic.main.fragment_login_form.* import kotlinx.android.synthetic.main.fragment_login_form.*
import javax.inject.Inject import javax.inject.Inject
@ -43,6 +43,12 @@ class LoginFormFragment : BaseFragment(), LoginFormView {
override val formHostValue: String override val formHostValue: String
get() = hostValues.getOrNull(hostKeys.indexOf(loginFormHost.text.toString())).orEmpty() get() = hostValues.getOrNull(hostKeys.indexOf(loginFormHost.text.toString())).orEmpty()
override val formHostSymbol: String
get() = hostSymbols.getOrNull(hostKeys.indexOf(loginFormHost.text.toString())).orEmpty()
override val formSymbolValue: String
get() = loginFormSymbol.text.toString()
override val nicknameLabel: String override val nicknameLabel: String
get() = getString(R.string.login_nickname_hint) get() = getString(R.string.login_nickname_hint)
@ -53,6 +59,8 @@ class LoginFormFragment : BaseFragment(), LoginFormView {
private lateinit var hostValues: Array<String> private lateinit var hostValues: Array<String>
private lateinit var hostSymbols: Array<String>
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_login_form, container, false) return inflater.inflate(R.layout.fragment_login_form, container, false)
} }
@ -65,9 +73,11 @@ class LoginFormFragment : BaseFragment(), LoginFormView {
override fun initView() { override fun initView() {
hostKeys = resources.getStringArray(R.array.hosts_keys) hostKeys = resources.getStringArray(R.array.hosts_keys)
hostValues = resources.getStringArray(R.array.hosts_values) hostValues = resources.getStringArray(R.array.hosts_values)
hostSymbols = resources.getStringArray(R.array.hosts_symbols)
loginFormUsername.doOnTextChanged { _, _, _, _ -> presenter.onUsernameTextChanged() } loginFormUsername.doOnTextChanged { _, _, _, _ -> presenter.onUsernameTextChanged() }
loginFormPass.doOnTextChanged { _, _, _, _ -> presenter.onPassTextChanged() } loginFormPass.doOnTextChanged { _, _, _, _ -> presenter.onPassTextChanged() }
loginFormSymbol.doOnTextChanged { _, _, _, _ -> presenter.onSymbolTextChanged() }
loginFormHost.setOnItemClickListener { _, _, _, _ -> presenter.onHostSelected() } loginFormHost.setOnItemClickListener { _, _, _, _ -> presenter.onHostSelected() }
loginFormSignIn.setOnClickListener { presenter.onSignInClick() } loginFormSignIn.setOnClickListener { presenter.onSignInClick() }
loginFormAdvancedButton.setOnClickListener { presenter.onAdvancedLoginClick() } loginFormAdvancedButton.setOnClickListener { presenter.onAdvancedLoginClick() }
@ -75,9 +85,10 @@ class LoginFormFragment : BaseFragment(), LoginFormView {
loginFormFaq.setOnClickListener { presenter.onFaqClick() } loginFormFaq.setOnClickListener { presenter.onFaqClick() }
loginFormContactEmail.setOnClickListener { presenter.onEmailClick() } loginFormContactEmail.setOnClickListener { presenter.onEmailClick() }
loginFormRecoverLink.setOnClickListener { presenter.onRecoverClick() } loginFormRecoverLink.setOnClickListener { presenter.onRecoverClick() }
loginFormPass.setOnEditorActionListener { _, id, _ -> loginFormPass.setOnEditorDoneSignIn { loginFormSignIn.callOnClick() }
if (id == IME_ACTION_DONE || id == IME_NULL) loginFormSignIn.callOnClick() else false loginFormSymbol.setOnEditorDoneSignIn { loginFormSignIn.callOnClick() }
}
loginFormSymbol.setAdapter(ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, resources.getStringArray(R.array.symbols_values)))
with(loginFormHost) { with(loginFormHost) {
setText(hostKeys.getOrNull(0).orEmpty()) setText(hostKeys.getOrNull(0).orEmpty())
@ -91,10 +102,18 @@ class LoginFormFragment : BaseFragment(), LoginFormView {
loginFormPass.setText(pass) loginFormPass.setText(pass)
} }
override fun setSymbol(symbol: String) {
loginFormSymbol.setText(symbol)
}
override fun setUsernameLabel(label: String) { override fun setUsernameLabel(label: String) {
loginFormUsernameLayout.hint = label loginFormUsernameLayout.hint = label
} }
override fun showSymbol(show: Boolean) {
loginFormSymbolLayout.visibility = if (show) VISIBLE else GONE
}
override fun setErrorUsernameRequired() { override fun setErrorUsernameRequired() {
with(loginFormUsernameLayout) { with(loginFormUsernameLayout) {
requestFocus() requestFocus()
@ -102,6 +121,13 @@ class LoginFormFragment : BaseFragment(), LoginFormView {
} }
} }
override fun setErrorSymbolRequired(focus: Boolean) {
with(loginFormSymbolLayout) {
if (focus) requestFocus()
error = getString(R.string.login_field_required)
}
}
override fun setErrorPassRequired(focus: Boolean) { override fun setErrorPassRequired(focus: Boolean) {
with(loginFormPassLayout) { with(loginFormPassLayout) {
if (focus) requestFocus() if (focus) requestFocus()
@ -131,6 +157,10 @@ class LoginFormFragment : BaseFragment(), LoginFormView {
loginFormPassLayout.error = null loginFormPassLayout.error = null
} }
override fun clearSymbolError() {
loginFormSymbolLayout.error = null
}
override fun showSoftKeyboard() { override fun showSoftKeyboard() {
activity?.showSoftInput() activity?.showSoftInput()
} }
@ -183,7 +213,10 @@ class LoginFormFragment : BaseFragment(), LoginFormView {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
presenter.updateUsernameLabel() with(presenter) {
updateUsernameLabel()
updateSymbolInputVisibility()
}
} }
override fun openEmail() { override fun openEmail() {

View File

@ -46,13 +46,21 @@ class LoginFormPresenter @Inject constructor(
if (formHostValue.contains("fakelog")) { if (formHostValue.contains("fakelog")) {
setCredentials("jan@fakelog.cf", "jan123") setCredentials("jan@fakelog.cf", "jan123")
} }
setSymbol(formHostSymbol)
updateUsernameLabel() updateUsernameLabel()
updateSymbolInputVisibility()
} }
} }
fun updateUsernameLabel() { fun updateUsernameLabel() {
view?.apply { view?.run {
setUsernameLabel(if ("vulcan" in formHostValue || "fakelog" in formHostValue) emailLabel else nicknameLabel) setUsernameLabel(if ("standard" in formHostValue) emailLabel else nicknameLabel)
}
}
fun updateSymbolInputVisibility() {
view?.run {
showSymbol("adfs" in formHostValue)
} }
} }
@ -64,14 +72,19 @@ class LoginFormPresenter @Inject constructor(
view?.clearUsernameError() view?.clearUsernameError()
} }
fun onSymbolTextChanged() {
view?.clearSymbolError()
}
fun onSignInClick() { fun onSignInClick() {
val email = view?.formUsernameValue.orEmpty().trim() val email = view?.formUsernameValue.orEmpty().trim()
val password = view?.formPassValue.orEmpty().trim() val password = view?.formPassValue.orEmpty().trim()
val endpoint = view?.formHostValue.orEmpty().trim() val host = view?.formHostValue.orEmpty().trim()
val symbol = view?.formSymbolValue.orEmpty().trim()
if (!validateCredentials(email, password)) return if (!validateCredentials(email, password, host, symbol)) return
disposable.add(studentRepository.getStudentsScrapper(email, password, endpoint) disposable.add(studentRepository.getStudentsScrapper(email, password, host, symbol)
.subscribeOn(schedulers.backgroundThread) .subscribeOn(schedulers.backgroundThread)
.observeOn(schedulers.mainThread) .observeOn(schedulers.mainThread)
.doOnSubscribe { .doOnSubscribe {
@ -90,11 +103,11 @@ class LoginFormPresenter @Inject constructor(
} }
.subscribe({ .subscribe({
Timber.i("Login result: Success") Timber.i("Login result: Success")
analytics.logEvent("registration_form", "success" to true, "students" to it.size, "scrapperBaseUrl" to endpoint, "error" to "No error") analytics.logEvent("registration_form", "success" to true, "students" to it.size, "scrapperBaseUrl" to host, "error" to "No error")
view?.notifyParentAccountLogged(it, Triple(email, password, endpoint)) view?.notifyParentAccountLogged(it, Triple(email, password, host))
}, { }, {
Timber.i("Login result: An exception occurred") Timber.i("Login result: An exception occurred")
analytics.logEvent("registration_form", "success" to false, "students" to -1, "scrapperBaseUrl" to endpoint, "error" to it.message.ifNullOrBlank { "No message" }) analytics.logEvent("registration_form", "success" to false, "students" to -1, "scrapperBaseUrl" to host, "error" to it.message.ifNullOrBlank { "No message" })
loginErrorHandler.dispatch(it) loginErrorHandler.dispatch(it)
view?.showContact(true) view?.showContact(true)
})) }))
@ -112,7 +125,7 @@ class LoginFormPresenter @Inject constructor(
view?.onRecoverClick() view?.onRecoverClick()
} }
private fun validateCredentials(login: String, password: String): Boolean { private fun validateCredentials(login: String, password: String, host: String, symbol: String): Boolean {
var isCorrect = true var isCorrect = true
if (login.isEmpty()) { if (login.isEmpty()) {
@ -129,6 +142,12 @@ class LoginFormPresenter @Inject constructor(
view?.setErrorPassInvalid(focus = isCorrect) view?.setErrorPassInvalid(focus = isCorrect)
isCorrect = false isCorrect = false
} }
if ("standard" !in host && symbol.isBlank()) {
view?.setErrorSymbolRequired(focus = isCorrect)
isCorrect = false
}
return isCorrect return isCorrect
} }
} }

View File

@ -13,16 +13,26 @@ interface LoginFormView : BaseView {
val formHostValue: String val formHostValue: String
val formHostSymbol: String
val formSymbolValue: String
val nicknameLabel: String val nicknameLabel: String
val emailLabel: String val emailLabel: String
fun setCredentials(username: String, pass: String) fun setCredentials(username: String, pass: String)
fun setSymbol(symbol: String)
fun setUsernameLabel(label: String) fun setUsernameLabel(label: String)
fun showSymbol(show: Boolean)
fun setErrorUsernameRequired() fun setErrorUsernameRequired()
fun setErrorSymbolRequired(focus: Boolean)
fun setErrorPassRequired(focus: Boolean) fun setErrorPassRequired(focus: Boolean)
fun setErrorPassInvalid(focus: Boolean) fun setErrorPassInvalid(focus: Boolean)
@ -33,6 +43,8 @@ interface LoginFormView : BaseView {
fun clearPassError() fun clearPassError()
fun clearSymbolError()
fun showSoftKeyboard() fun showSoftKeyboard()
fun hideSoftKeyboard() fun hideSoftKeyboard()

View File

@ -68,6 +68,7 @@ class LoginRecoverFragment : BaseFragment(), LoginRecoverView {
hostValues = resources.getStringArray(R.array.hosts_values) hostValues = resources.getStringArray(R.array.hosts_values)
loginRecoverName.doOnTextChanged { _, _, _, _ -> presenter.onNameTextChanged() } loginRecoverName.doOnTextChanged { _, _, _, _ -> presenter.onNameTextChanged() }
loginRecoverSymbol.doOnTextChanged { _, _, _, _ -> presenter.onSymbolTextChanged() }
loginRecoverHost.setOnItemClickListener { _, _, _, _ -> presenter.onHostSelected() } loginRecoverHost.setOnItemClickListener { _, _, _, _ -> presenter.onHostSelected() }
loginRecoverButton.setOnClickListener { presenter.onRecoverClick() } loginRecoverButton.setOnClickListener { presenter.onRecoverClick() }
loginRecoverErrorRetry.setOnClickListener { presenter.onRecoverClick() } loginRecoverErrorRetry.setOnClickListener { presenter.onRecoverClick() }
@ -83,9 +84,8 @@ class LoginRecoverFragment : BaseFragment(), LoginRecoverView {
} }
} }
override fun setDefaultCredentials(username: String, symbol: String) { override fun setDefaultCredentials(username: String) {
loginRecoverName.setText(username) loginRecoverName.setText(username)
loginRecoverSymbol.setText(symbol)
} }
override fun setErrorNameRequired() { override fun setErrorNameRequired() {
@ -106,10 +106,21 @@ class LoginRecoverFragment : BaseFragment(), LoginRecoverView {
} }
} }
override fun setSymbolError(focus: Boolean) {
with(loginRecoverSymbolLayout) {
if (focus) requestFocus()
error = getString(R.string.login_field_required)
}
}
override fun clearUsernameError() { override fun clearUsernameError() {
loginRecoverNameLayout.error = null loginRecoverNameLayout.error = null
} }
override fun clearSymbolError() {
loginRecoverSymbolLayout.error = null
}
override fun showSymbol(show: Boolean) { override fun showSymbol(show: Boolean) {
loginRecoverSymbolLayout.visibility = if (show) VISIBLE else GONE loginRecoverSymbolLayout.visibility = if (show) VISIBLE else GONE
} }

View File

@ -34,9 +34,13 @@ class LoginRecoverPresenter @Inject constructor(
view?.clearUsernameError() view?.clearUsernameError()
} }
fun onSymbolTextChanged() {
view?.clearSymbolError()
}
fun onHostSelected() { fun onHostSelected() {
view?.run { view?.run {
if ("fakelog" in recoverHostValue) setDefaultCredentials("jan@fakelog.cf", "Default") if ("fakelog" in recoverHostValue) setDefaultCredentials("jan@fakelog.cf")
clearUsernameError() clearUsernameError()
updateFields() updateFields()
} }
@ -44,32 +48,19 @@ class LoginRecoverPresenter @Inject constructor(
fun updateFields() { fun updateFields() {
view?.run { view?.run {
if ("fakelog" in recoverHostValue || "vulcan" in recoverHostValue) { showSymbol("adfs" in recoverHostValue)
showSymbol(true) setUsernameHint(if ("standard" in recoverHostValue) emailHintString else loginPeselEmailHintString)
setUsernameHint(emailHintString)
} else {
showSymbol(false)
setUsernameHint(loginPeselEmailHintString)
}
} }
} }
fun onRecoverClick() { fun onRecoverClick() {
val username = view?.recoverNameValue.orEmpty() val username = view?.recoverNameValue.orEmpty()
val host = view?.recoverHostValue.orEmpty() val host = view?.recoverHostValue.orEmpty()
val symbol = view?.recoverSymbolValue.ifNullOrBlank { "Default" } val symbol = view?.recoverSymbolValue.orEmpty()
if (username.isEmpty()) { if (!validateInput(username, host, symbol)) return
view?.setErrorNameRequired()
return
}
if (("fakelog" in host || "vulcan" in host) && "@" !in username) { disposable.add(recoverRepository.getReCaptchaSiteKey(host, symbol.ifBlank { "Default" })
view?.setUsernameError(view?.invalidEmailString.orEmpty())
return
}
disposable.add(recoverRepository.getReCaptchaSiteKey(host, symbol)
.subscribeOn(schedulers.backgroundThread) .subscribeOn(schedulers.backgroundThread)
.observeOn(schedulers.mainThread) .observeOn(schedulers.mainThread)
.doOnSubscribe { .doOnSubscribe {
@ -89,6 +80,27 @@ class LoginRecoverPresenter @Inject constructor(
}) })
} }
private fun validateInput(username: String, host: String, symbol: String): Boolean {
var isCorrect = true
if (username.isEmpty()) {
view?.setErrorNameRequired()
isCorrect = false
}
if ("standard" in host && "@" !in username) {
view?.setUsernameError(view?.invalidEmailString.orEmpty())
isCorrect = false
}
if ("adfs" in host && symbol.isBlank()) {
view?.setSymbolError(focus = isCorrect)
isCorrect = false
}
return isCorrect
}
fun onReCaptchaVerified(reCaptchaResponse: String) { fun onReCaptchaVerified(reCaptchaResponse: String) {
val username = view?.recoverNameValue.orEmpty() val username = view?.recoverNameValue.orEmpty()
val host = view?.recoverHostValue.orEmpty() val host = view?.recoverHostValue.orEmpty()

View File

@ -18,10 +18,12 @@ interface LoginRecoverView : BaseView {
fun initView() fun initView()
fun setDefaultCredentials(username: String, symbol: String) fun setDefaultCredentials(username: String)
fun clearUsernameError() fun clearUsernameError()
fun clearSymbolError()
fun showSymbol(show: Boolean) fun showSymbol(show: Boolean)
fun setErrorNameRequired() fun setErrorNameRequired()
@ -30,6 +32,8 @@ interface LoginRecoverView : BaseView {
fun setUsernameError(message: String) fun setUsernameError(message: String)
fun setSymbolError(focus: Boolean)
fun showSoftKeyboard() fun showSoftKeyboard()
fun hideSoftKeyboard() fun hideSoftKeyboard()

View File

@ -0,0 +1,10 @@
package io.github.wulkanowy.utils
import android.view.inputmethod.EditorInfo
import android.widget.EditText
fun EditText.setOnEditorDoneSignIn(callback: () -> Boolean) {
setOnEditorActionListener { _, id, _ ->
if (id == EditorInfo.IME_ACTION_DONE || id == EditorInfo.IME_NULL) callback() else false
}
}

View File

@ -202,7 +202,7 @@
android:layout_marginRight="24dp" android:layout_marginRight="24dp"
android:hint="@string/login_host_hint" android:hint="@string/login_host_hint"
android:orientation="vertical" android:orientation="vertical"
app:layout_constraintBottom_toTopOf="@+id/loginFormSignIn" app:layout_constraintBottom_toTopOf="@+id/loginFormSymbolLayout"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/loginFormRecoverLink"> app:layout_constraintTop_toBottomOf="@+id/loginFormRecoverLink">
@ -215,6 +215,36 @@
tools:ignore="Deprecated,LabelFor" /> tools:ignore="Deprecated,LabelFor" />
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/loginFormSymbolLayout"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginLeft="24dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="24dp"
android:layout_marginRight="24dp"
android:hint="@string/login_symbol_hint"
app:errorEnabled="true"
app:layout_constraintBottom_toTopOf="@+id/loginFormSignIn"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/loginFormHostLayout">
<AutoCompleteTextView
android:id="@+id/loginFormSymbol"
style="@style/Widget.MaterialComponents.TextInputEditText.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeActionLabel="@string/login_sign_in"
android:imeOptions="actionDone"
android:importantForAutofill="no"
android:inputType="textAutoComplete|textNoSuggestions"
android:maxLines="1"
tools:ignore="LabelFor" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/loginFormAdvancedButton" android:id="@+id/loginFormAdvancedButton"
style="@style/Widget.MaterialComponents.Button.OutlinedButton" style="@style/Widget.MaterialComponents.Button.OutlinedButton"
@ -229,7 +259,7 @@
app:layout_constraintBottom_toBottomOf="@id/loginFormSignIn" app:layout_constraintBottom_toBottomOf="@id/loginFormSignIn"
app:layout_constraintEnd_toStartOf="@+id/loginFormSignIn" app:layout_constraintEnd_toStartOf="@+id/loginFormSignIn"
app:layout_constraintHorizontal_bias="0.0" app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="@id/loginFormHostLayout" app:layout_constraintStart_toStartOf="@id/loginFormSymbolLayout"
app:layout_constraintTop_toTopOf="@+id/loginFormSignIn" /> app:layout_constraintTop_toTopOf="@+id/loginFormSignIn" />
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
@ -244,7 +274,7 @@
android:text="@string/login_sign_in" android:text="@string/login_sign_in"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/loginFormHostLayout" /> app:layout_constraintTop_toBottomOf="@+id/loginFormSymbolLayout" />
<TextView <TextView
android:id="@+id/loginFormPrivacyLink" android:id="@+id/loginFormPrivacyLink"

View File

@ -20,7 +20,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:fillViewport="true" android:fillViewport="true"
android:scrollbars="none" android:scrollbars="none"
tools:visibility="invisible"> tools:visibility="visible">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/loginRecoverFormContainer" android:id="@+id/loginRecoverFormContainer"
@ -113,7 +113,7 @@
android:layout_marginTop="24dp" android:layout_marginTop="24dp"
android:layout_marginEnd="24dp" android:layout_marginEnd="24dp"
android:layout_marginRight="24dp" android:layout_marginRight="24dp"
android:hint="@string/login_symbol_hint_optional" android:hint="@string/login_symbol_hint"
app:errorEnabled="true" app:errorEnabled="true"
app:layout_constraintBottom_toTopOf="@+id/loginRecoverButton" app:layout_constraintBottom_toTopOf="@+id/loginRecoverButton"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
@ -220,7 +220,7 @@
android:fillViewport="true" android:fillViewport="true"
android:scrollbars="none" android:scrollbars="none"
android:visibility="invisible" android:visibility="invisible"
tools:visibility="visible"> tools:visibility="invisible">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -31,9 +31,8 @@
<string name="login_email_hint">Email</string> <string name="login_email_hint">Email</string>
<string name="login_login_pesel_email_hint">Login, PESEL lub e-mail</string> <string name="login_login_pesel_email_hint">Login, PESEL lub e-mail</string>
<string name="login_password_hint">Hasło</string> <string name="login_password_hint">Hasło</string>
<string name="login_host_hint">Dziennik</string> <string name="login_host_hint">Dziennik UONET+</string>
<string name="login_symbol_hint">Symbol</string> <string name="login_symbol_hint">Symbol</string>
<string name="login_symbol_hint_optional">Symbol (opcjonalnie)</string>
<string name="login_type_api">Mobilne API</string> <string name="login_type_api">Mobilne API</string>
<string name="login_type_scrapper">Scraper</string> <string name="login_type_scrapper">Scraper</string>
<string name="login_type_hybrid">Hybrydowe</string> <string name="login_type_hybrid">Hybrydowe</string>

View File

@ -32,7 +32,7 @@
<string name="login_email_hint">Электронная почта</string> <string name="login_email_hint">Электронная почта</string>
<string name="login_login_pesel_email_hint">Логин, PESEL или электронная почта</string> <string name="login_login_pesel_email_hint">Логин, PESEL или электронная почта</string>
<string name="login_password_hint">Пароль</string> <string name="login_password_hint">Пароль</string>
<string name="login_host_hint">Дневник</string> <string name="login_host_hint">Дневник UONET+</string>
<string name="login_type_api">Мобильный API</string> <string name="login_type_api">Мобильный API</string>
<string name="login_type_scrapper">Scraper</string> <string name="login_type_scrapper">Scraper</string>
<string name="login_type_hybrid">Гибрид</string> <string name="login_type_hybrid">Гибрид</string>
@ -40,7 +40,6 @@
<string name="login_pin_hint">PIN</string> <string name="login_pin_hint">PIN</string>
<string name="login_api_key_hint">клавиша API</string> <string name="login_api_key_hint">клавиша API</string>
<string name="login_symbol_hint">Symbol</string> <string name="login_symbol_hint">Symbol</string>
<string name="login_symbol_hint_optional">Символ (необязательно)</string>
<string name="login_sign_in">Войти</string> <string name="login_sign_in">Войти</string>
<string name="login_invalid_password">Слишком короткий пароль</string> <string name="login_invalid_password">Слишком короткий пароль</string>
<string name="login_incorrect_password">Указаны неверные данные</string> <string name="login_incorrect_password">Указаны неверные данные</string>

View File

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation"> <resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
<string-array name="hosts_keys"> <string-array name="hosts_keys">
<item>Vulcan</item> <item>Vulcan - standardowy</item>
<item>Vulcan - niestandardowy</item>
<item>Opolska eSzkoła</item> <item>Opolska eSzkoła</item>
<item>Gdańska Platforma Edukacyjna</item> <item>Gdańska Platforma Edukacyjna</item>
<item>Lubelski Portal Oświatowy</item> <item>Lubelski Portal Oświatowy</item>
@ -10,12 +11,23 @@
<item>Fakelog</item> <item>Fakelog</item>
</string-array> </string-array>
<string-array name="hosts_values"> <string-array name="hosts_values">
<item>https://vulcan.net.pl</item> <item>https://vulcan.net.pl/?standard</item>
<item>https://vulcan.net.pl/?adfs</item>
<item>https://eszkola.opolskie.pl</item> <item>https://eszkola.opolskie.pl</item>
<item>https://edu.gdansk.pl</item> <item>https://edu.gdansk.pl</item>
<item>https://edu.lublin.eu</item> <item>https://edu.lublin.eu</item>
<item>https://umt.tarnow.pl</item> <item>https://umt.tarnow.pl</item>
<item>https://resman.pl</item> <item>https://resman.pl</item>
<item>http://fakelog.cf</item> <item>http://fakelog.cf/?standard</item>
</string-array>
<string-array name="hosts_symbols">
<item>Default</item>
<item />
<item>opole</item>
<item>gdansk</item>
<item>lublin</item>
<item>tarnow</item>
<item>rzeszow</item>
<item>Default</item>
</string-array> </string-array>
</resources> </resources>

View File

@ -32,7 +32,7 @@
<string name="login_email_hint">Email</string> <string name="login_email_hint">Email</string>
<string name="login_login_pesel_email_hint">Login, PESEL or e-mail</string> <string name="login_login_pesel_email_hint">Login, PESEL or e-mail</string>
<string name="login_password_hint">Password</string> <string name="login_password_hint">Password</string>
<string name="login_host_hint">Register</string> <string name="login_host_hint">UONET+ Register</string>
<string name="login_type_api">Mobile API</string> <string name="login_type_api">Mobile API</string>
<string name="login_type_scrapper">Scraper</string> <string name="login_type_scrapper">Scraper</string>
<string name="login_type_hybrid">Hybrid</string> <string name="login_type_hybrid">Hybrid</string>
@ -40,7 +40,6 @@
<string name="login_pin_hint">PIN</string> <string name="login_pin_hint">PIN</string>
<string name="login_api_key_hint">API key</string> <string name="login_api_key_hint">API key</string>
<string name="login_symbol_hint">Symbol</string> <string name="login_symbol_hint">Symbol</string>
<string name="login_symbol_hint_optional">Symbol (optional)</string>
<string name="login_sign_in">Sign in</string> <string name="login_sign_in">Sign in</string>
<string name="login_invalid_password">Password too short</string> <string name="login_invalid_password">Password too short</string>
<string name="login_incorrect_password">Login details are incorrect</string> <string name="login_incorrect_password">Login details are incorrect</string>

View File

@ -92,6 +92,8 @@ class LoginFormPresenterTest {
`when`(loginFormView.formUsernameValue).thenReturn("@") `when`(loginFormView.formUsernameValue).thenReturn("@")
`when`(loginFormView.formPassValue).thenReturn("123456") `when`(loginFormView.formPassValue).thenReturn("123456")
`when`(loginFormView.formHostValue).thenReturn("https://fakelog.cf") `when`(loginFormView.formHostValue).thenReturn("https://fakelog.cf")
`when`(loginFormView.formSymbolValue).thenReturn("Default")
`when`(loginFormView.formHostSymbol).thenReturn("Default")
presenter.onSignInClick() presenter.onSignInClick()
verify(loginFormView).hideSoftKeyboard() verify(loginFormView).hideSoftKeyboard()
@ -108,6 +110,8 @@ class LoginFormPresenterTest {
`when`(loginFormView.formUsernameValue).thenReturn("@") `when`(loginFormView.formUsernameValue).thenReturn("@")
`when`(loginFormView.formPassValue).thenReturn("123456") `when`(loginFormView.formPassValue).thenReturn("123456")
`when`(loginFormView.formHostValue).thenReturn("https://fakelog.cf") `when`(loginFormView.formHostValue).thenReturn("https://fakelog.cf")
`when`(loginFormView.formSymbolValue).thenReturn("Default")
`when`(loginFormView.formHostSymbol).thenReturn("Default")
presenter.onSignInClick() presenter.onSignInClick()
verify(loginFormView).hideSoftKeyboard() verify(loginFormView).hideSoftKeyboard()
@ -124,6 +128,8 @@ class LoginFormPresenterTest {
`when`(loginFormView.formUsernameValue).thenReturn("@") `when`(loginFormView.formUsernameValue).thenReturn("@")
`when`(loginFormView.formPassValue).thenReturn("123456") `when`(loginFormView.formPassValue).thenReturn("123456")
`when`(loginFormView.formHostValue).thenReturn("https://fakelog.cf") `when`(loginFormView.formHostValue).thenReturn("https://fakelog.cf")
`when`(loginFormView.formSymbolValue).thenReturn("Default")
`when`(loginFormView.formHostSymbol).thenReturn("Default")
presenter.onSignInClick() presenter.onSignInClick()
presenter.onSignInClick() presenter.onSignInClick()
@ -141,6 +147,8 @@ class LoginFormPresenterTest {
`when`(loginFormView.formUsernameValue).thenReturn("@") `when`(loginFormView.formUsernameValue).thenReturn("@")
`when`(loginFormView.formPassValue).thenReturn("123456") `when`(loginFormView.formPassValue).thenReturn("123456")
`when`(loginFormView.formHostValue).thenReturn("https://fakelog.cf") `when`(loginFormView.formHostValue).thenReturn("https://fakelog.cf")
`when`(loginFormView.formSymbolValue).thenReturn("Default")
`when`(loginFormView.formHostSymbol).thenReturn("Default")
presenter.onSignInClick() presenter.onSignInClick()
verify(loginFormView).hideSoftKeyboard() verify(loginFormView).hideSoftKeyboard()