Refactor Profiles, Login Stores and Login activity (hoping it works).

This commit is contained in:
Kuba Szczodrzyński 2020-01-04 22:08:56 +01:00
parent 95a150f7d8
commit 30c5b2d1c9
115 changed files with 2314 additions and 2944 deletions

View File

@ -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.AppDb;
import pl.szczodrzynski.edziennik.data.db.modules.debuglog.DebugLog; 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.Profile;
import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull;
import pl.szczodrzynski.edziennik.network.NetworkUtils; import pl.szczodrzynski.edziennik.network.NetworkUtils;
import pl.szczodrzynski.edziennik.network.TLSSocketFactory; import pl.szczodrzynski.edziennik.network.TLSSocketFactory;
import pl.szczodrzynski.edziennik.sync.SyncWorker; 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 SharedPreferences appSharedPrefs; // sharedPreferences for APPCONFIG + JOBS STORE
public AppConfig appConfig; // APPCONFIG: common for all profiles public AppConfig appConfig; // APPCONFIG: common for all profiles
//public AppProfile profile; // current profile //public AppProfile profile; // current profile
public JsonObject loginStore = null;
public SharedPreferences registerStore; // sharedPreferences for REGISTER public SharedPreferences registerStore; // sharedPreferences for REGISTER
//public Register register; // REGISTER for current profile, read from registerStore //public Register register; // REGISTER for current profile, read from registerStore
public ProfileFull profile; public Profile profile;
public Config config; public Config config;
private static Config mConfig; private static Config mConfig;
public static Config getConfig() { public static Config getConfig() {
@ -616,15 +614,6 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
db.profileDao().add(profile); 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) { public void profileLoadById(int id) {
profileLoadById(id, false); profileLoadById(id, false);
@ -638,7 +627,7 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
return; return;
}*/ }*/
if (profile == null || profile.getId() != id) { if (profile == null || profile.getId() != id) {
profile = db.profileDao().getFullByIdNow(id); profile = db.profileDao().getByIdNow(id);
/*if (profile == null) { /*if (profile == null) {
profileLoadById(id); profileLoadById(id);
return; 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) /*public void profileRemove(int id)
{ {
Profile profile = db.profileDao().getFullByIdNow(id); Profile profile = db.profileDao().getFullByIdNow(id);
@ -703,11 +686,13 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
}*/ }*/
public int profileFirstId() { public int profileFirstId() {
return db.profileDao().getFirstId(); Integer id = db.profileDao().getFirstId();
return id == null ? 1 : id;
} }
public int profileLastId() { public int profileLastId() {
return db.profileDao().getLastId(); Integer id = db.profileDao().getLastId();
return id == null ? 1 : id;
} }

View File

@ -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?.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?.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?.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?.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 } 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?.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?.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?.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?.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 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 { fun CharSequence?.isNotNullNorEmpty(): Boolean {
return this != null && this.isNotEmpty() return this != null && this.isNotEmpty()
@ -233,10 +247,7 @@ fun colorFromCssName(name: String): Int {
}.toInt() }.toInt()
} }
fun MutableList<Profile>.filterOutArchived(): MutableList<Profile> { fun List<Profile>.filterOutArchived() = this.filter { !it.archived }
this.removeAll { it.archived }
return this
}
fun Activity.isStoragePermissionGranted(): Boolean { fun Activity.isStoragePermissionGranted(): Boolean {
return if (Build.VERSION.SDK_INT >= 23) { return if (Build.VERSION.SDK_INT >= 23) {

View File

@ -41,6 +41,7 @@ import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode import org.greenrobot.eventbus.ThreadMode
import pl.droidsonroids.gif.GifDrawable import pl.droidsonroids.gif.GifDrawable
import pl.szczodrzynski.edziennik.data.api.events.* 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.szkolny.interceptor.Signing
import pl.szczodrzynski.edziennik.data.api.task.EdziennikTask import pl.szczodrzynski.edziennik.data.api.task.EdziennikTask
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata.* import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata.*
@ -321,6 +322,10 @@ class MainActivity : AppCompatActivity() {
removeAllItems() removeAllItems()
toggleGroupEnabled = false toggleGroupEnabled = false
textInputEnabled = false textInputEnabled = false
onCloseListener = {
if (!app.config.ui.bottomSheetOpened)
app.config.ui.bottomSheetOpened = true
}
} }
drawer.apply { drawer.apply {
@ -328,7 +333,6 @@ class MainActivity : AppCompatActivity() {
drawerProfileListEmptyListener = { drawerProfileListEmptyListener = {
app.config.loginFinished = false app.config.loginFinished = false
app.saveConfig("loginFinished")
profileListEmptyListener() profileListEmptyListener()
} }
drawerItemSelectedListener = { id, position, drawerItem -> drawerItemSelectedListener = { id, position, drawerItem ->
@ -368,10 +372,8 @@ class MainActivity : AppCompatActivity() {
if (!profileListEmpty) { if (!profileListEmpty) {
handleIntent(intent?.extras) handleIntent(intent?.extras)
} }
app.db.profileDao().allFull.observe(this, Observer { profiles -> app.db.profileDao().all.observe(this, Observer { profiles ->
// TODO fix weird -1 profiles ??? drawer.setProfileList(profiles.filter { it.id >= 0 }.toMutableList())
profiles.removeAll { it.id < 0 }
drawer.setProfileList(profiles)
if (profileListEmpty) { if (profileListEmpty) {
profileListEmpty = false profileListEmpty = false
handleIntent(intent?.extras) handleIntent(intent?.extras)
@ -505,13 +507,6 @@ class MainActivity : AppCompatActivity() {
.withIcon(CommunityMaterial.Icon.cmd_android_studio) .withIcon(CommunityMaterial.Icon.cmd_android_studio)
.withOnClickListener(View.OnClickListener { loadTarget(DRAWER_ITEM_DEBUG) }) .withOnClickListener(View.OnClickListener { loadTarget(DRAWER_ITEM_DEBUG) })
} }
EventBus.getDefault().register(this)
}
override fun onDestroy() {
EventBus.getDefault().unregister(this)
super.onDestroy()
} }
var profileListEmptyListener = { var profileListEmptyListener = {
@ -520,9 +515,6 @@ class MainActivity : AppCompatActivity() {
private var profileSettingClickListener = { id: Int, view: View? -> private var profileSettingClickListener = { id: Int, view: View? ->
when (id) { when (id) {
DRAWER_PROFILE_ADD_NEW -> { 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() profileListEmptyListener()
} }
DRAWER_PROFILE_SYNC_ALL -> { DRAWER_PROFILE_SYNC_ALL -> {
@ -601,6 +593,7 @@ class MainActivity : AppCompatActivity() {
} }
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true) @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
fun onApiTaskErrorEvent(event: ApiTaskErrorEvent) { fun onApiTaskErrorEvent(event: ApiTaskErrorEvent) {
EventBus.getDefault().removeStickyEvent(event)
navView.toolbar.apply { navView.toolbar.apply {
subtitleFormat = R.string.toolbar_subtitle subtitleFormat = R.string.toolbar_subtitle
subtitleFormatWithUnread = R.plurals.toolbar_subtitle_with_unread subtitleFormatWithUnread = R.plurals.toolbar_subtitle_with_unread
@ -754,10 +747,12 @@ class MainActivity : AppCompatActivity() {
val filter = IntentFilter() val filter = IntentFilter()
filter.addAction(Intent.ACTION_MAIN) filter.addAction(Intent.ACTION_MAIN)
registerReceiver(intentReceiver, filter) registerReceiver(intentReceiver, filter)
EventBus.getDefault().register(this)
super.onResume() super.onResume()
} }
override fun onPause() { override fun onPause() {
unregisterReceiver(intentReceiver) unregisterReceiver(intentReceiver)
EventBus.getDefault().unregister(this)
super.onPause() super.onPause()
} }
@ -817,7 +812,6 @@ class MainActivity : AppCompatActivity() {
this.runOnUiThread { this.runOnUiThread {
if (app.profile == null) { if (app.profile == null) {
LoginActivity.firstCompleted = false
if (app.config.loginFinished) { if (app.config.loginFinished) {
// this shouldn't run // this shouldn't run
profileListEmptyListener() 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 snackbar(text: String, actionText: String? = null, onClick: (() -> Unit)? = null) = mainSnackbar.snackbar(text, actionText, onClick)
fun snackbarDismiss() = mainSnackbar.dismiss() fun snackbarDismiss() = mainSnackbar.dismiss()
} }

View File

@ -17,7 +17,6 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull;
import pl.szczodrzynski.edziennik.receivers.BootReceiver; import pl.szczodrzynski.edziennik.receivers.BootReceiver;
import pl.szczodrzynski.edziennik.utils.models.Date; import pl.szczodrzynski.edziennik.utils.models.Date;
import pl.szczodrzynski.edziennik.utils.models.Time; import pl.szczodrzynski.edziennik.utils.models.Time;
@ -221,10 +220,8 @@ public class Notifier {
app.appConfig.notifications.add(notification); 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); 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) { if (app.appConfig.notifications.size() > 40) {
app.appConfig.notifications.subList(40, app.appConfig.notifications.size() - 1).clear(); app.appConfig.notifications.subList(40, app.appConfig.notifications.size() - 1).clear();

View File

@ -49,6 +49,11 @@ class Config(val db: AppDb) : CoroutineScope, AbstractConfig {
get() { mLoginFinished = mLoginFinished ?: values.get("loginFinished", false); return mLoginFinished ?: false } get() { mLoginFinished = mLoginFinished ?: values.get("loginFinished", false); return mLoginFinished ?: false }
set(value) { set("loginFinished", value); mLoginFinished = value } 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 private var mDevModePassword: String? = null
var devModePassword: String? var devModePassword: String?
get() { mDevModePassword = mDevModePassword ?: values.get("devModePassword", null as String?); return mDevModePassword } get() { mDevModePassword = mDevModePassword ?: values.get("devModePassword", null as String?); return mDevModePassword }

View File

@ -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.interfaces.EdziennikCallback
import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.api.task.* 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 pl.szczodrzynski.edziennik.utils.Utils.d
import kotlin.math.min import kotlin.math.min
import kotlin.math.roundToInt import kotlin.math.roundToInt
@ -38,7 +38,7 @@ class ApiService : Service() {
private val app by lazy { applicationContext as App } private val app by lazy { applicationContext as App }
private val syncingProfiles = mutableListOf<ProfileFull>() private val syncingProfiles = mutableListOf<Profile>()
private val finishingTaskQueue = mutableListOf( private val finishingTaskQueue = mutableListOf(
SzkolnyTask.sync(syncingProfiles), SzkolnyTask.sync(syncingProfiles),

View File

@ -47,7 +47,6 @@ class DataNotifications(val data: Data) {
val today = Date.getToday() val today = Date.getToday()
val todayValue = today.value val todayValue = today.value
profile.currentSemester = profile.dateToSemester(today)
for (lesson in app.db.timetableDao().getNotNotifiedNow(profileId)) { 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) val text = app.getString(R.string.notification_lesson_change_format, lesson.getDisplayChangeType(app), if (lesson.displayDate == null) "" else lesson.displayDate!!.formattedString, lesson.changeSubjectName)

View File

@ -23,7 +23,7 @@ import pl.szczodrzynski.edziennik.data.api.models.LoginMethod
// vulcan // vulcan
// mobireg // mobireg
const val SYNERGIA_API_ENABLED = true const val SYNERGIA_API_ENABLED = false

View File

@ -74,7 +74,7 @@ object Regexes {
"""id="ctl00_CzyRodzic" value="([01])" />""".toRegex() """id="ctl00_CzyRodzic" value="([01])" />""".toRegex()
} }
val IDZIENNIK_LOGIN_FIRST_SCHOOL_YEAR by lazy { 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 { val IDZIENNIK_LOGIN_FIRST_STUDENT_SELECT by lazy {
"""<select.*?name="ctl00\${"$"}dxComboUczniowie".*?</select>""".toRegex(DOT_MATCHES_ALL) """<select.*?name="ctl00\${"$"}dxComboUczniowie".*?</select>""".toRegex(DOT_MATCHES_ALL)

View File

@ -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 private var mLoginEmail: String? = null
var loginEmail: String? var loginEmail: String?
get() { mLoginEmail = mLoginEmail ?: loginStore.getLoginData("email", null); return mLoginEmail } get() { mLoginEmail = mLoginEmail ?: loginStore.getLoginData("email", null); return mLoginEmail }

View File

@ -5,6 +5,7 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.firstlogin package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.firstlogin
import org.greenrobot.eventbus.EventBus 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_ACCOUNT_NAME_START
import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_STUDENTS_START import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_STUDENTS_START
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik 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.fixName
import pl.szczodrzynski.edziennik.get import pl.szczodrzynski.edziennik.get
import pl.szczodrzynski.edziennik.getShortName import pl.szczodrzynski.edziennik.getShortName
import pl.szczodrzynski.edziennik.utils.Utils import pl.szczodrzynski.edziennik.set
class EdudziennikFirstLogin(val data: DataEdudziennik, val onSuccess: () -> Unit) { class EdudziennikFirstLogin(val data: DataEdudziennik, val onSuccess: () -> Unit) {
companion object { companion object {
@ -26,25 +27,35 @@ class EdudziennikFirstLogin(val data: DataEdudziennik, val onSuccess: () -> Unit
private val profileList = mutableListOf<Profile>() private val profileList = mutableListOf<Profile>()
init { init {
val loginStoreId = data.loginStore.id
val loginStoreType = LOGIN_TYPE_EDUDZIENNIK
var firstProfileId = loginStoreId
EdudziennikLoginWeb(data) { EdudziennikLoginWeb(data) {
web.webGet(TAG, "") { text -> 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 { EDUDZIENNIK_STUDENTS_START.findAll(text).forEach {
val studentId = it[1] 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() val studentNameShort = studentNameLong.getShortName()
profile.studentNameLong = studentName val accountName = if (accountNameLong == studentNameLong) null else accountNameLong
profile.studentNameShort = studentName.getShortName()
profile.accountNameLong = if (studentName == accountName) null else accountName val profile = Profile(
profile.studentSchoolYear = Utils.getCurrentSchoolYear() firstProfileId++,
profile.name = studentName loginStoreId,
profile.subname = data.loginEmail loginStoreType,
profile.empty = true studentNameLong,
profile.putStudentData("studentId", studentId) data.loginEmail,
studentNameLong,
studentNameShort,
accountName
).apply {
studentData["studentId"] = studentId
}
profileList.add(profile) profileList.add(profile)
} }

View File

@ -41,6 +41,8 @@ class DataIdziennik(app: App, profile: Profile?, loginStore: LoginStore) : Data(
loginMethods += LOGIN_METHOD_IDZIENNIK_API loginMethods += LOGIN_METHOD_IDZIENNIK_API
} }
override fun generateUserCode() = "$webSchoolName:$webUsername:$registerId"
private var mLoginExpiryTime: Long? = null private var mLoginExpiryTime: Long? = null
var loginExpiryTime: Long var loginExpiryTime: Long
get() { mLoginExpiryTime = mLoginExpiryTime ?: loginStore.getLoginData("loginExpiryTime", 0L); return mLoginExpiryTime ?: 0L } get() { mLoginExpiryTime = mLoginExpiryTime ?: loginStore.getLoginData("loginExpiryTime", 0L); return mLoginExpiryTime ?: 0L }

View File

@ -25,9 +25,6 @@ class IdziennikApiCurrentRegister(override val data: DataIdziennik,
} }
init { init {
data.profile?.luckyNumber = -1
data.profile?.luckyNumberDate = null
apiGet(TAG, IDZIENNIK_API_CURRENT_REGISTER) { json -> apiGet(TAG, IDZIENNIK_API_CURRENT_REGISTER) { json ->
if (json !is JsonObject) { if (json !is JsonObject) {
onSuccess() onSuccess()
@ -37,9 +34,9 @@ class IdziennikApiCurrentRegister(override val data: DataIdziennik,
var nextSync = System.currentTimeMillis() + 14*DAY*1000 var nextSync = System.currentTimeMillis() + 14*DAY*1000
val settings = json.getJsonObject("ustawienia")?.apply { val settings = json.getJsonObject("ustawienia")?.apply {
profile?.dateSemester1Start = getString("poczatekSemestru1")?.let { Date.fromY_m_d(it) } getString("poczatekSemestru1")?.let { profile?.dateSemester1Start = Date.fromY_m_d(it) }
profile?.dateSemester2Start = getString("koniecSemestru1")?.let { Date.fromY_m_d(it).stepForward(0, 0, 1) } getString("koniecSemestru1")?.let { profile?.dateSemester2Start = Date.fromY_m_d(it).stepForward(0, 0, 1) }
profile?.dateYearEnd = getString("koniecSemestru2")?.let { Date.fromY_m_d(it) } getString("koniecSemestru2")?.let { profile?.dateYearEnd = Date.fromY_m_d(it) }
} }
json.getInt("szczesliwyNumerek")?.let { luckyNumber -> json.getInt("szczesliwyNumerek")?.let { luckyNumber ->

View File

@ -57,7 +57,7 @@ class IdziennikWebGetMessage(
recipientObject.readDate = if (readDateString.isNullOrBlank()) System.currentTimeMillis() recipientObject.readDate = if (readDateString.isNullOrBlank()) System.currentTimeMillis()
else Date.fromIso(readDateString) else Date.fromIso(readDateString)
recipientObject.fullName = profile.accountNameLong ?: profile.studentNameLong recipientObject.fullName = profile.accountName ?: profile.studentNameLong
data.messageRecipientList.add(recipientObject) data.messageRecipientList.add(recipientObject)
message.addRecipient(recipientObject) message.addRecipient(recipientObject)

View File

@ -51,12 +51,12 @@ class IdziennikWebTimetable(override val data: DataIdziennik,
return@webApiGet return@webApiGet
} }
json.getJsonArray("GodzinyLekcyjne")?.asJsonObjectList()?.forEach { range -> json.getJsonArray("GodzinyLekcyjne")?.asJsonObjectList()?.forEachIndexed { index, range ->
val lessonRange = LessonRange( val lessonRange = LessonRange(
profileId, profileId,
range.getInt("LiczbaP") ?: return@forEach, index + 1,
range.getString("Poczatek")?.let { Time.fromH_m(it) } ?: return@forEach, range.getString("Poczatek")?.let { Time.fromH_m(it) } ?: return@forEachIndexed,
range.getString("Koniec")?.let { Time.fromH_m(it) } ?: return@forEach range.getString("Koniec")?.let { Time.fromH_m(it) } ?: return@forEachIndexed
) )
data.lessonRanges[lessonRange.lessonNumber] = lessonRange data.lessonRanges[lessonRange.lessonNumber] = lessonRange
} }

View File

@ -7,6 +7,7 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.firstlogin
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
import pl.szczodrzynski.edziennik.data.api.ERROR_LOGIN_IDZIENNIK_FIRST_NO_SCHOOL_YEAR 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.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.Regexes
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb 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.data.db.modules.profiles.Profile
import pl.szczodrzynski.edziennik.fixName import pl.szczodrzynski.edziennik.fixName
import pl.szczodrzynski.edziennik.get import pl.szczodrzynski.edziennik.get
import pl.szczodrzynski.edziennik.set
import pl.szczodrzynski.edziennik.swapFirstLastName import pl.szczodrzynski.edziennik.swapFirstLastName
class IdziennikFirstLogin(val data: DataIdziennik, val onSuccess: () -> Unit) { class IdziennikFirstLogin(val data: DataIdziennik, val onSuccess: () -> Unit) {
@ -27,6 +29,10 @@ class IdziennikFirstLogin(val data: DataIdziennik, val onSuccess: () -> Unit) {
private val profileList = mutableListOf<Profile>() private val profileList = mutableListOf<Profile>()
init { init {
val loginStoreId = data.loginStore.id
val loginStoreType = LOGIN_TYPE_IDZIENNIK
var firstProfileId = loginStoreId
IdziennikLoginWeb(data) { IdziennikLoginWeb(data) {
web.webGet(TAG, IDZIENNIK_WEB_SETTINGS) { text -> web.webGet(TAG, IDZIENNIK_WEB_SETTINGS) { text ->
//val accounts = json.getJsonArray("accounts") //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 isParent = Regexes.IDZIENNIK_LOGIN_FIRST_IS_PARENT.find(text)?.get(1) != "0"
val accountNameLong = if (isParent) val accountNameLong = if (isParent)
Regexes.IDZIENNIK_LOGIN_FIRST_ACCOUNT_NAME.find(text)?.get(1)?.swapFirstLastName()?.fixName() Regexes.IDZIENNIK_LOGIN_FIRST_ACCOUNT_NAME.find(text)?.get(1)?.swapFirstLastName()?.fixName()
else else null
null
var schoolYearStart: Int? = null
var schoolYearEnd: Int? = null
var schoolYearName: String? = null var schoolYearName: String? = null
val schoolYear = Regexes.IDZIENNIK_LOGIN_FIRST_SCHOOL_YEAR.find(text)?.let { val schoolYearId = Regexes.IDZIENNIK_LOGIN_FIRST_SCHOOL_YEAR.find(text)?.let {
schoolYearName = it[2] schoolYearName = it[2]+"/"+it[3]
schoolYearStart = it[2].toIntOrNull()
schoolYearEnd = it[3].toIntOrNull()
it[1].toIntOrNull() it[1].toIntOrNull()
} ?: run { } ?: run {
data.error(ApiError(TAG, ERROR_LOGIN_IDZIENNIK_FIRST_NO_SCHOOL_YEAR) 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 lastName = match[4]
val className = match[5] + " " + match[6] val className = match[5] + " " + match[6]
val profile = Profile() val studentNameLong = "$firstName $lastName".fixName()
profile.studentNameLong = "$firstName $lastName".fixName() val studentNameShort = "$firstName ${lastName[0]}.".fixName()
profile.studentNameShort = "$firstName ${lastName[0]}.".fixName() val accountName = if (accountNameLong == studentNameLong) null else accountNameLong
profile.accountNameLong = accountNameLong
profile.studentClassName = className val profile = Profile(
profile.studentSchoolYear = schoolYearName firstProfileId++,
profile.name = profile.studentNameLong loginStoreId,
profile.subname = data.webUsername loginStoreType,
profile.empty = true studentNameLong,
profile.putStudentData("studentId", studentId) data.webUsername,
profile.putStudentData("registerId", registerId) studentNameLong,
profile.putStudentData("schoolYearId", schoolYear) studentNameShort,
accountName
).apply {
schoolYearStart?.let { studentSchoolYearStart = it }
studentClassName = className
studentData["studentId"] = studentId
studentData["registerId"] = registerId
studentData["schoolYearId"] = schoolYearId
}
profileList.add(profile) profileList.add(profile)
} }

View File

@ -51,6 +51,8 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
} }
} }
override fun generateUserCode() = "$schoolName:$apiLogin"
fun getColor(id: Int?): Int { fun getColor(id: Int?): Int {
return when (id) { return when (id) {
1 -> 0xFFF0E68C 1 -> 0xFFF0E68C

View File

@ -21,7 +21,7 @@ class LibrusApiAnnouncements(override val data: DataLibrus,
init { data.profile?.also { profile -> init { data.profile?.also { profile ->
apiGet(TAG, "SchoolNotices") { json -> apiGet(TAG, "SchoolNotices") { json ->
val announcements = json.getJsonArray("SchoolNotices").asJsonObjectList() val announcements = json.getJsonArray("SchoolNotices")?.asJsonObjectList()
announcements?.forEach { announcement -> announcements?.forEach { announcement ->
val longId = announcement.getString("Id") ?: return@forEach val longId = announcement.getString("Id") ?: return@forEach

View File

@ -20,7 +20,7 @@ class LibrusApiAttendanceTypes(override val data: DataLibrus,
init { init {
apiGet(TAG, "Attendances/Types") { json -> apiGet(TAG, "Attendances/Types") { json ->
val attendanceTypes = json.getJsonArray("Types").asJsonObjectList() val attendanceTypes = json.getJsonArray("Types")?.asJsonObjectList()
attendanceTypes?.forEach { attendanceType -> attendanceTypes?.forEach { attendanceType ->
val id = attendanceType.getLong("Id") ?: return@forEach val id = attendanceType.getLong("Id") ?: return@forEach

View File

@ -27,7 +27,7 @@ class LibrusApiAttendances(override val data: DataLibrus,
} }
apiGet(TAG, "Attendances") { json -> apiGet(TAG, "Attendances") { json ->
val attendances = json.getJsonArray("Attendances").asJsonObjectList() val attendances = json.getJsonArray("Attendances")?.asJsonObjectList()
attendances?.forEach { attendance -> attendances?.forEach { attendance ->
val id = Utils.strToInt((attendance.getString("Id") ?: return@forEach) val id = Utils.strToInt((attendance.getString("Id") ?: return@forEach)

View File

@ -38,6 +38,8 @@ class LibrusApiClasses(override val data: DataLibrus,
teacherId teacherId
) )
data.profile?.studentClassName = name
data.teamList.put(id, teamObject) data.teamList.put(id, teamObject)
data.unitId = studentClass.getJsonObject("Unit").getLong("Id") ?: 0L data.unitId = studentClass.getJsonObject("Unit").getLong("Id") ?: 0L

View File

@ -19,7 +19,7 @@ class LibrusApiClassrooms(override val data: DataLibrus,
init { init {
apiGet(TAG, "Classrooms") { json -> apiGet(TAG, "Classrooms") { json ->
val classrooms = json.getJsonArray("Classrooms").asJsonObjectList() val classrooms = json.getJsonArray("Classrooms")?.asJsonObjectList()
classrooms?.forEach { classroom -> classrooms?.forEach { classroom ->
val id = classroom.getLong("Id") ?: return@forEach val id = classroom.getLong("Id") ?: return@forEach

View File

@ -18,7 +18,7 @@ class LibrusApiEventTypes(override val data: DataLibrus,
init { init {
apiGet(TAG, "HomeWorks/Categories") { json -> apiGet(TAG, "HomeWorks/Categories") { json ->
val eventTypes = json.getJsonArray("Categories").asJsonObjectList() val eventTypes = json.getJsonArray("Categories")?.asJsonObjectList()
eventTypes?.forEach { eventType -> eventTypes?.forEach { eventType ->
val id = eventType.getLong("Id") ?: return@forEach val id = eventType.getLong("Id") ?: return@forEach

View File

@ -28,7 +28,7 @@ class LibrusApiEvents(override val data: DataLibrus,
} }
apiGet(TAG, "HomeWorks") { json -> apiGet(TAG, "HomeWorks") { json ->
val events = json.getJsonArray("HomeWorks").asJsonObjectList() val events = json.getJsonArray("HomeWorks")?.asJsonObjectList()
events?.forEach { event -> events?.forEach { event ->
val id = event.getLong("Id") ?: return@forEach val id = event.getLong("Id") ?: return@forEach

View File

@ -21,7 +21,7 @@ class LibrusApiGrades(override val data: DataLibrus,
init { data.profile?.also { profile -> init { data.profile?.also { profile ->
apiGet(TAG, "Grades") { json -> apiGet(TAG, "Grades") { json ->
val grades = json.getJsonArray("Grades").asJsonObjectList() val grades = json.getJsonArray("Grades")?.asJsonObjectList()
grades?.forEach { grade -> grades?.forEach { grade ->
val id = grade.getLong("Id") ?: return@forEach val id = grade.getLong("Id") ?: return@forEach

View File

@ -22,7 +22,7 @@ class LibrusApiHomework(override val data: DataLibrus,
init { init {
apiGet(TAG, "HomeWorkAssignments") { json -> apiGet(TAG, "HomeWorkAssignments") { json ->
val homeworkList = json.getJsonArray("HomeWorkAssignments").asJsonObjectList() val homeworkList = json.getJsonArray("HomeWorkAssignments")?.asJsonObjectList()
homeworkList?.forEach { homework -> homeworkList?.forEach { homework ->
val id = homework.getLong("Id") ?: return@forEach val id = homework.getLong("Id") ?: return@forEach

View File

@ -23,9 +23,6 @@ class LibrusApiLuckyNumber(override val data: DataLibrus,
} }
init { init {
data.profile?.luckyNumber = -1
data.profile?.luckyNumberDate = null
var nextSync = System.currentTimeMillis() + 2*DAY*1000 var nextSync = System.currentTimeMillis() + 2*DAY*1000
apiGet(TAG, "LuckyNumbers") { json -> apiGet(TAG, "LuckyNumbers") { json ->

View File

@ -24,7 +24,7 @@ class LibrusApiMe(override val data: DataLibrus,
data.isPremium = account?.getBoolean("IsPremium") == true || account?.getBoolean("IsPremiumDemo") == true data.isPremium = account?.getBoolean("IsPremium") == true || account?.getBoolean("IsPremiumDemo") == true
val isParent = account?.getInt("GroupId") == 5 val isParent = account?.getInt("GroupId") == 5
data.profile?.accountNameLong = data.profile?.accountName =
if (isParent) if (isParent)
buildFullName(account?.getString("FirstName"), account?.getString("LastName")) buildFullName(account?.getString("FirstName"), account?.getString("LastName"))
else null else null

View File

@ -18,7 +18,7 @@ class LibrusApiNoticeTypes(override val data: DataLibrus,
init { init {
apiGet(TAG, "Notes/Categories") { json -> apiGet(TAG, "Notes/Categories") { json ->
val noticeTypes = json.getJsonArray("Categories").asJsonObjectList() val noticeTypes = json.getJsonArray("Categories")?.asJsonObjectList()
noticeTypes?.forEach { noticeType -> noticeTypes?.forEach { noticeType ->
val id = noticeType.getLong("Id") ?: return@forEach val id = noticeType.getLong("Id") ?: return@forEach

View File

@ -26,7 +26,7 @@ class LibrusApiNotices(override val data: DataLibrus,
} }
apiGet(TAG, "Notes") { json -> apiGet(TAG, "Notes") { json ->
val notes = json.getJsonArray("Notes").asJsonObjectList() val notes = json.getJsonArray("Notes")?.asJsonObjectList()
notes?.forEach { note -> notes?.forEach { note ->
val id = note.getLong("Id") ?: return@forEach val id = note.getLong("Id") ?: return@forEach

View File

@ -22,7 +22,7 @@ class LibrusApiPtMeetings(override val data: DataLibrus,
init { init {
apiGet(TAG, "ParentTeacherConferences") { json -> apiGet(TAG, "ParentTeacherConferences") { json ->
val ptMeetings = json.getJsonArray("ParentTeacherConferences").asJsonObjectList() val ptMeetings = json.getJsonArray("ParentTeacherConferences")?.asJsonObjectList()
ptMeetings?.forEach { meeting -> ptMeetings?.forEach { meeting ->
val id = meeting.getLong("Id") ?: return@forEach val id = meeting.getLong("Id") ?: return@forEach

View File

@ -18,7 +18,7 @@ class LibrusApiSubjects(override val data: DataLibrus,
init { init {
apiGet(TAG, "Subjects") { json -> apiGet(TAG, "Subjects") { json ->
val subjects = json.getJsonArray("Subjects").asJsonObjectList() val subjects = json.getJsonArray("Subjects")?.asJsonObjectList()
subjects?.forEach { subject -> subjects?.forEach { subject ->
val id = subject.getLong("Id") ?: return@forEach val id = subject.getLong("Id") ?: return@forEach

View File

@ -18,7 +18,7 @@ class LibrusApiTeacherFreeDayTypes(override val data: DataLibrus,
init { init {
apiGet(TAG, "TeacherFreeDays/Types") { json -> apiGet(TAG, "TeacherFreeDays/Types") { json ->
val teacherAbsenceTypes = json.getJsonArray("Types").asJsonObjectList() val teacherAbsenceTypes = json.getJsonArray("Types")?.asJsonObjectList()
teacherAbsenceTypes?.forEach { teacherAbsenceType -> teacherAbsenceTypes?.forEach { teacherAbsenceType ->
val id = teacherAbsenceType.getLong("Id") ?: return@forEach val id = teacherAbsenceType.getLong("Id") ?: return@forEach

View File

@ -27,7 +27,7 @@ class LibrusApiTeacherFreeDays(override val data: DataLibrus,
} }
apiGet(TAG, "TeacherFreeDays") { json -> apiGet(TAG, "TeacherFreeDays") { json ->
val teacherAbsences = json.getJsonArray("TeacherFreeDays").asJsonObjectList() val teacherAbsences = json.getJsonArray("TeacherFreeDays")?.asJsonObjectList()
teacherAbsences?.forEach { teacherAbsence -> teacherAbsences?.forEach { teacherAbsence ->
val id = teacherAbsence.getLong("Id") ?: return@forEach val id = teacherAbsence.getLong("Id") ?: return@forEach

View File

@ -23,7 +23,7 @@ class LibrusApiUnits(override val data: DataLibrus,
} }
apiGet(TAG, "Units") { json -> 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 -> units?.singleOrNull { it.getLong("Id") == data.unitId }?.also { unit ->
val startPoints = unit.getJsonObject("BehaviourGradesSettings")?.getJsonObject("StartPoints") val startPoints = unit.getJsonObject("BehaviourGradesSettings")?.getJsonObject("StartPoints")

View File

@ -18,7 +18,7 @@ class LibrusApiUsers(override val data: DataLibrus,
init { init {
apiGet(TAG, "Users") { json -> apiGet(TAG, "Users") { json ->
val users = json.getJsonArray("Users").asJsonObjectList() val users = json.getJsonArray("Users")?.asJsonObjectList()
users?.forEach { user -> users?.forEach { user ->
val id = user.getLong("Id") ?: return@forEach val id = user.getLong("Id") ?: return@forEach

View File

@ -18,7 +18,7 @@ class LibrusApiVirtualClasses(override val data: DataLibrus,
init { init {
apiGet(TAG, "VirtualClasses") { json -> apiGet(TAG, "VirtualClasses") { json ->
val virtualClasses = json.getJsonArray("VirtualClasses").asJsonObjectList() val virtualClasses = json.getJsonArray("VirtualClasses")?.asJsonObjectList()
virtualClasses?.forEach { virtualClass -> virtualClasses?.forEach { virtualClass ->
val id = virtualClass.getLong("Id") ?: return@forEach val id = virtualClass.getLong("Id") ?: return@forEach

View File

@ -110,7 +110,7 @@ class LibrusMessagesGetMessage(
messageObject.id messageObject.id
) )
messageRecipientObject.fullName = profile.accountNameLong ?: profile.studentNameLong ?: "" messageRecipientObject.fullName = profile.accountName ?: profile.studentNameLong ?: ""
messageRecipientList.add(messageRecipientObject) messageRecipientList.add(messageRecipientObject)
} }

View File

@ -22,6 +22,10 @@ class LibrusFirstLogin(val data: DataLibrus, val onSuccess: () -> Unit) {
private val profileList = mutableListOf<Profile>() private val profileList = mutableListOf<Profile>()
init { init {
val loginStoreId = data.loginStore.id
val loginStoreType = LOGIN_TYPE_LIBRUS
var firstProfileId = loginStoreId
if (data.loginStore.mode == LOGIN_MODE_LIBRUS_EMAIL) { if (data.loginStore.mode == LOGIN_MODE_LIBRUS_EMAIL) {
// email login: use Portal for account list // email login: use Portal for account list
LibrusLoginPortal(data) { LibrusLoginPortal(data) {
@ -55,18 +59,24 @@ class LibrusFirstLogin(val data: DataLibrus, val onSuccess: () -> Unit) {
val login = account.getString("login") ?: continue val login = account.getString("login") ?: continue
val token = account.getString("accessToken") ?: continue val token = account.getString("accessToken") ?: continue
val tokenTime = (accountDataTime ?: 0) + DAY val tokenTime = (accountDataTime ?: 0) + DAY
val name = account.getString("studentName")?.fixName() ?: "" val studentNameLong = account.getString("studentName").fixName()
val studentNameShort = studentNameLong.getShortName()
val profile = Profile() val profile = Profile(
profile.studentNameLong = name firstProfileId++,
profile.studentNameShort = name.getShortName() loginStoreId,
profile.name = profile.studentNameLong loginStoreType,
profile.subname = data.portalEmail studentNameLong,
profile.empty = true data.portalEmail,
profile.putStudentData("accountId", id) studentNameLong,
profile.putStudentData("accountLogin", login) studentNameShort,
profile.putStudentData("accountToken", token) null
profile.putStudentData("accountTokenTime", tokenTime) ).apply {
studentData["accountId"] = id
studentData["accountLogin"] = login
studentData["accountToken"] = token
studentData["accountTokenTime"] = tokenTime
}
profileList.add(profile) profileList.add(profile)
} }
@ -80,32 +90,36 @@ class LibrusFirstLogin(val data: DataLibrus, val onSuccess: () -> Unit) {
LibrusLoginApi(data) { LibrusLoginApi(data) {
api.apiGet(TAG, "Me") { json -> api.apiGet(TAG, "Me") { json ->
val profile = Profile()
val me = json.getJsonObject("Me") val me = json.getJsonObject("Me")
val account = me?.getJsonObject("Account") val account = me?.getJsonObject("Account")
val user = me?.getJsonObject("User") 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 val studentNameLong = buildFullName(user?.getString("FirstName"), user?.getString("LastName"))
profile.accountNameLong = val studentNameShort = studentNameLong.getShortName()
if (isParent) val accountNameLong = if (isParent)
buildFullName(account?.getString("FirstName"), account?.getString("LastName")) buildFullName(account?.getString("FirstName"), account?.getString("LastName"))
else null else null
profile.studentNameLong = val profile = Profile(
buildFullName(user?.getString("FirstName"), user?.getString("LastName")) firstProfileId++,
loginStoreId,
profile.studentNameShort = profile.studentNameLong?.getShortName() loginStoreType,
profile.name = profile.studentNameLong studentNameLong,
profile.subname = account.getString("Login") login,
profile.empty = true studentNameLong,
profile.putStudentData("accountId", account.getInt("Id") ?: 0) studentNameShort,
profile.putStudentData("accountLogin", profile.subname) accountNameLong
profile.putStudentData("accountToken", data.apiAccessToken) ).apply {
profile.putStudentData("accountRefreshToken", data.apiRefreshToken) studentData["isPremium"] = account?.getBoolean("IsPremium") == true || account?.getBoolean("IsPremiumDemo") == true
profile.putStudentData("accountTokenTime", data.apiTokenExpiryTime) studentData["accountId"] = account.getInt("Id") ?: 0
studentData["accountLogin"] = login
studentData["accountToken"] = data.apiAccessToken
studentData["accountTokenTime"] = data.apiTokenExpiryTime
studentData["accountRefreshToken"] = data.apiRefreshToken
}
profileList.add(profile) profileList.add(profile)
EventBus.getDefault().post(FirstLoginFinishedEvent(profileList, data.loginStore)) EventBus.getDefault().post(FirstLoginFinishedEvent(profileList, data.loginStore))

View File

@ -7,9 +7,9 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik
import android.util.LongSparseArray import android.util.LongSparseArray
import androidx.core.util.isNotEmpty import androidx.core.util.isNotEmpty
import pl.szczodrzynski.edziennik.App 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.LOGIN_METHOD_MOBIDZIENNIK_WEB
import pl.szczodrzynski.edziennik.data.api.models.Data 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.login.LoginStore
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
import pl.szczodrzynski.edziennik.isNotNullNorEmpty 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<String>() val teachersMap = LongSparseArray<String>()
val subjectsMap = LongSparseArray<String>() val subjectsMap = LongSparseArray<String>()

View File

@ -53,6 +53,7 @@ class MobidziennikApiTeams(val data: DataMobidziennik, tableTeams: List<String>?
if (team.type == 1) { if (team.type == 1) {
data.profile?.studentNumber = studentNumber data.profile?.studentNumber = studentNumber
data.teamClass = team data.teamClass = team
data.profile?.studentClassName = team.name
} }
data.teamList.put(teamId, team) data.teamList.put(teamId, team)
} }

View File

@ -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.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.db.modules.luckynumber.LuckyNumber import pl.szczodrzynski.edziennik.data.db.modules.luckynumber.LuckyNumber
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
import pl.szczodrzynski.edziennik.get
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
class MobidziennikLuckyNumberExtractor(val data: DataMobidziennik, text: String) { class MobidziennikLuckyNumberExtractor(val data: DataMobidziennik, text: String) {
init { init {
data.profile?.luckyNumber = -1 Regexes.MOBIDZIENNIK_LUCKY_NUMBER.find(text)?.let {
data.profile?.luckyNumberDate = null try {
val luckyNumber = it.groupValues[1].toInt()
Regexes.MOBIDZIENNIK_LUCKY_NUMBER.find(text)?.get(1)?.toIntOrNull()?.let { val luckyNumberObject = LuckyNumber(
val luckyNumberObject = LuckyNumber( data.profileId,
data.profileId, Date.getToday(),
Date.getToday(), luckyNumber
it )
)
data.luckyNumberList.add(luckyNumberObject) data.luckyNumberList.add(luckyNumberObject)
data.metadataList.add( data.metadataList.add(
Metadata( Metadata(
data.profileId, data.profileId,
Metadata.TYPE_LUCKY_NUMBER, Metadata.TYPE_LUCKY_NUMBER,
luckyNumberObject.date.value.toLong(), luckyNumberObject.date.value.toLong(),
data.profile?.empty ?: false, data.profile?.empty ?: false,
data.profile?.empty ?: false, data.profile?.empty ?: false,
System.currentTimeMillis() System.currentTimeMillis()
)) ))
} catch (_: Exception){}
} }
} }
} }

View File

@ -68,7 +68,7 @@ class MobidziennikWebGetMessage(
message.id message.id
) )
recipient.fullName = profile?.accountNameLong ?: profile?.studentNameLong ?: "" recipient.fullName = profile?.accountName ?: profile?.studentNameLong ?: ""
messageRecipientList.add(recipient) messageRecipientList.add(recipient)
} else { } else {

View File

@ -1,13 +1,15 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.firstlogin package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.firstlogin
import org.greenrobot.eventbus.EventBus 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.DataMobidziennik
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb 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.edziennik.mobidziennik.login.MobidziennikLoginWeb
import pl.szczodrzynski.edziennik.data.api.events.FirstLoginFinishedEvent import pl.szczodrzynski.edziennik.data.api.events.FirstLoginFinishedEvent
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
import pl.szczodrzynski.edziennik.fixName 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) { class MobidziennikFirstLogin(val data: DataMobidziennik, val onSuccess: () -> Unit) {
companion object { companion object {
@ -18,6 +20,10 @@ class MobidziennikFirstLogin(val data: DataMobidziennik, val onSuccess: () -> Un
private val profileList = mutableListOf<Profile>() private val profileList = mutableListOf<Profile>()
init { init {
val loginStoreId = data.loginStore.id
val loginStoreType = LOGIN_TYPE_MOBIDZIENNIK
var firstProfileId = loginStoreId
MobidziennikLoginWeb(data) { MobidziennikLoginWeb(data) {
web.webGet(TAG, "/api/zrzutbazy") { text -> web.webGet(TAG, "/api/zrzutbazy") { text ->
val tables = text.split("T@B#LA") 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 -> tables[8].split("\n").forEach { student ->
if (student.isEmpty()) if (student.isEmpty())
return@forEach return@forEach
@ -39,15 +60,28 @@ class MobidziennikFirstLogin(val data: DataMobidziennik, val onSuccess: () -> Un
if (student1.size == 2) if (student1.size == 2)
return@forEach return@forEach
val profile = Profile() val studentNameLong = "${student1[2]} ${student1[4]}".fixName()
profile.studentNameLong = "${student1[2]} ${student1[4]}".fixName() val studentNameShort = "${student1[2]} ${student1[4][0]}.".fixName()
profile.studentNameShort = "${student1[2]} ${student1[4][0]}.".fixName() val accountName = if (accountNameLong == studentNameLong) null else accountNameLong
profile.accountNameLong = if (accountNameLong == profile.studentNameLong) null else accountNameLong
profile.studentSchoolYear = Utils.getCurrentSchoolYear() val profile = Profile(
profile.name = profile.studentNameLong firstProfileId++,
profile.subname = data.loginUsername loginStoreId,
profile.empty = true loginStoreType,
profile.putStudentData("studentId", student1[0].toInt()) 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) profileList.add(profile)
} }

View File

@ -6,10 +6,10 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.template
import okhttp3.Cookie import okhttp3.Cookie
import pl.szczodrzynski.edziennik.App 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_API
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_TEMPLATE_WEB import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_TEMPLATE_WEB
import pl.szczodrzynski.edziennik.data.api.models.Data 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.login.LoginStore
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
import pl.szczodrzynski.edziennik.isNotNullNorEmpty import pl.szczodrzynski.edziennik.isNotNullNorEmpty
@ -40,6 +40,8 @@ class DataTemplate(app: App, profile: Profile?, loginStore: LoginStore) : Data(a
loginMethods += LOGIN_METHOD_TEMPLATE_API loginMethods += LOGIN_METHOD_TEMPLATE_API
} }
override fun generateUserCode() = "TEMPLATE:DO_NOT_USE"
/* __ __ _ /* __ __ _
\ \ / / | | \ \ / / | |
\ \ /\ / /__| |__ \ \ /\ / /__| |__

View File

@ -5,6 +5,7 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan
import pl.szczodrzynski.edziennik.App 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.LOGIN_METHOD_VULCAN_API
import pl.szczodrzynski.edziennik.data.api.models.Data import pl.szczodrzynski.edziennik.data.api.models.Data
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore 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) { class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app, profile, loginStore) {
fun isApiLoginValid() = /*apiCertificateExpiryTime-30 > currentTimeUnix() fun isApiLoginValid() = currentSemesterEndDate-30 > currentTimeUnix()
&&*/ apiCertificateKey.isNotNullNorEmpty() && apiCertificateKey.isNotNullNorEmpty()
&& apiCertificatePrivate.isNotNullNorEmpty() && apiCertificatePrivate.isNotNullNorEmpty()
&& symbol.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. * 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 } get() { mStudentSemesterNumber = mStudentSemesterNumber ?: profile?.getStudentData("studentSemesterNumber", 0); return mStudentSemesterNumber ?: 0 }
set(value) { profile?.putStudentData("studentSemesterNumber", value) ?: return; mStudentSemesterNumber = value } 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 } get() { mApiCertificateKey = mApiCertificateKey ?: loginStore.getLoginData("certificateKey", null); return mApiCertificateKey }
set(value) { loginStore.putLoginData("certificateKey", value); mApiCertificateKey = value } 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 private var mApiCertificatePfx: String? = null
var apiCertificatePfx: String? var apiCertificatePfx: String?
get() { mApiCertificatePfx = mApiCertificatePfx ?: loginStore.getLoginData("certificatePfx", null); return mApiCertificatePfx } 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 } get() { mApiCertificatePrivate = mApiCertificatePrivate ?: loginStore.getLoginData("certificatePrivate", null); return mApiCertificatePrivate }
set(value) { loginStore.putLoginData("certificatePrivate", value); mApiCertificatePrivate = value } 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? val apiUrl: String?
get() { get() {
val url = when (apiToken?.substring(0, 3)) { val url = when (apiToken?.substring(0, 3)) {

View File

@ -39,7 +39,7 @@ class VulcanApiMessagesInbox(override val data: DataVulcan, val onSuccess: () ->
"LoginId" to data.studentLoginId, "LoginId" to data.studentLoginId,
"IdUczen" to data.studentId "IdUczen" to data.studentId
)) { json, _ -> )) { json, _ ->
json.getJsonArray("Data").asJsonObjectList()?.forEach { message -> json.getJsonArray("Data")?.asJsonObjectList()?.forEach { message ->
val id = message.getLong("WiadomoscId") ?: return@forEach val id = message.getLong("WiadomoscId") ?: return@forEach
val subject = message.getString("Tytul") ?: "" val subject = message.getString("Tytul") ?: ""
val body = message.getString("Tresc") ?: "" val body = message.getString("Tresc") ?: ""

View File

@ -36,7 +36,7 @@ class VulcanApiSendMessage(
} }
} }
val params = mapOf( val params = mapOf(
"NadawcaWiadomosci" to (profile?.accountNameLong ?: profile?.studentNameLong ?: ""), "NadawcaWiadomosci" to (profile?.accountName ?: profile?.studentNameLong ?: ""),
"Tytul" to subject, "Tytul" to subject,
"Tresc" to text, "Tresc" to text,
"Adresaci" to recipientsArray, "Adresaci" to recipientsArray,

View File

@ -7,6 +7,7 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.firstlogin
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.ERROR_NO_STUDENTS_IN_ACCOUNT 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.VULCAN_API_ENDPOINT_STUDENT_LIST
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan 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.edziennik.vulcan.data.VulcanApi
@ -25,11 +26,15 @@ class VulcanFirstLogin(val data: DataVulcan, val onSuccess: () -> Unit) {
private val profileList = mutableListOf<Profile>() private val profileList = mutableListOf<Profile>()
init { init {
val loginStoreId = data.loginStore.id
val loginStoreType = LOGIN_TYPE_VULCAN
var firstProfileId = loginStoreId
VulcanLoginApi(data) { VulcanLoginApi(data) {
api.apiGet(TAG, VULCAN_API_ENDPOINT_STUDENT_LIST, baseUrl = true) { json, response -> api.apiGet(TAG, VULCAN_API_ENDPOINT_STUDENT_LIST, baseUrl = true) { json, response ->
val students = json.getJsonArray("Data") 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) data.error(ApiError(TAG, ERROR_NO_STUDENTS_IN_ACCOUNT)
.withResponse(response) .withResponse(response)
.withApiResponse(json)) .withApiResponse(json))
@ -53,49 +58,56 @@ class VulcanFirstLogin(val data: DataVulcan, val onSuccess: () -> Unit) {
val userLogin = student.getString("UzytkownikLogin") ?: "" val userLogin = student.getString("UzytkownikLogin") ?: ""
val currentSemesterStartDate = student.getLong("OkresDataOd") ?: return@forEach val currentSemesterStartDate = student.getLong("OkresDataOd") ?: return@forEach
val currentSemesterEndDate = (student.getLong("OkresDataDo") val currentSemesterEndDate = (student.getLong("OkresDataDo") ?: return@forEach) + 86400
?: return@forEach) + 86400
val studentSemesterNumber = student.getInt("OkresNumer") ?: return@forEach val studentSemesterNumber = student.getInt("OkresNumer") ?: return@forEach
val newProfile = Profile()
newProfile.empty = true
val isParent = student.getString("UzytkownikRola") == "opiekun" val isParent = student.getString("UzytkownikRola") == "opiekun"
val userName = if (isParent) val accountName = if (isParent)
student.getString("UzytkownikNazwa")?.swapFirstLastName()?.fixName() student.getString("UzytkownikNazwa")?.swapFirstLastName()?.fixName()
else else null
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)
var dateSemester1Start: Date? = null
var dateSemester2Start: Date? = null
var dateYearEnd: Date? = null
when (studentSemesterNumber) { when (studentSemesterNumber) {
1 -> { 1 -> {
newProfile.dateSemester1Start = Date.fromMillis(currentSemesterStartDate * 1000) dateSemester1Start = Date.fromMillis(currentSemesterStartDate * 1000)
newProfile.dateSemester2Start = Date.fromMillis(currentSemesterEndDate * 1000) dateSemester2Start = Date.fromMillis(currentSemesterEndDate * 1000)
} }
2 -> { 2 -> {
newProfile.dateSemester2Start = Date.fromMillis(currentSemesterStartDate * 1000) dateSemester2Start = Date.fromMillis(currentSemesterStartDate * 1000)
newProfile.dateYearEnd = Date.fromMillis(currentSemesterEndDate * 1000) dateYearEnd = Date.fromMillis(currentSemesterEndDate * 1000)
} }
} }
newProfile.studentNameLong = studentNameLong val profile = Profile(
newProfile.studentNameShort = studentNameShort firstProfileId++,
newProfile.name = studentNameLong loginStoreId,
newProfile.subname = userLogin 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)) EventBus.getDefault().post(FirstLoginFinishedEvent(profileList, data.loginStore))

View File

@ -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()}
}

View File

@ -10,10 +10,10 @@ import im.wangchao.mhttp.Request
import im.wangchao.mhttp.Response import im.wangchao.mhttp.Response
import im.wangchao.mhttp.callback.JsonCallbackHandler import im.wangchao.mhttp.callback.JsonCallbackHandler
import io.github.wulkanowy.signer.android.getPrivateKeyFromCert import io.github.wulkanowy.signer.android.getPrivateKeyFromCert
import pl.szczodrzynski.edziennik.currentTimeUnix
import pl.szczodrzynski.edziennik.data.api.* import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.currentTimeUnix
import pl.szczodrzynski.edziennik.getJsonObject import pl.szczodrzynski.edziennik.getJsonObject
import pl.szczodrzynski.edziennik.getString import pl.szczodrzynski.edziennik.getString
import pl.szczodrzynski.edziennik.isNotNullNorEmpty import pl.szczodrzynski.edziennik.isNotNullNorEmpty
@ -32,6 +32,7 @@ class VulcanLoginApi(val data: DataVulcan, val onSuccess: () -> Unit) {
onSuccess() onSuccess()
} }
else { else {
// < v4.0 - PFX to Private Key migration
if (data.apiCertificatePfx.isNotNullNorEmpty()) { if (data.apiCertificatePfx.isNotNullNorEmpty()) {
try { try {
data.apiCertificatePrivate = getPrivateKeyFromCert( data.apiCertificatePrivate = getPrivateKeyFromCert(
@ -46,6 +47,16 @@ class VulcanLoginApi(val data: DataVulcan, val onSuccess: () -> Unit) {
return@run 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()) { if (data.symbol.isNotNullNorEmpty() && data.apiToken.isNotNullNorEmpty() && data.apiPin.isNotNullNorEmpty()) {
loginWithToken() loginWithToken()
} }
@ -107,12 +118,10 @@ class VulcanLoginApi(val data: DataVulcan, val onSuccess: () -> Unit) {
} }
data.apiCertificateKey = cert.getString("CertyfikatKlucz") data.apiCertificateKey = cert.getString("CertyfikatKlucz")
data.apiCertificatePfx = cert.getString("CertyfikatPfx")
data.apiCertificateExpiryTime = 1598832000
data.apiToken = data.apiToken?.substring(0, 3) data.apiToken = data.apiToken?.substring(0, 3)
data.apiCertificatePrivate = getPrivateKeyFromCert( data.apiCertificatePrivate = getPrivateKeyFromCert(
if (data.apiToken?.get(0) == 'F') VULCAN_API_PASSWORD_FAKELOG else VULCAN_API_PASSWORD, 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("certificatePfx")
data.loginStore.removeLoginData("devicePin") data.loginStore.removeLoginData("devicePin")

View File

@ -46,7 +46,7 @@ import java.net.SocketTimeoutException
import java.net.UnknownHostException import java.net.UnknownHostException
import javax.net.ssl.SSLException 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 { companion object {
private const val TAG = "Data" 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 return // return on first login
profile.empty = false profile.empty = false
profile.userCode = generateUserCode()
db.profileDao().add(profile) db.profileDao().add(profile)
db.loginStoreDao().add(loginStore) db.loginStoreDao().add(loginStore)
@ -230,31 +231,18 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
name = profile.name name = profile.name
subname = profile.subname subname = profile.subname
syncEnabled = profile.syncEnabled syncEnabled = profile.syncEnabled
loggedIn = profile.loggedIn
empty = profile.empty empty = profile.empty
archived = profile.archived archived = profile.archived
studentNameLong = profile.studentNameLong studentNameLong = profile.studentNameLong
studentNameShort = profile.studentNameShort studentNameShort = profile.studentNameShort
studentNumber = profile.studentNumber studentNumber = profile.studentNumber
studentData = profile.studentData accountName = profile.accountName
accountNameLong = profile.accountNameLong
yearAverageMode = profile.yearAverageMode
currentSemester = profile.currentSemester
attendancePercentage = profile.attendancePercentage
dateSemester1Start = profile.dateSemester1Start dateSemester1Start = profile.dateSemester1Start
dateSemester2Start = profile.dateSemester2Start dateSemester2Start = profile.dateSemester2Start
dateYearEnd = profile.dateYearEnd dateYearEnd = profile.dateYearEnd
luckyNumberEnabled = profile.luckyNumberEnabled
luckyNumber = profile.luckyNumber
luckyNumberDate = profile.luckyNumberDate
lastFullSync = profile.lastFullSync
lastReceiversSync = profile.lastReceiversSync 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 // always present and not empty, during every sync
db.endpointTimerDao().addAll(endpointTimers) 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() { fun cancel() {
d("Data", "Cancelled") d("Data", "Cancelled")
cancelled = true cancelled = true

View File

@ -8,13 +8,12 @@ import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata 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.Profile
import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull
class Szkolny(val app: App, val callback: EdziennikCallback) { class Szkolny(val app: App, val callback: EdziennikCallback) {
private val api = SzkolnyApi(app) private val api = SzkolnyApi(app)
fun sync(profileList: List<ProfileFull>) { fun sync(profileList: List<Profile>) {
val profiles = profileList.filter { it.registration == Profile.REGISTRATION_ENABLED } val profiles = profileList.filter { it.registration == Profile.REGISTRATION_ENABLED }
if (profiles.isNotEmpty()) { if (profiles.isNotEmpty()) {
val events = api.getEvents(profiles) val events = api.getEvents(profiles)

View File

@ -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.api.szkolny.response.WebPushResponse
import pl.szczodrzynski.edziennik.data.db.modules.events.Event 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.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.Date
import pl.szczodrzynski.edziennik.utils.models.Time import pl.szczodrzynski.edziennik.utils.models.Time
import retrofit2.Retrofit import retrofit2.Retrofit
@ -55,7 +55,7 @@ class SzkolnyApi(val app: App) {
api = retrofit.create() api = retrofit.create()
} }
fun getEvents(profiles: List<ProfileFull>): List<EventFull> { fun getEvents(profiles: List<Profile>): List<EventFull> {
val teams = app.db.teamDao().allNow val teams = app.db.teamDao().allNow
val notifications = app.db.notificationDao().getNotPostedNow() val notifications = app.db.notificationDao().getNotPostedNow()
@ -71,10 +71,10 @@ class SzkolnyApi(val app: App) {
appVersionCode = BuildConfig.VERSION_CODE, appVersionCode = BuildConfig.VERSION_CODE,
syncInterval = app.config.sync.interval syncInterval = app.config.sync.interval
), ),
userCodes = profiles.map { it.usernameId }, userCodes = profiles.map { it.userCode },
users = profiles.map { profile -> users = profiles.map { profile ->
ServerSyncRequest.User( ServerSyncRequest.User(
profile.usernameId, profile.userCode,
profile.studentNameLong ?: "", profile.studentNameLong ?: "",
profile.studentNameShort ?: "", profile.studentNameShort ?: "",
profile.loginStoreType, profile.loginStoreType,
@ -97,7 +97,7 @@ class SzkolnyApi(val app: App) {
seen = profile?.empty ?: false seen = profile?.empty ?: false
notified = profile?.empty ?: false notified = profile?.empty ?: false
if (profile?.usernameId == event.sharedBy) sharedBy = "self" if (profile?.userCode == event.sharedBy) sharedBy = "self"
}) })
} }
} }

View File

@ -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) taskName = app.getString(R.string.edziennik_notification_api_first_login_title)
} else { } else {
// get the requested profile and login store // 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 this.profile = profile
if (profile == null) {
return
}
val loginStore = app.db.loginStoreDao().getByIdNow(profile.loginStoreId) ?: return val loginStore = app.db.loginStoreDao().getByIdNow(profile.loginStoreId) ?: return
this.loginStore = loginStore this.loginStore = loginStore
// save the profile ID and name as the current task's // save the profile ID and name as the current task's

View File

@ -11,11 +11,11 @@ import android.os.Build.VERSION_CODES.O
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.data.api.ApiService 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) { abstract class IApiTask(open val profileId: Int) {
var taskId: Int = 0 var taskId: Int = 0
var profile: ProfileFull? = null var profile: Profile? = null
var taskName: String? = null var taskName: String? = null
/** /**

View File

@ -8,14 +8,13 @@ import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
import pl.szczodrzynski.edziennik.data.api.szkolny.Szkolny 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.Profile
import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull
class SzkolnyTask(val request: Any) : IApiTask(-1) { class SzkolnyTask(val request: Any) : IApiTask(-1) {
companion object { companion object {
private const val TAG = "SzkolnyTask" private const val TAG = "SzkolnyTask"
fun sync(profiles: List<ProfileFull>) = SzkolnyTask(SyncRequest(profiles)) fun sync(profiles: List<Profile>) = SzkolnyTask(SyncRequest(profiles))
/*fun shareEvent(event: EventFull) = SzkolnyTask(ShareEventRequest(event)) /*fun shareEvent(event: EventFull) = SzkolnyTask(ShareEventRequest(event))
fun unshareEvent(event: EventFull) = SzkolnyTask(UnshareEventRequest(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<ProfileFull>) data class SyncRequest(val profiles: List<Profile>)
/*data class ShareEventRequest(val event: EventFull) /*data class ShareEventRequest(val event: EventFull)
data class UnshareEventRequest(val event: EventFull)*/ data class UnshareEventRequest(val event: EventFull)*/
} }

View File

@ -1,6 +1,7 @@
package pl.szczodrzynski.edziennik.data.db; package pl.szczodrzynski.edziennik.data.db;
import android.content.Context; import android.content.Context;
import android.database.Cursor;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.room.Database; import androidx.room.Database;
@ -10,6 +11,7 @@ import androidx.room.TypeConverters;
import androidx.room.migration.Migration; import androidx.room.migration.Migration;
import androidx.sqlite.db.SupportSQLiteDatabase; import androidx.sqlite.db.SupportSQLiteDatabase;
import pl.szczodrzynski.edziennik.ExtensionsKt;
import pl.szczodrzynski.edziennik.config.db.ConfigDao; import pl.szczodrzynski.edziennik.config.db.ConfigDao;
import pl.szczodrzynski.edziennik.config.db.ConfigEntry; import pl.szczodrzynski.edziennik.config.db.ConfigEntry;
import pl.szczodrzynski.edziennik.data.db.converters.ConverterDate; import pl.szczodrzynski.edziennik.data.db.converters.ConverterDate;
@ -108,7 +110,7 @@ import pl.szczodrzynski.edziennik.utils.models.Date;
AttendanceType.class, AttendanceType.class,
pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson.class, pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson.class,
ConfigEntry.class, ConfigEntry.class,
Metadata.class}, version = 71) Metadata.class}, version = 72)
@TypeConverters({ @TypeConverters({
ConverterTime.class, ConverterTime.class,
ConverterDate.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\");"); 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) { public static AppDb getDatabase(final Context context) {
@ -917,7 +1027,8 @@ public abstract class AppDb extends RoomDatabase {
MIGRATION_67_68, MIGRATION_67_68,
MIGRATION_68_69, MIGRATION_68_69,
MIGRATION_69_70, MIGRATION_69_70,
MIGRATION_70_71 MIGRATION_70_71,
MIGRATION_71_72
) )
.allowMainThreadQueries() .allowMainThreadQueries()
//.fallbackToDestructiveMigration() //.fallbackToDestructiveMigration()

View File

@ -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 +
'}';
}
}

View File

@ -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 +
'}'
}
}

View File

@ -8,8 +8,6 @@ import androidx.room.Query;
import java.util.List; import java.util.List;
import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull;
@Dao @Dao
public abstract class LoginStoreDao { public abstract class LoginStoreDao {
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
@ -27,10 +25,6 @@ public abstract class LoginStoreDao {
@Query("SELECT * FROM loginStores WHERE loginStoreId = :loginStoreId") @Query("SELECT * FROM loginStores WHERE loginStoreId = :loginStoreId")
public abstract LoginStore getByIdNow(int 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") @Query("UPDATE loginStores SET loginStoreId = :targetId WHERE loginStoreId = :sourceId")
public abstract void changeId(int sourceId, int targetId); public abstract void changeId(int sourceId, int targetId);

View File

@ -1,10 +1,13 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-1-3.
*/
package pl.szczodrzynski.edziennik.data.db.modules.profiles package pl.szczodrzynski.edziennik.data.db.modules.profiles
import android.content.Context import android.content.Context
import android.graphics.PorterDuff import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter import android.graphics.PorterDuffColorFilter
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.net.ConnectivityManager
import android.widget.ImageView import android.widget.ImageView
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory
import androidx.room.ColumnInfo import androidx.room.ColumnInfo
@ -12,7 +15,9 @@ import androidx.room.Entity
import androidx.room.Ignore import androidx.room.Ignore
import com.google.gson.JsonObject import com.google.gson.JsonObject
import pl.droidsonroids.gif.GifDrawable 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.edziennik.utils.models.Date
import pl.szczodrzynski.navlib.ImageHolder import pl.szczodrzynski.navlib.ImageHolder
import pl.szczodrzynski.navlib.R import pl.szczodrzynski.navlib.R
@ -20,143 +25,91 @@ import pl.szczodrzynski.navlib.drawer.IDrawerProfile
import pl.szczodrzynski.navlib.getDrawableFromRes import pl.szczodrzynski.navlib.getDrawableFromRes
@Entity(tableName = "profiles", primaryKeys = ["profileId"]) @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 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 empty = true
var archived = false var archived = false
/** var syncEnabled = true
* The name of the student. var enableSharedEvents = true
* This doesn't change, no matter if it's a parent or student account. var registration = REGISTRATION_UNSPECIFIED
*/ var userCode = ""
var studentNameLong: String? = null
var studentNameShort: String? = null
/** /**
* The student's number in the class register. * The student's number in the class register.
*/ */
var studentNumber = -1 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 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 dateSemester1Start = Date(studentSchoolYearStart, 9, 1)
var dateSemester2Start = Date(studentSchoolYearStart + 1, 2, 1)
var gradeColorMode = COLOR_MODE_WEIGHTED var dateYearEnd = Date(studentSchoolYearStart + 1, 6, 30)
var agendaViewType = AGENDA_DEFAULT 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
var yearAverageMode = YEAR_ALL_GRADES fun dateToSemester(date: Date) = if (date.value >= getSemesterStart(2).value) 2 else 1
@delegate:Ignore
var currentSemester = 1 val currentSemester by lazy { dateToSemester(Date.getToday()) }
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<Integer, Pair<String, Integer>> eventTypes;
var loginStoreId = id
var changedEndpoints: List<String>? = null
var disabledNotifications: List<Long>? = null var disabledNotifications: List<Long>? = null
var lastFullSync: Long = 0
var lastReceiversSync: Long = 0 var lastReceiversSync: Long = 0
fun shouldFullSync(context: Context): Boolean { fun hasStudentData(key: String) = studentData.has(key)
val connManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager fun getStudentData(key: String, defaultValue: Boolean) = studentData.getBoolean(key) ?: defaultValue
val mWifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI) fun getStudentData(key: String, defaultValue: String?) = studentData.getString(key) ?: defaultValue
// if time since last full sync is > 7 days and wifi is connected fun getStudentData(key: String, defaultValue: Int) = studentData.getInt(key) ?: defaultValue
// or fun getStudentData(key: String, defaultValue: Long) = studentData.getLong(key) ?: defaultValue
// if time since last full sync is > 14 days, regardless of wifi state fun getStudentData(key: String, defaultValue: Float) = studentData.getFloat(key) ?: defaultValue
return System.currentTimeMillis() - lastFullSync > 7 * 24 * 60 * 60 * 1000 && mWifi.isConnected || System.currentTimeMillis() - lastFullSync > 14 * 24 * 60 * 60 * 1000 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 val isParent
constructor(id: Int, name: String, subname: String, loginStoreId: Int) : this() { get() = accountName != null
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);
}
override fun getImageDrawable(context: Context): Drawable { override fun getImageDrawable(context: Context): Drawable {
@ -179,13 +132,6 @@ open class Profile : IDrawerProfile {
it.colorFilter = PorterDuffColorFilter(colorFromName(name), PorterDuff.Mode.DST_OVER) 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 { override fun getImageHolder(context: Context): ImageHolder {
return if (!image.isNullOrEmpty()) { return if (!image.isNullOrEmpty()) {
@ -203,130 +149,43 @@ open class Profile : IDrawerProfile {
getImageHolder(imageView.context).applyTo(imageView) getImageHolder(imageView.context).applyTo(imageView)
} }
fun hasStudentData(key: String): Boolean { val supportedFragments: List<Int>
if (studentData == null) get() = when (loginStoreType) {
return false LoginStore.LOGIN_TYPE_MOBIDZIENNIK,
return studentData?.has(key) ?: false LoginStore.LOGIN_TYPE_DEMO,
} LoginStore.LOGIN_TYPE_VULCAN -> listOf(
MainActivity.DRAWER_ITEM_TIMETABLE,
fun getStudentData(key: String, defaultValue: String?): String? { MainActivity.DRAWER_ITEM_AGENDA,
if (studentData == null) MainActivity.DRAWER_ITEM_GRADES,
return defaultValue MainActivity.DRAWER_ITEM_MESSAGES,
val element = studentData!!.get(key) MainActivity.DRAWER_ITEM_HOMEWORK,
return if (element != null) { MainActivity.DRAWER_ITEM_BEHAVIOUR,
element.asString MainActivity.DRAWER_ITEM_ATTENDANCE
} else defaultValue )
} LoginStore.LOGIN_TYPE_LIBRUS,
LoginStore.LOGIN_TYPE_IDZIENNIK -> listOf(
fun getStudentData(key: String, defaultValue: Int): Int { MainActivity.DRAWER_ITEM_TIMETABLE,
if (studentData == null) MainActivity.DRAWER_ITEM_AGENDA,
return defaultValue MainActivity.DRAWER_ITEM_GRADES,
val element = studentData!!.get(key) MainActivity.DRAWER_ITEM_MESSAGES,
return element?.asInt ?: defaultValue MainActivity.DRAWER_ITEM_HOMEWORK,
} MainActivity.DRAWER_ITEM_BEHAVIOUR,
MainActivity.DRAWER_ITEM_ATTENDANCE,
fun getStudentData(key: String, defaultValue: Long): Long { MainActivity.DRAWER_ITEM_ANNOUNCEMENTS
if (studentData == null) )
return defaultValue LOGIN_TYPE_EDUDZIENNIK -> listOf(
val element = studentData!!.get(key) MainActivity.DRAWER_ITEM_TIMETABLE,
return element?.asLong ?: defaultValue MainActivity.DRAWER_ITEM_AGENDA,
} MainActivity.DRAWER_ITEM_GRADES,
MainActivity.DRAWER_ITEM_HOMEWORK,
fun getStudentData(key: String, defaultValue: Float): Float { MainActivity.DRAWER_ITEM_BEHAVIOUR,
if (studentData == null) MainActivity.DRAWER_ITEM_ATTENDANCE,
return defaultValue MainActivity.DRAWER_ITEM_ANNOUNCEMENTS
val element = studentData!!.get(key) )
return element?.asFloat ?: defaultValue else -> listOf(
} MainActivity.DRAWER_ITEM_TIMETABLE,
MainActivity.DRAWER_ITEM_AGENDA,
fun getStudentData(key: String, defaultValue: Boolean): Boolean { MainActivity.DRAWER_ITEM_GRADES
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
}
} }

View File

@ -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<Profile> 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<ProfileFull> 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<List<Profile>> getAll();
@Query("SELECT * FROM profiles WHERE profileId >= 0 ORDER BY profileId")
List<Profile> 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<List<ProfileFull>> 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<ProfileFull> getAllFullNow();
@Query("SELECT profileId FROM profiles WHERE loginStoreId = :loginStoreId ORDER BY profileId")
List<Integer> getIdsByLoginStoreIdNow(int loginStoreId);
@Query("SELECT * FROM profiles WHERE syncEnabled = 1 AND archived = 0 AND profileId >= 0 ORDER BY profileId")
List<Profile> getProfilesForSyncNow();
@Query("SELECT profileId FROM profiles WHERE syncEnabled = 1 AND archived = 0 AND profileId >= 0 ORDER BY profileId")
List<Integer> getIdsForSyncNow();
@Query("SELECT profileId FROM profiles WHERE profileId >= 0 ORDER BY profileId")
List<Integer> 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<ProfileFull> 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);
}

View File

@ -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<Profile>)
@Query("DELETE FROM profiles WHERE profileId = :profileId")
fun remove(profileId: Int)
@Query("SELECT profiles.* FROM profiles WHERE profileId = :profileId")
fun getById(profileId: Int): LiveData<Profile?>
@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<List<Profile>>
@get:Query("SELECT * FROM profiles WHERE profileId >= 0 ORDER BY profileId")
val allNow: List<Profile>
@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<Int>
@get:Query("SELECT * FROM profiles WHERE syncEnabled = 1 AND archived = 0 AND profileId >= 0 ORDER BY profileId")
val profilesForSyncNow: List<Profile>
@get:Query("SELECT profileId FROM profiles WHERE syncEnabled = 1 AND archived = 0 AND profileId >= 0 ORDER BY profileId")
val idsForSyncNow: List<Int>
@get:Query("SELECT profileId FROM profiles WHERE profileId >= 0 ORDER BY profileId")
val idsNow: List<Int>
@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<Profile>
@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?
}

View File

@ -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<Int>
get() {
val fragmentIds: MutableList<Int>
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()
}
}

View File

@ -17,7 +17,6 @@ import im.wangchao.mhttp.callback.JsonCallbackHandler;
import pl.szczodrzynski.edziennik.App; import pl.szczodrzynski.edziennik.App;
import pl.szczodrzynski.edziennik.BuildConfig; import pl.szczodrzynski.edziennik.BuildConfig;
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile; 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 pl.szczodrzynski.edziennik.utils.Utils;
import static pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile.REGISTRATION_ENABLED; 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); this(app, url, source, app.profile);
} }
public ServerRequest(App app, String url, String source, ProfileFull profileFull) { public ServerRequest(App app, String url, String source, Profile profileFull) {
this(app, url, source, profileFull, profileFull == null ? -1 : profileFull.getLoginStoreType(), profileFull == null ? "" : profileFull.getUsernameId()); 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) { public ServerRequest(App app, String url, String source, Profile profile, int loginStoreType, String usernameId) {

View File

@ -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.EventFull;
import pl.szczodrzynski.edziennik.data.db.modules.events.EventType; 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.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.data.db.modules.teams.Team;
import pl.szczodrzynski.edziennik.network.ServerRequest; import pl.szczodrzynski.edziennik.network.ServerRequest;
import pl.szczodrzynski.edziennik.ui.modules.base.DebugFragment; import pl.szczodrzynski.edziennik.ui.modules.base.DebugFragment;
@ -88,11 +88,11 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService {
if (studentIdStr != null) { if (studentIdStr != null) {
int studentId = strToInt(studentIdStr); int studentId = strToInt(studentIdStr);
AsyncTask.execute(() -> { AsyncTask.execute(() -> {
List<ProfileFull> profileList = app.db.profileDao().getAllFullNow(); List<Profile> 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 if (profileFull.getLoginStoreType() == LOGIN_TYPE_MOBIDZIENNIK
&& studentId == profileFull.getStudentData("studentId", -1)) { && studentId == profileFull.getStudentData("studentId", -1)) {
profile = profileFull; profile = profileFull;
@ -185,7 +185,7 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService {
.withType(TYPE_SERVER_MESSAGE) .withType(TYPE_SERVER_MESSAGE)
.withFragmentRedirect(MainActivity.DRAWER_ITEM_NOTIFICATIONS) .withFragmentRedirect(MainActivity.DRAWER_ITEM_NOTIFICATIONS)
); );
app.notifier.postAll(null); app.notifier.postAll();
app.saveConfig("notifications"); app.saveConfig("notifications");
break; break;
case "feedback_message_from_dev": case "feedback_message_from_dev":
@ -212,7 +212,7 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService {
.withType(TYPE_FEEDBACK_MESSAGE) .withType(TYPE_FEEDBACK_MESSAGE)
.withFragmentRedirect(MainActivity.TARGET_FEEDBACK) .withFragmentRedirect(MainActivity.TARGET_FEEDBACK)
); );
app.notifier.postAll(null); app.notifier.postAll();
app.saveConfig("notifications"); app.saveConfig("notifications");
} }
}); });
@ -234,7 +234,7 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService {
.withType(TYPE_FEEDBACK_MESSAGE) .withType(TYPE_FEEDBACK_MESSAGE)
.withFragmentRedirect(MainActivity.TARGET_FEEDBACK) .withFragmentRedirect(MainActivity.TARGET_FEEDBACK)
); );
app.notifier.postAll(null); app.notifier.postAll();
app.saveConfig("notifications"); app.saveConfig("notifications");
break; break;
case "ping": case "ping":
@ -254,8 +254,8 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService {
while (teamCode != null || teamUnshareCode != null) { while (teamCode != null || teamUnshareCode != null) {
d(TAG, "Got an event for teamCode " + teamCode + " and teamUnshareCode " + teamUnshareCode); d(TAG, "Got an event for teamCode " + teamCode + " and teamUnshareCode " + teamUnshareCode);
// get the target Profile by the corresponding teamCode // get the target Profile by the corresponding teamCode
List<ProfileFull> profiles = app.db.profileDao().getByTeamCodeNowWithRegistration(teamCode == null ? teamUnshareCode : teamCode); List<Profile> profiles = app.db.profileDao().getByTeamCodeNowWithRegistration(teamCode == null ? teamUnshareCode : teamCode);
for (ProfileFull profile : profiles) { for (Profile profile : profiles) {
d(TAG, "Matched profile " + profile.getName()); d(TAG, "Matched profile " + profile.getName());
if (teamCode != null) { if (teamCode != null) {
// SHARING // SHARING
@ -276,7 +276,7 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService {
// TODO? i guess // TODO? i guess
Event oldEvent = app.db.eventDao().getByIdNow(profile.getId(), event.id); 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"); d(TAG, "Shared by self! Changing name");
event.sharedBy = "self"; event.sharedBy = "self";
event.sharedByName = profile.getStudentNameLong(); event.sharedByName = profile.getStudentNameLong();
@ -318,7 +318,7 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService {
teamUnshareCode = null; teamUnshareCode = null;
} }
} }
app.notifier.postAll(null); app.notifier.postAll();
app.saveConfig(); app.saveConfig();
}); });
break; break;

View File

@ -21,7 +21,6 @@ import kotlinx.coroutines.*
import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_AGENDA import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_AGENDA
import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi 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.Event
import pl.szczodrzynski.edziennik.data.db.modules.events.EventFull 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.events.EventType
@ -609,7 +608,7 @@ class EventManualDialog(
) )
launch { launch {
val profile = app.db.profileDao().getFullByIdNow(profileId) val profile = app.db.profileDao().getByIdNow(profileId)
if (!share && !editingShared) { if (!share && !editingShared) {
Toast.makeText(activity, "Save without sharing", Toast.LENGTH_SHORT).show() 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() Toast.makeText(activity, "Share/update own event", Toast.LENGTH_SHORT).show()
eventObject.apply { eventObject.apply {
sharedBy = profile?.usernameId sharedBy = profile?.userCode
sharedByName = profile?.studentNameLong sharedByName = profile?.studentNameLong
} }

View File

@ -74,7 +74,7 @@ public class GradeDetailsDialog {
b.setGrade(grade); b.setGrade(grade);
int gradeColor; int gradeColor;
if (app.profile.getGradeColorMode() == COLOR_MODE_DEFAULT) { if (App.getConfig().getFor(profileId).getGrades().getColorMode() == COLOR_MODE_DEFAULT) {
gradeColor = grade.color; gradeColor = grade.color;
} }
else { else {

View File

@ -312,10 +312,7 @@ public class AttendanceFragment extends Fragment {
float attendancePercentage; float attendancePercentage;
// in Mobidziennik there are no TYPE_PRESENT records so we cannot calculate the percentage // in Mobidziennik there are no TYPE_PRESENT records so we cannot calculate the percentage
if (app.profile.getLoginStoreType() == LOGIN_TYPE_MOBIDZIENNIK && false) { if (app.profile.getLoginStoreType() == LOGIN_TYPE_VULCAN) {
attendancePercentage = app.profile.getAttendancePercentage();
}
else if (app.profile.getLoginStoreType() == LOGIN_TYPE_VULCAN) {
float allCount = presentCount + absentCount + belatedCount; // do not count releases float allCount = presentCount + absentCount + belatedCount; // do not count releases
float present = allCount - absentCount; float present = allCount - absentCount;
attendancePercentage = present / allCount * 100.0f; attendancePercentage = present / allCount * 100.0f;

View File

@ -138,7 +138,7 @@ class CrashActivity : AppCompatActivity(), CoroutineScope {
content = content.replace("\n".toRegex(), "<br>") content = content.replace("\n".toRegex(), "<br>")
contentPlain += "\n" + Build.MANUFACTURER + "\n" + Build.BRAND + "\n" + Build.MODEL + "\n" + Build.DEVICE + "\n" contentPlain += "\n" + Build.MANUFACTURER + "\n" + Build.BRAND + "\n" + Build.MODEL + "\n" + Build.DEVICE + "\n"
if (app.profile != null && app.profile.registration == Profile.REGISTRATION_ENABLED) { 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 contentPlain += BuildConfig.VERSION_NAME + " " + BuildConfig.BUILD_TYPE
return if (plain) contentPlain else content return if (plain) contentPlain else content

View File

@ -18,7 +18,7 @@ import com.mikepenz.iconics.utils.colorRes
import com.mikepenz.iconics.utils.sizeDp import com.mikepenz.iconics.utils.sizeDp
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.R 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.Notice
import pl.szczodrzynski.edziennik.data.db.modules.notices.NoticeFull import pl.szczodrzynski.edziennik.data.db.modules.notices.NoticeFull
import pl.szczodrzynski.edziennik.utils.Utils.bs import pl.szczodrzynski.edziennik.utils.Utils.bs

View File

@ -71,7 +71,7 @@ public class GradesFragment extends Fragment {
private boolean sortModeChanged = false; private boolean sortModeChanged = false;
private String getRegisterCardAverageModeSubText() { private String getRegisterCardAverageModeSubText() {
switch (app.profile.getYearAverageMode()) { switch (App.getConfig().forProfile().getGrades().getYearAverageMode()) {
default: default:
case YEAR_1_AVG_2_AVG: case YEAR_1_AVG_2_AVG:
return getString(R.string.settings_register_avg_mode_0_short); 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)) .title(getString(R.string.settings_register_avg_mode_dialog_title))
.content(getString(R.string.settings_register_avg_mode_dialog_text)) .content(getString(R.string.settings_register_avg_mode_dialog_text))
.items(modeNames) .items(modeNames)
.itemsCallbackSingleChoice(modeIds.indexOf(app.profile.getYearAverageMode()), (dialog, itemView, which, text) -> { .itemsCallbackSingleChoice(modeIds.indexOf(App.getConfig().forProfile().getGrades().getYearAverageMode()), (dialog, itemView, which, text) -> {
app.profile.setYearAverageMode(modeIds.get(which)); App.getConfig().forProfile().getGrades().setYearAverageMode(modeIds.get(which));
app.profileSaveAsync();
activity.reloadTarget(); activity.reloadTarget();
return true; return true;
}) })
@ -253,11 +252,16 @@ public class GradesFragment extends Fragment {
for (GradeFull grade: grades) { for (GradeFull grade: grades) {
ItemGradesSubjectModel model = ItemGradesSubjectModel.searchModelBySubjectId(subjectList, grade.subjectId); ItemGradesSubjectModel model = ItemGradesSubjectModel.searchModelBySubjectId(subjectList, grade.subjectId);
if (model == null) { 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); subjectList.add(model);
if (model.subject != null && model.subject.id == finalExpandSubjectId) { if (model.subject != null && model.subject.id == finalExpandSubjectId) {
model.expandView = true; model.expandView = true;
} }
model.colorMode = App.getConfig().forProfile().getGrades().getColorMode();
model.yearAverageMode = App.getConfig().forProfile().getGrades().getYearAverageMode();
} }
if (!grade.seen && grade.semester == 1) { if (!grade.seen && grade.semester == 1) {
model.semester1Unread++; model.semester1Unread++;
@ -376,7 +380,7 @@ public class GradesFragment extends Fragment {
else if (!model.isBehaviourSubject && model.isNormalSubject) { else if (!model.isBehaviourSubject && model.isNormalSubject) {
// applies for normal grades & normal+descriptive grades // applies for normal grades & normal+descriptive grades
// calculate the normal grade average based on the user's setting // 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: case YEAR_1_AVG_2_AVG:
model.yearAverage = (model.semester1Average + model.semester2Average) / 2; model.yearAverage = (model.semester1Average + model.semester2Average) / 2;
break; break;

View File

@ -56,7 +56,7 @@ public class GradesListAdapter extends RecyclerView.Adapter<GradesListAdapter.Vi
})); }));
int gradeColor; int gradeColor;
if (app.profile.getGradeColorMode() == COLOR_MODE_DEFAULT) { if (App.getConfig().forProfile().getGrades().getColorMode() == COLOR_MODE_DEFAULT) {
gradeColor = grade.color; gradeColor = grade.color;
} }
else { else {

View File

@ -491,7 +491,7 @@ public class GradesSubjectAdapter extends ArrayAdapter<ItemGradesSubjectModel> i
continue; continue;
int gradeColor; int gradeColor;
if (model.profile.getGradeColorMode() == COLOR_MODE_DEFAULT) { if (model.colorMode == COLOR_MODE_DEFAULT) {
gradeColor = grade.color; gradeColor = grade.color;
} else { } else {
gradeColor = Colors.gradeToColor(grade); gradeColor = Colors.gradeToColor(grade);
@ -581,13 +581,13 @@ public class GradesSubjectAdapter extends ArrayAdapter<ItemGradesSubjectModel> i
} }
arguments.putInt("semester", 1); arguments.putInt("semester", 1);
//d(TAG, "Model is " + model); //d(TAG, "Model is " + model);
switch (model.profile.getYearAverageMode()) { switch (model.yearAverageMode) {
case YEAR_1_SEM_2_AVG: case YEAR_1_SEM_2_AVG:
case YEAR_1_SEM_2_SEM: case YEAR_1_SEM_2_SEM:
arguments.putInt("averageMode", -1); arguments.putInt("averageMode", -1);
break; break;
default: 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("yearAverageBefore", model.yearAverage);
arguments.putFloat("gradeSumOtherSemester", model.gradeSumSemester2); arguments.putFloat("gradeSumOtherSemester", model.gradeSumSemester2);
arguments.putFloat("gradeCountOtherSemester", model.gradeCountSemester2); arguments.putFloat("gradeCountOtherSemester", model.gradeCountSemester2);
@ -607,13 +607,13 @@ public class GradesSubjectAdapter extends ArrayAdapter<ItemGradesSubjectModel> i
} }
arguments.putInt("semester", 2); arguments.putInt("semester", 2);
//d(TAG, "Model is " + model); //d(TAG, "Model is " + model);
switch (model.profile.getYearAverageMode()) { switch (model.yearAverageMode) {
case YEAR_1_AVG_2_SEM: case YEAR_1_AVG_2_SEM:
case YEAR_1_SEM_2_SEM: case YEAR_1_SEM_2_SEM:
arguments.putInt("averageMode", -1); arguments.putInt("averageMode", -1);
break; break;
default: 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("yearAverageBefore", model.yearAverage);
arguments.putFloat("gradeSumOtherSemester", model.gradeSumSemester1); arguments.putFloat("gradeSumOtherSemester", model.gradeSumSemester1);
arguments.putFloat("gradeCountOtherSemester", model.gradeCountSemester1); arguments.putFloat("gradeCountOtherSemester", model.gradeCountSemester1);

View File

@ -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.lessons.LessonFull;
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile; import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile;
import pl.szczodrzynski.edziennik.data.db.modules.subjects.Subject; 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.CardUpdateBinding;
import pl.szczodrzynski.edziennik.databinding.FragmentHomeOldBinding; import pl.szczodrzynski.edziennik.databinding.FragmentHomeOldBinding;
import pl.szczodrzynski.edziennik.receivers.BootReceiver; 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 = new HomeTimetableCardOld(app, activity, this, layoutInflater, insertPoint);
timetableCard.run(); timetableCard.run();
@ -498,7 +479,7 @@ public class HomeFragmentOld extends Fragment {
if (ellipsized) if (ellipsized)
continue; continue;
int gradeColor; int gradeColor;
if (app.profile.getGradeColorMode() == Profile.COLOR_MODE_DEFAULT) { if (App.getConfig().forProfile().getGrades().getColorMode() == Profile.COLOR_MODE_DEFAULT) {
gradeColor = grade.color; gradeColor = grade.color;
} }
else { else {

View File

@ -121,7 +121,7 @@ class HomeGradesCard(
16 /*ellipsize width*/)) / 1.5f 16 /*ellipsize width*/)) / 1.5f
subject.grades1.onEach { grade -> subject.grades1.onEach { grade ->
val gradeColor = when (app.profile.gradeColorMode) { val gradeColor = when (App.getConfig().forProfile().grades.colorMode) {
Profile.COLOR_MODE_DEFAULT -> grade.color Profile.COLOR_MODE_DEFAULT -> grade.color
else -> Colors.gradeToColor(grade) else -> Colors.gradeToColor(grade)
} }

View File

@ -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<LoginProfileObject> 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();
}));*/
}
}

View File

@ -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<LoginSummaryProfileAdapter.Item>()
val loginStores = mutableListOf<LoginStore>()
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 }
}

View File

@ -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));
}));
}
}

View File

@ -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)) }
}
}

View File

@ -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 package pl.szczodrzynski.edziennik.ui.modules.login
@ -9,89 +9,85 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.NavController
import androidx.navigation.Navigation
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.launch import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.ERROR_LOGIN_EDUDZIENNIK_WEB_INVALID_LOGIN 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.databinding.FragmentLoginEdudziennikBinding
import pl.szczodrzynski.edziennik.startCoroutineTimer import java.util.*
import pl.szczodrzynski.edziennik.ui.modules.error.ErrorSnackbar
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
class LoginEdudziennikFragment : Fragment(), CoroutineScope { 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 override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main 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? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
activity?.also { activity -> activity = (getActivity() as LoginActivity?) ?: return null
nav = Navigation.findNavController(activity, R.id.nav_host_fragment) context ?: return null
errorSnackbar = (activity as LoginActivity).errorSnackbar app = activity.application as App
} b = FragmentLoginEdudziennikBinding.inflate(inflater)
b = FragmentLoginEdudziennikBinding.inflate(inflater, container, false)
return b.root return b.root
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { launch { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
startCoroutineTimer(delayMillis = 100) { activity.lastError?.let { error ->
val error = LoginActivity.error activity.lastError = null
startCoroutineTimer(delayMillis = 100) {
if (error != null) {
when (error.errorCode) { when (error.errorCode) {
ERROR_LOGIN_EDUDZIENNIK_WEB_INVALID_LOGIN -> ERROR_LOGIN_EDUDZIENNIK_WEB_INVALID_LOGIN ->
b.loginPasswordLayout.error = getString(R.string.login_error_incorrect_login_or_password) b.loginPasswordLayout.error = getString(R.string.login_error_incorrect_login_or_password)
} }
errorSnackbar.addError(error)
LoginActivity.error = null
} }
} }
b.backButton.setOnClickListener { nav.navigateUp() } b.backButton.onClick { nav.navigateUp() }
b.loginButton.setOnClickListener { login() }
}}
private fun login() { b.loginButton.onClick {
var errors = false var errors = false
b.loginEmailLayout.error = null b.loginEmailLayout.error = null
b.loginPasswordLayout.error = null b.loginPasswordLayout.error = null
val emailEditable = b.loginEmail.text val email = b.loginEmail.text?.toString()?.toLowerCase(Locale.ROOT) ?: ""
val passwordEditable = b.loginPassword.text val password = b.loginPassword.text?.toString() ?: ""
if (emailEditable.isNullOrBlank()) { if (email.isBlank()) {
b.loginEmailLayout.error = getString(R.string.login_error_no_email) b.loginEmailLayout.error = getString(R.string.login_error_no_email)
errors = true 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)
} }
} }

View File

@ -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();
}));
}
}

View File

@ -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()
}
}
}

View File

@ -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);
});
}
}

View File

@ -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)
}
}
}

View File

@ -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);
});
}
}

View File

@ -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)
}
}
}

View File

@ -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);
});
}
}

View File

@ -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)
}
}
}

View File

@ -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);
});
}
}

View File

@ -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)
}
}
}

View File

@ -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);
}
}

View File

@ -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)
}
}

View File

@ -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<ItemProfileModel> profileList = new ArrayList<>();
int index = 0;
for (LoginProfileObject profileObject: LoginActivity.profileObjects) {
int subIndex = 0;
for (Profile profile: profileObject.profileList) {
List<String> 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 <a href=\"http://szkolny.eu/privacy-policy\">przeczytanie Polityki prywatności</a> 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<ProfileListAdapter.ViewHolder> {
private List<ItemProfileModel> profileList;
public ProfileListAdapter(List<ItemProfileModel> 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;
}
}
}
}

View File

@ -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 <a href=\"http://szkolny.eu/privacy-policy\">przeczytanie Polityki prywatności</a> 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)
}
}
}

View File

@ -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<Item>,
val onSelectionChanged: ((item: Item) -> Unit)? = null
) : RecyclerView.Adapter<LoginSummaryProfileAdapter.ViewHolder>() {
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)
}

View File

@ -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);
}));
}
}

View File

@ -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)
}
}
}

View File

@ -1,20 +1,19 @@
package pl.szczodrzynski.edziennik.ui.modules.login package pl.szczodrzynski.edziennik.ui.modules.login
import android.os.AsyncTask
import android.os.Bundle import android.os.Bundle
import android.text.Html
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.Navigation 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.EventBus
import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode import org.greenrobot.eventbus.ThreadMode
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.events.ApiTaskAllFinishedEvent import pl.szczodrzynski.edziennik.data.api.events.ApiTaskAllFinishedEvent
import pl.szczodrzynski.edziennik.data.api.events.ApiTaskErrorEvent import pl.szczodrzynski.edziennik.data.api.events.ApiTaskErrorEvent
import pl.szczodrzynski.edziennik.data.api.events.ApiTaskProgressEvent 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.api.task.EdziennikTask
import pl.szczodrzynski.edziennik.data.db.modules.events.Event.* 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.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_DISABLED
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile.Companion.REGISTRATION_ENABLED 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 pl.szczodrzynski.edziennik.databinding.FragmentLoginSyncBinding
import kotlin.coroutines.CoroutineContext
import kotlin.math.roundToInt 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 app: App
private lateinit var activity: LoginActivity private lateinit var activity: LoginActivity
private lateinit var b: FragmentLoginSyncBinding private lateinit var b: FragmentLoginSyncBinding
private val nav: NavController by lazy { Navigation.findNavController(activity, R.id.nav_host_fragment) } 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? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
activity = (getActivity() as LoginActivity?) ?: return null activity = (getActivity() as LoginActivity?) ?: return null
if (context == null) context ?: return null
return null
app = activity.application as App app = activity.application as App
b = FragmentLoginSyncBinding.inflate(inflater) b = FragmentLoginSyncBinding.inflate(inflater)
return b.root 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) @Subscribe(threadMode = ThreadMode.MAIN)
fun onSyncStartedEvent(event: ApiTaskStartedEvent) { 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) @Subscribe(threadMode = ThreadMode.MAIN)
fun onSyncFinishedEvent(event: ApiTaskAllFinishedEvent) { fun onSyncFinishedEvent(event: ApiTaskAllFinishedEvent) {
nav.navigate(R.id.loginFinishFragment, null, LoginActivity.navOptions) nav.navigate(R.id.loginFinishFragment, finishArguments, LoginActivity.navOptions)
} }
@Subscribe(threadMode = ThreadMode.MAIN) @Subscribe(threadMode = ThreadMode.MAIN)
@ -63,93 +111,11 @@ class LoginSyncFragment : Fragment() {
b.loginSyncSubtitle2.text = event.progressText b.loginSyncSubtitle2.text = event.progressText
} }
@Subscribe(threadMode = ThreadMode.MAIN) @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
fun onSyncErrorEvent(event: ApiTaskErrorEvent) { fun onSyncErrorEvent(event: ApiTaskErrorEvent) {
LoginActivity.error = event.error EventBus.getDefault().removeStickyEvent(event)
nav.navigate(R.id.loginSyncErrorFragment, null, LoginActivity.navOptions) activity.error(event.error)
} nav.navigate(R.id.loginSyncErrorFragment, finishArguments, 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<Int>()
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()
} }
override fun onStart() { override fun onStart() {

Some files were not shown because too many files have changed in this diff Show More