[API] Implement basic profile archiving.

This commit is contained in:
Kuba Szczodrzyński 2020-08-25 10:46:50 +02:00
parent 33a8fa2a1e
commit 7c6dbca986
8 changed files with 148 additions and 7 deletions

View File

@ -299,6 +299,10 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
b.nightlyText.isVisible = true
b.nightlyText.text = "Nightly\n"+BuildConfig.VERSION_NAME.substringAfterLast(".")
}
else if (BuildConfig.VERSION_NAME.contains("daily")) {
b.nightlyText.isVisible = true
b.nightlyText.text = "Daily\n"+BuildConfig.VERSION_NAME.substringAfterLast(".")
}
else
b.nightlyText.isVisible = false
@ -399,7 +403,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
}
app.db.profileDao().all.observe(this, Observer { profiles ->
drawer.setProfileList(profiles.filter { it.id >= 0 }.toMutableList())
drawer.setProfileList(profiles.filter { it.id >= 0 && !it.archived }.toMutableList())
drawer.currentProfile = App.profileId
})

View File

@ -26,6 +26,7 @@ import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
import pl.szczodrzynski.edziennik.data.db.full.EventFull
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
import pl.szczodrzynski.edziennik.utils.Utils.d
import pl.szczodrzynski.edziennik.utils.models.Date
open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTask(profileId) {
companion object {
@ -72,10 +73,28 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
private var edziennikInterface: EdziennikInterface? = null
internal fun run(app: App, taskCallback: EdziennikCallback) {
if (profile?.archived == true) {
taskCallback.onError(ApiError(TAG, ERROR_PROFILE_ARCHIVED))
return
profile?.let { profile ->
if (profile.dateYearEnd.month > 6) {
profile.dateYearEnd.month = 6
profile.dateYearEnd.day = 30
}
if (profile.archived) {
d(TAG, "The profile $profileId is archived")
taskCallback.onError(ApiError(TAG, ERROR_PROFILE_ARCHIVED))
return
}
else if (Date.getToday() >= profile.dateYearEnd) {
d(TAG, "The profile $profileId's year ended on ${profile.dateYearEnd}, archiving")
ProfileArchiver(app, profile)
}
if (Date.getToday() < profile.dateSemester1Start) {
d(TAG, "The profile $profileId's school year has not started yet; aborting sync")
cancel()
taskCallback.onCompleted()
return
}
}
edziennikInterface = when (loginStore.type) {
LOGIN_TYPE_LIBRUS -> Librus(app, profile, loginStore, taskCallback)
LOGIN_TYPE_MOBIDZIENNIK -> Mobidziennik(app, profile, loginStore, taskCallback)

View File

@ -0,0 +1,88 @@
package pl.szczodrzynski.edziennik.data.api.edziennik
import android.content.Intent
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.Intent
import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.utils.Utils.d
import pl.szczodrzynski.edziennik.utils.models.Date
class ProfileArchiver(val app: App, val profile: Profile) {
companion object {
private const val TAG = "ProfileArchiver"
}
init {
if (profile.archiveId == null)
profile.archiveId = profile.id
d(TAG, "Processing ${profile.name}#${profile.id}, archiveId = ${profile.archiveId}")
profile.archived = true
app.db.profileDao().add(profile)
//app.db.metadataDao().setAllSeen(profile.id, true)
app.db.notificationDao().clear(profile.id)
app.db.endpointTimerDao().clear(profile.id)
d(TAG, "Archived profile ${profile.id} saved")
profile.archived = false
// guess the nearest school year
val today = Date.getToday()
profile.studentSchoolYearStart = when {
today.month <= profile.dateYearEnd.month -> today.year - 1
else -> today.year
}
// set default semester dates
profile.dateSemester1Start = Date(profile.studentSchoolYearStart, 9, 1)
profile.dateSemester2Start = Date(profile.studentSchoolYearStart + 1, 2, 1)
profile.dateYearEnd = Date(profile.studentSchoolYearStart + 1, 6, 30)
val oldId = profile.id
val newId = (app.db.profileDao().lastId ?: profile.id) + 1
profile.id = newId
profile.subname = "Nowy rok szkolny - ${profile.studentSchoolYearStart}"
profile.studentClassName = null
d(TAG, "New profile ID for ${profile.name}: ${profile.id}")
when (profile.loginStoreType) {
LOGIN_TYPE_LIBRUS -> {
profile.removeStudentData("isPremium")
profile.removeStudentData("pushDeviceId")
profile.removeStudentData("startPointsSemester1")
profile.removeStudentData("startPointsSemester2")
profile.removeStudentData("enablePointGrades")
profile.removeStudentData("enableDescriptiveGrades")
}
LOGIN_TYPE_MOBIDZIENNIK -> {
}
LOGIN_TYPE_VULCAN -> {
// DataVulcan.isApiLoginValid() returns false so it will update the semester
profile.removeStudentData("currentSemesterEndDate")
}
LOGIN_TYPE_IDZIENNIK -> {
profile.removeStudentData("schoolYearId")
}
LOGIN_TYPE_EDUDZIENNIK -> {
}
LOGIN_TYPE_PODLASIE -> {
}
}
d(TAG, "Processed student data: ${profile.studentData}")
app.db.profileDao().add(profile)
if (app.profileId == oldId) {
val intent = Intent(
Intent.ACTION_MAIN,
"profileId" to newId
)
app.sendBroadcast(intent)
}
}
}

View File

@ -43,7 +43,7 @@ import pl.szczodrzynski.edziennik.data.db.migration.*
LibrusLesson::class,
TimetableManual::class,
Metadata::class
], version = 88)
], version = 89)
@TypeConverters(
ConverterTime::class,
ConverterDate::class,
@ -173,7 +173,8 @@ abstract class AppDb : RoomDatabase() {
Migration85(),
Migration86(),
Migration87(),
Migration88()
Migration88(),
Migration89()
).allowMainThreadQueries().build()
}
}

