mirror of
https://github.com/wulkanowy/wulkanowy.git
synced 2024-11-22 10:46:32 -06:00
Add account recover (#635)
This commit is contained in:
parent
96c1bb4c69
commit
18d6ec6961
@ -1,9 +1,6 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<option name="LINE_SEPARATOR" value=" " />
|
||||
<AndroidXmlCodeStyleSettings>
|
||||
<option name="ARRANGEMENT_SETTINGS_MIGRATED_TO_191" value="true" />
|
||||
</AndroidXmlCodeStyleSettings>
|
||||
<JetCodeStyleSettings>
|
||||
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
||||
<value>
|
||||
|
@ -122,7 +122,7 @@ configurations.all {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "io.github.wulkanowy:sdk:7e89883"
|
||||
implementation "io.github.wulkanowy:sdk:6789442"
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||
implementation "androidx.core:core-ktx:1.2.0"
|
||||
@ -173,7 +173,7 @@ dependencies {
|
||||
implementation "com.jakewharton.threetenabp:threetenabp:1.2.2"
|
||||
implementation "com.jakewharton.timber:timber:4.7.1"
|
||||
implementation "at.favre.lib:slf4j-timber:1.0.1"
|
||||
implementation "fr.bipi.treessence:treessence:0.3.0"
|
||||
implementation "fr.bipi.treessence:treessence:0.3.2"
|
||||
implementation "com.mikepenz:aboutlibraries-core:7.1.0"
|
||||
implementation 'com.wdullaer:materialdatetimepicker:4.2.3'
|
||||
|
||||
|
@ -0,0 +1,19 @@
|
||||
package io.github.wulkanowy.data.repositories.recover
|
||||
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.reactivex.Single
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class RecoverRemote @Inject constructor(private val sdk: Sdk) {
|
||||
|
||||
fun getReCaptchaSiteKey(host: String, symbol: String): Single<Pair<String, String>> {
|
||||
return sdk.getPasswordResetCaptchaCode(host, symbol)
|
||||
}
|
||||
|
||||
fun sendRecoverRequest(url: String, symbol: String, email: String, reCaptchaResponse: String): Single<String> {
|
||||
return sdk.sendPasswordResetRequest(url, symbol, email, reCaptchaResponse)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,26 @@
|
||||
package io.github.wulkanowy.data.repositories.recover
|
||||
|
||||
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
||||
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
||||
import io.reactivex.Single
|
||||
import java.net.UnknownHostException
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class RecoverRepository @Inject constructor(private val settings: InternetObservingSettings, private val remote: RecoverRemote) {
|
||||
|
||||
fun getReCaptchaSiteKey(host: String, symbol: String): Single<Pair<String, String>> {
|
||||
return ReactiveNetwork.checkInternetConnectivity(settings).flatMap {
|
||||
if (it) remote.getReCaptchaSiteKey(host, symbol)
|
||||
else Single.error(UnknownHostException())
|
||||
}
|
||||
}
|
||||
|
||||
fun sendRecoverRequest(url: String, symbol: String, email: String, reCaptchaResponse: String): Single<String> {
|
||||
return ReactiveNetwork.checkInternetConnectivity(settings).flatMap {
|
||||
if (it) remote.sendRecoverRequest(url, symbol, email, reCaptchaResponse)
|
||||
else Single.error(UnknownHostException())
|
||||
}
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@ import io.github.wulkanowy.ui.base.BaseActivity
|
||||
import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter
|
||||
import io.github.wulkanowy.ui.modules.login.advanced.LoginAdvancedFragment
|
||||
import io.github.wulkanowy.ui.modules.login.form.LoginFormFragment
|
||||
import io.github.wulkanowy.ui.modules.login.recover.LoginRecoverFragment
|
||||
import io.github.wulkanowy.ui.modules.login.studentselect.LoginStudentSelectFragment
|
||||
import io.github.wulkanowy.ui.modules.login.symbol.LoginSymbolFragment
|
||||
import io.github.wulkanowy.utils.setOnSelectPageListener
|
||||
@ -52,7 +53,8 @@ class LoginActivity : BaseActivity<LoginPresenter>(), LoginView {
|
||||
LoginFormFragment.newInstance(),
|
||||
LoginSymbolFragment.newInstance(),
|
||||
LoginStudentSelectFragment.newInstance(),
|
||||
LoginAdvancedFragment.newInstance()
|
||||
LoginAdvancedFragment.newInstance(),
|
||||
LoginRecoverFragment.newInstance()
|
||||
))
|
||||
}
|
||||
|
||||
@ -99,4 +101,8 @@ class LoginActivity : BaseActivity<LoginPresenter>(), LoginView {
|
||||
fun onAdvancedLoginClick() {
|
||||
presenter.onAdvancedLoginClick()
|
||||
}
|
||||
|
||||
fun onRecoverClick() {
|
||||
presenter.onRecoverClick()
|
||||
}
|
||||
}
|
||||
|
@ -43,5 +43,8 @@ class LoginErrorHandler @Inject constructor(
|
||||
super.clear()
|
||||
onBadCredentials = {}
|
||||
onStudentDuplicate = {}
|
||||
onInvalidToken = {}
|
||||
onInvalidPin = {}
|
||||
onInvalidSymbol = {}
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import io.github.wulkanowy.di.scopes.PerFragment
|
||||
import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter
|
||||
import io.github.wulkanowy.ui.modules.login.advanced.LoginAdvancedFragment
|
||||
import io.github.wulkanowy.ui.modules.login.form.LoginFormFragment
|
||||
import io.github.wulkanowy.ui.modules.login.recover.LoginRecoverFragment
|
||||
import io.github.wulkanowy.ui.modules.login.studentselect.LoginStudentSelectFragment
|
||||
import io.github.wulkanowy.ui.modules.login.symbol.LoginSymbolFragment
|
||||
|
||||
@ -37,4 +38,8 @@ internal abstract class LoginModule {
|
||||
@PerFragment
|
||||
@ContributesAndroidInjector
|
||||
abstract fun bindLoginSelectStudentFragment(): LoginStudentSelectFragment
|
||||
|
||||
@PerFragment
|
||||
@ContributesAndroidInjector
|
||||
abstract fun bindLoginRecoverFragment(): LoginRecoverFragment
|
||||
}
|
||||
|
@ -49,11 +49,15 @@ class LoginPresenter @Inject constructor(
|
||||
view?.switchView(3)
|
||||
}
|
||||
|
||||
fun onRecoverClick() {
|
||||
view?.switchView(4)
|
||||
}
|
||||
|
||||
fun onViewSelected(index: Int) {
|
||||
view?.apply {
|
||||
when (index) {
|
||||
0 -> showActionBar(false)
|
||||
1, 2 -> showActionBar(true)
|
||||
1, 2, 3, 4 -> showActionBar(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -62,7 +66,7 @@ class LoginPresenter @Inject constructor(
|
||||
Timber.i("Back pressed in login view")
|
||||
view?.apply {
|
||||
when (currentViewIndex) {
|
||||
1, 2, 3 -> switchView(0)
|
||||
1, 2, 3, 4 -> switchView(0)
|
||||
else -> default()
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ package io.github.wulkanowy.ui.modules.login.advanced
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.View.GONE
|
||||
import android.view.View.VISIBLE
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.widget.ArrayAdapter
|
||||
@ -98,8 +100,9 @@ class LoginAdvancedFragment : BaseFragment(), LoginAdvancedView {
|
||||
loginFormSymbol.setAdapter(ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, resources.getStringArray(R.array.symbols_values)))
|
||||
|
||||
with(loginFormHost) {
|
||||
setText(hostKeys.getOrElse(0) { "" })
|
||||
setText(hostKeys.getOrNull(0).orEmpty())
|
||||
setAdapter(LoginSymbolAdapter(context, R.layout.support_simple_spinner_dropdown_item, hostKeys))
|
||||
setOnClickListener { if (loginFormContainer.visibility == GONE) dismissDropDown() }
|
||||
}
|
||||
}
|
||||
|
||||
@ -212,30 +215,30 @@ class LoginAdvancedFragment : BaseFragment(), LoginAdvancedView {
|
||||
}
|
||||
|
||||
override fun showOnlyHybridModeInputs() {
|
||||
loginFormUsernameLayout.visibility = View.VISIBLE
|
||||
loginFormPassLayout.visibility = View.VISIBLE
|
||||
loginFormHostLayout.visibility = View.VISIBLE
|
||||
loginFormPinLayout.visibility = View.GONE
|
||||
loginFormSymbolLayout.visibility = View.VISIBLE
|
||||
loginFormTokenLayout.visibility = View.GONE
|
||||
loginFormUsernameLayout.visibility = VISIBLE
|
||||
loginFormPassLayout.visibility = VISIBLE
|
||||
loginFormHostLayout.visibility = VISIBLE
|
||||
loginFormPinLayout.visibility = GONE
|
||||
loginFormSymbolLayout.visibility = VISIBLE
|
||||
loginFormTokenLayout.visibility = GONE
|
||||
}
|
||||
|
||||
override fun showOnlyScrapperModeInputs() {
|
||||
loginFormUsernameLayout.visibility = View.VISIBLE
|
||||
loginFormPassLayout.visibility = View.VISIBLE
|
||||
loginFormHostLayout.visibility = View.VISIBLE
|
||||
loginFormPinLayout.visibility = View.GONE
|
||||
loginFormSymbolLayout.visibility = View.VISIBLE
|
||||
loginFormTokenLayout.visibility = View.GONE
|
||||
loginFormUsernameLayout.visibility = VISIBLE
|
||||
loginFormPassLayout.visibility = VISIBLE
|
||||
loginFormHostLayout.visibility = VISIBLE
|
||||
loginFormPinLayout.visibility = GONE
|
||||
loginFormSymbolLayout.visibility = VISIBLE
|
||||
loginFormTokenLayout.visibility = GONE
|
||||
}
|
||||
|
||||
override fun showOnlyMobileApiModeInputs() {
|
||||
loginFormUsernameLayout.visibility = View.GONE
|
||||
loginFormPassLayout.visibility = View.GONE
|
||||
loginFormHostLayout.visibility = View.GONE
|
||||
loginFormPinLayout.visibility = View.VISIBLE
|
||||
loginFormSymbolLayout.visibility = View.VISIBLE
|
||||
loginFormTokenLayout.visibility = View.VISIBLE
|
||||
loginFormUsernameLayout.visibility = GONE
|
||||
loginFormPassLayout.visibility = GONE
|
||||
loginFormHostLayout.visibility = GONE
|
||||
loginFormPinLayout.visibility = VISIBLE
|
||||
loginFormSymbolLayout.visibility = VISIBLE
|
||||
loginFormTokenLayout.visibility = VISIBLE
|
||||
}
|
||||
|
||||
override fun showSoftKeyboard() {
|
||||
@ -247,11 +250,11 @@ class LoginAdvancedFragment : BaseFragment(), LoginAdvancedView {
|
||||
}
|
||||
|
||||
override fun showProgress(show: Boolean) {
|
||||
loginFormProgress.visibility = if (show) View.VISIBLE else View.GONE
|
||||
loginFormProgress.visibility = if (show) VISIBLE else GONE
|
||||
}
|
||||
|
||||
override fun showContent(show: Boolean) {
|
||||
loginFormContainer.visibility = if (show) View.VISIBLE else View.GONE
|
||||
loginFormContainer.visibility = if (show) VISIBLE else GONE
|
||||
}
|
||||
|
||||
override fun notifyParentAccountLogged(students: List<Student>) {
|
||||
|
@ -74,14 +74,15 @@ class LoginFormFragment : BaseFragment(), LoginFormView {
|
||||
loginFormPrivacyLink.setOnClickListener { presenter.onPrivacyLinkClick() }
|
||||
loginFormFaq.setOnClickListener { presenter.onFaqClick() }
|
||||
loginFormContactEmail.setOnClickListener { presenter.onEmailClick() }
|
||||
|
||||
loginFormRecoverLink.setOnClickListener { presenter.onRecoverClick() }
|
||||
loginFormPass.setOnEditorActionListener { _, id, _ ->
|
||||
if (id == IME_ACTION_DONE || id == IME_NULL) loginFormSignIn.callOnClick() else false
|
||||
}
|
||||
|
||||
with(loginFormHost) {
|
||||
setText(hostKeys.getOrElse(0) { "" })
|
||||
setText(hostKeys.getOrNull(0).orEmpty())
|
||||
setAdapter(LoginSymbolAdapter(context, R.layout.support_simple_spinner_dropdown_item, hostKeys))
|
||||
setOnClickListener { if (loginFormContainer.visibility == GONE) dismissDropDown() }
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,6 +168,10 @@ class LoginFormFragment : BaseFragment(), LoginFormView {
|
||||
(activity as? LoginActivity)?.onAdvancedLoginClick()
|
||||
}
|
||||
|
||||
override fun onRecoverClick() {
|
||||
(activity as? LoginActivity)?.onRecoverClick()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
presenter.onDetachView()
|
||||
|
@ -108,6 +108,10 @@ class LoginFormPresenter @Inject constructor(
|
||||
view?.openEmail()
|
||||
}
|
||||
|
||||
fun onRecoverClick() {
|
||||
view?.onRecoverClick()
|
||||
}
|
||||
|
||||
private fun validateCredentials(login: String, password: String): Boolean {
|
||||
var isCorrect = true
|
||||
|
||||
|
@ -54,4 +54,6 @@ interface LoginFormView : BaseView {
|
||||
fun openEmail()
|
||||
|
||||
fun openAdvancedLogin()
|
||||
|
||||
fun onRecoverClick()
|
||||
}
|
||||
|
@ -0,0 +1,209 @@
|
||||
package io.github.wulkanowy.ui.modules.login.recover
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.View.GONE
|
||||
import android.view.View.VISIBLE
|
||||
import android.view.ViewGroup
|
||||
import android.webkit.JavascriptInterface
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import android.widget.ArrayAdapter
|
||||
import androidx.core.widget.doOnTextChanged
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
||||
import io.github.wulkanowy.ui.modules.login.form.LoginSymbolAdapter
|
||||
import io.github.wulkanowy.utils.hideSoftInput
|
||||
import io.github.wulkanowy.utils.showSoftInput
|
||||
import kotlinx.android.synthetic.main.fragment_login_recover.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class LoginRecoverFragment : BaseFragment(), LoginRecoverView {
|
||||
|
||||
@Inject
|
||||
lateinit var presenter: LoginRecoverPresenter
|
||||
|
||||
companion object {
|
||||
fun newInstance() = LoginRecoverFragment()
|
||||
}
|
||||
|
||||
private lateinit var hostKeys: Array<String>
|
||||
|
||||
private lateinit var hostValues: Array<String>
|
||||
|
||||
override val recoverHostValue: String
|
||||
get() = hostValues.getOrNull(hostKeys.indexOf(loginRecoverHost.text.toString())).orEmpty()
|
||||
|
||||
override val recoverNameValue: String
|
||||
get() = loginRecoverName.text.toString().trim()
|
||||
|
||||
override val recoverSymbolValue: String
|
||||
get() = loginRecoverSymbol.text.toString().trim()
|
||||
|
||||
override val emailHintString: String
|
||||
get() = getString(R.string.login_email_hint)
|
||||
|
||||
override val loginPeselEmailHintString: String
|
||||
get() = getString(R.string.login_login_pesel_email_hint)
|
||||
|
||||
override val invalidEmailString: String
|
||||
get() = getString(R.string.login_invalid_email)
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_login_recover, container, false)
|
||||
}
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
presenter.onAttachView(this)
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
loginRecoverWebView.setBackgroundColor(Color.TRANSPARENT)
|
||||
hostKeys = resources.getStringArray(R.array.hosts_keys)
|
||||
hostValues = resources.getStringArray(R.array.hosts_values)
|
||||
|
||||
loginRecoverName.doOnTextChanged { _, _, _, _ -> presenter.onNameTextChanged() }
|
||||
loginRecoverHost.setOnItemClickListener { _, _, _, _ -> presenter.onHostSelected() }
|
||||
loginRecoverButton.setOnClickListener { presenter.onRecoverClick() }
|
||||
loginRecoverErrorRetry.setOnClickListener { presenter.onRecoverClick() }
|
||||
loginRecoverErrorDetails.setOnClickListener { presenter.onDetailsClick() }
|
||||
loginRecoverLogin.setOnClickListener { (activity as LoginActivity).switchView(0) }
|
||||
|
||||
loginRecoverSymbol.setAdapter(ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, resources.getStringArray(R.array.symbols_values)))
|
||||
|
||||
with(loginRecoverHost) {
|
||||
setText(hostKeys.getOrNull(0).orEmpty())
|
||||
setAdapter(LoginSymbolAdapter(context, R.layout.support_simple_spinner_dropdown_item, hostKeys))
|
||||
setOnClickListener { if (loginRecoverFormContainer.visibility == GONE) dismissDropDown() }
|
||||
}
|
||||
}
|
||||
|
||||
override fun setDefaultCredentials(username: String, symbol: String) {
|
||||
loginRecoverName.setText(username)
|
||||
loginRecoverSymbol.setText(symbol)
|
||||
}
|
||||
|
||||
override fun setErrorNameRequired() {
|
||||
with(loginRecoverNameLayout) {
|
||||
requestFocus()
|
||||
error = getString(R.string.login_field_required)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setUsernameHint(hint: String) {
|
||||
loginRecoverNameLayout.hint = hint
|
||||
}
|
||||
|
||||
override fun setUsernameError(message: String) {
|
||||
with(loginRecoverNameLayout) {
|
||||
requestFocus()
|
||||
error = message
|
||||
}
|
||||
}
|
||||
|
||||
override fun clearUsernameError() {
|
||||
loginRecoverNameLayout.error = null
|
||||
}
|
||||
|
||||
override fun showSymbol(show: Boolean) {
|
||||
loginRecoverSymbolLayout.visibility = if (show) VISIBLE else GONE
|
||||
}
|
||||
|
||||
override fun showProgress(show: Boolean) {
|
||||
loginRecoverProgress.visibility = if (show) VISIBLE else GONE
|
||||
}
|
||||
|
||||
override fun showRecoverForm(show: Boolean) {
|
||||
loginRecoverFormContainer.visibility = if (show) VISIBLE else GONE
|
||||
}
|
||||
|
||||
override fun showCaptcha(show: Boolean) {
|
||||
loginRecoverCaptchaContainer.visibility = if (show) VISIBLE else GONE
|
||||
}
|
||||
|
||||
override fun showErrorView(show: Boolean) {
|
||||
loginRecoverError.visibility = if (show) VISIBLE else GONE
|
||||
}
|
||||
|
||||
override fun setErrorDetails(message: String) {
|
||||
loginRecoverErrorMessage.text = message
|
||||
}
|
||||
|
||||
override fun showSuccessView(show: Boolean) {
|
||||
loginRecoverSuccess.visibility = if (show) VISIBLE else GONE
|
||||
}
|
||||
|
||||
override fun setSuccessTitle(title: String) {
|
||||
loginRecoverSuccessTitle.text = title
|
||||
}
|
||||
|
||||
override fun setSuccessMessage(message: String) {
|
||||
loginRecoverSuccessMessage.text = message
|
||||
}
|
||||
|
||||
override fun showSoftKeyboard() {
|
||||
activity?.showSoftInput()
|
||||
}
|
||||
|
||||
override fun hideSoftKeyboard() {
|
||||
activity?.hideSoftInput()
|
||||
}
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled", "AddJavascriptInterface")
|
||||
override fun loadReCaptcha(siteKey: String, url: String) {
|
||||
val html = """
|
||||
<div style="position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);" id="recaptcha"></div>
|
||||
<script src="https://www.google.com/recaptcha/api.js?onload=cl&render=explicit&hl=pl" async defer></script>
|
||||
<script>var cl=()=>grecaptcha.render("recaptcha",{
|
||||
sitekey:'$siteKey',
|
||||
callback:e =>Android.captchaCallback(e)})</script>
|
||||
""".trimIndent()
|
||||
|
||||
with(loginRecoverWebView) {
|
||||
settings.javaScriptEnabled = true
|
||||
webViewClient = object : WebViewClient() {
|
||||
private var recoverWebViewSuccess: Boolean = true
|
||||
|
||||
override fun onPageFinished(view: WebView?, url: String?) {
|
||||
if (recoverWebViewSuccess) {
|
||||
showCaptcha(true)
|
||||
showProgress(false)
|
||||
} else {
|
||||
showProgress(false)
|
||||
showErrorView(true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onReceivedError(view: WebView, errorCode: Int, description: String, failingUrl: String) {
|
||||
recoverWebViewSuccess = false
|
||||
}
|
||||
}
|
||||
|
||||
loadDataWithBaseURL(url, html, "text/html", "UTF-8", null)
|
||||
addJavascriptInterface(object {
|
||||
@JavascriptInterface
|
||||
fun captchaCallback(reCaptchaResponse: String) {
|
||||
activity?.runOnUiThread {
|
||||
presenter.onReCaptchaVerified(reCaptchaResponse)
|
||||
}
|
||||
}
|
||||
}, "Android")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
presenter.updateFields()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
loginRecoverWebView.destroy()
|
||||
presenter.onDetachView()
|
||||
}
|
||||
}
|
@ -0,0 +1,157 @@
|
||||
package io.github.wulkanowy.ui.modules.login.recover
|
||||
|
||||
import io.github.wulkanowy.data.repositories.recover.RecoverRepository
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import io.github.wulkanowy.utils.ifNullOrBlank
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class LoginRecoverPresenter @Inject constructor(
|
||||
schedulers: SchedulersProvider,
|
||||
studentRepository: StudentRepository,
|
||||
private val loginErrorHandler: RecoverErrorHandler,
|
||||
private val analytics: FirebaseAnalyticsHelper,
|
||||
private val recoverRepository: RecoverRepository
|
||||
) : BasePresenter<LoginRecoverView>(loginErrorHandler, studentRepository, schedulers) {
|
||||
|
||||
private lateinit var lastError: Throwable
|
||||
|
||||
override fun onAttachView(view: LoginRecoverView) {
|
||||
super.onAttachView(view)
|
||||
view.initView()
|
||||
|
||||
with(loginErrorHandler) {
|
||||
showErrorMessage = ::showErrorMessage
|
||||
onInvalidUsername = ::onInvalidUsername
|
||||
onInvalidCaptcha = ::onInvalidCaptcha
|
||||
}
|
||||
}
|
||||
|
||||
fun onNameTextChanged() {
|
||||
view?.clearUsernameError()
|
||||
}
|
||||
|
||||
fun onHostSelected() {
|
||||
view?.run {
|
||||
if ("fakelog" in recoverHostValue) setDefaultCredentials("jan@fakelog.cf", "Default")
|
||||
clearUsernameError()
|
||||
updateFields()
|
||||
}
|
||||
}
|
||||
|
||||
fun updateFields() {
|
||||
view?.run {
|
||||
if ("fakelog" in recoverHostValue || "vulcan" in recoverHostValue) {
|
||||
showSymbol(true)
|
||||
setUsernameHint(emailHintString)
|
||||
} else {
|
||||
showSymbol(false)
|
||||
setUsernameHint(loginPeselEmailHintString)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onRecoverClick() {
|
||||
val username = view?.recoverNameValue.orEmpty()
|
||||
val host = view?.recoverHostValue.orEmpty()
|
||||
val symbol = view?.recoverSymbolValue.ifNullOrBlank { "Default" }
|
||||
|
||||
if (username.isEmpty()) {
|
||||
view?.setErrorNameRequired()
|
||||
return
|
||||
}
|
||||
|
||||
if (("fakelog" in host || "vulcan" in host) && "@" !in username) {
|
||||
view?.setUsernameError(view?.invalidEmailString.orEmpty())
|
||||
return
|
||||
}
|
||||
|
||||
disposable.add(recoverRepository.getReCaptchaSiteKey(host, symbol)
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doOnSubscribe {
|
||||
view?.run {
|
||||
hideSoftKeyboard()
|
||||
showRecoverForm(false)
|
||||
showProgress(true)
|
||||
showErrorView(false)
|
||||
showCaptcha(false)
|
||||
}
|
||||
}
|
||||
.subscribe({ (resetUrl, siteKey) ->
|
||||
view?.loadReCaptcha(siteKey, resetUrl)
|
||||
}) {
|
||||
Timber.e("Obtain captcha site key result: An exception occurred")
|
||||
errorHandler.dispatch(it)
|
||||
})
|
||||
}
|
||||
|
||||
fun onReCaptchaVerified(reCaptchaResponse: String) {
|
||||
val username = view?.recoverNameValue.orEmpty()
|
||||
val host = view?.recoverHostValue.orEmpty()
|
||||
val symbol = view?.recoverSymbolValue.ifNullOrBlank { "Default" }
|
||||
|
||||
with(disposable) {
|
||||
clear()
|
||||
add(recoverRepository.sendRecoverRequest(host, symbol, username, reCaptchaResponse)
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doOnSubscribe {
|
||||
view?.run {
|
||||
showProgress(true)
|
||||
showRecoverForm(false)
|
||||
showCaptcha(false)
|
||||
}
|
||||
}
|
||||
.doFinally {
|
||||
view?.showProgress(false)
|
||||
}
|
||||
.subscribe({
|
||||
view?.run {
|
||||
showSuccessView(true)
|
||||
setSuccessTitle(it.substringBefore(". "))
|
||||
setSuccessMessage(it.substringAfter(". "))
|
||||
}
|
||||
|
||||
analytics.logEvent("account_recover", "register" to host, "symbol" to symbol, "success" to true)
|
||||
}) {
|
||||
Timber.e("Send recover request result: An exception occurred")
|
||||
errorHandler.dispatch(it)
|
||||
analytics.logEvent("account_recover", "register" to host, "symbol" to symbol, "success" to false)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fun onDetailsClick() {
|
||||
view?.showErrorDetailsDialog(lastError)
|
||||
}
|
||||
|
||||
private fun showErrorMessage(message: String, error: Throwable) {
|
||||
view?.run {
|
||||
lastError = error
|
||||
showProgress(false)
|
||||
setErrorDetails(message)
|
||||
showErrorView(true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onInvalidUsername(message: String) {
|
||||
view?.run {
|
||||
setUsernameError(message)
|
||||
showRecoverForm(true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onInvalidCaptcha(message: String, error: Throwable) {
|
||||
view?.run {
|
||||
lastError = error
|
||||
setErrorDetails(message)
|
||||
showCaptcha(false)
|
||||
showRecoverForm(false)
|
||||
showErrorView(true)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package io.github.wulkanowy.ui.modules.login.recover
|
||||
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
|
||||
interface LoginRecoverView : BaseView {
|
||||
|
||||
val recoverHostValue: String
|
||||
|
||||
val recoverNameValue: String
|
||||
|
||||
val recoverSymbolValue: String
|
||||
|
||||
val emailHintString: String
|
||||
|
||||
val loginPeselEmailHintString: String
|
||||
|
||||
val invalidEmailString: String
|
||||
|
||||
fun initView()
|
||||
|
||||
fun setDefaultCredentials(username: String, symbol: String)
|
||||
|
||||
fun clearUsernameError()
|
||||
|
||||
fun showSymbol(show: Boolean)
|
||||
|
||||
fun setErrorNameRequired()
|
||||
|
||||
fun setUsernameHint(hint: String)
|
||||
|
||||
fun setUsernameError(message: String)
|
||||
|
||||
fun showSoftKeyboard()
|
||||
|
||||
fun hideSoftKeyboard()
|
||||
|
||||
fun showProgress(show: Boolean)
|
||||
|
||||
fun showRecoverForm(show: Boolean)
|
||||
|
||||
fun showCaptcha(show: Boolean)
|
||||
|
||||
fun showErrorView(show: Boolean)
|
||||
|
||||
fun setErrorDetails(message: String)
|
||||
|
||||
fun showSuccessView(show: Boolean)
|
||||
|
||||
fun setSuccessMessage(message: String)
|
||||
|
||||
fun setSuccessTitle(title: String)
|
||||
|
||||
fun loadReCaptcha(siteKey: String, url: String)
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package io.github.wulkanowy.ui.modules.login.recover
|
||||
|
||||
import android.content.res.Resources
|
||||
import com.readystatesoftware.chuck.api.ChuckCollector
|
||||
import io.github.wulkanowy.sdk.scrapper.exception.InvalidCaptchaException
|
||||
import io.github.wulkanowy.sdk.scrapper.exception.InvalidEmailException
|
||||
import io.github.wulkanowy.sdk.scrapper.exception.NoAccountFoundException
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import javax.inject.Inject
|
||||
|
||||
class RecoverErrorHandler @Inject constructor(
|
||||
resources: Resources,
|
||||
chuckCollector: ChuckCollector
|
||||
) : ErrorHandler(resources, chuckCollector) {
|
||||
|
||||
var onInvalidUsername: (String) -> Unit = {}
|
||||
|
||||
var onInvalidCaptcha: (String, Throwable) -> Unit = { _, _ -> }
|
||||
|
||||
override fun proceed(error: Throwable) {
|
||||
when (error) {
|
||||
is InvalidEmailException, is NoAccountFoundException -> onInvalidUsername(error.localizedMessage.orEmpty())
|
||||
is InvalidCaptchaException -> onInvalidCaptcha(error.localizedMessage.orEmpty(), error)
|
||||
else -> super.proceed(error)
|
||||
}
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
super.clear()
|
||||
onInvalidUsername = {}
|
||||
}
|
||||
}
|
@ -154,7 +154,7 @@
|
||||
android:hint="@string/login_password_hint"
|
||||
app:errorEnabled="true"
|
||||
app:errorIconDrawable="@null"
|
||||
app:layout_constraintBottom_toTopOf="@+id/loginFormHostLayout"
|
||||
app:layout_constraintBottom_toTopOf="@+id/loginFormRecoverLink"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/loginFormUsernameLayout"
|
||||
@ -174,6 +174,22 @@
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/loginFormRecoverLink"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:layout_marginRight="24dp"
|
||||
android:text="@string/login_recover_button"
|
||||
android:textAppearance="?android:textAppearance"
|
||||
app:backgroundTint="?android:windowBackground"
|
||||
app:fontFamily="sans-serif-medium"
|
||||
app:layout_constraintBottom_toTopOf="@id/loginFormHostLayout"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/loginFormPassLayout"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/loginFormHostLayout"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
|
||||
@ -181,7 +197,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginLeft="24dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:layout_marginRight="24dp"
|
||||
android:hint="@string/login_host_hint"
|
||||
@ -189,7 +205,7 @@
|
||||
app:layout_constraintBottom_toTopOf="@+id/loginFormSignIn"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/loginFormPassLayout">
|
||||
app:layout_constraintTop_toBottomOf="@+id/loginFormRecoverLink">
|
||||
|
||||
<AutoCompleteTextView
|
||||
android:id="@+id/loginFormHost"
|
||||
|
272
app/src/main/res/layout/fragment_login_recover.xml
Normal file
272
app/src/main/res/layout/fragment_login_recover.xml
Normal file
@ -0,0 +1,272 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ui.modules.login.recover.LoginRecoverFragment">
|
||||
|
||||
<me.zhanghai.android.materialprogressbar.MaterialProgressBar
|
||||
android:id="@+id/loginRecoverProgress"
|
||||
style="@style/Widget.MaterialProgressBar.ProgressBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminate="true"
|
||||
android:visibility="gone" />
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/nestedScrollView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true"
|
||||
android:scrollbars="none"
|
||||
tools:visibility="invisible">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/loginRecoverFormContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="16dp"
|
||||
android:visibility="visible">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/loginFormHeader"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginLeft="32dp"
|
||||
android:layout_marginTop="48dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:layout_marginRight="32dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:text="@string/login_recover_title"
|
||||
android:textSize="16sp"
|
||||
app:fontFamily="sans-serif-light"
|
||||
app:layout_constraintBottom_toTopOf="@+id/loginRecoverNameLayout"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/loginRecoverNameLayout"
|
||||
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_email_hint"
|
||||
app:errorEnabled="true"
|
||||
app:layout_constraintBottom_toTopOf="@+id/loginRecoverHostLayout"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/loginFormHeader">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/loginRecoverName"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:autofillHints="emailAddress"
|
||||
android:inputType="textEmailAddress"
|
||||
android:maxLines="1"
|
||||
tools:targetApi="o" />
|
||||
|
||||
<requestFocus />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/loginRecoverHostLayout"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginLeft="24dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:layout_marginRight="24dp"
|
||||
android:hint="@string/login_host_hint"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintBottom_toTopOf="@+id/loginRecoverSymbolLayout"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/loginRecoverNameLayout">
|
||||
|
||||
<AutoCompleteTextView
|
||||
android:id="@+id/loginRecoverHost"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:editable="false"
|
||||
tools:ignore="Deprecated,LabelFor" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/loginRecoverSymbolLayout"
|
||||
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_optional"
|
||||
app:errorEnabled="true"
|
||||
app:layout_constraintBottom_toTopOf="@+id/loginRecoverButton"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/loginRecoverHostLayout">
|
||||
|
||||
<AutoCompleteTextView
|
||||
android:id="@+id/loginRecoverSymbol"
|
||||
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:inputType="textAutoComplete|textNoSuggestions"
|
||||
android:maxLines="1"
|
||||
tools:ignore="LabelFor" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/loginRecoverButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:layout_marginRight="24dp"
|
||||
android:text="@string/login_recover"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/loginRecoverSymbolLayout" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/loginRecoverCaptchaContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone">
|
||||
|
||||
<WebView
|
||||
android:id="@+id/loginRecoverWebView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/loginRecoverError"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="invisible"
|
||||
tools:ignore="UseCompoundDrawables"
|
||||
tools:visibility="invisible">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
app:srcCompat="@drawable/ic_error"
|
||||
app:tint="?colorOnBackground"
|
||||
tools:ignore="contentDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/loginRecoverErrorMessage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:gravity="center"
|
||||
android:padding="8dp"
|
||||
android:text="@string/error_unknown"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/loginRecoverErrorDetails"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:text="@string/all_details" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/loginRecoverErrorRetry"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/all_retry" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/loginRecoverSuccess"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true"
|
||||
android:scrollbars="none"
|
||||
android:visibility="invisible"
|
||||
tools:visibility="visible">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
app:srcCompat="@drawable/ic_all_done"
|
||||
app:tint="?colorOnBackground"
|
||||
tools:ignore="contentDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/loginRecoverSuccessTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="35dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginEnd="35dp"
|
||||
android:gravity="center"
|
||||
android:textSize="20sp"
|
||||
tools:text="Pomyślnie wysłano email!" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/loginRecoverSuccessMessage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="35dp"
|
||||
android:lineSpacingMultiplier="1.5"
|
||||
android:scrollbars="vertical"
|
||||
android:text="@string/login_recover"
|
||||
android:textSize="14sp"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/loginRecoverLogin"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginEnd="30dp"
|
||||
android:layout_marginBottom="30dp"
|
||||
android:text="@android:string/ok" />
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
</FrameLayout>
|
@ -29,9 +29,11 @@
|
||||
<string name="login_header_symbol">Podaj symbol</string>
|
||||
<string name="login_nickname_hint">Nazwa użytkownika</string>
|
||||
<string name="login_email_hint">Email</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_host_hint">Dziennik</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_scrapper">Scraper</string>
|
||||
<string name="login_type_hybrid">Hybrydowe</string>
|
||||
@ -44,11 +46,12 @@
|
||||
<string name="login_invalid_pin">Nieprawidłowy PIN</string>
|
||||
<string name="login_invalid_token">Nieprawidłowy token</string>
|
||||
<string name="login_expired_token">Token stracił ważność</string>
|
||||
<string name="login_invalid_email">Niepoprawny adres email</string>
|
||||
<string name="login_invalid_symbol">Niepoprawny symbol</string>
|
||||
<string name="login_incorrect_symbol">Nie znaleziono ucznia. Sprawdź symbol</string>
|
||||
<string name="login_field_required">To pole jest wymagane</string>
|
||||
<string name="login_duplicate_student">Wybrany uczeń jest już zalogowany</string>
|
||||
<string name="login_symbol_helper">Symbol znajdziesz na stronie dziennika w Uczeń -> Dostęp Mobilny -> Zarejestruj urządzenie mobilne</string>
|
||||
<string name="login_symbol_helper">Symbol znajdziesz na stronie dziennika w Uczeń -> Dostęp Mobilny -> Zarejestruj urządzenie mobilne</string>
|
||||
<string name="login_select_student">Wybierz uczniów do zalogowania w aplikacji</string>
|
||||
<string name="login_advanced">Inne opcje</string>
|
||||
<string name="login_privacy_policy">Polityka prywatności</string>
|
||||
@ -56,6 +59,9 @@
|
||||
<string name="login_contact_email">Email</string>
|
||||
<string name="login_contact_discord">Discord</string>
|
||||
<string name="login_email_intent_title">Wyślij email</string>
|
||||
<string name="login_recover_button">Nie pamiętam hasła</string>
|
||||
<string name="login_recover_title">Przywróć swoje konto</string>
|
||||
<string name="login_recover">Przywróć</string>
|
||||
<string name="login_signed_in">Uczeń jest już zalogowany</string>
|
||||
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
<string name="login_header_symbol">Впишите \"symbol\"</string>
|
||||
<string name="login_nickname_hint">Имя пользователя</string>
|
||||
<string name="login_email_hint">Электронная почта</string>
|
||||
<string name="login_login_pesel_email_hint">Логин, PESEL или электронная почта</string>
|
||||
<string name="login_password_hint">Пароль</string>
|
||||
<string name="login_host_hint">Дневник</string>
|
||||
<string name="login_type_api">Мобильный API</string>
|
||||
@ -39,12 +40,14 @@
|
||||
<string name="login_pin_hint">PIN</string>
|
||||
<string name="login_api_key_hint">клавиша API</string>
|
||||
<string name="login_symbol_hint">Symbol</string>
|
||||
<string name="login_symbol_hint_optional">Символ (необязательно)</string>
|
||||
<string name="login_sign_in">Войти</string>
|
||||
<string name="login_invalid_password">Слишком короткий пароль</string>
|
||||
<string name="login_incorrect_password">Указаны неверные данные</string>
|
||||
<string name="login_invalid_pin">Недействительный PIN</string>
|
||||
<string name="login_invalid_token">Недействительный token</string>
|
||||
<string name="login_expired_token">Токен просрочен</string>
|
||||
<string name="login_invalid_email">Неверный адрес электронной почты</string>
|
||||
<string name="login_invalid_symbol">Недействительный symbol</string>
|
||||
<string name="login_incorrect_symbol">Не удалось найти ученика. Пожалуйста, проверьте \"symbol\"</string>
|
||||
<string name="login_field_required">Это поле обязательно</string>
|
||||
@ -57,6 +60,9 @@
|
||||
<string name="login_contact_email">Электронная почта</string>
|
||||
<string name="login_contact_discord">Discord</string>
|
||||
<string name="login_email_intent_title">Отправить письмо</string>
|
||||
<string name="login_recover">восстановление</string>
|
||||
<string name="login_recover_button">Я не помню пароль</string>
|
||||
<string name="login_recover_title">Восстановите свой аккаунт</string>
|
||||
<string name="login_signed_in">Студент уже вошел в систему</string>
|
||||
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
<string name="login_header_symbol">Enter the symbol</string>
|
||||
<string name="login_nickname_hint">Username</string>
|
||||
<string name="login_email_hint">Email</string>
|
||||
<string name="login_login_pesel_email_hint">Login, PESEL or e-mail</string>
|
||||
<string name="login_password_hint">Password</string>
|
||||
<string name="login_host_hint">Register</string>
|
||||
<string name="login_type_api">Mobile API</string>
|
||||
@ -39,12 +40,14 @@
|
||||
<string name="login_pin_hint">PIN</string>
|
||||
<string name="login_api_key_hint">API key</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_invalid_password">Password too short</string>
|
||||
<string name="login_incorrect_password">Login details are incorrect</string>
|
||||
<string name="login_invalid_pin">Invalid PIN</string>
|
||||
<string name="login_invalid_token">Invalid token</string>
|
||||
<string name="login_expired_token">Token expired</string>
|
||||
<string name="login_invalid_email">Invalid email</string>
|
||||
<string name="login_invalid_symbol">Invalid symbol</string>
|
||||
<string name="login_incorrect_symbol">Student not found. Check the symbol</string>
|
||||
<string name="login_field_required">This field is required</string>
|
||||
@ -59,6 +62,9 @@
|
||||
<string name="login_email_intent_title">Send email</string>
|
||||
<string name="login_email_subject" translatable="false">Zgłoszenie: Problemy z logowaniem</string>
|
||||
<string name="login_email_text" translatable="false">Informacje o aplikacji:\n\nUrządzenie: %1$s\nWersja SDK: %2$s\nWersja aplikacji: %3$s\n\nOpis problemu:</string>
|
||||
<string name="login_recover_button">I forgot my password</string>
|
||||
<string name="login_recover_title">Recover your account</string>
|
||||
<string name="login_recover">Recover</string>
|
||||
<string name="login_signed_in">Student is already signed in</string>
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user