diff --git a/app/sampledata/vulcan/edu.lublin.eu.png b/app/sampledata/vulcan/edu.lublin.eu.png
new file mode 100644
index 00000000..ece8b925
Binary files /dev/null and b/app/sampledata/vulcan/edu.lublin.eu.png differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index cc82fed3..a146711d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -135,9 +135,6 @@
android:configChanges="orientation|screenSize"
android:launchMode="singleTop"
android:theme="@style/AppTheme.Light" />
-
Unit) {
).apply {
studentData["isPremium"] = account?.getBoolean("IsPremium") == true || account?.getBoolean("IsPremiumDemo") == true
studentData["accountId"] = account.getInt("Id") ?: 0
- studentData["accountLogin"] = login
+ studentData["accountLogin"] = data.apiLogin ?: login
+ studentData["accountPassword"] = data.apiPassword
studentData["accountToken"] = data.apiAccessToken
studentData["accountTokenTime"] = data.apiTokenExpiryTime
studentData["accountRefreshToken"] = data.apiRefreshToken
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/LibrusLoginPortal.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/LibrusLoginPortal.kt
index 166a4ae5..5198d155 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/LibrusLoginPortal.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/LibrusLoginPortal.kt
@@ -146,12 +146,14 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
}
val error = if (response.code() == 200) null else
json.getJsonArray("errors")?.getString(0)
+ ?: json.getJsonObject("errors")?.entrySet()?.firstOrNull()?.value?.asString
error?.let { code ->
when {
code.contains("Sesja logowania wygasła") -> ERROR_LOGIN_LIBRUS_PORTAL_CSRF_EXPIRED
code.contains("Upewnij się, że nie") -> ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN
// this doesn't work anyway: `errors` is an object with `g-recaptcha-response` set
code.contains("robotem") -> ERROR_CAPTCHA_LIBRUS_PORTAL
+ code.contains("Podany adres e-mail jest nieprawidłowy.") -> ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN
else -> ERROR_LOGIN_LIBRUS_PORTAL_ACTION_ERROR
}.let { errorCode ->
data.error(ApiError(TAG, errorCode)
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/models/Data.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/models/Data.kt
index 5e998425..ed1fba00 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/models/Data.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/models/Data.kt
@@ -197,6 +197,13 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
profile.userCode = generateUserCode()
+ // update profile subname with class name, school year and account type
+ profile.subname = joinNotNullStrings(
+ " - ",
+ profile.studentClassName,
+ "${profile.studentSchoolYearStart}/${profile.studentSchoolYearStart + 1}"
+ ) + " " + app.getString(if (profile.isParent) R.string.account_type_parent else R.string.account_type_child)
+
db.profileDao().add(profile)
db.loginStoreDao().add(loginStore)
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyApi.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyApi.kt
index bdd14f33..ae82ff8f 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyApi.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyApi.kt
@@ -27,6 +27,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.db.full.EventFull
import pl.szczodrzynski.edziennik.ui.modules.error.ErrorDetailsDialog
import pl.szczodrzynski.edziennik.ui.modules.error.ErrorSnackbar
+import pl.szczodrzynski.edziennik.ui.modules.login.LoginInfo
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
import retrofit2.Response
@@ -73,7 +74,7 @@ class SzkolnyApi(val app: App) : CoroutineScope {
suspend inline fun runCatching(errorSnackbar: ErrorSnackbar, crossinline block: SzkolnyApi.() -> T?): T? {
return try {
- withContext(Dispatchers.Default) { block() }
+ withContext(Dispatchers.Default) { block.invoke(this@SzkolnyApi) }
}
catch (e: Exception) {
errorSnackbar.addError(e.toApiError(TAG)).show()
@@ -82,7 +83,7 @@ class SzkolnyApi(val app: App) : CoroutineScope {
}
suspend inline fun runCatching(activity: AppCompatActivity, crossinline block: SzkolnyApi.() -> T?): T? {
return try {
- withContext(Dispatchers.Default) { block() }
+ withContext(Dispatchers.Default) { block.invoke(this@SzkolnyApi) }
}
catch (e: Exception) {
ErrorDetailsDialog(
@@ -95,7 +96,7 @@ class SzkolnyApi(val app: App) : CoroutineScope {
}
inline fun runCatching(block: SzkolnyApi.() -> T, onError: (e: Throwable) -> Unit): T? {
return try {
- block()
+ block.invoke(this@SzkolnyApi)
}
catch (e: Exception) {
onError(e)
@@ -327,4 +328,11 @@ class SzkolnyApi(val app: App) : CoroutineScope {
return parseResponse(response).message
}
+
+ @Throws(Exception::class)
+ fun getPlatforms(registerName: String): List {
+ val response = api.appLoginPlatforms(registerName).execute()
+
+ return parseResponse(response)
+ }
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyService.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyService.kt
index 0e3dd574..bce3aef0 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyService.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyService.kt
@@ -6,11 +6,9 @@ package pl.szczodrzynski.edziennik.data.api.szkolny
import pl.szczodrzynski.edziennik.data.api.szkolny.request.*
import pl.szczodrzynski.edziennik.data.api.szkolny.response.*
+import pl.szczodrzynski.edziennik.ui.modules.login.LoginInfo
import retrofit2.Call
-import retrofit2.http.Body
-import retrofit2.http.GET
-import retrofit2.http.POST
-import retrofit2.http.Query
+import retrofit2.http.*
interface SzkolnyService {
@@ -34,4 +32,7 @@ interface SzkolnyService {
@POST("feedbackMessage")
fun feedbackMessage(@Body request: FeedbackMessageRequest): Call>
+
+ @GET("appLogin/platforms/{registerName}")
+ fun appLoginPlatforms(@Path("registerName") registerName: String): Call>>
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Profile.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Profile.kt
index 1442f40c..aa28faf7 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Profile.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Profile.kt
@@ -80,7 +80,7 @@ open class Profile(
var dateYearEnd = Date(studentSchoolYearStart + 1, 6, 30)
fun getSemesterStart(semester: Int) = if (semester == 1) dateSemester1Start else dateSemester2Start
fun getSemesterEnd(semester: Int) = if (semester == 1) dateSemester2Start.clone().stepForward(0, 0, -1) else dateYearEnd
- fun dateToSemester(date: Date) = if (date.value >= getSemesterStart(2).value) 2 else 1
+ fun dateToSemester(date: Date) = if (date >= dateSemester2Start) 2 else 1
@delegate:Ignore
val currentSemester by lazy { dateToSemester(Date.getToday()) }
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginActivity.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginActivity.kt
index 7f65279f..c686b857 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginActivity.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginActivity.kt
@@ -1,3 +1,7 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-16.
+ */
+
package pl.szczodrzynski.edziennik.ui.modules.login
import android.app.Activity
@@ -14,20 +18,19 @@ import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
-import pl.szczodrzynski.edziennik.databinding.ActivityLoginBinding
+import pl.szczodrzynski.edziennik.databinding.LoginActivityBinding
import pl.szczodrzynski.edziennik.ui.modules.error.ErrorSnackbar
import kotlin.coroutines.CoroutineContext
class LoginActivity : AppCompatActivity(), CoroutineScope {
companion object {
private const val TAG = "LoginActivity"
- @JvmField
- var navOptions: NavOptions? = null
var thisOneIsTricky = 0
}
private val app: App by lazy { applicationContext as App }
- private lateinit var b: ActivityLoginBinding
+ private lateinit var b: LoginActivityBinding
+ lateinit var navOptions: NavOptions
val nav by lazy { Navigation.findNavController(this, R.id.nav_host_fragment) }
val errorSnackbar: ErrorSnackbar by lazy { ErrorSnackbar(this) }
@@ -36,7 +39,7 @@ class LoginActivity : AppCompatActivity(), CoroutineScope {
get() = job + Dispatchers.Main
var lastError: ApiError? = null
- val profiles = mutableListOf()
+ val profiles = mutableListOf()
val loginStores = mutableListOf()
override fun onBackPressed() {
@@ -50,7 +53,9 @@ class LoginActivity : AppCompatActivity(), CoroutineScope {
return
if (destination.id == R.id.loginSyncFragment)
return
- if (destination.id == R.id.loginChooserFragment) {
+ if (destination.id == R.id.loginFinishFragment)
+ return
+ if (destination.id == R.id.loginChooserFragment && loginStores.isEmpty()) {
setResult(Activity.RESULT_CANCELED)
finish()
return
@@ -83,7 +88,7 @@ class LoginActivity : AppCompatActivity(), CoroutineScope {
.setPopExitAnim(R.anim.slide_out_right)
.build()
- b = ActivityLoginBinding.inflate(layoutInflater)
+ b = LoginActivityBinding.inflate(layoutInflater)
setContentView(b.root)
errorSnackbar.setCoordinator(b.coordinator, b.snackbarAnchor)
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserAdapter.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserAdapter.kt
new file mode 100644
index 00000000..c9ed2d6e
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserAdapter.kt
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-16.
+ */
+
+package pl.szczodrzynski.edziennik.ui.modules.login
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.appcompat.app.AppCompatActivity
+import androidx.recyclerview.widget.RecyclerView
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import pl.szczodrzynski.edziennik.App
+import pl.szczodrzynski.edziennik.R
+import pl.szczodrzynski.edziennik.ui.modules.grades.models.ExpandableItemModel
+import pl.szczodrzynski.edziennik.ui.modules.grades.viewholder.BindableViewHolder
+import pl.szczodrzynski.edziennik.ui.modules.login.viewholder.ModeViewHolder
+import pl.szczodrzynski.edziennik.ui.modules.login.viewholder.RegisterViewHolder
+import kotlin.coroutines.CoroutineContext
+
+class LoginChooserAdapter(
+ val activity: AppCompatActivity,
+ val onModeClick: ((loginType: LoginInfo.Register, loginMode: LoginInfo.Mode) -> Unit)? = null
+) : RecyclerView.Adapter(), CoroutineScope {
+ companion object {
+ private const val TAG = "LoginChooserAdapter"
+ private const val ITEM_TYPE_REGISTER = 0
+ private const val ITEM_TYPE_MODE = 1
+ const val STATE_CLOSED = 0
+ const val STATE_OPENED = 1
+ }
+
+ private val app = activity.applicationContext as App
+ // optional: place the manager here
+
+ private val job = Job()
+ override val coroutineContext: CoroutineContext
+ get() = job + Dispatchers.Main
+
+ var items = mutableListOf()
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
+ val inflater = LayoutInflater.from(parent.context)
+ return when (viewType) {
+ ITEM_TYPE_REGISTER -> RegisterViewHolder(inflater, parent)
+ ITEM_TYPE_MODE -> ModeViewHolder(inflater, parent)
+ else -> throw IllegalArgumentException("Incorrect viewType")
+ }
+ }
+
+ override fun getItemViewType(position: Int): Int {
+ return when (items[position]) {
+ is LoginInfo.Register -> ITEM_TYPE_REGISTER
+ is LoginInfo.Mode -> ITEM_TYPE_MODE
+ else -> throw IllegalArgumentException("Incorrect viewType")
+ }
+ }
+
+ private val onClickListener = View.OnClickListener { view ->
+ val model = view.getTag(R.string.tag_key_model)
+ if (model is LoginInfo.Register && model.loginModes.size == 1) {
+ onModeClick?.invoke(model, model.loginModes.first())
+ return@OnClickListener
+ }
+ if (model is LoginInfo.Mode) {
+ val loginInfo = items.firstOrNull {
+ it is LoginInfo.Register && it.loginModes.contains(model)
+ } as? LoginInfo.Register
+ ?: return@OnClickListener
+
+ onModeClick?.invoke(loginInfo, model)
+ return@OnClickListener
+ }
+ if (model !is LoginInfo.Register)
+ return@OnClickListener
+ expandModel(model, view)
+ }
+
+ private fun expandModel(model: LoginInfo.Register, view: View?, notifyAdapter: Boolean = true) {
+ val position = items.indexOf(model)
+ if (position == -1)
+ return
+
+ if (model.state == STATE_CLOSED) {
+
+ val subItems = model.items
+
+ model.state = STATE_OPENED
+ items.addAll(position + 1, subItems)
+ if (notifyAdapter) notifyItemRangeInserted(position + 1, subItems.size)
+ }
+ else {
+ val start = position + 1
+ var end: Int = items.size
+ for (i in start until items.size) {
+ val model1 = items[i]
+ val level = (model1 as? ExpandableItemModel<*>)?.level ?: 3
+ if (level <= model.level) {
+ end = i
+ break
+ } else {
+ if (model1 is ExpandableItemModel<*> && model1.state == STATE_OPENED) {
+ model1.state = STATE_CLOSED
+ }
+ }
+ }
+
+ if (end != -1) {
+ items.subList(start, end).clear()
+ if (notifyAdapter) notifyItemRangeRemoved(start, end - start)
+ }
+
+ model.state = STATE_CLOSED
+ }
+ }
+
+ override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
+ val item = items[position]
+ if (holder !is BindableViewHolder<*, *>)
+ return
+
+ holder.itemView.setTag(R.string.tag_key_model, item)
+
+ when {
+ holder is RegisterViewHolder && item is LoginInfo.Register -> holder.onBind(activity, app, item, position, this)
+ holder is ModeViewHolder && item is LoginInfo.Mode -> holder.onBind(activity, app, item, position, this)
+ }
+
+ holder.itemView.setOnClickListener(onClickListener)
+ }
+
+ override fun getItemCount() = items.size
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserFragment.kt
index a522d427..37391924 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserFragment.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserFragment.kt
@@ -1,78 +1,90 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-16.
+ */
+
package pl.szczodrzynski.edziennik.ui.modules.login
import android.app.Activity
-import android.content.Intent
import android.os.Bundle
-import android.os.Process
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import android.view.animation.AnimationUtils
-import android.widget.CompoundButton
+import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
-import com.afollestad.materialdialogs.DialogAction
-import com.afollestad.materialdialogs.MaterialDialog
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import androidx.recyclerview.widget.LinearLayoutManager
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
import pl.szczodrzynski.edziennik.App
+import pl.szczodrzynski.edziennik.Bundle
import pl.szczodrzynski.edziennik.R
-import pl.szczodrzynski.edziennik.databinding.FragmentLoginChooserBinding
-import pl.szczodrzynski.edziennik.onChange
+import pl.szczodrzynski.edziennik.databinding.LoginChooserFragmentBinding
import pl.szczodrzynski.edziennik.onClick
-import pl.szczodrzynski.edziennik.ui.modules.feedback.FeedbackActivity
-import pl.szczodrzynski.edziennik.utils.Anim
-import kotlin.system.exitProcess
+import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration
+import kotlin.coroutines.CoroutineContext
-
-class LoginChooserFragment : Fragment() {
+class LoginChooserFragment : Fragment(), CoroutineScope {
companion object {
private const val TAG = "LoginChooserFragment"
- var fakeLogin = false
}
private lateinit var app: App
private lateinit var activity: LoginActivity
- private lateinit var b: FragmentLoginChooserBinding
+ private lateinit var b: LoginChooserFragmentBinding
private val nav by lazy { activity.nav }
+ private val job: Job = Job()
+ override val coroutineContext: CoroutineContext
+ get() = job + Dispatchers.Main
+
+ // local/private variables go here
+
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
activity = (getActivity() as LoginActivity?) ?: return null
context ?: return null
app = activity.application as App
- b = FragmentLoginChooserBinding.inflate(inflater)
+ b = LoginChooserFragmentBinding.inflate(inflater)
return b.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- b.topLogo.onClick {
- if (LoginActivity.thisOneIsTricky <= -1) {
- LoginActivity.thisOneIsTricky = 999
- }
- if (LoginActivity.thisOneIsTricky in 0..7) {
- LoginActivity.thisOneIsTricky++
- if (LoginActivity.thisOneIsTricky == 7) {
- b.topLogo.startAnimation(AnimationUtils.loadAnimation(activity, R.anim.shake));
- if (b.devMode.visibility != View.VISIBLE)
- Anim.expand(b.devMode, 500, null);
- LoginActivity.thisOneIsTricky = 3
- }
+ if (!isAdded) return
+
+ val adapter = LoginChooserAdapter(activity) { loginType, loginMode ->
+ if (loginMode.isPlatformSelection) {
+ nav.navigate(R.id.loginPlatformListFragment, Bundle(
+ "loginType" to loginType.loginType,
+ "loginMode" to loginMode.loginMode
+ ), activity.navOptions)
+ return@LoginChooserAdapter
}
+
+ nav.navigate(R.id.loginFormFragment, Bundle(
+ "loginType" to loginType.loginType,
+ "loginMode" to loginMode.loginMode
+ ), activity.navOptions)
+ }
+
+ LoginInfo.chooserList = LoginInfo.chooserList
+ ?: LoginInfo.list.toMutableList()
+
+ adapter.items = LoginInfo.chooserList!!
+ b.list.adapter = adapter
+ b.list.apply {
+ setHasFixedSize(true)
+ layoutManager = LinearLayoutManager(context)
+ addItemDecoration(SimpleDividerItemDecoration(context))
}
- b.loginMobidziennikLogo.onClick { nav.navigate(R.id.loginMobidziennikFragment, null, LoginActivity.navOptions) }
- b.loginLibrusLogo.onClick { nav.navigate(R.id.loginLibrusFragment, null, LoginActivity.navOptions) }
- b.loginVulcanLogo.onClick { nav.navigate(R.id.loginVulcanFragment, null, LoginActivity.navOptions) }
- b.loginIuczniowieLogo.onClick { nav.navigate(R.id.loginIuczniowieFragment, null, LoginActivity.navOptions) }
- b.loginLibrusJstLogo.onClick { nav.navigate(R.id.loginLibrusJstFragment, null, LoginActivity.navOptions) }
- b.loginEdudziennikLogo.onClick { nav.navigate(R.id.loginEdudziennikFragment, null, LoginActivity.navOptions) }
when {
activity.loginStores.isNotEmpty() -> {
// we are navigated here from LoginSummary
- b.cancelButton.visibility = View.VISIBLE
+ b.cancelButton.isVisible = true
b.cancelButton.onClick { nav.navigateUp() }
}
app.config.loginFinished -> {
// we are navigated here from AppDrawer
- b.cancelButton.visibility = View.VISIBLE
+ b.cancelButton.isVisible = true
b.cancelButton.onClick {
activity.setResult(Activity.RESULT_CANCELED)
activity.finish()
@@ -80,57 +92,8 @@ class LoginChooserFragment : Fragment() {
}
else -> {
// there are no profiles
- b.cancelButton.visibility = View.GONE
+ b.cancelButton.isVisible = false
}
}
-
- b.devMode.visibility = if (App.debugMode) View.VISIBLE else View.GONE
- b.devMode.isChecked = app.config.debugMode
- b.devMode.onChange { v, isChecked ->
- if (isChecked) {
- MaterialDialog.Builder(activity)
- .title(R.string.are_you_sure)
- .content(R.string.dev_mode_enable_warning)
- .positiveText(R.string.yes)
- .negativeText(R.string.no)
- .onPositive { _: MaterialDialog?, _: DialogAction? ->
- app.config.debugMode = true
- App.devMode = true
- MaterialAlertDialogBuilder(activity)
- .setTitle("Restart")
- .setMessage("Wymagany restart aplikacji")
- .setPositiveButton("OK") { _, _ ->
- Process.killProcess(Process.myPid())
- Runtime.getRuntime().exit(0)
- exitProcess(0)
- }
- .setCancelable(false)
- .show()
- }
- .onNegative { _: MaterialDialog?, _: DialogAction? ->
- app.config.debugMode = false
- App.devMode = false
- b.devMode.isChecked = app.config.debugMode
- b.devMode.jumpDrawablesToCurrentState()
- Anim.collapse(b.devMode, 1000, null)
- }
- .show()
- } else {
- app.config.debugMode = false
- App.devMode = false
- /*if (b.devModeLayout.getVisibility() === View.VISIBLE) {
- Anim.collapse(b.devModeTitle, 500, null)
- Anim.collapse(b.devModeLayout, 500, null)
- }*/
- }
- }
-
- b.fakeLogin.visibility = if (App.devMode) View.VISIBLE else View.GONE
- b.fakeLogin.isChecked = fakeLogin
- b.fakeLogin.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
- fakeLogin = isChecked
- }
-
- b.helpButton.onClick { startActivity(Intent(activity, FeedbackActivity::class.java)) }
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginEdudziennikFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginEdudziennikFragment.kt
deleted file mode 100644
index be1a83a7..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginEdudziennikFragment.kt
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) Kuba Szczodrzyński 2020-1-3.
- */
-
-package pl.szczodrzynski.edziennik.ui.modules.login
-
-import android.animation.ArgbEvaluator
-import android.animation.ObjectAnimator
-import android.graphics.Color
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import androidx.fragment.app.Fragment
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.Job
-import pl.szczodrzynski.edziennik.*
-import pl.szczodrzynski.edziennik.data.api.ERROR_LOGIN_EDUDZIENNIK_WEB_INVALID_LOGIN
-import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_EDUDZIENNIK
-import pl.szczodrzynski.edziennik.databinding.FragmentLoginEdudziennikBinding
-import java.util.*
-import kotlin.coroutines.CoroutineContext
-
-
-class LoginEdudziennikFragment : Fragment(), CoroutineScope {
- companion object {
- private const val TAG = "LoginEdudziennikFragment"
- }
-
- private lateinit var app: App
- private lateinit var activity: LoginActivity
- private lateinit var b: FragmentLoginEdudziennikBinding
- private val nav by lazy { activity.nav }
- private var hehe = 0
-
- private val job: Job = Job()
- override val coroutineContext: CoroutineContext
- get() = job + Dispatchers.Main
-
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- activity = (getActivity() as LoginActivity?) ?: return null
- context ?: return null
- app = activity.application as App
- b = FragmentLoginEdudziennikBinding.inflate(inflater)
- return b.root
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- activity.lastError?.let { error ->
- activity.lastError = null
- startCoroutineTimer(delayMillis = 100) {
- when (error.errorCode) {
- ERROR_LOGIN_EDUDZIENNIK_WEB_INVALID_LOGIN ->
- b.loginPasswordLayout.error = getString(R.string.login_error_incorrect_login_or_password)
- }
- }
- }
-
- b.topText.onClick {
- if (LoginActivity.thisOneIsTricky != -1)
- return@onClick
- hehe++
- if (hehe >= 5) {
- LoginActivity.thisOneIsTricky = 3
- val colorAnim = ObjectAnimator.ofInt(
- b.topText,
- "textColor",
- Color.BLACK,
- Color.RED,
- Color.BLACK,
- Color.RED,
- Color.BLACK,
- Color.RED,
- Color.BLACK
- )
- colorAnim.setEvaluator(ArgbEvaluator())
- colorAnim.duration = 1500L
- colorAnim.start()
- }
- }
-
- b.backButton.onClick { nav.navigateUp() }
-
- b.loginButton.onClick {
- var errors = false
-
- b.loginEmailLayout.error = null
- b.loginPasswordLayout.error = null
-
- val email = b.loginEmail.text?.toString()?.toLowerCase(Locale.ROOT) ?: ""
- val password = b.loginPassword.text?.toString() ?: ""
-
- if (email.isBlank()) {
- b.loginEmailLayout.error = getString(R.string.login_error_no_email)
- errors = true
- }
- if (password.isBlank()) {
- b.loginPasswordLayout.error = getString(R.string.login_error_no_password)
- errors = true
- }
- if (errors) return@onClick
-
- errors = false
-
- b.loginEmail.setText(email)
- if (!"([\\w.\\-_+]+)?\\w+@[\\w-_]+(\\.\\w+)+".toRegex().matches(email)) {
- b.loginEmailLayout.error = getString(R.string.login_error_incorrect_email)
- errors = true
- }
- if (errors) return@onClick
-
- val args = Bundle(
- "loginType" to LOGIN_TYPE_EDUDZIENNIK,
- "email" to email,
- "password" to password
- )
- nav.navigate(R.id.loginProgressFragment, args, LoginActivity.navOptions)
- }
- }
-}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFinishFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFinishFragment.kt
index 8f52b41a..7b2e66b8 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFinishFragment.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFinishFragment.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (c) Kuba Szczodrzyński 2020-1-4.
+ * Copyright (c) Kuba Szczodrzyński 2020-4-16.
*/
package pl.szczodrzynski.edziennik.ui.modules.login
@@ -14,7 +14,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import pl.szczodrzynski.edziennik.*
-import pl.szczodrzynski.edziennik.databinding.FragmentLoginFinishBinding
+import pl.szczodrzynski.edziennik.databinding.LoginFinishFragmentBinding
import kotlin.coroutines.CoroutineContext
class LoginFinishFragment : Fragment(), CoroutineScope {
@@ -24,27 +24,29 @@ class LoginFinishFragment : Fragment(), CoroutineScope {
private lateinit var app: App
private lateinit var activity: LoginActivity
- private lateinit var b: FragmentLoginFinishBinding
+ private lateinit var b: LoginFinishFragmentBinding
private val nav by lazy { activity.nav }
private val job: Job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
+ // local/private variables go here
+
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
activity = (getActivity() as LoginActivity?) ?: return null
context ?: return null
app = activity.application as App
- b = FragmentLoginFinishBinding.inflate(inflater)
+ b = LoginFinishFragmentBinding.inflate(inflater)
return b.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- val firstRun = !App.config.loginFinished
- App.config.loginFinished = true
+ val firstRun = !app.config.loginFinished
+ app.config.loginFinished = true
if (!firstRun) {
- b.loginFinishSubtitle.setText(R.string.login_finish_subtitle_not_first_run)
+ b.subTitle.setText(R.string.login_finish_subtitle_not_first_run)
}
b.finishButton.onClick {
@@ -74,4 +76,4 @@ class LoginFinishFragment : Fragment(), CoroutineScope {
}
}
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFormFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFormFragment.kt
new file mode 100644
index 00000000..d0676105
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFormFragment.kt
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-16.
+ */
+
+package pl.szczodrzynski.edziennik.ui.modules.login
+
+import android.annotation.SuppressLint
+import android.os.Bundle
+import android.text.InputType
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.core.view.isVisible
+import androidx.core.widget.addTextChangedListener
+import androidx.fragment.app.Fragment
+import com.google.android.material.textfield.TextInputLayout
+import com.google.gson.JsonParser
+import com.mikepenz.iconics.IconicsDrawable
+import com.mikepenz.iconics.utils.paddingDp
+import com.mikepenz.iconics.utils.sizeDp
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import pl.szczodrzynski.edziennik.*
+import pl.szczodrzynski.edziennik.databinding.LoginFormFragmentBinding
+import pl.szczodrzynski.edziennik.databinding.LoginFormItemBinding
+import pl.szczodrzynski.navlib.colorAttr
+import java.util.*
+import kotlin.coroutines.CoroutineContext
+
+class LoginFormFragment : Fragment(), CoroutineScope {
+ companion object {
+ private const val TAG = "LoginFormFragment"
+ }
+
+ private lateinit var app: App
+ private lateinit var activity: LoginActivity
+ private lateinit var b: LoginFormFragmentBinding
+ private val nav by lazy { activity.nav }
+
+ private val job: Job = Job()
+ override val coroutineContext: CoroutineContext
+ get() = job + Dispatchers.Main
+
+ // local/private variables go here
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ activity = (getActivity() as LoginActivity?) ?: return null
+ context ?: return null
+ app = activity.application as App
+ b = LoginFormFragmentBinding.inflate(inflater)
+ return b.root
+ }
+
+ @SuppressLint("ResourceType")
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ if (!isAdded) return
+ b.backButton.onClick { nav.navigateUp() }
+
+ b.errorLayout.isVisible = false
+ b.errorLayout.background?.setTintColor(R.attr.colorError.resolveAttr(activity))
+
+ val loginType = arguments?.getInt("loginType") ?: return
+ val register = LoginInfo.list.firstOrNull { it.loginType == loginType } ?: return
+ val loginMode = arguments?.getInt("loginMode") ?: return
+ val mode = register.loginModes.firstOrNull { it.loginMode == loginMode } ?: return
+
+ val platformName = arguments?.getString("platformName")
+ val platformGuideText = arguments?.getString("platformGuideText")
+ val platformDescription = arguments?.getString("platformDescription")
+ val platformFormFields = arguments?.getString("platformFormFields")?.split(";")
+ val platformApiData = arguments?.getString("platformApiData")?.let { JsonParser().parse(it)?.asJsonObject }
+
+ b.title.setText(R.string.login_form_title_format, app.getString(register.registerName))
+ b.subTitle.text = platformName ?: app.getString(mode.name)
+ b.text.text = platformGuideText ?: app.getString(mode.guideText)
+
+ val credentials = mutableMapOf()
+
+ for (credential in mode.credentials) {
+ if (platformFormFields?.contains(credential.keyName) == false)
+ continue
+
+ val b = LoginFormItemBinding.inflate(layoutInflater)
+ b.textLayout.hint = app.getString(credential.name)
+ if (credential.hideText) {
+ b.textEdit.inputType = InputType.TYPE_TEXT_VARIATION_PASSWORD
+ b.textLayout.endIconMode = TextInputLayout.END_ICON_PASSWORD_TOGGLE
+ }
+ b.textEdit.addTextChangedListener {
+ b.textLayout.error = null
+ }
+
+ b.textEdit.id = credential.name
+
+ b.textEdit.setText(arguments?.getString(credential.keyName) ?: "")
+ b.textLayout.startIconDrawable = IconicsDrawable(activity)
+ .icon(credential.icon)
+ .sizeDp(24)
+ .paddingDp(2)
+ .colorAttr(activity, R.attr.colorOnBackground)
+
+ this.b.formContainer.addView(b.root)
+ credentials[credential] = b
+ }
+
+ activity.lastError?.let { error ->
+ activity.lastError = null
+ startCoroutineTimer(delayMillis = 200L) {
+ for (credential in credentials) {
+ credential.key.errorCodes[error.errorCode]?.let {
+ credential.value.textLayout.error = app.getString(it)
+ return@startCoroutineTimer
+ }
+ }
+ mode.errorCodes[error.errorCode]?.let {
+ b.errorText.text = app.getString(it)
+ b.errorLayout.isVisible = true
+ return@startCoroutineTimer
+ }
+ }
+ }
+
+ b.loginButton.onClick {
+ val payload = Bundle(
+ "loginType" to loginType,
+ "loginMode" to loginMode
+ )
+
+ if (App.devMode && b.fakeLogin.isChecked) {
+ payload.putBoolean("fakeLogin", true)
+ }
+
+ platformApiData?.entrySet()?.forEach {
+ payload.putString(it.key, it.value.asString)
+ }
+
+ var hasErrors = false
+ credentials.forEach { (credential, b) ->
+ var text = b.textEdit.text?.toString() ?: return@forEach
+ if (!credential.hideText)
+ text = text.trim()
+
+ if (credential.caseMode == LoginInfo.Credential.CaseMode.UPPER_CASE)
+ text = text.toUpperCase(Locale.getDefault())
+ if (credential.caseMode == LoginInfo.Credential.CaseMode.LOWER_CASE)
+ text = text.toLowerCase(Locale.getDefault())
+
+ credential.stripTextRegex?.let {
+ text = text.replace(it.toRegex(), "")
+ }
+
+ b.textEdit.setText(text)
+
+ if (credential.isRequired && text.isBlank()) {
+ b.textLayout.error = app.getString(credential.emptyText)
+ hasErrors = true
+ return@forEach
+ }
+
+ if (!text.matches(credential.validationRegex.toRegex())) {
+ b.textLayout.error = app.getString(credential.invalidText)
+ hasErrors = true
+ return@forEach
+ }
+
+ payload.putString(credential.keyName, text)
+ arguments?.putString(credential.keyName, text)
+ }
+
+ if (hasErrors)
+ return@onClick
+
+ nav.navigate(R.id.loginProgressFragment, payload, activity.navOptions)
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginInfo.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginInfo.kt
new file mode 100644
index 00000000..29624d40
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginInfo.kt
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-16.
+ */
+
+package pl.szczodrzynski.edziennik.ui.modules.login
+
+import androidx.annotation.DrawableRes
+import androidx.annotation.StringRes
+import com.google.gson.JsonObject
+import com.mikepenz.iconics.typeface.IIcon
+import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
+import pl.szczodrzynski.edziennik.R
+import pl.szczodrzynski.edziennik.data.api.*
+import pl.szczodrzynski.edziennik.ui.modules.grades.models.ExpandableItemModel
+
+object LoginInfo {
+
+ private fun getEmailCredential(keyName: String) = Credential(
+ keyName = keyName,
+ name = R.string.login_hint_email,
+ icon = CommunityMaterial.Icon.cmd_at,
+ emptyText = R.string.login_error_no_email,
+ invalidText = R.string.login_error_incorrect_email,
+ errorCodes = mapOf(),
+ isRequired = true,
+ validationRegex = "([\\w.\\-_+]+)?\\w+@[\\w-_]+(\\.\\w+)+",
+ caseMode = Credential.CaseMode.LOWER_CASE
+ )
+ private fun getPasswordCredential(keyName: String) = Credential(
+ keyName = keyName,
+ name = R.string.login_hint_password,
+ icon = CommunityMaterial.Icon2.cmd_lock_outline,
+ emptyText = R.string.login_error_no_password,
+ invalidText = R.string.login_error_incorrect_login_or_password,
+ errorCodes = mapOf(),
+ isRequired = true,
+ validationRegex = ".*",
+ hideText = true
+ )
+
+ val list by lazy { listOf(
+ Register(
+ loginType = LOGIN_TYPE_LIBRUS,
+ internalName = "librus",
+ registerName = R.string.login_register_librus,
+ registerLogo = R.drawable.login_logo_librus,
+ loginModes = listOf(
+ Mode(
+ loginMode = LOGIN_MODE_LIBRUS_EMAIL,
+ name = R.string.login_mode_librus_email,
+ icon = R.drawable.login_mode_librus_email,
+ hintText = R.string.login_mode_librus_email_hint,
+ guideText = R.string.login_mode_librus_email_guide,
+ isRecommended = true,
+ credentials = listOf(
+ getEmailCredential("email"),
+ getPasswordCredential("password")
+ ),
+ errorCodes = mapOf(
+ ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED to R.string.login_error_account_not_activated,
+ ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN to R.string.login_error_incorrect_login_or_password,
+ ERROR_CAPTCHA_LIBRUS_PORTAL to R.string.error_3001_reason
+ )
+ ),
+ Mode(
+ loginMode = LOGIN_MODE_LIBRUS_SYNERGIA,
+ name = R.string.login_mode_librus_synergia,
+ icon = R.drawable.login_mode_librus_synergia,
+ hintText = R.string.login_mode_librus_synergia_hint,
+ guideText = R.string.login_mode_librus_synergia_guide,
+ credentials = listOf(
+ Credential(
+ keyName = "accountLogin",
+ name = R.string.login_hint_login,
+ icon = CommunityMaterial.Icon.cmd_account_outline,
+ emptyText = R.string.login_error_no_login,
+ invalidText = R.string.login_error_incorrect_login,
+ errorCodes = mapOf(),
+ isRequired = true,
+ validationRegex = "[A-z0-9._\\-+]+",
+ caseMode = Credential.CaseMode.LOWER_CASE
+ ),
+ getPasswordCredential("accountPassword")
+ ),
+ errorCodes = mapOf(
+ ERROR_LOGIN_LIBRUS_API_INVALID_LOGIN to R.string.login_error_incorrect_login_or_password,
+ ERROR_LOGIN_LIBRUS_API_INVALID_REQUEST to R.string.login_error_incorrect_login_or_password
+ )
+ ),
+ Mode(
+ loginMode = LOGIN_MODE_LIBRUS_JST,
+ name = R.string.login_mode_librus_jst,
+ icon = R.drawable.login_mode_librus_jst,
+ hintText = R.string.login_mode_librus_jst_hint,
+ guideText = R.string.login_mode_librus_jst_guide,
+ credentials = listOf(
+ Credential(
+ keyName = "accountCode",
+ name = R.string.login_hint_token,
+ icon = CommunityMaterial.Icon.cmd_code_braces,
+ emptyText = R.string.login_error_no_token,
+ invalidText = R.string.login_error_incorrect_token,
+ errorCodes = mapOf(),
+ isRequired = true,
+ validationRegex = "[A-Z0-9_]+",
+ caseMode = Credential.CaseMode.UPPER_CASE
+ ),
+ Credential(
+ keyName = "accountPin",
+ name = R.string.login_hint_pin,
+ icon = CommunityMaterial.Icon2.cmd_lock,
+ emptyText = R.string.login_error_no_pin,
+ invalidText = R.string.login_error_incorrect_pin,
+ errorCodes = mapOf(),
+ isRequired = true,
+ validationRegex = "[a-z0-9_]+",
+ caseMode = Credential.CaseMode.LOWER_CASE
+ )
+ ),
+ errorCodes = mapOf(
+ ERROR_LOGIN_LIBRUS_API_INVALID_LOGIN to R.string.login_error_incorrect_code_or_pin,
+ ERROR_LOGIN_LIBRUS_API_INVALID_REQUEST to R.string.login_error_incorrect_code_or_pin
+ )
+ )
+ )
+ ),
+ Register(
+ loginType = LOGIN_TYPE_VULCAN,
+ internalName = "vulcan",
+ registerName = R.string.login_type_vulcan,
+ registerLogo = R.drawable.login_logo_vulcan,
+ loginModes = listOf(
+ Mode(
+ loginMode = LOGIN_MODE_VULCAN_API,
+ name = R.string.login_mode_vulcan_api,
+ icon = R.drawable.login_mode_vulcan_api,
+ hintText = R.string.login_mode_vulcan_api_hint,
+ guideText = R.string.login_mode_vulcan_api_guide,
+ isRecommended = true,
+ credentials = listOf(
+ Credential(
+ keyName = "deviceToken",
+ name = R.string.login_hint_token,
+ icon = CommunityMaterial.Icon.cmd_code_braces,
+ emptyText = R.string.login_error_no_token,
+ invalidText = R.string.login_error_incorrect_token,
+ errorCodes = mapOf(
+ ERROR_LOGIN_VULCAN_INVALID_TOKEN to R.string.login_error_incorrect_token
+ ),
+ isRequired = true,
+ validationRegex = "[A-Z0-9]{5,12}",
+ caseMode = Credential.CaseMode.UPPER_CASE
+ ),
+ Credential(
+ keyName = "deviceSymbol",
+ name = R.string.login_hint_symbol,
+ icon = CommunityMaterial.Icon2.cmd_school,
+ emptyText = R.string.login_error_no_symbol,
+ invalidText = R.string.login_error_incorrect_symbol,
+ errorCodes = mapOf(
+ ERROR_LOGIN_VULCAN_INVALID_SYMBOL to R.string.login_error_incorrect_symbol
+ ),
+ isRequired = true,
+ validationRegex = "[a-z0-9_-]+",
+ caseMode = Credential.CaseMode.LOWER_CASE
+ ),
+ Credential(
+ keyName = "devicePin",
+ name = R.string.login_hint_pin,
+ icon = CommunityMaterial.Icon2.cmd_lock,
+ emptyText = R.string.login_error_no_pin,
+ invalidText = R.string.login_error_incorrect_pin,
+ errorCodes = mapOf(
+ ERROR_LOGIN_VULCAN_INVALID_PIN to R.string.login_error_incorrect_pin
+ ),
+ isRequired = true,
+ validationRegex = "[0-9]+",
+ caseMode = Credential.CaseMode.LOWER_CASE
+ )
+ ),
+ errorCodes = mapOf(
+ ERROR_LOGIN_VULCAN_EXPIRED_TOKEN to R.string.login_error_expired_token
+ )
+ ),
+ Mode(
+ loginMode = LOGIN_MODE_VULCAN_WEB,
+ name = R.string.login_mode_vulcan_web,
+ icon = R.drawable.login_mode_vulcan_web,
+ hintText = R.string.login_mode_vulcan_web_hint,
+ guideText = R.string.login_mode_vulcan_web_guide,
+ isTesting = true,
+ isPlatformSelection = true,
+ credentials = listOf(
+ getEmailCredential("webEmail"),
+ Credential(
+ keyName = "webUsername",
+ name = R.string.login_hint_username,
+ icon = CommunityMaterial.Icon.cmd_account_outline,
+ emptyText = R.string.login_error_no_username,
+ invalidText = R.string.login_error_incorrect_username,
+ errorCodes = mapOf(),
+ isRequired = true,
+ validationRegex = "[A-Z]{7}[0-9]+",
+ caseMode = Credential.CaseMode.UPPER_CASE
+ ),
+ Credential(
+ keyName = "webPassword",
+ name = R.string.login_hint_password,
+ icon = CommunityMaterial.Icon2.cmd_lock_outline,
+ emptyText = R.string.login_error_no_password,
+ invalidText = R.string.login_error_incorrect_login_or_password,
+ errorCodes = mapOf(),
+ isRequired = true,
+ validationRegex = ".*",
+ hideText = true
+ )
+ ),
+ errorCodes = mapOf()
+ )
+ )
+ ),
+ Register(
+ loginType = LOGIN_TYPE_MOBIDZIENNIK,
+ internalName = "mobidziennik",
+ registerName = R.string.login_type_mobidziennik,
+ registerLogo = R.drawable.login_logo_mobidziennik,
+ loginModes = listOf(
+ Mode(
+ loginMode = LOGIN_MODE_MOBIDZIENNIK_WEB,
+ name = R.string.login_mode_mobidziennik_web,
+ icon = R.drawable.login_mode_mobidziennik_web,
+ hintText = R.string.login_mode_mobidziennik_web_hint,
+ guideText = R.string.login_mode_mobidziennik_web_guide,
+ credentials = listOf(
+ Credential(
+ keyName = "username",
+ name = R.string.login_hint_login_email,
+ icon = CommunityMaterial.Icon.cmd_account_outline,
+ emptyText = R.string.login_error_no_login,
+ invalidText = R.string.login_error_incorrect_login,
+ errorCodes = mapOf(),
+ isRequired = true,
+ validationRegex = "^[a-z0-9_\\-@+.]+$",
+ caseMode = Credential.CaseMode.LOWER_CASE
+ ),
+ Credential(
+ keyName = "password",
+ name = R.string.login_hint_password,
+ icon = CommunityMaterial.Icon2.cmd_lock_outline,
+ emptyText = R.string.login_error_no_password,
+ invalidText = R.string.login_error_incorrect_login_or_password,
+ errorCodes = mapOf(
+ ERROR_LOGIN_MOBIDZIENNIK_WEB_OLD_PASSWORD to R.string.login_error_old_password
+ ),
+ isRequired = true,
+ validationRegex = ".*",
+ hideText = true
+ ),
+ Credential(
+ keyName = "serverName",
+ name = R.string.login_hint_address,
+ icon = CommunityMaterial.Icon2.cmd_web,
+ emptyText = R.string.login_error_no_address,
+ invalidText = R.string.login_error_incorrect_address,
+ errorCodes = mapOf(
+ ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_ADDRESS to R.string.login_error_incorrect_address
+ ),
+ isRequired = true,
+ validationRegex = "^[a-z0-9_\\-]+\$",
+ caseMode = Credential.CaseMode.LOWER_CASE
+ )
+ ),
+ errorCodes = mapOf(
+ ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_LOGIN to R.string.login_error_incorrect_login_or_password,
+ ERROR_LOGIN_MOBIDZIENNIK_WEB_ARCHIVED to R.string.sync_error_archived
+ )
+ )
+ )
+ )
+ /*Register(
+ loginType = LOGIN_TYPE_IDZIENNIK,
+
+ )*/
+ ) }
+
+ data class Register(
+ val loginType: Int,
+ val internalName: String,
+ val registerName: Int,
+ @DrawableRes
+ val registerLogo: Int,
+
+ val loginModes: List
+ ) : ExpandableItemModel(loginModes.toMutableList()) {
+ override var level = 1
+ }
+
+ data class Mode(
+ val loginMode: Int,
+
+ @StringRes
+ val name: Int,
+ @DrawableRes
+ val icon: Int,
+ @StringRes
+ val hintText: Int? = null,
+ @StringRes
+ val guideText: Int,
+
+ val isRecommended: Boolean = false,
+ val isTesting: Boolean = false,
+ val isPlatformSelection: Boolean = false,
+
+ val credentials: List,
+ val errorCodes: Map
+ )
+
+ data class Platform(
+ val id: Int,
+ val loginType: Int,
+ val loginMode: Int,
+ val name: String,
+ val description: String?,
+ val guideText: String?,
+ val icon: String,
+ val screenshot: String?,
+ val formFields: List,
+ val apiData: JsonObject
+ )
+
+ data class Credential(
+ val keyName: String,
+
+ @StringRes
+ val name: Int,
+ val icon: IIcon,
+ @StringRes
+ val placeholder: Int? = null,
+ @StringRes
+ val emptyText: Int,
+ @StringRes
+ val invalidText: Int,
+ val errorCodes: Map,
+ @StringRes
+ val hintText: Int? = null,
+
+ val isRequired: Boolean = true,
+ val validationRegex: String,
+ val caseMode: CaseMode = CaseMode.UNCHANGED,
+ val hideText: Boolean = false,
+ val stripTextRegex: String? = null
+ ) {
+ enum class CaseMode { UNCHANGED, UPPER_CASE, LOWER_CASE }
+ }
+
+ var chooserList: MutableList? = null
+ var platformList: MutableMap> = mutableMapOf()
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginIuczniowieFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginIuczniowieFragment.kt
deleted file mode 100644
index 379eee1a..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginIuczniowieFragment.kt
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) Kuba Szczodrzyński 2020-1-3.
- */
-
-package pl.szczodrzynski.edziennik.ui.modules.login
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import androidx.fragment.app.Fragment
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.Job
-import pl.szczodrzynski.edziennik.*
-import pl.szczodrzynski.edziennik.data.api.ERROR_LOGIN_IDZIENNIK_WEB_INVALID_SCHOOL_NAME
-import pl.szczodrzynski.edziennik.data.api.ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED
-import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_IDZIENNIK
-import pl.szczodrzynski.edziennik.databinding.FragmentLoginIuczniowieBinding
-import java.util.*
-import kotlin.coroutines.CoroutineContext
-
-class LoginIuczniowieFragment : Fragment(), CoroutineScope {
- companion object {
- private const val TAG = "LoginIuczniowieFragment"
- }
-
- private lateinit var app: App
- private lateinit var activity: LoginActivity
- private lateinit var b: FragmentLoginIuczniowieBinding
- private val nav by lazy { activity.nav }
-
- private val job: Job = Job()
- override val coroutineContext: CoroutineContext
- get() = job + Dispatchers.Main
-
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- activity = (getActivity() as LoginActivity?) ?: return null
- context ?: return null
- app = activity.application as App
- b = FragmentLoginIuczniowieBinding.inflate(inflater)
- return b.root
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- activity.lastError?.let { error ->
- activity.lastError = null
- startCoroutineTimer(delayMillis = 100) {
- when (error.errorCode) {
- ERROR_LOGIN_IDZIENNIK_WEB_INVALID_SCHOOL_NAME ->
- b.loginSchoolNameLayout.error = getString(R.string.login_error_incorrect_school_name)
- ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED ->
- b.loginPasswordLayout.error = getString(R.string.login_error_incorrect_login_or_password)
- }
- }
- }
-
- b.helpButton.onClick { nav.navigate(R.id.loginIuczniowieHelpFragment, null, LoginActivity.navOptions) }
- b.backButton.onClick { nav.navigateUp() }
-
- b.loginButton.onClick {
- var errors = false
-
- b.loginSchoolNameLayout.error = null
- b.loginUsernameLayout.error = null
- b.loginPasswordLayout.error = null
-
- val schoolName = b.loginSchoolName.text?.toString()?.toLowerCase(Locale.ROOT) ?: ""
- val username = b.loginUsername.text?.toString()?.toLowerCase(Locale.ROOT) ?: ""
- val password = b.loginPassword.text?.toString() ?: ""
-
- if (schoolName.isBlank()) {
- b.loginSchoolNameLayout.error = getString(R.string.login_error_no_school_name)
- errors = true
- }
- if (username.isBlank()) {
- b.loginUsernameLayout.error = getString(R.string.login_error_no_username)
- errors = true
- }
- if (password.isBlank()) {
- b.loginPasswordLayout.error = getString(R.string.login_error_no_password)
- errors = true
- }
- if (errors) return@onClick
-
- errors = false
-
- b.loginSchoolName.setText(schoolName)
- b.loginUsername.setText(username)
- if (!"[a-z0-9_\\-]+".toRegex().matches(schoolName)) {
- b.loginSchoolNameLayout.error = getString(R.string.login_error_incorrect_school_name)
- errors = true
- }
- if (!"[a-z0-9_\\-]+".toRegex().matches(username)) {
- b.loginUsernameLayout.error = getString(R.string.login_error_incorrect_username)
- errors = true
- }
- if (errors) return@onClick
-
- val args = Bundle(
- "loginType" to LOGIN_TYPE_IDZIENNIK,
- "schoolName" to schoolName,
- "username" to username,
- "password" to password
- )
- nav.navigate(R.id.loginProgressFragment, args, LoginActivity.navOptions)
- }
- }
-}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginIuczniowieHelpFragment.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginIuczniowieHelpFragment.java
deleted file mode 100644
index 7b5c9d96..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginIuczniowieHelpFragment.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package pl.szczodrzynski.edziennik.ui.modules.login;
-
-import androidx.databinding.DataBindingUtil;
-import android.os.Bundle;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.navigation.NavController;
-import androidx.navigation.Navigation;
-import pl.szczodrzynski.edziennik.App;
-import pl.szczodrzynski.edziennik.R;
-import pl.szczodrzynski.edziennik.databinding.FragmentLoginIuczniowieHelpBinding;
-
-public class LoginIuczniowieHelpFragment extends Fragment {
-
- private App app;
- private NavController nav;
- private FragmentLoginIuczniowieHelpBinding b;
- private static final String TAG = "LoginIuczniowieHelp";
-
- public LoginIuczniowieHelpFragment() { }
-
- @Override
- public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- // Inflate the layout for this fragment
- if (getActivity() != null) {
- app = (App) getActivity().getApplicationContext();
- nav = Navigation.findNavController(getActivity(), R.id.nav_host_fragment);
- }
- else {
- return null;
- }
- b = DataBindingUtil.inflate(inflater, R.layout.fragment_login_iuczniowie_help, container, false);
- return b.getRoot();
- }
-
- @Override
- public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
- assert getContext() != null;
- assert getActivity() != null;
-
- b.backButton.setOnClickListener((v) -> nav.navigateUp());
- }
-}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginLibrusCaptchaActivity.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginLibrusCaptchaActivity.kt
deleted file mode 100644
index 3cbf29ed..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginLibrusCaptchaActivity.kt
+++ /dev/null
@@ -1,116 +0,0 @@
-package pl.szczodrzynski.edziennik.ui.modules.login
-
-import android.annotation.SuppressLint
-import android.graphics.Color
-import android.os.Build
-import android.os.Bundle
-import android.util.Base64
-import android.webkit.JavascriptInterface
-import android.webkit.WebView
-import androidx.appcompat.app.AlertDialog
-import androidx.appcompat.app.AppCompatActivity
-import com.afollestad.materialdialogs.MaterialDialog
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import pl.szczodrzynski.edziennik.R
-import pl.szczodrzynski.edziennik.data.api.LIBRUS_USER_AGENT
-import pl.szczodrzynski.edziennik.utils.Themes
-import pl.szczodrzynski.edziennik.utils.Utils.hexFromColorInt
-import java.nio.charset.Charset
-
-class LoginLibrusCaptchaActivity : AppCompatActivity() {
- companion object {
- private const val TAG = "LoginLibrusCaptchaActivity"
- }
-
- private lateinit var webView: WebView
- private lateinit var dialog: AlertDialog
- private lateinit var jsInterface: CaptchaCallbackInterface
-
- @SuppressLint("AddJavascriptInterface", "SetJavaScriptEnabled")
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setTheme(Themes.appThemeNoDisplay)
- setFinishOnTouchOutside(false)
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- WebView.setWebContentsDebuggingEnabled(true)
- }
-
- val base64Content = """
-PCFET0NUWVBFIGh0bWw+PGh0bWw+PGhlYWQ+PHNjcmlwdCBzcmM9Imh0dHBzOi8vd3d3Lmdvb2ds
-ZS5jb20vcmVjYXB0Y2hhL2FwaS5qcz9vbmxvYWQ9cmVhZHkmcmVuZGVyPWV4cGxpY2l0Ij48L3Nj
-cmlwdD48L2hlYWQ+PGJvZHk+PGJyPjxjZW50ZXIgaWQ9ImdyIj48L2NlbnRlcj48YnI+PHNjcmlw
-dD5mdW5jdGlvbiByZWFkeSgpe2dyZWNhcHRjaGEucmVuZGVyKCdncicse3NpdGVrZXk6JzZMZjQ4
-bW9VQUFBQUFCOUNsaGR2SHI0NmdSV1ItQ04zMUNYUVBHMlUnLHRoZW1lOidUSEVNRScsY2FsbGJh
-Y2s6ZnVuY3Rpb24oZSl7d2luZG93LmlmLmNhbGxiYWNrKGUpO30sImV4cGlyZWQtY2FsbGJhY2si
-OmZ1bmN0aW9uKCl7d2luZG93LmlmLmV4cGlyZWRDYWxsYmFjayhlKTt9LCJlcnJvci1jYWxsYmFj
-ayI6ZnVuY3Rpb24oKXt3aW5kb3cuaWYuZXJyb3JDYWxsYmFjayhlKTt9fSk7fTwvc2NyaXB0Pjwv
-Ym9keT48L2h0bWw+"""
-
- val backgroundColor = if (Themes.isDark) 0x424242 else 0xffffff
- val backgroundColorString = hexFromColorInt(backgroundColor)
-
- val htmlContent = Base64.decode(base64Content, Base64.DEFAULT)
- .toString(Charset.defaultCharset())
- .replace("COLOR", backgroundColorString, true)
- .replace("THEME", if (Themes.isDark) "dark" else "light")
-
- jsInterface = object : CaptchaCallbackInterface {
- @JavascriptInterface
- override fun callback(recaptchaResponse: String) {
- MaterialDialog.Builder(this@LoginLibrusCaptchaActivity)
- .title("Captcha checked")
- .content("Response: $recaptchaResponse")
- .positiveText("OK")
- .show()
- }
-
- @JavascriptInterface
- override fun expiredCallback() {
- MaterialDialog.Builder(this@LoginLibrusCaptchaActivity)
- .title("Captcha expired")
- .content("Captcha expired")
- .positiveText("OK")
- .show()
- }
-
- @JavascriptInterface
- override fun errorCallback() {
- MaterialDialog.Builder(this@LoginLibrusCaptchaActivity)
- .title("Captcha error")
- .content("Captcha error")
- .positiveText("OK")
- .show()
- }
- }
-
- webView = WebView(this).apply {
- //setBackgroundColor((backgroundColor.toLong() or 0xff000000).toInt())
- setBackgroundColor(Color.TRANSPARENT)
- settings.javaScriptEnabled = true
- settings.userAgentString = LIBRUS_USER_AGENT
- addJavascriptInterface(jsInterface, "if")
- loadDataWithBaseURL("https://portal.librus.pl/rodzina/login/", htmlContent, "text/html", "UTF-8", null)
- setLayerType(WebView.LAYER_TYPE_SOFTWARE, null)
- }
-
- dialog = MaterialAlertDialogBuilder(this)
- .setTitle(R.string.login_librus_captcha_title)
- .setView(webView)
- .setNegativeButton(R.string.cancel) { dialog, _ ->
- dialog.dismiss()
- finish()
- }
- .setCancelable(false)
- .show()
- }
-
- interface CaptchaCallbackInterface {
- @JavascriptInterface
- fun callback(recaptchaResponse: String)
- @JavascriptInterface
- fun expiredCallback()
- @JavascriptInterface
- fun errorCallback()
- }
-}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginLibrusFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginLibrusFragment.kt
deleted file mode 100644
index 11c2bdd2..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginLibrusFragment.kt
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) Kuba Szczodrzyński 2020-1-3.
- */
-
-package pl.szczodrzynski.edziennik.ui.modules.login
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import androidx.fragment.app.Fragment
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.Job
-import pl.szczodrzynski.edziennik.*
-import pl.szczodrzynski.edziennik.data.api.ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN
-import pl.szczodrzynski.edziennik.data.api.ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED
-import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_LIBRUS
-import pl.szczodrzynski.edziennik.databinding.FragmentLoginLibrusBinding
-import java.util.*
-import kotlin.coroutines.CoroutineContext
-
-class LoginLibrusFragment : Fragment(), CoroutineScope {
- companion object {
- private const val TAG = "LoginLibrusFragment"
- }
-
- private lateinit var app: App
- private lateinit var activity: LoginActivity
- private lateinit var b: FragmentLoginLibrusBinding
- private val nav by lazy { activity.nav }
-
- private val job: Job = Job()
- override val coroutineContext: CoroutineContext
- get() = job + Dispatchers.Main
-
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- activity = (getActivity() as LoginActivity?) ?: return null
- context ?: return null
- app = activity.application as App
- b = FragmentLoginLibrusBinding.inflate(inflater)
- return b.root
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- activity.lastError?.let { error ->
- activity.lastError = null
- startCoroutineTimer(delayMillis = 100) {
- when (error.errorCode) {
- ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN ->
- b.loginPasswordLayout.error = getString(R.string.login_error_incorrect_login_or_password)
- ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED ->
- b.loginEmailLayout.error = getString(R.string.login_error_account_not_activated)
- }
- }
- }
-
- b.helpButton.onClick { nav.navigate(R.id.loginLibrusHelpFragment, null, LoginActivity.navOptions) }
- b.backButton.onClick { nav.navigateUp() }
-
- b.loginButton.onClick {
- var errors = false
-
- b.loginEmailLayout.error = null
- b.loginPasswordLayout.error = null
-
- val email = b.loginEmail.text?.toString()?.toLowerCase(Locale.ROOT) ?: ""
- val password = b.loginPassword.text?.toString() ?: ""
-
- if (email.isBlank()) {
- b.loginEmailLayout.error = getString(R.string.login_error_no_email)
- errors = true
- }
- if (password.isBlank()) {
- b.loginPasswordLayout.error = getString(R.string.login_error_no_password)
- errors = true
- }
- if (errors) return@onClick
-
- errors = false
-
- b.loginEmail.setText(email)
- if (!"([\\w.\\-_+]+)?\\w+@[\\w-_]+(\\.\\w+)+".toRegex().matches(email)) {
- b.loginEmailLayout.error = getString(R.string.login_error_incorrect_email)
- errors = true
- }
- if (errors) return@onClick
-
- val args = Bundle(
- "loginType" to LOGIN_TYPE_LIBRUS,
- "email" to email,
- "password" to password
- )
- nav.navigate(R.id.loginProgressFragment, args, LoginActivity.navOptions)
- }
- }
-}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginLibrusHelpFragment.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginLibrusHelpFragment.java
deleted file mode 100644
index 6984498a..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginLibrusHelpFragment.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package pl.szczodrzynski.edziennik.ui.modules.login;
-
-import androidx.databinding.DataBindingUtil;
-import android.os.Bundle;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.navigation.NavController;
-import androidx.navigation.Navigation;
-import pl.szczodrzynski.edziennik.App;
-import pl.szczodrzynski.edziennik.R;
-import pl.szczodrzynski.edziennik.databinding.FragmentLoginLibrusHelpBinding;
-
-public class LoginLibrusHelpFragment extends Fragment {
-
- private App app;
- private NavController nav;
- private FragmentLoginLibrusHelpBinding b;
- private static final String TAG = "LoginLibrusHelp";
-
- public LoginLibrusHelpFragment() { }
-
- @Override
- public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- // Inflate the layout for this fragment
- if (getActivity() != null) {
- app = (App) getActivity().getApplicationContext();
- nav = Navigation.findNavController(getActivity(), R.id.nav_host_fragment);
- }
- else {
- return null;
- }
- b = DataBindingUtil.inflate(inflater, R.layout.fragment_login_librus_help, container, false);
- return b.getRoot();
- }
-
- @Override
- public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
- assert getContext() != null;
- assert getActivity() != null;
-
- b.backButton.setOnClickListener((v) -> nav.navigateUp());
- }
-}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginLibrusJstFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginLibrusJstFragment.kt
deleted file mode 100644
index d4e3d445..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginLibrusJstFragment.kt
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (c) Kuba Szczodrzyński 2020-1-3.
- */
-
-package pl.szczodrzynski.edziennik.ui.modules.login
-
-import android.graphics.Color
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.view.WindowManager
-import androidx.fragment.app.Fragment
-import com.mikepenz.iconics.IconicsDrawable
-import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
-import com.mikepenz.iconics.utils.colorInt
-import com.mikepenz.iconics.utils.sizeDp
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.Job
-import pl.szczodrzynski.edziennik.*
-import pl.szczodrzynski.edziennik.data.api.ERROR_LOGIN_LIBRUS_API_INVALID_LOGIN
-import pl.szczodrzynski.edziennik.data.api.ERROR_LOGIN_LIBRUS_API_INVALID_REQUEST
-import pl.szczodrzynski.edziennik.data.api.LOGIN_MODE_LIBRUS_JST
-import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_LIBRUS
-import pl.szczodrzynski.edziennik.databinding.FragmentLoginLibrusJstBinding
-import pl.szczodrzynski.edziennik.ui.dialogs.QrScannerDialog
-import java.util.*
-import kotlin.coroutines.CoroutineContext
-
-class LoginLibrusJstFragment : Fragment(), CoroutineScope {
- companion object {
- private const val TAG = "LoginLibrusJstFragment"
- }
-
- private lateinit var app: App
- private lateinit var activity: LoginActivity
- private lateinit var b: FragmentLoginLibrusJstBinding
- private val nav by lazy { activity.nav }
-
- private val job: Job = Job()
- override val coroutineContext: CoroutineContext
- get() = job + Dispatchers.Main
-
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- activity = (getActivity() as LoginActivity?) ?: return null
- context ?: return null
- app = activity.application as App
- b = FragmentLoginLibrusJstBinding.inflate(inflater)
- return b.root
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- activity.lastError?.let { error ->
- activity.lastError = null
- startCoroutineTimer(delayMillis = 100) {
- when (error.errorCode) {
- ERROR_LOGIN_LIBRUS_API_INVALID_LOGIN,
- ERROR_LOGIN_LIBRUS_API_INVALID_REQUEST ->
- b.loginCodeLayout.error = getString(R.string.login_error_incorrect_code_or_pin)
- }
- }
- }
-
- b.loginQrScan.setImageDrawable(IconicsDrawable(activity)
- .icon(CommunityMaterial.Icon2.cmd_qrcode_scan)
- .colorInt(Color.BLACK)
- .sizeDp(72))
- b.loginQrScan.onClick {
- QrScannerDialog(activity, { code ->
- b.loginCode.setText(code)
- if (b.loginPin.requestFocus()) {
- activity.window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
- }
- })
- }
-
- b.helpButton.onClick { nav.navigate(R.id.loginLibrusHelpFragment, null, LoginActivity.navOptions) }
- b.backButton.onClick { nav.navigateUp() }
-
- b.loginButton.onClick {
- var errors = false
-
- b.loginCodeLayout.error = null
- b.loginPinLayout.error = null
-
- val code = b.loginCode.text?.toString()?.toUpperCase(Locale.ROOT) ?: ""
- val pin = b.loginPin.text?.toString() ?: ""
-
- if (code.isBlank()) {
- b.loginCodeLayout.error = getString(R.string.login_error_no_code)
- errors = true
- }
- if (pin.isBlank()) {
- b.loginPinLayout.error = getString(R.string.login_error_no_pin)
- errors = true
- }
- if (errors) return@onClick
-
- errors = false
-
- b.loginCode.setText(code)
- if (!"[A-Z0-9_]+".toRegex().matches(code)) {
- b.loginCodeLayout.error = getString(R.string.login_error_incorrect_code)
- errors = true
- }
- if (!"[a-z0-9_]+".toRegex().matches(pin)) {
- b.loginPinLayout.error = getString(R.string.login_error_incorrect_pin)
- errors = true
- }
- if (errors) return@onClick
-
- val args = Bundle(
- "loginType" to LOGIN_TYPE_LIBRUS,
- "loginMode" to LOGIN_MODE_LIBRUS_JST,
- "accountCode" to code,
- "accountPin" to pin
- )
- nav.navigate(R.id.loginProgressFragment, args, LoginActivity.navOptions)
- }
- }
-}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginMobidziennikFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginMobidziennikFragment.kt
deleted file mode 100644
index de0deb3d..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginMobidziennikFragment.kt
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (c) Kuba Szczodrzyński 2020-1-3.
- */
-
-package pl.szczodrzynski.edziennik.ui.modules.login
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import androidx.fragment.app.Fragment
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.Job
-import pl.szczodrzynski.edziennik.*
-import pl.szczodrzynski.edziennik.data.api.*
-import pl.szczodrzynski.edziennik.databinding.FragmentLoginMobidziennikBinding
-import java.util.*
-import kotlin.coroutines.CoroutineContext
-
-class LoginMobidziennikFragment : Fragment(), CoroutineScope {
- companion object {
- private const val TAG = "LoginMobidziennikFragment"
- }
-
- private lateinit var app: App
- private lateinit var activity: LoginActivity
- private lateinit var b: FragmentLoginMobidziennikBinding
- private val nav by lazy { activity.nav }
-
- private val job: Job = Job()
- override val coroutineContext: CoroutineContext
- get() = job + Dispatchers.Main
-
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- activity = (getActivity() as LoginActivity?) ?: return null
- context ?: return null
- app = activity.application as App
- b = FragmentLoginMobidziennikBinding.inflate(inflater)
- return b.root
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- activity.lastError?.let { error ->
- activity.lastError = null
- startCoroutineTimer(delayMillis = 100) {
- when (error.errorCode) {
- ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_LOGIN ->
- b.loginPasswordLayout.error = getString(R.string.login_error_incorrect_login_or_password)
- ERROR_LOGIN_MOBIDZIENNIK_WEB_OLD_PASSWORD ->
- b.loginPasswordLayout.error = getString(R.string.login_error_old_password)
- ERROR_LOGIN_MOBIDZIENNIK_WEB_ARCHIVED ->
- b.loginUsernameLayout.error = getString(R.string.sync_error_archived)
- ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_ADDRESS ->
- b.loginServerAddressLayout.error = getString(R.string.login_error_incorrect_address)
- }
- }
- }
-
- b.helpButton.onClick { nav.navigate(R.id.loginMobidziennikHelpFragment, null, LoginActivity.navOptions) }
- b.backButton.onClick { nav.navigateUp() }
-
- b.loginButton.onClick {
- var errors = false
-
- b.loginServerAddressLayout.error = null
- b.loginUsernameLayout.error = null
- b.loginPasswordLayout.error = null
-
- val serverName = b.loginServerAddress.text
- ?.toString()
- ?.toLowerCase(Locale.ROOT)
- ?.replace("(?:http://|www.|mobidziennik\\.pl|wizja\\.net|\\.)".toRegex(), "") ?: ""
- val username = b.loginUsername.text?.toString()?.toLowerCase(Locale.ROOT) ?: ""
- val password = b.loginPassword.text?.toString() ?: ""
-
- if (serverName.isBlank()) {
- b.loginServerAddressLayout.error = getString(R.string.login_error_no_address)
- errors = true
- }
- if (username.isBlank()) {
- b.loginUsernameLayout.error = getString(R.string.login_error_no_login)
- errors = true
- }
- if (password.isBlank()) {
- b.loginPasswordLayout.error = getString(R.string.login_error_no_password)
- errors = true
- }
- if (errors) return@onClick
-
- errors = false
-
- b.loginServerAddress.setText(serverName)
- b.loginUsername.setText(username)
- if (!"^[a-z0-9_\\-]+$".toRegex().matches(serverName)) {
- b.loginServerAddressLayout.error = getString(R.string.login_error_incorrect_address)
- errors = true
- }
- if (!"^[a-z0-9_\\-@+.]+$".toRegex().matches(username)) {
- b.loginUsernameLayout.error = getString(R.string.login_error_incorrect_login)
- errors = true
- }
- if (errors) return@onClick
-
- val args = Bundle(
- "loginType" to LOGIN_TYPE_MOBIDZIENNIK,
- "serverName" to serverName,
- "username" to username,
- "password" to password
- )
- nav.navigate(R.id.loginProgressFragment, args, LoginActivity.navOptions)
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginMobidziennikHelpFragment.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginMobidziennikHelpFragment.java
deleted file mode 100644
index 511f6682..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginMobidziennikHelpFragment.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package pl.szczodrzynski.edziennik.ui.modules.login;
-
-import androidx.databinding.DataBindingUtil;
-import android.os.Bundle;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.navigation.NavController;
-import androidx.navigation.Navigation;
-import pl.szczodrzynski.edziennik.App;
-import pl.szczodrzynski.edziennik.R;
-import pl.szczodrzynski.edziennik.databinding.FragmentLoginMobidziennikHelpBinding;
-
-public class LoginMobidziennikHelpFragment extends Fragment {
-
- private App app;
- private NavController nav;
- private FragmentLoginMobidziennikHelpBinding b;
- private static final String TAG = "LoginMobidziennikHelp";
-
- public LoginMobidziennikHelpFragment() { }
-
- @Override
- public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- // Inflate the layout for this fragment
- if (getActivity() != null) {
- app = (App) getActivity().getApplicationContext();
- nav = Navigation.findNavController(getActivity(), R.id.nav_host_fragment);
- }
- else {
- return null;
- }
- b = DataBindingUtil.inflate(inflater, R.layout.fragment_login_mobidziennik_help, container, false);
- return b.getRoot();
- }
-
- @Override
- public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
- assert getContext() != null;
- assert getActivity() != null;
-
- b.backButton.setOnClickListener((v) -> nav.navigateUp());
- }
-}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPlatformAdapter.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPlatformAdapter.kt
new file mode 100644
index 00000000..5bc80f36
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPlatformAdapter.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-16.
+ */
+
+package pl.szczodrzynski.edziennik.ui.modules.login
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.appcompat.app.AppCompatActivity
+import androidx.recyclerview.widget.RecyclerView
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import pl.szczodrzynski.edziennik.App
+import pl.szczodrzynski.edziennik.onClick
+import pl.szczodrzynski.edziennik.ui.modules.login.viewholder.PlatformViewHolder
+import kotlin.coroutines.CoroutineContext
+
+class LoginPlatformAdapter(
+ val activity: AppCompatActivity,
+ val onPlatformClick: ((platform: LoginInfo.Platform) -> Unit)? = null
+) : RecyclerView.Adapter(), CoroutineScope {
+ companion object {
+ private const val TAG = "LoginPlatformAdapter"
+ }
+
+ private val app = activity.applicationContext as App
+ // optional: place the manager here
+
+ private val job = Job()
+ override val coroutineContext: CoroutineContext
+ get() = job + Dispatchers.Main
+
+ var items = listOf()
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PlatformViewHolder {
+ val inflater = LayoutInflater.from(parent.context)
+ return PlatformViewHolder(inflater, parent)
+ }
+
+ override fun onBindViewHolder(holder: PlatformViewHolder, position: Int) {
+ val item = items[position]
+ holder.onBind(activity, app, item, position, this)
+ onPlatformClick?.let {
+ holder.b.root.onClick { _ -> it(item) }
+ }
+ }
+
+ override fun getItemCount() = items.size
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPlatformListFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPlatformListFragment.kt
new file mode 100644
index 00000000..9beb0860
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPlatformListFragment.kt
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-16.
+ */
+
+package pl.szczodrzynski.edziennik.ui.modules.login
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.core.view.isVisible
+import androidx.fragment.app.Fragment
+import androidx.recyclerview.widget.LinearLayoutManager
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.launch
+import pl.szczodrzynski.edziennik.*
+import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
+import pl.szczodrzynski.edziennik.databinding.LoginPlatformListFragmentBinding
+import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration
+import kotlin.coroutines.CoroutineContext
+
+class LoginPlatformListFragment : Fragment(), CoroutineScope {
+ companion object {
+ private const val TAG = "LoginPlatformListFragment"
+ }
+
+ private lateinit var app: App
+ private lateinit var activity: LoginActivity
+ private lateinit var b: LoginPlatformListFragmentBinding
+ private val nav by lazy { activity.nav }
+
+ private val job: Job = Job()
+ override val coroutineContext: CoroutineContext
+ get() = job + Dispatchers.Main
+
+ // local/private variables go here
+ private val api by lazy { SzkolnyApi(app) }
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ activity = (getActivity() as LoginActivity?) ?: return null
+ context ?: return null
+ app = activity.application as App
+ b = LoginPlatformListFragmentBinding.inflate(inflater)
+ return b.root
+ }
+
+ private lateinit var timeoutJob: Job
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ if (!isAdded) return
+ b.backButton.onClick { nav.navigateUp() }
+
+ val loginType = arguments?.getInt("loginType") ?: return
+ val register = LoginInfo.list.firstOrNull { it.loginType == loginType } ?: return
+ val loginMode = arguments?.getInt("loginMode") ?: return
+ val mode = register.loginModes.firstOrNull { it.loginMode == loginMode } ?: return
+
+ timeoutJob = startCoroutineTimer(5000L) {
+ b.timeoutText.isVisible = true
+ timeoutJob.cancel()
+ }
+
+ val adapter = LoginPlatformAdapter(activity) { platform ->
+ nav.navigate(R.id.loginFormFragment, Bundle(
+ "loginType" to platform.loginType,
+ "loginMode" to platform.loginMode,
+ "platformName" to platform.name,
+ "platformDescription" to platform.description,
+ "platformFormFields" to platform.formFields.joinToString(";"),
+ "platformApiData" to platform.apiData.toString()
+ ), activity.navOptions)
+ }
+
+ launch {
+ val platforms = LoginInfo.platformList[mode.name]
+ ?: run {
+ api.runCatching(activity) {
+ getPlatforms(register.internalName)
+ } ?: run {
+ nav.navigateUp()
+ return@launch
+ }
+ }
+ LoginInfo.platformList[mode.name] = platforms
+
+ adapter.items = platforms
+ b.list.adapter = adapter
+ b.list.apply {
+ setHasFixedSize(true)
+ layoutManager = LinearLayoutManager(context)
+ addItemDecoration(SimpleDividerItemDecoration(context))
+ }
+ timeoutJob.cancel()
+ b.loadingLayout.isVisible = false
+ b.list.isVisible = true
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginProfileObject.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginProfileObject.java
deleted file mode 100644
index a86cfa86..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginProfileObject.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package pl.szczodrzynski.edziennik.ui.modules.login;
-
-
-import java.util.ArrayList;
-import java.util.List;
-
-import androidx.annotation.NonNull;
-import pl.szczodrzynski.edziennik.data.db.entity.LoginStore;
-import pl.szczodrzynski.edziennik.data.db.entity.Profile;
-
-public class LoginProfileObject {
- LoginStore loginStore = null;
- List profileList = new ArrayList<>();
- List selectedList = new ArrayList<>();
-
- public LoginProfileObject(@NonNull LoginStore loginStore, @NonNull List profileList) {
- this.loginStore = loginStore;
- this.profileList = profileList;
- for (Profile ignored : profileList) {
- selectedList.add(true);
- }
- }
-
- public LoginProfileObject addProfile(Profile profile) {
- profileList.add(profile);
- selectedList.add(true);
- return this;
- }
-}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginProgressFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginProgressFragment.kt
index 929d9551..ab76327e 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginProgressFragment.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginProgressFragment.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (c) Kuba Szczodrzyński 2020-1-3.
+ * Copyright (c) Kuba Szczodrzyński 2020-4-16.
*/
package pl.szczodrzynski.edziennik.ui.modules.login
@@ -27,8 +27,10 @@ import pl.szczodrzynski.edziennik.data.api.events.FirstLoginFinishedEvent
import pl.szczodrzynski.edziennik.data.api.events.UserActionRequiredEvent
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
-import pl.szczodrzynski.edziennik.databinding.FragmentLoginProgressBinding
+import pl.szczodrzynski.edziennik.databinding.LoginProgressFragmentBinding
+import pl.szczodrzynski.edziennik.joinNotNullStrings
import kotlin.coroutines.CoroutineContext
+import kotlin.math.max
class LoginProgressFragment : Fragment(), CoroutineScope {
companion object {
@@ -37,22 +39,26 @@ class LoginProgressFragment : Fragment(), CoroutineScope {
private lateinit var app: App
private lateinit var activity: LoginActivity
- private lateinit var b: FragmentLoginProgressBinding
+ private lateinit var b: LoginProgressFragmentBinding
private val nav by lazy { activity.nav }
private val job: Job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
+ // local/private variables go here
+
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
activity = (getActivity() as LoginActivity?) ?: return null
context ?: return null
app = activity.application as App
- b = FragmentLoginProgressBinding.inflate(inflater)
+ b = LoginProgressFragmentBinding.inflate(inflater)
return b.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ if (!isAdded) return
+
val args = arguments ?: run {
activity.error(ApiError(TAG, LOGIN_NO_ARGUMENTS))
nav.navigateUp()
@@ -66,19 +72,21 @@ class LoginProgressFragment : Fragment(), CoroutineScope {
launch {
activity.errorSnackbar.dismiss()
- val firstProfileId = (app.db.profileDao().lastId ?: 0) + 1
+ val maxProfileId = max(
+ app.db.profileDao().lastId ?: 0,
+ activity.profiles.maxBy { it.profile.id }?.profile?.id ?: 0
+ )
val loginType = args.getInt("loginType", -1)
val loginMode = args.getInt("loginMode", 0)
val loginStore = LoginStore(
- id = firstProfileId,
+ id = maxProfileId + 1,
type = loginType,
mode = loginMode
)
loginStore.copyFrom(args)
- if (App.devMode && LoginChooserFragment.fakeLogin) {
- loginStore.putLoginData("fakeLogin", true)
- }
+ loginStore.removeLoginData("loginType")
+ loginStore.removeLoginData("loginMode")
EdziennikTask.firstLogin(loginStore).enqueue(activity)
}
}
@@ -94,10 +102,21 @@ class LoginProgressFragment : Fragment(), CoroutineScope {
.show()
return
}
+
+ // update subnames with school years and class name
+ for (profile in event.profileList) {
+ val schoolYearName = "${profile.studentSchoolYearStart}/${profile.studentSchoolYearStart + 1}"
+ profile.subname = joinNotNullStrings(
+ " - ",
+ profile.studentClassName,
+ schoolYearName
+ )
+ }
+
activity.loginStores += event.loginStore
- activity.profiles += event.profileList.map { LoginSummaryProfileAdapter.Item(it) }
+ activity.profiles += event.profileList.map { LoginSummaryAdapter.Item(it) }
activity.errorSnackbar.dismiss()
- nav.navigate(R.id.loginSummaryFragment, null, LoginActivity.navOptions)
+ nav.navigate(R.id.loginSummaryFragment, null, activity.navOptions)
}
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSummaryAdapter.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSummaryAdapter.kt
new file mode 100644
index 00000000..bc9cafbf
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSummaryAdapter.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-16.
+ */
+
+package pl.szczodrzynski.edziennik.ui.modules.login
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import pl.szczodrzynski.edziennik.App
+import pl.szczodrzynski.edziennik.R
+import pl.szczodrzynski.edziennik.data.db.entity.Profile
+import pl.szczodrzynski.edziennik.databinding.LoginSummaryItemBinding
+import pl.szczodrzynski.edziennik.onClick
+import pl.szczodrzynski.edziennik.trigger
+import kotlin.coroutines.CoroutineContext
+
+class LoginSummaryAdapter(
+ val activity: LoginActivity,
+ val onSelectionChanged: ((item: Item) -> Unit)? = null
+) : RecyclerView.Adapter(), CoroutineScope {
+ companion object {
+ private const val TAG = "LoginSummaryAdapter"
+ }
+
+ private val app = activity.applicationContext as App
+ // optional: place the manager here
+
+ private val job = Job()
+ override val coroutineContext: CoroutineContext
+ get() = job + Dispatchers.Main
+
+ var items = listOf- ()
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val inflater = LayoutInflater.from(parent.context)
+ return ViewHolder(LoginSummaryItemBinding.inflate(inflater, parent, false))
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ val item = items[position]
+ val b = holder.b
+ val profile = item.profile
+ val loginStore = activity.loginStores.firstOrNull { it.id == profile.loginStoreId }
+ ?: return
+
+ val loginType = loginStore.type
+ val register = LoginInfo.list.firstOrNull { it.loginType == loginType } ?: return
+ val loginMode = loginStore.mode
+ val mode = register.loginModes.firstOrNull { it.loginMode == loginMode } ?: return
+
+ b.profileName.text = profile.name
+ b.profileDetails.text = profile.subname
+ b.checkBox.isChecked = item.isSelected
+ b.modeIcon.setImageResource(mode.icon)
+
+ if (profile.isParent) {
+ b.accountType.setText(R.string.account_type_parent)
+ } else {
+ b.accountType.setText(R.string.account_type_child)
+ }
+
+ b.root.onClick {
+ b.checkBox.trigger()
+ }
+ b.checkBox.setOnCheckedChangeListener { _, isChecked ->
+ item.isSelected = isChecked
+ onSelectionChanged?.invoke(item)
+ }
+ }
+
+ override fun getItemCount() = items.size
+
+ class ViewHolder(val b: LoginSummaryItemBinding) : RecyclerView.ViewHolder(b.root)
+
+ class Item(val profile: Profile, var isSelected: Boolean = true)
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSummaryFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSummaryFragment.kt
index b16c0256..63525c45 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSummaryFragment.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSummaryFragment.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (c) Kuba Szczodrzyński 2020-1-3.
+ * Copyright (c) Kuba Szczodrzyński 2020-4-16.
*/
package pl.szczodrzynski.edziennik.ui.modules.login
@@ -16,7 +16,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import pl.szczodrzynski.edziennik.*
-import pl.szczodrzynski.edziennik.databinding.FragmentLoginSummaryBinding
+import pl.szczodrzynski.edziennik.databinding.LoginSummaryFragmentBinding
import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration
import kotlin.coroutines.CoroutineContext
@@ -27,27 +27,32 @@ class LoginSummaryFragment : Fragment(), CoroutineScope {
private lateinit var app: App
private lateinit var activity: LoginActivity
- private lateinit var b: FragmentLoginSummaryBinding
+ private lateinit var b: LoginSummaryFragmentBinding
private val nav by lazy { activity.nav }
private val job: Job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
+ // local/private variables go here
+
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
activity = (getActivity() as LoginActivity?) ?: return null
context ?: return null
app = activity.application as App
- b = FragmentLoginSummaryBinding.inflate(inflater)
+ b = LoginSummaryFragmentBinding.inflate(inflater)
return b.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- b.profileListView.apply {
- adapter = LoginSummaryProfileAdapter(activity, activity.profiles) { item ->
- b.finishButton.isEnabled = activity.profiles.any { it.isSelected }
- }
+ val adapter = LoginSummaryAdapter(activity) { _ ->
+ b.finishButton.isEnabled = activity.profiles.any { it.isSelected }
+ }
+
+ adapter.items = activity.profiles
+ b.list.adapter = adapter
+ b.list.apply {
isNestedScrollingEnabled = false
setHasFixedSize(true)
layoutManager = LinearLayoutManager(context)
@@ -66,7 +71,7 @@ class LoginSummaryFragment : Fragment(), CoroutineScope {
}
b.anotherButton.onClick {
- nav.navigate(R.id.loginChooserFragment, null, LoginActivity.navOptions)
+ nav.navigate(R.id.loginChooserFragment, null, activity.navOptions)
}
b.finishButton.onClick {
@@ -86,7 +91,7 @@ class LoginSummaryFragment : Fragment(), CoroutineScope {
val args = Bundle(
"registrationAllowed" to b.registerMeSwitch.isChecked
)
- nav.navigate(R.id.loginSyncFragment, args, LoginActivity.navOptions)
+ nav.navigate(R.id.loginSyncFragment, args, activity.navOptions)
}
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSummaryProfileAdapter.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSummaryProfileAdapter.kt
deleted file mode 100644
index 7a74dd76..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSummaryProfileAdapter.kt
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) Kuba Szczodrzyński 2020-1-3.
- */
-
-package pl.szczodrzynski.edziennik.ui.modules.login
-
-import android.content.Context
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import androidx.recyclerview.widget.RecyclerView
-import pl.szczodrzynski.edziennik.*
-import pl.szczodrzynski.edziennik.data.api.*
-import pl.szczodrzynski.edziennik.data.db.entity.Profile
-import pl.szczodrzynski.edziennik.databinding.RowLoginProfileListItemBinding
-
-class LoginSummaryProfileAdapter(
- val context: Context,
- val items: List
- ,
- val onSelectionChanged: ((item: Item) -> Unit)? = null
-) : RecyclerView.Adapter() {
-
- private val app by lazy { context.applicationContext as App }
-
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
- val inflater = LayoutInflater.from(parent.context)
- val view = RowLoginProfileListItemBinding.inflate(inflater, parent, false)
- return ViewHolder(view)
- }
-
- override fun onBindViewHolder(holder: ViewHolder, position: Int) {
- val item = items[position]
- val profile = item.profile
- val b = holder.b
-
- b.textView.text = profile.name
- b.checkBox.isChecked = item.isSelected
-
- val registerIcon = when (profile.loginStoreType) {
- LOGIN_TYPE_MOBIDZIENNIK -> R.drawable.logo_mobidziennik
- LOGIN_TYPE_LIBRUS -> R.drawable.logo_librus
- LOGIN_TYPE_IDZIENNIK -> R.drawable.logo_idziennik
- LOGIN_TYPE_VULCAN -> R.drawable.logo_vulcan
- LOGIN_TYPE_EDUDZIENNIK -> R.drawable.logo_edudziennik
- else -> null
- }
- if (registerIcon == null)
- b.registerIcon.visibility = View.GONE
- else {
- b.registerIcon.visibility = View.VISIBLE
- b.registerIcon.setImageResource(registerIcon)
- }
-
- if (profile.isParent) {
- b.accountType.setText(R.string.login_summary_account_parent)
- } else {
- b.accountType.setText(R.string.login_summary_account_child)
- }
-
- val schoolYearName = "${profile.studentSchoolYearStart}/${profile.studentSchoolYearStart+1}"
- b.textDetails.text = joinNotNullStrings(
- " - ",
- profile.studentClassName,
- schoolYearName
- )
-
- b.root.onClick {
- b.checkBox.trigger()
- }
- b.checkBox.setOnCheckedChangeListener { _, isChecked ->
- item.isSelected = isChecked
- onSelectionChanged?.invoke(item)
- }
- }
-
- override fun getItemCount() = items.size
-
- class ViewHolder(val b: RowLoginProfileListItemBinding) : RecyclerView.ViewHolder(b.root)
-
- class Item(val profile: Profile, var isSelected: Boolean = true)
-}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSyncErrorFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSyncErrorFragment.kt
index 49977dee..e13130a5 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSyncErrorFragment.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSyncErrorFragment.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (c) Kuba Szczodrzyński 2020-1-3.
+ * Copyright (c) Kuba Szczodrzyński 2020-4-14.
*/
package pl.szczodrzynski.edziennik.ui.modules.login
@@ -14,7 +14,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.R
-import pl.szczodrzynski.edziennik.databinding.FragmentLoginSyncErrorBinding
+import pl.szczodrzynski.edziennik.databinding.LoginSyncErrorFragmentBinding
import pl.szczodrzynski.edziennik.onClick
import kotlin.coroutines.CoroutineContext
@@ -25,18 +25,20 @@ class LoginSyncErrorFragment : Fragment(), CoroutineScope {
private lateinit var app: App
private lateinit var activity: LoginActivity
- private lateinit var b: FragmentLoginSyncErrorBinding
+ private lateinit var b: LoginSyncErrorFragmentBinding
private val nav by lazy { activity.nav }
private val job: Job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
+ // local/private variables go here
+
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
activity = (getActivity() as LoginActivity?) ?: return null
context ?: return null
app = activity.application as App
- b = FragmentLoginSyncErrorBinding.inflate(inflater)
+ b = LoginSyncErrorFragmentBinding.inflate(inflater)
return b.root
}
@@ -44,7 +46,7 @@ class LoginSyncErrorFragment : Fragment(), CoroutineScope {
b.errorDetails.text = activity.lastError?.getStringReason(activity)
activity.lastError = null
b.nextButton.onClick {
- nav.navigate(R.id.loginFinishFragment, arguments, LoginActivity.navOptions)
+ nav.navigate(R.id.loginFinishFragment, arguments, activity.navOptions)
}
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSyncFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSyncFragment.kt
index 789bcb07..c0aab663 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSyncFragment.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSyncFragment.kt
@@ -1,3 +1,7 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-16.
+ */
+
package pl.szczodrzynski.edziennik.ui.modules.login
import android.os.Bundle
@@ -19,9 +23,8 @@ import pl.szczodrzynski.edziennik.data.api.events.ApiTaskAllFinishedEvent
import pl.szczodrzynski.edziennik.data.api.events.ApiTaskErrorEvent
import pl.szczodrzynski.edziennik.data.api.events.ApiTaskProgressEvent
import pl.szczodrzynski.edziennik.data.api.events.ApiTaskStartedEvent
-import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.REGISTRATION_DISABLED
-import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.REGISTRATION_ENABLED
-import pl.szczodrzynski.edziennik.databinding.FragmentLoginSyncBinding
+import pl.szczodrzynski.edziennik.data.db.entity.Profile
+import pl.szczodrzynski.edziennik.databinding.LoginSyncFragmentBinding
import kotlin.coroutines.CoroutineContext
import kotlin.math.roundToInt
@@ -32,7 +35,7 @@ class LoginSyncFragment : Fragment(), CoroutineScope {
private lateinit var app: App
private lateinit var activity: LoginActivity
- private lateinit var b: FragmentLoginSyncBinding
+ private lateinit var b: LoginSyncFragmentBinding
private val nav: NavController by lazy { Navigation.findNavController(activity, R.id.nav_host_fragment) }
private val job: Job = Job()
@@ -45,7 +48,7 @@ class LoginSyncFragment : Fragment(), CoroutineScope {
activity = (getActivity() as LoginActivity?) ?: return null
context ?: return null
app = activity.application as App
- b = FragmentLoginSyncBinding.inflate(inflater)
+ b = LoginSyncFragmentBinding.inflate(inflater)
return b.root
}
@@ -56,9 +59,9 @@ class LoginSyncFragment : Fragment(), CoroutineScope {
val registrationAllowed = arguments?.getBoolean("registrationAllowed") ?: false
profiles.forEach {
it.registration = if (registrationAllowed)
- REGISTRATION_ENABLED
+ Profile.REGISTRATION_ENABLED
else
- REGISTRATION_DISABLED
+ Profile.REGISTRATION_DISABLED
app.db.eventTypeDao().addDefaultTypes(activity, it.id)
}
@@ -84,13 +87,13 @@ class LoginSyncFragment : Fragment(), CoroutineScope {
@Subscribe(threadMode = ThreadMode.MAIN)
fun onSyncFinishedEvent(event: ApiTaskAllFinishedEvent) {
- nav.navigate(R.id.loginFinishFragment, finishArguments, LoginActivity.navOptions)
+ nav.navigate(R.id.loginFinishFragment, finishArguments, activity.navOptions)
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onSyncProgressEvent(event: ApiTaskProgressEvent) {
b.loginSyncProgressBar.progress = event.progress.roundToInt()
- b.loginSyncProgressBar.isIndeterminate = event.progress < 0f
+ b.loginSyncProgressBar.isIndeterminate = event.progress <= 0f
b.loginSyncSubtitle2.text = event.progressText
}
@@ -98,7 +101,7 @@ class LoginSyncFragment : Fragment(), CoroutineScope {
fun onSyncErrorEvent(event: ApiTaskErrorEvent) {
EventBus.getDefault().removeStickyEvent(event)
activity.error(event.error)
- nav.navigate(R.id.loginSyncErrorFragment, finishArguments, LoginActivity.navOptions)
+ nav.navigate(R.id.loginSyncErrorFragment, finishArguments, activity.navOptions)
}
override fun onStart() {
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginTemplateFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginTemplateFragment.kt
deleted file mode 100644
index 4264416a..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginTemplateFragment.kt
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) Kuba Szczodrzyński 2020-1-3.
- */
-
-package pl.szczodrzynski.edziennik.ui.modules.login
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import androidx.fragment.app.Fragment
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.Job
-import pl.szczodrzynski.edziennik.*
-import pl.szczodrzynski.edziennik.data.api.ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN
-import pl.szczodrzynski.edziennik.data.api.ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED
-import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_TEMPLATE
-import pl.szczodrzynski.edziennik.databinding.FragmentLoginTemplateBinding
-import java.util.*
-import kotlin.coroutines.CoroutineContext
-
-class LoginTemplateFragment : Fragment(), CoroutineScope {
- companion object {
- private const val TAG = "LoginTemplateFragment"
- }
-
- private lateinit var app: App
- private lateinit var activity: LoginActivity
- private lateinit var b: FragmentLoginTemplateBinding
- private val nav by lazy { activity.nav }
-
- private val job: Job = Job()
- override val coroutineContext: CoroutineContext
- get() = job + Dispatchers.Main
-
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- activity = (getActivity() as LoginActivity?) ?: return null
- context ?: return null
- app = activity.application as App
- b = FragmentLoginTemplateBinding.inflate(inflater)
- return b.root
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- activity.lastError?.let { error ->
- activity.lastError = null
- startCoroutineTimer(delayMillis = 100) {
- when (error.errorCode) {
- ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN ->
- b.loginPasswordLayout.error = getString(R.string.login_error_incorrect_login_or_password)
- ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED ->
- b.loginEmailLayout.error = getString(R.string.login_error_account_not_activated)
- }
- }
- }
-
- b.helpButton.onClick { nav.navigate(R.id.loginLibrusHelpFragment, null, LoginActivity.navOptions) }
- b.backButton.onClick { nav.navigateUp() }
-
- b.loginButton.onClick {
- var errors = false
-
- b.loginEmailLayout.error = null
- b.loginPasswordLayout.error = null
-
- val email = b.loginEmail.text?.toString()?.toLowerCase(Locale.ROOT) ?: ""
- val password = b.loginPassword.text?.toString() ?: ""
-
- if (email.isBlank()) {
- b.loginEmailLayout.error = getString(R.string.login_error_no_email)
- errors = true
- }
- if (password.isBlank()) {
- b.loginPasswordLayout.error = getString(R.string.login_error_no_password)
- errors = true
- }
- if (errors) return@onClick
-
- errors = false
-
- b.loginEmail.setText(email)
- if (!"([\\w.\\-_+]+)?\\w+@[\\w-_]+(\\.\\w+)+".toRegex().matches(email)) {
- b.loginEmailLayout.error = getString(R.string.login_error_incorrect_email)
- errors = true
- }
- if (errors) return@onClick
-
- val args = Bundle(
- "loginType" to LOGIN_TYPE_TEMPLATE,
- "email" to email,
- "password" to password
- )
- nav.navigate(R.id.loginProgressFragment, args, LoginActivity.navOptions)
- }
- }
-}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginVulcanFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginVulcanFragment.kt
deleted file mode 100644
index 63ea9834..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginVulcanFragment.kt
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) Kuba Szczodrzyński 2020-1-3.
- */
-
-package pl.szczodrzynski.edziennik.ui.modules.login
-
-import android.graphics.Color
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.view.WindowManager
-import androidx.fragment.app.Fragment
-import com.mikepenz.iconics.IconicsDrawable
-import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
-import com.mikepenz.iconics.utils.colorInt
-import com.mikepenz.iconics.utils.sizeDp
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.Job
-import pl.szczodrzynski.edziennik.*
-import pl.szczodrzynski.edziennik.data.api.*
-import pl.szczodrzynski.edziennik.databinding.FragmentLoginVulcanBinding
-import pl.szczodrzynski.edziennik.ui.dialogs.QrScannerDialog
-import pl.szczodrzynski.edziennik.utils.Utils
-import java.util.*
-import kotlin.coroutines.CoroutineContext
-
-class LoginVulcanFragment : Fragment(), CoroutineScope {
- companion object {
- private const val TAG = "LoginVulcanFragment"
- }
-
- private lateinit var app: App
- private lateinit var activity: LoginActivity
- private lateinit var b: FragmentLoginVulcanBinding
- private val nav by lazy { activity.nav }
-
- private val job: Job = Job()
- override val coroutineContext: CoroutineContext
- get() = job + Dispatchers.Main
-
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- activity = (getActivity() as LoginActivity?) ?: return null
- context ?: return null
- app = activity.application as App
- b = FragmentLoginVulcanBinding.inflate(inflater)
- return b.root
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- activity.lastError?.let { error ->
- activity.lastError = null
- startCoroutineTimer(delayMillis = 100) {
- when (error.errorCode) {
- ERROR_LOGIN_VULCAN_INVALID_TOKEN ->
- b.loginTokenLayout.error = getString(R.string.login_error_incorrect_token)
- ERROR_LOGIN_VULCAN_EXPIRED_TOKEN ->
- b.loginTokenLayout.error = getString(R.string.login_error_expired_token)
- ERROR_LOGIN_VULCAN_INVALID_SYMBOL ->
- b.loginSymbolLayout.error = getString(R.string.login_error_incorrect_symbol)
- ERROR_LOGIN_VULCAN_INVALID_PIN ->
- b.loginPinLayout.error = getString(R.string.login_error_incorrect_pin)
- }
- }
- }
-
- b.loginQrScan.setImageDrawable(IconicsDrawable(activity)
- .icon(CommunityMaterial.Icon2.cmd_qrcode_scan)
- .colorInt(Color.BLACK)
- .sizeDp(72))
- b.loginQrScan.onClick {
- QrScannerDialog(activity, { code ->
- try {
- val data = Utils.VulcanQrEncryptionUtils.decode(code)
- "CERT#https?://.+?/([A-z]+)/mobile-api#([A-z0-9]+)#ENDCERT".toRegex().find(data)?.let {
- b.loginToken.setText(it[2])
- b.loginSymbol.setText(it[1])
- if (b.loginPin.requestFocus()) {
- activity.window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
- }
- }
- }
- catch (_: Exception) {}
- })
- }
-
- b.helpButton.onClick { nav.navigate(R.id.loginVulcanHelpFragment, null, LoginActivity.navOptions) }
- b.backButton.onClick { nav.navigateUp() }
-
- b.loginButton.onClick {
- var errors = false
-
- b.loginTokenLayout.error = null
- b.loginSymbolLayout.error = null
- b.loginPinLayout.error = null
-
- val token = b.loginToken.text?.toString()?.toUpperCase(Locale.ROOT) ?: ""
- val symbol = b.loginSymbol.text?.toString()?.toLowerCase(Locale.ROOT) ?: ""
- val pin = b.loginPin.text?.toString() ?: ""
-
- if (token.isBlank()) {
- b.loginTokenLayout.error = getString(R.string.login_error_no_token)
- errors = true
- }
- if (symbol.isBlank()) {
- b.loginSymbolLayout.error = getString(R.string.login_error_no_symbol)
- errors = true
- }
- if (pin.isBlank()) {
- b.loginPinLayout.error = getString(R.string.login_error_no_pin)
- errors = true
- }
- if (errors) return@onClick
-
- errors = false
-
- b.loginToken.setText(token)
- b.loginSymbol.setText(symbol)
- b.loginPin.setText(pin)
- if (!"[A-Z0-9]{5,12}".toRegex().matches(token)) {
- b.loginTokenLayout.error = getString(R.string.login_error_incorrect_token)
- errors = true
- }
- if (!"[a-z0-9_-]+".toRegex().matches(symbol)) {
- b.loginSymbolLayout.error = getString(R.string.login_error_incorrect_symbol)
- errors = true
- }
- if (!"[a-z0-9_]+".toRegex().matches(pin)) {
- b.loginPinLayout.error = getString(R.string.login_error_incorrect_pin)
- errors = true
- }
- if (errors) return@onClick
-
- val args = Bundle(
- "loginType" to LOGIN_TYPE_VULCAN,
- "deviceToken" to token,
- "deviceSymbol" to symbol,
- "devicePin" to pin
- )
- nav.navigate(R.id.loginProgressFragment, args, LoginActivity.navOptions)
- }
- }
-}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginVulcanHelpFragment.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginVulcanHelpFragment.java
deleted file mode 100644
index 0aa899ae..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginVulcanHelpFragment.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package pl.szczodrzynski.edziennik.ui.modules.login;
-
-import androidx.databinding.DataBindingUtil;
-import android.os.Bundle;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.navigation.NavController;
-import androidx.navigation.Navigation;
-import pl.szczodrzynski.edziennik.App;
-import pl.szczodrzynski.edziennik.R;
-import pl.szczodrzynski.edziennik.databinding.FragmentLoginVulcanHelpBinding;
-
-public class LoginVulcanHelpFragment extends Fragment {
-
- private App app;
- private NavController nav;
- private FragmentLoginVulcanHelpBinding b;
- private static final String TAG = "LoginVulcanHelp";
-
- public LoginVulcanHelpFragment() { }
-
- @Override
- public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- // Inflate the layout for this fragment
- if (getActivity() != null) {
- app = (App) getActivity().getApplicationContext();
- nav = Navigation.findNavController(getActivity(), R.id.nav_host_fragment);
- }
- else {
- return null;
- }
- b = DataBindingUtil.inflate(inflater, R.layout.fragment_login_vulcan_help, container, false);
- return b.getRoot();
- }
-
- @Override
- public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
- assert getContext() != null;
- assert getActivity() != null;
-
- b.backButton.setOnClickListener((v) -> nav.navigateUp());
- }
-}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/viewholder/ModeViewHolder.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/viewholder/ModeViewHolder.kt
new file mode 100644
index 00000000..cdb0e7b8
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/viewholder/ModeViewHolder.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-10.
+ */
+
+package pl.szczodrzynski.edziennik.ui.modules.login.viewholder
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.isVisible
+import androidx.recyclerview.widget.RecyclerView
+import pl.szczodrzynski.edziennik.App
+import pl.szczodrzynski.edziennik.databinding.LoginChooserModeItemBinding
+import pl.szczodrzynski.edziennik.ui.modules.grades.viewholder.BindableViewHolder
+import pl.szczodrzynski.edziennik.ui.modules.login.LoginChooserAdapter
+import pl.szczodrzynski.edziennik.ui.modules.login.LoginInfo
+
+class ModeViewHolder(
+ inflater: LayoutInflater,
+ parent: ViewGroup,
+ val b: LoginChooserModeItemBinding = LoginChooserModeItemBinding.inflate(inflater, parent, false)
+) : RecyclerView.ViewHolder(b.root), BindableViewHolder {
+ companion object {
+ private const val TAG = "ModeViewHolder"
+ }
+
+ override fun onBind(activity: AppCompatActivity, app: App, item: LoginInfo.Mode, position: Int, adapter: LoginChooserAdapter) {
+ b.logo.setImageResource(item.icon)
+ b.name.setText(item.name)
+ if (item.hintText == null) {
+ b.description.isVisible = false
+ }
+ else {
+ b.description.isVisible = true
+ b.description.setText(item.hintText)
+ }
+ b.hint.isVisible = false
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/viewholder/PlatformViewHolder.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/viewholder/PlatformViewHolder.kt
new file mode 100644
index 00000000..ea8a063d
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/viewholder/PlatformViewHolder.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-10.
+ */
+
+package pl.szczodrzynski.edziennik.ui.modules.login.viewholder
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.isVisible
+import androidx.recyclerview.widget.RecyclerView
+import coil.api.load
+import pl.szczodrzynski.edziennik.App
+import pl.szczodrzynski.edziennik.databinding.LoginPlatformItemBinding
+import pl.szczodrzynski.edziennik.ui.modules.grades.viewholder.BindableViewHolder
+import pl.szczodrzynski.edziennik.ui.modules.login.LoginInfo
+import pl.szczodrzynski.edziennik.ui.modules.login.LoginPlatformAdapter
+
+class PlatformViewHolder(
+ inflater: LayoutInflater,
+ parent: ViewGroup,
+ val b: LoginPlatformItemBinding = LoginPlatformItemBinding.inflate(inflater, parent, false)
+) : RecyclerView.ViewHolder(b.root), BindableViewHolder {
+ companion object {
+ private const val TAG = "PlatformViewHolder"
+ }
+
+ override fun onBind(activity: AppCompatActivity, app: App, item: LoginInfo.Platform, position: Int, adapter: LoginPlatformAdapter) {
+ b.logo.load(item.icon)
+ b.name.text = item.name
+ b.description.text = item.description
+ b.description.isVisible = item.description != null
+ b.screenshotButton.isVisible = false
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/viewholder/RegisterViewHolder.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/viewholder/RegisterViewHolder.kt
new file mode 100644
index 00000000..921041c8
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/viewholder/RegisterViewHolder.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-10.
+ */
+
+package pl.szczodrzynski.edziennik.ui.modules.login.viewholder
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.isVisible
+import androidx.recyclerview.widget.RecyclerView
+import pl.szczodrzynski.edziennik.App
+import pl.szczodrzynski.edziennik.databinding.LoginChooserItemBinding
+import pl.szczodrzynski.edziennik.ui.modules.grades.viewholder.BindableViewHolder
+import pl.szczodrzynski.edziennik.ui.modules.login.LoginChooserAdapter
+import pl.szczodrzynski.edziennik.ui.modules.login.LoginInfo
+
+class RegisterViewHolder(
+ inflater: LayoutInflater,
+ parent: ViewGroup,
+ val b: LoginChooserItemBinding = LoginChooserItemBinding.inflate(inflater, parent, false)
+) : RecyclerView.ViewHolder(b.root), BindableViewHolder {
+ companion object {
+ private const val TAG = "RegisterViewHolder"
+ }
+
+ override fun onBind(activity: AppCompatActivity, app: App, item: LoginInfo.Register, position: Int, adapter: LoginChooserAdapter) {
+ b.logo.setImageResource(item.registerLogo)
+ b.name.setText(item.registerName)
+ b.description.isVisible = false
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java
index cc72c46c..3e3eac0e 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java
@@ -55,6 +55,7 @@ import pl.szczodrzynski.edziennik.ui.dialogs.changelog.ChangelogDialog;
import pl.szczodrzynski.edziennik.ui.dialogs.settings.GradesConfigDialog;
import pl.szczodrzynski.edziennik.ui.dialogs.settings.ProfileRemoveDialog;
import pl.szczodrzynski.edziennik.ui.dialogs.sync.NotificationFilterDialog;
+import pl.szczodrzynski.edziennik.ui.modules.login.LoginActivity;
import pl.szczodrzynski.edziennik.utils.Themes;
import pl.szczodrzynski.edziennik.utils.Utils;
import pl.szczodrzynski.edziennik.utils.models.Date;
@@ -161,7 +162,7 @@ public class SettingsNewFragment extends MaterialAboutFragment {
profileCardTitleItem = new MaterialAboutProfileItem(
app.getProfile().getName(),
- getString(R.string.settings_profile_subtitle_format, app.getProfile().getSubname()),
+ app.getProfile().getSubname(),
getProfileDrawable()
);
profileCardTitleItem.setOnClickAction(() -> {
@@ -218,6 +219,20 @@ public class SettingsNewFragment extends MaterialAboutFragment {
})
);*/
+ items.add(
+ new MaterialAboutActionItem(
+ getString(R.string.settings_add_student_text),
+ getString(R.string.settings_add_student_subtext),
+ new IconicsDrawable(activity)
+ .icon(CommunityMaterial.Icon.cmd_account_plus_outline)
+ .size(IconicsSize.dp(iconSizeDp))
+ .color(IconicsColor.colorInt(iconColor))
+ )
+ .setOnClickAction(() -> {
+ startActivity(new Intent(activity, LoginActivity.class));
+ })
+ );
+
items.add(
new MaterialAboutActionItem(
getString(R.string.settings_profile_notifications_text),
@@ -232,6 +247,20 @@ public class SettingsNewFragment extends MaterialAboutFragment {
})
);
+ items.add(
+ new MaterialAboutActionItem(
+ getString(R.string.settings_profile_remove_text),
+ getString(R.string.settings_profile_remove_subtext),
+ new IconicsDrawable(activity)
+ .icon(SzkolnyFont.Icon.szf_delete_empty_outline)
+ .size(IconicsSize.dp(iconSizeDp))
+ .color(IconicsColor.colorInt(iconColor))
+ )
+ .setOnClickAction(() -> {
+ new ProfileRemoveDialog(activity, app.getProfile().getId(), app.getProfile().getName());
+ })
+ );
+
items.add(getMoreItem(() -> addCardItems(CARD_PROFILE, getProfileCard(true))));
}
else {
@@ -253,20 +282,6 @@ public class SettingsNewFragment extends MaterialAboutFragment {
}))
);
- items.add(
- new MaterialAboutActionItem(
- getString(R.string.settings_profile_remove_text),
- getString(R.string.settings_profile_remove_subtext),
- new IconicsDrawable(activity)
- .icon(SzkolnyFont.Icon.szf_delete_empty_outline)
- .size(IconicsSize.dp(iconSizeDp))
- .color(IconicsColor.colorInt(iconColor))
- )
- .setOnClickAction(() -> {
- new ProfileRemoveDialog(activity, app.getProfile().getId(), app.getProfile().getName());
- })
- );
-
}
return items;
}
diff --git a/app/src/main/res/drawable/logo_librus.png b/app/src/main/res/drawable/login_mode_librus_email.png
similarity index 100%
rename from app/src/main/res/drawable/logo_librus.png
rename to app/src/main/res/drawable/login_mode_librus_email.png
diff --git a/app/src/main/res/drawable/login_mode_librus_jst.png b/app/src/main/res/drawable/login_mode_librus_jst.png
new file mode 100644
index 00000000..b0ea579c
Binary files /dev/null and b/app/src/main/res/drawable/login_mode_librus_jst.png differ
diff --git a/app/src/main/res/drawable/logo_synergia.png b/app/src/main/res/drawable/login_mode_librus_synergia.png
similarity index 100%
rename from app/src/main/res/drawable/logo_synergia.png
rename to app/src/main/res/drawable/login_mode_librus_synergia.png
diff --git a/app/src/main/res/drawable/login_mode_mobidziennik_web.png b/app/src/main/res/drawable/login_mode_mobidziennik_web.png
new file mode 100644
index 00000000..5ab3d146
Binary files /dev/null and b/app/src/main/res/drawable/login_mode_mobidziennik_web.png differ
diff --git a/app/src/main/res/drawable/logo_dzienniczek.png b/app/src/main/res/drawable/login_mode_vulcan_api.png
similarity index 100%
rename from app/src/main/res/drawable/logo_dzienniczek.png
rename to app/src/main/res/drawable/login_mode_vulcan_api.png
diff --git a/app/src/main/res/drawable/logo_vulcan.png b/app/src/main/res/drawable/login_mode_vulcan_web.png
similarity index 100%
rename from app/src/main/res/drawable/logo_vulcan.png
rename to app/src/main/res/drawable/login_mode_vulcan_web.png
diff --git a/app/src/main/res/drawable/logo_mobidziennik.png b/app/src/main/res/drawable/logo_mobidziennik.png
deleted file mode 100644
index 0d4d853f..00000000
Binary files a/app/src/main/res/drawable/logo_mobidziennik.png and /dev/null differ
diff --git a/app/src/main/res/layout/activity_grades_editor.xml b/app/src/main/res/layout/activity_grades_editor.xml
deleted file mode 100644
index 7e3a6998..00000000
--- a/app/src/main/res/layout/activity_grades_editor.xml
+++ /dev/null
@@ -1,194 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
deleted file mode 100644
index 020e3de9..00000000
--- a/app/src/main/res/layout/activity_main.xml
+++ /dev/null
@@ -1,87 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/activity_szkolny.xml b/app/src/main/res/layout/activity_szkolny.xml
index 7ce06741..2a78de30 100644
--- a/app/src/main/res/layout/activity_szkolny.xml
+++ b/app/src/main/res/layout/activity_szkolny.xml
@@ -34,4 +34,4 @@
-
\ No newline at end of file
+
diff --git a/app/src/main/res/layout/activity_web_push_config.xml b/app/src/main/res/layout/activity_web_push_config.xml
deleted file mode 100644
index 17e62ec6..00000000
--- a/app/src/main/res/layout/activity_web_push_config.xml
+++ /dev/null
@@ -1,178 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/fragment_login_chooser.xml b/app/src/main/res/layout/fragment_login_chooser.xml
deleted file mode 100644
index 8a7c0f77..00000000
--- a/app/src/main/res/layout/fragment_login_chooser.xml
+++ /dev/null
@@ -1,262 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/fragment_login_edudziennik.xml b/app/src/main/res/layout/fragment_login_edudziennik.xml
deleted file mode 100644
index 551962b5..00000000
--- a/app/src/main/res/layout/fragment_login_edudziennik.xml
+++ /dev/null
@@ -1,174 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/fragment_login_finish.xml b/app/src/main/res/layout/fragment_login_finish.xml
deleted file mode 100644
index 8635620a..00000000
--- a/app/src/main/res/layout/fragment_login_finish.xml
+++ /dev/null
@@ -1,92 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_login_iuczniowie.xml b/app/src/main/res/layout/fragment_login_iuczniowie.xml
deleted file mode 100644
index 89686298..00000000
--- a/app/src/main/res/layout/fragment_login_iuczniowie.xml
+++ /dev/null
@@ -1,189 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_login_iuczniowie_help.xml b/app/src/main/res/layout/fragment_login_iuczniowie_help.xml
deleted file mode 100644
index 1bcd16c9..00000000
--- a/app/src/main/res/layout/fragment_login_iuczniowie_help.xml
+++ /dev/null
@@ -1,97 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_login_librus.xml b/app/src/main/res/layout/fragment_login_librus.xml
deleted file mode 100644
index 2ed16cd2..00000000
--- a/app/src/main/res/layout/fragment_login_librus.xml
+++ /dev/null
@@ -1,169 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_login_librus_help.xml b/app/src/main/res/layout/fragment_login_librus_help.xml
deleted file mode 100644
index 21a6d88d..00000000
--- a/app/src/main/res/layout/fragment_login_librus_help.xml
+++ /dev/null
@@ -1,97 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_login_librus_jst.xml b/app/src/main/res/layout/fragment_login_librus_jst.xml
deleted file mode 100644
index 53390d63..00000000
--- a/app/src/main/res/layout/fragment_login_librus_jst.xml
+++ /dev/null
@@ -1,194 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/fragment_login_migration_sync.xml b/app/src/main/res/layout/fragment_login_migration_sync.xml
deleted file mode 100644
index ab0cce52..00000000
--- a/app/src/main/res/layout/fragment_login_migration_sync.xml
+++ /dev/null
@@ -1,98 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_login_mobidziennik.xml b/app/src/main/res/layout/fragment_login_mobidziennik.xml
deleted file mode 100644
index 1eac127d..00000000
--- a/app/src/main/res/layout/fragment_login_mobidziennik.xml
+++ /dev/null
@@ -1,191 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_login_mobidziennik_help.xml b/app/src/main/res/layout/fragment_login_mobidziennik_help.xml
deleted file mode 100644
index 0355abea..00000000
--- a/app/src/main/res/layout/fragment_login_mobidziennik_help.xml
+++ /dev/null
@@ -1,129 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_login_progress.xml b/app/src/main/res/layout/fragment_login_progress.xml
deleted file mode 100644
index fa73a596..00000000
--- a/app/src/main/res/layout/fragment_login_progress.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_login_summary.xml b/app/src/main/res/layout/fragment_login_summary.xml
deleted file mode 100644
index 26643b57..00000000
--- a/app/src/main/res/layout/fragment_login_summary.xml
+++ /dev/null
@@ -1,124 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_login_sync.xml b/app/src/main/res/layout/fragment_login_sync.xml
deleted file mode 100644
index a0b072c6..00000000
--- a/app/src/main/res/layout/fragment_login_sync.xml
+++ /dev/null
@@ -1,99 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_login_template.xml b/app/src/main/res/layout/fragment_login_template.xml
deleted file mode 100644
index 2ed16cd2..00000000
--- a/app/src/main/res/layout/fragment_login_template.xml
+++ /dev/null
@@ -1,169 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_login_vulcan.xml b/app/src/main/res/layout/fragment_login_vulcan.xml
deleted file mode 100644
index c1668e60..00000000
--- a/app/src/main/res/layout/fragment_login_vulcan.xml
+++ /dev/null
@@ -1,213 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_login_vulcan_help.xml b/app/src/main/res/layout/fragment_login_vulcan_help.xml
deleted file mode 100644
index d60f8362..00000000
--- a/app/src/main/res/layout/fragment_login_vulcan_help.xml
+++ /dev/null
@@ -1,129 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/login_activity.xml
similarity index 71%
rename from app/src/main/res/layout/activity_login.xml
rename to app/src/main/res/layout/login_activity.xml
index 56d3f169..52bccaec 100644
--- a/app/src/main/res/layout/activity_login.xml
+++ b/app/src/main/res/layout/login_activity.xml
@@ -1,4 +1,8 @@
+
+
@@ -8,11 +12,6 @@
android:orientation="vertical"
android:visibility="visible">
-
-
-
+ android:layout_marginBottom="16dp"
+ android:visibility="invisible" />
-
\ No newline at end of file
+
diff --git a/app/src/main/res/layout/login_chooser_fragment.xml b/app/src/main/res/layout/login_chooser_fragment.xml
new file mode 100644
index 00000000..90aa1bc8
--- /dev/null
+++ b/app/src/main/res/layout/login_chooser_fragment.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/login_chooser_item.xml b/app/src/main/res/layout/login_chooser_item.xml
new file mode 100644
index 00000000..3486a504
--- /dev/null
+++ b/app/src/main/res/layout/login_chooser_item.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/login_chooser_mode_item.xml b/app/src/main/res/layout/login_chooser_mode_item.xml
new file mode 100644
index 00000000..cbfae377
--- /dev/null
+++ b/app/src/main/res/layout/login_chooser_mode_item.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_login_migration.xml b/app/src/main/res/layout/login_finish_fragment.xml
similarity index 51%
rename from app/src/main/res/layout/fragment_login_migration.xml
rename to app/src/main/res/layout/login_finish_fragment.xml
index 2948b9ec..fcd2c29c 100644
--- a/app/src/main/res/layout/fragment_login_migration.xml
+++ b/app/src/main/res/layout/login_finish_fragment.xml
@@ -1,7 +1,12 @@
-
+
+
+
+
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:paddingHorizontal="24dp">
+ tools:srcCompat="@android:drawable/stat_sys_phone_call_forward" />
-
-
-
-
-
-
-
+ tools:text="@string/login_finish_subtitle" />
-
-
-
-
\ No newline at end of file
+
diff --git a/app/src/main/res/layout/login_form_fragment.xml b/app/src/main/res/layout/login_form_fragment.xml
new file mode 100644
index 00000000..80f7bdc4
--- /dev/null
+++ b/app/src/main/res/layout/login_form_fragment.xml
@@ -0,0 +1,152 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/login_form_item.xml b/app/src/main/res/layout/login_form_item.xml
new file mode 100644
index 00000000..3a4a1660
--- /dev/null
+++ b/app/src/main/res/layout/login_form_item.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/login_form_item_qr.xml b/app/src/main/res/layout/login_form_item_qr.xml
new file mode 100644
index 00000000..ab46a2be
--- /dev/null
+++ b/app/src/main/res/layout/login_form_item_qr.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/login_platform_item.xml b/app/src/main/res/layout/login_platform_item.xml
new file mode 100644
index 00000000..a0fb08ae
--- /dev/null
+++ b/app/src/main/res/layout/login_platform_item.xml
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/login_platform_list_fragment.xml b/app/src/main/res/layout/login_platform_list_fragment.xml
new file mode 100644
index 00000000..ebe8c169
--- /dev/null
+++ b/app/src/main/res/layout/login_platform_list_fragment.xml
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/login_progress_fragment.xml b/app/src/main/res/layout/login_progress_fragment.xml
new file mode 100644
index 00000000..553ce03e
--- /dev/null
+++ b/app/src/main/res/layout/login_progress_fragment.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/login_summary_fragment.xml b/app/src/main/res/layout/login_summary_fragment.xml
new file mode 100644
index 00000000..1b7aac65
--- /dev/null
+++ b/app/src/main/res/layout/login_summary_fragment.xml
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/login_summary_item.xml b/app/src/main/res/layout/login_summary_item.xml
new file mode 100644
index 00000000..99f73853
--- /dev/null
+++ b/app/src/main/res/layout/login_summary_item.xml
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_login_sync_error.xml b/app/src/main/res/layout/login_sync_error_fragment.xml
similarity index 56%
rename from app/src/main/res/layout/fragment_login_sync_error.xml
rename to app/src/main/res/layout/login_sync_error_fragment.xml
index 6d629323..fe7cabb3 100644
--- a/app/src/main/res/layout/fragment_login_sync_error.xml
+++ b/app/src/main/res/layout/login_sync_error_fragment.xml
@@ -1,7 +1,12 @@
-
+
+
+
+
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:paddingHorizontal="24dp">
+ tools:srcCompat="@android:drawable/stat_sys_phone_call_forward" />
-
-
-
-
+ tools:text="@string/login_sync_error_subtitle" />
-
-
-
-
-
-
-
\ No newline at end of file
+
diff --git a/app/src/main/res/layout/login_sync_fragment.xml b/app/src/main/res/layout/login_sync_fragment.xml
new file mode 100644
index 00000000..59b0b09c
--- /dev/null
+++ b/app/src/main/res/layout/login_sync_fragment.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/row_login_profile_list_item.xml b/app/src/main/res/layout/row_login_profile_list_item.xml
index 322fad71..550034a3 100644
--- a/app/src/main/res/layout/row_login_profile_list_item.xml
+++ b/app/src/main/res/layout/row_login_profile_list_item.xml
@@ -66,7 +66,7 @@
android:layout_height="24dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
- tools:srcCompat="@drawable/logo_mobidziennik" />
+ tools:srcCompat="@drawable/login_mode_mobidziennik_web" />
-
\ No newline at end of file
+
diff --git a/app/src/main/res/navigation/nav_login.xml b/app/src/main/res/navigation/nav_login.xml
index af47d04f..7feb8fc7 100644
--- a/app/src/main/res/navigation/nav_login.xml
+++ b/app/src/main/res/navigation/nav_login.xml
@@ -1,164 +1,80 @@
+
+
+ android:label="LoginChooserFragment">
+ android:id="@+id/action_loginChooserFragment_to_loginPlatformListFragment"
+ app:destination="@id/loginPlatformListFragment" />
-
-
-
+ android:id="@+id/action_loginChooserFragment_to_loginFormFragment"
+ app:destination="@id/loginFormFragment" />
+ android:id="@+id/loginPlatformListFragment"
+ android:name="pl.szczodrzynski.edziennik.ui.modules.login.LoginPlatformListFragment"
+ android:label="LoginPlatformListFragment">
-
+ android:id="@+id/action_loginPlatformListFragment_to_loginFormFragment"
+ app:destination="@id/loginFormFragment" />
+ android:id="@+id/loginFormFragment"
+ android:name="pl.szczodrzynski.edziennik.ui.modules.login.LoginFormFragment"
+ android:label="LoginFormFragment">
-
-
-
-
+ android:label="LoginProgressFragment">
-
-
+ android:label="LoginSummaryFragment">
+ android:label="LoginSyncFragment">
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:label="LoginSyncErrorFragment">
+
diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml
index 3a16ddf2..63a4607b 100644
--- a/app/src/main/res/values-en/strings.xml
+++ b/app/src/main/res/values-en/strings.xml
@@ -592,8 +592,8 @@
Logging in…
Choose the e-register which your school uses. Later you\'ll be able to add more accounts using different e-registers.
Which e-register do you use?
- (child)
- (parent)
+ (child)
+ (parent)
Add a student
You have to select at least one profile to save in the app.
No profile selected
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 6aa583a9..5eb7fd82 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -626,8 +626,8 @@
Loguję…
Wybierz z jakiego e-dziennika korzysta Twoja szkoła. W późniejszych etapach będziesz mógł dodać kilka kont z różnych e-dzienników.
Z jakiego e-dziennika korzystasz?
- (uczeń)
- (rodzic)
+ (uczeń)
+ (rodzic)
Dodaj ucznia
Musisz wybrać przynajmniej jeden profil, który chcesz zapisać w aplikacji.
Nie wybrałeś żadnego profilu
@@ -1286,4 +1286,34 @@
wczoraj
Jesteś offline. Spróbuj włączyć Wi-Fi lub dane komórkowe.
Połączenie sieciowe
+ Jaki masz e-dziennik w szkole?
+ Wybierz z jakiego e-dziennika korzysta Twoja szkoła. Jeśli masz kilka kont w różnych dziennikach, będziesz mógł je dodać później.
+ Librus/Synergia
+ Zaloguj używając e-maila
+ Musisz posiadać konto Librus Rodzina
+ Zaloguj używając loginu i hasła
+ Użyj loginu w postaci \"9874123u\"
+ Logowanie przez platformę VULCAN
+ Oświata w Radomiu oraz Innowacyjny Tarnobrzeg
+ Vulcan UONET+
+ Użyj tokenu, symbolu i kodu PIN
+ Zarejestruj urządzenie na stronie dziennika Vulcan
+ Użyj e-maila/nazwy użytkownika i hasła
+ Zaloguj danymi, które podajesz na stronie e-dziennika VULCAN
+ MobiDziennik
+ Zaloguj nazwą serwera, loginem i hasłem
+ Podaj dane, których używasz na stronie e-dziennika
+ W jaki sposób się logujesz do dziennika?
+ Wybierz, który obrazek odpowiada temu, który widzisz podczas logowania na stronie internetowej swojego dziennika.\n\nJeżeli Twoja szkoła nie korzysta z żadnej z tych platform miejskich, wybierz pierwszą opcję.
+ Ładowanie listy e-dzienników…
+ Jeśli trwa to za długo, sprawdź swoje połączenie internetowe i zrestartuj aplikację.
+ Zaloguj się - %s
+ Zaloguj się swoim kontem Librus, które działa w oficjalnej aplikacji Librus oraz na stronie portal.librus.pl, w niebieskim formularzu.\n\nJeśli nie masz konta Librus, możesz je założyć na stronie https://portal.librus.pl/rodzina/register.
+ Podaj login otrzymany od szkoły, którym logujesz się do Synergii (fioletowy formularz).\n\nZalecane jest logowanie kontem Portal Librus (używając e-maila) w poprzednim kroku.
+ Zaloguj się do Librusa na komputerze, wybierz zakładkę Aplikacje Mobilne, następnie wpisz otrzymany Token i PIN poniżej.
+ Zaloguj się do dziennika Vulcan na komputerze, wybierz zakładkę Dostęp Mobilny, kliknij przycisk Zarejestruj urządzenie mobilne. Podaj otrzymany Token, Symbol i PIN w polach poniżej.
+ Podaj dane, którymi logujesz się na stronie internetowej dziennika VULCAN lub na miejskiej platformie.
+ Podaj dane, których używasz do logowania na stronie MobiDziennika. Jako adres serwera możesz wpisać adres strony internetowej, na której masz MobiDziennik.
+ Dodaj nowego ucznia
+ Zaloguj konto ucznia/rodzica w aplikacji