View File

@ -28,7 +28,7 @@ import pl.szczodrzynski.navlib.getDrawableFromRes
@Entity(tableName = "profiles", primaryKeys = ["profileId"])
open class Profile(
@ColumnInfo(name = "profileId")
override val id: Int,
override var id: Int, /* needs to be var for ProfileArchiver */
val loginStoreId: Int,
val loginStoreType: Int,
@ -64,6 +64,12 @@ open class Profile(
var empty = true
var archived = false
/**
* A unique ID matching [archived] profiles with current ones
* and vice-versa.
*/
var archiveId: Int? = null
var syncEnabled = true
var enableSharedEvents = true
var registration = REGISTRATION_UNSPECIFIED

View File

@ -0,0 +1,10 @@
package pl.szczodrzynski.edziennik.data.db.migration
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
class Migration89 : Migration(88, 89) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE profiles ADD COLUMN archiveId INTEGER DEFAULT NULL;")
}
}

View File

@ -62,6 +62,12 @@ class LabPageFragment : LazyFragment(), CoroutineScope {
app.db.eventDao().getRawNow("UPDATE events SET homeworkBody = NULL WHERE profileId = ${App.profileId}")
}
b.unarchive.onClick {
app.profile.archived = false
app.profile.archiveId = null
app.profileSave()
}
val colorSecondary = android.R.attr.textColorSecondary.resolveAttr(activity)
startCoroutineTimer(500L, 300L) {
val text = app.cookieJar.sessionCookies

View File

@ -61,6 +61,13 @@
android:layout_height="wrap_content"
android:fontFamily="monospace"
tools:text="Cookies:\n\nsynergia.librus.pl\n DZIENNIKSID=L01~1234567890abcdef"/>
<Button
android:id="@+id/unarchive"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Unarchive this profile"
android:textAllCaps="false" />
</LinearLayout>
</ScrollView>
</layout>