diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/App.java b/app/src/main/java/pl/szczodrzynski/edziennik/App.java index 3f9caa41..a8365d5d 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/App.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/App.java @@ -73,7 +73,6 @@ import pl.szczodrzynski.edziennik.data.api.task.EdziennikTask; import pl.szczodrzynski.edziennik.data.db.AppDb; import pl.szczodrzynski.edziennik.data.db.modules.debuglog.DebugLog; import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile; -import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull; import pl.szczodrzynski.edziennik.network.NetworkUtils; import pl.szczodrzynski.edziennik.network.TLSSocketFactory; import pl.szczodrzynski.edziennik.sync.SyncWorker; @@ -139,11 +138,10 @@ public class App extends androidx.multidex.MultiDexApplication implements Config public SharedPreferences appSharedPrefs; // sharedPreferences for APPCONFIG + JOBS STORE public AppConfig appConfig; // APPCONFIG: common for all profiles //public AppProfile profile; // current profile - public JsonObject loginStore = null; public SharedPreferences registerStore; // sharedPreferences for REGISTER //public Register register; // REGISTER for current profile, read from registerStore - public ProfileFull profile; + public Profile profile; public Config config; private static Config mConfig; public static Config getConfig() { @@ -616,15 +614,6 @@ public class App extends androidx.multidex.MultiDexApplication implements Config db.profileDao().add(profile); }); } - public void profileSaveFullAsync(ProfileFull profile) { - AsyncTask.execute(() -> { - profileSaveFull(profile); - }); - } - public void profileSaveFull(ProfileFull profileFull) { - db.profileDao().add(profileFull); - db.loginStoreDao().add(profileFull); - } public void profileLoadById(int id) { profileLoadById(id, false); @@ -638,7 +627,7 @@ public class App extends androidx.multidex.MultiDexApplication implements Config return; }*/ if (profile == null || profile.getId() != id) { - profile = db.profileDao().getFullByIdNow(id); + profile = db.profileDao().getByIdNow(id); /*if (profile == null) { profileLoadById(id); return; @@ -658,12 +647,6 @@ public class App extends androidx.multidex.MultiDexApplication implements Config } } - public void profileLoad(ProfileFull profile) { - MainActivity.Companion.setUseOldMessages(profile.getLoginStoreType() == LOGIN_TYPE_MOBIDZIENNIK && appConfig.mobidziennikOldMessages == 1); - this.profile = profile; - profileId = profile.getId(); - } - /*public void profileRemove(int id) { Profile profile = db.profileDao().getFullByIdNow(id); @@ -703,11 +686,13 @@ public class App extends androidx.multidex.MultiDexApplication implements Config }*/ public int profileFirstId() { - return db.profileDao().getFirstId(); + Integer id = db.profileDao().getFirstId(); + return id == null ? 1 : id; } public int profileLastId() { - return db.profileDao().getLastId(); + Integer id = db.profileDao().getLastId(); + return id == null ? 1 : id; } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt b/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt index c3206cbe..5ab046bf 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt @@ -69,6 +69,7 @@ fun JsonObject?.getString(key: String): String? = get(key)?.let { if (it.isJsonN fun JsonObject?.getInt(key: String): Int? = get(key)?.let { if (it.isJsonNull) null else it.asInt } fun JsonObject?.getLong(key: String): Long? = get(key)?.let { if (it.isJsonNull) null else it.asLong } fun JsonObject?.getFloat(key: String): Float? = get(key)?.let { if(it.isJsonNull) null else it.asFloat } +fun JsonObject?.getChar(key: String): Char? = get(key)?.let { if(it.isJsonNull) null else it.asCharacter } fun JsonObject?.getJsonObject(key: String): JsonObject? = get(key)?.let { if (it.isJsonNull) null else it.asJsonObject } fun JsonObject?.getJsonArray(key: String): JsonArray? = get(key)?.let { if (it.isJsonNull) null else it.asJsonArray } @@ -77,10 +78,23 @@ fun JsonObject?.getString(key: String, defaultValue: String): String = get(key)? fun JsonObject?.getInt(key: String, defaultValue: Int): Int = get(key)?.let { if (it.isJsonNull) defaultValue else it.asInt } ?: defaultValue fun JsonObject?.getLong(key: String, defaultValue: Long): Long = get(key)?.let { if (it.isJsonNull) defaultValue else it.asLong } ?: defaultValue fun JsonObject?.getFloat(key: String, defaultValue: Float): Float = get(key)?.let { if(it.isJsonNull) defaultValue else it.asFloat } ?: defaultValue +fun JsonObject?.getChar(key: String, defaultValue: Char): Char = get(key)?.let { if(it.isJsonNull) defaultValue else it.asCharacter } ?: defaultValue fun JsonObject?.getJsonObject(key: String, defaultValue: JsonObject): JsonObject = get(key)?.let { if (it.isJsonNull) defaultValue else it.asJsonObject } ?: defaultValue fun JsonObject?.getJsonArray(key: String, defaultValue: JsonArray): JsonArray = get(key)?.let { if (it.isJsonNull) defaultValue else it.asJsonArray } ?: defaultValue -fun JsonArray?.asJsonObjectList() = this?.map { it.asJsonObject } +operator fun JsonObject.set(key: String, value: JsonElement) = this.add(key, value) +operator fun JsonObject.set(key: String, value: Boolean) = this.addProperty(key, value) +operator fun JsonObject.set(key: String, value: String?) = this.addProperty(key, value) +operator fun JsonObject.set(key: String, value: Number) = this.addProperty(key, value) +operator fun JsonObject.set(key: String, value: Char) = this.addProperty(key, value) + +operator fun Profile.set(key: String, value: JsonElement) = this.studentData.add(key, value) +operator fun Profile.set(key: String, value: Boolean) = this.studentData.addProperty(key, value) +operator fun Profile.set(key: String, value: String?) = this.studentData.addProperty(key, value) +operator fun Profile.set(key: String, value: Number) = this.studentData.addProperty(key, value) +operator fun Profile.set(key: String, value: Char) = this.studentData.addProperty(key, value) + +fun JsonArray.asJsonObjectList() = this.map { it.asJsonObject } fun CharSequence?.isNotNullNorEmpty(): Boolean { return this != null && this.isNotEmpty() @@ -233,10 +247,7 @@ fun colorFromCssName(name: String): Int { }.toInt() } -fun MutableList.filterOutArchived(): MutableList { - this.removeAll { it.archived } - return this -} +fun List.filterOutArchived() = this.filter { !it.archived } fun Activity.isStoragePermissionGranted(): Boolean { return if (Build.VERSION.SDK_INT >= 23) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt b/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt index 726d79d1..5b648a6c 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt @@ -41,6 +41,7 @@ import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode import pl.droidsonroids.gif.GifDrawable import pl.szczodrzynski.edziennik.data.api.events.* +import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.Signing import pl.szczodrzynski.edziennik.data.api.task.EdziennikTask import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata.* @@ -321,6 +322,10 @@ class MainActivity : AppCompatActivity() { removeAllItems() toggleGroupEnabled = false textInputEnabled = false + onCloseListener = { + if (!app.config.ui.bottomSheetOpened) + app.config.ui.bottomSheetOpened = true + } } drawer.apply { @@ -328,7 +333,6 @@ class MainActivity : AppCompatActivity() { drawerProfileListEmptyListener = { app.config.loginFinished = false - app.saveConfig("loginFinished") profileListEmptyListener() } drawerItemSelectedListener = { id, position, drawerItem -> @@ -368,10 +372,8 @@ class MainActivity : AppCompatActivity() { if (!profileListEmpty) { handleIntent(intent?.extras) } - app.db.profileDao().allFull.observe(this, Observer { profiles -> - // TODO fix weird -1 profiles ??? - profiles.removeAll { it.id < 0 } - drawer.setProfileList(profiles) + app.db.profileDao().all.observe(this, Observer { profiles -> + drawer.setProfileList(profiles.filter { it.id >= 0 }.toMutableList()) if (profileListEmpty) { profileListEmpty = false handleIntent(intent?.extras) @@ -505,13 +507,6 @@ class MainActivity : AppCompatActivity() { .withIcon(CommunityMaterial.Icon.cmd_android_studio) .withOnClickListener(View.OnClickListener { loadTarget(DRAWER_ITEM_DEBUG) }) } - - EventBus.getDefault().register(this) - } - - override fun onDestroy() { - EventBus.getDefault().unregister(this) - super.onDestroy() } var profileListEmptyListener = { @@ -520,9 +515,6 @@ class MainActivity : AppCompatActivity() { private var profileSettingClickListener = { id: Int, view: View? -> when (id) { DRAWER_PROFILE_ADD_NEW -> { - LoginActivity.privacyPolicyAccepted = true - // else it would try to navigateUp onBackPressed, which it can't do. There is no parent fragment - LoginActivity.firstCompleted = false profileListEmptyListener() } DRAWER_PROFILE_SYNC_ALL -> { @@ -601,6 +593,7 @@ class MainActivity : AppCompatActivity() { } @Subscribe(threadMode = ThreadMode.MAIN, sticky = true) fun onApiTaskErrorEvent(event: ApiTaskErrorEvent) { + EventBus.getDefault().removeStickyEvent(event) navView.toolbar.apply { subtitleFormat = R.string.toolbar_subtitle subtitleFormatWithUnread = R.plurals.toolbar_subtitle_with_unread @@ -754,10 +747,12 @@ class MainActivity : AppCompatActivity() { val filter = IntentFilter() filter.addAction(Intent.ACTION_MAIN) registerReceiver(intentReceiver, filter) + EventBus.getDefault().register(this) super.onResume() } override fun onPause() { unregisterReceiver(intentReceiver) + EventBus.getDefault().unregister(this) super.onPause() } @@ -817,7 +812,6 @@ class MainActivity : AppCompatActivity() { this.runOnUiThread { if (app.profile == null) { - LoginActivity.firstCompleted = false if (app.config.loginFinished) { // this shouldn't run profileListEmptyListener() @@ -1101,6 +1095,7 @@ class MainActivity : AppCompatActivity() { } } + fun error(error: ApiError) = errorSnackbar.addError(error).show() fun snackbar(text: String, actionText: String? = null, onClick: (() -> Unit)? = null) = mainSnackbar.snackbar(text, actionText, onClick) fun snackbarDismiss() = mainSnackbar.dismiss() } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/Notifier.java b/app/src/main/java/pl/szczodrzynski/edziennik/Notifier.java index 0b2d01b5..0b878b53 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/Notifier.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/Notifier.java @@ -17,7 +17,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull; import pl.szczodrzynski.edziennik.receivers.BootReceiver; import pl.szczodrzynski.edziennik.utils.models.Date; import pl.szczodrzynski.edziennik.utils.models.Time; @@ -221,10 +220,8 @@ public class Notifier { app.appConfig.notifications.add(notification); } - public void postAll(ProfileFull profile) { + public void postAll() { Collections.sort(app.appConfig.notifications, (o1, o2) -> (o2.addedDate - o1.addedDate > 0) ? 1 : (o2.addedDate - o1.addedDate < 0) ? -1 : 0); - if (profile != null && !profile.getSyncNotifications()) - return; if (app.appConfig.notifications.size() > 40) { app.appConfig.notifications.subList(40, app.appConfig.notifications.size() - 1).clear(); diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/config/Config.kt b/app/src/main/java/pl/szczodrzynski/edziennik/config/Config.kt index d96dea61..9977fe10 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/config/Config.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/config/Config.kt @@ -49,6 +49,11 @@ class Config(val db: AppDb) : CoroutineScope, AbstractConfig { get() { mLoginFinished = mLoginFinished ?: values.get("loginFinished", false); return mLoginFinished ?: false } set(value) { set("loginFinished", value); mLoginFinished = value } + private var mPrivacyPolicyAccepted: Boolean? = null + var privacyPolicyAccepted: Boolean + get() { mPrivacyPolicyAccepted = mPrivacyPolicyAccepted ?: values.get("privacyPolicyAccepted", false); return mPrivacyPolicyAccepted ?: false } + set(value) { set("privacyPolicyAccepted", value); mPrivacyPolicyAccepted = value } + private var mDevModePassword: String? = null var devModePassword: String? get() { mDevModePassword = mDevModePassword ?: values.get("devModePassword", null as String?); return mDevModePassword } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/ApiService.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/ApiService.kt index b14e8e7b..db677b5b 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/ApiService.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/ApiService.kt @@ -18,7 +18,7 @@ import pl.szczodrzynski.edziennik.data.api.events.requests.TaskCancelRequest import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.data.api.task.* -import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull +import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile import pl.szczodrzynski.edziennik.utils.Utils.d import kotlin.math.min import kotlin.math.roundToInt @@ -38,7 +38,7 @@ class ApiService : Service() { private val app by lazy { applicationContext as App } - private val syncingProfiles = mutableListOf() + private val syncingProfiles = mutableListOf() private val finishingTaskQueue = mutableListOf( SzkolnyTask.sync(syncingProfiles), diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/DataNotifications.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/DataNotifications.kt index d416e858..47042a80 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/DataNotifications.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/DataNotifications.kt @@ -47,7 +47,6 @@ class DataNotifications(val data: Data) { val today = Date.getToday() val todayValue = today.value - profile.currentSemester = profile.dateToSemester(today) for (lesson in app.db.timetableDao().getNotNotifiedNow(profileId)) { val text = app.getString(R.string.notification_lesson_change_format, lesson.getDisplayChangeType(app), if (lesson.displayDate == null) "" else lesson.displayDate!!.formattedString, lesson.changeSubjectName) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/LoginMethods.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/LoginMethods.kt index 6f73a59a..c9a2568f 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/LoginMethods.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/LoginMethods.kt @@ -23,7 +23,7 @@ import pl.szczodrzynski.edziennik.data.api.models.LoginMethod // vulcan // mobireg -const val SYNERGIA_API_ENABLED = true +const val SYNERGIA_API_ENABLED = false diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Regexes.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Regexes.kt index 2de3cca5..b442d5c4 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Regexes.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Regexes.kt @@ -74,7 +74,7 @@ object Regexes { """id="ctl00_CzyRodzic" value="([01])" />""".toRegex() } val IDZIENNIK_LOGIN_FIRST_SCHOOL_YEAR by lazy { - """name="ctl00\${"$"}dxComboRokSzkolny".+?selected="selected".*?value="([0-9]+)">([0-9/]+)<""".toRegex(DOT_MATCHES_ALL) + """name="ctl00\\${'$'}dxComboRokSzkolny".+?selected="selected".*?value="([0-9]+)">([0-9]+)/([0-9]+)<""".toRegex(DOT_MATCHES_ALL) } val IDZIENNIK_LOGIN_FIRST_STUDENT_SELECT by lazy { """""".toRegex(DOT_MATCHES_ALL) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/DataEdudziennik.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/DataEdudziennik.kt index 787e7c5c..a363848c 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/DataEdudziennik.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/DataEdudziennik.kt @@ -32,6 +32,8 @@ class DataEdudziennik(app: App, profile: Profile?, loginStore: LoginStore) : Dat } } + override fun generateUserCode() = "$schoolName:$loginEmail:${studentId?.crc32()}" + private var mLoginEmail: String? = null var loginEmail: String? get() { mLoginEmail = mLoginEmail ?: loginStore.getLoginData("email", null); return mLoginEmail } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/firstlogin/EdudziennikFirstLogin.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/firstlogin/EdudziennikFirstLogin.kt index e9b9156c..4268944f 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/firstlogin/EdudziennikFirstLogin.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/firstlogin/EdudziennikFirstLogin.kt @@ -5,6 +5,7 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.firstlogin import org.greenrobot.eventbus.EventBus +import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_EDUDZIENNIK import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_ACCOUNT_NAME_START import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_STUDENTS_START import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik @@ -15,7 +16,7 @@ import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile import pl.szczodrzynski.edziennik.fixName import pl.szczodrzynski.edziennik.get import pl.szczodrzynski.edziennik.getShortName -import pl.szczodrzynski.edziennik.utils.Utils +import pl.szczodrzynski.edziennik.set class EdudziennikFirstLogin(val data: DataEdudziennik, val onSuccess: () -> Unit) { companion object { @@ -26,25 +27,35 @@ class EdudziennikFirstLogin(val data: DataEdudziennik, val onSuccess: () -> Unit private val profileList = mutableListOf() init { + val loginStoreId = data.loginStore.id + val loginStoreType = LOGIN_TYPE_EDUDZIENNIK + var firstProfileId = loginStoreId + EdudziennikLoginWeb(data) { web.webGet(TAG, "") { text -> - val accountName = EDUDZIENNIK_ACCOUNT_NAME_START.find(text)?.get(1)?.fixName() + val accountNameLong = EDUDZIENNIK_ACCOUNT_NAME_START.find(text)?.get(1)?.fixName() EDUDZIENNIK_STUDENTS_START.findAll(text).forEach { val studentId = it[1] - val studentName = it[2].fixName() + val studentNameLong = it[2].fixName() - if (studentId.isBlank() || studentName.isBlank()) return@forEach + if (studentId.isBlank() || studentNameLong.isBlank()) return@forEach - val profile = Profile() - profile.studentNameLong = studentName - profile.studentNameShort = studentName.getShortName() - profile.accountNameLong = if (studentName == accountName) null else accountName - profile.studentSchoolYear = Utils.getCurrentSchoolYear() - profile.name = studentName - profile.subname = data.loginEmail - profile.empty = true - profile.putStudentData("studentId", studentId) + val studentNameShort = studentNameLong.getShortName() + val accountName = if (accountNameLong == studentNameLong) null else accountNameLong + + val profile = Profile( + firstProfileId++, + loginStoreId, + loginStoreType, + studentNameLong, + data.loginEmail, + studentNameLong, + studentNameShort, + accountName + ).apply { + studentData["studentId"] = studentId + } profileList.add(profile) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/DataIdziennik.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/DataIdziennik.kt index c3bd925a..e852f70b 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/DataIdziennik.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/DataIdziennik.kt @@ -41,6 +41,8 @@ class DataIdziennik(app: App, profile: Profile?, loginStore: LoginStore) : Data( loginMethods += LOGIN_METHOD_IDZIENNIK_API } + override fun generateUserCode() = "$webSchoolName:$webUsername:$registerId" + private var mLoginExpiryTime: Long? = null var loginExpiryTime: Long get() { mLoginExpiryTime = mLoginExpiryTime ?: loginStore.getLoginData("loginExpiryTime", 0L); return mLoginExpiryTime ?: 0L } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/api/IdziennikApiCurrentRegister.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/api/IdziennikApiCurrentRegister.kt index 1970c225..2fcfbd71 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/api/IdziennikApiCurrentRegister.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/api/IdziennikApiCurrentRegister.kt @@ -25,9 +25,6 @@ class IdziennikApiCurrentRegister(override val data: DataIdziennik, } init { - data.profile?.luckyNumber = -1 - data.profile?.luckyNumberDate = null - apiGet(TAG, IDZIENNIK_API_CURRENT_REGISTER) { json -> if (json !is JsonObject) { onSuccess() @@ -37,9 +34,9 @@ class IdziennikApiCurrentRegister(override val data: DataIdziennik, var nextSync = System.currentTimeMillis() + 14*DAY*1000 val settings = json.getJsonObject("ustawienia")?.apply { - profile?.dateSemester1Start = getString("poczatekSemestru1")?.let { Date.fromY_m_d(it) } - profile?.dateSemester2Start = getString("koniecSemestru1")?.let { Date.fromY_m_d(it).stepForward(0, 0, 1) } - profile?.dateYearEnd = getString("koniecSemestru2")?.let { Date.fromY_m_d(it) } + getString("poczatekSemestru1")?.let { profile?.dateSemester1Start = Date.fromY_m_d(it) } + getString("koniecSemestru1")?.let { profile?.dateSemester2Start = Date.fromY_m_d(it).stepForward(0, 0, 1) } + getString("koniecSemestru2")?.let { profile?.dateYearEnd = Date.fromY_m_d(it) } } json.getInt("szczesliwyNumerek")?.let { luckyNumber -> diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetMessage.kt index b0d372de..e1b63c15 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetMessage.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetMessage.kt @@ -57,7 +57,7 @@ class IdziennikWebGetMessage( recipientObject.readDate = if (readDateString.isNullOrBlank()) System.currentTimeMillis() else Date.fromIso(readDateString) - recipientObject.fullName = profile.accountNameLong ?: profile.studentNameLong + recipientObject.fullName = profile.accountName ?: profile.studentNameLong data.messageRecipientList.add(recipientObject) message.addRecipient(recipientObject) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebTimetable.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebTimetable.kt index d85e5692..dbef2a62 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebTimetable.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebTimetable.kt @@ -51,12 +51,12 @@ class IdziennikWebTimetable(override val data: DataIdziennik, return@webApiGet } - json.getJsonArray("GodzinyLekcyjne")?.asJsonObjectList()?.forEach { range -> + json.getJsonArray("GodzinyLekcyjne")?.asJsonObjectList()?.forEachIndexed { index, range -> val lessonRange = LessonRange( profileId, - range.getInt("LiczbaP") ?: return@forEach, - range.getString("Poczatek")?.let { Time.fromH_m(it) } ?: return@forEach, - range.getString("Koniec")?.let { Time.fromH_m(it) } ?: return@forEach + index + 1, + range.getString("Poczatek")?.let { Time.fromH_m(it) } ?: return@forEachIndexed, + range.getString("Koniec")?.let { Time.fromH_m(it) } ?: return@forEachIndexed ) data.lessonRanges[lessonRange.lessonNumber] = lessonRange } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/firstlogin/IdziennikFirstLogin.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/firstlogin/IdziennikFirstLogin.kt index 6ef9950f..3f1f6252 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/firstlogin/IdziennikFirstLogin.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/firstlogin/IdziennikFirstLogin.kt @@ -7,6 +7,7 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.firstlogin import org.greenrobot.eventbus.EventBus import pl.szczodrzynski.edziennik.data.api.ERROR_LOGIN_IDZIENNIK_FIRST_NO_SCHOOL_YEAR import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_SETTINGS +import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_IDZIENNIK import pl.szczodrzynski.edziennik.data.api.Regexes import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb @@ -16,6 +17,7 @@ import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile import pl.szczodrzynski.edziennik.fixName import pl.szczodrzynski.edziennik.get +import pl.szczodrzynski.edziennik.set import pl.szczodrzynski.edziennik.swapFirstLastName class IdziennikFirstLogin(val data: DataIdziennik, val onSuccess: () -> Unit) { @@ -27,6 +29,10 @@ class IdziennikFirstLogin(val data: DataIdziennik, val onSuccess: () -> Unit) { private val profileList = mutableListOf() init { + val loginStoreId = data.loginStore.id + val loginStoreType = LOGIN_TYPE_IDZIENNIK + var firstProfileId = loginStoreId + IdziennikLoginWeb(data) { web.webGet(TAG, IDZIENNIK_WEB_SETTINGS) { text -> //val accounts = json.getJsonArray("accounts") @@ -34,12 +40,15 @@ class IdziennikFirstLogin(val data: DataIdziennik, val onSuccess: () -> Unit) { val isParent = Regexes.IDZIENNIK_LOGIN_FIRST_IS_PARENT.find(text)?.get(1) != "0" val accountNameLong = if (isParent) Regexes.IDZIENNIK_LOGIN_FIRST_ACCOUNT_NAME.find(text)?.get(1)?.swapFirstLastName()?.fixName() - else - null + else null + var schoolYearStart: Int? = null + var schoolYearEnd: Int? = null var schoolYearName: String? = null - val schoolYear = Regexes.IDZIENNIK_LOGIN_FIRST_SCHOOL_YEAR.find(text)?.let { - schoolYearName = it[2] + val schoolYearId = Regexes.IDZIENNIK_LOGIN_FIRST_SCHOOL_YEAR.find(text)?.let { + schoolYearName = it[2]+"/"+it[3] + schoolYearStart = it[2].toIntOrNull() + schoolYearEnd = it[3].toIntOrNull() it[1].toIntOrNull() } ?: run { data.error(ApiError(TAG, ERROR_LOGIN_IDZIENNIK_FIRST_NO_SCHOOL_YEAR) @@ -57,18 +66,26 @@ class IdziennikFirstLogin(val data: DataIdziennik, val onSuccess: () -> Unit) { val lastName = match[4] val className = match[5] + " " + match[6] - val profile = Profile() - profile.studentNameLong = "$firstName $lastName".fixName() - profile.studentNameShort = "$firstName ${lastName[0]}.".fixName() - profile.accountNameLong = accountNameLong - profile.studentClassName = className - profile.studentSchoolYear = schoolYearName - profile.name = profile.studentNameLong - profile.subname = data.webUsername - profile.empty = true - profile.putStudentData("studentId", studentId) - profile.putStudentData("registerId", registerId) - profile.putStudentData("schoolYearId", schoolYear) + val studentNameLong = "$firstName $lastName".fixName() + val studentNameShort = "$firstName ${lastName[0]}.".fixName() + val accountName = if (accountNameLong == studentNameLong) null else accountNameLong + + val profile = Profile( + firstProfileId++, + loginStoreId, + loginStoreType, + studentNameLong, + data.webUsername, + studentNameLong, + studentNameShort, + accountName + ).apply { + schoolYearStart?.let { studentSchoolYearStart = it } + studentClassName = className + studentData["studentId"] = studentId + studentData["registerId"] = registerId + studentData["schoolYearId"] = schoolYearId + } profileList.add(profile) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/DataLibrus.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/DataLibrus.kt index a4ca17ba..98aa2a56 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/DataLibrus.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/DataLibrus.kt @@ -51,6 +51,8 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app } } + override fun generateUserCode() = "$schoolName:$apiLogin" + fun getColor(id: Int?): Int { return when (id) { 1 -> 0xFFF0E68C diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAnnouncements.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAnnouncements.kt index 0236fcc9..e75301b0 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAnnouncements.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAnnouncements.kt @@ -21,7 +21,7 @@ class LibrusApiAnnouncements(override val data: DataLibrus, init { data.profile?.also { profile -> apiGet(TAG, "SchoolNotices") { json -> - val announcements = json.getJsonArray("SchoolNotices").asJsonObjectList() + val announcements = json.getJsonArray("SchoolNotices")?.asJsonObjectList() announcements?.forEach { announcement -> val longId = announcement.getString("Id") ?: return@forEach diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAttendanceTypes.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAttendanceTypes.kt index 2d85e1fa..5fc3b191 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAttendanceTypes.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAttendanceTypes.kt @@ -20,7 +20,7 @@ class LibrusApiAttendanceTypes(override val data: DataLibrus, init { apiGet(TAG, "Attendances/Types") { json -> - val attendanceTypes = json.getJsonArray("Types").asJsonObjectList() + val attendanceTypes = json.getJsonArray("Types")?.asJsonObjectList() attendanceTypes?.forEach { attendanceType -> val id = attendanceType.getLong("Id") ?: return@forEach diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAttendances.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAttendances.kt index bbc0d26e..8c99ad76 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAttendances.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAttendances.kt @@ -27,7 +27,7 @@ class LibrusApiAttendances(override val data: DataLibrus, } apiGet(TAG, "Attendances") { json -> - val attendances = json.getJsonArray("Attendances").asJsonObjectList() + val attendances = json.getJsonArray("Attendances")?.asJsonObjectList() attendances?.forEach { attendance -> val id = Utils.strToInt((attendance.getString("Id") ?: return@forEach) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiClasses.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiClasses.kt index 6f497021..73de998b 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiClasses.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiClasses.kt @@ -38,6 +38,8 @@ class LibrusApiClasses(override val data: DataLibrus, teacherId ) + data.profile?.studentClassName = name + data.teamList.put(id, teamObject) data.unitId = studentClass.getJsonObject("Unit").getLong("Id") ?: 0L diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiClassrooms.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiClassrooms.kt index 422321ca..e072ad5c 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiClassrooms.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiClassrooms.kt @@ -19,7 +19,7 @@ class LibrusApiClassrooms(override val data: DataLibrus, init { apiGet(TAG, "Classrooms") { json -> - val classrooms = json.getJsonArray("Classrooms").asJsonObjectList() + val classrooms = json.getJsonArray("Classrooms")?.asJsonObjectList() classrooms?.forEach { classroom -> val id = classroom.getLong("Id") ?: return@forEach diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiEventTypes.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiEventTypes.kt index 48c479c1..a44864fb 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiEventTypes.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiEventTypes.kt @@ -18,7 +18,7 @@ class LibrusApiEventTypes(override val data: DataLibrus, init { apiGet(TAG, "HomeWorks/Categories") { json -> - val eventTypes = json.getJsonArray("Categories").asJsonObjectList() + val eventTypes = json.getJsonArray("Categories")?.asJsonObjectList() eventTypes?.forEach { eventType -> val id = eventType.getLong("Id") ?: return@forEach diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiEvents.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiEvents.kt index 43cddd54..54acaddf 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiEvents.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiEvents.kt @@ -28,7 +28,7 @@ class LibrusApiEvents(override val data: DataLibrus, } apiGet(TAG, "HomeWorks") { json -> - val events = json.getJsonArray("HomeWorks").asJsonObjectList() + val events = json.getJsonArray("HomeWorks")?.asJsonObjectList() events?.forEach { event -> val id = event.getLong("Id") ?: return@forEach diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiGrades.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiGrades.kt index 5cbc67e5..7640072a 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiGrades.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiGrades.kt @@ -21,7 +21,7 @@ class LibrusApiGrades(override val data: DataLibrus, init { data.profile?.also { profile -> apiGet(TAG, "Grades") { json -> - val grades = json.getJsonArray("Grades").asJsonObjectList() + val grades = json.getJsonArray("Grades")?.asJsonObjectList() grades?.forEach { grade -> val id = grade.getLong("Id") ?: return@forEach diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiHomework.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiHomework.kt index 16bbac1c..7519cddd 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiHomework.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiHomework.kt @@ -22,7 +22,7 @@ class LibrusApiHomework(override val data: DataLibrus, init { apiGet(TAG, "HomeWorkAssignments") { json -> - val homeworkList = json.getJsonArray("HomeWorkAssignments").asJsonObjectList() + val homeworkList = json.getJsonArray("HomeWorkAssignments")?.asJsonObjectList() homeworkList?.forEach { homework -> val id = homework.getLong("Id") ?: return@forEach diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiLuckyNumber.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiLuckyNumber.kt index a272a5dd..1e825c6c 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiLuckyNumber.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiLuckyNumber.kt @@ -23,9 +23,6 @@ class LibrusApiLuckyNumber(override val data: DataLibrus, } init { - data.profile?.luckyNumber = -1 - data.profile?.luckyNumberDate = null - var nextSync = System.currentTimeMillis() + 2*DAY*1000 apiGet(TAG, "LuckyNumbers") { json -> diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiMe.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiMe.kt index c226cf58..5e697a4c 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiMe.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiMe.kt @@ -24,7 +24,7 @@ class LibrusApiMe(override val data: DataLibrus, data.isPremium = account?.getBoolean("IsPremium") == true || account?.getBoolean("IsPremiumDemo") == true val isParent = account?.getInt("GroupId") == 5 - data.profile?.accountNameLong = + data.profile?.accountName = if (isParent) buildFullName(account?.getString("FirstName"), account?.getString("LastName")) else null diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiNoticeTypes.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiNoticeTypes.kt index 14f251b6..2c5bd0ea 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiNoticeTypes.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiNoticeTypes.kt @@ -18,7 +18,7 @@ class LibrusApiNoticeTypes(override val data: DataLibrus, init { apiGet(TAG, "Notes/Categories") { json -> - val noticeTypes = json.getJsonArray("Categories").asJsonObjectList() + val noticeTypes = json.getJsonArray("Categories")?.asJsonObjectList() noticeTypes?.forEach { noticeType -> val id = noticeType.getLong("Id") ?: return@forEach diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiNotices.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiNotices.kt index 7d2036ca..0743d979 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiNotices.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiNotices.kt @@ -26,7 +26,7 @@ class LibrusApiNotices(override val data: DataLibrus, } apiGet(TAG, "Notes") { json -> - val notes = json.getJsonArray("Notes").asJsonObjectList() + val notes = json.getJsonArray("Notes")?.asJsonObjectList() notes?.forEach { note -> val id = note.getLong("Id") ?: return@forEach diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiPtMeetings.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiPtMeetings.kt index ab78a6e8..11b6acde 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiPtMeetings.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiPtMeetings.kt @@ -22,7 +22,7 @@ class LibrusApiPtMeetings(override val data: DataLibrus, init { apiGet(TAG, "ParentTeacherConferences") { json -> - val ptMeetings = json.getJsonArray("ParentTeacherConferences").asJsonObjectList() + val ptMeetings = json.getJsonArray("ParentTeacherConferences")?.asJsonObjectList() ptMeetings?.forEach { meeting -> val id = meeting.getLong("Id") ?: return@forEach diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiSubjects.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiSubjects.kt index 4c383933..75b45365 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiSubjects.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiSubjects.kt @@ -18,7 +18,7 @@ class LibrusApiSubjects(override val data: DataLibrus, init { apiGet(TAG, "Subjects") { json -> - val subjects = json.getJsonArray("Subjects").asJsonObjectList() + val subjects = json.getJsonArray("Subjects")?.asJsonObjectList() subjects?.forEach { subject -> val id = subject.getLong("Id") ?: return@forEach diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTeacherFreeDayTypes.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTeacherFreeDayTypes.kt index 88c8ce14..48ef7c6e 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTeacherFreeDayTypes.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTeacherFreeDayTypes.kt @@ -18,7 +18,7 @@ class LibrusApiTeacherFreeDayTypes(override val data: DataLibrus, init { apiGet(TAG, "TeacherFreeDays/Types") { json -> - val teacherAbsenceTypes = json.getJsonArray("Types").asJsonObjectList() + val teacherAbsenceTypes = json.getJsonArray("Types")?.asJsonObjectList() teacherAbsenceTypes?.forEach { teacherAbsenceType -> val id = teacherAbsenceType.getLong("Id") ?: return@forEach diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTeacherFreeDays.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTeacherFreeDays.kt index 1069ffa3..b86db95f 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTeacherFreeDays.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTeacherFreeDays.kt @@ -27,7 +27,7 @@ class LibrusApiTeacherFreeDays(override val data: DataLibrus, } apiGet(TAG, "TeacherFreeDays") { json -> - val teacherAbsences = json.getJsonArray("TeacherFreeDays").asJsonObjectList() + val teacherAbsences = json.getJsonArray("TeacherFreeDays")?.asJsonObjectList() teacherAbsences?.forEach { teacherAbsence -> val id = teacherAbsence.getLong("Id") ?: return@forEach diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiUnits.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiUnits.kt index be4b0087..5532db5c 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiUnits.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiUnits.kt @@ -23,7 +23,7 @@ class LibrusApiUnits(override val data: DataLibrus, } apiGet(TAG, "Units") { json -> - val units = json.getJsonArray("Units").asJsonObjectList() + val units = json.getJsonArray("Units")?.asJsonObjectList() units?.singleOrNull { it.getLong("Id") == data.unitId }?.also { unit -> val startPoints = unit.getJsonObject("BehaviourGradesSettings")?.getJsonObject("StartPoints") diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiUsers.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiUsers.kt index fb95c9ac..f63dcfa0 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiUsers.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiUsers.kt @@ -18,7 +18,7 @@ class LibrusApiUsers(override val data: DataLibrus, init { apiGet(TAG, "Users") { json -> - val users = json.getJsonArray("Users").asJsonObjectList() + val users = json.getJsonArray("Users")?.asJsonObjectList() users?.forEach { user -> val id = user.getLong("Id") ?: return@forEach diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiVirtualClasses.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiVirtualClasses.kt index e8249978..f9792cb7 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiVirtualClasses.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiVirtualClasses.kt @@ -18,7 +18,7 @@ class LibrusApiVirtualClasses(override val data: DataLibrus, init { apiGet(TAG, "VirtualClasses") { json -> - val virtualClasses = json.getJsonArray("VirtualClasses").asJsonObjectList() + val virtualClasses = json.getJsonArray("VirtualClasses")?.asJsonObjectList() virtualClasses?.forEach { virtualClass -> val id = virtualClass.getLong("Id") ?: return@forEach diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetMessage.kt index 5bdfc42d..16d610ad 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetMessage.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetMessage.kt @@ -110,7 +110,7 @@ class LibrusMessagesGetMessage( messageObject.id ) - messageRecipientObject.fullName = profile.accountNameLong ?: profile.studentNameLong ?: "" + messageRecipientObject.fullName = profile.accountName ?: profile.studentNameLong ?: "" messageRecipientList.add(messageRecipientObject) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/firstlogin/LibrusFirstLogin.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/firstlogin/LibrusFirstLogin.kt index ea687d29..98ed982d 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/firstlogin/LibrusFirstLogin.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/firstlogin/LibrusFirstLogin.kt @@ -22,6 +22,10 @@ class LibrusFirstLogin(val data: DataLibrus, val onSuccess: () -> Unit) { private val profileList = mutableListOf() init { + val loginStoreId = data.loginStore.id + val loginStoreType = LOGIN_TYPE_LIBRUS + var firstProfileId = loginStoreId + if (data.loginStore.mode == LOGIN_MODE_LIBRUS_EMAIL) { // email login: use Portal for account list LibrusLoginPortal(data) { @@ -55,18 +59,24 @@ class LibrusFirstLogin(val data: DataLibrus, val onSuccess: () -> Unit) { val login = account.getString("login") ?: continue val token = account.getString("accessToken") ?: continue val tokenTime = (accountDataTime ?: 0) + DAY - val name = account.getString("studentName")?.fixName() ?: "" + val studentNameLong = account.getString("studentName").fixName() + val studentNameShort = studentNameLong.getShortName() - val profile = Profile() - profile.studentNameLong = name - profile.studentNameShort = name.getShortName() - profile.name = profile.studentNameLong - profile.subname = data.portalEmail - profile.empty = true - profile.putStudentData("accountId", id) - profile.putStudentData("accountLogin", login) - profile.putStudentData("accountToken", token) - profile.putStudentData("accountTokenTime", tokenTime) + val profile = Profile( + firstProfileId++, + loginStoreId, + loginStoreType, + studentNameLong, + data.portalEmail, + studentNameLong, + studentNameShort, + null + ).apply { + studentData["accountId"] = id + studentData["accountLogin"] = login + studentData["accountToken"] = token + studentData["accountTokenTime"] = tokenTime + } profileList.add(profile) } @@ -80,32 +90,36 @@ class LibrusFirstLogin(val data: DataLibrus, val onSuccess: () -> Unit) { LibrusLoginApi(data) { api.apiGet(TAG, "Me") { json -> - val profile = Profile() - val me = json.getJsonObject("Me") val account = me?.getJsonObject("Account") val user = me?.getJsonObject("User") - profile.putStudentData("isPremium", account?.getBoolean("IsPremium") == true || account?.getBoolean("IsPremiumDemo") == true) + val login = account.getString("Login") + val isParent = account?.getInt("GroupId") in 5..6 - val isParent = account?.getInt("GroupId") == 5 - profile.accountNameLong = - if (isParent) - buildFullName(account?.getString("FirstName"), account?.getString("LastName")) - else null + val studentNameLong = buildFullName(user?.getString("FirstName"), user?.getString("LastName")) + val studentNameShort = studentNameLong.getShortName() + val accountNameLong = if (isParent) + buildFullName(account?.getString("FirstName"), account?.getString("LastName")) + else null - profile.studentNameLong = - buildFullName(user?.getString("FirstName"), user?.getString("LastName")) - - profile.studentNameShort = profile.studentNameLong?.getShortName() - profile.name = profile.studentNameLong - profile.subname = account.getString("Login") - profile.empty = true - profile.putStudentData("accountId", account.getInt("Id") ?: 0) - profile.putStudentData("accountLogin", profile.subname) - profile.putStudentData("accountToken", data.apiAccessToken) - profile.putStudentData("accountRefreshToken", data.apiRefreshToken) - profile.putStudentData("accountTokenTime", data.apiTokenExpiryTime) + val profile = Profile( + firstProfileId++, + loginStoreId, + loginStoreType, + studentNameLong, + login, + studentNameLong, + studentNameShort, + accountNameLong + ).apply { + studentData["isPremium"] = account?.getBoolean("IsPremium") == true || account?.getBoolean("IsPremiumDemo") == true + studentData["accountId"] = account.getInt("Id") ?: 0 + studentData["accountLogin"] = login + studentData["accountToken"] = data.apiAccessToken + studentData["accountTokenTime"] = data.apiTokenExpiryTime + studentData["accountRefreshToken"] = data.apiRefreshToken + } profileList.add(profile) EventBus.getDefault().post(FirstLoginFinishedEvent(profileList, data.loginStore)) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/DataMobidziennik.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/DataMobidziennik.kt index 40ba688d..c024aa6d 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/DataMobidziennik.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/DataMobidziennik.kt @@ -7,9 +7,9 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik import android.util.LongSparseArray import androidx.core.util.isNotEmpty import pl.szczodrzynski.edziennik.App +import pl.szczodrzynski.edziennik.currentTimeUnix import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_MOBIDZIENNIK_WEB import pl.szczodrzynski.edziennik.data.api.models.Data -import pl.szczodrzynski.edziennik.currentTimeUnix import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile import pl.szczodrzynski.edziennik.isNotNullNorEmpty @@ -30,6 +30,8 @@ class DataMobidziennik(app: App, profile: Profile?, loginStore: LoginStore) : Da } } + override fun generateUserCode() = "$loginServerName:$loginUsername:$studentId" + val teachersMap = LongSparseArray() val subjectsMap = LongSparseArray() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiTeams.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiTeams.kt index 309e9cdb..00707c4f 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiTeams.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiTeams.kt @@ -53,6 +53,7 @@ class MobidziennikApiTeams(val data: DataMobidziennik, tableTeams: List? if (team.type == 1) { data.profile?.studentNumber = studentNumber data.teamClass = team + data.profile?.studentClassName = team.name } data.teamList.put(teamId, team) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikLuckyNumberExtractor.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikLuckyNumberExtractor.kt index bee916e7..27823910 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikLuckyNumberExtractor.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikLuckyNumberExtractor.kt @@ -8,31 +8,31 @@ import pl.szczodrzynski.edziennik.data.api.Regexes import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik import pl.szczodrzynski.edziennik.data.db.modules.luckynumber.LuckyNumber import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata -import pl.szczodrzynski.edziennik.get import pl.szczodrzynski.edziennik.utils.models.Date class MobidziennikLuckyNumberExtractor(val data: DataMobidziennik, text: String) { init { - data.profile?.luckyNumber = -1 - data.profile?.luckyNumberDate = null + Regexes.MOBIDZIENNIK_LUCKY_NUMBER.find(text)?.let { + try { + val luckyNumber = it.groupValues[1].toInt() - Regexes.MOBIDZIENNIK_LUCKY_NUMBER.find(text)?.get(1)?.toIntOrNull()?.let { - val luckyNumberObject = LuckyNumber( - data.profileId, - Date.getToday(), - it - ) + val luckyNumberObject = LuckyNumber( + data.profileId, + Date.getToday(), + luckyNumber + ) - data.luckyNumberList.add(luckyNumberObject) - data.metadataList.add( - Metadata( - data.profileId, - Metadata.TYPE_LUCKY_NUMBER, - luckyNumberObject.date.value.toLong(), - data.profile?.empty ?: false, - data.profile?.empty ?: false, - System.currentTimeMillis() - )) + data.luckyNumberList.add(luckyNumberObject) + data.metadataList.add( + Metadata( + data.profileId, + Metadata.TYPE_LUCKY_NUMBER, + luckyNumberObject.date.value.toLong(), + data.profile?.empty ?: false, + data.profile?.empty ?: false, + System.currentTimeMillis() + )) + } catch (_: Exception){} } } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetMessage.kt index 41e22e85..cc93c074 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetMessage.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetMessage.kt @@ -68,7 +68,7 @@ class MobidziennikWebGetMessage( message.id ) - recipient.fullName = profile?.accountNameLong ?: profile?.studentNameLong ?: "" + recipient.fullName = profile?.accountName ?: profile?.studentNameLong ?: "" messageRecipientList.add(recipient) } else { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/firstlogin/MobidziennikFirstLogin.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/firstlogin/MobidziennikFirstLogin.kt index e69aba2f..39ea8fe9 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/firstlogin/MobidziennikFirstLogin.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/firstlogin/MobidziennikFirstLogin.kt @@ -1,13 +1,15 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.firstlogin import org.greenrobot.eventbus.EventBus +import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_MOBIDZIENNIK import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.login.MobidziennikLoginWeb import pl.szczodrzynski.edziennik.data.api.events.FirstLoginFinishedEvent import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile import pl.szczodrzynski.edziennik.fixName -import pl.szczodrzynski.edziennik.utils.Utils +import pl.szczodrzynski.edziennik.set +import pl.szczodrzynski.edziennik.utils.models.Date class MobidziennikFirstLogin(val data: DataMobidziennik, val onSuccess: () -> Unit) { companion object { @@ -18,6 +20,10 @@ class MobidziennikFirstLogin(val data: DataMobidziennik, val onSuccess: () -> Un private val profileList = mutableListOf() init { + val loginStoreId = data.loginStore.id + val loginStoreType = LOGIN_TYPE_MOBIDZIENNIK + var firstProfileId = loginStoreId + MobidziennikLoginWeb(data) { web.webGet(TAG, "/api/zrzutbazy") { text -> val tables = text.split("T@B#LA") @@ -32,6 +38,21 @@ class MobidziennikFirstLogin(val data: DataMobidziennik, val onSuccess: () -> Un } } + var dateSemester1Start: Date? = null + var dateSemester2Start: Date? = null + var dateYearEnd: Date? = null + for (row in tables[3].split("\n")) { + if (row.isEmpty()) + continue + val cols = row.split("|") + + when (cols[1]) { + "semestr1_poczatek" -> dateSemester1Start = Date.fromYmd(cols[3]) + "semestr2_poczatek" -> dateSemester2Start = Date.fromYmd(cols[3]) + "koniec_roku_szkolnego" -> dateYearEnd = Date.fromYmd(cols[3]) + } + } + tables[8].split("\n").forEach { student -> if (student.isEmpty()) return@forEach @@ -39,15 +60,28 @@ class MobidziennikFirstLogin(val data: DataMobidziennik, val onSuccess: () -> Un if (student1.size == 2) return@forEach - val profile = Profile() - profile.studentNameLong = "${student1[2]} ${student1[4]}".fixName() - profile.studentNameShort = "${student1[2]} ${student1[4][0]}.".fixName() - profile.accountNameLong = if (accountNameLong == profile.studentNameLong) null else accountNameLong - profile.studentSchoolYear = Utils.getCurrentSchoolYear() - profile.name = profile.studentNameLong - profile.subname = data.loginUsername - profile.empty = true - profile.putStudentData("studentId", student1[0].toInt()) + val studentNameLong = "${student1[2]} ${student1[4]}".fixName() + val studentNameShort = "${student1[2]} ${student1[4][0]}.".fixName() + val accountName = if (accountNameLong == studentNameLong) null else accountNameLong + + val profile = Profile( + firstProfileId++, + loginStoreId, + loginStoreType, + studentNameLong, + data.loginUsername, + studentNameLong, + studentNameShort, + accountName + ).apply { + studentData["studentId"] = student1[0].toInt() + } + dateSemester1Start?.let { + profile.dateSemester1Start = it + profile.studentSchoolYearStart = it.year + } + dateSemester2Start?.let { profile.dateSemester2Start = it } + dateYearEnd?.let { profile.dateYearEnd = it } profileList.add(profile) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/template/DataTemplate.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/template/DataTemplate.kt index 86616983..297084dd 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/template/DataTemplate.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/template/DataTemplate.kt @@ -6,10 +6,10 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.template import okhttp3.Cookie import pl.szczodrzynski.edziennik.App +import pl.szczodrzynski.edziennik.currentTimeUnix import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_TEMPLATE_API import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_TEMPLATE_WEB import pl.szczodrzynski.edziennik.data.api.models.Data -import pl.szczodrzynski.edziennik.currentTimeUnix import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile import pl.szczodrzynski.edziennik.isNotNullNorEmpty @@ -40,6 +40,8 @@ class DataTemplate(app: App, profile: Profile?, loginStore: LoginStore) : Data(a loginMethods += LOGIN_METHOD_TEMPLATE_API } + override fun generateUserCode() = "TEMPLATE:DO_NOT_USE" + /* __ __ _ \ \ / / | | \ \ /\ / /__| |__ diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/DataVulcan.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/DataVulcan.kt index 8a7e609b..69d525e5 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/DataVulcan.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/DataVulcan.kt @@ -5,6 +5,7 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan import pl.szczodrzynski.edziennik.App +import pl.szczodrzynski.edziennik.currentTimeUnix import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_VULCAN_API import pl.szczodrzynski.edziennik.data.api.models.Data import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore @@ -13,8 +14,8 @@ import pl.szczodrzynski.edziennik.isNotNullNorEmpty class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app, profile, loginStore) { - fun isApiLoginValid() = /*apiCertificateExpiryTime-30 > currentTimeUnix() - &&*/ apiCertificateKey.isNotNullNorEmpty() + fun isApiLoginValid() = currentSemesterEndDate-30 > currentTimeUnix() + && apiCertificateKey.isNotNullNorEmpty() && apiCertificatePrivate.isNotNullNorEmpty() && symbol.isNotNullNorEmpty() @@ -25,6 +26,8 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app } } + override fun generateUserCode() = "$schoolName:$studentId" + /** * A UONET+ client symbol. * @@ -107,6 +110,16 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app get() { mStudentSemesterNumber = mStudentSemesterNumber ?: profile?.getStudentData("studentSemesterNumber", 0); return mStudentSemesterNumber ?: 0 } set(value) { profile?.putStudentData("studentSemesterNumber", value) ?: return; mStudentSemesterNumber = value } + /** + * Date of the end of the current semester ([studentSemesterNumber]). + * + * After this date, an API refresh of student list is required. + */ + private var mCurrentSemesterEndDate: Long? = null + var currentSemesterEndDate: Long + get() { mCurrentSemesterEndDate = mCurrentSemesterEndDate ?: profile?.getStudentData("currentSemesterEndDate", 0L); return mCurrentSemesterEndDate ?: 0L } + set(value) { profile?.putStudentData("currentSemesterEndDate", value) ?: return; mCurrentSemesterEndDate = value } + /* _____ _____ ____ /\ | __ \_ _| |___ \ / \ | |__) || | __ ____) | @@ -139,6 +152,12 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app get() { mApiCertificateKey = mApiCertificateKey ?: loginStore.getLoginData("certificateKey", null); return mApiCertificateKey } set(value) { loginStore.putLoginData("certificateKey", value); mApiCertificateKey = value } + /** + * This is not meant for normal usage. + * + * It provides a backward compatibility (<4.0) in order + * to migrate and use private keys instead of PFX. + */ private var mApiCertificatePfx: String? = null var apiCertificatePfx: String? get() { mApiCertificatePfx = mApiCertificatePfx ?: loginStore.getLoginData("certificatePfx", null); return mApiCertificatePfx } @@ -149,11 +168,6 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app get() { mApiCertificatePrivate = mApiCertificatePrivate ?: loginStore.getLoginData("certificatePrivate", null); return mApiCertificatePrivate } set(value) { loginStore.putLoginData("certificatePrivate", value); mApiCertificatePrivate = value } - private var mApiCertificateExpiryTime: Int? = null - var apiCertificateExpiryTime: Int - get() { mApiCertificateExpiryTime = mApiCertificateExpiryTime ?: loginStore.getLoginData("certificateExpiryTime", 0); return mApiCertificateExpiryTime ?: 0 } - set(value) { loginStore.putLoginData("certificateExpiryTime", value); mApiCertificateExpiryTime = value } - val apiUrl: String? get() { val url = when (apiToken?.substring(0, 3)) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesInbox.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesInbox.kt index 3ac292db..b06a29f7 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesInbox.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesInbox.kt @@ -39,7 +39,7 @@ class VulcanApiMessagesInbox(override val data: DataVulcan, val onSuccess: () -> "LoginId" to data.studentLoginId, "IdUczen" to data.studentId )) { json, _ -> - json.getJsonArray("Data").asJsonObjectList()?.forEach { message -> + json.getJsonArray("Data")?.asJsonObjectList()?.forEach { message -> val id = message.getLong("WiadomoscId") ?: return@forEach val subject = message.getString("Tytul") ?: "" val body = message.getString("Tresc") ?: "" diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiSendMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiSendMessage.kt index 2a76ab1d..799af29a 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiSendMessage.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiSendMessage.kt @@ -36,7 +36,7 @@ class VulcanApiSendMessage( } } val params = mapOf( - "NadawcaWiadomosci" to (profile?.accountNameLong ?: profile?.studentNameLong ?: ""), + "NadawcaWiadomosci" to (profile?.accountName ?: profile?.studentNameLong ?: ""), "Tytul" to subject, "Tresc" to text, "Adresaci" to recipientsArray, diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/firstlogin/VulcanFirstLogin.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/firstlogin/VulcanFirstLogin.kt index b82388d1..4af88cc0 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/firstlogin/VulcanFirstLogin.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/firstlogin/VulcanFirstLogin.kt @@ -7,6 +7,7 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.firstlogin import org.greenrobot.eventbus.EventBus import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.data.api.ERROR_NO_STUDENTS_IN_ACCOUNT +import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_VULCAN import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_STUDENT_LIST import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi @@ -25,11 +26,15 @@ class VulcanFirstLogin(val data: DataVulcan, val onSuccess: () -> Unit) { private val profileList = mutableListOf() init { + val loginStoreId = data.loginStore.id + val loginStoreType = LOGIN_TYPE_VULCAN + var firstProfileId = loginStoreId + VulcanLoginApi(data) { api.apiGet(TAG, VULCAN_API_ENDPOINT_STUDENT_LIST, baseUrl = true) { json, response -> val students = json.getJsonArray("Data") - if (students == null || students.size() < 1) { + if (students == null || students.isEmpty()) { data.error(ApiError(TAG, ERROR_NO_STUDENTS_IN_ACCOUNT) .withResponse(response) .withApiResponse(json)) @@ -53,49 +58,56 @@ class VulcanFirstLogin(val data: DataVulcan, val onSuccess: () -> Unit) { val userLogin = student.getString("UzytkownikLogin") ?: "" val currentSemesterStartDate = student.getLong("OkresDataOd") ?: return@forEach - val currentSemesterEndDate = (student.getLong("OkresDataDo") - ?: return@forEach) + 86400 + val currentSemesterEndDate = (student.getLong("OkresDataDo") ?: return@forEach) + 86400 val studentSemesterNumber = student.getInt("OkresNumer") ?: return@forEach - val newProfile = Profile() - newProfile.empty = true - val isParent = student.getString("UzytkownikRola") == "opiekun" - val userName = if (isParent) + val accountName = if (isParent) student.getString("UzytkownikNazwa")?.swapFirstLastName()?.fixName() - else - null - newProfile.accountNameLong = userName - newProfile.studentClassName = studentClassName - val today = Date.getToday() - newProfile.studentSchoolYear = "${today.year}/${today.year+1}" - - newProfile.putStudentData("studentId", studentId) - newProfile.putStudentData("studentLoginId", studentLoginId) - newProfile.putStudentData("studentClassId", studentClassId) - newProfile.putStudentData("studentSemesterId", studentSemesterId) - newProfile.putStudentData("schoolSymbol", schoolSymbol) - newProfile.putStudentData("schoolName", schoolName) - newProfile.putStudentData("currentSemesterEndDate", currentSemesterEndDate) - newProfile.putStudentData("studentSemesterNumber", studentSemesterNumber) + else null + var dateSemester1Start: Date? = null + var dateSemester2Start: Date? = null + var dateYearEnd: Date? = null when (studentSemesterNumber) { 1 -> { - newProfile.dateSemester1Start = Date.fromMillis(currentSemesterStartDate * 1000) - newProfile.dateSemester2Start = Date.fromMillis(currentSemesterEndDate * 1000) + dateSemester1Start = Date.fromMillis(currentSemesterStartDate * 1000) + dateSemester2Start = Date.fromMillis(currentSemesterEndDate * 1000) } 2 -> { - newProfile.dateSemester2Start = Date.fromMillis(currentSemesterStartDate * 1000) - newProfile.dateYearEnd = Date.fromMillis(currentSemesterEndDate * 1000) + dateSemester2Start = Date.fromMillis(currentSemesterStartDate * 1000) + dateYearEnd = Date.fromMillis(currentSemesterEndDate * 1000) } } - newProfile.studentNameLong = studentNameLong - newProfile.studentNameShort = studentNameShort - newProfile.name = studentNameLong - newProfile.subname = userLogin + val profile = Profile( + firstProfileId++, + loginStoreId, + loginStoreType, + studentNameLong, + userLogin, + studentNameLong, + studentNameShort, + accountName + ).apply { + this.studentClassName = studentClassName + studentData["studentId"] = studentId + studentData["studentLoginId"] = studentLoginId + studentData["studentClassId"] = studentClassId + studentData["studentSemesterId"] = studentSemesterId + studentData["studentSemesterNumber"] = studentSemesterNumber + studentData["schoolSymbol"] = schoolSymbol + studentData["schoolName"] = schoolName + studentData["currentSemesterEndDate"] = currentSemesterEndDate + } + dateSemester1Start?.let { + profile.dateSemester1Start = it + profile.studentSchoolYearStart = it.year + } + dateSemester2Start?.let { profile.dateSemester2Start = it } + dateYearEnd?.let { profile.dateYearEnd = it } - profileList.add(newProfile) + profileList.add(profile) } EventBus.getDefault().post(FirstLoginFinishedEvent(profileList, data.loginStore)) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanApiUpdateSemester.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanApiUpdateSemester.kt new file mode 100644 index 00000000..e0518f9c --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanApiUpdateSemester.kt @@ -0,0 +1,72 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2020-1-3. + */ + +package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login + +import pl.szczodrzynski.edziennik.* +import pl.szczodrzynski.edziennik.data.api.ERROR_NO_STUDENTS_IN_ACCOUNT +import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_STUDENT_LIST +import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan +import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi +import pl.szczodrzynski.edziennik.data.api.models.ApiError +import pl.szczodrzynski.edziennik.utils.models.Date + +class VulcanApiUpdateSemester(override val data: DataVulcan, val onSuccess: () -> Unit) : VulcanApi(data) { + companion object { + const val TAG = "VulcanApiUpdateSemester" + } + + init { data.profile?.also { profile -> + apiGet(TAG, VULCAN_API_ENDPOINT_STUDENT_LIST, baseUrl = true) { json, response -> + val students = json.getJsonArray("Data") + + if (students == null || students.isEmpty()) { + data.error(ApiError(TAG, ERROR_NO_STUDENTS_IN_ACCOUNT) + .withResponse(response) + .withApiResponse(json)) + return@apiGet + } + + students.asJsonObjectList().firstOrNull { + it.getInt("Id") == data.studentId + }?.let { student -> + val studentClassId = student.getInt("IdOddzial") ?: return@let + val studentClassName = student.getString("OkresPoziom").toString() + (student.getString("OddzialSymbol") ?: return@let) + val studentSemesterId = student.getInt("IdOkresKlasyfikacyjny") ?: return@let + + val currentSemesterStartDate = student.getLong("OkresDataOd") ?: return@let + val currentSemesterEndDate = (student.getLong("OkresDataDo") ?: return@let) + 86400 + val studentSemesterNumber = student.getInt("OkresNumer") ?: return@let + + var dateSemester1Start: Date? = null + var dateSemester2Start: Date? = null + var dateYearEnd: Date? = null + when (studentSemesterNumber) { + 1 -> { + dateSemester1Start = Date.fromMillis(currentSemesterStartDate * 1000) + dateSemester2Start = Date.fromMillis(currentSemesterEndDate * 1000) + } + 2 -> { + dateSemester2Start = Date.fromMillis(currentSemesterStartDate * 1000) + dateYearEnd = Date.fromMillis(currentSemesterEndDate * 1000) + } + } + + data.studentClassId = studentClassId + data.studentSemesterId = studentSemesterId + data.studentSemesterNumber = studentSemesterNumber + data.currentSemesterEndDate = currentSemesterEndDate + profile.studentClassName = studentClassName + dateSemester1Start?.let { + profile.dateSemester1Start = it + profile.studentSchoolYearStart = it.year + } + dateSemester2Start?.let { profile.dateSemester2Start = it } + dateYearEnd?.let { profile.dateYearEnd = it } + } + + onSuccess() + } + } ?: onSuccess()} +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginApi.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginApi.kt index dfa1c2ac..1332bbe7 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginApi.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginApi.kt @@ -10,10 +10,10 @@ import im.wangchao.mhttp.Request import im.wangchao.mhttp.Response import im.wangchao.mhttp.callback.JsonCallbackHandler import io.github.wulkanowy.signer.android.getPrivateKeyFromCert +import pl.szczodrzynski.edziennik.currentTimeUnix import pl.szczodrzynski.edziennik.data.api.* import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan import pl.szczodrzynski.edziennik.data.api.models.ApiError -import pl.szczodrzynski.edziennik.currentTimeUnix import pl.szczodrzynski.edziennik.getJsonObject import pl.szczodrzynski.edziennik.getString import pl.szczodrzynski.edziennik.isNotNullNorEmpty @@ -32,6 +32,7 @@ class VulcanLoginApi(val data: DataVulcan, val onSuccess: () -> Unit) { onSuccess() } else { + // < v4.0 - PFX to Private Key migration if (data.apiCertificatePfx.isNotNullNorEmpty()) { try { data.apiCertificatePrivate = getPrivateKeyFromCert( @@ -46,6 +47,16 @@ class VulcanLoginApi(val data: DataVulcan, val onSuccess: () -> Unit) { return@run } } + + if (data.apiCertificateKey.isNotNullNorEmpty() + && data.apiCertificatePrivate.isNotNullNorEmpty() + && data.symbol.isNotNullNorEmpty()) { + // (see data.isApiLoginValid()) + // the semester end date is over + VulcanApiUpdateSemester(data, onSuccess) + return@run + } + if (data.symbol.isNotNullNorEmpty() && data.apiToken.isNotNullNorEmpty() && data.apiPin.isNotNullNorEmpty()) { loginWithToken() } @@ -107,12 +118,10 @@ class VulcanLoginApi(val data: DataVulcan, val onSuccess: () -> Unit) { } data.apiCertificateKey = cert.getString("CertyfikatKlucz") - data.apiCertificatePfx = cert.getString("CertyfikatPfx") - data.apiCertificateExpiryTime = 1598832000 data.apiToken = data.apiToken?.substring(0, 3) data.apiCertificatePrivate = getPrivateKeyFromCert( if (data.apiToken?.get(0) == 'F') VULCAN_API_PASSWORD_FAKELOG else VULCAN_API_PASSWORD, - data.apiCertificatePfx ?: "" + cert.getString("CertyfikatPfx") ?: "" ) data.loginStore.removeLoginData("certificatePfx") data.loginStore.removeLoginData("devicePin") 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 6fb1af98..25858560 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 @@ -46,7 +46,7 @@ import java.net.SocketTimeoutException import java.net.UnknownHostException import javax.net.ssl.SSLException -open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore) { +abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginStore) { companion object { private const val TAG = "Data" } @@ -221,6 +221,7 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore) return // return on first login profile.empty = false + profile.userCode = generateUserCode() db.profileDao().add(profile) db.loginStoreDao().add(loginStore) @@ -230,31 +231,18 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore) name = profile.name subname = profile.subname syncEnabled = profile.syncEnabled - loggedIn = profile.loggedIn empty = profile.empty archived = profile.archived studentNameLong = profile.studentNameLong studentNameShort = profile.studentNameShort studentNumber = profile.studentNumber - studentData = profile.studentData - accountNameLong = profile.accountNameLong - yearAverageMode = profile.yearAverageMode - currentSemester = profile.currentSemester - attendancePercentage = profile.attendancePercentage + accountName = profile.accountName dateSemester1Start = profile.dateSemester1Start dateSemester2Start = profile.dateSemester2Start dateYearEnd = profile.dateYearEnd - luckyNumberEnabled = profile.luckyNumberEnabled - luckyNumber = profile.luckyNumber - luckyNumberDate = profile.luckyNumberDate - lastFullSync = profile.lastFullSync lastReceiversSync = profile.lastReceiversSync } } - if (loginStore.id == app.profile?.loginStoreId) { - app.loginStore = loginStore.data - app.profile.loginStoreData = loginStore.data - } // always present and not empty, during every sync db.endpointTimerDao().addAll(endpointTimers) @@ -372,6 +360,8 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore) } } + abstract fun generateUserCode(): String + fun cancel() { d("Data", "Cancelled") cancelled = true diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/Szkolny.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/Szkolny.kt index 071f6be1..85c052d4 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/Szkolny.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/Szkolny.kt @@ -8,13 +8,12 @@ import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile -import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull class Szkolny(val app: App, val callback: EdziennikCallback) { private val api = SzkolnyApi(app) - fun sync(profileList: List) { + fun sync(profileList: List) { val profiles = profileList.filter { it.registration == Profile.REGISTRATION_ENABLED } if (profiles.isNotEmpty()) { val events = api.getEvents(profiles) 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 f5521520..6859d010 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 @@ -20,7 +20,7 @@ import pl.szczodrzynski.edziennik.data.api.szkolny.response.ApiResponse import pl.szczodrzynski.edziennik.data.api.szkolny.response.WebPushResponse import pl.szczodrzynski.edziennik.data.db.modules.events.Event import pl.szczodrzynski.edziennik.data.db.modules.events.EventFull -import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull +import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Time import retrofit2.Retrofit @@ -55,7 +55,7 @@ class SzkolnyApi(val app: App) { api = retrofit.create() } - fun getEvents(profiles: List): List { + fun getEvents(profiles: List): List { val teams = app.db.teamDao().allNow val notifications = app.db.notificationDao().getNotPostedNow() @@ -71,10 +71,10 @@ class SzkolnyApi(val app: App) { appVersionCode = BuildConfig.VERSION_CODE, syncInterval = app.config.sync.interval ), - userCodes = profiles.map { it.usernameId }, + userCodes = profiles.map { it.userCode }, users = profiles.map { profile -> ServerSyncRequest.User( - profile.usernameId, + profile.userCode, profile.studentNameLong ?: "", profile.studentNameShort ?: "", profile.loginStoreType, @@ -97,7 +97,7 @@ class SzkolnyApi(val app: App) { seen = profile?.empty ?: false notified = profile?.empty ?: false - if (profile?.usernameId == event.sharedBy) sharedBy = "self" + if (profile?.userCode == event.sharedBy) sharedBy = "self" }) } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/EdziennikTask.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/EdziennikTask.kt index 21a8622d..67e39867 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/EdziennikTask.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/EdziennikTask.kt @@ -45,11 +45,8 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa taskName = app.getString(R.string.edziennik_notification_api_first_login_title) } else { // get the requested profile and login store - val profile = app.db.profileDao().getFullByIdNow(profileId) + val profile = app.db.profileDao().getByIdNow(profileId) ?: return this.profile = profile - if (profile == null) { - return - } val loginStore = app.db.loginStoreDao().getByIdNow(profile.loginStoreId) ?: return this.loginStore = loginStore // save the profile ID and name as the current task's diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/IApiTask.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/IApiTask.kt index 88a2abff..078fed7e 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/IApiTask.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/IApiTask.kt @@ -11,11 +11,11 @@ import android.os.Build.VERSION_CODES.O import org.greenrobot.eventbus.EventBus import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.data.api.ApiService -import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull +import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile abstract class IApiTask(open val profileId: Int) { var taskId: Int = 0 - var profile: ProfileFull? = null + var profile: Profile? = null var taskName: String? = null /** diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/SzkolnyTask.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/SzkolnyTask.kt index d58d806e..ac227c76 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/SzkolnyTask.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/SzkolnyTask.kt @@ -8,14 +8,13 @@ import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback import pl.szczodrzynski.edziennik.data.api.szkolny.Szkolny -import pl.szczodrzynski.edziennik.data.db.modules.events.EventFull -import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull +import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile class SzkolnyTask(val request: Any) : IApiTask(-1) { companion object { private const val TAG = "SzkolnyTask" - fun sync(profiles: List) = SzkolnyTask(SyncRequest(profiles)) + fun sync(profiles: List) = SzkolnyTask(SyncRequest(profiles)) /*fun shareEvent(event: EventFull) = SzkolnyTask(ShareEventRequest(event)) fun unshareEvent(event: EventFull) = SzkolnyTask(UnshareEventRequest(event))*/ } @@ -40,7 +39,7 @@ class SzkolnyTask(val request: Any) : IApiTask(-1) { } } - data class SyncRequest(val profiles: List) + data class SyncRequest(val profiles: List) /*data class ShareEventRequest(val event: EventFull) data class UnshareEventRequest(val event: EventFull)*/ } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/AppDb.java b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/AppDb.java index ecbf13bf..3b074235 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/AppDb.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/AppDb.java @@ -1,6 +1,7 @@ package pl.szczodrzynski.edziennik.data.db; import android.content.Context; +import android.database.Cursor; import androidx.annotation.NonNull; import androidx.room.Database; @@ -10,6 +11,7 @@ import androidx.room.TypeConverters; import androidx.room.migration.Migration; import androidx.sqlite.db.SupportSQLiteDatabase; +import pl.szczodrzynski.edziennik.ExtensionsKt; import pl.szczodrzynski.edziennik.config.db.ConfigDao; import pl.szczodrzynski.edziennik.config.db.ConfigEntry; import pl.szczodrzynski.edziennik.data.db.converters.ConverterDate; @@ -108,7 +110,7 @@ import pl.szczodrzynski.edziennik.utils.models.Date; AttendanceType.class, pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson.class, ConfigEntry.class, - Metadata.class}, version = 71) + Metadata.class}, version = 72) @TypeConverters({ ConverterTime.class, ConverterDate.class, @@ -849,6 +851,114 @@ public abstract class AppDb extends RoomDatabase { database.execSQL("INSERT INTO config (profileId, `key`, value) VALUES (-1, \"runSync\", \"true\");"); } }; + private static final Migration MIGRATION_71_72 = new Migration(71, 72) { + @Override + public void migrate(@NonNull SupportSQLiteDatabase database) { + database.execSQL("ALTER TABLE loginStores RENAME to _loginStores;"); + database.execSQL("CREATE TABLE loginStores(" + + "loginStoreId INTEGER NOT NULL," + + "loginStoreType INTEGER NOT NULL," + + "loginStoreMode INTEGER NOT NULL," + + "loginStoreData TEXT NOT NULL," + + "PRIMARY KEY(loginStoreId));"); + database.execSQL("INSERT INTO loginStores " + + "(loginStoreId, loginStoreType, loginStoreMode, loginStoreData) " + + "SELECT loginStoreId, loginStoreType, loginStoreMode, loginStoreData " + + "FROM _loginStores;"); + database.execSQL("DROP TABLE _loginStores;"); + + database.execSQL("ALTER TABLE profiles RENAME TO _profiles_old;"); + database.execSQL("CREATE TABLE profiles (\n" + + "profileId INTEGER NOT NULL, name TEXT NOT NULL, subname TEXT, image TEXT DEFAULT NULL, \n" + + "studentNameLong TEXT NOT NULL, studentNameShort TEXT NOT NULL, accountName TEXT, \n" + + "studentData TEXT NOT NULL, empty INTEGER NOT NULL DEFAULT 1, archived INTEGER NOT NULL DEFAULT 0, \n" + + "syncEnabled INTEGER NOT NULL DEFAULT 1, enableSharedEvents INTEGER NOT NULL DEFAULT 1, registration INTEGER NOT NULL DEFAULT 0, \n" + + "userCode TEXT NOT NULL DEFAULT \"\", studentNumber INTEGER NOT NULL DEFAULT -1, studentClassName TEXT DEFAULT NULL, \n" + + "studentSchoolYearStart INTEGER NOT NULL, dateSemester1Start TEXT NOT NULL, dateSemester2Start TEXT NOT NULL, \n" + + "dateYearEnd TEXT NOT NULL, disabledNotifications TEXT DEFAULT NULL, lastReceiversSync INTEGER NOT NULL DEFAULT 0, \n" + + "loginStoreId INTEGER NOT NULL, loginStoreType INTEGER NOT NULL, PRIMARY KEY(profileId));"); + database.execSQL("INSERT INTO profiles (profileId, name, subname, image, studentNameLong, studentNameShort, accountName, \n" + + "userCode, studentData, empty, archived, syncEnabled, enableSharedEvents, registration, studentNumber, studentSchoolYearStart, \n" + + "dateSemester1Start, dateSemester2Start, dateYearEnd, lastReceiversSync, loginStoreId, loginStoreType \n" + + ") SELECT profileId, name, subname, image, studentNameLong, studentNameShort, accountNameLong, \"\" AS userCode, studentData, \n" + + "empty, archived, syncEnabled, enableSharedEvents, registration, studentNumber, SUBSTR(dateSemester1Start, 0, 5) AS studentSchoolYearStart, \n" + + "dateSemester1Start, dateSemester2Start, dateYearEnd, lastReceiversSync, _profiles_old.loginStoreId, loginStoreType FROM _profiles_old \n" + + "JOIN loginStores ON loginStores.loginStoreId = _profiles_old.loginStoreId \n" + + "WHERE profileId >= 0;"); + database.execSQL("DROP TABLE _profiles_old;"); + + // MIGRACJA userCode - mobidziennik + database.execSQL("DROP TABLE IF EXISTS _userCodes;"); + database.execSQL("CREATE TABLE _userCodes (profileId INTEGER, loginData TEXT, studentData TEXT, userCode TEXT, serverName TEXT, username TEXT, studentId TEXT);"); + database.execSQL("DELETE FROM _userCodes;"); + database.execSQL("INSERT INTO _userCodes SELECT profileId, loginStores.loginStoreData, studentData, \"\", \"\", \"\", \"\" FROM profiles JOIN loginStores ON loginStores.loginStoreId = profiles.loginStoreId WHERE profiles.loginStoreType = 1;"); + database.execSQL("UPDATE _userCodes SET serverName = SUBSTR(loginData, instr(loginData, '\"serverName\":\"')+14);"); + database.execSQL("UPDATE _userCodes SET serverName = SUBSTR(serverName, 0, instr(serverName, '\",')+instr(serverName, '\"}')-(instr(serverName, '\"}')*min(instr(serverName, '\",'), 1)));"); + database.execSQL("UPDATE _userCodes SET username = SUBSTR(loginData, instr(loginData, '\"username\":\"')+12);"); + database.execSQL("UPDATE _userCodes SET username = SUBSTR(username, 0, instr(username, '\",')+instr(username, '\"}')-(instr(username, '\"}')*min(instr(username, '\",'), 1)));"); + database.execSQL("UPDATE _userCodes SET studentId = SUBSTR(studentData, instr(studentData, '\"studentId\":')+12);"); + database.execSQL("UPDATE _userCodes SET studentId = SUBSTR(studentId, 0, instr(studentId, ',')+instr(studentId, '}')-(instr(studentId, '}')*min(instr(studentId, ','), 1)));"); + database.execSQL("UPDATE _userCodes SET userCode = serverName||\":\"||username||\":\"||studentId;"); + database.execSQL("UPDATE profiles SET userCode = (SELECT userCode FROM _userCodes WHERE profileId = profiles.profileId) WHERE profileId IN (SELECT profileId FROM _userCodes);"); + // MIGRACJA userCode - librus + database.execSQL("DROP TABLE IF EXISTS _userCodes;"); + database.execSQL("CREATE TABLE _userCodes (profileId INTEGER, loginData TEXT, studentData TEXT, userCode TEXT, schoolName TEXT, accountLogin TEXT);"); + database.execSQL("DELETE FROM _userCodes;"); + database.execSQL("INSERT INTO _userCodes SELECT profileId, loginStores.loginStoreData, studentData, \"\", \"\", \"\" FROM profiles JOIN loginStores ON loginStores.loginStoreId = profiles.loginStoreId WHERE profiles.loginStoreType = 2;"); + database.execSQL("UPDATE _userCodes SET schoolName = SUBSTR(studentData, instr(studentData, '\"schoolName\":\"')+14);"); + database.execSQL("UPDATE _userCodes SET schoolName = SUBSTR(schoolName, 0, instr(schoolName, '\",')+instr(schoolName, '\"}')-(instr(schoolName, '\"}')*min(instr(schoolName, '\",'), 1)));"); + database.execSQL("UPDATE _userCodes SET accountLogin = SUBSTR(studentData, instr(studentData, '\"accountLogin\":\"')+16);"); + database.execSQL("UPDATE _userCodes SET accountLogin = SUBSTR(accountLogin, 0, instr(accountLogin, '\",')+instr(accountLogin, '\"}')-(instr(accountLogin, '\"}')*min(instr(accountLogin, '\",'), 1)));"); + database.execSQL("UPDATE _userCodes SET userCode = schoolName||\":\"||accountLogin;"); + database.execSQL("UPDATE profiles SET userCode = (SELECT userCode FROM _userCodes WHERE profileId = profiles.profileId) WHERE profileId IN (SELECT profileId FROM _userCodes);"); + // MIGRACJA userCode - iuczniowie + database.execSQL("DROP TABLE IF EXISTS _userCodes;"); + database.execSQL("CREATE TABLE _userCodes (profileId INTEGER, loginData TEXT, studentData TEXT, userCode TEXT, schoolName TEXT, username TEXT, registerId TEXT);"); + database.execSQL("DELETE FROM _userCodes;"); + database.execSQL("INSERT INTO _userCodes SELECT profileId, loginStores.loginStoreData, studentData, \"\", \"\", \"\", \"\" FROM profiles JOIN loginStores ON loginStores.loginStoreId = profiles.loginStoreId WHERE profiles.loginStoreType = 3;"); + database.execSQL("UPDATE _userCodes SET schoolName = SUBSTR(loginData, instr(loginData, '\"schoolName\":\"')+14);"); + database.execSQL("UPDATE _userCodes SET schoolName = SUBSTR(schoolName, 0, instr(schoolName, '\",')+instr(schoolName, '\"}')-(instr(schoolName, '\"}')*min(instr(schoolName, '\",'), 1)));"); + database.execSQL("UPDATE _userCodes SET username = SUBSTR(loginData, instr(loginData, '\"username\":\"')+12);"); + database.execSQL("UPDATE _userCodes SET username = SUBSTR(username, 0, instr(username, '\",')+instr(username, '\"}')-(instr(username, '\"}')*min(instr(username, '\",'), 1)));"); + database.execSQL("UPDATE _userCodes SET registerId = SUBSTR(studentData, instr(studentData, '\"registerId\":')+13);"); + database.execSQL("UPDATE _userCodes SET registerId = SUBSTR(registerId, 0, instr(registerId, ',')+instr(registerId, '}')-(instr(registerId, '}')*min(instr(registerId, ','), 1)));"); + database.execSQL("UPDATE _userCodes SET userCode = schoolName||\":\"||username||\":\"||registerId;"); + database.execSQL("UPDATE profiles SET userCode = (SELECT userCode FROM _userCodes WHERE profileId = profiles.profileId) WHERE profileId IN (SELECT profileId FROM _userCodes);"); + // MIGRACJA userCode - vulcan + database.execSQL("DROP TABLE IF EXISTS _userCodes;"); + database.execSQL("CREATE TABLE _userCodes (profileId INTEGER, loginData TEXT, studentData TEXT, userCode TEXT, schoolName TEXT, studentId TEXT);"); + database.execSQL("DELETE FROM _userCodes;"); + database.execSQL("INSERT INTO _userCodes SELECT profileId, loginStores.loginStoreData, studentData, \"\", \"\", \"\" FROM profiles JOIN loginStores ON loginStores.loginStoreId = profiles.loginStoreId WHERE profiles.loginStoreType = 4;"); + database.execSQL("UPDATE _userCodes SET schoolName = SUBSTR(studentData, instr(studentData, '\"schoolName\":\"')+14);"); + database.execSQL("UPDATE _userCodes SET schoolName = SUBSTR(schoolName, 0, instr(schoolName, '\",')+instr(schoolName, '\"}')-(instr(schoolName, '\"}')*min(instr(schoolName, '\",'), 1)));"); + database.execSQL("UPDATE _userCodes SET studentId = SUBSTR(studentData, instr(studentData, '\"studentId\":')+12);"); + database.execSQL("UPDATE _userCodes SET studentId = SUBSTR(studentId, 0, instr(studentId, ',')+instr(studentId, '}')-(instr(studentId, '}')*min(instr(studentId, ','), 1)));"); + database.execSQL("UPDATE _userCodes SET userCode = schoolName||\":\"||studentId;"); + database.execSQL("UPDATE profiles SET userCode = (SELECT userCode FROM _userCodes WHERE profileId = profiles.profileId) WHERE profileId IN (SELECT profileId FROM _userCodes);"); + // MIGRACJA userCode - edudziennik + database.execSQL("DROP TABLE IF EXISTS _userCodes;"); + database.execSQL("CREATE TABLE _userCodes (profileId INTEGER, loginData TEXT, studentData TEXT, userCode TEXT, schoolName TEXT, email TEXT, studentId TEXT);"); + database.execSQL("DELETE FROM _userCodes;"); + database.execSQL("INSERT INTO _userCodes SELECT profileId, loginStores.loginStoreData, studentData, \"\", \"\", \"\", \"\" FROM profiles JOIN loginStores ON loginStores.loginStoreId = profiles.loginStoreId WHERE profiles.loginStoreType = 5;"); + database.execSQL("UPDATE _userCodes SET schoolName = SUBSTR(studentData, instr(studentData, '\"schoolName\":\"')+14);"); + database.execSQL("UPDATE _userCodes SET schoolName = SUBSTR(schoolName, 0, instr(schoolName, '\",')+instr(schoolName, '\"}')-(instr(schoolName, '\"}')*min(instr(schoolName, '\",'), 1)));"); + database.execSQL("UPDATE _userCodes SET email = SUBSTR(loginData, instr(loginData, '\"email\":\"')+9);"); + database.execSQL("UPDATE _userCodes SET email = SUBSTR(email, 0, instr(email, '\",')+instr(email, '\"}')-(instr(email, '\"}')*min(instr(email, '\",'), 1)));"); + database.execSQL("UPDATE _userCodes SET studentId = SUBSTR(studentData, instr(studentData, '\"studentId\":\"')+13);"); + database.execSQL("UPDATE _userCodes SET studentId = SUBSTR(studentId, 0, instr(studentId, '\",')+instr(studentId, '\"}')-(instr(studentId, '\"}')*min(instr(studentId, '\",'), 1)));"); + // CRC32 Student IDs + try (Cursor cursor = database.query("SELECT profileId, studentId FROM _userCodes;")) { + while (cursor.moveToNext()) { + int profileId = cursor.getInt(0); + long crc = ExtensionsKt.crc32(cursor.getString(1)); + database.execSQL("UPDATE _userCodes SET studentId = "+crc+" WHERE profileId = "+profileId); + } + } + database.execSQL("UPDATE _userCodes SET userCode = schoolName||\":\"||email||\":\"||studentId;"); + database.execSQL("UPDATE profiles SET userCode = (SELECT userCode FROM _userCodes WHERE profileId = profiles.profileId) WHERE profileId IN (SELECT profileId FROM _userCodes);"); + database.execSQL("DROP TABLE _userCodes;"); + } + }; public static AppDb getDatabase(final Context context) { @@ -917,7 +1027,8 @@ public abstract class AppDb extends RoomDatabase { MIGRATION_67_68, MIGRATION_68_69, MIGRATION_69_70, - MIGRATION_70_71 + MIGRATION_70_71, + MIGRATION_71_72 ) .allowMainThreadQueries() //.fallbackToDestructiveMigration() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/login/LoginStore.java b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/login/LoginStore.java deleted file mode 100644 index ccd13615..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/login/LoginStore.java +++ /dev/null @@ -1,197 +0,0 @@ -package pl.szczodrzynski.edziennik.data.db.modules.login; - -import android.os.Bundle; - -import androidx.annotation.Nullable; -import androidx.room.ColumnInfo; -import androidx.room.Entity; - -import com.google.gson.JsonElement; -import com.google.gson.JsonNull; -import com.google.gson.JsonObject; - -import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull; - -@Entity(tableName = "loginStores", - primaryKeys = {"loginStoreId"}) -public class LoginStore { - @ColumnInfo(name = "loginStoreId") - public int id = -1; - @ColumnInfo(name = "loginStoreType") - public int type = -1; - public final static int LOGIN_TYPE_MOBIDZIENNIK = 1; - public final static int LOGIN_TYPE_LIBRUS = 2; - public final static int LOGIN_TYPE_VULCAN = 4; - public final static int LOGIN_TYPE_IUCZNIOWIE = 3; - public final static int LOGIN_TYPE_EDUDZIENNIK = 5; - public final static int LOGIN_TYPE_DEMO = 20; - @ColumnInfo(name = "loginStoreData") - public JsonObject data; - - @ColumnInfo(name = "loginStoreMode") - public int mode = 0; - public static final int LOGIN_MODE_LIBRUS_EMAIL = 0; - public static final int LOGIN_MODE_LIBRUS_SYNERGIA = 1; - public static final int LOGIN_MODE_LIBRUS_JST = 2; - - public LoginStore(int id, int type, JsonObject data) { - this.id = id; - this.type = type; - this.data = data; - } - - public static LoginStore fromProfileFull(ProfileFull profileFull) { - return new LoginStore(profileFull.getLoginStoreId(), profileFull.getLoginStoreType(), profileFull.getLoginStoreData()); - } - - public void copyFrom(Bundle args) { - for (String key: args.keySet()) { - Object o = args.get(key); - if (o instanceof String) { - putLoginData(key, (String) o); - } - else if (o instanceof Integer) { - putLoginData(key, (Integer) o); - } - else if (o instanceof Long) { - putLoginData(key, (Long) o); - } - else if (o instanceof Float) { - putLoginData(key, (Float) o); - } - else if (o instanceof Boolean) { - putLoginData(key, (Boolean) o); - } - } - } - public boolean hasLoginData(String key) { - if (data == null) - return false; - return data.has(key); - } - @Nullable - public String getLoginData(String key, @Nullable String defaultValue) { - if (data == null) - return defaultValue; - JsonElement element = data.get(key); - if (element != null && !(element instanceof JsonNull)) { - return element.getAsString(); - } - return defaultValue; - } - @Nullable - public int getLoginData(String key, int defaultValue) { - if (data == null) - return defaultValue; - JsonElement element = data.get(key); - if (element != null && !(element instanceof JsonNull)) { - return element.getAsInt(); - } - return defaultValue; - } - @Nullable - public long getLoginData(String key, long defaultValue) { - if (data == null) - return defaultValue; - JsonElement element = data.get(key); - if (element != null && !(element instanceof JsonNull)) { - return element.getAsLong(); - } - return defaultValue; - } - @Nullable - public float getLoginData(String key, float defaultValue) { - if (data == null) - return defaultValue; - JsonElement element = data.get(key); - if (element != null && !(element instanceof JsonNull)) { - return element.getAsFloat(); - } - return defaultValue; - } - public boolean getLoginData(String key, boolean defaultValue) { - if (data == null) - return defaultValue; - JsonElement element = data.get(key); - if (element != null && !(element instanceof JsonNull)) { - return element.getAsBoolean(); - } - return defaultValue; - } - - public void putLoginData(String key, String value) { - forceLoginStore(); - data.addProperty(key, value); - } - public void putLoginData(String key, int value) { - forceLoginStore(); - data.addProperty(key, value); - } - public void putLoginData(String key, long value) { - forceLoginStore(); - data.addProperty(key, value); - } - public void putLoginData(String key, float value) { - forceLoginStore(); - data.addProperty(key, value); - } - public void putLoginData(String key, boolean value) { - forceLoginStore(); - data.addProperty(key, value); - } - - public void removeLoginData(String key) { - if (data == null) - return; - data.remove(key); - } - - public void clearLoginStore() { - data = new JsonObject(); - } - - private void forceLoginStore() { - if (data == null) { - clearLoginStore(); - } - } - - public String type() { - switch (type) { - case LOGIN_TYPE_MOBIDZIENNIK: - return "LOGIN_TYPE_MOBIDZIENNIK"; - case LOGIN_TYPE_LIBRUS: - return "LOGIN_TYPE_LIBRUS"; - case LOGIN_TYPE_IUCZNIOWIE: - return "LOGIN_TYPE_IDZIENNIK"; - case LOGIN_TYPE_VULCAN: - return "LOGIN_TYPE_VULCAN"; - case LOGIN_TYPE_DEMO: - return "LOGIN_TYPE_DEMO"; - default: - return "unknown"; - } - } - public String mode() { - switch (mode) { - case LOGIN_MODE_LIBRUS_EMAIL: - return "LOGIN_MODE_LIBRUS_EMAIL"; - case LOGIN_MODE_LIBRUS_SYNERGIA: - return "LOGIN_MODE_LIBRUS_SYNERGIA"; - case LOGIN_MODE_LIBRUS_JST: - return "LOGIN_MODE_LIBRUS_JST"; - default: - return "unknown"; - } - } - - @Override - public String toString() { - return "LoginStore{" + - "id=" + id + - ", type=" + type() + - ", mode=" + mode() + - ", data=" + data + - '}'; - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/login/LoginStore.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/login/LoginStore.kt new file mode 100644 index 00000000..38811269 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/login/LoginStore.kt @@ -0,0 +1,88 @@ +package pl.szczodrzynski.edziennik.data.db.modules.login + +import android.os.Bundle +import androidx.room.ColumnInfo +import androidx.room.Entity +import com.google.gson.JsonObject +import pl.szczodrzynski.edziennik.* + +@Entity(tableName = "loginStores", primaryKeys = ["loginStoreId"]) +class LoginStore( + @ColumnInfo(name = "loginStoreId") + val id: Int, + + @ColumnInfo(name = "loginStoreType") + val type: Int, + + @ColumnInfo(name = "loginStoreMode") + val mode: Int, + + @ColumnInfo(name = "loginStoreData") + val data: JsonObject = JsonObject() +) { + companion object { + const val LOGIN_TYPE_MOBIDZIENNIK = 1 + const val LOGIN_TYPE_LIBRUS = 2 + const val LOGIN_TYPE_VULCAN = 4 + const val LOGIN_TYPE_IDZIENNIK = 3 + const val LOGIN_TYPE_EDUDZIENNIK = 5 + const val LOGIN_TYPE_DEMO = 20 + const val LOGIN_MODE_LIBRUS_EMAIL = 0 + const val LOGIN_MODE_LIBRUS_SYNERGIA = 1 + const val LOGIN_MODE_LIBRUS_JST = 2 + } + + fun hasLoginData(key: String) = data.has(key) + fun getLoginData(key: String, defaultValue: Boolean) = data.getBoolean(key) ?: defaultValue + fun getLoginData(key: String, defaultValue: String?) = data.getString(key) ?: defaultValue + fun getLoginData(key: String, defaultValue: Int) = data.getInt(key) ?: defaultValue + fun getLoginData(key: String, defaultValue: Long) = data.getLong(key) ?: defaultValue + fun getLoginData(key: String, defaultValue: Float) = data.getFloat(key) ?: defaultValue + fun getLoginData(key: String, defaultValue: Char) = data.getChar(key) ?: defaultValue + fun putLoginData(key: String, value: Boolean) { data[key] = value } + fun putLoginData(key: String, value: String?) { data[key] = value } + fun putLoginData(key: String, value: Number) { data[key] = value } + fun putLoginData(key: String, value: Char) { data[key] = value } + fun removeLoginData(key: String) { data.remove(key) } + + fun copyFrom(args: Bundle) { + for (key in args.keySet()) { + when (val o = args[key]) { + is String -> putLoginData(key, o) + is Int -> putLoginData(key, o) + is Long -> putLoginData(key, o) + is Float -> putLoginData(key, o) + is Boolean -> putLoginData(key, o) + } + } + } + + fun type(): String { + return when (type) { + LOGIN_TYPE_MOBIDZIENNIK -> "LOGIN_TYPE_MOBIDZIENNIK" + LOGIN_TYPE_LIBRUS -> "LOGIN_TYPE_LIBRUS" + LOGIN_TYPE_IDZIENNIK -> "LOGIN_TYPE_IDZIENNIK" + LOGIN_TYPE_VULCAN -> "LOGIN_TYPE_VULCAN" + LOGIN_TYPE_DEMO -> "LOGIN_TYPE_DEMO" + else -> "unknown" + } + } + + fun mode(): String { + return when (mode) { + LOGIN_MODE_LIBRUS_EMAIL -> "LOGIN_MODE_LIBRUS_EMAIL" + LOGIN_MODE_LIBRUS_SYNERGIA -> "LOGIN_MODE_LIBRUS_SYNERGIA" + LOGIN_MODE_LIBRUS_JST -> "LOGIN_MODE_LIBRUS_JST" + else -> "unknown" + } + } + + override fun toString(): String { + return "LoginStore{" + + "id=" + id + + ", type=" + type() + + ", mode=" + mode() + + ", data=" + data + + '}' + } +} \ No newline at end of file diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/login/LoginStoreDao.java b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/login/LoginStoreDao.java index 49fc3eea..32fdb1d4 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/login/LoginStoreDao.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/login/LoginStoreDao.java @@ -8,8 +8,6 @@ import androidx.room.Query; import java.util.List; -import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull; - @Dao public abstract class LoginStoreDao { @Insert(onConflict = OnConflictStrategy.REPLACE) @@ -27,10 +25,6 @@ public abstract class LoginStoreDao { @Query("SELECT * FROM loginStores WHERE loginStoreId = :loginStoreId") public abstract LoginStore getByIdNow(int loginStoreId); - public void add(ProfileFull profileFull) { - add(new LoginStore(profileFull.getLoginStoreId(), profileFull.getLoginStoreType(), profileFull.getLoginStoreData())); - } - @Query("UPDATE loginStores SET loginStoreId = :targetId WHERE loginStoreId = :sourceId") public abstract void changeId(int sourceId, int targetId); diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/profiles/Profile.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/profiles/Profile.kt index 83420c95..14316845 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/profiles/Profile.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/profiles/Profile.kt @@ -1,10 +1,13 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2020-1-3. + */ + package pl.szczodrzynski.edziennik.data.db.modules.profiles import android.content.Context import android.graphics.PorterDuff import android.graphics.PorterDuffColorFilter import android.graphics.drawable.Drawable -import android.net.ConnectivityManager import android.widget.ImageView import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory import androidx.room.ColumnInfo @@ -12,7 +15,9 @@ import androidx.room.Entity import androidx.room.Ignore import com.google.gson.JsonObject import pl.droidsonroids.gif.GifDrawable -import pl.szczodrzynski.edziennik.colorFromName +import pl.szczodrzynski.edziennik.* +import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_EDUDZIENNIK +import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.navlib.ImageHolder import pl.szczodrzynski.navlib.R @@ -20,143 +25,91 @@ import pl.szczodrzynski.navlib.drawer.IDrawerProfile import pl.szczodrzynski.navlib.getDrawableFromRes @Entity(tableName = "profiles", primaryKeys = ["profileId"]) -open class Profile : IDrawerProfile { +open class Profile( + @ColumnInfo(name = "profileId") + override val id: Int, + val loginStoreId: Int, + val loginStoreType: Int, + + override var name: String, + override var subname: String?, + + /** + * The name of the student. + * This doesn't change, no matter if it's a parent or student account. + */ + var studentNameLong: String, + var studentNameShort: String, + /** + * A full name of the account owner. + * If null, then it's a student account. + * If not null, then it's a parent account with this name. + */ + var accountName: String?, + + val studentData: JsonObject = JsonObject() + +) : IDrawerProfile { + companion object { + const val REGISTRATION_UNSPECIFIED = 0 + const val REGISTRATION_DISABLED = 1 + const val REGISTRATION_ENABLED = 2 + const val COLOR_MODE_DEFAULT = 0 + const val COLOR_MODE_WEIGHTED = 1 + const val AGENDA_DEFAULT = 0 + const val AGENDA_CALENDAR = 1 + const val YEAR_1_AVG_2_AVG = 0 + const val YEAR_1_SEM_2_AVG = 1 + const val YEAR_1_AVG_2_SEM = 2 + const val YEAR_1_SEM_2_SEM = 3 + const val YEAR_ALL_GRADES = 4 + } - @ColumnInfo(name = "profileId") - override var id = -1 - override var name: String? = "" - override var subname: String? = null override var image: String? = null - /*public String name = ""; - public String subname = null; - public String image = null;*/ - var syncEnabled = true - var syncNotifications = true - var enableSharedEvents = true - var countInSeconds = false - var loggedIn = false var empty = true var archived = false - /** - * The name of the student. - * This doesn't change, no matter if it's a parent or student account. - */ - var studentNameLong: String? = null - var studentNameShort: String? = null + var syncEnabled = true + var enableSharedEvents = true + var registration = REGISTRATION_UNSPECIFIED + var userCode = "" + /** * The student's number in the class register. */ var studentNumber = -1 - var studentData: JsonObject? = null - - /** - * A full name of the account owner. - * If null, then it's a student account. - * If not null, then it's a parent account with this name. - */ - var accountNameLong: String? = null - var studentClassName: String? = null - var studentSchoolYear: String? = null + var studentSchoolYearStart = Date.getToday().let { if (it.month < 9) it.year - 1 else it.year } - var registration = REGISTRATION_UNSPECIFIED - - var gradeColorMode = COLOR_MODE_WEIGHTED - var agendaViewType = AGENDA_DEFAULT - - var yearAverageMode = YEAR_ALL_GRADES - - var currentSemester = 1 - - var attendancePercentage: Float = 0.0f - - var dateSemester1Start: Date? = null - var dateSemester2Start: Date? = null - var dateYearEnd: Date? = null - - var luckyNumberEnabled = true - var luckyNumber = -1 - var luckyNumberDate: Date? = null - - //public Map> eventTypes; - - var loginStoreId = id - - var changedEndpoints: List? = null + var dateSemester1Start = Date(studentSchoolYearStart, 9, 1) + var dateSemester2Start = Date(studentSchoolYearStart + 1, 2, 1) + 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 + @delegate:Ignore + val currentSemester by lazy { dateToSemester(Date.getToday()) } var disabledNotifications: List? = null - var lastFullSync: Long = 0 var lastReceiversSync: Long = 0 - fun shouldFullSync(context: Context): Boolean { - val connManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager - val mWifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI) - // if time since last full sync is > 7 days and wifi is connected - // or - // if time since last full sync is > 14 days, regardless of wifi state - return System.currentTimeMillis() - lastFullSync > 7 * 24 * 60 * 60 * 1000 && mWifi.isConnected || System.currentTimeMillis() - lastFullSync > 14 * 24 * 60 * 60 * 1000 - } + fun hasStudentData(key: String) = studentData.has(key) + fun getStudentData(key: String, defaultValue: Boolean) = studentData.getBoolean(key) ?: defaultValue + fun getStudentData(key: String, defaultValue: String?) = studentData.getString(key) ?: defaultValue + fun getStudentData(key: String, defaultValue: Int) = studentData.getInt(key) ?: defaultValue + fun getStudentData(key: String, defaultValue: Long) = studentData.getLong(key) ?: defaultValue + fun getStudentData(key: String, defaultValue: Float) = studentData.getFloat(key) ?: defaultValue + fun getStudentData(key: String, defaultValue: Char) = studentData.getChar(key) ?: defaultValue + fun putStudentData(key: String, value: Boolean) { studentData[key] = value } + fun putStudentData(key: String, value: String?) { studentData[key] = value } + fun putStudentData(key: String, value: Number) { studentData[key] = value } + fun putStudentData(key: String, value: Char) { studentData[key] = value } + fun removeStudentData(key: String) { studentData.remove(key) } - @Ignore - constructor(id: Int, name: String, subname: String, loginStoreId: Int) : this() { - this.id = id - this.name = name - this.subname = subname - this.loginStoreId = loginStoreId - } - - constructor() { - //eventTypes = new HashMap<>(); - val today = Date.getToday() - val schoolYearStart = if (today.month < 9) today.year - 1 else today.year - dateSemester1Start = Date(schoolYearStart, 9, 1) - dateSemester2Start = Date(schoolYearStart + 1, 2, 1) - dateYearEnd = Date(schoolYearStart + 1, 6, 30) - } - - fun getSemesterStart(semester: Int): Date { - if (dateSemester1Start == null || dateSemester2Start == null || dateYearEnd == null) { - val today = Date.getToday() - val schoolYearStart = if (today.month < 9) today.year - 1 else today.year - dateSemester1Start = Date(schoolYearStart, 9, 1) - dateSemester2Start = Date(schoolYearStart + 1, 2, 1) - dateYearEnd = Date(schoolYearStart + 1, 6, 30) - } - - return if (semester == 1) - dateSemester1Start!! - else - dateSemester2Start!! - } - - fun getSemesterEnd(semester: Int): Date { - if (dateSemester1Start == null || dateSemester2Start == null || dateYearEnd == null) { - val today = Date.getToday() - val schoolYearStart = if (today.month < 9) today.year - 1 else today.year - dateSemester1Start = Date(schoolYearStart, 9, 1) - dateSemester2Start = Date(schoolYearStart + 1, 2, 1) - dateYearEnd = Date(schoolYearStart + 1, 6, 30) - } - - return if (semester == 1) - dateSemester2Start!!.clone().stepForward(0, 0, -1) - else - dateYearEnd!! - } - - fun dateToSemester(date: Date?): Int { - if (date == null) - return 1 - return if (date.value >= getSemesterStart(2).value) 2 else 1 - } - - @Ignore - constructor(context: Context) { - //RegisterEvent.checkPredefinedEventTypes(context, eventTypes); - } + val isParent + get() = accountName != null override fun getImageDrawable(context: Context): Drawable { @@ -179,13 +132,6 @@ open class Profile : IDrawerProfile { it.colorFilter = PorterDuffColorFilter(colorFromName(name), PorterDuff.Mode.DST_OVER) } - /*if (profileImage == null) { - profileImage = BitmapFactory.decodeResource(getResources(), pl.szczodrzynski.edziennik.R.drawable.profile); - } - profileImage = ThumbnailUtils.extractThumbnail(profileImage, Math.min(profileImage.getWidth(), profileImage.getHeight()), Math.min(profileImage.getWidth(), profileImage.getHeight())); - RoundedBitmapDrawable roundDrawable = RoundedBitmapDrawableFactory.create(getResources(), profileImage); - roundDrawable.setCircular(true); - return roundDrawable;*/ } override fun getImageHolder(context: Context): ImageHolder { return if (!image.isNullOrEmpty()) { @@ -203,130 +149,43 @@ open class Profile : IDrawerProfile { getImageHolder(imageView.context).applyTo(imageView) } - fun hasStudentData(key: String): Boolean { - if (studentData == null) - return false - return studentData?.has(key) ?: false - } - - fun getStudentData(key: String, defaultValue: String?): String? { - if (studentData == null) - return defaultValue - val element = studentData!!.get(key) - return if (element != null) { - element.asString - } else defaultValue - } - - fun getStudentData(key: String, defaultValue: Int): Int { - if (studentData == null) - return defaultValue - val element = studentData!!.get(key) - return element?.asInt ?: defaultValue - } - - fun getStudentData(key: String, defaultValue: Long): Long { - if (studentData == null) - return defaultValue - val element = studentData!!.get(key) - return element?.asLong ?: defaultValue - } - - fun getStudentData(key: String, defaultValue: Float): Float { - if (studentData == null) - return defaultValue - val element = studentData!!.get(key) - return element?.asFloat ?: defaultValue - } - - fun getStudentData(key: String, defaultValue: Boolean): Boolean { - if (studentData == null) - return defaultValue - val element = studentData!!.get(key) - return element?.asBoolean ?: defaultValue - } - - fun putStudentData(key: String, value: String?) { - if (studentData == null) - studentData = JsonObject() - studentData!!.addProperty(key, value) - } - - fun putStudentData(key: String, value: Int) { - if (studentData == null) - studentData = JsonObject() - studentData!!.addProperty(key, value) - } - - fun putStudentData(key: String, value: Long) { - if (studentData == null) - studentData = JsonObject() - studentData!!.addProperty(key, value) - } - - fun putStudentData(key: String, value: Float) { - if (studentData == null) - studentData = JsonObject() - studentData!!.addProperty(key, value) - } - - fun putStudentData(key: String, value: Boolean) { - if (studentData == null) - studentData = JsonObject() - studentData!!.addProperty(key, value) - } - - fun removeStudentData(key: String) { - if (studentData == null) - studentData = JsonObject() - studentData!!.remove(key) - } - - fun clearStudentStore() { - studentData = JsonObject() - } - - override fun toString(): String { - return "Profile{" + - "id=" + id + - ", name='" + name + '\''.toString() + - ", subname='" + subname + '\''.toString() + - ", image='" + image + '\''.toString() + - ", syncEnabled=" + syncEnabled + - ", syncNotifications=" + syncNotifications + - ", enableSharedEvents=" + enableSharedEvents + - ", empty=" + empty + - ", studentNameLong='" + studentNameLong + '\''.toString() + - ", studentNameShort='" + studentNameShort + '\''.toString() + - ", studentNumber=" + studentNumber + - ", studentData=" + studentData.toString() + - ", registration=" + registration + - ", gradeColorMode=" + gradeColorMode + - ", agendaViewType=" + agendaViewType + - ", currentSemester=" + currentSemester + - ", attendancePercentage=" + attendancePercentage + - ", dateSemester1Start=" + dateSemester1Start + - ", dateSemester2Start=" + dateSemester2Start + - ", dateYearEnd=" + dateYearEnd + - ", luckyNumberEnabled=" + luckyNumberEnabled + - ", luckyNumber=" + luckyNumber + - ", luckyNumberDate=" + luckyNumberDate + - ", loginStoreId=" + loginStoreId + - '}'.toString() - } - - companion object { - const val REGISTRATION_UNSPECIFIED = 0 - const val REGISTRATION_DISABLED = 1 - const val REGISTRATION_ENABLED = 2 - const val COLOR_MODE_DEFAULT = 0 - const val COLOR_MODE_WEIGHTED = 1 - const val AGENDA_DEFAULT = 0 - const val AGENDA_CALENDAR = 1 - const val YEAR_1_AVG_2_AVG = 0 - const val YEAR_1_SEM_2_AVG = 1 - const val YEAR_1_AVG_2_SEM = 2 - const val YEAR_1_SEM_2_SEM = 3 - const val YEAR_ALL_GRADES = 4 - } + val supportedFragments: List + get() = when (loginStoreType) { + LoginStore.LOGIN_TYPE_MOBIDZIENNIK, + LoginStore.LOGIN_TYPE_DEMO, + LoginStore.LOGIN_TYPE_VULCAN -> listOf( + MainActivity.DRAWER_ITEM_TIMETABLE, + MainActivity.DRAWER_ITEM_AGENDA, + MainActivity.DRAWER_ITEM_GRADES, + MainActivity.DRAWER_ITEM_MESSAGES, + MainActivity.DRAWER_ITEM_HOMEWORK, + MainActivity.DRAWER_ITEM_BEHAVIOUR, + MainActivity.DRAWER_ITEM_ATTENDANCE + ) + LoginStore.LOGIN_TYPE_LIBRUS, + LoginStore.LOGIN_TYPE_IDZIENNIK -> listOf( + MainActivity.DRAWER_ITEM_TIMETABLE, + MainActivity.DRAWER_ITEM_AGENDA, + MainActivity.DRAWER_ITEM_GRADES, + MainActivity.DRAWER_ITEM_MESSAGES, + MainActivity.DRAWER_ITEM_HOMEWORK, + MainActivity.DRAWER_ITEM_BEHAVIOUR, + MainActivity.DRAWER_ITEM_ATTENDANCE, + MainActivity.DRAWER_ITEM_ANNOUNCEMENTS + ) + LOGIN_TYPE_EDUDZIENNIK -> listOf( + MainActivity.DRAWER_ITEM_TIMETABLE, + MainActivity.DRAWER_ITEM_AGENDA, + MainActivity.DRAWER_ITEM_GRADES, + MainActivity.DRAWER_ITEM_HOMEWORK, + MainActivity.DRAWER_ITEM_BEHAVIOUR, + MainActivity.DRAWER_ITEM_ATTENDANCE, + MainActivity.DRAWER_ITEM_ANNOUNCEMENTS + ) + else -> listOf( + MainActivity.DRAWER_ITEM_TIMETABLE, + MainActivity.DRAWER_ITEM_AGENDA, + MainActivity.DRAWER_ITEM_GRADES + ) + } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/profiles/ProfileDao.java b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/profiles/ProfileDao.java deleted file mode 100644 index cea18c81..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/profiles/ProfileDao.java +++ /dev/null @@ -1,74 +0,0 @@ -package pl.szczodrzynski.edziennik.data.db.modules.profiles; - -import androidx.annotation.Nullable; -import androidx.lifecycle.LiveData; -import androidx.room.Dao; -import androidx.room.Insert; -import androidx.room.OnConflictStrategy; -import androidx.room.Query; - -import java.util.List; - -import static pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile.REGISTRATION_ENABLED; - -@Dao -public interface ProfileDao { - @Insert(onConflict = OnConflictStrategy.REPLACE) - void add(Profile profile); - - @Insert(onConflict = OnConflictStrategy.REPLACE) - void addAll(List profileList); - - @Query("DELETE FROM profiles WHERE profileId = :profileId") - void remove(int profileId); - - @Query("SELECT profiles.*, loginStores.loginStoreType, loginStores.loginStoreData FROM profiles LEFT JOIN loginStores ON profiles.loginStoreId = loginStores.loginStoreId WHERE profileId = :profileId") - LiveData getById(int profileId); - - @Nullable - @Query("SELECT profiles.*, loginStores.loginStoreType, loginStores.loginStoreData FROM profiles LEFT JOIN loginStores ON profiles.loginStoreId = loginStores.loginStoreId WHERE profileId = :profileId") - ProfileFull getFullByIdNow(int profileId); - - @Query("SELECT* FROM profiles WHERE profileId = :profileId") - Profile getByIdNow(int profileId); - - @Query("SELECT * FROM profiles WHERE profileId >= 0 ORDER BY profileId") - LiveData> getAll(); - - @Query("SELECT * FROM profiles WHERE profileId >= 0 ORDER BY profileId") - List getAllNow(); - - @Query("SELECT profiles.*, loginStores.loginStoreType, loginStores.loginStoreData FROM profiles LEFT JOIN loginStores ON profiles.loginStoreId = loginStores.loginStoreId WHERE profileId >= 0 ORDER BY profileId") - LiveData> getAllFull(); - - @Query("SELECT profiles.*, loginStores.loginStoreType, loginStores.loginStoreData FROM profiles LEFT JOIN loginStores ON profiles.loginStoreId = loginStores.loginStoreId WHERE profileId >= 0 ORDER BY profileId") - List getAllFullNow(); - - @Query("SELECT profileId FROM profiles WHERE loginStoreId = :loginStoreId ORDER BY profileId") - List getIdsByLoginStoreIdNow(int loginStoreId); - - @Query("SELECT * FROM profiles WHERE syncEnabled = 1 AND archived = 0 AND profileId >= 0 ORDER BY profileId") - List getProfilesForSyncNow(); - - @Query("SELECT profileId FROM profiles WHERE syncEnabled = 1 AND archived = 0 AND profileId >= 0 ORDER BY profileId") - List getIdsForSyncNow(); - - @Query("SELECT profileId FROM profiles WHERE profileId >= 0 ORDER BY profileId") - List getIdsNow(); - - @Query("SELECT profiles.*, loginStores.* FROM teams JOIN profiles USING(profileId) LEFT JOIN loginStores ON profiles.loginStoreId = loginStores.loginStoreId WHERE teamCode = :teamCode AND registration = "+ REGISTRATION_ENABLED +" AND enableSharedEvents = 1") - List getByTeamCodeNowWithRegistration(String teamCode); - - @Query("SELECT profileId FROM profiles WHERE profileId >= 0 ORDER BY profileId ASC LIMIT 1") - int getFirstId(); - - @Query("SELECT profileId FROM profiles WHERE profileId >= 0 ORDER BY profileId DESC LIMIT 1") - int getLastId(); - - @Query("UPDATE profiles SET loginStoreId = :targetId WHERE loginStoreId = :sourceId") - void changeStoreId(int sourceId, int targetId); - - @Query("UPDATE profiles SET currentSemester = :semester WHERE profileId = :profileId") - void changeSemester(int profileId, int semester); -} - diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/profiles/ProfileDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/profiles/ProfileDao.kt new file mode 100644 index 00000000..90e29e4f --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/profiles/ProfileDao.kt @@ -0,0 +1,55 @@ +package pl.szczodrzynski.edziennik.data.db.modules.profiles + +import androidx.lifecycle.LiveData +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query + +@Dao +interface ProfileDao { + @Insert(onConflict = OnConflictStrategy.REPLACE) + fun add(profile: Profile) + + @Insert(onConflict = OnConflictStrategy.REPLACE) + fun addAll(profileList: List) + + @Query("DELETE FROM profiles WHERE profileId = :profileId") + fun remove(profileId: Int) + + @Query("SELECT profiles.* FROM profiles WHERE profileId = :profileId") + fun getById(profileId: Int): LiveData + + @Query("SELECT * FROM profiles WHERE profileId = :profileId") + fun getByIdNow(profileId: Int): Profile? + + @get:Query("SELECT * FROM profiles WHERE profileId >= 0 ORDER BY profileId") + val all: LiveData> + + @get:Query("SELECT * FROM profiles WHERE profileId >= 0 ORDER BY profileId") + val allNow: List + + @get:Query("SELECT COUNT(profileId) FROM profiles WHERE profileId >= 0") + val count: Int + + @Query("SELECT profileId FROM profiles WHERE loginStoreId = :loginStoreId ORDER BY profileId") + fun getIdsByLoginStoreIdNow(loginStoreId: Int): List + + @get:Query("SELECT * FROM profiles WHERE syncEnabled = 1 AND archived = 0 AND profileId >= 0 ORDER BY profileId") + val profilesForSyncNow: List + + @get:Query("SELECT profileId FROM profiles WHERE syncEnabled = 1 AND archived = 0 AND profileId >= 0 ORDER BY profileId") + val idsForSyncNow: List + + @get:Query("SELECT profileId FROM profiles WHERE profileId >= 0 ORDER BY profileId") + val idsNow: List + + @Query("SELECT profiles.* FROM teams JOIN profiles USING(profileId) WHERE teamCode = :teamCode AND registration = " + Profile.REGISTRATION_ENABLED + " AND enableSharedEvents = 1") + fun getByTeamCodeNowWithRegistration(teamCode: String?): List + + @get:Query("SELECT profileId FROM profiles WHERE profileId >= 0 ORDER BY profileId ASC LIMIT 1") + val firstId: Int? + + @get:Query("SELECT profileId FROM profiles WHERE profileId >= 0 ORDER BY profileId DESC LIMIT 1") + val lastId: Int? +} \ No newline at end of file diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/profiles/ProfileFull.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/profiles/ProfileFull.kt deleted file mode 100644 index 365e2736..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/profiles/ProfileFull.kt +++ /dev/null @@ -1,246 +0,0 @@ -package pl.szczodrzynski.edziennik.data.db.modules.profiles - -import android.content.Context -import androidx.room.ColumnInfo -import androidx.room.Ignore -import com.google.gson.JsonObject -import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_AGENDA -import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_ANNOUNCEMENTS -import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_ATTENDANCE -import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_BEHAVIOUR -import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_GRADES -import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_HOMEWORK -import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_MESSAGES -import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_TIMETABLE -import pl.szczodrzynski.edziennik.crc32 -import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_EDUDZIENNIK -import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore -import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.* -import java.util.* - -class ProfileFull : Profile { - @ColumnInfo(name = "loginStoreType") - var loginStoreType: Int = 0 - @ColumnInfo(name = "loginStoreData") - var loginStoreData: JsonObject? = null - - val usernameId: String - get() { - if (loginStoreData == null) { - return "NO_LOGIN_STORE" - } - if (studentData == null) { - return "NO_STUDENT_STORE" - } - return when (loginStoreType) { - LOGIN_TYPE_MOBIDZIENNIK -> getLoginData("serverName", "MOBI_UN") + ":" + getLoginData("username", "MOBI_UN") + ":" + getStudentData("studentId", -1) - LOGIN_TYPE_LIBRUS -> getStudentData("schoolName", "LIBRUS_UN") + ":" + getStudentData("accountLogin", "LIBRUS_LOGIN_UN") - LOGIN_TYPE_IUCZNIOWIE -> getLoginData("schoolName", "IUCZNIOWIE_UN") + ":" + getLoginData("username", "IUCZNIOWIE_UN") + ":" + getStudentData("registerId", -1) - LOGIN_TYPE_VULCAN -> getStudentData("schoolName", "VULCAN_UN") + ":" + getStudentData("studentId", -1) - LOGIN_TYPE_EDUDZIENNIK -> getStudentData("schoolName", "EDU_UN") + ":" + getLoginData("email", "EDU_UN") + ":" + getStudentData("studentId", null)?.crc32() - LOGIN_TYPE_DEMO -> getLoginData("serverName", "DEMO_UN") + ":" + getLoginData("username", "DEMO_UN") + ":" + getStudentData("studentId", -1) - else -> "TYPE_UNKNOWN" - } - } - - // example (minimal) list of fragments - // there will never be less available options - val supportedFragments: List - get() { - val fragmentIds: MutableList - when (loginStoreType) { - LOGIN_TYPE_MOBIDZIENNIK, LOGIN_TYPE_DEMO, LOGIN_TYPE_VULCAN -> { - fragmentIds = ArrayList() - fragmentIds.add(DRAWER_ITEM_TIMETABLE) - fragmentIds.add(DRAWER_ITEM_AGENDA) - fragmentIds.add(DRAWER_ITEM_GRADES) - fragmentIds.add(DRAWER_ITEM_MESSAGES) - fragmentIds.add(DRAWER_ITEM_HOMEWORK) - fragmentIds.add(DRAWER_ITEM_BEHAVIOUR) - fragmentIds.add(DRAWER_ITEM_ATTENDANCE) - return fragmentIds - } - LOGIN_TYPE_LIBRUS, LOGIN_TYPE_IUCZNIOWIE -> { - fragmentIds = ArrayList() - fragmentIds.add(DRAWER_ITEM_TIMETABLE) - fragmentIds.add(DRAWER_ITEM_AGENDA) - fragmentIds.add(DRAWER_ITEM_GRADES) - fragmentIds.add(DRAWER_ITEM_MESSAGES) - fragmentIds.add(DRAWER_ITEM_HOMEWORK) - fragmentIds.add(DRAWER_ITEM_BEHAVIOUR) - fragmentIds.add(DRAWER_ITEM_ATTENDANCE) - fragmentIds.add(DRAWER_ITEM_ANNOUNCEMENTS) - return fragmentIds - } - LOGIN_TYPE_EDUDZIENNIK -> { - fragmentIds = ArrayList() - fragmentIds.add(DRAWER_ITEM_TIMETABLE) - fragmentIds.add(DRAWER_ITEM_AGENDA) - fragmentIds.add(DRAWER_ITEM_GRADES) - fragmentIds.add(DRAWER_ITEM_HOMEWORK) - fragmentIds.add(DRAWER_ITEM_BEHAVIOUR) - fragmentIds.add(DRAWER_ITEM_ATTENDANCE) - fragmentIds.add(DRAWER_ITEM_ANNOUNCEMENTS) - return fragmentIds - } - } - fragmentIds = ArrayList() - fragmentIds.add(DRAWER_ITEM_TIMETABLE) - fragmentIds.add(DRAWER_ITEM_AGENDA) - fragmentIds.add(DRAWER_ITEM_GRADES) - return fragmentIds - } - - constructor() : super() - - constructor(profile: Profile, loginStore: LoginStore) { - - /*Profile::class.memberProperties.forEach { profileProperty -> - if (profileProperty.visibility == KVisibility.PUBLIC) { - ProfileFull::class.memberProperties.singleOrNull { it.name == profileProperty.name }?.let { fullProperty -> - if (fullProperty is KMutableProperty<*>) { - fullProperty.setter.call(this, profileProperty.get(profile)) - } - } - } - }*/ - - Profile::class.java.declaredFields.forEach { profileProperty -> - profileProperty.isAccessible = true - profileProperty.set(this, profileProperty.get(profile)) - } - - this.loginStoreType = loginStore.type - this.loginStoreId = loginStore.id - this.loginStoreData = loginStore.data - /*for (Field field: LoginStore.class.getFields()) { - try { - ProfileFull.class.getField(field.getName()).set(this, field.get(loginStore)); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (NoSuchFieldException e) { - e.printStackTrace(); - } - }*/ - } - - constructor(context: Context) : super(context) - - @Ignore - constructor(id: Int, name: String, subname: String, loginStoreId: Int) : super(id, name, subname, loginStoreId) - - fun canChangeLoginPassword(): Boolean { - return loginStoreType == LOGIN_TYPE_MOBIDZIENNIK || loginStoreType == LOGIN_TYPE_LIBRUS || loginStoreType == LOGIN_TYPE_IUCZNIOWIE - } - - fun changeLoginPassword(password: String) { - if (loginStoreData == null) { - return - } - if (studentData == null) { - return - } - when (loginStoreType) { - LOGIN_TYPE_MOBIDZIENNIK, LOGIN_TYPE_LIBRUS, LOGIN_TYPE_IUCZNIOWIE -> putLoginData("password", password) - } - } - - - fun getLoginData(key: String, defaultValue: String): String { - if (loginStoreData == null) - return defaultValue - val element = loginStoreData!!.get(key) - return if (element != null) { - element.asString - } else defaultValue - } - - fun getLoginData(key: String, defaultValue: Int): Int { - if (loginStoreData == null) - return defaultValue - val element = loginStoreData!!.get(key) - return element?.asInt ?: defaultValue - } - - fun getLoginData(key: String, defaultValue: Long): Long { - if (loginStoreData == null) - return defaultValue - val element = loginStoreData!!.get(key) - return element?.asLong ?: defaultValue - } - - fun getLoginData(key: String, defaultValue: Float): Float { - if (loginStoreData == null) - return defaultValue - val element = loginStoreData!!.get(key) - return element?.asFloat ?: defaultValue - } - - fun getLoginData(key: String, defaultValue: Boolean): Boolean { - if (loginStoreData == null) - return defaultValue - val element = loginStoreData!!.get(key) - return element?.asBoolean ?: defaultValue - } - - fun putLoginData(key: String, value: String) { - forceLoginStore() - loginStoreData!!.addProperty(key, value) - } - - fun putLoginData(key: String, value: Int) { - forceLoginStore() - loginStoreData!!.addProperty(key, value) - } - - fun putLoginData(key: String, value: Long) { - forceLoginStore() - loginStoreData!!.addProperty(key, value) - } - - fun putLoginData(key: String, value: Float) { - forceLoginStore() - loginStoreData!!.addProperty(key, value) - } - - fun putLoginData(key: String, value: Boolean) { - forceLoginStore() - loginStoreData!!.addProperty(key, value) - } - - fun removeLoginData(key: String) { - if (loginStoreData == null) - return - loginStoreData!!.remove(key) - } - - fun clearLoginStore() { - loginStoreData = JsonObject() - } - - private fun forceLoginStore() { - if (loginStoreData == null) { - clearLoginStore() - } - } - - fun loginStoreType(): String { - return when (loginStoreType) { - LOGIN_TYPE_MOBIDZIENNIK -> "LOGIN_TYPE_MOBIDZIENNIK" - LOGIN_TYPE_LIBRUS -> "LOGIN_TYPE_LIBRUS" - LOGIN_TYPE_IUCZNIOWIE -> "LOGIN_TYPE_IDZIENNIK" - LOGIN_TYPE_VULCAN -> "LOGIN_TYPE_VULCAN" - LOGIN_TYPE_DEMO -> "LOGIN_TYPE_DEMO" - else -> "LOGIN_TYPE_UNKNOWN" - } - } - - override fun toString(): String { - return "ProfileFull{" + - "parent=" + super.toString() + - "loginStoreId=" + loginStoreId + - ", loginStoreType=" + loginStoreType() + - ", loginStoreData=" + loginStoreData + - '}'.toString() - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/network/ServerRequest.java b/app/src/main/java/pl/szczodrzynski/edziennik/network/ServerRequest.java index bfc96343..c5cf8ee8 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/network/ServerRequest.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/network/ServerRequest.java @@ -17,7 +17,6 @@ import im.wangchao.mhttp.callback.JsonCallbackHandler; import pl.szczodrzynski.edziennik.App; import pl.szczodrzynski.edziennik.BuildConfig; import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile; -import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull; import pl.szczodrzynski.edziennik.utils.Utils; import static pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile.REGISTRATION_ENABLED; @@ -33,8 +32,8 @@ public class ServerRequest { this(app, url, source, app.profile); } - public ServerRequest(App app, String url, String source, ProfileFull profileFull) { - this(app, url, source, profileFull, profileFull == null ? -1 : profileFull.getLoginStoreType(), profileFull == null ? "" : profileFull.getUsernameId()); + public ServerRequest(App app, String url, String source, Profile profileFull) { + this(app, url, source, profileFull, profileFull == null ? -1 : profileFull.getLoginStoreType(), profileFull == null ? "" : profileFull.getUserCode()); } public ServerRequest(App app, String url, String source, Profile profile, int loginStoreType, String usernameId) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/sync/MyFirebaseMessagingService.java b/app/src/main/java/pl/szczodrzynski/edziennik/sync/MyFirebaseMessagingService.java index 546f760e..5a07d43d 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/sync/MyFirebaseMessagingService.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/sync/MyFirebaseMessagingService.java @@ -22,7 +22,7 @@ import pl.szczodrzynski.edziennik.data.db.modules.events.Event; import pl.szczodrzynski.edziennik.data.db.modules.events.EventFull; import pl.szczodrzynski.edziennik.data.db.modules.events.EventType; import pl.szczodrzynski.edziennik.data.db.modules.feedback.FeedbackMessage; -import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull; +import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile; import pl.szczodrzynski.edziennik.data.db.modules.teams.Team; import pl.szczodrzynski.edziennik.network.ServerRequest; import pl.szczodrzynski.edziennik.ui.modules.base.DebugFragment; @@ -88,11 +88,11 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService { if (studentIdStr != null) { int studentId = strToInt(studentIdStr); AsyncTask.execute(() -> { - List profileList = app.db.profileDao().getAllFullNow(); + List profileList = app.db.profileDao().getAllNow(); - ProfileFull profile = null; + Profile profile = null; - for (ProfileFull profileFull: profileList) { + for (Profile profileFull: profileList) { if (profileFull.getLoginStoreType() == LOGIN_TYPE_MOBIDZIENNIK && studentId == profileFull.getStudentData("studentId", -1)) { profile = profileFull; @@ -185,7 +185,7 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService { .withType(TYPE_SERVER_MESSAGE) .withFragmentRedirect(MainActivity.DRAWER_ITEM_NOTIFICATIONS) ); - app.notifier.postAll(null); + app.notifier.postAll(); app.saveConfig("notifications"); break; case "feedback_message_from_dev": @@ -212,7 +212,7 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService { .withType(TYPE_FEEDBACK_MESSAGE) .withFragmentRedirect(MainActivity.TARGET_FEEDBACK) ); - app.notifier.postAll(null); + app.notifier.postAll(); app.saveConfig("notifications"); } }); @@ -234,7 +234,7 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService { .withType(TYPE_FEEDBACK_MESSAGE) .withFragmentRedirect(MainActivity.TARGET_FEEDBACK) ); - app.notifier.postAll(null); + app.notifier.postAll(); app.saveConfig("notifications"); break; case "ping": @@ -254,8 +254,8 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService { while (teamCode != null || teamUnshareCode != null) { d(TAG, "Got an event for teamCode " + teamCode + " and teamUnshareCode " + teamUnshareCode); // get the target Profile by the corresponding teamCode - List profiles = app.db.profileDao().getByTeamCodeNowWithRegistration(teamCode == null ? teamUnshareCode : teamCode); - for (ProfileFull profile : profiles) { + List profiles = app.db.profileDao().getByTeamCodeNowWithRegistration(teamCode == null ? teamUnshareCode : teamCode); + for (Profile profile : profiles) { d(TAG, "Matched profile " + profile.getName()); if (teamCode != null) { // SHARING @@ -276,7 +276,7 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService { // TODO? i guess Event oldEvent = app.db.eventDao().getByIdNow(profile.getId(), event.id); - if (event.sharedBy != null && event.sharedBy.equals(profile.getUsernameId())) { + if (event.sharedBy != null && event.sharedBy.equals(profile.getUserCode())) { d(TAG, "Shared by self! Changing name"); event.sharedBy = "self"; event.sharedByName = profile.getStudentNameLong(); @@ -318,7 +318,7 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService { teamUnshareCode = null; } } - app.notifier.postAll(null); + app.notifier.postAll(); app.saveConfig(); }); break; diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualDialog.kt index ab713135..3f2d224b 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualDialog.kt @@ -21,7 +21,6 @@ import kotlinx.coroutines.* import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_AGENDA import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi -import pl.szczodrzynski.edziennik.data.api.task.SzkolnyTask import pl.szczodrzynski.edziennik.data.db.modules.events.Event import pl.szczodrzynski.edziennik.data.db.modules.events.EventFull import pl.szczodrzynski.edziennik.data.db.modules.events.EventType @@ -609,7 +608,7 @@ class EventManualDialog( ) launch { - val profile = app.db.profileDao().getFullByIdNow(profileId) + val profile = app.db.profileDao().getByIdNow(profileId) if (!share && !editingShared) { Toast.makeText(activity, "Save without sharing", Toast.LENGTH_SHORT).show() @@ -643,7 +642,7 @@ class EventManualDialog( Toast.makeText(activity, "Share/update own event", Toast.LENGTH_SHORT).show() eventObject.apply { - sharedBy = profile?.usernameId + sharedBy = profile?.userCode sharedByName = profile?.studentNameLong } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/grade/GradeDetailsDialog.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/grade/GradeDetailsDialog.java index 30b6fc42..ae71ed47 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/grade/GradeDetailsDialog.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/grade/GradeDetailsDialog.java @@ -74,7 +74,7 @@ public class GradeDetailsDialog { b.setGrade(grade); int gradeColor; - if (app.profile.getGradeColorMode() == COLOR_MODE_DEFAULT) { + if (App.getConfig().getFor(profileId).getGrades().getColorMode() == COLOR_MODE_DEFAULT) { gradeColor = grade.color; } else { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceFragment.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceFragment.java index 68942d5b..3fc6d344 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceFragment.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceFragment.java @@ -312,10 +312,7 @@ public class AttendanceFragment extends Fragment { float attendancePercentage; // in Mobidziennik there are no TYPE_PRESENT records so we cannot calculate the percentage - if (app.profile.getLoginStoreType() == LOGIN_TYPE_MOBIDZIENNIK && false) { - attendancePercentage = app.profile.getAttendancePercentage(); - } - else if (app.profile.getLoginStoreType() == LOGIN_TYPE_VULCAN) { + if (app.profile.getLoginStoreType() == LOGIN_TYPE_VULCAN) { float allCount = presentCount + absentCount + belatedCount; // do not count releases float present = allCount - absentCount; attendancePercentage = present / allCount * 100.0f; diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/base/CrashActivity.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/base/CrashActivity.kt index 229d5926..a010dba8 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/base/CrashActivity.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/base/CrashActivity.kt @@ -138,7 +138,7 @@ class CrashActivity : AppCompatActivity(), CoroutineScope { content = content.replace("\n".toRegex(), "
") contentPlain += "\n" + Build.MANUFACTURER + "\n" + Build.BRAND + "\n" + Build.MODEL + "\n" + Build.DEVICE + "\n" if (app.profile != null && app.profile.registration == Profile.REGISTRATION_ENABLED) { - contentPlain += "U: " + app.profile.usernameId + "\nS: " + app.profile.studentNameLong + "\n" + contentPlain += "U: " + app.profile.userCode + "\nS: " + app.profile.studentNameLong + "\n" } contentPlain += BuildConfig.VERSION_NAME + " " + BuildConfig.BUILD_TYPE return if (plain) contentPlain else content diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/behaviour/NoticesAdapter.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/behaviour/NoticesAdapter.kt index 39ab4efd..1487ef10 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/behaviour/NoticesAdapter.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/behaviour/NoticesAdapter.kt @@ -18,7 +18,7 @@ import com.mikepenz.iconics.utils.colorRes import com.mikepenz.iconics.utils.sizeDp import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.R -import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_MOBIDZIENNIK +import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_MOBIDZIENNIK import pl.szczodrzynski.edziennik.data.db.modules.notices.Notice import pl.szczodrzynski.edziennik.data.db.modules.notices.NoticeFull import pl.szczodrzynski.edziennik.utils.Utils.bs diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesFragment.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesFragment.java index 00af375a..54b3162a 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesFragment.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesFragment.java @@ -71,7 +71,7 @@ public class GradesFragment extends Fragment { private boolean sortModeChanged = false; private String getRegisterCardAverageModeSubText() { - switch (app.profile.getYearAverageMode()) { + switch (App.getConfig().forProfile().getGrades().getYearAverageMode()) { default: case YEAR_1_AVG_2_AVG: return getString(R.string.settings_register_avg_mode_0_short); @@ -184,9 +184,8 @@ public class GradesFragment extends Fragment { .title(getString(R.string.settings_register_avg_mode_dialog_title)) .content(getString(R.string.settings_register_avg_mode_dialog_text)) .items(modeNames) - .itemsCallbackSingleChoice(modeIds.indexOf(app.profile.getYearAverageMode()), (dialog, itemView, which, text) -> { - app.profile.setYearAverageMode(modeIds.get(which)); - app.profileSaveAsync(); + .itemsCallbackSingleChoice(modeIds.indexOf(App.getConfig().forProfile().getGrades().getYearAverageMode()), (dialog, itemView, which, text) -> { + App.getConfig().forProfile().getGrades().setYearAverageMode(modeIds.get(which)); activity.reloadTarget(); return true; }) @@ -253,11 +252,16 @@ public class GradesFragment extends Fragment { for (GradeFull grade: grades) { ItemGradesSubjectModel model = ItemGradesSubjectModel.searchModelBySubjectId(subjectList, grade.subjectId); if (model == null) { - model = new ItemGradesSubjectModel(app.profile, new Subject(App.profileId, grade.subjectId, grade.subjectLongName, grade.subjectShortName), new ArrayList<>(), new ArrayList<>());//ItemGradesSubjectModel.searchModelBySubjectId(subjectList, grade.subjectId); + model = new ItemGradesSubjectModel(app.profile, + new Subject(App.profileId, grade.subjectId, grade.subjectLongName, grade.subjectShortName), + new ArrayList<>(), + new ArrayList<>()); subjectList.add(model); if (model.subject != null && model.subject.id == finalExpandSubjectId) { model.expandView = true; } + model.colorMode = App.getConfig().forProfile().getGrades().getColorMode(); + model.yearAverageMode = App.getConfig().forProfile().getGrades().getYearAverageMode(); } if (!grade.seen && grade.semester == 1) { model.semester1Unread++; @@ -376,7 +380,7 @@ public class GradesFragment extends Fragment { else if (!model.isBehaviourSubject && model.isNormalSubject) { // applies for normal grades & normal+descriptive grades // calculate the normal grade average based on the user's setting - switch (app.profile.getYearAverageMode()) { + switch (App.getConfig().forProfile().getGrades().getYearAverageMode()) { case YEAR_1_AVG_2_AVG: model.yearAverage = (model.semester1Average + model.semester2Average) / 2; break; diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesListAdapter.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesListAdapter.java index 8b1cad99..38cd5591 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesListAdapter.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesListAdapter.java @@ -56,7 +56,7 @@ public class GradesListAdapter extends RecyclerView.Adapter i continue; int gradeColor; - if (model.profile.getGradeColorMode() == COLOR_MODE_DEFAULT) { + if (model.colorMode == COLOR_MODE_DEFAULT) { gradeColor = grade.color; } else { gradeColor = Colors.gradeToColor(grade); @@ -581,13 +581,13 @@ public class GradesSubjectAdapter extends ArrayAdapter i } arguments.putInt("semester", 1); //d(TAG, "Model is " + model); - switch (model.profile.getYearAverageMode()) { + switch (model.yearAverageMode) { case YEAR_1_SEM_2_AVG: case YEAR_1_SEM_2_SEM: arguments.putInt("averageMode", -1); break; default: - arguments.putInt("averageMode", model.semester2Final == null && model.profile.getYearAverageMode() == YEAR_1_AVG_2_SEM ? -1 : model.profile.getYearAverageMode()); + arguments.putInt("averageMode", model.semester2Final == null && model.yearAverageMode == YEAR_1_AVG_2_SEM ? -1 : model.yearAverageMode); arguments.putFloat("yearAverageBefore", model.yearAverage); arguments.putFloat("gradeSumOtherSemester", model.gradeSumSemester2); arguments.putFloat("gradeCountOtherSemester", model.gradeCountSemester2); @@ -607,13 +607,13 @@ public class GradesSubjectAdapter extends ArrayAdapter i } arguments.putInt("semester", 2); //d(TAG, "Model is " + model); - switch (model.profile.getYearAverageMode()) { + switch (model.yearAverageMode) { case YEAR_1_AVG_2_SEM: case YEAR_1_SEM_2_SEM: arguments.putInt("averageMode", -1); break; default: - arguments.putInt("averageMode", model.semester1Final == null && model.profile.getYearAverageMode() == YEAR_1_SEM_2_AVG ? -1 : model.profile.getYearAverageMode()); + arguments.putInt("averageMode", model.semester1Final == null && model.yearAverageMode == YEAR_1_SEM_2_AVG ? -1 : model.yearAverageMode); arguments.putFloat("yearAverageBefore", model.yearAverage); arguments.putFloat("gradeSumOtherSemester", model.gradeSumSemester1); arguments.putFloat("gradeCountOtherSemester", model.gradeCountSemester1); diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragmentOld.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragmentOld.java index d86e1d54..b3bf1cc6 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragmentOld.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragmentOld.java @@ -51,7 +51,6 @@ import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeFull; import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonFull; import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile; import pl.szczodrzynski.edziennik.data.db.modules.subjects.Subject; -import pl.szczodrzynski.edziennik.databinding.CardLuckyNumberBinding; import pl.szczodrzynski.edziennik.databinding.CardUpdateBinding; import pl.szczodrzynski.edziennik.databinding.FragmentHomeOldBinding; import pl.szczodrzynski.edziennik.receivers.BootReceiver; @@ -240,24 +239,6 @@ public class HomeFragmentOld extends Fragment { } } - if (app.profile.getLuckyNumberEnabled() - && app.profile.getLuckyNumber() != -1 - && app.profile.getLuckyNumberDate() != null && app.profile.getLuckyNumberDate().getValue() == Date.getToday().getValue()) { - CardLuckyNumberBinding b; - b = DataBindingUtil.inflate(layoutInflater, R.layout.card_lucky_number, insertPoint, false); - insertPoint.addView(b.getRoot()); - - b.cardLuckyNumberTitle.setText(getString(R.string.card_lucky_number_title_format, app.profile.getLuckyNumber())); - if (app.profile.getStudentNumber() == -1) { - b.cardLuckyNumberText.setText(R.string.card_lucky_number_not_set); - } - else { - b.cardLuckyNumberText.setText(getString(R.string.card_lucky_number_text_format, app.profile.getStudentNumber())); - } - - b.cardLuckyNumber.setOnClickListener(v1 -> setNumberDialog()); - } - timetableCard = new HomeTimetableCardOld(app, activity, this, layoutInflater, insertPoint); timetableCard.run(); @@ -498,7 +479,7 @@ public class HomeFragmentOld extends Fragment { if (ellipsized) continue; int gradeColor; - if (app.profile.getGradeColorMode() == Profile.COLOR_MODE_DEFAULT) { + if (App.getConfig().forProfile().getGrades().getColorMode() == Profile.COLOR_MODE_DEFAULT) { gradeColor = grade.color; } else { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeGradesCard.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeGradesCard.kt index 8d5a5fc5..de223091 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeGradesCard.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeGradesCard.kt @@ -121,7 +121,7 @@ class HomeGradesCard( 16 /*ellipsize width*/)) / 1.5f subject.grades1.onEach { grade -> - val gradeColor = when (app.profile.gradeColorMode) { + val gradeColor = when (App.getConfig().forProfile().grades.colorMode) { Profile.COLOR_MODE_DEFAULT -> grade.color else -> Colors.gradeToColor(grade) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginActivity.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginActivity.java deleted file mode 100644 index 4606a3a5..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginActivity.java +++ /dev/null @@ -1,161 +0,0 @@ -package pl.szczodrzynski.edziennik.ui.modules.login; - -import android.os.Bundle; - -import androidx.appcompat.app.AppCompatActivity; -import androidx.databinding.DataBindingUtil; -import androidx.navigation.NavDestination; -import androidx.navigation.NavOptions; -import androidx.navigation.Navigation; - -import com.afollestad.materialdialogs.MaterialDialog; - -import java.util.ArrayList; -import java.util.List; - -import pl.szczodrzynski.edziennik.App; -import pl.szczodrzynski.edziennik.R; -import pl.szczodrzynski.edziennik.data.api.models.ApiError; -import pl.szczodrzynski.edziennik.databinding.ActivityLoginBinding; -import pl.szczodrzynski.edziennik.ui.modules.error.ErrorSnackbar; - -public class LoginActivity extends AppCompatActivity { - - private ActivityLoginBinding b; - private App app; - private static final String TAG = "LoginActivity"; - public static final int RESULT_OK = 1; - public static NavOptions navOptions; - - static ApiError error = null; - ErrorSnackbar errorSnackbar = new ErrorSnackbar(this); - - static List profileObjects; - public static boolean firstCompleted = false; // if a profile is already added during *this* login. This means that LoginChooser has to navigateUp onBackPressed. Else, finish the activity. - public static boolean privacyPolicyAccepted = false; - - @Override - public void onBackPressed() { - NavDestination destination = Navigation.findNavController(this, R.id.nav_host_fragment).getCurrentDestination(); - if (destination != null && destination.getId() == R.id.loginSyncErrorFragment) { - return; - } - if (destination != null && destination.getId() == R.id.loginProgressFragment) { - return; - } - if (destination != null && destination.getId() == R.id.loginSyncFragment) { - return; - } - if (destination != null && destination.getId() == R.id.loginChooserFragment && !firstCompleted) { - setResult(RESULT_CANCELED); - finish(); - return; - } - if (destination != null && destination.getId() == R.id.loginSummaryFragment) { - new MaterialDialog.Builder(this) - .title(R.string.are_you_sure) - .content(R.string.login_cancel_confirmation) - .positiveText(R.string.yes) - .negativeText(R.string.no) - .onPositive((dialog, which) -> { - setResult(RESULT_CANCELED); - finish(); - }) - .show(); - return; - } - Navigation.findNavController(this, R.id.nav_host_fragment).navigateUp(); - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setTheme(R.style.AppTheme_Light); - - firstCompleted = false; - profileObjects = new ArrayList<>(); - error = null; - - navOptions = new NavOptions.Builder() - .setEnterAnim(R.anim.slide_in_right) - .setExitAnim(R.anim.slide_out_left) - .setPopEnterAnim(R.anim.slide_in_left) - .setPopExitAnim(R.anim.slide_out_right) - .build(); - - b = DataBindingUtil.inflate(getLayoutInflater(), R.layout.activity_login, null, false); - setContentView(b.getRoot()); - - errorSnackbar.setCoordinator(b.coordinator, null); - - app = (App) getApplication(); - - if (!app.config.getLoginFinished()) { - app.config.getUi().setMiniMenuVisible(getResources().getConfiguration().smallestScreenWidthDp > 480); - } - - /*b.getRoot().addOnLayoutChangeListener(((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { - Animator circularReveal = null; - float finalRadius = (float) (Math.max(b.revealView.getWidth(), b.revealView.getHeight()) * 1.1); - circularReveal = ViewAnimationUtils.createCircularReveal(b.revealView, b.revealView.getWidth()/2, b.revealView.getHeight()/2, 0, finalRadius); - circularReveal.setDuration(400); - circularReveal.setInterpolator(new AccelerateInterpolator()); - // make the view visible and start the animation - b.revealView.setVisibility(View.VISIBLE); - circularReveal.addListener(new Animator.AnimatorListener() { - @Override public void onAnimationEnd(Animator animation) { - Anim.fadeIn(b.title1, 500, new Animation.AnimationListener() { - @Override public void onAnimationEnd(Animation animation) { - b.title2.postDelayed(() -> { - Anim.fadeIn(b.title2, 500, new Animation.AnimationListener() { - @Override public void onAnimationEnd(Animation animation) { - b.revealView.postDelayed(() -> { - Anim.fadeOut(b.title1, 500, null); - Animation anim2 = null; - anim2 = new Anim.ResizeAnimation(b.revealView, 1.0f, 1.0f, 1.0f, 0.15f); - anim2.setDuration(800); - anim2.setInterpolator(new AccelerateDecelerateInterpolator()); - b.revealView.startAnimation(anim2); - }, 700); - } - @Override public void onAnimationStart(Animation animation) { } - @Override public void onAnimationRepeat(Animation animation) { } - }); - }, 1500); - } - @Override public void onAnimationStart(Animation animation) { } - @Override public void onAnimationRepeat(Animation animation) { } - }); - } - @Override public void onAnimationCancel(Animator animation) { } - @Override public void onAnimationStart(Animator animation) { } - @Override public void onAnimationRepeat(Animator animation) { } - }); - circularReveal.start(); - }));*/ - - /**/ - - /*TextInputEditText e = findViewById(R.id.buttontest); - - e.setOnClickListener((v -> { - Toast.makeText(this, "clicked", Toast.LENGTH_SHORT).show(); - PopupMenu popup = new PopupMenu(this, e); - //popup.getMenu().add(0, 15, 0, HomeFragment.plural(c, R.plurals.time_till_seconds, 15)); - //popup.getMenu().add(0, 15 * 60, 0, HomeFragment.plural(c, R.plurals.time_till_minutes, 15)); - popup.getMenu().add(0, 30 * 60, 0, HomeFragment.plural(this, R.plurals.time_till_minutes, 30)); - popup.getMenu().add(0, 60 * 60, 0, HomeFragment.plural(this, R.plurals.time_till_hours, 1)); - popup.getMenu().add(0, 120 * 60, 0, HomeFragment.plural(this, R.plurals.time_till_hours, 2)); - popup.getMenu().add(0, 180 * 60, 0, HomeFragment.plural(this, R.plurals.time_till_hours, 3)); - popup.getMenu().add(0, 240 * 60, 0, HomeFragment.plural(this, R.plurals.time_till_hours, 4)); - popup.setOnMenuItemClickListener(item -> { - e.setText(item.getTitle()); - return false; - }); - popup.show(); - }));*/ - - - } -} 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 new file mode 100644 index 00000000..e4d07ee4 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginActivity.kt @@ -0,0 +1,96 @@ +package pl.szczodrzynski.edziennik.ui.modules.login + +import android.app.Activity +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.navigation.NavOptions +import androidx.navigation.Navigation +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import pl.szczodrzynski.edziennik.App +import pl.szczodrzynski.edziennik.R +import pl.szczodrzynski.edziennik.data.api.models.ApiError +import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore +import pl.szczodrzynski.edziennik.databinding.ActivityLoginBinding +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 + } + + private val app: App by lazy { applicationContext as App } + private lateinit var b: ActivityLoginBinding + val nav by lazy { Navigation.findNavController(this, R.id.nav_host_fragment) } + val errorSnackbar: ErrorSnackbar by lazy { ErrorSnackbar(this) } + + private val job: Job = Job() + override val coroutineContext: CoroutineContext + get() = job + Dispatchers.Main + + var lastError: ApiError? = null + val profiles = mutableListOf() + val loginStores = mutableListOf() + + override fun onBackPressed() { + val destination = nav.currentDestination + if (destination != null && destination.id == R.id.loginSyncErrorFragment) { + return + } + if (destination != null && destination.id == R.id.loginProgressFragment) { + return + } + if (destination != null && destination.id == R.id.loginSyncFragment) { + return + } + if (destination != null && destination.id == R.id.loginChooserFragment && !app.config.loginFinished) { + setResult(Activity.RESULT_CANCELED) + finish() + return + } + if (destination != null && destination.id == R.id.loginSummaryFragment) { + MaterialAlertDialogBuilder(this) + .setTitle(R.string.are_you_sure) + .setMessage(R.string.login_cancel_confirmation) + .setPositiveButton(R.string.yes) { _, _ -> + setResult(Activity.RESULT_CANCELED) + finish() + } + .setNegativeButton(R.string.no, null) + .show() + return + } + nav.navigateUp() + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setTheme(R.style.AppTheme_Light) + + navOptions = NavOptions.Builder() + .setEnterAnim(R.anim.slide_in_right) + .setExitAnim(R.anim.slide_out_left) + .setPopEnterAnim(R.anim.slide_in_left) + .setPopExitAnim(R.anim.slide_out_right) + .build() + + b = ActivityLoginBinding.inflate(layoutInflater) + setContentView(b.root) + errorSnackbar.setCoordinator(b.coordinator, null) + + launch { + app.config.loginFinished = app.db.profileDao().count > 0 + if (!app.config.loginFinished) { + app.config.ui.miniMenuVisible = resources.configuration.smallestScreenWidthDp > 480 + } + } + } + + fun error(error: ApiError) { errorSnackbar.addError(error).show(); lastError = error } +} \ No newline at end of file diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserFragment.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserFragment.java deleted file mode 100644 index 752eaa99..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserFragment.java +++ /dev/null @@ -1,85 +0,0 @@ -package pl.szczodrzynski.edziennik.ui.modules.login; - -import android.content.Intent; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.databinding.DataBindingUtil; -import androidx.fragment.app.Fragment; -import androidx.navigation.NavController; -import androidx.navigation.Navigation; - -import pl.szczodrzynski.edziennik.App; -import pl.szczodrzynski.edziennik.R; -import pl.szczodrzynski.edziennik.databinding.FragmentLoginChooserBinding; -import pl.szczodrzynski.edziennik.ui.modules.feedback.FeedbackActivity; - -import static android.app.Activity.RESULT_CANCELED; - -public class LoginChooserFragment extends Fragment { - - private App app; - private NavController nav; - private FragmentLoginChooserBinding b; - private static final String TAG = "LoginTemplate"; - public static boolean fakeLogin = false; - - public LoginChooserFragment() { } - - @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_chooser, container, false); - return b.getRoot(); - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - assert getContext() != null; - assert getActivity() != null; - - b.loginMobidziennikLogo.setOnClickListener((v) -> nav.navigate(R.id.loginMobidziennikFragment, null, LoginActivity.navOptions)); - b.loginLibrusLogo.setOnClickListener((v) -> nav.navigate(R.id.loginLibrusFragment, null, LoginActivity.navOptions)); - b.loginLibrusJstLogo.setOnClickListener((v) -> nav.navigate(R.id.loginLibrusJstFragment, null, LoginActivity.navOptions)); - b.loginVulcanLogo.setOnClickListener((v) -> nav.navigate(R.id.loginVulcanFragment, null, LoginActivity.navOptions)); - b.loginIuczniowieLogo.setOnClickListener((v) -> nav.navigate(R.id.loginIuczniowieFragment, null, LoginActivity.navOptions)); - b.loginEdudziennikLogo.setOnClickListener((v) -> nav.navigate(R.id.loginEdudziennikFragment, null, LoginActivity.navOptions)); - - if (LoginActivity.firstCompleted) { - // we are navigated here from LoginSummary - b.cancelButton.setVisibility(View.VISIBLE); - b.cancelButton.setOnClickListener((v -> nav.navigateUp())); - } - else if (app.config.getLoginFinished()) { - // we are navigated here from AppDrawer - b.cancelButton.setVisibility(View.VISIBLE); - b.cancelButton.setOnClickListener((v -> { - getActivity().setResult(RESULT_CANCELED); - getActivity().finish(); - })); - } - else { - // there is no profiles - b.cancelButton.setVisibility(View.GONE); - } - - b.fakeLogin.setVisibility(App.devMode ? View.VISIBLE : View.GONE); - b.fakeLogin.setChecked(fakeLogin); - b.fakeLogin.setOnCheckedChangeListener((v, isChecked) -> fakeLogin = isChecked); - - b.helpButton.setOnClickListener((v -> { - startActivity(new Intent(getActivity(), FeedbackActivity.class)); - })); - } -} 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 new file mode 100644 index 00000000..a1fdcf0a --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserFragment.kt @@ -0,0 +1,72 @@ +package pl.szczodrzynski.edziennik.ui.modules.login + +import android.app.Activity +import android.content.Intent +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.CompoundButton +import androidx.fragment.app.Fragment +import pl.szczodrzynski.edziennik.App +import pl.szczodrzynski.edziennik.R +import pl.szczodrzynski.edziennik.databinding.FragmentLoginChooserBinding +import pl.szczodrzynski.edziennik.onClick +import pl.szczodrzynski.edziennik.ui.modules.feedback.FeedbackActivity + +class LoginChooserFragment : Fragment() { + 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 val nav by lazy { activity.nav } + + 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) + return b.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + 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.onClick { nav.navigateUp() } + } + app.config.loginFinished -> { + // we are navigated here from AppDrawer + b.cancelButton.visibility = View.VISIBLE + b.cancelButton.onClick { + activity.setResult(Activity.RESULT_CANCELED) + activity.finish() + } + } + else -> { + // there is no profiles + b.cancelButton.visibility = View.GONE + } + } + + 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)) } + } +} \ No newline at end of file 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 index 89221ee7..d150add9 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) Kacper Ziubryniewicz 2019-12-23 + * Copyright (c) Kuba Szczodrzyński 2020-1-3. */ package pl.szczodrzynski.edziennik.ui.modules.login @@ -9,89 +9,85 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment -import androidx.navigation.NavController -import androidx.navigation.Navigation import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import pl.szczodrzynski.edziennik.App -import pl.szczodrzynski.edziennik.R +import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.data.api.ERROR_LOGIN_EDUDZIENNIK_WEB_INVALID_LOGIN -import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_EDUDZIENNIK +import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_EDUDZIENNIK import pl.szczodrzynski.edziennik.databinding.FragmentLoginEdudziennikBinding -import pl.szczodrzynski.edziennik.startCoroutineTimer -import pl.szczodrzynski.edziennik.ui.modules.error.ErrorSnackbar +import java.util.* import kotlin.coroutines.CoroutineContext class LoginEdudziennikFragment : Fragment(), CoroutineScope { + companion object { + private const val TAG = "LoginEdudziennikFragment" + } - private val app by lazy { activity?.application as App? } + private lateinit var app: App + private lateinit var activity: LoginActivity + private lateinit var b: FragmentLoginEdudziennikBinding + private val nav by lazy { activity.nav } - private var job = Job() + private val job: Job = Job() override val coroutineContext: CoroutineContext get() = job + Dispatchers.Main - private lateinit var b: FragmentLoginEdudziennikBinding - - private lateinit var nav: NavController - private lateinit var errorSnackbar: ErrorSnackbar - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - activity?.also { activity -> - nav = Navigation.findNavController(activity, R.id.nav_host_fragment) - errorSnackbar = (activity as LoginActivity).errorSnackbar - } - - b = FragmentLoginEdudziennikBinding.inflate(inflater, container, false) + 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?) { launch { - startCoroutineTimer(delayMillis = 100) { - val error = LoginActivity.error - - if (error != null) { + 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) } - - errorSnackbar.addError(error) - LoginActivity.error = null } } - b.backButton.setOnClickListener { nav.navigateUp() } - b.loginButton.setOnClickListener { login() } - }} + b.backButton.onClick { nav.navigateUp() } - private fun login() { - var errors = false + b.loginButton.onClick { + var errors = false - b.loginEmailLayout.error = null - b.loginPasswordLayout.error = null + b.loginEmailLayout.error = null + b.loginPasswordLayout.error = null - val emailEditable = b.loginEmail.text - val passwordEditable = b.loginPassword.text + val email = b.loginEmail.text?.toString()?.toLowerCase(Locale.ROOT) ?: "" + val password = b.loginPassword.text?.toString() ?: "" - if (emailEditable.isNullOrBlank()) { - b.loginEmailLayout.error = getString(R.string.login_error_no_email) - errors = true + 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) } - - if (passwordEditable.isNullOrBlank()) { - b.loginPasswordLayout.error = getString(R.string.login_error_no_password) - errors = true - } - - if (errors) - return - - nav.navigate(R.id.loginProgressFragment, Bundle().apply { - putInt("loginType", LOGIN_TYPE_EDUDZIENNIK) - putString("email", emailEditable.toString()) - putString("password", passwordEditable.toString()) - }, LoginActivity.navOptions) } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFinishFragment.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFinishFragment.java deleted file mode 100644 index a5c9cd47..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFinishFragment.java +++ /dev/null @@ -1,67 +0,0 @@ -package pl.szczodrzynski.edziennik.ui.modules.login; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.databinding.DataBindingUtil; -import androidx.fragment.app.Fragment; -import androidx.navigation.NavController; -import androidx.navigation.Navigation; - -import pl.szczodrzynski.edziennik.App; -import pl.szczodrzynski.edziennik.R; -import pl.szczodrzynski.edziennik.MainActivity; -import pl.szczodrzynski.edziennik.databinding.FragmentLoginFinishBinding; - -public class LoginFinishFragment extends Fragment { - - private App app; - private NavController nav; - private FragmentLoginFinishBinding b; - private static final String TAG = "LoginFinishFragment"; - static boolean firstRun = true; - static int firstProfileId = -1; - - public LoginFinishFragment() { } - - @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_finish, container, false); - return b.getRoot(); - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - assert getContext() != null; - assert getActivity() != null; - - if (!firstRun) { - b.loginFinishSubtitle.setText(R.string.login_finish_subtitle_not_first_run); - } - - b.finishButton.setOnClickListener((v -> { - Intent intent = null; - if (firstProfileId != -1) { - intent = new Intent(); - intent.putExtra("profileId", firstProfileId); - intent.putExtra("fragmentId", MainActivity.DRAWER_ITEM_HOME); - } - getActivity().setResult(Activity.RESULT_OK, intent); - getActivity().finish(); - })); - } -} 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 new file mode 100644 index 00000000..d2ab5df4 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFinishFragment.kt @@ -0,0 +1,63 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2020-1-4. + */ + +package pl.szczodrzynski.edziennik.ui.modules.login + +import android.app.Activity +import android.content.Intent +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.App +import pl.szczodrzynski.edziennik.MainActivity +import pl.szczodrzynski.edziennik.R +import pl.szczodrzynski.edziennik.databinding.FragmentLoginFinishBinding +import pl.szczodrzynski.edziennik.onClick +import kotlin.coroutines.CoroutineContext + +class LoginFinishFragment : Fragment(), CoroutineScope { + companion object { + private const val TAG = "LoginFinishFragment" + } + + private lateinit var app: App + private lateinit var activity: LoginActivity + private lateinit var b: FragmentLoginFinishBinding + 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 = FragmentLoginFinishBinding.inflate(inflater) + return b.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + val firstRun = arguments?.getBoolean("firstRun", true) ?: true + if (!firstRun) { + b.loginFinishSubtitle.setText(R.string.login_finish_subtitle_not_first_run) + } + + b.finishButton.onClick { + val firstProfileId = arguments?.getInt("firstProfileId", -1) ?: -1 + if (firstProfileId != -1) { + val intent = Intent() + intent.putExtra("profileId", firstProfileId) + intent.putExtra("fragmentId", MainActivity.DRAWER_ITEM_HOME) + activity.setResult(Activity.RESULT_OK, intent) + } + activity.finish() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginIuczniowieFragment.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginIuczniowieFragment.java deleted file mode 100644 index 05f2f0b7..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginIuczniowieFragment.java +++ /dev/null @@ -1,128 +0,0 @@ -package pl.szczodrzynski.edziennik.ui.modules.login; - -import android.os.Bundle; -import android.text.Editable; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.databinding.DataBindingUtil; -import androidx.fragment.app.Fragment; -import androidx.navigation.NavController; -import androidx.navigation.Navigation; - -import pl.szczodrzynski.edziennik.App; -import pl.szczodrzynski.edziennik.R; -import pl.szczodrzynski.edziennik.data.api.models.ApiError; -import pl.szczodrzynski.edziennik.databinding.FragmentLoginIuczniowieBinding; -import pl.szczodrzynski.edziennik.ui.modules.error.ErrorSnackbar; - -import static pl.szczodrzynski.edziennik.data.api.ErrorsKt.ERROR_LOGIN_IDZIENNIK_WEB_INVALID_LOGIN; -import static pl.szczodrzynski.edziennik.data.api.ErrorsKt.ERROR_LOGIN_IDZIENNIK_WEB_INVALID_SCHOOL_NAME; -import static pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_IUCZNIOWIE; - -public class LoginIuczniowieFragment extends Fragment { - - private App app; - private NavController nav; - private FragmentLoginIuczniowieBinding b; - private static final String TAG = "LoginIuczniowie"; - private ErrorSnackbar errorSnackbar; - - public LoginIuczniowieFragment() { } - - @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); - errorSnackbar = ((LoginActivity) getActivity()).errorSnackbar; - } - else { - return null; - } - b = DataBindingUtil.inflate(inflater, R.layout.fragment_login_iuczniowie, container, false); - return b.getRoot(); - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - assert getContext() != null; - assert getActivity() != null; - - view.postDelayed(() -> { - ApiError error = LoginActivity.error; - if (error != null) { - switch (error.getErrorCode()) { - case ERROR_LOGIN_IDZIENNIK_WEB_INVALID_SCHOOL_NAME: - b.loginSchoolNameLayout.setError(getString(R.string.login_error_incorrect_school_name)); - break; - case ERROR_LOGIN_IDZIENNIK_WEB_INVALID_LOGIN: - b.loginPasswordLayout.setError(getString(R.string.login_error_incorrect_login_or_password)); - break; - } - errorSnackbar.addError(error).show(); - LoginActivity.error = null; - } - }, 100); - - b.helpButton.setOnClickListener((v) -> nav.navigate(R.id.loginIuczniowieHelpFragment, null, LoginActivity.navOptions)); - b.backButton.setOnClickListener((v) -> nav.navigateUp()); - - b.loginButton.setOnClickListener((v) -> { - boolean errors = false; - - b.loginSchoolNameLayout.setError(null); - b.loginUsernameLayout.setError(null); - b.loginPasswordLayout.setError(null); - - Editable schoolNameEditable = b.loginSchoolName.getText(); - Editable usernameEditable = b.loginUsername.getText(); - Editable passwordEditable = b.loginPassword.getText(); - if (schoolNameEditable == null || schoolNameEditable.length() == 0) { - b.loginSchoolNameLayout.setError(getString(R.string.login_error_no_school_name)); - errors = true; - } - if (usernameEditable == null || usernameEditable.length() == 0) { - b.loginUsernameLayout.setError(getString(R.string.login_error_no_username)); - errors = true; - } - if (passwordEditable == null || passwordEditable.length() == 0) { - b.loginPasswordLayout.setError(getString(R.string.login_error_no_password)); - errors = true; - } - - if (errors) - return; - errors = false; - - String schoolName = schoolNameEditable.toString().toLowerCase(); - String username = usernameEditable.toString().toLowerCase(); - String password = passwordEditable.toString(); - b.loginSchoolName.setText(schoolName); - b.loginUsername.setText(username); - if (!schoolName.matches("[a-z0-9_\\-]+")) { - b.loginSchoolNameLayout.setError(getString(R.string.login_error_incorrect_school_name)); - errors = true; - } - if (!username.matches("[a-z0-9_\\-]+")) { - b.loginUsernameLayout.setError(getString(R.string.login_error_incorrect_username)); - errors = true; - } - - if (errors) - return; - errors = false; - - Bundle args = new Bundle(); - args.putInt("loginType", LOGIN_TYPE_IUCZNIOWIE); - args.putString("schoolName", schoolName); - args.putString("username", username); - args.putString("password", password); - nav.navigate(R.id.loginProgressFragment, args, LoginActivity.navOptions); - }); - } -} 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 new file mode 100644 index 00000000..379eee1a --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginIuczniowieFragment.kt @@ -0,0 +1,109 @@ +/* + * 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/LoginLibrusFragment.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginLibrusFragment.java deleted file mode 100644 index 123be31e..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginLibrusFragment.java +++ /dev/null @@ -1,115 +0,0 @@ -package pl.szczodrzynski.edziennik.ui.modules.login; - -import android.os.Bundle; -import android.text.Editable; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.databinding.DataBindingUtil; -import androidx.fragment.app.Fragment; -import androidx.navigation.NavController; -import androidx.navigation.Navigation; - -import pl.szczodrzynski.edziennik.App; -import pl.szczodrzynski.edziennik.R; -import pl.szczodrzynski.edziennik.data.api.models.ApiError; -import pl.szczodrzynski.edziennik.databinding.FragmentLoginLibrusBinding; -import pl.szczodrzynski.edziennik.ui.modules.error.ErrorSnackbar; - -import static pl.szczodrzynski.edziennik.data.api.ErrorsKt.ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN; -import static pl.szczodrzynski.edziennik.data.api.ErrorsKt.ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED; -import static pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_LIBRUS; - -public class LoginLibrusFragment extends Fragment { - - private App app; - private NavController nav; - private FragmentLoginLibrusBinding b; - private static final String TAG = "LoginLibrus"; - private ErrorSnackbar errorSnackbar; - - public LoginLibrusFragment() { } - - @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); - errorSnackbar = ((LoginActivity) getActivity()).errorSnackbar; - } - else { - return null; - } - b = DataBindingUtil.inflate(inflater, R.layout.fragment_login_librus, container, false); - return b.getRoot(); - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - assert getContext() != null; - assert getActivity() != null; - - view.postDelayed(() -> { - ApiError error = LoginActivity.error; - if (error != null) { - switch (error.getErrorCode()) { - case ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN: - b.loginPasswordLayout.setError(getString(R.string.login_error_incorrect_login_or_password)); - break; - case ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED: - b.loginEmailLayout.setError(getString(R.string.login_error_account_not_activated)); - break; - } - errorSnackbar.addError(error).show(); - LoginActivity.error = null; - } - }, 100); - - b.helpButton.setOnClickListener((v) -> nav.navigate(R.id.loginLibrusHelpFragment, null, LoginActivity.navOptions)); - b.backButton.setOnClickListener((v) -> nav.navigateUp()); - - b.loginButton.setOnClickListener((v) -> { - boolean errors = false; - - b.loginEmailLayout.setError(null); - b.loginPasswordLayout.setError(null); - - Editable emailEditable = b.loginEmail.getText(); - Editable passwordEditable = b.loginPassword.getText(); - if (emailEditable == null || emailEditable.length() == 0) { - b.loginEmailLayout.setError(getString(R.string.login_error_no_email)); - errors = true; - } - if (passwordEditable == null || passwordEditable.length() == 0) { - b.loginPasswordLayout.setError(getString(R.string.login_error_no_password)); - errors = true; - } - - if (errors) - return; - errors = false; - - String email = emailEditable.toString().toLowerCase(); - String password = passwordEditable.toString(); - b.loginEmail.setText(email); - if (!email.matches("([\\w.\\-_+]+)?\\w+@[\\w-_]+(\\.\\w+)+")) { - b.loginEmailLayout.setError(getString(R.string.login_error_incorrect_email)); - errors = true; - } - - if (errors) - return; - errors = false; - - Bundle args = new Bundle(); - args.putInt("loginType", LOGIN_TYPE_LIBRUS); - args.putString("email", email); - args.putString("password", password); - nav.navigate(R.id.loginProgressFragment, args, LoginActivity.navOptions); - }); - } -} 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 new file mode 100644 index 00000000..11c2bdd2 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginLibrusFragment.kt @@ -0,0 +1,97 @@ +/* + * 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/LoginLibrusJstFragment.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginLibrusJstFragment.java deleted file mode 100644 index 1ed7676f..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginLibrusJstFragment.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2019-12-13. - */ - -package pl.szczodrzynski.edziennik.ui.modules.login; - -import android.os.Bundle; -import android.text.Editable; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.databinding.DataBindingUtil; -import androidx.fragment.app.Fragment; -import androidx.navigation.NavController; -import androidx.navigation.Navigation; - -import pl.szczodrzynski.edziennik.App; -import pl.szczodrzynski.edziennik.R; -import pl.szczodrzynski.edziennik.data.api.models.ApiError; -import pl.szczodrzynski.edziennik.databinding.FragmentLoginLibrusJstBinding; -import pl.szczodrzynski.edziennik.ui.modules.error.ErrorSnackbar; - -import static pl.szczodrzynski.edziennik.data.api.ErrorsKt.ERROR_LOGIN_LIBRUS_API_INVALID_LOGIN; -import static pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_MODE_LIBRUS_JST; -import static pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_LIBRUS; - -public class LoginLibrusJstFragment extends Fragment { - - private App app; - private NavController nav; - private FragmentLoginLibrusJstBinding b; - private static final String TAG = "LoginLibrus"; - private ErrorSnackbar errorSnackbar; - - public LoginLibrusJstFragment() { } - - @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); - errorSnackbar = ((LoginActivity) getActivity()).errorSnackbar; - } - else { - return null; - } - b = DataBindingUtil.inflate(inflater, R.layout.fragment_login_librus_jst, container, false); - return b.getRoot(); - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - assert getContext() != null; - assert getActivity() != null; - - view.postDelayed(() -> { - ApiError error = LoginActivity.error; - if (error != null) { - switch (error.getErrorCode()) { - case ERROR_LOGIN_LIBRUS_API_INVALID_LOGIN: - b.loginCodeLayout.setError(getString(R.string.login_error_incorrect_code_or_pin)); - break; - } - errorSnackbar.addError(error).show(); - LoginActivity.error = null; - } - }, 100); - - b.helpButton.setOnClickListener((v) -> nav.navigate(R.id.loginLibrusHelpFragment, null, LoginActivity.navOptions)); - b.backButton.setOnClickListener((v) -> nav.navigateUp()); - - b.loginButton.setOnClickListener((v) -> { - boolean errors = false; - - b.loginCodeLayout.setError(null); - b.loginPinLayout.setError(null); - - Editable codeEditable = b.loginCode.getText(); - Editable pinEditable = b.loginPin.getText(); - if (codeEditable == null || codeEditable.length() == 0) { - b.loginCodeLayout.setError(getString(R.string.login_error_no_code)); - errors = true; - } - if (pinEditable == null || pinEditable.length() == 0) { - b.loginPinLayout.setError(getString(R.string.login_error_no_pin)); - errors = true; - } - - if (errors) - return; - errors = false; - - String code = codeEditable.toString().toUpperCase(); - String pin = pinEditable.toString(); - b.loginCode.setText(code); - if (!code.matches("[A-Z0-9_]+")) { - b.loginCodeLayout.setError(getString(R.string.login_error_incorrect_code)); - errors = true; - } - if (!pin.matches("[a-z0-9_]+")) { - b.loginPinLayout.setError(getString(R.string.login_error_incorrect_pin)); - errors = true; - } - - if (errors) - return; - errors = false; - - Bundle args = new Bundle(); - args.putInt("loginType", LOGIN_TYPE_LIBRUS); - args.putInt("loginMode", LOGIN_MODE_LIBRUS_JST); - args.putString("accountCode", code); - args.putString("accountPin", pin); - nav.navigate(R.id.loginProgressFragment, args, LoginActivity.navOptions); - }); - } -} 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 new file mode 100644 index 00000000..9799d805 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginLibrusJstFragment.kt @@ -0,0 +1,100 @@ +/* + * 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_API_INVALID_LOGIN +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 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 -> + b.loginCodeLayout.error = getString(R.string.login_error_incorrect_code_or_pin) + } + } + } + + 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.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginMobidziennikFragment.java deleted file mode 100644 index 6245def3..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginMobidziennikFragment.java +++ /dev/null @@ -1,136 +0,0 @@ -package pl.szczodrzynski.edziennik.ui.modules.login; - -import android.os.Bundle; -import android.text.Editable; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.databinding.DataBindingUtil; -import androidx.fragment.app.Fragment; -import androidx.navigation.NavController; -import androidx.navigation.Navigation; - -import pl.szczodrzynski.edziennik.App; -import pl.szczodrzynski.edziennik.R; -import pl.szczodrzynski.edziennik.data.api.models.ApiError; -import pl.szczodrzynski.edziennik.databinding.FragmentLoginMobidziennikBinding; -import pl.szczodrzynski.edziennik.ui.modules.error.ErrorSnackbar; - -import static pl.szczodrzynski.edziennik.data.api.ErrorsKt.ERROR_LOGIN_MOBIDZIENNIK_WEB_ARCHIVED; -import static pl.szczodrzynski.edziennik.data.api.ErrorsKt.ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_ADDRESS; -import static pl.szczodrzynski.edziennik.data.api.ErrorsKt.ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_LOGIN; -import static pl.szczodrzynski.edziennik.data.api.ErrorsKt.ERROR_LOGIN_MOBIDZIENNIK_WEB_OLD_PASSWORD; -import static pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_MOBIDZIENNIK; - -public class LoginMobidziennikFragment extends Fragment { - - private App app; - private NavController nav; - private FragmentLoginMobidziennikBinding b; - private static final String TAG = "LoginMobidziennik"; - private ErrorSnackbar errorSnackbar; - - public LoginMobidziennikFragment() { } - - @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); - errorSnackbar = ((LoginActivity) getActivity()).errorSnackbar; - } - else { - return null; - } - b = DataBindingUtil.inflate(inflater, R.layout.fragment_login_mobidziennik, container, false); - return b.getRoot(); - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - assert getContext() != null; - assert getActivity() != null; - - view.postDelayed(() -> { - ApiError error = LoginActivity.error; - if (error != null) { - switch (error.getErrorCode()) { - case ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_LOGIN: - b.loginPasswordLayout.setError(getString(R.string.login_error_incorrect_login_or_password)); - break; - case ERROR_LOGIN_MOBIDZIENNIK_WEB_OLD_PASSWORD: - b.loginPasswordLayout.setError(getString(R.string.login_error_old_password)); - break; - case ERROR_LOGIN_MOBIDZIENNIK_WEB_ARCHIVED: - b.loginUsernameLayout.setError(getString(R.string.sync_error_archived)); - break; - case ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_ADDRESS: - b.loginServerAddressLayout.setError(getString(R.string.login_error_incorrect_address)); - break; - } - errorSnackbar.addError(error).show(); - LoginActivity.error = null; - } - }, 100); - - b.helpButton.setOnClickListener((v) -> nav.navigate(R.id.loginMobidziennikHelpFragment, null, LoginActivity.navOptions)); - b.backButton.setOnClickListener((v) -> nav.navigateUp()); - - b.loginButton.setOnClickListener((v) -> { - boolean errors = false; - - b.loginServerAddressLayout.setError(null); - b.loginUsernameLayout.setError(null); - b.loginPasswordLayout.setError(null); - - Editable serverNameEditable = b.loginServerAddress.getText(); - Editable usernameEditable = b.loginUsername.getText(); - Editable passwordEditable = b.loginPassword.getText(); - if (serverNameEditable == null || serverNameEditable.length() == 0) { - b.loginServerAddressLayout.setError(getString(R.string.login_error_no_address)); - errors = true; - } - if (usernameEditable == null || usernameEditable.length() == 0) { - b.loginUsernameLayout.setError(getString(R.string.login_error_no_login)); - errors = true; - } - if (passwordEditable == null || passwordEditable.length() == 0) { - b.loginPasswordLayout.setError(getString(R.string.login_error_no_password)); - errors = true; - } - - if (errors) - return; - errors = false; - - String serverName = serverNameEditable.toString().toLowerCase().replaceAll("(?:http://|www.|mobidziennik\\.pl|wizja\\.net|\\.)", ""); - String username = usernameEditable.toString().toLowerCase(); - String password = passwordEditable.toString(); - b.loginServerAddress.setText(serverName); - b.loginUsername.setText(username); - if (!serverName.matches("^[a-z0-9_\\-]+$")) { - b.loginServerAddressLayout.setError(getString(R.string.login_error_incorrect_address)); - errors = true; - } - if (!username.matches("^[a-z0-9_\\-@+.]+$")) { - b.loginUsernameLayout.setError(getString(R.string.login_error_incorrect_login)); - errors = true; - } - - if (errors) - return; - errors = false; - - Bundle args = new Bundle(); - args.putInt("loginType", LOGIN_TYPE_MOBIDZIENNIK); - args.putString("serverName", serverName); - args.putString("username", username); - args.putString("password", password); - 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 new file mode 100644 index 00000000..de0deb3d --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginMobidziennikFragment.kt @@ -0,0 +1,114 @@ +/* + * 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/LoginProgressFragment.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginProgressFragment.java deleted file mode 100644 index 4cd25ca3..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginProgressFragment.java +++ /dev/null @@ -1,112 +0,0 @@ -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.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.databinding.DataBindingUtil; -import androidx.fragment.app.Fragment; -import androidx.navigation.NavController; -import androidx.navigation.Navigation; - -import com.google.gson.JsonObject; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; -import org.greenrobot.eventbus.ThreadMode; - -import pl.szczodrzynski.edziennik.App; -import pl.szczodrzynski.edziennik.R; -import pl.szczodrzynski.edziennik.data.api.events.ApiTaskErrorEvent; -import pl.szczodrzynski.edziennik.data.api.events.FirstLoginFinishedEvent; -import pl.szczodrzynski.edziennik.data.api.models.ApiError; -import pl.szczodrzynski.edziennik.data.api.task.EdziennikTask; -import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore; -import pl.szczodrzynski.edziennik.databinding.FragmentLoginProgressBinding; - -import static pl.szczodrzynski.edziennik.data.api.ErrorsKt.LOGIN_NO_ARGUMENTS; - -public class LoginProgressFragment extends Fragment { - - private App app; - private NavController nav; - private FragmentLoginProgressBinding b; - private static final String TAG = "LoginProgress"; - - public LoginProgressFragment() { } - - @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_progress, container, false); - return b.getRoot(); - } - - @Subscribe(threadMode = ThreadMode.MAIN) - public void onFirstLoginFinishedEvent(FirstLoginFinishedEvent event) { - LoginActivity.profileObjects.add(new LoginProfileObject( - event.getLoginStore(), - event.getProfileList())); - nav.navigate(R.id.loginSummaryFragment, null, LoginActivity.navOptions); - } - - @Subscribe(threadMode = ThreadMode.MAIN, sticky = true) - public void onSyncErrorEvent(ApiTaskErrorEvent event) { - LoginActivity.error = event.getError(); - if (getActivity() == null) - return; - nav.navigateUp(); - } - - // TODO add progress bar in login - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - assert getContext() != null; - assert getActivity() != null; - Bundle args = getArguments(); - - LoginActivity.error = null; - - if (args == null) { - LoginActivity.error = new ApiError(TAG, LOGIN_NO_ARGUMENTS); - nav.navigateUp(); - return; - } - - int loginType = args.getInt("loginType", -1); - int loginMode = args.getInt("loginMode", 0); - - LoginStore loginStore = new LoginStore(-1, loginType, new JsonObject()); - loginStore.mode = loginMode; - loginStore.copyFrom(args); - - if (App.devMode && LoginChooserFragment.fakeLogin) { - loginStore.putLoginData("fakeLogin", true); - } - - EdziennikTask.Companion.firstLogin(loginStore).enqueue(getContext()); - } - - @Override - public void onStart() { - EventBus.getDefault().register(this); - super.onStart(); - } - - @Override - public void onStop() { - super.onStop(); - EventBus.getDefault().unregister(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 new file mode 100644 index 00000000..3452b8c9 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginProgressFragment.kt @@ -0,0 +1,110 @@ +/* + * 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 com.google.android.material.dialog.MaterialAlertDialogBuilder +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import org.greenrobot.eventbus.EventBus +import org.greenrobot.eventbus.Subscribe +import org.greenrobot.eventbus.ThreadMode +import pl.szczodrzynski.edziennik.App +import pl.szczodrzynski.edziennik.R +import pl.szczodrzynski.edziennik.data.api.LOGIN_NO_ARGUMENTS +import pl.szczodrzynski.edziennik.data.api.events.ApiTaskErrorEvent +import pl.szczodrzynski.edziennik.data.api.events.FirstLoginFinishedEvent +import pl.szczodrzynski.edziennik.data.api.models.ApiError +import pl.szczodrzynski.edziennik.data.api.task.EdziennikTask +import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore +import pl.szczodrzynski.edziennik.databinding.FragmentLoginProgressBinding +import kotlin.coroutines.CoroutineContext + +class LoginProgressFragment : Fragment(), CoroutineScope { + companion object { + private const val TAG = "LoginProgressFragment" + } + + private lateinit var app: App + private lateinit var activity: LoginActivity + private lateinit var b: FragmentLoginProgressBinding + 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 = FragmentLoginProgressBinding.inflate(inflater) + return b.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + val args = arguments ?: run { + activity.error(ApiError(TAG, LOGIN_NO_ARGUMENTS)) + nav.navigateUp() + return + } + + launch { + val firstProfileId = (app.db.profileDao().lastId ?: 0) + 1 + val loginType = args.getInt("loginType", -1) + val loginMode = args.getInt("loginMode", 0) + + val loginStore = LoginStore( + id = firstProfileId, + type = loginType, + mode = loginMode + ) + loginStore.copyFrom(args) + if (App.devMode && LoginChooserFragment.fakeLogin) { + loginStore.putLoginData("fakeLogin", true) + } + EdziennikTask.firstLogin(loginStore).enqueue(activity) + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + fun onFirstLoginFinishedEvent(event: FirstLoginFinishedEvent) { + if (event.profileList.isEmpty()) { + MaterialAlertDialogBuilder(activity) + .setTitle(R.string.login_account_no_students) + .setMessage(R.string.login_account_no_students_text) + .setPositiveButton(R.string.ok, null) + .setOnDismissListener { nav.navigateUp() } + .show() + return + } + activity.loginStores += event.loginStore + activity.profiles += event.profileList.map { LoginSummaryProfileAdapter.Item(it) } + nav.navigate(R.id.loginSummaryFragment, null, LoginActivity.navOptions) + } + + @Subscribe(threadMode = ThreadMode.MAIN, sticky = true) + fun onSyncErrorEvent(event: ApiTaskErrorEvent) { + EventBus.getDefault().removeStickyEvent(event) + activity.error(event.error) + nav.navigateUp() + } + + override fun onStart() { + EventBus.getDefault().register(this) + super.onStart() + } + + override fun onStop() { + super.onStop() + EventBus.getDefault().unregister(this) + } +} \ No newline at end of file diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSummaryFragment.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSummaryFragment.java deleted file mode 100644 index f82aa249..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSummaryFragment.java +++ /dev/null @@ -1,268 +0,0 @@ -package pl.szczodrzynski.edziennik.ui.modules.login; - -import android.os.Bundle; -import android.text.Html; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.CheckBox; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.databinding.DataBindingUtil; -import androidx.fragment.app.Fragment; -import androidx.navigation.NavController; -import androidx.navigation.Navigation; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import com.afollestad.materialdialogs.MaterialDialog; - -import java.util.ArrayList; -import java.util.List; - -import pl.szczodrzynski.edziennik.App; -import pl.szczodrzynski.edziennik.ExtensionsKt; -import pl.szczodrzynski.edziennik.R; -import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile; -import pl.szczodrzynski.edziennik.databinding.FragmentLoginSummaryBinding; -import pl.szczodrzynski.edziennik.databinding.RowLoginProfileListItemBinding; - -import static pl.szczodrzynski.edziennik.data.api.LoginMethodsKt.LOGIN_MODE_LIBRUS_EMAIL; -import static pl.szczodrzynski.edziennik.data.api.LoginMethodsKt.LOGIN_MODE_VULCAN_API; -import static pl.szczodrzynski.edziennik.data.api.LoginMethodsKt.LOGIN_MODE_VULCAN_WEB; -import static pl.szczodrzynski.edziennik.data.api.LoginMethodsKt.LOGIN_TYPE_EDUDZIENNIK; -import static pl.szczodrzynski.edziennik.data.api.LoginMethodsKt.LOGIN_TYPE_IDZIENNIK; -import static pl.szczodrzynski.edziennik.data.api.LoginMethodsKt.LOGIN_TYPE_LIBRUS; -import static pl.szczodrzynski.edziennik.data.api.LoginMethodsKt.LOGIN_TYPE_MOBIDZIENNIK; -import static pl.szczodrzynski.edziennik.data.api.LoginMethodsKt.LOGIN_TYPE_VULCAN; - -public class LoginSummaryFragment extends Fragment { - - private App app; - private NavController nav; - private FragmentLoginSummaryBinding b; - private static final String TAG = "LoginSummary"; - - public LoginSummaryFragment() { } - - @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_summary, container, false); - return b.getRoot(); - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - assert getContext() != null; - assert getActivity() != null; - - LoginActivity.firstCompleted = true; - - List profileList = new ArrayList<>(); - int index = 0; - for (LoginProfileObject profileObject: LoginActivity.profileObjects) { - int subIndex = 0; - for (Profile profile: profileObject.profileList) { - List subnameList = new ArrayList<>(); - if (profile.getStudentClassName() != null) - subnameList.add(profile.getStudentClassName()); - if (profile.getStudentSchoolYear() != null) - subnameList.add(profile.getStudentSchoolYear()); - ItemProfileModel profileModel = new ItemProfileModel( - index, - subIndex, - profile.getName(), - ExtensionsKt.join(subnameList, " - "), - profileObject.loginStore.type, - profileObject.loginStore.mode, - profile.getAccountNameLong() != null, - profileObject.selectedList.get(subIndex) - ); - profileList.add(profileModel); - subIndex++; - } - index++; - } - - b.profileListView.setLayoutManager(new LinearLayoutManager(getContext())); - b.profileListView.setAdapter(new ProfileListAdapter(profileList)); - - b.registerMeSwitch.setOnCheckedChangeListener(((buttonView, isChecked) -> { - if (!isChecked) { - new MaterialDialog.Builder(getActivity()) - .title(R.string.login_summary_unregister_title) - .content(R.string.login_summary_unregister_text) - .positiveText(R.string.yes) - .negativeText(R.string.cancel) - .onNegative(((dialog, which) -> { - b.registerMeSwitch.setChecked(true); - })) - .show(); - } - })); - - b.anotherButton.setOnClickListener((v -> nav.navigate(R.id.loginChooserFragment, null, LoginActivity.navOptions))); - - b.finishButton.setOnClickListener(v -> { - if (LoginActivity.privacyPolicyAccepted) { - Bundle args = new Bundle(); - args.putBoolean("registrationAllowed", b.registerMeSwitch.isChecked()); - nav.navigate(R.id.loginSyncFragment, args, LoginActivity.navOptions); - return; - } - boolean profileSelected = true; - for (LoginProfileObject profileObject: LoginActivity.profileObjects) { - if (profileObject.selectedList.size() == 0 && profileSelected) - profileSelected = false; - } - if (!profileSelected) { - new MaterialDialog.Builder(getActivity()) - .title(R.string.login_summary_no_profiles_title) - .content(R.string.login_summary_no_profiles_text) - .positiveText(R.string.ok) - .show(); - return; - } - new MaterialDialog.Builder(getActivity()) - .title(R.string.privacy_policy) - .content(Html.fromHtml("Korzystając z aplikacji potwierdzasz przeczytanie Polityki prywatności i akceptujesz jej postanowienia.")) - .positiveText(R.string.i_agree) - .neutralText(R.string.i_disagree) - .onPositive(((dialog, which) -> { - Bundle args = new Bundle(); - args.putBoolean("registrationAllowed", b.registerMeSwitch.isChecked()); - nav.navigate(R.id.loginSyncFragment, args, LoginActivity.navOptions); - })) - .show(); - }); - } - - class ItemProfileModel { - int listIndex; - int listSubIndex; - String name; - String subname; - int loginType; - int loginMode; - boolean isParent; - boolean selected; - - public ItemProfileModel(int listIndex, int listSubIndex, String name, String subname, int loginType, int loginMode, boolean isParent, boolean selected) { - this.listIndex = listIndex; - this.listSubIndex = listSubIndex; - this.name = name; - this.subname = subname; - this.loginType = loginType; - this.loginMode = loginMode; - this.isParent = isParent; - this.selected = selected; - } - } - - public class ProfileListAdapter extends RecyclerView.Adapter { - private List profileList; - - public ProfileListAdapter(List profileList) { - this.profileList = profileList; - } - - @NonNull - @Override - public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - RowLoginProfileListItemBinding b = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.row_login_profile_list_item, parent, false); - return new ViewHolder(b); - } - - @Override - public void onBindViewHolder(@NonNull ViewHolder holder, int position) { - RowLoginProfileListItemBinding b = holder.b; - ItemProfileModel m = profileList.get(position); - - b.textView.setText(m.name); - b.checkBox.setChecked(m.selected); - b.checkBox.jumpDrawablesToCurrentState(); - View.OnClickListener onClickListener = v -> { - if (v instanceof CheckBox) { - m.selected = ((CheckBox) v).isChecked(); - } else { - m.selected = !m.selected; - b.checkBox.setChecked(m.selected); - b.checkBox.jumpDrawablesToCurrentState(); - } - LoginActivity.profileObjects.get(m.listIndex).selectedList.set(m.listSubIndex, m.selected); - - }; - b.checkBox.setOnClickListener(onClickListener); - b.getRoot().setOnClickListener(onClickListener); - int imageRes = 0; - if (m.loginType == LOGIN_TYPE_MOBIDZIENNIK) { - imageRes = R.drawable.logo_mobidziennik; - } - else if (m.loginType == LOGIN_TYPE_IDZIENNIK) { - imageRes = R.drawable.logo_idziennik; - } - else if (m.loginType == LOGIN_TYPE_LIBRUS) { - if (m.loginMode == LOGIN_MODE_LIBRUS_EMAIL) { - imageRes = R.drawable.logo_librus; - } - else { - imageRes = R.drawable.logo_synergia; - } - } - else if (m.loginType == LOGIN_TYPE_VULCAN) { - if (m.loginMode == LOGIN_MODE_VULCAN_WEB) { - imageRes = R.drawable.logo_vulcan; - } - else if (m.loginMode == LOGIN_MODE_VULCAN_API) { - imageRes = R.drawable.logo_dzienniczek; - } - } - else if (m.loginType == LOGIN_TYPE_EDUDZIENNIK) { - imageRes = R.drawable.logo_edudziennik; - } - if (imageRes != 0) { - b.registerIcon.setImageResource(imageRes); - } - if (m.isParent) { - b.accountType.setText(R.string.login_summary_account_parent); - } - else { - b.accountType.setText(R.string.login_summary_account_child); - } - if (m.subname.trim().isEmpty()) { - b.textDetails.setText(null); - b.textDetails.setVisibility(View.GONE); - } - else { - b.textDetails.setText(m.subname); - b.textDetails.setVisibility(View.VISIBLE); - } - //b.root.setOnClickListener(onClickListener); - //holder.bind(b.textView, onClickListener); - } - - - @Override - public int getItemCount() { - return profileList.size(); - } - - public class ViewHolder extends RecyclerView.ViewHolder { - RowLoginProfileListItemBinding b; - - public ViewHolder(@NonNull RowLoginProfileListItemBinding b) { - super(b.getRoot()); - this.b = b; - } - } - } -} 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 new file mode 100644 index 00000000..b16c0256 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSummaryFragment.kt @@ -0,0 +1,92 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2020-1-3. + */ + +package pl.szczodrzynski.edziennik.ui.modules.login + +import android.os.Bundle +import android.text.Html +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.LinearLayoutManager +import com.google.android.material.dialog.MaterialAlertDialogBuilder +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.utils.SimpleDividerItemDecoration +import kotlin.coroutines.CoroutineContext + +class LoginSummaryFragment : Fragment(), CoroutineScope { + companion object { + private const val TAG = "LoginSummaryFragment" + } + + private lateinit var app: App + private lateinit var activity: LoginActivity + private lateinit var b: FragmentLoginSummaryBinding + 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 = FragmentLoginSummaryBinding.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 } + } + isNestedScrollingEnabled = false + setHasFixedSize(true) + layoutManager = LinearLayoutManager(context) + addItemDecoration(SimpleDividerItemDecoration(context)) + } + + b.registerMeSwitch.onChange { _, isChecked -> + if (isChecked) + return@onChange + MaterialAlertDialogBuilder(activity) + .setTitle(R.string.login_summary_unregister_title) + .setMessage(R.string.login_summary_unregister_text) + .setPositiveButton(R.string.ok, null) + .setNegativeButton(R.string.cancel) { _, _ -> b.registerMeSwitch.isChecked = true } + .show() + } + + b.anotherButton.onClick { + nav.navigate(R.id.loginChooserFragment, null, LoginActivity.navOptions) + } + + b.finishButton.onClick { + if (!app.config.privacyPolicyAccepted) { + MaterialAlertDialogBuilder(activity) + .setTitle(R.string.privacy_policy) + .setMessage(Html.fromHtml("Korzystając z aplikacji potwierdzasz przeczytanie Polityki prywatności i akceptujesz jej postanowienia.")) + .setPositiveButton(R.string.i_agree) { _, _ -> + app.config.privacyPolicyAccepted = true + b.finishButton.performClick() + } + .setNegativeButton(R.string.i_disagree, null) + .show() + return@onClick + } + + val args = Bundle( + "registrationAllowed" to b.registerMeSwitch.isChecked + ) + nav.navigate(R.id.loginSyncFragment, args, LoginActivity.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 new file mode 100644 index 00000000..b0d33e71 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSummaryProfileAdapter.kt @@ -0,0 +1,84 @@ +/* + * 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.App +import pl.szczodrzynski.edziennik.R +import pl.szczodrzynski.edziennik.data.api.* +import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile +import pl.szczodrzynski.edziennik.databinding.RowLoginProfileListItemBinding +import pl.szczodrzynski.edziennik.joinNotNullStrings +import pl.szczodrzynski.edziennik.onClick + +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.performClick() + } + 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.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSyncErrorFragment.java deleted file mode 100644 index 52ff1a0f..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSyncErrorFragment.java +++ /dev/null @@ -1,58 +0,0 @@ -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.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.databinding.DataBindingUtil; -import androidx.fragment.app.Fragment; -import androidx.navigation.NavController; -import androidx.navigation.Navigation; - -import pl.szczodrzynski.edziennik.App; -import pl.szczodrzynski.edziennik.R; -import pl.szczodrzynski.edziennik.databinding.FragmentLoginSyncErrorBinding; - -public class LoginSyncErrorFragment extends Fragment { - - private App app; - private NavController nav; - private FragmentLoginSyncErrorBinding b; - private static final String TAG = "LoginSyncError"; - - public LoginSyncErrorFragment() { } - - @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_sync_error, container, false); - return b.getRoot(); - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - assert getContext() != null; - assert getActivity() != null; - - b.errorDetails.setText(LoginActivity.error == null ? "" : LoginActivity.error.getStringReason(getActivity())); - - b.reportButton.setOnClickListener((v -> { - // TODO error report activity open here app.apiEdziennik.guiReportError(getActivity(), LoginActivity.error, null); - })); - - b.nextButton.setOnClickListener((v -> { - nav.navigate(R.id.loginFinishFragment, null, LoginActivity.navOptions); - })); - } -} - 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 new file mode 100644 index 00000000..49977dee --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginSyncErrorFragment.kt @@ -0,0 +1,50 @@ +/* + * 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.App +import pl.szczodrzynski.edziennik.R +import pl.szczodrzynski.edziennik.databinding.FragmentLoginSyncErrorBinding +import pl.szczodrzynski.edziennik.onClick +import kotlin.coroutines.CoroutineContext + +class LoginSyncErrorFragment : Fragment(), CoroutineScope { + companion object { + private const val TAG = "LoginSyncErrorFragment" + } + + private lateinit var app: App + private lateinit var activity: LoginActivity + private lateinit var b: FragmentLoginSyncErrorBinding + 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 = FragmentLoginSyncErrorBinding.inflate(inflater) + return b.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + b.errorDetails.text = activity.lastError?.getStringReason(activity) + activity.lastError = null + b.nextButton.onClick { + nav.navigate(R.id.loginFinishFragment, arguments, LoginActivity.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 4a789a8b..5b93cb5a 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,20 +1,19 @@ package pl.szczodrzynski.edziennik.ui.modules.login - -import android.os.AsyncTask import android.os.Bundle -import android.text.Html import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.navigation.NavController import androidx.navigation.Navigation +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode -import pl.szczodrzynski.edziennik.App -import pl.szczodrzynski.edziennik.R +import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.data.api.events.ApiTaskAllFinishedEvent import pl.szczodrzynski.edziennik.data.api.events.ApiTaskErrorEvent import pl.szczodrzynski.edziennik.data.api.events.ApiTaskProgressEvent @@ -22,38 +21,87 @@ import pl.szczodrzynski.edziennik.data.api.events.ApiTaskStartedEvent import pl.szczodrzynski.edziennik.data.api.task.EdziennikTask import pl.szczodrzynski.edziennik.data.db.modules.events.Event.* import pl.szczodrzynski.edziennik.data.db.modules.events.EventType -import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore -import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile.Companion.REGISTRATION_DISABLED import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile.Companion.REGISTRATION_ENABLED -import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile.Companion.REGISTRATION_UNSPECIFIED import pl.szczodrzynski.edziennik.databinding.FragmentLoginSyncBinding +import kotlin.coroutines.CoroutineContext import kotlin.math.roundToInt -class LoginSyncFragment : Fragment() { +class LoginSyncFragment : Fragment(), CoroutineScope { + companion object { + private const val TAG = "LoginSyncFragment" + } private lateinit var app: App private lateinit var activity: LoginActivity private lateinit var b: FragmentLoginSyncBinding private val nav: NavController by lazy { Navigation.findNavController(activity, R.id.nav_host_fragment) } + private val job: Job = Job() + override val coroutineContext: CoroutineContext + get() = job + Dispatchers.Main + + private lateinit var finishArguments: Bundle + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { activity = (getActivity() as LoginActivity?) ?: return null - if (context == null) - return null + context ?: return null app = activity.application as App b = FragmentLoginSyncBinding.inflate(inflater) return b.root } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + val profiles = activity.profiles.filter { it.isSelected }.map { it.profile } + val loginStores = activity.loginStores.filter { store -> profiles.any { it.loginStoreId == store.id } } + + val registrationAllowed = arguments?.getBoolean("registrationAllowed") ?: false + profiles.forEach { + it.registration = if (registrationAllowed) + REGISTRATION_ENABLED + else + REGISTRATION_DISABLED + + val typeList = listOf( + EventType(it.id, TYPE_HOMEWORK.toLong(), getString(R.string.event_type_homework), COLOR_HOMEWORK), + EventType(it.id, TYPE_DEFAULT.toLong(), getString(R.string.event_other), COLOR_DEFAULT), + EventType(it.id, TYPE_EXAM.toLong(), getString(R.string.event_exam), COLOR_EXAM), + EventType(it.id, TYPE_SHORT_QUIZ.toLong(), getString(R.string.event_short_quiz), COLOR_SHORT_QUIZ), + EventType(it.id, TYPE_ESSAY.toLong(), getString(R.string.event_essay), COLOR_SHORT_QUIZ), + EventType(it.id, TYPE_PROJECT.toLong(), getString(R.string.event_project), COLOR_PROJECT), + EventType(it.id, TYPE_PT_MEETING.toLong(), getString(R.string.event_pt_meeting), COLOR_PT_MEETING), + EventType(it.id, TYPE_EXCURSION.toLong(), getString(R.string.event_excursion), COLOR_EXCURSION), + EventType(it.id, TYPE_READING.toLong(), getString(R.string.event_reading), COLOR_READING), + EventType(it.id, TYPE_CLASS_EVENT.toLong(), getString(R.string.event_class_event), COLOR_CLASS_EVENT), + EventType(it.id, TYPE_INFORMATION.toLong(), getString(R.string.event_information), COLOR_INFORMATION) + ) + app.db.eventTypeDao().addAll(typeList) + } + + app.db.profileDao().addAll(profiles) + app.db.loginStoreDao().addAll(loginStores) + + finishArguments = Bundle( + "firstProfileId" to profiles.firstOrNull()?.id, + "firstRun" to !app.config.loginFinished + ) + app.config.loginFinished = true + + val profileIds = profiles.map { it.id } + EdziennikTask.syncProfileList(profileIds).enqueue(activity) + } + @Subscribe(threadMode = ThreadMode.MAIN) fun onSyncStartedEvent(event: ApiTaskStartedEvent) { - b.loginSyncSubtitle1.text = Html.fromHtml(getString(R.string.login_sync_subtitle_1_format, event.profile?.name ?: "")) + b.loginSyncSubtitle1.text = listOf( + getString(R.string.login_sync_subtitle_1_format), + event.profile?.name?.asBoldSpannable() + ).concat(" ") } @Subscribe(threadMode = ThreadMode.MAIN) fun onSyncFinishedEvent(event: ApiTaskAllFinishedEvent) { - nav.navigate(R.id.loginFinishFragment, null, LoginActivity.navOptions) + nav.navigate(R.id.loginFinishFragment, finishArguments, LoginActivity.navOptions) } @Subscribe(threadMode = ThreadMode.MAIN) @@ -63,93 +111,11 @@ class LoginSyncFragment : Fragment() { b.loginSyncSubtitle2.text = event.progressText } - @Subscribe(threadMode = ThreadMode.MAIN) + @Subscribe(threadMode = ThreadMode.MAIN, sticky = true) fun onSyncErrorEvent(event: ApiTaskErrorEvent) { - LoginActivity.error = event.error - nav.navigate(R.id.loginSyncErrorFragment, null, LoginActivity.navOptions) - } - - private fun begin() { - AsyncTask.execute { - var profileId = app.profileLastId() + 1 - val firstProfileId = profileId - var loginStoreId = profileId - // profileId contains the first ID free to use - - val profileIds = mutableListOf() - - for (profileObject in LoginActivity.profileObjects) { - for ((subIndex, profile) in profileObject.profileList.withIndex()) { - if (profileObject.selectedList[subIndex]) { - saveProfile( - profile, - profileObject.loginStore, - profileId, - loginStoreId - ) - profileIds += profileId - profileId++ - } - } - loginStoreId = profileId - } - - /*for (profile in app.db.profileDao().allNow) { - d(TAG, profile.toString()) - } - for (loginStore in app.db.loginStoreDao().allNow) { - d(TAG, loginStore.toString()) - }*/ - - if (app.config.loginFinished) { - LoginFinishFragment.firstRun = false - } else { - LoginFinishFragment.firstRun = true - app.config.loginFinished = true - } - LoginFinishFragment.firstProfileId = firstProfileId - - EdziennikTask.syncProfileList(profileIds).enqueue(activity) - } - } - - private fun saveProfile(profile: Profile, loginStore: LoginStore, profileId: Int, loginStoreId: Int) { - profile.registration = REGISTRATION_UNSPECIFIED - if (arguments != null) { - if (arguments!!.getBoolean("registrationAllowed", false)) { - profile.registration = REGISTRATION_ENABLED - } else { - profile.registration = REGISTRATION_DISABLED - } - } - profile.id = profileId - profile.loginStoreId = loginStoreId - loginStore.id = loginStoreId - val typeList = listOf( - EventType(profileId, TYPE_HOMEWORK.toLong(), getString(R.string.event_type_homework), COLOR_HOMEWORK), - EventType(profileId, TYPE_DEFAULT.toLong(), getString(R.string.event_other), COLOR_DEFAULT), - EventType(profileId, TYPE_EXAM.toLong(), getString(R.string.event_exam), COLOR_EXAM), - EventType(profileId, TYPE_SHORT_QUIZ.toLong(), getString(R.string.event_short_quiz), COLOR_SHORT_QUIZ), - EventType(profileId, TYPE_ESSAY.toLong(), getString(R.string.event_essay), COLOR_SHORT_QUIZ), - EventType(profileId, TYPE_PROJECT.toLong(), getString(R.string.event_project), COLOR_PROJECT), - EventType(profileId, TYPE_PT_MEETING.toLong(), getString(R.string.event_pt_meeting), COLOR_PT_MEETING), - EventType(profileId, TYPE_EXCURSION.toLong(), getString(R.string.event_excursion), COLOR_EXCURSION), - EventType(profileId, TYPE_READING.toLong(), getString(R.string.event_reading), COLOR_READING), - EventType(profileId, TYPE_CLASS_EVENT.toLong(), getString(R.string.event_class_event), COLOR_CLASS_EVENT), - EventType(profileId, TYPE_INFORMATION.toLong(), getString(R.string.event_information), COLOR_INFORMATION) - ) - app.db.eventTypeDao().addAll(typeList) - app.db.profileDao().add(profile) - app.db.loginStoreDao().add(loginStore) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - if (!isAdded) - return - - LoginActivity.error = null - - begin() + EventBus.getDefault().removeStickyEvent(event) + activity.error(event.error) + nav.navigate(R.id.loginSyncErrorFragment, finishArguments, LoginActivity.navOptions) } override fun onStart() { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginTemplateFragment.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginTemplateFragment.java deleted file mode 100644 index 41ff3beb..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginTemplateFragment.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.FragmentLoginTemplateBinding; - -public class LoginTemplateFragment extends Fragment { - - private App app; - private NavController nav; - private FragmentLoginTemplateBinding b; - private static final String TAG = "LoginTemplate"; - - public LoginTemplateFragment() { } - - @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_template, container, false); - return b.getRoot(); - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - assert getContext() != null; - assert getActivity() != null; - - - } -} 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 new file mode 100644 index 00000000..4264416a --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginTemplateFragment.kt @@ -0,0 +1,97 @@ +/* + * 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.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginVulcanFragment.java deleted file mode 100644 index 2214a873..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginVulcanFragment.java +++ /dev/null @@ -1,202 +0,0 @@ -package pl.szczodrzynski.edziennik.ui.modules.login; - -import android.content.Intent; -import android.graphics.Color; -import android.os.Bundle; -import android.text.Editable; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.WindowManager; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.databinding.DataBindingUtil; -import androidx.fragment.app.Fragment; -import androidx.navigation.NavController; -import androidx.navigation.Navigation; - -import com.mikepenz.iconics.IconicsColor; -import com.mikepenz.iconics.IconicsDrawable; -import com.mikepenz.iconics.IconicsSize; -import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial; - -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.crypto.BadPaddingException; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.ShortBufferException; - -import pl.szczodrzynski.edziennik.App; -import pl.szczodrzynski.edziennik.R; -import pl.szczodrzynski.edziennik.data.api.models.ApiError; -import pl.szczodrzynski.edziennik.databinding.FragmentLoginVulcanBinding; -import pl.szczodrzynski.edziennik.ui.modules.error.ErrorSnackbar; -import pl.szczodrzynski.edziennik.ui.modules.webpush.QrScannerActivity; -import pl.szczodrzynski.edziennik.utils.Utils; - -import static pl.szczodrzynski.edziennik.data.api.ErrorsKt.ERROR_LOGIN_VULCAN_EXPIRED_TOKEN; -import static pl.szczodrzynski.edziennik.data.api.ErrorsKt.ERROR_LOGIN_VULCAN_INVALID_PIN; -import static pl.szczodrzynski.edziennik.data.api.ErrorsKt.ERROR_LOGIN_VULCAN_INVALID_SYMBOL; -import static pl.szczodrzynski.edziennik.data.api.ErrorsKt.ERROR_LOGIN_VULCAN_INVALID_TOKEN; -import static pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_VULCAN; - -public class LoginVulcanFragment extends Fragment { - - private App app; - private NavController nav; - private FragmentLoginVulcanBinding b; - private static final String TAG = "LoginVulcan"; - private ErrorSnackbar errorSnackbar; - - public LoginVulcanFragment() { } - - @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); - errorSnackbar = ((LoginActivity) getActivity()).errorSnackbar; - } - else { - return null; - } - b = DataBindingUtil.inflate(inflater, R.layout.fragment_login_vulcan, container, false); - return b.getRoot(); - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - assert getContext() != null; - assert getActivity() != null; - - view.postDelayed(() -> { - ApiError error = LoginActivity.error; - if (error != null) { - switch (error.getErrorCode()) { - case ERROR_LOGIN_VULCAN_INVALID_TOKEN: - b.loginTokenLayout.setError(getString(R.string.login_error_incorrect_token)); - break; - case ERROR_LOGIN_VULCAN_EXPIRED_TOKEN: - b.loginTokenLayout.setError(getString(R.string.login_error_expired_token)); - break; - case ERROR_LOGIN_VULCAN_INVALID_SYMBOL: - b.loginSymbolLayout.setError(getString(R.string.login_error_incorrect_symbol)); - break; - case ERROR_LOGIN_VULCAN_INVALID_PIN: - /*if (!"?".equals(error.errorText)) { - b.loginPinLayout.setError(getString(R.string.login_error_incorrect_pin_format, error.errorText)); - break; - }*/ - b.loginPinLayout.setError(getString(R.string.login_error_incorrect_pin)); - break; - } - errorSnackbar.addError(error).show(); - LoginActivity.error = null; - } - }, 100); - - b.helpButton.setOnClickListener((v) -> nav.navigate(R.id.loginVulcanHelpFragment, null, LoginActivity.navOptions)); - b.backButton.setOnClickListener((v) -> nav.navigateUp()); - - b.loginQrScan.setImageDrawable(new IconicsDrawable(getActivity()).icon(CommunityMaterial.Icon2.cmd_qrcode_scan).color(IconicsColor.colorInt(Color.BLACK)).size(IconicsSize.dp(72))); - b.loginQrScan.setOnClickListener((v -> { - QrScannerActivity.resultHandler = result -> { - try { - String qr = result.getText(); - String data = Utils.VulcanQrEncryptionUtils.decode(qr); - Matcher matcher = Pattern.compile("CERT#https?://.+?/([A-z]+)/mobile-api#([A-z0-9]+)#ENDCERT").matcher(data); - if (matcher.find()) { - b.loginToken.setText(matcher.group(2)); - b.loginSymbol.setText(matcher.group(1)); - if(b.loginPin.requestFocus()) { - getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); - } - } - else { - - } - } catch (NoSuchPaddingException e) { - e.printStackTrace(); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } catch (InvalidKeyException e) { - e.printStackTrace(); - } catch (ShortBufferException e) { - e.printStackTrace(); - } catch (BadPaddingException e) { - e.printStackTrace(); - } catch (IllegalBlockSizeException e) { - e.printStackTrace(); - } - }; - startActivity(new Intent(getContext(), QrScannerActivity.class)); - })); - - b.loginButton.setOnClickListener((v) -> { - boolean errors = false; - - b.loginTokenLayout.setError(null); - b.loginSymbolLayout.setError(null); - b.loginPinLayout.setError(null); - - Editable tokenEditable = b.loginToken.getText(); - Editable symbolEditable = b.loginSymbol.getText(); - Editable pinEditable = b.loginPin.getText(); - if (tokenEditable == null || tokenEditable.length() == 0) { - b.loginTokenLayout.setError(getString(R.string.login_error_no_token)); - errors = true; - } - if (symbolEditable == null || symbolEditable.length() == 0) { - b.loginSymbolLayout.setError(getString(R.string.login_error_no_symbol)); - errors = true; - } - if (pinEditable == null || pinEditable.length() == 0) { - b.loginPinLayout.setError(getString(R.string.login_error_no_pin)); - errors = true; - } - - if (errors) - return; - errors = false; - - String token = tokenEditable.toString().toUpperCase(); - String symbol = symbolEditable.toString().toLowerCase(); - String pin = pinEditable.toString(); - b.loginToken.setText(token); - b.loginSymbol.setText(symbol); - b.loginPin.setText(pin); - if (!token.matches("[A-Z0-9]{5,12}")) { - b.loginTokenLayout.setError(getString(R.string.login_error_incorrect_token)); - errors = true; - } - if (!symbol.matches("[a-z0-9]+")) { - b.loginSymbolLayout.setError(getString(R.string.login_error_incorrect_symbol)); - errors = true; - } - if (!pin.matches("[a-z0-9_]+")) { - b.loginPinLayout.setError(getString(R.string.login_error_incorrect_pin)); - errors = true; - } - - if (errors) - return; - errors = false; - - Bundle args = new Bundle(); - args.putInt("loginType", LOGIN_TYPE_VULCAN); - args.putString("deviceToken", token); - args.putString("deviceSymbol", symbol); - args.putString("devicePin", pin); - nav.navigate(R.id.loginProgressFragment, args, LoginActivity.navOptions); - }); - }// narysowac raz dwa trzy cztery wyresy funkcji ktore sa tak dzielone - // nire wnikac w szkczegoly jak dzialaja - // takie same sa funckje sinus comisinus - // -} 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 new file mode 100644 index 00000000..9a3f2590 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginVulcanFragment.kt @@ -0,0 +1,116 @@ +/* + * 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.FragmentLoginVulcanBinding +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.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/messages/MessageFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessageFragment.kt index c6a6d1de..a177db9b 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessageFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessageFragment.kt @@ -35,7 +35,7 @@ import pl.szczodrzynski.edziennik.data.api.events.AttachmentGetEvent.Companion.T import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent import pl.szczodrzynski.edziennik.data.api.task.EdziennikTask import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore -import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_IUCZNIOWIE +import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.Companion.LOGIN_TYPE_IDZIENNIK import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_RECEIVED import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_SENT import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull @@ -162,7 +162,7 @@ class MessageFragment : Fragment(), CoroutineScope { return } - if (app.profile.loginStoreType == LOGIN_TYPE_IUCZNIOWIE) { + if (app.profile.loginStoreType == LOGIN_TYPE_IDZIENNIK) { val meta = "\\[META:([A-z0-9]+);([0-9-]+)]".toRegex().find(message.body!!) val messageIdBefore = meta?.get(2)?.toLong() ?: -1 @@ -185,7 +185,7 @@ class MessageFragment : Fragment(), CoroutineScope { private fun checkRecipients(): Boolean { message.recipients?.forEach { recipient -> if (recipient.id == -1L) - recipient.fullName = app.profile.accountNameLong ?: app.profile.studentNameLong ?: "" + recipient.fullName = app.profile.accountName ?: app.profile.studentNameLong ?: "" if (message.type == TYPE_SENT && recipient.readDate < 1) return false } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesComposeFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesComposeFragment.kt index 4a9bfcc6..fd7dd3da 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesComposeFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesComposeFragment.kt @@ -173,7 +173,7 @@ class MessagesComposeFragment : Fragment(), CoroutineScope { LoginStore.LOGIN_TYPE_MOBIDZIENNIK -> 100 LoginStore.LOGIN_TYPE_LIBRUS -> 150 LoginStore.LOGIN_TYPE_VULCAN -> 200 - LoginStore.LOGIN_TYPE_IUCZNIOWIE -> 180 + LoginStore.LOGIN_TYPE_IDZIENNIK -> 180 LoginStore.LOGIN_TYPE_EDUDZIENNIK -> 0 else -> -1 } @@ -181,7 +181,7 @@ class MessagesComposeFragment : Fragment(), CoroutineScope { LoginStore.LOGIN_TYPE_MOBIDZIENNIK -> -1 LoginStore.LOGIN_TYPE_LIBRUS -> 20000 LoginStore.LOGIN_TYPE_VULCAN -> -1 - LoginStore.LOGIN_TYPE_IUCZNIOWIE -> 1983 + LoginStore.LOGIN_TYPE_IDZIENNIK -> 1983 LoginStore.LOGIN_TYPE_EDUDZIENNIK -> 0 else -> -1 } @@ -345,7 +345,7 @@ class MessagesComposeFragment : Fragment(), CoroutineScope { if (arguments?.getString("type") == "reply") { // add greeting text - span.replace(0, 0, "\n\nZ poważaniem,\n${app.profile.accountNameLong + span.replace(0, 0, "\n\nZ poważaniem,\n${app.profile.accountName ?: app.profile.studentNameLong ?: ""}\n\n\n") teachers.firstOrNull { it.id == msg.senderId }?.let { teacher -> @@ -415,7 +415,7 @@ class MessagesComposeFragment : Fragment(), CoroutineScope { if (b.textLayout.counterMaxLength != -1 && b.text.length() > b.textLayout.counterMaxLength) return - var textHtml = if (app.profile.loginStoreType != LoginStore.LOGIN_TYPE_VULCAN && app.profile.loginStoreType != LoginStore.LOGIN_TYPE_IUCZNIOWIE) { + var textHtml = if (app.profile.loginStoreType != LoginStore.LOGIN_TYPE_VULCAN && app.profile.loginStoreType != LoginStore.LOGIN_TYPE_IDZIENNIK) { HtmlCompat.toHtml(SpannableString(text), HtmlCompat.TO_HTML_PARAGRAPH_LINES_INDIVIDUAL) .replace("\n", "") .replace(" dir=\"ltr\"", "") @@ -458,7 +458,7 @@ class MessagesComposeFragment : Fragment(), CoroutineScope { EventBus.getDefault().removeStickyEvent(event) if (event.message == null) { - activity.errorSnackbar.addError(ApiError(TAG, ERROR_MESSAGE_NOT_SENT)).show() + activity.error(ApiError(TAG, ERROR_MESSAGE_NOT_SENT)) return } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesFragment.kt index ba1cd04b..1b1b9739 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesFragment.kt @@ -10,13 +10,9 @@ import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial import org.greenrobot.eventbus.EventBus -import org.greenrobot.eventbus.Subscribe -import org.greenrobot.eventbus.ThreadMode import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.MainActivity import pl.szczodrzynski.edziennik.R -import pl.szczodrzynski.edziennik.data.api.events.ApiTaskErrorEvent -import pl.szczodrzynski.edziennik.data.api.events.ApiTaskFinishedEvent import pl.szczodrzynski.edziennik.data.db.modules.messages.Message import pl.szczodrzynski.edziennik.databinding.FragmentMessagesBinding import pl.szczodrzynski.edziennik.utils.Themes @@ -131,26 +127,6 @@ class MessagesFragment : Fragment() { }*/ } - @Subscribe(threadMode = ThreadMode.MAIN) - fun onSyncProfileFinishedEvent(event: ApiTaskFinishedEvent) { - if (event.profileId == App.profileId) { - app.profileSaveFullAsync(app.profile) - } - } - - @Subscribe(threadMode = ThreadMode.MAIN) - fun onSyncErrorEvent(event: ApiTaskErrorEvent) { - app.profile.removeStudentData("accountPassword") - app.profileSaveFullAsync(app.profile) - /*MaterialDialog.Builder(activity) - .title(R.string.login_failed) - .content(R.string.login_failed_text) - .positiveText(R.string.ok) - .neutralText(R.string.report) - .onNeutral { dialog2, which1 -> app.apiEdziennik.guiReportError(getActivity(), error, null) } - .show()*/ - } - override fun onStart() { EventBus.getDefault().register(this) super.onStart() 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 fd7daa71..44299ebe 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 @@ -814,7 +814,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { __/ | |__*/ private String getRegisterCardAverageModeSubText() { - switch (app.profile.getYearAverageMode()) { + switch (App.getConfig().forProfile().getGrades().getYearAverageMode()) { default: case YEAR_1_AVG_2_AVG: return getString(R.string.settings_register_avg_mode_0_short); @@ -894,9 +894,8 @@ public class SettingsNewFragment extends MaterialAboutFragment { .title(getString(R.string.settings_register_avg_mode_dialog_title)) .content(getString(R.string.settings_register_avg_mode_dialog_text)) .items(modeNames) - .itemsCallbackSingleChoice(modeIds.indexOf(app.profile.getYearAverageMode()), (dialog, itemView, which, text) -> { - app.profile.setYearAverageMode(modeIds.get(which)); - app.profileSaveAsync(); + .itemsCallbackSingleChoice(modeIds.indexOf(App.getConfig().forProfile().getGrades().getYearAverageMode()), (dialog, itemView, which, text) -> { + App.getConfig().forProfile().getGrades().setYearAverageMode(modeIds.get(which)); registerCardAverageModeItem.setSubText(getRegisterCardAverageModeSubText()); refreshMaterialAboutList(); return true; @@ -946,7 +945,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { .negativeText(R.string.abort) .show(); new ServerRequest(app, app.requestScheme + APP_URL + "main.php?unregister", "Edziennik/UREG", app.profile) - .withUsername(app.profile.getUsernameId()) + .withUsername(app.profile.getUserCode()) .run((e, result) -> { progressDialog.dismiss(); if (result == null || !result.get("success").getAsString().equals("true")) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/ItemGradesSubjectModel.java b/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/ItemGradesSubjectModel.java index 6a437d14..7c203d03 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/ItemGradesSubjectModel.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/ItemGradesSubjectModel.java @@ -14,6 +14,9 @@ public class ItemGradesSubjectModel { public List grades1; public List grades2; + public int colorMode; + public int yearAverageMode; + public int semester1Unread = 0; public int semester2Unread = 0; diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/widgets/luckynumber/WidgetLuckyNumber.java b/app/src/main/java/pl/szczodrzynski/edziennik/widgets/luckynumber/WidgetLuckyNumber.java index ca0b69f0..10425e43 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/widgets/luckynumber/WidgetLuckyNumber.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/widgets/luckynumber/WidgetLuckyNumber.java @@ -26,7 +26,6 @@ import pl.szczodrzynski.edziennik.MainActivity; import pl.szczodrzynski.edziennik.R; import pl.szczodrzynski.edziennik.data.api.task.EdziennikTask; import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile; -import pl.szczodrzynski.edziennik.utils.models.Date; import pl.szczodrzynski.edziennik.widgets.WidgetConfig; import static pl.szczodrzynski.edziennik.utils.Utils.getCellsForSize; @@ -159,7 +158,7 @@ public class WidgetLuckyNumber extends AppWidgetProvider { } } - Profile profile = app.db.profileDao().getFullByIdNow(widgetConfig.profileId); + Profile profile = app.db.profileDao().getByIdNow(widgetConfig.profileId); IIcon icon = CommunityMaterial.Icon.cmd_emoticon_dead_outline; boolean noNumberText = false; if (profile == null) { @@ -174,8 +173,8 @@ public class WidgetLuckyNumber extends AppWidgetProvider { // profile is available, show its name views.setTextViewText(R.id.widgetLuckyNumberProfileRight, profile.getName()); views.setTextViewText(R.id.widgetLuckyNumberProfileBottom, profile.getName()); - - if (profile.getLuckyNumberEnabled() + // TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + /*if (profile.getLuckyNumberEnabled() && profile.getLuckyNumber() != -1 && profile.getLuckyNumberDate() != null && profile.getLuckyNumberDate().getValue() == Date.getToday().getValue()) { @@ -197,7 +196,7 @@ public class WidgetLuckyNumber extends AppWidgetProvider { views.setTextViewText(R.id.widgetLuckyNumberTextRight, null); views.setTextViewText(R.id.widgetLuckyNumberTextBottom, null); icon = CommunityMaterial.Icon.cmd_emoticon_sad_outline; - } + }*/ } views.setViewVisibility(R.id.widgetLuckyNumberTextRightLayout, noNumberText ? View.GONE : View.VISIBLE); diff --git a/app/src/main/res/layout/fragment_login_sync_error.xml b/app/src/main/res/layout/fragment_login_sync_error.xml index 36a06211..6d629323 100644 --- a/app/src/main/res/layout/fragment_login_sync_error.xml +++ b/app/src/main/res/layout/fragment_login_sync_error.xml @@ -69,15 +69,6 @@ android:layout_marginBottom="16dp" android:orientation="horizontal"> - - - - + + + android:layout_height="match_parent"> - - - + android:layout_height="0dp" + android:layout_weight="1"> - - - - - - - - - - - - - + android:orientation="vertical"> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + android:layout_marginBottom="16dp" + android:orientation="horizontal"> - - + android:layout_marginLeft="8dp" + android:text="@string/back" + android:textAllCaps="false" + android:layout_marginStart="8dp" /> - - - - - - + - - - - - - - - - - + \ No newline at end of file diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index c9d81ac4..5d66c724 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -375,7 +375,7 @@ Turn off registration? An error occurred during sync. Click the button on the bottom to report the error.\n\nProfiles were saved, so the app should work correctly. In case of any problems you can go to Feedback in the Drawer.\n Sync error - %s]]> + Syncing profile Syncing… Registering the device: Login into desktop version of Vulcan e-register and select \"Dostęp mobilny\" option. Click \"Zarejestruj urządzenie mobilne\". You can type in the data or scan the QR code and type only the PIN. diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bbc1f228..ff039368 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -416,8 +416,7 @@ Na pewno wyłączyć rejestrację? Podczas synchronizacji wystąpił błąd. Kliknij przycisk na dole strony, aby go zgłosić.\n\nProfile zostały zapisane, tak więc aplikacja powinna działać poprawnie. W razie co, możesz skorzystać z opcji Pomoc i opinie w menu.\n Błąd synchronizacji - %s]]> - %s… + Synchronizuję profil Synchronizacja… Rejestracja urządzenia: Zaloguj się w wersji komputerowej dziennika Vulcan, a następnie wybierz opcję Dostęp mobilny. Kliknij Zarejestruj urządzenie mobilne. Możesz wpisać otrzymane dane lub zeskanować kod QR i wpisać sam kod PIN. @@ -1147,4 +1146,6 @@ Odpowiedz Kod błędu: %d (w %s) Ten odbiorca został już wybrany + To konto nie ma żadnych uczniów + Do tego konta nie ma przypisanego żadnego ucznia, dlatego zalogowanie nie jest możliwe.\n\nPrzypisz ucznia na stronie swojego e-dziennika lub zaloguj się kontem, które ma przypisanego ucznia. diff --git a/build.gradle b/build.gradle index bcf15e25..31dd5f47 100644 --- a/build.gradle +++ b/build.gradle @@ -45,7 +45,7 @@ buildscript { iconics : "4.0.1", font_cmd : "3.5.95.1-kotlin", - navlib : "8b31921697", + navlib : "9c8fb47c52", gifdrawable : "1.2.15",