merge with latest Szkolny.eu changes (TODO)

This commit is contained in:
Franek 2024-06-13 10:55:14 +02:00
commit 4d9c9368dd
No known key found for this signature in database
GPG Key ID: 0329F871B2079351
359 changed files with 14132 additions and 4290 deletions

View File

@ -23,11 +23,11 @@ if __name__ == "__main__":
(title, changelog) = get_changelog(project_dir, format="plain") (title, changelog) = get_changelog(project_dir, format="plain")
# plain text changelog - Firebase App Distribution # plain text changelog - Firebase App Distribution
with open(dir + "whatsnew-titled.txt", "w", encoding="utf-8") as f: with open(dir + "whatsnew_titled.txt", "w", encoding="utf-8") as f:
f.write(title) f.write(title)
f.write("\n") f.write("\n")
f.write(changelog) f.write(changelog)
print("::set-output name=changelogPlainTitledFile::" + dir + "whatsnew-titled.txt") print("::set-output name=changelogPlainTitledFile::" + dir + "whatsnew_titled.txt")
print("::set-output name=changelogTitle::" + title) print("::set-output name=changelogTitle::" + title)

View File

@ -113,10 +113,11 @@ jobs:
with: with:
serviceAccountJsonPlainText: ${{ secrets.PLAY_SERVICE_ACCOUNT_JSON }} serviceAccountJsonPlainText: ${{ secrets.PLAY_SERVICE_ACCOUNT_JSON }}
packageName: pl.szczodrzynski.edziennik packageName: pl.szczodrzynski.edziennik
releaseFile: ${{ needs.sign.outputs.signedReleaseFile }} releaseFiles: ${{ needs.sign.outputs.signedReleaseFile }}
releaseName: ${{ steps.changelog.outputs.appVersionName }} releaseName: ${{ steps.changelog.outputs.appVersionName }}
track: ${{ secrets.PLAY_RELEASE_TRACK }} track: ${{ secrets.PLAY_RELEASE_TRACK }}
whatsNewDirectory: ${{ steps.changelog.outputs.changelogDir }} whatsNewDirectory: ${{ steps.changelog.outputs.changelogDir }}
status: completed
- name: Upload workflow artifact - name: Upload workflow artifact
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v2

View File

@ -1,9 +1,17 @@
<component name="ProjectCodeStyleConfiguration"> <component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173"> <code_scheme name="Project" version="173">
<JetCodeStyleSettings> <JetCodeStyleSettings>
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
<option name="ALLOW_TRAILING_COMMA" value="true" /> <option name="ALLOW_TRAILING_COMMA" value="true" />
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings> </JetCodeStyleSettings>
<codeStyleSettings language="JSON">
<indentOptions>
<option name="INDENT_SIZE" value="4" />
<option name="USE_TAB_CHARACTER" value="true" />
<option name="SMART_TABS" value="true" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="XML"> <codeStyleSettings language="XML">
<option name="FORCE_REARRANGE_MODE" value="1" /> <option name="FORCE_REARRANGE_MODE" value="1" />
<indentOptions> <indentOptions>

View File

@ -5,6 +5,7 @@
<w>ciasteczko</w> <w>ciasteczko</w>
<w>csrf</w> <w>csrf</w>
<w>edziennik</w> <w>edziennik</w>
<w>eggfall</w>
<w>elearning</w> <w>elearning</w>
<w>gson</w> <w>gson</w>
<w>hebe</w> <w>hebe</w>
@ -13,6 +14,7 @@
<w>synergia</w> <w>synergia</w>
<w>szczodrzyński</w> <w>szczodrzyński</w>
<w>szkolny</w> <w>szkolny</w>
<w>usos</w>
</words> </words>
</dictionary> </dictionary>
</component> </component>

View File

@ -148,28 +148,29 @@ dependencies {
// Language cores // Language cores
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "androidx.multidex:multidex:2.0.1" implementation "androidx.multidex:multidex:2.0.1"
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5" coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:2.0.4"
// Android Jetpack // Android Jetpack
implementation "androidx.appcompat:appcompat:1.5.1" implementation "androidx.appcompat:appcompat:1.7.0"
implementation "androidx.cardview:cardview:1.0.0" implementation "androidx.cardview:cardview:1.0.0"
implementation "androidx.constraintlayout:constraintlayout:2.1.4" implementation "androidx.constraintlayout:constraintlayout:2.1.4"
implementation "androidx.core:core-ktx:1.9.0" implementation "androidx.core:core-ktx:1.13.1"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.5.1" implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.8.2"
implementation "androidx.navigation:navigation-fragment-ktx:2.5.2" implementation "androidx.navigation:navigation-fragment-ktx:2.7.7"
implementation "androidx.recyclerview:recyclerview:1.2.1" implementation "androidx.recyclerview:recyclerview:1.3.2"
implementation "androidx.room:room-runtime:2.4.3" implementation "androidx.room:room-runtime:2.6.1"
implementation "androidx.work:work-runtime-ktx:2.7.1" implementation "androidx.room:room-ktx:2.6.1"
kapt "androidx.room:room-compiler:2.4.3" implementation "androidx.work:work-runtime-ktx:2.9.0"
kapt "androidx.room:room-compiler:2.6.1"
// Google design libs // Google design libs
implementation "com.google.android.material:material:1.11.0-beta01" implementation "com.google.android.material:material:1.12.0"
implementation "com.google.android.flexbox:flexbox:3.0.0" implementation "com.google.android.flexbox:flexbox:3.0.0"
// Play Services/Firebase // Play Services/Firebase
implementation "com.google.android.gms:play-services-wearable:17.1.0" implementation "com.google.android.gms:play-services-wearable:18.2.0"
implementation("com.google.firebase:firebase-core") { version { strictly "19.0.2" } } implementation("com.google.firebase:firebase-core") { version { strictly "19.0.2" } }
implementation "com.google.firebase:firebase-crashlytics:18.2.13" implementation "com.google.firebase:firebase-crashlytics:19.0.1"
implementation("com.google.firebase:firebase-messaging") { version { strictly "20.1.3" } } implementation("com.google.firebase:firebase-messaging") { version { strictly "20.1.3" } }
// OkHttp, Retrofit, Gson, Jsoup // OkHttp, Retrofit, Gson, Jsoup
@ -177,7 +178,7 @@ dependencies {
implementation "com.squareup.retrofit2:retrofit:2.9.0" implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.retrofit2:converter-gson:2.9.0" implementation "com.squareup.retrofit2:converter-gson:2.9.0"
implementation "com.squareup.retrofit2:converter-scalars:2.9.0" implementation "com.squareup.retrofit2:converter-scalars:2.9.0"
implementation 'com.google.code.gson:gson:2.8.8' implementation 'com.google.code.gson:gson:2.10.1'
implementation 'org.jsoup:jsoup:1.14.3' implementation 'org.jsoup:jsoup:1.14.3'
implementation "pl.droidsonroids:jspoon:1.3.2" implementation "pl.droidsonroids:jspoon:1.3.2"
implementation "pl.droidsonroids.retrofit2:converter-jspoon:1.3.2" implementation "pl.droidsonroids.retrofit2:converter-jspoon:1.3.2"
@ -255,5 +256,5 @@ dependencies {
debugImplementation 'net.yslibrary.licenseadapter:licenseadapter:3.0.0' debugImplementation 'net.yslibrary.licenseadapter:licenseadapter:3.0.0'
testImplementation 'junit:junit:4.13' testImplementation 'junit:junit:4.13.2'
} }

View File

@ -22,6 +22,7 @@
-keep class android.support.v7.widget.** { *; } -keep class android.support.v7.widget.** { *; }
-keep class pl.szczodrzynski.edziennik.utils.models.** { *; } -keep class pl.szczodrzynski.edziennik.utils.models.** { *; }
-keep class pl.szczodrzynski.edziennik.data.db.enums.* { *; }
-keep class pl.szczodrzynski.edziennik.data.db.entity.Event { *; } -keep class pl.szczodrzynski.edziennik.data.db.entity.Event { *; }
-keep class pl.szczodrzynski.edziennik.data.db.full.EventFull { *; } -keep class pl.szczodrzynski.edziennik.data.db.full.EventFull { *; }
-keep class pl.szczodrzynski.edziennik.data.db.entity.FeedbackMessage { *; } -keep class pl.szczodrzynski.edziennik.data.db.entity.FeedbackMessage { *; }
@ -31,6 +32,9 @@
-keepnames class pl.szczodrzynski.edziennik.ui.widgets.timetable.WidgetTimetableProvider -keepnames class pl.szczodrzynski.edziennik.ui.widgets.timetable.WidgetTimetableProvider
-keepnames class pl.szczodrzynski.edziennik.ui.widgets.notifications.WidgetNotificationsProvider -keepnames class pl.szczodrzynski.edziennik.ui.widgets.notifications.WidgetNotificationsProvider
-keepnames class pl.szczodrzynski.edziennik.ui.widgets.luckynumber.WidgetLuckyNumberProvider -keepnames class pl.szczodrzynski.edziennik.ui.widgets.luckynumber.WidgetLuckyNumberProvider
-keep class pl.szczodrzynski.edziennik.config.AppData { *; }
-keep class pl.szczodrzynski.edziennik.config.AppData$** { *; }
-keep class pl.szczodrzynski.edziennik.utils.managers.TextStylingManager$HtmlMode { *; }
-keepnames class androidx.appcompat.view.menu.MenuBuilder { setHeaderTitleInt(java.lang.CharSequence); } -keepnames class androidx.appcompat.view.menu.MenuBuilder { setHeaderTitleInt(java.lang.CharSequence); }
-keepnames class androidx.appcompat.view.menu.MenuPopupHelper { showPopup(int, int, boolean, boolean); } -keepnames class androidx.appcompat.view.menu.MenuPopupHelper { showPopup(int, int, boolean, boolean); }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,6 @@
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<!-- PowerPermission uses minSdk 21, it's safe to override as it is used only in >= 23 --> <!-- PowerPermission uses minSdk 21, it's safe to override as it is used only in >= 23 -->
<uses-sdk tools:overrideLibrary="com.qifan.powerpermission.coroutines, com.qifan.powerpermission.core, com.mikepenz:materialdrawer, com.mikepenz.iconics.typeface.library.navlibfont" /> <uses-sdk tools:overrideLibrary="com.qifan.powerpermission.coroutines, com.qifan.powerpermission.core, com.mikepenz:materialdrawer, com.mikepenz.iconics.typeface.library.navlibfont" />
@ -159,6 +158,14 @@
android:configChanges="orientation|keyboardHidden" android:configChanges="orientation|keyboardHidden"
android:exported="false" android:exported="false"
android:theme="@style/Base.Theme.AppCompat" /> android:theme="@style/Base.Theme.AppCompat" />
<activity android:name=".ui.login.oauth.OAuthLoginActivity"
android:configChanges="orientation|keyboardHidden"
android:exported="false"
android:theme="@style/Theme.MaterialComponents.Light.DarkActionBar" />
<activity android:name=".ui.login.recaptcha.RecaptchaActivity"
android:configChanges="orientation|keyboardHidden"
android:exported="false"
android:theme="@style/Theme.MaterialComponents.Light.DarkActionBar" />
<activity android:name=".ui.base.BuildInvalidActivity" android:exported="false" /> <activity android:name=".ui.base.BuildInvalidActivity" android:exported="false" />
<activity android:name=".ui.settings.contributors.ContributorsActivity" android:exported="false" /> <activity android:name=".ui.settings.contributors.ContributorsActivity" android:exported="false" />

View File

@ -1,12 +1,10 @@
<h3>Wersja 4.12.1, 2022-09-23</h3> <h3>Wersja 4.13.6, 2023-03-24</h3>
<ul> <ul>
<li>Vulcan UONET+: naprawiono działanie systemu wiadomości. @Antoni-Czaplicki</li> <li>Naprawiono pobieranie załączników na Androidzie 13 i nowszym.</li>
<li>Vulcan UONET+: naprawiono błędy wersji 4.11.9 i starszych.</li> <li>Dodano opcję odświeżenia planu lekcji na wybrany tydzień.</li>
<li>Poprawiono wyświetlanie lekcji odwołanych na stronie głównej.</li> <li>Usunięto błędy logowania. @BxOxSxS</li>
<li>Dodano dostęp do Laboratorium na ekranie logowania.</li>
<li>Usunięto obsługę dziennika EduDziennik. [*]</li>
</ul> </ul>
<br> <br>
<br> <br>
Dzięki za korzystanie ze Szkolnego!<br> Dzięki za korzystanie ze Szkolnego!<br>
<i>&copy; [Kuba Szczodrzyński](@kuba2k2), [Kacper Ziubryniewicz](@kapi2289) 2022</i> <i>&copy; [Kuba Szczodrzyński](@kuba2k2) 2023</i>

View File

@ -9,7 +9,7 @@
/*secret password - removed for source code publication*/ /*secret password - removed for source code publication*/
static toys AES_IV[16] = { static toys AES_IV[16] = {
0xdf, 0xe4, 0x2d, 0xa3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 0x6d, 0xa5, 0x32, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
unsigned char *agony(unsigned int laugh, unsigned char *box, unsigned char *heat); unsigned char *agony(unsigned int laugh, unsigned char *box, unsigned char *heat);

View File

@ -12,6 +12,7 @@ import android.graphics.drawable.Icon
import android.os.Build import android.os.Build
import android.provider.Settings import android.provider.Settings
import android.util.Log import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import androidx.multidex.MultiDexApplication import androidx.multidex.MultiDexApplication
import androidx.work.Configuration import androidx.work.Configuration
@ -27,36 +28,65 @@ import com.google.gson.Gson
import com.hypertrack.hyperlog.HyperLog import com.hypertrack.hyperlog.HyperLog
import com.mikepenz.iconics.Iconics import com.mikepenz.iconics.Iconics
import im.wangchao.mhttp.MHttp import im.wangchao.mhttp.MHttp
import kotlinx.coroutines.* import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import me.leolin.shortcutbadger.ShortcutBadger import me.leolin.shortcutbadger.ShortcutBadger
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
import pl.szczodrzynski.edziennik.config.AppData
import pl.szczodrzynski.edziennik.config.Config import pl.szczodrzynski.edziennik.config.Config
import pl.szczodrzynski.edziennik.data.api.events.ProfileListEmptyEvent import pl.szczodrzynski.edziennik.data.api.events.ProfileListEmptyEvent
import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.Signing import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.Signing
import pl.szczodrzynski.edziennik.data.db.AppDb import pl.szczodrzynski.edziennik.data.db.AppDb
import pl.szczodrzynski.edziennik.data.db.entity.Profile import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.db.enums.LoginType
import pl.szczodrzynski.edziennik.ext.DAY import pl.szczodrzynski.edziennik.ext.DAY
import pl.szczodrzynski.edziennik.ext.MS import pl.szczodrzynski.edziennik.ext.MS
import pl.szczodrzynski.edziennik.ext.putExtras
import pl.szczodrzynski.edziennik.ext.setLanguage import pl.szczodrzynski.edziennik.ext.setLanguage
import pl.szczodrzynski.edziennik.network.SSLProviderInstaller import pl.szczodrzynski.edziennik.network.SSLProviderInstaller
import pl.szczodrzynski.edziennik.network.cookie.DumbCookieJar import pl.szczodrzynski.edziennik.network.cookie.DumbCookieJar
import pl.szczodrzynski.edziennik.sync.SyncWorker import pl.szczodrzynski.edziennik.sync.SyncWorker
import pl.szczodrzynski.edziennik.sync.UpdateWorker import pl.szczodrzynski.edziennik.sync.UpdateWorker
import pl.szczodrzynski.edziennik.ui.base.CrashActivity import pl.szczodrzynski.edziennik.ui.base.CrashActivity
import pl.szczodrzynski.edziennik.utils.* import pl.szczodrzynski.edziennik.ui.base.enums.NavTarget
import pl.szczodrzynski.edziennik.utils.DebugLogFormat
import pl.szczodrzynski.edziennik.utils.PermissionChecker
import pl.szczodrzynski.edziennik.utils.Themes
import pl.szczodrzynski.edziennik.utils.Utils
import pl.szczodrzynski.edziennik.utils.Utils.d import pl.szczodrzynski.edziennik.utils.Utils.d
import pl.szczodrzynski.edziennik.utils.managers.* import pl.szczodrzynski.edziennik.utils.managers.AttendanceManager
import pl.szczodrzynski.edziennik.utils.managers.AvailabilityManager
import pl.szczodrzynski.edziennik.utils.managers.BuildManager
import pl.szczodrzynski.edziennik.utils.managers.EventManager
import pl.szczodrzynski.edziennik.utils.managers.GradesManager
import pl.szczodrzynski.edziennik.utils.managers.MessageManager
import pl.szczodrzynski.edziennik.utils.managers.NoteManager
import pl.szczodrzynski.edziennik.utils.managers.NotificationChannelsManager
import pl.szczodrzynski.edziennik.utils.managers.PermissionManager
import pl.szczodrzynski.edziennik.utils.managers.TextStylingManager
import pl.szczodrzynski.edziennik.utils.managers.TimetableManager
import pl.szczodrzynski.edziennik.utils.managers.UpdateManager
import pl.szczodrzynski.edziennik.utils.managers.UserActionManager
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.system.exitProcess
class App : MultiDexApplication(), Configuration.Provider, CoroutineScope { class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
companion object { companion object {
@Volatile @Volatile
lateinit var db: AppDb lateinit var db: AppDb
private set
lateinit var config: Config lateinit var config: Config
// private set // for LabFragment
lateinit var profile: Profile lateinit var profile: Profile
private set
lateinit var data: AppData
private set
val profileId val profileId
get() = profile.id get() = profile.id
@ -66,18 +96,19 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
} }
val api by lazy { SzkolnyApi(this) } val api by lazy { SzkolnyApi(this) }
val notificationChannelsManager by lazy { NotificationChannelsManager(this) }
val userActionManager by lazy { UserActionManager(this) }
val gradesManager by lazy { GradesManager(this) }
val timetableManager by lazy { TimetableManager(this) }
val eventManager by lazy { EventManager(this) }
val permissionManager by lazy { PermissionManager(this) }
val attendanceManager by lazy { AttendanceManager(this) } val attendanceManager by lazy { AttendanceManager(this) }
val buildManager by lazy { BuildManager(this) }
val availabilityManager by lazy { AvailabilityManager(this) } val availabilityManager by lazy { AvailabilityManager(this) }
val textStylingManager by lazy { TextStylingManager(this) } val buildManager by lazy { BuildManager(this) }
val eventManager by lazy { EventManager(this) }
val gradesManager by lazy { GradesManager(this) }
val messageManager by lazy { MessageManager(this) } val messageManager by lazy { MessageManager(this) }
val noteManager by lazy { NoteManager(this) } val noteManager by lazy { NoteManager(this) }
val notificationChannelsManager by lazy { NotificationChannelsManager(this) }
val permissionManager by lazy { PermissionManager(this) }
val textStylingManager by lazy { TextStylingManager(this) }
val timetableManager by lazy { TimetableManager(this) }
val updateManager by lazy { UpdateManager(this) }
val userActionManager by lazy { UserActionManager(this) }
val db val db
get() = App.db get() = App.db
@ -87,6 +118,8 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
get() = App.profile get() = App.profile
val profileId val profileId
get() = App.profileId get() = App.profileId
val data
get() = App.data
private val job = Job() private val job = Job()
override val coroutineContext: CoroutineContext override val coroutineContext: CoroutineContext
@ -121,9 +154,6 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
SSLProviderInstaller.enableSupportedTls(builder, enableCleartext = true) SSLProviderInstaller.enableSupportedTls(builder, enableCleartext = true)
if (devMode) { if (devMode) {
HyperLog.initialize(this)
HyperLog.setLogLevel(Log.VERBOSE)
HyperLog.setLogFormat(DebugLogFormat(this))
if (enableChucker) { if (enableChucker) {
val chuckerCollector = ChuckerCollector(this, true, RetentionManager.Period.ONE_HOUR) val chuckerCollector = ChuckerCollector(this, true, RetentionManager.Period.ONE_HOUR)
val chuckerInterceptor = ChuckerInterceptor(this, chuckerCollector) val chuckerInterceptor = ChuckerInterceptor(this, chuckerCollector)
@ -178,15 +208,23 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
Iconics.respectFontBoundsDefault = true Iconics.respectFontBoundsDefault = true
// initialize companion object values // initialize companion object values
AppData.read(this)
App.db = AppDb(this) App.db = AppDb(this)
App.config = Config(App.db) App.config = Config(App.db)
App.profile = Profile(0, 0, 0, "")
debugMode = BuildConfig.DEBUG debugMode = BuildConfig.DEBUG
devMode = config.devMode ?: debugMode devMode = config.devMode ?: debugMode
enableChucker = config.enableChucker ?: devMode enableChucker = config.enableChucker ?: devMode
if (devMode) {
HyperLog.initialize(this)
HyperLog.setLogLevel(Log.VERBOSE)
HyperLog.setLogFormat(DebugLogFormat(this))
}
if (!profileLoadById(config.lastProfileId)) { if (!profileLoadById(config.lastProfileId)) {
db.profileDao().firstId?.let { profileLoadById(it) } val success = db.profileDao().firstId?.let { profileLoadById(it) }
if (success != true)
profileLoad(Profile(0, 0, LoginType.TEMPLATE, ""))
} }
buildHttp() buildHttp()
@ -197,6 +235,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
} }
Signing.getCert(this) Signing.getCert(this)
Utils.initializeStorageDir(this)
launch { launch {
withContext(Dispatchers.Default) { withContext(Dispatchers.Default) {
@ -224,35 +263,35 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
.setShortLabel(getString(R.string.shortcut_timetable)).setLongLabel(getString(R.string.shortcut_timetable)) .setShortLabel(getString(R.string.shortcut_timetable)).setLongLabel(getString(R.string.shortcut_timetable))
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_timetable)) .setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_timetable))
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java) .setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_TIMETABLE)) .putExtras("fragmentId" to NavTarget.TIMETABLE))
.build() .build()
val shortcutAgenda = ShortcutInfo.Builder(this@App, "item_agenda") val shortcutAgenda = ShortcutInfo.Builder(this@App, "item_agenda")
.setShortLabel(getString(R.string.shortcut_agenda)).setLongLabel(getString(R.string.shortcut_agenda)) .setShortLabel(getString(R.string.shortcut_agenda)).setLongLabel(getString(R.string.shortcut_agenda))
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_agenda)) .setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_agenda))
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java) .setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_AGENDA)) .putExtras("fragmentId" to NavTarget.AGENDA))
.build() .build()
val shortcutGrades = ShortcutInfo.Builder(this@App, "item_grades") val shortcutGrades = ShortcutInfo.Builder(this@App, "item_grades")
.setShortLabel(getString(R.string.shortcut_grades)).setLongLabel(getString(R.string.shortcut_grades)) .setShortLabel(getString(R.string.shortcut_grades)).setLongLabel(getString(R.string.shortcut_grades))
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_grades)) .setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_grades))
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java) .setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_GRADES)) .putExtras("fragmentId" to NavTarget.GRADES))
.build() .build()
val shortcutHomework = ShortcutInfo.Builder(this@App, "item_homeworks") val shortcutHomework = ShortcutInfo.Builder(this@App, "item_homeworks")
.setShortLabel(getString(R.string.shortcut_homework)).setLongLabel(getString(R.string.shortcut_homework)) .setShortLabel(getString(R.string.shortcut_homework)).setLongLabel(getString(R.string.shortcut_homework))
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_homework)) .setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_homework))
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java) .setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_HOMEWORK)) .putExtras("fragmentId" to NavTarget.HOMEWORK))
.build() .build()
val shortcutMessages = ShortcutInfo.Builder(this@App, "item_messages") val shortcutMessages = ShortcutInfo.Builder(this@App, "item_messages")
.setShortLabel(getString(R.string.shortcut_messages)).setLongLabel(getString(R.string.shortcut_messages)) .setShortLabel(getString(R.string.shortcut_messages)).setLongLabel(getString(R.string.shortcut_messages))
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_messages)) .setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_messages))
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java) .setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_MESSAGES)) .putExtras("fragmentId" to NavTarget.MESSAGES))
.build() .build()
shortcutManager.dynamicShortcuts = listOf( shortcutManager.dynamicShortcuts = listOf(
@ -378,10 +417,28 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
} }
} }
fun profileLoad(profile: Profile) {
App.profile = profile
App.config.lastProfileId = profile.id
try {
App.data = AppData.get(profile.loginStoreType)
d("App", "Loaded AppData: ${App.data}")
// apply newly-added config overrides, if not changed by the user yet
for ((key, value) in App.data.configOverrides) {
val config = App.profile.config
if (!config.has(key))
config.set(key, value)
}
} catch (e: Exception) {
Log.e("App", "Cannot load AppData", e)
Toast.makeText(this, R.string.app_cannot_load_data, Toast.LENGTH_LONG).show()
exitProcess(0)
}
}
private fun profileLoadById(profileId: Int): Boolean { private fun profileLoadById(profileId: Int): Boolean {
db.profileDao().getByIdNow(profileId)?.also { db.profileDao().getByIdNow(profileId)?.also {
App.profile = it profileLoad(it)
App.config.lastProfileId = it.id
return true return true
} }
return false return false
@ -412,6 +469,8 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
} }
fun profileSave() = profileSave(profile) fun profileSave() = profileSave(profile)
fun profileSave(profile: Profile) { fun profileSave(profile: Profile) {
if (profile.id == profileId)
App.profile = profile
launch(Dispatchers.Default) { launch(Dispatchers.Default) {
App.db.profileDao().add(profile) App.db.profileDao().add(profile)
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +0,0 @@
/*
* Copyright (c) Kuba Szczodrzyński 2019-11-27.
*/
package pl.szczodrzynski.edziennik.config
interface AbstractConfig {
fun set(key: String, value: String?)
}

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) Kuba Szczodrzyński 2022-10-21.
*/
package pl.szczodrzynski.edziennik.config
import com.google.gson.Gson
import com.google.gson.JsonObject
import com.google.gson.JsonParser
import com.google.gson.stream.JsonReader
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.db.enums.LoginType
import pl.szczodrzynski.edziennik.ext.getJsonObject
import pl.szczodrzynski.edziennik.ext.mergeWith
import pl.szczodrzynski.edziennik.utils.managers.TextStylingManager.HtmlMode
data class AppData(
val configOverrides: Map<String, String>,
val messagesConfig: MessagesConfig,
val uiConfig: UIConfig,
val eventTypes: List<EventType>,
) {
companion object {
private var data: JsonObject? = null
private val appData = mutableMapOf<LoginType, AppData>()
fun read(app: App) {
val res = app.resources.openRawResource(R.raw.app_data)
data = JsonParser.parseReader(JsonReader(res.reader())).asJsonObject
}
fun get(loginType: LoginType): AppData {
if (loginType in appData)
return appData.getValue(loginType)
val json = data?.getJsonObject("base")?.deepCopy()
?: throw NoSuchElementException("Base data not found")
val overrides = setOf(loginType, loginType.schoolType)
for (overrideType in overrides) {
val override = data?.getJsonObject(overrideType.name.lowercase()) ?: continue
json.mergeWith(override)
}
val value = Gson().fromJson(json, AppData::class.java)
appData[loginType] = value
return value
}
}
data class MessagesConfig(
val subjectLength: Int?,
val bodyLength: Int?,
val textStyling: Boolean,
val syncRecipientList: Boolean,
val htmlMode: HtmlMode,
val needsReadStatus: Boolean,
)
data class UIConfig(
val lessonHeight: Int,
val enableMarkAsReadAnnouncements: Boolean,
val enableNoticePoints: Boolean,
val eventManualShowSubjectDropdown: Boolean,
)
data class EventType(
val id: Long,
val color: String,
val name: String,
)
}

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) Kuba Szczodrzyński 2019-11-27.
*/
package pl.szczodrzynski.edziennik.config
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import pl.szczodrzynski.edziennik.config.db.ConfigEntry
import pl.szczodrzynski.edziennik.data.db.AppDb
import pl.szczodrzynski.edziennik.ext.takePositive
import kotlin.coroutines.CoroutineContext
abstract class BaseConfig(
@Transient
val db: AppDb,
val profileId: Int? = null,
protected var entries: List<ConfigEntry>? = null,
) : CoroutineScope {
private val job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Default
val values = hashMapOf<String, String?>()
init {
if (entries == null)
entries = db.configDao().getAllNow()
values.clear()
for ((profileId, key, value) in entries!!) {
if (profileId.takePositive() != this.profileId)
continue
values[key] = value
}
}
fun set(key: String, value: String?) {
values[key] = value
launch(Dispatchers.IO) {
db.configDao().add(ConfigEntry(profileId ?: -1, key, value))
}
}
fun has(key: String) = values.containsKey(key)
}

View File

@ -5,151 +5,59 @@
package pl.szczodrzynski.edziennik.config package pl.szczodrzynski.edziennik.config
import com.google.gson.JsonObject import com.google.gson.JsonObject
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.App
import pl.szczodrzynski.edziennik.BuildConfig import pl.szczodrzynski.edziennik.BuildConfig
import pl.szczodrzynski.edziennik.config.db.ConfigEntry
import pl.szczodrzynski.edziennik.config.utils.* import pl.szczodrzynski.edziennik.config.utils.*
import pl.szczodrzynski.edziennik.data.api.szkolny.response.Update import pl.szczodrzynski.edziennik.data.api.szkolny.response.Update
import pl.szczodrzynski.edziennik.data.db.AppDb import pl.szczodrzynski.edziennik.data.db.AppDb
import kotlin.coroutines.CoroutineContext
class Config(val db: AppDb) : CoroutineScope, AbstractConfig { @Suppress("RemoveExplicitTypeArguments")
class Config(db: AppDb) : BaseConfig(db) {
companion object { companion object {
const val DATA_VERSION = 12 const val DATA_VERSION = 12
} }
private val job = Job() private val profileConfigs: HashMap<Int, ProfileConfig> = hashMapOf()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Default
val values: HashMap<String, String?> = hashMapOf()
val ui by lazy { ConfigUI(this) } val ui by lazy { ConfigUI(this) }
val sync by lazy { ConfigSync(this) } val sync by lazy { ConfigSync(this) }
val timetable by lazy { ConfigTimetable(this) } val timetable by lazy { ConfigTimetable(this) }
val grades by lazy { ConfigGrades(this) } val grades by lazy { ConfigGrades(this) }
private var mDataVersion: Int? = null var dataVersion by config<Int>(DATA_VERSION)
var dataVersion: Int var hash by config<String>("")
get() { mDataVersion = mDataVersion ?: values.get("dataVersion", 0); return mDataVersion ?: 0 }
set(value) { set("dataVersion", value); mDataVersion = value }
private var mHash: String? = null var lastProfileId by config<Int>(0)
var hash: String var loginFinished by config<Boolean>(false)
get() { mHash = mHash ?: values.get("hash", ""); return mHash ?: "" } var privacyPolicyAccepted by config<Boolean>(false)
set(value) { set("hash", value); mHash = value } var update by config<Update?>(null)
var updatesChannel by config<String>("release")
private var mLastProfileId: Int? = null var devMode by config<Boolean?>("debugMode", null)
var lastProfileId: Int var devModePassword by config<String?>(null)
get() { mLastProfileId = mLastProfileId ?: values.get("lastProfileId", 0); return mLastProfileId ?: 0 } var enableChucker by config<Boolean?>(null)
set(value) { set("lastProfileId", value); mLastProfileId = value }
private var mUpdatesChannel: String? = null var apiAvailabilityCheck by config<Boolean>(true)
var updatesChannel: String var apiInvalidCert by config<String?>(null)
get() { mUpdatesChannel = mUpdatesChannel ?: values.get("updatesChannel", "release"); return mUpdatesChannel ?: "release" } var apiKeyCustom by config<String?>(null)
set(value) { set("updatesChannel", value); mUpdatesChannel = value } var appInstalledTime by config<Long>(0L)
private var mUpdate: Update? = null var appRateSnackbarTime by config<Long>(0L)
var update: Update? var appVersion by config<Int>(BuildConfig.VERSION_CODE)
get() { mUpdate = mUpdate ?: values.get("update", null as Update?); return mUpdate ?: null as Update? } var validation by config<String?>(null, "buildValidation")
set(value) { set("update", value); mUpdate = value }
private var mAppVersion: Int? = null var archiverEnabled by config<Boolean>(true)
var appVersion: Int var runSync by config<Boolean>(false)
get() { mAppVersion = mAppVersion ?: values.get("appVersion", BuildConfig.VERSION_CODE); return mAppVersion ?: BuildConfig.VERSION_CODE } var widgetConfigs by config<JsonObject> { JsonObject() }
set(value) { set("appVersion", value); mAppVersion = value }
private var mLoginFinished: Boolean? = null
var loginFinished: Boolean
get() { mLoginFinished = mLoginFinished ?: values.get("loginFinished", false); return mLoginFinished ?: false }
set(value) { set("loginFinished", value); mLoginFinished = value }
private var mPrivacyPolicyAccepted: Boolean? = null
var privacyPolicyAccepted: Boolean
get() { mPrivacyPolicyAccepted = mPrivacyPolicyAccepted ?: values.get("privacyPolicyAccepted", false); return mPrivacyPolicyAccepted ?: false }
set(value) { set("privacyPolicyAccepted", value); mPrivacyPolicyAccepted = value }
private var mDevMode: Boolean? = null
var devMode: Boolean?
get() { mDevMode = mDevMode ?: values.getBooleanOrNull("debugMode"); return mDevMode }
set(value) { set("debugMode", value?.toString()); mDevMode = value }
private var mEnableChucker: Boolean? = null
var enableChucker: Boolean?
get() { mEnableChucker = mEnableChucker ?: values.getBooleanOrNull("enableChucker"); return mEnableChucker }
set(value) { set("enableChucker", value?.toString()); mEnableChucker = value }
private var mDevModePassword: String? = null
var devModePassword: String?
get() { mDevModePassword = mDevModePassword ?: values.get("devModePassword", null as String?); return mDevModePassword }
set(value) { set("devModePassword", value); mDevModePassword = value }
private var mAppInstalledTime: Long? = null
var appInstalledTime: Long
get() { mAppInstalledTime = mAppInstalledTime ?: values.get("appInstalledTime", 0L); return mAppInstalledTime ?: 0L }
set(value) { set("appInstalledTime", value); mAppInstalledTime = value }
private var mAppRateSnackbarTime: Long? = null
var appRateSnackbarTime: Long
get() { mAppRateSnackbarTime = mAppRateSnackbarTime ?: values.get("appRateSnackbarTime", 0L); return mAppRateSnackbarTime ?: 0L }
set(value) { set("appRateSnackbarTime", value); mAppRateSnackbarTime = value }
private var mRunSync: Boolean? = null
var runSync: Boolean
get() { mRunSync = mRunSync ?: values.get("runSync", false); return mRunSync ?: false }
set(value) { set("runSync", value); mRunSync = value }
private var mWidgetConfigs: JsonObject? = null
var widgetConfigs: JsonObject
get() { mWidgetConfigs = mWidgetConfigs ?: values.get("widgetConfigs", JsonObject()); return mWidgetConfigs ?: JsonObject() }
set(value) { set("widgetConfigs", value); mWidgetConfigs = value }
private var mArchiverEnabled: Boolean? = null
var archiverEnabled: Boolean
get() { mArchiverEnabled = mArchiverEnabled ?: values.get("archiverEnabled", true); return mArchiverEnabled ?: true }
set(value) { set("archiverEnabled", value); mArchiverEnabled = value }
private var mValidation: String? = null
var validation: String?
get() { mValidation = mValidation ?: values["buildValidation"]; return mValidation }
set(value) { set("buildValidation", value); mValidation = value }
private var mApiInvalidCert: String? = null
var apiInvalidCert: String?
get() { mApiInvalidCert = mApiInvalidCert ?: values["apiInvalidCert"]; return mApiInvalidCert }
set(value) { set("apiInvalidCert", value); mApiInvalidCert = value }
private var mApiAvailabilityCheck: Boolean? = null
var apiAvailabilityCheck: Boolean
get() { mApiAvailabilityCheck = mApiAvailabilityCheck ?: values.get("apiAvailabilityCheck", true); return mApiAvailabilityCheck ?: true }
set(value) { set("apiAvailabilityCheck", value); mApiAvailabilityCheck = value }
private var rawEntries: List<ConfigEntry> = db.configDao().getAllNow()
private val profileConfigs: HashMap<Int, ProfileConfig> = hashMapOf()
init {
rawEntries.toHashMap(-1, values)
}
fun migrate(app: App) { fun migrate(app: App) {
if (dataVersion < DATA_VERSION) if (dataVersion < DATA_VERSION || hash == "")
// migrate old data version OR freshly installed app (or updated from 3.x)
ConfigMigration(app, this) ConfigMigration(app, this)
} }
fun getFor(profileId: Int): ProfileConfig {
return profileConfigs[profileId] ?: ProfileConfig(db, profileId, db.configDao().getAllNow(profileId)).also { operator fun get(profileId: Int): ProfileConfig {
return profileConfigs[profileId] ?: ProfileConfig(db, profileId, entries).also {
profileConfigs[profileId] = it profileConfigs[profileId] = it
} }
} }
fun forProfile() = getFor(App.profileId)
fun setProfile(profileId: Int) {
}
override fun set(key: String, value: String?) {
values[key] = value
launch {
db.configDao().add(ConfigEntry(-1, key, value))
}
}
} }

View File

@ -4,13 +4,10 @@
package pl.szczodrzynski.edziennik.config package pl.szczodrzynski.edziennik.config
import pl.szczodrzynski.edziennik.config.utils.get import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.ORDER_BY_DATE_DESC
import pl.szczodrzynski.edziennik.config.utils.set
import pl.szczodrzynski.edziennik.utils.managers.GradesManager
class ConfigGrades(private val config: Config) { @Suppress("RemoveExplicitTypeArguments")
private var mOrderBy: Int? = null class ConfigGrades(base: Config) {
var orderBy: Int
get() { mOrderBy = mOrderBy ?: config.values.get("gradesOrderBy", 0); return mOrderBy ?: GradesManager.ORDER_BY_DATE_DESC } var orderBy by base.config<Int>("gradesOrderBy", ORDER_BY_DATE_DESC)
set(value) { config.set("gradesOrderBy", value); mOrderBy = value }
} }

View File

@ -4,139 +4,53 @@
package pl.szczodrzynski.edziennik.config package pl.szczodrzynski.edziennik.config
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import pl.szczodrzynski.edziennik.BuildConfig import pl.szczodrzynski.edziennik.BuildConfig
import pl.szczodrzynski.edziennik.config.utils.get
import pl.szczodrzynski.edziennik.config.utils.getIntList
import pl.szczodrzynski.edziennik.config.utils.set
import pl.szczodrzynski.edziennik.config.utils.setMap
import pl.szczodrzynski.edziennik.data.api.szkolny.response.RegisterAvailabilityStatus import pl.szczodrzynski.edziennik.data.api.szkolny.response.RegisterAvailabilityStatus
import pl.szczodrzynski.edziennik.ext.HOUR
import pl.szczodrzynski.edziennik.utils.models.Time import pl.szczodrzynski.edziennik.utils.models.Time
class ConfigSync(private val config: Config) { @Suppress("RemoveExplicitTypeArguments")
private val gson = Gson() class ConfigSync(base: Config) {
private var mDontShowAppManagerDialog: Boolean? = null var enabled by base.config<Boolean>("syncEnabled", true)
var dontShowAppManagerDialog: Boolean var interval by base.config<Int>("syncInterval", 1 * HOUR.toInt())
get() { mDontShowAppManagerDialog = mDontShowAppManagerDialog ?: config.values.get("dontShowAppManagerDialog", false); return mDontShowAppManagerDialog ?: false } var onlyWifi by base.config<Boolean>("syncOnlyWifi", false)
set(value) { config.set("dontShowAppManagerDialog", value); mDontShowAppManagerDialog = value }
private var mSyncEnabled: Boolean? = null var dontShowAppManagerDialog by base.config<Boolean>(false)
var enabled: Boolean var lastAppSync by base.config<Long>(0L)
get() { mSyncEnabled = mSyncEnabled ?: config.values.get("syncEnabled", true); return mSyncEnabled ?: true } var notifyAboutUpdates by base.config<Boolean>(true)
set(value) { config.set("syncEnabled", value); mSyncEnabled = value } var webPushEnabled by base.config<Boolean>(true)
private var mWebPushEnabled: Boolean? = null // Quiet Hours
var webPushEnabled: Boolean var quietHoursEnabled by base.config<Boolean>(false)
get() { mWebPushEnabled = mWebPushEnabled ?: config.values.get("webPushEnabled", true); return mWebPushEnabled ?: true } var quietHoursStart by base.config<Time?>(null)
set(value) { config.set("webPushEnabled", value); mWebPushEnabled = value } var quietHoursEnd by base.config<Time?>(null)
var quietDuringLessons by base.config<Boolean>(false)
private var mSyncOnlyWifi: Boolean? = null // FCM Tokens
var onlyWifi: Boolean var tokenApp by base.config<String?>(null)
get() { mSyncOnlyWifi = mSyncOnlyWifi ?: config.values.get("syncOnlyWifi", false); return mSyncOnlyWifi ?: notifyAboutUpdates } var tokenMobidziennik by base.config<String?>(null)
set(value) { config.set("syncOnlyWifi", value); mSyncOnlyWifi = value } var tokenLibrus by base.config<String?>(null)
var tokenVulcan by base.config<String?>(null)
var tokenVulcanHebe by base.config<String?>(null)
private var mSyncInterval: Int? = null var tokenMobidziennikList by base.config<List<Int>> { listOf() }
var interval: Int var tokenLibrusList by base.config<List<Int>> { listOf() }
get() { mSyncInterval = mSyncInterval ?: config.values.get("syncInterval", 60*60); return mSyncInterval ?: 60*60 } var tokenVulcanList by base.config<List<Int>> { listOf() }
set(value) { config.set("syncInterval", value); mSyncInterval = value } var tokenVulcanHebeList by base.config<List<Int>> { listOf() }
private var mNotifyAboutUpdates: Boolean? = null // Register Availability
var notifyAboutUpdates: Boolean private var registerAvailabilityMap by base.config<Map<String, RegisterAvailabilityStatus>>("registerAvailability") { mapOf() }
get() { mNotifyAboutUpdates = mNotifyAboutUpdates ?: config.values.get("notifyAboutUpdates", true); return mNotifyAboutUpdates ?: true } private var registerAvailabilityFlavor by base.config<String?>(null)
set(value) { config.set("notifyAboutUpdates", value); mNotifyAboutUpdates = value }
private var mLastAppSync: Long? = null
var lastAppSync: Long
get() { mLastAppSync = mLastAppSync ?: config.values.get("lastAppSync", 0L); return mLastAppSync ?: 0L }
set(value) { config.set("lastAppSync", value); mLastAppSync = value }
/* ____ _ _ _
/ __ \ (_) | | | |
| | | |_ _ _ ___| |_ | |__ ___ _ _ _ __ ___
| | | | | | | |/ _ \ __| | '_ \ / _ \| | | | '__/ __|
| |__| | |_| | | __/ |_ | | | | (_) | |_| | | \__ \
\___\_\\__,_|_|\___|\__| |_| |_|\___/ \__,_|_| |__*/
private var mQuietHoursEnabled: Boolean? = null
var quietHoursEnabled: Boolean
get() { mQuietHoursEnabled = mQuietHoursEnabled ?: config.values.get("quietHoursEnabled", false); return mQuietHoursEnabled ?: false }
set(value) { config.set("quietHoursEnabled", value); mQuietHoursEnabled = value }
private var mQuietHoursStart: Time? = null
var quietHoursStart: Time?
get() { mQuietHoursStart = mQuietHoursStart ?: config.values.get("quietHoursStart", null as Time?); return mQuietHoursStart }
set(value) { config.set("quietHoursStart", value); mQuietHoursStart = value }
private var mQuietHoursEnd: Time? = null
var quietHoursEnd: Time?
get() { mQuietHoursEnd = mQuietHoursEnd ?: config.values.get("quietHoursEnd", null as Time?); return mQuietHoursEnd }
set(value) { config.set("quietHoursEnd", value); mQuietHoursEnd = value }
private var mQuietDuringLessons: Boolean? = null
var quietDuringLessons: Boolean
get() { mQuietDuringLessons = mQuietDuringLessons ?: config.values.get("quietDuringLessons", false); return mQuietDuringLessons ?: false }
set(value) { config.set("quietDuringLessons", value); mQuietDuringLessons = value }
/* ______ _____ __ __ _______ _
| ____/ ____| \/ | |__ __| | |
| |__ | | | \ / | | | ___ | | _____ _ __ ___
| __|| | | |\/| | | |/ _ \| |/ / _ \ '_ \/ __|
| | | |____| | | | | | (_) | < __/ | | \__ \
|_| \_____|_| |_| |_|\___/|_|\_\___|_| |_|__*/
private var mTokenApp: String? = null
var tokenApp: String?
get() { mTokenApp = mTokenApp ?: config.values.get("tokenApp", null as String?); return mTokenApp }
set(value) { config.set("tokenApp", value); mTokenApp = value }
private var mTokenMobidziennik: String? = null
var tokenMobidziennik: String?
get() { mTokenMobidziennik = mTokenMobidziennik ?: config.values.get("tokenMobidziennik", null as String?); return mTokenMobidziennik }
set(value) { config.set("tokenMobidziennik", value); mTokenMobidziennik = value }
private var mTokenLibrus: String? = null
var tokenLibrus: String?
get() { mTokenLibrus = mTokenLibrus ?: config.values.get("tokenLibrus", null as String?); return mTokenLibrus }
set(value) { config.set("tokenLibrus", value); mTokenLibrus = value }
private var mTokenVulcan: String? = null
var tokenVulcan: String?
get() { mTokenVulcan = mTokenVulcan ?: config.values.get("tokenVulcan", null as String?); return mTokenVulcan }
set(value) { config.set("tokenVulcan", value); mTokenVulcan = value }
private var mTokenVulcanHebe: String? = null
var tokenVulcanHebe: String?
get() { mTokenVulcanHebe = mTokenVulcanHebe ?: config.values.get("tokenVulcanHebe", null as String?); return mTokenVulcanHebe }
set(value) { config.set("tokenVulcanHebe", value); mTokenVulcanHebe = value }
private var mTokenMobidziennikList: List<Int>? = null
var tokenMobidziennikList: List<Int>
get() { mTokenMobidziennikList = mTokenMobidziennikList ?: config.values.getIntList("tokenMobidziennikList", listOf()); return mTokenMobidziennikList ?: listOf() }
set(value) { config.set("tokenMobidziennikList", value); mTokenMobidziennikList = value }
private var mTokenLibrusList: List<Int>? = null
var tokenLibrusList: List<Int>
get() { mTokenLibrusList = mTokenLibrusList ?: config.values.getIntList("tokenLibrusList", listOf()); return mTokenLibrusList ?: listOf() }
set(value) { config.set("tokenLibrusList", value); mTokenLibrusList = value }
private var mTokenVulcanList: List<Int>? = null
var tokenVulcanList: List<Int>
get() { mTokenVulcanList = mTokenVulcanList ?: config.values.getIntList("tokenVulcanList", listOf()); return mTokenVulcanList ?: listOf() }
set(value) { config.set("tokenVulcanList", value); mTokenVulcanList = value }
private var mTokenVulcanHebeList: List<Int>? = null
var tokenVulcanHebeList: List<Int>
get() { mTokenVulcanHebeList = mTokenVulcanHebeList ?: config.values.getIntList("tokenVulcanHebeList", listOf()); return mTokenVulcanHebeList ?: listOf() }
set(value) { config.set("tokenVulcanHebeList", value); mTokenVulcanHebeList = value }
private var mRegisterAvailability: Map<String, RegisterAvailabilityStatus>? = null
var registerAvailability: Map<String, RegisterAvailabilityStatus> var registerAvailability: Map<String, RegisterAvailabilityStatus>
get() { get() {
val flavor = config.values.get("registerAvailabilityFlavor", null as String?) if (BuildConfig.FLAVOR != registerAvailabilityFlavor)
if (BuildConfig.FLAVOR != flavor)
return mapOf() return mapOf()
return registerAvailabilityMap
mRegisterAvailability = mRegisterAvailability ?: config.values.get("registerAvailability", null as String?)?.let { it ->
gson.fromJson(it, object: TypeToken<Map<String, RegisterAvailabilityStatus>>(){}.type)
}
return mRegisterAvailability ?: mapOf()
} }
set(value) { set(value) {
config.setMap("registerAvailability", value) registerAvailabilityMap = value
config.set("registerAvailabilityFlavor", BuildConfig.FLAVOR) registerAvailabilityFlavor = BuildConfig.FLAVOR
mRegisterAvailability = value
} }
} }

View File

@ -4,23 +4,12 @@
package pl.szczodrzynski.edziennik.config package pl.szczodrzynski.edziennik.config
import pl.szczodrzynski.edziennik.config.utils.get
import pl.szczodrzynski.edziennik.config.utils.set
import pl.szczodrzynski.edziennik.utils.models.Time import pl.szczodrzynski.edziennik.utils.models.Time
class ConfigTimetable(private val config: Config) { @Suppress("RemoveExplicitTypeArguments")
private var mBellSyncMultiplier: Int? = null class ConfigTimetable(base: Config) {
var bellSyncMultiplier: Int
get() { mBellSyncMultiplier = mBellSyncMultiplier ?: config.values.get("bellSyncMultiplier", 0); return mBellSyncMultiplier ?: 0 }
set(value) { config.set("bellSyncMultiplier", value); mBellSyncMultiplier = value }
private var mBellSyncDiff: Time? = null var bellSyncMultiplier by base.config<Int>(0)
var bellSyncDiff: Time? var bellSyncDiff by base.config<Time?>(null)
get() { mBellSyncDiff = mBellSyncDiff ?: config.values.get("bellSyncDiff", null as Time?); return mBellSyncDiff } var countInSeconds by base.config<Boolean>(false)
set(value) { config.set("bellSyncDiff", value); mBellSyncDiff = value }
private var mCountInSeconds: Boolean? = null
var countInSeconds: Boolean
get() { mCountInSeconds = mCountInSeconds ?: config.values.get("countInSeconds", false); return mCountInSeconds ?: false }
set(value) { config.set("countInSeconds", value); mCountInSeconds = value }
} }

View File

@ -4,58 +4,32 @@
package pl.szczodrzynski.edziennik.config package pl.szczodrzynski.edziennik.config
import pl.szczodrzynski.edziennik.config.utils.get import pl.szczodrzynski.edziennik.ui.base.enums.NavTarget
import pl.szczodrzynski.edziennik.config.utils.getIntList
import pl.szczodrzynski.edziennik.config.utils.set
class ConfigUI(private val config: Config) { @Suppress("RemoveExplicitTypeArguments")
private var mTheme: Int? = null class ConfigUI(base: Config) {
var theme: Int
get() { mTheme = mTheme ?: config.values.get("theme", 1); return mTheme ?: 1 }
set(value) { config.set("theme", value); mTheme = value }
private var mLanguage: String? = null var theme by base.config<Int>(1)
var language: String? var language by base.config<String?>(null)
get() { mLanguage = mLanguage ?: config.values.get("language", null as String?); return mLanguage }
set(value) { config.set("language", value); mLanguage = value }
private var mHeaderBackground: String? = null var appBackground by base.config<String?>("appBg", null)
var headerBackground: String? var headerBackground by base.config<String?>("headerBg", null)
get() { mHeaderBackground = mHeaderBackground ?: config.values.get("headerBg", null as String?); return mHeaderBackground }
set(value) { config.set("headerBg", value); mHeaderBackground = value }
private var mAppBackground: String? = null var miniMenuVisible by base.config<Boolean>(false)
var appBackground: String? var miniMenuButtons by base.config<Set<NavTarget>> {
get() { mAppBackground = mAppBackground ?: config.values.get("appBg", null as String?); return mAppBackground } setOf(
set(value) { config.set("appBg", value); mAppBackground = value } NavTarget.HOME,
NavTarget.TIMETABLE,
private var mMiniMenuVisible: Boolean? = null NavTarget.AGENDA,
var miniMenuVisible: Boolean NavTarget.GRADES,
get() { mMiniMenuVisible = mMiniMenuVisible ?: config.values.get("miniMenuVisible", false); return mMiniMenuVisible ?: false } NavTarget.MESSAGES,
set(value) { config.set("miniMenuVisible", value); mMiniMenuVisible = value } NavTarget.HOMEWORK,
NavTarget.SETTINGS
private var mMiniMenuButtons: List<Int>? = null )
var miniMenuButtons: List<Int> }
get() { mMiniMenuButtons = mMiniMenuButtons ?: config.values.getIntList("miniMenuButtons", listOf()); return mMiniMenuButtons ?: listOf() } var openDrawerOnBackPressed by base.config<Boolean>(false)
set(value) { config.set("miniMenuButtons", value); mMiniMenuButtons = value }
var bottomSheetOpened by base.config<Boolean>(false)
private var mOpenDrawerOnBackPressed: Boolean? = null var snowfall by base.config<Boolean>(false)
var openDrawerOnBackPressed: Boolean var eggfall by base.config<Boolean>(false)
get() { mOpenDrawerOnBackPressed = mOpenDrawerOnBackPressed ?: config.values.get("openDrawerOnBackPressed", false); return mOpenDrawerOnBackPressed ?: false }
set(value) { config.set("openDrawerOnBackPressed", value); mOpenDrawerOnBackPressed = value }
private var mSnowfall: Boolean? = null
var snowfall: Boolean
get() { mSnowfall = mSnowfall ?: config.values.get("snowfall", false); return mSnowfall ?: false }
set(value) { config.set("snowfall", value); mSnowfall = value }
private var mEggfall: Boolean? = null
var eggfall: Boolean
get() { mEggfall = mEggfall ?: config.values.get("eggfall", false); return mEggfall ?: false }
set(value) { config.set("eggfall", value); mEggfall = value }
private var mBottomSheetOpened: Boolean? = null
var bottomSheetOpened: Boolean
get() { mBottomSheetOpened = mBottomSheetOpened ?: config.values.get("bottomSheetOpened", false); return mBottomSheetOpened ?: false }
set(value) { config.set("bottomSheetOpened", value); mBottomSheetOpened = value }
} }

View File

@ -0,0 +1,175 @@
/*
* Copyright (c) Kuba Szczodrzyński 2022-10-21.
*/
package pl.szczodrzynski.edziennik.config
import com.google.gson.Gson
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import com.google.gson.reflect.TypeToken
import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
import java.lang.reflect.ParameterizedType
import java.lang.reflect.WildcardType
import kotlin.reflect.KProperty
private val gson = Gson()
inline fun <reified T> BaseConfig.config(name: String? = null, noinline default: () -> T) = ConfigDelegate(
config = this,
type = T::class.java,
nullable = null is T,
typeToken = object : TypeToken<T>() {},
defaultFunc = default,
defaultValue = null,
fieldName = name,
)
inline fun <reified T> BaseConfig.config(default: T) = ConfigDelegate(
config = this,
type = T::class.java,
nullable = null is T,
typeToken = object : TypeToken<T>() {},
defaultFunc = null,
defaultValue = default,
fieldName = null,
)
inline fun <reified T> BaseConfig.config(name: String? = null, default: T) = ConfigDelegate(
config = this,
type = T::class.java,
nullable = null is T,
typeToken = object : TypeToken<T>() {},
defaultFunc = null,
defaultValue = default,
fieldName = name,
)
@Suppress("UNCHECKED_CAST")
class ConfigDelegate<T>(
private val config: BaseConfig,
private val type: Class<T>,
private val nullable: Boolean,
private val typeToken: TypeToken<T>,
private val defaultFunc: (() -> T)?,
private val defaultValue: T?,
private val fieldName: String?,
) {
private var value: T? = null
private var isInitialized = false
private fun getDefault(): T = when {
defaultFunc != null -> defaultFunc.invoke()
else -> defaultValue as T
}
private fun getGenericType(index: Int = 0): Class<*> {
val parameterizedType = typeToken.type as ParameterizedType
val typeArgument = parameterizedType.actualTypeArguments[index] as WildcardType
return typeArgument.upperBounds[0] as Class<*>
}
operator fun setValue(_thisRef: Any, property: KProperty<*>, newValue: T) {
value = newValue
isInitialized = true
config.set(fieldName ?: property.name, serialize(newValue)?.toString())
}
operator fun getValue(_thisRef: Any, property: KProperty<*>): T {
if (isInitialized)
return value as T
val key = fieldName ?: property.name
if (key !in config.values) {
value = getDefault()
isInitialized = true
return value as T
}
val str = config.values[key]
value = if (str == null && nullable)
null as T
else if (str == null)
getDefault()
else
deserialize(str)
isInitialized = true
return value as T
}
private fun <I> serialize(value: I?, serializeObjects: Boolean = true): Any? {
if (value == null)
return null
return when (value) {
is String -> value
is Date -> value.stringY_m_d
is Time -> value.stringValue
is JsonObject -> value
is JsonArray -> value
// primitives
is Number -> value
is Boolean -> value
// enums, maps & collections
is Enum<*> -> value.toInt()
is Collection<*> -> value.map {
if (it is Number || it is Boolean) it else serialize(it, serializeObjects = false)
}.toJsonElement()
is Map<*, *> -> gson.toJson(value.mapValues { (_, it) ->
if (it is Number || it is Boolean) it else serialize(it, serializeObjects = false)
})
// objects or else
else -> if (serializeObjects) gson.toJson(value) else value
}
}
private fun <I> deserialize(value: String?, type: Class<*> = this.type): I? {
if (value == null)
return null
@Suppress("TYPE_MISMATCH_WARNING")
return when (type) {
String::class.java -> value
Date::class.java -> Date.fromY_m_d(value)
Time::class.java -> Time.fromHms(value)
JsonObject::class.java -> value.toJsonObject()
JsonArray::class.java -> value.toJsonArray()
// primitives
java.lang.Integer::class.java -> value.toIntOrNull()
java.lang.Boolean::class.java -> value.toBooleanStrictOrNull()
java.lang.Long::class.java -> value.toLongOrNull()
java.lang.Float::class.java -> value.toFloatOrNull()
// enums, maps & collections
else -> when {
Enum::class.java.isAssignableFrom(type) -> value.toIntOrNull()?.toEnum(type) as Enum<*>
Collection::class.java.isAssignableFrom(type) -> {
val array = value.toJsonArray()
val genericType = getGenericType()
val list = array?.map {
val str = if (it.isJsonPrimitive) it.asString else it.toString()
deserialize<Any>(str, genericType)
}
when {
List::class.java.isAssignableFrom(type) -> list
Set::class.java.isAssignableFrom(type) -> list?.toSet()
else -> list?.toTypedArray()
}
}
Map::class.java.isAssignableFrom(type) -> {
val obj = value.toJsonObject()
val genericType = getGenericType(index = 1)
val map = obj?.entrySet()?.associate { (key, it) ->
val str = if (it.isJsonPrimitive) it.asString else it.toString()
key to deserialize<Any>(str, genericType)
}
map
}
// objects or else
else -> gson.fromJson(value, type)
}
} as? I
}
}

View File

@ -4,29 +4,20 @@
package pl.szczodrzynski.edziennik.config package pl.szczodrzynski.edziennik.config
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import pl.szczodrzynski.edziennik.config.db.ConfigEntry import pl.szczodrzynski.edziennik.config.db.ConfigEntry
import pl.szczodrzynski.edziennik.config.utils.ProfileConfigMigration import pl.szczodrzynski.edziennik.config.utils.ProfileConfigMigration
import pl.szczodrzynski.edziennik.config.utils.get
import pl.szczodrzynski.edziennik.config.utils.set
import pl.szczodrzynski.edziennik.config.utils.toHashMap
import pl.szczodrzynski.edziennik.data.db.AppDb import pl.szczodrzynski.edziennik.data.db.AppDb
import kotlin.coroutines.CoroutineContext
class ProfileConfig(val db: AppDb, val profileId: Int, rawEntries: List<ConfigEntry>) : CoroutineScope, AbstractConfig { @Suppress("RemoveExplicitTypeArguments")
class ProfileConfig(
db: AppDb,
profileId: Int,
entries: List<ConfigEntry>?,
) : BaseConfig(db, profileId, entries) {
companion object { companion object {
const val DATA_VERSION = 3 const val DATA_VERSION = 5
} }
private val job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Default
val values: HashMap<String, String?> = hashMapOf()
val grades by lazy { ProfileConfigGrades(this) } val grades by lazy { ProfileConfigGrades(this) }
val ui by lazy { ProfileConfigUI(this) } val ui by lazy { ProfileConfigUI(this) }
val sync by lazy { ProfileConfigSync(this) } val sync by lazy { ProfileConfigSync(this) }
@ -35,26 +26,13 @@ class ProfileConfig(val db: AppDb, val profileId: Int, rawEntries: List<ConfigEn
val timetable by lazy { ConfigTimetable(this) } val timetable by lazy { ConfigTimetable(this) }
val grades by lazy { ConfigGrades(this) }*/ val grades by lazy { ConfigGrades(this) }*/
private var mDataVersion: Int? = null var dataVersion by config<Int>(DATA_VERSION)
var dataVersion: Int var hash by config<String>("")
get() { mDataVersion = mDataVersion ?: values.get("dataVersion", 0); return mDataVersion ?: 0 }
set(value) { set("dataVersion", value); mDataVersion = value }
private var mHash: String? = null var shareByDefault by config<Boolean>(false)
var hash: String
get() { mHash = mHash ?: values.get("hash", ""); return mHash ?: "" }
set(value) { set("hash", value); mHash = value }
init { init {
rawEntries.toHashMap(profileId, values)
if (dataVersion < DATA_VERSION) if (dataVersion < DATA_VERSION)
ProfileConfigMigration(this) ProfileConfigMigration(this)
} }
override fun set(key: String, value: String?) {
values[key] = value
launch {
db.configDao().add(ConfigEntry(profileId, key, value))
}
}
} }

View File

@ -4,27 +4,11 @@
package pl.szczodrzynski.edziennik.config package pl.szczodrzynski.edziennik.config
import pl.szczodrzynski.edziennik.config.utils.get @Suppress("RemoveExplicitTypeArguments")
import pl.szczodrzynski.edziennik.config.utils.set class ProfileConfigAttendance(base: ProfileConfig) {
class ProfileConfigAttendance(private val config: ProfileConfig) { var attendancePageSelection by base.config<Int>(1)
private var mAttendancePageSelection: Int? = null var groupConsecutiveDays by base.config<Boolean>(true)
var attendancePageSelection: Int var showPresenceInMonth by base.config<Boolean>(false)
get() { mAttendancePageSelection = mAttendancePageSelection ?: config.values.get("attendancePageSelection", 1); return mAttendancePageSelection ?: 1 } var useSymbols by base.config<Boolean>(false)
set(value) { config.set("attendancePageSelection", value); mAttendancePageSelection = value }
private var mUseSymbols: Boolean? = null
var useSymbols: Boolean
get() { mUseSymbols = mUseSymbols ?: config.values.get("useSymbols", false); return mUseSymbols ?: false }
set(value) { config.set("useSymbols", value); mUseSymbols = value }
private var mGroupConsecutiveDays: Boolean? = null
var groupConsecutiveDays: Boolean
get() { mGroupConsecutiveDays = mGroupConsecutiveDays ?: config.values.get("groupConsecutiveDays", true); return mGroupConsecutiveDays ?: true }
set(value) { config.set("groupConsecutiveDays", value); mGroupConsecutiveDays = value }
private var mShowPresenceInMonth: Boolean? = null
var showPresenceInMonth: Boolean
get() { mShowPresenceInMonth = mShowPresenceInMonth ?: config.values.get("showPresenceInMonth", false); return mShowPresenceInMonth ?: false }
set(value) { config.set("showPresenceInMonth", value); mShowPresenceInMonth = value }
} }

View File

@ -4,54 +4,19 @@
package pl.szczodrzynski.edziennik.config package pl.szczodrzynski.edziennik.config
import pl.szczodrzynski.edziennik.config.utils.get
import pl.szczodrzynski.edziennik.config.utils.getFloat
import pl.szczodrzynski.edziennik.config.utils.set
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.COLOR_MODE_WEIGHTED import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.COLOR_MODE_WEIGHTED
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.YEAR_ALL_GRADES import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.YEAR_ALL_GRADES
class ProfileConfigGrades(private val config: ProfileConfig) { @Suppress("RemoveExplicitTypeArguments")
private var mColorMode: Int? = null class ProfileConfigGrades(base: ProfileConfig) {
var colorMode: Int
get() { mColorMode = mColorMode ?: config.values.get("gradesColorMode", COLOR_MODE_WEIGHTED); return mColorMode ?: COLOR_MODE_WEIGHTED }
set(value) { config.set("gradesColorMode", value); mColorMode = value }
private var mYearAverageMode: Int? = null var averageWithoutWeight by base.config<Boolean>(true)
var yearAverageMode: Int var colorMode by base.config<Int>(COLOR_MODE_WEIGHTED)
get() { mYearAverageMode = mYearAverageMode ?: config.values.get("yearAverageMode", YEAR_ALL_GRADES); return mYearAverageMode ?: YEAR_ALL_GRADES } var dontCountEnabled by base.config<Boolean>(false)
set(value) { config.set("yearAverageMode", value); mYearAverageMode = value } var dontCountGrades by base.config<List<String>> { listOf() }
var hideImproved by base.config<Boolean>(false)
private var mHideImproved: Boolean? = null var hideSticksFromOld by base.config<Boolean>(false)
var hideImproved: Boolean var minusValue by base.config<Float?>(null)
get() { mHideImproved = mHideImproved ?: config.values.get("hideImproved", false); return mHideImproved ?: false } var plusValue by base.config<Float?>(null)
set(value) { config.set("hideImproved", value); mHideImproved = value } var yearAverageMode by base.config<Int>(YEAR_ALL_GRADES)
private var mAverageWithoutWeight: Boolean? = null
var averageWithoutWeight: Boolean
get() { mAverageWithoutWeight = mAverageWithoutWeight ?: config.values.get("averageWithoutWeight", true); return mAverageWithoutWeight ?: true }
set(value) { config.set("averageWithoutWeight", value); mAverageWithoutWeight = value }
private var mPlusValue: Float? = null
var plusValue: Float?
get() { mPlusValue = mPlusValue ?: config.values.getFloat("plusValue"); return mPlusValue }
set(value) { config.set("plusValue", value); mPlusValue = value }
private var mMinusValue: Float? = null
var minusValue: Float?
get() { mMinusValue = mMinusValue ?: config.values.getFloat("minusValue"); return mMinusValue }
set(value) { config.set("minusValue", value); mMinusValue = value }
private var mDontCountEnabled: Boolean? = null
var dontCountEnabled: Boolean
get() { mDontCountEnabled = mDontCountEnabled ?: config.values.get("dontCountEnabled", false); return mDontCountEnabled ?: false }
set(value) { config.set("dontCountEnabled", value); mDontCountEnabled = value }
private var mDontCountGrades: List<String>? = null
var dontCountGrades: List<String>
get() { mDontCountGrades = mDontCountGrades ?: config.values.get("dontCountGrades", listOf()); return mDontCountGrades ?: listOf() }
set(value) { config.set("dontCountGrades", value); mDontCountGrades = value }
private var mHideSticksFromOld: Boolean? = null
var hideSticksFromOld: Boolean
get() { mHideSticksFromOld = mHideSticksFromOld ?: config.values.get("hideSticksFromOld", false); return mHideSticksFromOld ?: false }
set(value) { config.set("hideSticksFromOld", value); mHideSticksFromOld = value }
} }

View File

@ -4,12 +4,14 @@
package pl.szczodrzynski.edziennik.config package pl.szczodrzynski.edziennik.config
import pl.szczodrzynski.edziennik.config.utils.getIntList import pl.szczodrzynski.edziennik.data.db.enums.NotificationType
import pl.szczodrzynski.edziennik.config.utils.set
class ProfileConfigSync(private val config: ProfileConfig) { @Suppress("RemoveExplicitTypeArguments")
private var mNotificationFilter: List<Int>? = null class ProfileConfigSync(base: ProfileConfig) {
var notificationFilter: List<Int>
get() { mNotificationFilter = mNotificationFilter ?: config.values.getIntList("notificationFilter", listOf()); return mNotificationFilter ?: listOf() } var notificationFilter by base.config<Set<NotificationType>> {
set(value) { config.set("notificationFilter", value); mNotificationFilter = value } NotificationType.values()
.filter { it.enabledByDefault == false }
.toSet()
}
} }

View File

@ -4,69 +4,30 @@
package pl.szczodrzynski.edziennik.config package pl.szczodrzynski.edziennik.config
import pl.szczodrzynski.edziennik.config.utils.get
import pl.szczodrzynski.edziennik.config.utils.set
import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.AGENDA_DEFAULT import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.AGENDA_DEFAULT
import pl.szczodrzynski.edziennik.ui.home.HomeCardModel import pl.szczodrzynski.edziennik.ui.home.HomeCardModel
class ProfileConfigUI(private val config: ProfileConfig) { @Suppress("RemoveExplicitTypeArguments")
private var mAgendaViewType: Int? = null class ProfileConfigUI(base: ProfileConfig) {
var agendaViewType: Int
get() { mAgendaViewType = mAgendaViewType ?: config.values.get("agendaViewType", 0); return mAgendaViewType ?: AGENDA_DEFAULT }
set(value) { config.set("agendaViewType", value); mAgendaViewType = value }
private var mAgendaCompactMode: Boolean? = null var agendaViewType by base.config<Int>(AGENDA_DEFAULT)
var agendaCompactMode: Boolean var agendaCompactMode by base.config<Boolean>(false)
get() { mAgendaCompactMode = mAgendaCompactMode ?: config.values.get("agendaCompactMode", false); return mAgendaCompactMode ?: false } var agendaGroupByType by base.config<Boolean>(false)
set(value) { config.set("agendaCompactMode", value); mAgendaCompactMode = value } var agendaLessonChanges by base.config<Boolean>(true)
var agendaTeacherAbsence by base.config<Boolean>(true)
var agendaSubjectImportant by base.config<Boolean>(false)
var agendaElearningMark by base.config<Boolean>(false)
var agendaElearningGroup by base.config<Boolean>(true)
private var mAgendaGroupByType: Boolean? = null var homeCards by base.config<List<HomeCardModel>> { listOf() }
var agendaGroupByType: Boolean
get() { mAgendaGroupByType = mAgendaGroupByType ?: config.values.get("agendaGroupByType", false); return mAgendaGroupByType ?: false }
set(value) { config.set("agendaGroupByType", value); mAgendaGroupByType = value }
private var mAgendaLessonChanges: Boolean? = null var messagesGreetingOnCompose by base.config<Boolean>(true)
var agendaLessonChanges: Boolean var messagesGreetingOnReply by base.config<Boolean>(true)
get() { mAgendaLessonChanges = mAgendaLessonChanges ?: config.values.get("agendaLessonChanges", true); return mAgendaLessonChanges ?: true } var messagesGreetingOnForward by base.config<Boolean>(false)
set(value) { config.set("agendaLessonChanges", value); mAgendaLessonChanges = value } var messagesGreetingText by base.config<String?>(null)
private var mAgendaTeacherAbsence: Boolean? = null var timetableShowAttendance by base.config<Boolean>(true)
var agendaTeacherAbsence: Boolean var timetableShowEvents by base.config<Boolean>(true)
get() { mAgendaTeacherAbsence = mAgendaTeacherAbsence ?: config.values.get("agendaTeacherAbsence", true); return mAgendaTeacherAbsence ?: true } var timetableTrimHourRange by base.config<Boolean>(false)
set(value) { config.set("agendaTeacherAbsence", value); mAgendaTeacherAbsence = value } var timetableColorSubjectName by base.config<Boolean>(false)
private var mAgendaElearningMark: Boolean? = null
var agendaElearningMark: Boolean
get() { mAgendaElearningMark = mAgendaElearningMark ?: config.values.get("agendaElearningMark", false); return mAgendaElearningMark ?: false }
set(value) { config.set("agendaElearningMark", value); mAgendaElearningMark = value }
private var mAgendaElearningGroup: Boolean? = null
var agendaElearningGroup: Boolean
get() { mAgendaElearningGroup = mAgendaElearningGroup ?: config.values.get("agendaElearningGroup", true); return mAgendaElearningGroup ?: true }
set(value) { config.set("agendaElearningGroup", value); mAgendaElearningGroup = value }
private var mHomeCards: List<HomeCardModel>? = null
var homeCards: List<HomeCardModel>
get() { mHomeCards = mHomeCards ?: config.values.get("homeCards", listOf(), HomeCardModel::class.java); return mHomeCards ?: listOf() }
set(value) { config.set("homeCards", value); mHomeCards = value }
private var mMessagesGreetingOnCompose: Boolean? = null
var messagesGreetingOnCompose: Boolean
get() { mMessagesGreetingOnCompose = mMessagesGreetingOnCompose ?: config.values.get("messagesGreetingOnCompose", true); return mMessagesGreetingOnCompose ?: true }
set(value) { config.set("messagesGreetingOnCompose", value); mMessagesGreetingOnCompose = value }
private var mMessagesGreetingOnReply: Boolean? = null
var messagesGreetingOnReply: Boolean
get() { mMessagesGreetingOnReply = mMessagesGreetingOnReply ?: config.values.get("messagesGreetingOnReply", true); return mMessagesGreetingOnReply ?: true }
set(value) { config.set("messagesGreetingOnReply", value); mMessagesGreetingOnReply = value }
private var mMessagesGreetingOnForward: Boolean? = null
var messagesGreetingOnForward: Boolean
get() { mMessagesGreetingOnForward = mMessagesGreetingOnForward ?: config.values.get("messagesGreetingOnForward", false); return mMessagesGreetingOnForward ?: false }
set(value) { config.set("messagesGreetingOnForward", value); mMessagesGreetingOnForward = value }
private var mMessagesGreetingText: String? = null
var messagesGreetingText: String?
get() { mMessagesGreetingText = mMessagesGreetingText ?: config.values["messagesGreetingText"]; return mMessagesGreetingText }
set(value) { config.set("messagesGreetingText", value); mMessagesGreetingText = value }
} }

View File

@ -17,7 +17,7 @@ interface ConfigDao {
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
fun addAll(list: List<ConfigEntry>) fun addAll(list: List<ConfigEntry>)
@Query("SELECT * FROM config WHERE profileId = -1") @Query("SELECT * FROM config")
fun getAllNow(): List<ConfigEntry> fun getAllNow(): List<ConfigEntry>
@Query("SELECT * FROM config WHERE profileId = :profileId") @Query("SELECT * FROM config WHERE profileId = :profileId")

View File

@ -8,38 +8,35 @@ import android.content.SharedPreferences
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken
import pl.szczodrzynski.edziennik.BuildConfig import pl.szczodrzynski.edziennik.BuildConfig
import pl.szczodrzynski.edziennik.MainActivity
import pl.szczodrzynski.edziennik.config.Config import pl.szczodrzynski.edziennik.config.Config
import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_LIBRUS import pl.szczodrzynski.edziennik.data.db.enums.LoginType
import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_MOBIDZIENNIK import pl.szczodrzynski.edziennik.ext.asNavTargetOrNull
import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_VULCAN import pl.szczodrzynski.edziennik.ui.base.enums.NavTarget
import pl.szczodrzynski.edziennik.utils.models.Time import pl.szczodrzynski.edziennik.utils.models.Time
import kotlin.math.abs import kotlin.math.abs
class AppConfigMigrationV3(p: SharedPreferences, config: Config) { class AppConfigMigrationV3(p: SharedPreferences, config: Config) {
init { config.apply { init {
val s = "app.appConfig" val s = "app.appConfig"
if (dataVersion < 1) { config.apply {
ui.theme = p.getString("$s.appTheme", null)?.toIntOrNull() ?: 1 ui.theme = p.getString("$s.appTheme", null)?.toIntOrNull() ?: 1
sync.enabled = p.getString("$s.registerSyncEnabled", null)?.toBoolean() ?: true sync.enabled = p.getString("$s.registerSyncEnabled", null)?.toBoolean() ?: true
sync.interval = p.getString("$s.registerSyncInterval", null)?.toIntOrNull() ?: 3600 sync.interval = p.getString("$s.registerSyncInterval", null)?.toIntOrNull() ?: 3600
val oldButtons = p.getString("$s.miniDrawerButtonIds", null)?.let { str -> val oldButtons = p.getString("$s.miniDrawerButtonIds", null)?.let { str ->
str.replace("[\\[\\]]*".toRegex(), "") str.replace("[\\[\\]]*".toRegex(), "")
.split(",\\s?".toRegex()) .split(",\\s?".toRegex())
.mapNotNull { it.toIntOrNull() } .mapNotNull { it.toIntOrNull().asNavTargetOrNull() }
.toSet()
} }
ui.miniMenuButtons = oldButtons ?: listOf( ui.miniMenuButtons = oldButtons ?: setOf(
MainActivity.DRAWER_ITEM_HOME, NavTarget.HOME,
MainActivity.DRAWER_ITEM_TIMETABLE, NavTarget.TIMETABLE,
MainActivity.DRAWER_ITEM_AGENDA, NavTarget.AGENDA,
MainActivity.DRAWER_ITEM_GRADES, NavTarget.GRADES,
MainActivity.DRAWER_ITEM_MESSAGES, NavTarget.MESSAGES,
MainActivity.DRAWER_ITEM_HOMEWORK, NavTarget.HOMEWORK,
MainActivity.DRAWER_ITEM_SETTINGS NavTarget.SETTINGS
) )
dataVersion = 1
}
if (dataVersion < 2) {
devModePassword = p.getString("$s.devModePassword", null).fix() devModePassword = p.getString("$s.devModePassword", null).fix()
sync.tokenApp = p.getString("$s.fcmToken", null).fix() sync.tokenApp = p.getString("$s.fcmToken", null).fix()
timetable.bellSyncMultiplier = p.getString("$s.bellSyncMultiplier", null)?.toIntOrNull() ?: 0 timetable.bellSyncMultiplier = p.getString("$s.bellSyncMultiplier", null)?.toIntOrNull() ?: 0
@ -81,14 +78,13 @@ class AppConfigMigrationV3(p: SharedPreferences, config: Config) {
tokens?.forEach { tokens?.forEach {
val token = it.value.first val token = it.value.first
when (it.key) { when (it.key) {
LOGIN_TYPE_MOBIDZIENNIK -> sync.tokenMobidziennik = token LoginType.MOBIDZIENNIK.id -> sync.tokenMobidziennik = token
LOGIN_TYPE_VULCAN -> sync.tokenVulcan = token LoginType.VULCAN.id -> sync.tokenVulcan = token
LOGIN_TYPE_LIBRUS -> sync.tokenLibrus = token LoginType.LIBRUS.id -> sync.tokenLibrus = token
}
} }
} }
dataVersion = 2
} }
}}
private fun String?.fix(): String? { private fun String?.fix(): String? {
return this?.replace("\"", "")?.let { if (it == "null") null else it } return this?.replace("\"", "")?.let { if (it == "null") null else it }

View File

@ -1,113 +0,0 @@
/*
* Copyright (c) Kuba Szczodrzyński 2019-11-27.
*/
package pl.szczodrzynski.edziennik.config.utils
import com.google.gson.*
import com.google.gson.reflect.TypeToken
import pl.szczodrzynski.edziennik.config.AbstractConfig
import pl.szczodrzynski.edziennik.config.db.ConfigEntry
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
private val gson = Gson()
fun AbstractConfig.set(key: String, value: Int) {
set(key, value.toString())
}
fun AbstractConfig.set(key: String, value: Boolean) {
set(key, value.toString())
}
fun AbstractConfig.set(key: String, value: Long) {
set(key, value.toString())
}
fun AbstractConfig.set(key: String, value: Float) {
set(key, value.toString())
}
fun AbstractConfig.set(key: String, value: Date?) {
set(key, value?.stringY_m_d)
}
fun AbstractConfig.set(key: String, value: Time?) {
set(key, value?.stringValue)
}
fun AbstractConfig.set(key: String, value: JsonElement?) {
set(key, value?.toString())
}
fun AbstractConfig.set(key: String, value: List<Any>?) {
set(key, value?.let { gson.toJson(it) })
}
fun AbstractConfig.set(key: String, value: Any?) {
set(key, value?.let { gson.toJson(it) })
}
fun AbstractConfig.setStringList(key: String, value: List<String>?) {
set(key, value?.let { gson.toJson(it) })
}
fun AbstractConfig.setIntList(key: String, value: List<Int>?) {
set(key, value?.let { gson.toJson(it) })
}
fun AbstractConfig.setLongList(key: String, value: List<Long>?) {
set(key, value?.let { gson.toJson(it) })
}
fun <K, V> AbstractConfig.setMap(key: String, value: Map<K, V>?) {
set(key, value?.let { gson.toJson(it) })
}
fun HashMap<String, String?>.get(key: String, default: String?): String? {
return this[key] ?: default
}
fun HashMap<String, String?>.get(key: String, default: Boolean): Boolean {
return this[key]?.toBoolean() ?: default
}
fun HashMap<String, String?>.getBooleanOrNull(key: String): Boolean? {
return this[key]?.toBooleanStrictOrNull()
}
fun HashMap<String, String?>.get(key: String, default: Int): Int {
return this[key]?.toIntOrNull() ?: default
}
fun HashMap<String, String?>.get(key: String, default: Long): Long {
return this[key]?.toLongOrNull() ?: default
}
fun HashMap<String, String?>.get(key: String, default: Float): Float {
return this[key]?.toFloatOrNull() ?: default
}
fun HashMap<String, String?>.get(key: String, default: Date?): Date? {
return this[key]?.let { Date.fromY_m_d(it) } ?: default
}
fun HashMap<String, String?>.get(key: String, default: Time?): Time? {
return this[key]?.let { Time.fromHms(it) } ?: default
}
fun HashMap<String, String?>.get(key: String, default: JsonObject?): JsonObject? {
return this[key]?.let { JsonParser().parse(it)?.asJsonObject } ?: default
}
fun HashMap<String, String?>.get(key: String, default: JsonArray?): JsonArray? {
return this[key]?.let { JsonParser().parse(it)?.asJsonArray } ?: default
}
inline fun <reified T> HashMap<String, String?>.get(key: String, default: T?): T? {
return this[key]?.let { Gson().fromJson(it, T::class.java) } ?: default
}
/* !!! cannot use mutable list here - modifying it will not update the DB */
fun <T> HashMap<String, String?>.get(key: String, default: List<T>?, classOfT: Class<T>): List<T>? {
return this[key]?.let { ConfigGsonUtils().deserializeList<T>(gson, it, classOfT) } ?: default
}
fun HashMap<String, String?>.getStringList(key: String, default: List<String>?): List<String>? {
return this[key]?.let { gson.fromJson<List<String>>(it, object: TypeToken<List<String>>(){}.type) } ?: default
}
fun HashMap<String, String?>.getIntList(key: String, default: List<Int>?): List<Int>? {
return this[key]?.let { gson.fromJson<List<Int>>(it, object: TypeToken<List<Int>>(){}.type) } ?: default
}
fun HashMap<String, String?>.getLongList(key: String, default: List<Long>?): List<Long>? {
return this[key]?.let { gson.fromJson<List<Long>>(it, object: TypeToken<List<Long>>(){}.type) } ?: default
}
fun HashMap<String, String?>.getFloat(key: String): Float? {
return this[key]?.toFloatOrNull()
}
fun List<ConfigEntry>.toHashMap(profileId: Int, map: HashMap<String, String?>) {
map.clear()
forEach {
if (it.profileId == profileId)
map[it.key] = it.value
}
}

View File

@ -1,45 +0,0 @@
/*
* Copyright (c) Kuba Szczodrzyński 2019-12-2.
*/
package pl.szczodrzynski.edziennik.config.utils
import com.google.gson.Gson
import com.google.gson.JsonParser
import pl.szczodrzynski.edziennik.ext.getInt
import pl.szczodrzynski.edziennik.ui.home.HomeCardModel
import pl.szczodrzynski.edziennik.utils.models.Time
class ConfigGsonUtils {
@Suppress("UNCHECKED_CAST")
fun <T> deserializeList(gson: Gson, str: String?, classOfT: Class<T>): List<T> {
val json = JsonParser.parseString(str)
val list: MutableList<T> = mutableListOf()
if (!json.isJsonArray)
return list
json.asJsonArray.forEach { e ->
when (classOfT) {
String::class.java -> {
list += e.asString as T
}
HomeCardModel::class.java -> {
val o = e.asJsonObject
list += HomeCardModel(
o.getInt("profileId", 0),
o.getInt("cardId", 0)
) as T
}
Time::class.java -> {
val o = e.asJsonObject
list += Time(
o.getInt("hour", 0),
o.getInt("minute", 0),
o.getInt("second", 0)
) as T
}
}
}
return list
}
}

View File

@ -5,12 +5,9 @@
package pl.szczodrzynski.edziennik.config.utils package pl.szczodrzynski.edziennik.config.utils
import android.content.Context import android.content.Context
import androidx.core.content.edit
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.BuildConfig
import pl.szczodrzynski.edziennik.MainActivity
import pl.szczodrzynski.edziennik.config.Config import pl.szczodrzynski.edziennik.config.Config
import pl.szczodrzynski.edziennik.ext.HOUR
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.ORDER_BY_DATE_DESC
import pl.szczodrzynski.edziennik.utils.models.Time import pl.szczodrzynski.edziennik.utils.models.Time
import kotlin.math.abs import kotlin.math.abs
@ -22,74 +19,14 @@ class ConfigMigration(app: App, config: Config) {
// migrate appConfig from app version 3.x and lower. // migrate appConfig from app version 3.x and lower.
// Updates dataVersion to level 2. // Updates dataVersion to level 2.
AppConfigMigrationV3(p, config) AppConfigMigrationV3(p, config)
p.edit {
remove("app.appConfig.appTheme")
} }
if (dataVersion < 2) {
appVersion = BuildConfig.VERSION_CODE
loginFinished = false
ui.language = null
ui.theme = 1
ui.appBackground = null
ui.headerBackground = null
ui.miniMenuVisible = false
ui.miniMenuButtons = listOf(
MainActivity.DRAWER_ITEM_HOME,
MainActivity.DRAWER_ITEM_TIMETABLE,
MainActivity.DRAWER_ITEM_AGENDA,
MainActivity.DRAWER_ITEM_GRADES,
MainActivity.DRAWER_ITEM_MESSAGES,
MainActivity.DRAWER_ITEM_HOMEWORK,
MainActivity.DRAWER_ITEM_SETTINGS
)
sync.enabled = true
sync.interval = 1* HOUR.toInt()
sync.notifyAboutUpdates = true
sync.onlyWifi = false
sync.quietHoursEnabled = false
sync.quietHoursStart = null
sync.quietHoursEnd = null
sync.quietDuringLessons = false
sync.tokenApp = null
sync.tokenMobidziennik = null
sync.tokenMobidziennikList = listOf()
sync.tokenLibrus = null
sync.tokenLibrusList = listOf()
sync.tokenVulcan = null
sync.tokenVulcanList = listOf()
timetable.bellSyncMultiplier = 0
timetable.bellSyncDiff = null
timetable.countInSeconds = false
grades.orderBy = ORDER_BY_DATE_DESC
dataVersion = 2
}
if (dataVersion < 3) {
update = null
privacyPolicyAccepted = false
devMode = null
devModePassword = null
appInstalledTime = 0L
appRateSnackbarTime = 0L
dataVersion = 3
}
if (dataVersion < 10) {
ui.openDrawerOnBackPressed = false
ui.snowfall = false
ui.bottomSheetOpened = false
sync.dontShowAppManagerDialog = false
sync.webPushEnabled = true
sync.lastAppSync = 0L
dataVersion = 10
} }
if (dataVersion < 11) { if (dataVersion < 11) {
val startMillis = config.values.get("quietHoursStart", 0L) val startMillis = config.values["quietHoursStart"]?.toLongOrNull() ?: 0L
val endMillis = config.values.get("quietHoursEnd", 0L) val endMillis = config.values["quietHoursEnd"]?.toLongOrNull() ?: 0L
if (startMillis > 0) { if (startMillis > 0) {
try { try {
sync.quietHoursStart = Time.fromMillis(abs(startMillis)) sync.quietHoursStart = Time.fromMillis(abs(startMillis))
@ -106,5 +43,7 @@ class ConfigMigration(app: App, config: Config) {
dataVersion = 11 dataVersion = 11
} }
hash = "invalid"
}} }}
} }

View File

@ -5,8 +5,9 @@
package pl.szczodrzynski.edziennik.config.utils package pl.szczodrzynski.edziennik.config.utils
import pl.szczodrzynski.edziennik.config.ProfileConfig import pl.szczodrzynski.edziennik.config.ProfileConfig
import pl.szczodrzynski.edziennik.data.db.entity.Notification
import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.AGENDA_DEFAULT import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.AGENDA_DEFAULT
import pl.szczodrzynski.edziennik.data.db.enums.NotificationType
import pl.szczodrzynski.edziennik.data.db.enums.SchoolType
import pl.szczodrzynski.edziennik.ui.home.HomeCard import pl.szczodrzynski.edziennik.ui.home.HomeCard
import pl.szczodrzynski.edziennik.ui.home.HomeCardModel import pl.szczodrzynski.edziennik.ui.home.HomeCardModel
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.COLOR_MODE_WEIGHTED import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.COLOR_MODE_WEIGHTED
@ -15,35 +16,46 @@ import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.YEAR_AL
class ProfileConfigMigration(config: ProfileConfig) { class ProfileConfigMigration(config: ProfileConfig) {
init { config.apply { init { config.apply {
if (dataVersion < 1) { val profile = db.profileDao().getByIdNow(profileId ?: -1)
grades.colorMode = COLOR_MODE_WEIGHTED
grades.yearAverageMode = YEAR_ALL_GRADES
grades.hideImproved = false
grades.averageWithoutWeight = true
grades.plusValue = null
grades.minusValue = null
grades.dontCountEnabled = false
grades.dontCountGrades = listOf()
ui.agendaViewType = AGENDA_DEFAULT
// no migration for ui.homeCards
dataVersion = 1
}
if (dataVersion < 2) { if (dataVersion < 2) {
sync.notificationFilter = sync.notificationFilter + Notification.TYPE_TEACHER_ABSENCE sync.notificationFilter = sync.notificationFilter + NotificationType.TEACHER_ABSENCE
dataVersion = 2 dataVersion = 2
} }
if (dataVersion < 3) { if (dataVersion < 3) {
if (ui.homeCards.isNotEmpty()) { if (ui.homeCards.isNotEmpty()) {
ui.homeCards = ui.homeCards.toMutableList().also { ui.homeCards = ui.homeCards + HomeCardModel(
it.add(HomeCardModel(config.profileId, HomeCard.CARD_NOTES)) profileId = config.profileId ?: -1,
} cardId = HomeCard.CARD_NOTES,
)
} }
dataVersion = 3 dataVersion = 3
} }
if (dataVersion < 4) {
// switch to new event types (USOS)
dataVersion = 4
if (profile?.loginStoreType?.schoolType == SchoolType.UNIVERSITY) {
db.eventTypeDao().clear(profileId ?: -1)
db.eventTypeDao().addDefaultTypes(profile)
}
}
if (dataVersion < 5) {
// update USOS event types and the appropriate events (2022-12-25)
dataVersion = 5
if (profile?.loginStoreType?.schoolType == SchoolType.UNIVERSITY) {
db.eventTypeDao().getAllWithDefaults(profile)
// wejściówka (4) -> kartkówka (3)
db.eventDao().getRawNow("UPDATE events SET eventType = 3 WHERE profileId = $profileId AND eventType = 4;")
// zadanie (6) -> zadanie domowe (-1)
db.eventDao().getRawNow("UPDATE events SET eventType = -1 WHERE profileId = $profileId AND eventType = 6;")
}
}
}} }}
} }

View File

@ -84,19 +84,21 @@ class ApiService : Service() {
runTask() runTask()
} }
override fun onRequiresUserAction(event: UserActionRequiredEvent) {
app.userActionManager.sendToUser(event)
taskRunning?.cancel()
clearTask()
runTask()
}
override fun onError(apiError: ApiError) { override fun onError(apiError: ApiError) {
lastEventTime = System.currentTimeMillis() lastEventTime = System.currentTimeMillis()
d(TAG, "Task $taskRunningId threw an error - $apiError") d(TAG, "Task $taskRunningId threw an error - $apiError")
apiError.profileId = taskProfileId apiError.profileId = taskProfileId
if (app.userActionManager.requiresUserAction(apiError)) {
app.userActionManager.sendToUser(apiError)
}
else {
EventBus.getDefault().postSticky(ApiTaskErrorEvent(apiError)) EventBus.getDefault().postSticky(ApiTaskErrorEvent(apiError))
errorList.add(apiError) errorList.add(apiError)
apiError.throwable?.printStackTrace() apiError.throwable?.printStackTrace()
}
if (apiError.isCritical) { if (apiError.isCritical) {
taskRunning?.cancel() taskRunning?.cancel()

View File

@ -26,9 +26,10 @@ val LIBRUS_USER_AGENT = "${SYSTEM_USER_AGENT}LibrusMobileApp"
const val SYNERGIA_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Gecko/20100101 Firefox/62.0" const val SYNERGIA_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Gecko/20100101 Firefox/62.0"
const val LIBRUS_CLIENT_ID = "VaItV6oRutdo8fnjJwysnTjVlvaswf52ZqmXsJGP" const val LIBRUS_CLIENT_ID = "VaItV6oRutdo8fnjJwysnTjVlvaswf52ZqmXsJGP"
const val LIBRUS_REDIRECT_URL = "app://librus" const val LIBRUS_REDIRECT_URL = "app://librus"
const val LIBRUS_AUTHORIZE_URL = "https://portal.librus.pl/oauth2/authorize?client_id=$LIBRUS_CLIENT_ID&redirect_uri=$LIBRUS_REDIRECT_URL&response_type=code" const val LIBRUS_AUTHORIZE_URL = "https://portal.librus.pl/konto-librus/redirect/dru"
const val LIBRUS_LOGIN_URL = "https://portal.librus.pl/rodzina/login/action" const val LIBRUS_LOGIN_URL = "https://portal.librus.pl/konto-librus/login/action"
const val LIBRUS_TOKEN_URL = "https://portal.librus.pl/oauth2/access_token" const val LIBRUS_TOKEN_URL = "https://portal.librus.pl/oauth2/access_token"
const val LIBRUS_HEADER = "pl.librus.synergiaDru2"
const val LIBRUS_ACCOUNT_URL = "/v3/SynergiaAccounts/fresh/" // + login const val LIBRUS_ACCOUNT_URL = "/v3/SynergiaAccounts/fresh/" // + login
const val LIBRUS_ACCOUNTS_URL = "/v3/SynergiaAccounts" const val LIBRUS_ACCOUNTS_URL = "/v3/SynergiaAccounts"
@ -99,3 +100,12 @@ const val PODLASIE_API_VERSION = "1.0.62"
const val PODLASIE_API_URL = "https://cpdklaser.zeto.bialystok.pl/api" const val PODLASIE_API_URL = "https://cpdklaser.zeto.bialystok.pl/api"
const val PODLASIE_API_USER_ENDPOINT = "/pobierzDaneUcznia" const val PODLASIE_API_USER_ENDPOINT = "/pobierzDaneUcznia"
const val PODLASIE_API_LOGOUT_DEVICES_ENDPOINT = "/wyczyscUrzadzenia" const val PODLASIE_API_LOGOUT_DEVICES_ENDPOINT = "/wyczyscUrzadzenia"
const val USOS_API_OAUTH_REDIRECT_URL = "szkolny://redirect/usos"
val USOS_API_SCOPES by lazy { listOf(
"offline_access",
"studies",
"grades",
"events",
) }

View File

@ -2,115 +2,116 @@ package pl.szczodrzynski.edziennik.data.api
import pl.szczodrzynski.edziennik.data.api.models.Data import pl.szczodrzynski.edziennik.data.api.models.Data
import pl.szczodrzynski.edziennik.data.api.models.Feature import pl.szczodrzynski.edziennik.data.api.models.Feature
import pl.szczodrzynski.edziennik.data.api.models.LoginMethod
import pl.szczodrzynski.edziennik.data.db.entity.EndpointTimer import pl.szczodrzynski.edziennik.data.db.entity.EndpointTimer
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_NEVER import pl.szczodrzynski.edziennik.data.db.entity.SYNC_NEVER
import pl.szczodrzynski.edziennik.data.db.enums.FeatureType
import pl.szczodrzynski.edziennik.data.db.enums.LoginMethod
import pl.szczodrzynski.edziennik.ext.getFeatureTypesNecessary
import pl.szczodrzynski.edziennik.ext.getFeatureTypesUnnecessary
import pl.szczodrzynski.edziennik.ext.isNotNullNorEmpty
fun Data.prepare(loginMethods: List<LoginMethod>, features: List<Feature>, featureIds: List<Int>, viewId: Int?, onlyEndpoints: List<Int>?) { fun Data.prepare(
val data = this features: List<Feature>,
featureTypes: Set<FeatureType>?,
val possibleLoginMethods = data.loginMethods.toMutableList() onlyEndpoints: Set<Int>?,
) {
for (loginMethod in loginMethods) { val loginType = this.loginStore.type
if (loginMethod.isPossible(profile, loginStore)) val possibleLoginMethods = this.loginMethods.toMutableList()
possibleLoginMethods += loginMethod.loginMethodId possibleLoginMethods += LoginMethod.values().filter {
it.loginType == loginType && it.isPossible?.invoke(profile, loginStore) != false
} }
//var highestLoginMethod = 0 //var highestLoginMethod = 0
var endpointList = mutableListOf<Feature>() var possibleFeatures = mutableListOf<Feature>()
val requiredLoginMethods = mutableListOf<Int>() val requiredLoginMethods = mutableListOf<LoginMethod>()
data.targetEndpointIds.clear() val syncFeatureTypes = when {
data.targetLoginMethodIds.clear() featureTypes.isNotNullNorEmpty() -> featureTypes!!
else -> getFeatureTypesUnnecessary()
} + getFeatureTypesNecessary()
val forceFeatureType = featureTypes?.singleOrNull()
this.targetEndpoints.clear()
this.targetLoginMethods.clear()
// get all endpoints for every feature, only if possible to login and possible/necessary to sync // get all endpoints for every feature, only if possible to login and possible/necessary to sync
for (featureId in featureIds) { for (featureId in syncFeatureTypes) {
features.filter { possibleFeatures += features.filter {
it.featureId == featureId // feature ID matches it.featureType == featureId // feature ID matches
&& possibleLoginMethods.containsAll(it.requiredLoginMethods) // is possible to login && possibleLoginMethods.containsAll(it.requiredLoginMethods) // is possible to login
&& it.shouldSync?.invoke(data) ?: true // is necessary/possible to sync && it.shouldSync?.invoke(this) ?: true // is necessary/possible to sync
}.let {
endpointList.addAll(it)
} }
} }
val timestamp = System.currentTimeMillis() val timestamp = System.currentTimeMillis()
endpointList = endpointList possibleFeatures = possibleFeatures
// sort the endpoint list by feature ID and priority // sort the endpoint list by feature ID and priority
.sortedWith(compareBy(Feature::featureId, Feature::priority)) .sortedWith(compareBy(Feature::featureType, Feature::priority))
// select only the most important endpoint for each feature // select only the most important endpoint for each feature
.distinctBy { it.featureId } .distinctBy { it.featureType }
.toMutableList() .toMutableList()
for (feature in possibleFeatures) {
// add all endpoint IDs and required login methods, filtering using timers // add all endpoint IDs and required login methods, filtering using timers
.onEach { feature -> feature.endpoints.forEach { endpoint ->
feature.endpointIds.forEach { endpoint ->
if (onlyEndpoints?.contains(endpoint.first) == false) if (onlyEndpoints?.contains(endpoint.first) == false)
return@forEach return@forEach
(data.endpointTimers val timer = this.endpointTimers
.singleOrNull { it.endpointId == endpoint.first } ?: EndpointTimer(data.profile?.id .singleOrNull { it.endpointId == endpoint.first }
?: -1, endpoint.first)) ?: EndpointTimer(this.profileId, endpoint.first)
.let { timer ->
if ( if (
onlyEndpoints?.contains(endpoint.first) == true || onlyEndpoints?.contains(endpoint.first) == true ||
timer.nextSync == SYNC_ALWAYS || timer.nextSync == SYNC_ALWAYS ||
viewId != null && timer.viewId == viewId || forceFeatureType != null && timer.featureType == forceFeatureType ||
timer.nextSync != SYNC_NEVER && timer.nextSync < timestamp timer.nextSync != SYNC_NEVER && timer.nextSync < timestamp
) { ) {
data.targetEndpointIds[endpoint.first] = timer.lastSync this.targetEndpoints[endpoint.first] = timer.lastSync
requiredLoginMethods.add(endpoint.second) requiredLoginMethods += endpoint.second
}
} }
} }
} }
// check every login method for any dependencies // check every login method for any dependencies
for (loginMethodId in requiredLoginMethods) { for (loginMethod in requiredLoginMethods) {
var requiredLoginMethod: Int? = loginMethodId var requiredLoginMethod: LoginMethod? = loginMethod
while (requiredLoginMethod != LOGIN_METHOD_NOT_NEEDED) { while (requiredLoginMethod != null) {
loginMethods.singleOrNull { it.loginMethodId == requiredLoginMethod }?.let { loginMethod -> this.targetLoginMethods += requiredLoginMethod
if (requiredLoginMethod != null) requiredLoginMethod = requiredLoginMethod.requiredLoginMethod?.invoke(this.profile, this.loginStore)
data.targetLoginMethodIds.add(requiredLoginMethod!!)
requiredLoginMethod = loginMethod.requiredLoginMethod(data.profile, data.loginStore)
}
} }
} }
// sort and distinct every login method and endpoint // sort and distinct every login method and endpoint
data.targetLoginMethodIds = data.targetLoginMethodIds.toHashSet().toMutableList() this.targetLoginMethods = this.targetLoginMethods.toHashSet().toMutableList()
data.targetLoginMethodIds.sort() this.targetLoginMethods.sort()
//data.targetEndpointIds = data.targetEndpointIds.toHashSet().toMutableList() //data.targetEndpointIds = data.targetEndpointIds.toHashSet().toMutableList()
//data.targetEndpointIds.sort() //data.targetEndpointIds.sort()
progressCount = targetLoginMethodIds.size + targetEndpointIds.size progressCount = targetLoginMethods.size + targetEndpoints.size
progressStep = if (progressCount <= 0) 0f else 100f / progressCount.toFloat() progressStep = if (progressCount <= 0) 0f else 100f / progressCount.toFloat()
} }
fun Data.prepareFor(loginMethods: List<LoginMethod>, loginMethodId: Int) { fun Data.prepareFor(loginMethod: LoginMethod) {
val loginType = loginStore.type
val possibleLoginMethods = this.loginMethods.toMutableList() val possibleLoginMethods = this.loginMethods.toMutableList()
possibleLoginMethods += LoginMethod.values().filter {
loginMethods.forEach { it.loginType == loginType && it.isPossible?.invoke(profile, loginStore) != false
if (it.isPossible(profile, loginStore))
possibleLoginMethods += it.loginMethodId
} }
targetLoginMethodIds.clear() this.targetLoginMethods.clear()
// check the login method for any dependencies // check the login method for any dependencies
var requiredLoginMethod: Int? = loginMethodId var requiredLoginMethod: LoginMethod? = loginMethod
while (requiredLoginMethod != LOGIN_METHOD_NOT_NEEDED) { while (requiredLoginMethod != null) {
loginMethods.singleOrNull { it.loginMethodId == requiredLoginMethod }?.let { this.targetLoginMethods += requiredLoginMethod
if (requiredLoginMethod != null) requiredLoginMethod = requiredLoginMethod.requiredLoginMethod?.invoke(this.profile, this.loginStore)
targetLoginMethodIds.add(requiredLoginMethod!!)
requiredLoginMethod = it.requiredLoginMethod(profile, loginStore)
}
} }
// sort and distinct every login method // sort and distinct every login method
targetLoginMethodIds = targetLoginMethodIds.toHashSet().toMutableList() this.targetLoginMethods = this.targetLoginMethods.toHashSet().toMutableList()
targetLoginMethodIds.sort() this.targetLoginMethods.sort()
progressCount = 0 progressCount = 0
progressStep = 0f progressStep = 0f

View File

@ -58,11 +58,7 @@ const val ERROR_INVALID_LOGIN_MODE = 110
const val ERROR_LOGIN_METHOD_NOT_SATISFIED = 111 const val ERROR_LOGIN_METHOD_NOT_SATISFIED = 111
const val ERROR_NOT_IMPLEMENTED = 112 const val ERROR_NOT_IMPLEMENTED = 112
const val ERROR_FILE_DOWNLOAD = 113 const val ERROR_FILE_DOWNLOAD = 113
const val ERROR_REQUIRES_USER_ACTION = 114
const val ERROR_NO_STUDENTS_IN_ACCOUNT = 115
const val ERROR_CAPTCHA_NEEDED = 3000
const val ERROR_CAPTCHA_LIBRUS_PORTAL = 3001
const val ERROR_API_PDO_ERROR = 5000 const val ERROR_API_PDO_ERROR = 5000
const val ERROR_API_INVALID_CLIENT = 5001 const val ERROR_API_INVALID_CLIENT = 5001
@ -204,6 +200,12 @@ const val ERROR_PODLASIE_API_NO_TOKEN = 630
const val ERROR_PODLASIE_API_OTHER = 631 const val ERROR_PODLASIE_API_OTHER = 631
const val ERROR_PODLASIE_API_DATA_MISSING = 632 const val ERROR_PODLASIE_API_DATA_MISSING = 632
const val ERROR_USOS_OAUTH_GOT_DIFFERENT_TOKEN = 702
const val ERROR_USOS_OAUTH_INCOMPLETE_RESPONSE = 703
const val ERROR_USOS_NO_STUDENT_PROGRAMMES = 704
const val ERROR_USOS_API_INCOMPLETE_RESPONSE = 705
const val ERROR_USOS_API_MISSING_RESPONSE = 706
const val ERROR_TEMPLATE_WEB_OTHER = 801 const val ERROR_TEMPLATE_WEB_OTHER = 801
const val EXCEPTION_API_TASK = 900 const val EXCEPTION_API_TASK = 900

View File

@ -1,86 +0,0 @@
/*
* Copyright (c) Kuba Szczodrzyński 2019-9-29.
*/
package pl.szczodrzynski.edziennik.data.api
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_HOME
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.data.db.entity.Message.Companion.TYPE_RECEIVED
import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT
internal const val FEATURE_TIMETABLE = 1
internal const val FEATURE_AGENDA = 2
internal const val FEATURE_GRADES = 3
internal const val FEATURE_HOMEWORK = 4
internal const val FEATURE_BEHAVIOUR = 5
internal const val FEATURE_ATTENDANCE = 6
internal const val FEATURE_MESSAGES_INBOX = 7
internal const val FEATURE_MESSAGES_SENT = 8
internal const val FEATURE_ANNOUNCEMENTS = 9
internal const val FEATURE_ALWAYS_NEEDED = 100
internal const val FEATURE_STUDENT_INFO = 101
internal const val FEATURE_STUDENT_NUMBER = 109
internal const val FEATURE_SCHOOL_INFO = 102
internal const val FEATURE_CLASS_INFO = 103
internal const val FEATURE_TEAM_INFO = 104
internal const val FEATURE_LUCKY_NUMBER = 105
internal const val FEATURE_TEACHERS = 106
internal const val FEATURE_SUBJECTS = 107
internal const val FEATURE_CLASSROOMS = 108
internal const val FEATURE_PUSH_CONFIG = 120
object Features {
private fun getAllNecessary(): List<Int> = listOf(
FEATURE_ALWAYS_NEEDED,
FEATURE_PUSH_CONFIG,
FEATURE_STUDENT_INFO,
FEATURE_STUDENT_NUMBER,
FEATURE_SCHOOL_INFO,
FEATURE_CLASS_INFO,
FEATURE_TEAM_INFO,
FEATURE_LUCKY_NUMBER,
FEATURE_TEACHERS,
FEATURE_SUBJECTS,
FEATURE_CLASSROOMS)
private fun getAllFeatures(): List<Int> = listOf(
FEATURE_TIMETABLE,
FEATURE_AGENDA,
FEATURE_GRADES,
FEATURE_HOMEWORK,
FEATURE_BEHAVIOUR,
FEATURE_ATTENDANCE,
FEATURE_MESSAGES_INBOX,
FEATURE_MESSAGES_SENT,
FEATURE_ANNOUNCEMENTS)
fun getAllIds(): List<Int> = getAllFeatures() + getAllNecessary()
fun getIdsByView(targetId: Int, targetType: Int): List<Int> {
return (when (targetId) {
DRAWER_ITEM_HOME -> getAllFeatures()
DRAWER_ITEM_TIMETABLE -> listOf(FEATURE_TIMETABLE)
DRAWER_ITEM_AGENDA -> listOf(FEATURE_AGENDA)
DRAWER_ITEM_GRADES -> listOf(FEATURE_GRADES)
DRAWER_ITEM_MESSAGES -> when (targetType) {
TYPE_RECEIVED -> listOf(FEATURE_MESSAGES_INBOX)
TYPE_SENT -> listOf(FEATURE_MESSAGES_SENT)
else -> listOf(FEATURE_MESSAGES_INBOX, FEATURE_MESSAGES_SENT)
}
DRAWER_ITEM_HOMEWORK -> listOf(FEATURE_HOMEWORK)
DRAWER_ITEM_BEHAVIOUR -> listOf(FEATURE_BEHAVIOUR)
DRAWER_ITEM_ATTENDANCE -> listOf(FEATURE_ATTENDANCE)
DRAWER_ITEM_ANNOUNCEMENTS -> listOf(FEATURE_ANNOUNCEMENTS)
else -> getAllFeatures()
} + getAllNecessary()).sorted()
}
}

View File

@ -1,138 +0,0 @@
/*
* Copyright (c) Kuba Szczodrzyński 2019-9-20.
*/
package pl.szczodrzynski.edziennik.data.api
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLoginApi
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLoginMessages
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLoginPortal
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLoginSynergia
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.login.MobidziennikLoginApi2
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.login.MobidziennikLoginWeb
import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.login.PodlasieLoginApi
import pl.szczodrzynski.edziennik.data.api.edziennik.template.login.TemplateLoginApi
import pl.szczodrzynski.edziennik.data.api.edziennik.template.login.TemplateLoginWeb
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLoginHebe
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLoginWebMain
import pl.szczodrzynski.edziennik.data.api.models.LoginMethod
// librus
// mobidziennik
// idziennik [*]
// vulcan
// mobireg
const val SYNERGIA_API_ENABLED = false
// the graveyard
const val LOGIN_TYPE_IDZIENNIK = 3
const val LOGIN_TYPE_EDUDZIENNIK = 5
const val LOGIN_TYPE_TEMPLATE = 21
// LOGIN MODES
const val LOGIN_MODE_TEMPLATE_WEB = 0
// LOGIN METHODS
const val LOGIN_METHOD_NOT_NEEDED = -1
const val LOGIN_METHOD_TEMPLATE_WEB = 100
const val LOGIN_METHOD_TEMPLATE_API = 200
const val LOGIN_TYPE_LIBRUS = 2
const val LOGIN_MODE_LIBRUS_EMAIL = 0
const val LOGIN_MODE_LIBRUS_SYNERGIA = 1
const val LOGIN_MODE_LIBRUS_JST = 2
const val LOGIN_METHOD_LIBRUS_PORTAL = 100
const val LOGIN_METHOD_LIBRUS_API = 200
const val LOGIN_METHOD_LIBRUS_SYNERGIA = 300
const val LOGIN_METHOD_LIBRUS_MESSAGES = 400
val librusLoginMethods = listOf(
LoginMethod(LOGIN_TYPE_LIBRUS, LOGIN_METHOD_LIBRUS_PORTAL, LibrusLoginPortal::class.java)
.withIsPossible { _, loginStore ->
loginStore.mode == LOGIN_MODE_LIBRUS_EMAIL
}
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_NOT_NEEDED },
LoginMethod(LOGIN_TYPE_LIBRUS, LOGIN_METHOD_LIBRUS_API, LibrusLoginApi::class.java)
.withIsPossible { _, loginStore ->
loginStore.mode != LOGIN_MODE_LIBRUS_SYNERGIA || SYNERGIA_API_ENABLED
}
.withRequiredLoginMethod { _, loginStore ->
if (loginStore.mode == LOGIN_MODE_LIBRUS_EMAIL) LOGIN_METHOD_LIBRUS_PORTAL else LOGIN_METHOD_NOT_NEEDED
},
LoginMethod(LOGIN_TYPE_LIBRUS, LOGIN_METHOD_LIBRUS_SYNERGIA, LibrusLoginSynergia::class.java)
.withIsPossible { _, loginStore -> !loginStore.hasLoginData("fakeLogin") }
.withRequiredLoginMethod { profile, _ ->
if (profile?.hasStudentData("accountPassword") == false || true) LOGIN_METHOD_LIBRUS_API else LOGIN_METHOD_NOT_NEEDED
},
LoginMethod(LOGIN_TYPE_LIBRUS, LOGIN_METHOD_LIBRUS_MESSAGES, LibrusLoginMessages::class.java)
.withIsPossible { _, loginStore -> !loginStore.hasLoginData("fakeLogin") }
.withRequiredLoginMethod { profile, _ ->
if (profile?.hasStudentData("accountPassword") == false || true) LOGIN_METHOD_LIBRUS_SYNERGIA else LOGIN_METHOD_NOT_NEEDED
}
)
const val LOGIN_TYPE_MOBIDZIENNIK = 1
const val LOGIN_MODE_MOBIDZIENNIK_WEB = 0
const val LOGIN_METHOD_MOBIDZIENNIK_WEB = 100
const val LOGIN_METHOD_MOBIDZIENNIK_API2 = 300
val mobidziennikLoginMethods = listOf(
LoginMethod(LOGIN_TYPE_MOBIDZIENNIK, LOGIN_METHOD_MOBIDZIENNIK_WEB, MobidziennikLoginWeb::class.java)
.withIsPossible { _, _ -> true }
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_NOT_NEEDED },
LoginMethod(LOGIN_TYPE_MOBIDZIENNIK, LOGIN_METHOD_MOBIDZIENNIK_API2, MobidziennikLoginApi2::class.java)
.withIsPossible { profile, _ -> profile?.getStudentData("email", null) != null }
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_NOT_NEEDED }
)
const val LOGIN_TYPE_VULCAN = 4
const val LOGIN_MODE_VULCAN_API = 0
const val LOGIN_MODE_VULCAN_WEB = 1
const val LOGIN_MODE_VULCAN_HEBE = 2
const val LOGIN_METHOD_VULCAN_WEB_MAIN = 100
const val LOGIN_METHOD_VULCAN_WEB_NEW = 200
const val LOGIN_METHOD_VULCAN_WEB_OLD = 300
const val LOGIN_METHOD_VULCAN_WEB_MESSAGES = 400
const val LOGIN_METHOD_VULCAN_HEBE = 600
val vulcanLoginMethods = listOf(
LoginMethod(LOGIN_TYPE_VULCAN, LOGIN_METHOD_VULCAN_WEB_MAIN, VulcanLoginWebMain::class.java)
.withIsPossible { _, loginStore -> loginStore.hasLoginData("webHost") }
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_NOT_NEEDED },
/*LoginMethod(LOGIN_TYPE_VULCAN, LOGIN_METHOD_VULCAN_WEB_NEW, VulcanLoginWebNew::class.java)
.withIsPossible { _, _ -> false }
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_VULCAN_WEB_MAIN },
LoginMethod(LOGIN_TYPE_VULCAN, LOGIN_METHOD_VULCAN_WEB_OLD, VulcanLoginWebOld::class.java)
.withIsPossible { _, _ -> false }
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_VULCAN_WEB_MAIN },*/
LoginMethod(LOGIN_TYPE_VULCAN, LOGIN_METHOD_VULCAN_HEBE, VulcanLoginHebe::class.java)
.withIsPossible { _, loginStore ->
loginStore.mode != LOGIN_MODE_VULCAN_API
}
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_NOT_NEEDED }
)
const val LOGIN_TYPE_PODLASIE = 6
const val LOGIN_MODE_PODLASIE_API = 0
const val LOGIN_METHOD_PODLASIE_API = 100
val podlasieLoginMethods = listOf(
LoginMethod(LOGIN_TYPE_PODLASIE, LOGIN_METHOD_PODLASIE_API, PodlasieLoginApi::class.java)
.withIsPossible { _, _ -> true }
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_NOT_NEEDED }
)
val templateLoginMethods = listOf(
LoginMethod(LOGIN_TYPE_TEMPLATE, LOGIN_METHOD_TEMPLATE_WEB, TemplateLoginWeb::class.java)
.withIsPossible { _, _ -> true }
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_NOT_NEEDED },
LoginMethod(LOGIN_TYPE_TEMPLATE, LOGIN_METHOD_TEMPLATE_API, TemplateLoginApi::class.java)
.withIsPossible { _, _ -> true }
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_TEMPLATE_WEB }
)

View File

@ -24,6 +24,25 @@ object Regexes {
"""^\[META:([A-z0-9-&=]+)]""".toRegex() """^\[META:([A-z0-9-&=]+)]""".toRegex()
} }
val HTML_INPUT_HIDDEN by lazy {
"""<input .*?type="hidden".+?>""".toRegex()
}
val HTML_INPUT_NAME by lazy {
"""name="(.+?)"""".toRegex()
}
val HTML_INPUT_VALUE by lazy {
"""value="(.+?)"""".toRegex()
}
val HTML_CSRF_TOKEN by lazy {
"""name="csrf-token" content="([A-z0-9=+/\-_]+?)"""".toRegex()
}
val HTML_FORM_ACTION by lazy {
"""<form .*?action="(.+?)"""".toRegex()
}
val HTML_RECAPTCHA_KEY by lazy {
"""data-sitekey="(.+?)"""".toRegex()
}
val MOBIDZIENNIK_GRADES_SUBJECT_NAME by lazy { val MOBIDZIENNIK_GRADES_SUBJECT_NAME by lazy {

View File

@ -6,12 +6,14 @@ package pl.szczodrzynski.edziennik.data.api.edziennik
import com.google.gson.JsonObject import com.google.gson.JsonObject
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.data.api.* import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.ERROR_PROFILE_ARCHIVED
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.Librus import pl.szczodrzynski.edziennik.data.api.edziennik.librus.Librus
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.Mobidziennik import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.Mobidziennik
import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.Podlasie import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.Podlasie
import pl.szczodrzynski.edziennik.data.api.edziennik.template.Template import pl.szczodrzynski.edziennik.data.api.edziennik.template.Template
import pl.szczodrzynski.edziennik.data.api.edziennik.usos.Usos
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.Vulcan import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.Vulcan
import pl.szczodrzynski.edziennik.data.api.events.RegisterAvailabilityEvent import pl.szczodrzynski.edziennik.data.api.events.RegisterAvailabilityEvent
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
@ -21,9 +23,13 @@ import pl.szczodrzynski.edziennik.data.api.task.IApiTask
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
import pl.szczodrzynski.edziennik.data.db.entity.Profile import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.db.entity.Teacher import pl.szczodrzynski.edziennik.data.db.entity.Teacher
import pl.szczodrzynski.edziennik.data.db.enums.FeatureType
import pl.szczodrzynski.edziennik.data.db.enums.LoginType
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
import pl.szczodrzynski.edziennik.data.db.full.EventFull import pl.szczodrzynski.edziennik.data.db.full.EventFull
import pl.szczodrzynski.edziennik.data.db.full.MessageFull import pl.szczodrzynski.edziennik.data.db.full.MessageFull
import pl.szczodrzynski.edziennik.ext.isBeforeYear
import pl.szczodrzynski.edziennik.ext.shouldArchive
import pl.szczodrzynski.edziennik.utils.Utils.d import pl.szczodrzynski.edziennik.utils.Utils.d
import pl.szczodrzynski.edziennik.utils.managers.AvailabilityManager.Error.Type import pl.szczodrzynski.edziennik.utils.managers.AvailabilityManager.Error.Type
@ -36,10 +42,10 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
fun firstLogin(loginStore: LoginStore) = EdziennikTask(-1, FirstLoginRequest(loginStore)) fun firstLogin(loginStore: LoginStore) = EdziennikTask(-1, FirstLoginRequest(loginStore))
fun sync() = EdziennikTask(-1, SyncRequest()) fun sync() = EdziennikTask(-1, SyncRequest())
fun syncProfile(profileId: Int, viewIds: List<Pair<Int, Int>>? = null, onlyEndpoints: List<Int>? = null, arguments: JsonObject? = null) = EdziennikTask(profileId, SyncProfileRequest(viewIds, onlyEndpoints, arguments)) fun syncProfile(profileId: Int, featureTypes: Set<FeatureType>? = null, onlyEndpoints: Set<Int>? = null, arguments: JsonObject? = null) = EdziennikTask(profileId, SyncProfileRequest(featureTypes, onlyEndpoints, arguments))
fun syncProfileList(profileList: List<Int>) = EdziennikTask(-1, SyncProfileListRequest(profileList)) fun syncProfileList(profileList: Set<Int>) = EdziennikTask(-1, SyncProfileListRequest(profileList))
fun messageGet(profileId: Int, message: MessageFull) = EdziennikTask(profileId, MessageGetRequest(message)) fun messageGet(profileId: Int, message: MessageFull) = EdziennikTask(profileId, MessageGetRequest(message))
fun messageSend(profileId: Int, recipients: List<Teacher>, subject: String, text: String) = EdziennikTask(profileId, MessageSendRequest(recipients, subject, text)) fun messageSend(profileId: Int, recipients: Set<Teacher>, subject: String, text: String) = EdziennikTask(profileId, MessageSendRequest(recipients, subject, text))
fun announcementsRead(profileId: Int) = EdziennikTask(profileId, AnnouncementsReadRequest()) fun announcementsRead(profileId: Int) = EdziennikTask(profileId, AnnouncementsReadRequest())
fun announcementGet(profileId: Int, announcement: AnnouncementFull) = EdziennikTask(profileId, AnnouncementGetRequest(announcement)) fun announcementGet(profileId: Int, announcement: AnnouncementFull) = EdziennikTask(profileId, AnnouncementGetRequest(announcement))
fun attachmentGet(profileId: Int, owner: Any, attachmentId: Long, attachmentName: String) = EdziennikTask(profileId, AttachmentGetRequest(owner, attachmentId, attachmentName)) fun attachmentGet(profileId: Int, owner: Any, attachmentId: Long, attachmentName: String) = EdziennikTask(profileId, AttachmentGetRequest(owner, attachmentId, attachmentName))
@ -108,11 +114,12 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
} }
edziennikInterface = when (loginStore.type) { edziennikInterface = when (loginStore.type) {
LOGIN_TYPE_LIBRUS -> Librus(app, profile, loginStore, taskCallback) LoginType.LIBRUS -> Librus(app, profile, loginStore, taskCallback)
LOGIN_TYPE_MOBIDZIENNIK -> Mobidziennik(app, profile, loginStore, taskCallback) LoginType.MOBIDZIENNIK -> Mobidziennik(app, profile, loginStore, taskCallback)
LOGIN_TYPE_VULCAN -> Vulcan(app, profile, loginStore, taskCallback) LoginType.VULCAN -> Vulcan(app, profile, loginStore, taskCallback)
LOGIN_TYPE_PODLASIE -> Podlasie(app, profile, loginStore, taskCallback) LoginType.PODLASIE -> Podlasie(app, profile, loginStore, taskCallback)
LOGIN_TYPE_TEMPLATE -> Template(app, profile, loginStore, taskCallback) LoginType.TEMPLATE -> Template(app, profile, loginStore, taskCallback)
LoginType.USOS -> Usos(app, profile, loginStore, taskCallback)
else -> null else -> null
} }
if (edziennikInterface == null) { if (edziennikInterface == null) {
@ -121,9 +128,7 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
when (request) { when (request) {
is SyncProfileRequest -> edziennikInterface?.sync( is SyncProfileRequest -> edziennikInterface?.sync(
featureIds = request.viewIds?.flatMap { Features.getIdsByView(it.first, it.second) } featureTypes = request.featureTypes,
?: Features.getAllIds(),
viewId = request.viewIds?.get(0)?.first,
onlyEndpoints = request.onlyEndpoints, onlyEndpoints = request.onlyEndpoints,
arguments = request.arguments) arguments = request.arguments)
is MessageGetRequest -> edziennikInterface?.getMessage(request.message) is MessageGetRequest -> edziennikInterface?.getMessage(request.message)
@ -148,10 +153,10 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
data class FirstLoginRequest(val loginStore: LoginStore) data class FirstLoginRequest(val loginStore: LoginStore)
class SyncRequest class SyncRequest
data class SyncProfileRequest(val viewIds: List<Pair<Int, Int>>? = null, val onlyEndpoints: List<Int>? = null, val arguments: JsonObject? = null) data class SyncProfileRequest(val featureTypes: Set<FeatureType>? = null, val onlyEndpoints: Set<Int>? = null, val arguments: JsonObject? = null)
data class SyncProfileListRequest(val profileList: List<Int>) data class SyncProfileListRequest(val profileList: Set<Int>)
data class MessageGetRequest(val message: MessageFull) data class MessageGetRequest(val message: MessageFull)
data class MessageSendRequest(val recipients: List<Teacher>, val subject: String, val text: String) data class MessageSendRequest(val recipients: Set<Teacher>, val subject: String, val text: String)
class AnnouncementsReadRequest class AnnouncementsReadRequest
data class AnnouncementGetRequest(val announcement: AnnouncementFull) data class AnnouncementGetRequest(val announcement: AnnouncementFull)
data class AttachmentGetRequest(val owner: Any, val attachmentId: Long, val attachmentName: String) data class AttachmentGetRequest(val owner: Any, val attachmentId: Long, val attachmentName: String)

View File

@ -6,8 +6,8 @@ package pl.szczodrzynski.edziennik.data.api.edziennik
import android.content.Intent import android.content.Intent
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.db.entity.Profile import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.db.enums.LoginType
import pl.szczodrzynski.edziennik.ext.Intent import pl.szczodrzynski.edziennik.ext.Intent
import pl.szczodrzynski.edziennik.utils.Utils.d import pl.szczodrzynski.edziennik.utils.Utils.d
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
@ -51,35 +51,32 @@ class ProfileArchiver(val app: App, val profile: Profile) {
d(TAG, "New profile ID for ${profile.name}: ${profile.id}") d(TAG, "New profile ID for ${profile.name}: ${profile.id}")
when (profile.loginStoreType) { when (profile.loginStoreType) {
LOGIN_TYPE_LIBRUS -> { LoginType.LIBRUS -> {
profile.removeStudentData("isPremium") profile.studentData.remove("isPremium")
profile.removeStudentData("pushDeviceId") profile.studentData.remove("pushDeviceId")
profile.removeStudentData("startPointsSemester1") profile.studentData.remove("startPointsSemester1")
profile.removeStudentData("startPointsSemester2") profile.studentData.remove("startPointsSemester2")
profile.removeStudentData("enablePointGrades") profile.studentData.remove("enablePointGrades")
profile.removeStudentData("enableDescriptiveGrades") profile.studentData.remove("enableDescriptiveGrades")
} }
LOGIN_TYPE_MOBIDZIENNIK -> { LoginType.MOBIDZIENNIK -> {}
LoginType.VULCAN -> {
}
LOGIN_TYPE_VULCAN -> {
// DataVulcan.isApiLoginValid() returns false so it will update the semester // DataVulcan.isApiLoginValid() returns false so it will update the semester
profile.removeStudentData("currentSemesterEndDate") profile.studentData.remove("currentSemesterEndDate")
profile.removeStudentData("studentSemesterId") profile.studentData.remove("studentSemesterId")
profile.removeStudentData("studentSemesterNumber") profile.studentData.remove("studentSemesterNumber")
profile.removeStudentData("semester1Id") profile.studentData.remove("semester1Id")
profile.removeStudentData("semester2Id") profile.studentData.remove("semester2Id")
profile.removeStudentData("studentClassId") profile.studentData.remove("studentClassId")
} }
LOGIN_TYPE_IDZIENNIK -> { LoginType.IDZIENNIK -> {
profile.removeStudentData("schoolYearId") profile.studentData.remove("schoolYearId")
}
LOGIN_TYPE_EDUDZIENNIK -> {
}
LOGIN_TYPE_PODLASIE -> {
} }
LoginType.EDUDZIENNIK -> {}
LoginType.PODLASIE -> {}
LoginType.USOS -> {}
LoginType.DEMO -> {}
LoginType.TEMPLATE -> {}
} }
d(TAG, "Processed student data: ${profile.studentData}") d(TAG, "Processed student data: ${profile.studentData}")

View File

@ -5,15 +5,14 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.librus package pl.szczodrzynski.edziennik.data.api.edziennik.librus
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_LIBRUS_API
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_LIBRUS_MESSAGES
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_LIBRUS_PORTAL
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_LIBRUS_SYNERGIA
import pl.szczodrzynski.edziennik.data.api.models.Data import pl.szczodrzynski.edziennik.data.api.models.Data
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
import pl.szczodrzynski.edziennik.data.db.entity.Profile import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.db.enums.LoginMethod
import pl.szczodrzynski.edziennik.ext.currentTimeUnix import pl.szczodrzynski.edziennik.ext.currentTimeUnix
import pl.szczodrzynski.edziennik.ext.getStudentData
import pl.szczodrzynski.edziennik.ext.isNotNullNorEmpty import pl.szczodrzynski.edziennik.ext.isNotNullNorEmpty
import pl.szczodrzynski.edziennik.ext.set
class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app, profile, loginStore) { class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app, profile, loginStore) {
@ -25,15 +24,15 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
override fun satisfyLoginMethods() { override fun satisfyLoginMethods() {
loginMethods.clear() loginMethods.clear()
if (isPortalLoginValid()) if (isPortalLoginValid())
loginMethods += LOGIN_METHOD_LIBRUS_PORTAL loginMethods += LoginMethod.LIBRUS_PORTAL
if (isApiLoginValid()) if (isApiLoginValid())
loginMethods += LOGIN_METHOD_LIBRUS_API loginMethods += LoginMethod.LIBRUS_API
if (isSynergiaLoginValid()) { if (isSynergiaLoginValid()) {
loginMethods += LOGIN_METHOD_LIBRUS_SYNERGIA loginMethods += LoginMethod.LIBRUS_SYNERGIA
app.cookieJar.set("synergia.librus.pl", "DZIENNIKSID", synergiaSessionId) app.cookieJar.set("synergia.librus.pl", "DZIENNIKSID", synergiaSessionId)
} }
if (isMessagesLoginValid()) { if (isMessagesLoginValid()) {
loginMethods += LOGIN_METHOD_LIBRUS_MESSAGES loginMethods += LoginMethod.LIBRUS_MESSAGES
app.cookieJar.set("wiadomosci.librus.pl", "DZIENNIKSID", messagesSessionId) app.cookieJar.set("wiadomosci.librus.pl", "DZIENNIKSID", messagesSessionId)
} }
} }
@ -120,7 +119,7 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
private var mApiLogin: String? = null private var mApiLogin: String? = null
var apiLogin: String? var apiLogin: String?
get() { mApiLogin = mApiLogin ?: profile?.getStudentData("accountLogin", null); return mApiLogin } get() { mApiLogin = mApiLogin ?: profile?.getStudentData("accountLogin", null); return mApiLogin }
set(value) { profile?.putStudentData("accountLogin", value); mApiLogin = value } set(value) { profile["accountLogin"] = value; mApiLogin = value }
/** /**
* A Synergia password. * A Synergia password.
* Used: for login (API Login Method) in Synergia mode. * Used: for login (API Login Method) in Synergia mode.
@ -129,7 +128,7 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
private var mApiPassword: String? = null private var mApiPassword: String? = null
var apiPassword: String? var apiPassword: String?
get() { mApiPassword = mApiPassword ?: profile?.getStudentData("accountPassword", null); return mApiPassword } get() { mApiPassword = mApiPassword ?: profile?.getStudentData("accountPassword", null); return mApiPassword }
set(value) { profile?.putStudentData("accountPassword", value); mApiPassword = value } set(value) { profile["accountPassword"] = value; mApiPassword = value }
/** /**
* A JST login Code. * A JST login Code.
@ -138,7 +137,7 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
private var mApiCode: String? = null private var mApiCode: String? = null
var apiCode: String? var apiCode: String?
get() { mApiCode = mApiCode ?: loginStore.getLoginData("accountCode", null); return mApiCode } get() { mApiCode = mApiCode ?: loginStore.getLoginData("accountCode", null); return mApiCode }
set(value) { profile?.putStudentData("accountCode", value); mApiCode = value } set(value) { profile["accountCode"] = value; mApiCode = value }
/** /**
* A JST login PIN. * A JST login PIN.
* Used only during first login in JST mode. * Used only during first login in JST mode.
@ -146,7 +145,7 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
private var mApiPin: String? = null private var mApiPin: String? = null
var apiPin: String? var apiPin: String?
get() { mApiPin = mApiPin ?: loginStore.getLoginData("accountPin", null); return mApiPin } get() { mApiPin = mApiPin ?: loginStore.getLoginData("accountPin", null); return mApiPin }
set(value) { profile?.putStudentData("accountPin", value); mApiPin = value } set(value) { profile["accountPin"] = value; mApiPin = value }
/** /**
* A Synergia API access token. * A Synergia API access token.
@ -157,7 +156,7 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
private var mApiAccessToken: String? = null private var mApiAccessToken: String? = null
var apiAccessToken: String? var apiAccessToken: String?
get() { mApiAccessToken = mApiAccessToken ?: profile?.getStudentData("accountToken", null); return mApiAccessToken } get() { mApiAccessToken = mApiAccessToken ?: profile?.getStudentData("accountToken", null); return mApiAccessToken }
set(value) { mApiAccessToken = value; profile?.putStudentData("accountToken", value) ?: return; } set(value) { mApiAccessToken = value; profile["accountToken"] = value ?: return; }
/** /**
* A Synergia API refresh token. * A Synergia API refresh token.
* Used when refreshing the [apiAccessToken] in JST, Synergia modes. * Used when refreshing the [apiAccessToken] in JST, Synergia modes.
@ -165,7 +164,7 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
private var mApiRefreshToken: String? = null private var mApiRefreshToken: String? = null
var apiRefreshToken: String? var apiRefreshToken: String?
get() { mApiRefreshToken = mApiRefreshToken ?: profile?.getStudentData("accountRefreshToken", null); return mApiRefreshToken } get() { mApiRefreshToken = mApiRefreshToken ?: profile?.getStudentData("accountRefreshToken", null); return mApiRefreshToken }
set(value) { mApiRefreshToken = value; profile?.putStudentData("accountRefreshToken", value) ?: return; } set(value) { mApiRefreshToken = value; profile["accountRefreshToken"] = value ?: return; }
/** /**
* The expiry time for [apiAccessToken], as a UNIX timestamp. * The expiry time for [apiAccessToken], as a UNIX timestamp.
* Used when refreshing the [apiAccessToken] in JST, Synergia modes. * Used when refreshing the [apiAccessToken] in JST, Synergia modes.
@ -174,7 +173,7 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
private var mApiTokenExpiryTime: Long? = null private var mApiTokenExpiryTime: Long? = null
var apiTokenExpiryTime: Long var apiTokenExpiryTime: Long
get() { mApiTokenExpiryTime = mApiTokenExpiryTime ?: profile?.getStudentData("accountTokenTime", 0L); return mApiTokenExpiryTime ?: 0L } get() { mApiTokenExpiryTime = mApiTokenExpiryTime ?: profile?.getStudentData("accountTokenTime", 0L); return mApiTokenExpiryTime ?: 0L }
set(value) { mApiTokenExpiryTime = value; profile?.putStudentData("accountTokenTime", value) ?: return; } set(value) { mApiTokenExpiryTime = value; profile["accountTokenTime"] = value; }
/** /**
* A push device ID, generated by Librus when registering * A push device ID, generated by Librus when registering
@ -184,7 +183,7 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
private var mPushDeviceId: Int? = null private var mPushDeviceId: Int? = null
var pushDeviceId: Int var pushDeviceId: Int
get() { mPushDeviceId = mPushDeviceId ?: profile?.getStudentData("pushDeviceId", 0); return mPushDeviceId ?: 0 } get() { mPushDeviceId = mPushDeviceId ?: profile?.getStudentData("pushDeviceId", 0); return mPushDeviceId ?: 0 }
set(value) { mPushDeviceId = value; profile?.putStudentData("pushDeviceId", value) ?: return; } set(value) { mPushDeviceId = value; profile["pushDeviceId"] = value; }
/* _____ _ /* _____ _
/ ____| (_) / ____| (_)
@ -201,7 +200,7 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
private var mSynergiaSessionId: String? = null private var mSynergiaSessionId: String? = null
var synergiaSessionId: String? var synergiaSessionId: String?
get() { mSynergiaSessionId = mSynergiaSessionId ?: profile?.getStudentData("accountSID", null); return mSynergiaSessionId } get() { mSynergiaSessionId = mSynergiaSessionId ?: profile?.getStudentData("accountSID", null); return mSynergiaSessionId }
set(value) { profile?.putStudentData("accountSID", value) ?: return; mSynergiaSessionId = value } set(value) { profile["accountSID"] = value; mSynergiaSessionId = value }
/** /**
* The expiry time for [synergiaSessionId], as a UNIX timestamp. * The expiry time for [synergiaSessionId], as a UNIX timestamp.
* Used in endpoints with Synergia login method. * Used in endpoints with Synergia login method.
@ -210,7 +209,7 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
private var mSynergiaSessionIdExpiryTime: Long? = null private var mSynergiaSessionIdExpiryTime: Long? = null
var synergiaSessionIdExpiryTime: Long var synergiaSessionIdExpiryTime: Long
get() { mSynergiaSessionIdExpiryTime = mSynergiaSessionIdExpiryTime ?: profile?.getStudentData("accountSIDTime", 0L); return mSynergiaSessionIdExpiryTime ?: 0L } get() { mSynergiaSessionIdExpiryTime = mSynergiaSessionIdExpiryTime ?: profile?.getStudentData("accountSIDTime", 0L); return mSynergiaSessionIdExpiryTime ?: 0L }
set(value) { profile?.putStudentData("accountSIDTime", value) ?: return; mSynergiaSessionIdExpiryTime = value } set(value) { profile["accountSIDTime"] = value; mSynergiaSessionIdExpiryTime = value }
/** /**
@ -220,7 +219,7 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
private var mMessagesSessionId: String? = null private var mMessagesSessionId: String? = null
var messagesSessionId: String? var messagesSessionId: String?
get() { mMessagesSessionId = mMessagesSessionId ?: profile?.getStudentData("messagesSID", null); return mMessagesSessionId } get() { mMessagesSessionId = mMessagesSessionId ?: profile?.getStudentData("messagesSID", null); return mMessagesSessionId }
set(value) { profile?.putStudentData("messagesSID", value) ?: return; mMessagesSessionId = value } set(value) { profile["messagesSID"] = value; mMessagesSessionId = value }
/** /**
* The expiry time for [messagesSessionId], as a UNIX timestamp. * The expiry time for [messagesSessionId], as a UNIX timestamp.
* Used in endpoints with Messages login method. * Used in endpoints with Messages login method.
@ -229,7 +228,7 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
private var mMessagesSessionIdExpiryTime: Long? = null private var mMessagesSessionIdExpiryTime: Long? = null
var messagesSessionIdExpiryTime: Long var messagesSessionIdExpiryTime: Long
get() { mMessagesSessionIdExpiryTime = mMessagesSessionIdExpiryTime ?: profile?.getStudentData("messagesSIDTime", 0L); return mMessagesSessionIdExpiryTime ?: 0L } get() { mMessagesSessionIdExpiryTime = mMessagesSessionIdExpiryTime ?: profile?.getStudentData("messagesSIDTime", 0L); return mMessagesSessionIdExpiryTime ?: 0L }
set(value) { profile?.putStudentData("messagesSIDTime", value) ?: return; mMessagesSessionIdExpiryTime = value } set(value) { profile["messagesSIDTime"] = value; mMessagesSessionIdExpiryTime = value }
/* ____ _ _ /* ____ _ _
/ __ \| | | | / __ \| | | |
@ -239,42 +238,42 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
\____/ \__|_| |_|\___|*/ \____/ \__|_| |_|\___|*/
var isPremium var isPremium
get() = profile?.getStudentData("isPremium", false) ?: false get() = profile?.getStudentData("isPremium", false) ?: false
set(value) { profile?.putStudentData("isPremium", value) } set(value) { profile["isPremium"] = value }
private var mSchoolName: String? = null private var mSchoolName: String? = null
var schoolName: String? var schoolName: String?
get() { mSchoolName = mSchoolName ?: profile?.getStudentData("schoolName", null); return mSchoolName } get() { mSchoolName = mSchoolName ?: profile?.getStudentData("schoolName", null); return mSchoolName }
set(value) { profile?.putStudentData("schoolName", value) ?: return; mSchoolName = value } set(value) { profile["schoolName"] = value; mSchoolName = value }
private var mUnitId: Long? = null private var mUnitId: Long? = null
var unitId: Long var unitId: Long
get() { mUnitId = mUnitId ?: profile?.getStudentData("unitId", 0L); return mUnitId ?: 0L } get() { mUnitId = mUnitId ?: profile?.getStudentData("unitId", 0L); return mUnitId ?: 0L }
set(value) { profile?.putStudentData("unitId", value) ?: return; mUnitId = value } set(value) { profile["unitId"] = value; mUnitId = value }
private var mStartPointsSemester1: Int? = null private var mStartPointsSemester1: Int? = null
var startPointsSemester1: Int var startPointsSemester1: Int
get() { mStartPointsSemester1 = mStartPointsSemester1 ?: profile?.getStudentData("startPointsSemester1", 0); return mStartPointsSemester1 ?: 0 } get() { mStartPointsSemester1 = mStartPointsSemester1 ?: profile?.getStudentData("startPointsSemester1", 0); return mStartPointsSemester1 ?: 0 }
set(value) { profile?.putStudentData("startPointsSemester1", value) ?: return; mStartPointsSemester1 = value } set(value) { profile["startPointsSemester1"] = value; mStartPointsSemester1 = value }
private var mStartPointsSemester2: Int? = null private var mStartPointsSemester2: Int? = null
var startPointsSemester2: Int var startPointsSemester2: Int
get() { mStartPointsSemester2 = mStartPointsSemester2 ?: profile?.getStudentData("startPointsSemester2", 0); return mStartPointsSemester2 ?: 0 } get() { mStartPointsSemester2 = mStartPointsSemester2 ?: profile?.getStudentData("startPointsSemester2", 0); return mStartPointsSemester2 ?: 0 }
set(value) { profile?.putStudentData("startPointsSemester2", value) ?: return; mStartPointsSemester2 = value } set(value) { profile["startPointsSemester2"] = value; mStartPointsSemester2 = value }
private var mEnablePointGrades: Boolean? = null private var mEnablePointGrades: Boolean? = null
var enablePointGrades: Boolean var enablePointGrades: Boolean
get() { mEnablePointGrades = mEnablePointGrades ?: profile?.getStudentData("enablePointGrades", true); return mEnablePointGrades ?: true } get() { mEnablePointGrades = mEnablePointGrades ?: profile?.getStudentData("enablePointGrades", true); return mEnablePointGrades ?: true }
set(value) { profile?.putStudentData("enablePointGrades", value) ?: return; mEnablePointGrades = value } set(value) { profile["enablePointGrades"] = value; mEnablePointGrades = value }
private var mEnableDescriptiveGrades: Boolean? = null private var mEnableDescriptiveGrades: Boolean? = null
var enableDescriptiveGrades: Boolean var enableDescriptiveGrades: Boolean
get() { mEnableDescriptiveGrades = mEnableDescriptiveGrades ?: profile?.getStudentData("enableDescriptiveGrades", true); return mEnableDescriptiveGrades ?: true } get() { mEnableDescriptiveGrades = mEnableDescriptiveGrades ?: profile?.getStudentData("enableDescriptiveGrades", true); return mEnableDescriptiveGrades ?: true }
set(value) { profile?.putStudentData("enableDescriptiveGrades", value) ?: return; mEnableDescriptiveGrades = value } set(value) { profile["enableDescriptiveGrades"] = value; mEnableDescriptiveGrades = value }
private var mTimetableNotPublic: Boolean? = null private var mTimetableNotPublic: Boolean? = null
var timetableNotPublic: Boolean var timetableNotPublic: Boolean
get() { mTimetableNotPublic = mTimetableNotPublic ?: profile?.getStudentData("timetableNotPublic", false); return mTimetableNotPublic ?: false } get() { mTimetableNotPublic = mTimetableNotPublic ?: profile?.getStudentData("timetableNotPublic", false); return mTimetableNotPublic ?: false }
set(value) { profile?.putStudentData("timetableNotPublic", value) ?: return; mTimetableNotPublic = value } set(value) { profile["timetableNotPublic"] = value; mTimetableNotPublic = value }
/** /**
* Set to false when Recaptcha helper doesn't provide a working token. * Set to false when Recaptcha helper doesn't provide a working token.

View File

@ -16,6 +16,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages.Librus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia.* import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.firstlogin.LibrusFirstLogin import pl.szczodrzynski.edziennik.data.api.edziennik.librus.firstlogin.LibrusFirstLogin
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLogin import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLogin
import pl.szczodrzynski.edziennik.data.api.events.UserActionRequiredEvent
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.data.api.models.ApiError
@ -23,6 +24,8 @@ import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
import pl.szczodrzynski.edziennik.data.db.entity.Message import pl.szczodrzynski.edziennik.data.db.entity.Message
import pl.szczodrzynski.edziennik.data.db.entity.Profile import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.db.entity.Teacher import pl.szczodrzynski.edziennik.data.db.entity.Teacher
import pl.szczodrzynski.edziennik.data.db.enums.FeatureType
import pl.szczodrzynski.edziennik.data.db.enums.LoginMethod
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
import pl.szczodrzynski.edziennik.data.db.full.EventFull import pl.szczodrzynski.edziennik.data.db.full.EventFull
import pl.szczodrzynski.edziennik.data.db.full.MessageFull import pl.szczodrzynski.edziennik.data.db.full.MessageFull
@ -57,19 +60,19 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_| |_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
__/ | __/ |
|__*/ |__*/
override fun sync(featureIds: List<Int>, viewId: Int?, onlyEndpoints: List<Int>?, arguments: JsonObject?) { override fun sync(featureTypes: Set<FeatureType>?, onlyEndpoints: Set<Int>?, arguments: JsonObject?) {
data.arguments = arguments data.arguments = arguments
data.prepare(librusLoginMethods, LibrusFeatures, featureIds, viewId, onlyEndpoints) data.prepare(LibrusFeatures, featureTypes, onlyEndpoints)
login() login()
} }
private fun login(loginMethodId: Int? = null, afterLogin: (() -> Unit)? = null) { private fun login(loginMethod: LoginMethod? = null, afterLogin: (() -> Unit)? = null) {
d(TAG, "Trying to login with ${data.targetLoginMethodIds}") d(TAG, "Trying to login with ${data.targetLoginMethods}")
if (internalErrorList.isNotEmpty()) { if (internalErrorList.isNotEmpty()) {
d(TAG, " - Internal errors:") d(TAG, " - Internal errors:")
internalErrorList.forEach { d(TAG, " - code $it") } internalErrorList.forEach { d(TAG, " - code $it") }
} }
loginMethodId?.let { data.prepareFor(librusLoginMethods, it) } loginMethod?.let { data.prepareFor(it) }
afterLogin?.let { this.afterLogin = it } afterLogin?.let { this.afterLogin = it }
LibrusLogin(data) { LibrusLogin(data) {
data() data()
@ -77,7 +80,7 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
} }
private fun data() { private fun data() {
d(TAG, "Endpoint IDs: ${data.targetEndpointIds}") d(TAG, "Endpoint IDs: ${data.targetEndpoints}")
if (internalErrorList.isNotEmpty()) { if (internalErrorList.isNotEmpty()) {
d(TAG, " - Internal errors:") d(TAG, " - Internal errors:")
internalErrorList.forEach { d(TAG, " - code $it") } internalErrorList.forEach { d(TAG, " - code $it") }
@ -88,14 +91,14 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
} }
override fun getMessage(message: MessageFull) { override fun getMessage(message: MessageFull) {
login(LOGIN_METHOD_LIBRUS_MESSAGES) { login(LoginMethod.LIBRUS_MESSAGES) {
if (data.messagesLoginSuccessful) LibrusMessagesGetMessage(data, message) { completed() } if (data.messagesLoginSuccessful) LibrusMessagesGetMessage(data, message) { completed() }
else LibrusSynergiaGetMessage(data, message) { completed() } else LibrusSynergiaGetMessage(data, message) { completed() }
} }
} }
override fun sendMessage(recipients: List<Teacher>, subject: String, text: String) { override fun sendMessage(recipients: Set<Teacher>, subject: String, text: String) {
login(LOGIN_METHOD_LIBRUS_MESSAGES) { login(LoginMethod.LIBRUS_MESSAGES) {
LibrusMessagesSendMessage(data, recipients, subject, text) { LibrusMessagesSendMessage(data, recipients, subject, text) {
completed() completed()
} }
@ -103,7 +106,7 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
} }
override fun markAllAnnouncementsAsRead() { override fun markAllAnnouncementsAsRead() {
login(LOGIN_METHOD_LIBRUS_SYNERGIA) { login(LoginMethod.LIBRUS_SYNERGIA) {
LibrusSynergiaMarkAllAnnouncementsAsRead(data) { LibrusSynergiaMarkAllAnnouncementsAsRead(data) {
completed() completed()
} }
@ -111,7 +114,7 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
} }
override fun getAnnouncement(announcement: AnnouncementFull) { override fun getAnnouncement(announcement: AnnouncementFull) {
login(LOGIN_METHOD_LIBRUS_API) { login(LoginMethod.LIBRUS_API) {
LibrusApiAnnouncementMarkAsRead(data, announcement) { LibrusApiAnnouncementMarkAsRead(data, announcement) {
completed() completed()
} }
@ -121,13 +124,13 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) { override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) {
when (owner) { when (owner) {
is Message -> { is Message -> {
login(LOGIN_METHOD_LIBRUS_SYNERGIA) { login(LoginMethod.LIBRUS_SYNERGIA) {
if (data.messagesLoginSuccessful) LibrusMessagesGetAttachment(data, owner, attachmentId, attachmentName) { completed() } if (data.messagesLoginSuccessful) LibrusMessagesGetAttachment(data, owner, attachmentId, attachmentName) { completed() }
LibrusSynergiaGetAttachment(data, owner, attachmentId, attachmentName) { completed() } LibrusSynergiaGetAttachment(data, owner, attachmentId, attachmentName) { completed() }
} }
} }
is EventFull -> { is EventFull -> {
login(LOGIN_METHOD_LIBRUS_SYNERGIA) { login(LoginMethod.LIBRUS_SYNERGIA) {
LibrusSynergiaHomeworkGetAttachment(data, owner, attachmentId, attachmentName) { LibrusSynergiaHomeworkGetAttachment(data, owner, attachmentId, attachmentName) {
completed() completed()
} }
@ -138,7 +141,7 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
} }
override fun getRecipientList() { override fun getRecipientList() {
login(LOGIN_METHOD_LIBRUS_MESSAGES) { login(LoginMethod.LIBRUS_MESSAGES) {
LibrusMessagesGetRecipientList(data) { LibrusMessagesGetRecipientList(data) {
completed() completed()
} }
@ -146,7 +149,7 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
} }
override fun getEvent(eventFull: EventFull) { override fun getEvent(eventFull: EventFull) {
login(LOGIN_METHOD_LIBRUS_SYNERGIA) { login(LoginMethod.LIBRUS_SYNERGIA) {
LibrusSynergiaGetHomework(data, eventFull) { LibrusSynergiaGetHomework(data, eventFull) {
completed() completed()
} }
@ -162,6 +165,7 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
private fun wrapCallback(callback: EdziennikCallback): EdziennikCallback { private fun wrapCallback(callback: EdziennikCallback): EdziennikCallback {
return object : EdziennikCallback { return object : EdziennikCallback {
override fun onCompleted() { callback.onCompleted() } override fun onCompleted() { callback.onCompleted() }
override fun onRequiresUserAction(event: UserActionRequiredEvent) { callback.onRequiresUserAction(event) }
override fun onProgress(step: Float) { callback.onProgress(step) } override fun onProgress(step: Float) { callback.onProgress(step) }
override fun onStartProgress(stringRes: Int) { callback.onStartProgress(stringRes) } override fun onStartProgress(stringRes: Int) { callback.onStartProgress(stringRes) }
override fun onError(apiError: ApiError) { override fun onError(apiError: ApiError) {
@ -173,27 +177,27 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
internalErrorList.add(apiError.errorCode) internalErrorList.add(apiError.errorCode)
when (apiError.errorCode) { when (apiError.errorCode) {
ERROR_LIBRUS_PORTAL_ACCESS_DENIED -> { ERROR_LIBRUS_PORTAL_ACCESS_DENIED -> {
data.loginMethods.remove(LOGIN_METHOD_LIBRUS_PORTAL) data.loginMethods.remove(LoginMethod.LIBRUS_PORTAL)
data.prepareFor(librusLoginMethods, LOGIN_METHOD_LIBRUS_PORTAL) data.prepareFor(LoginMethod.LIBRUS_PORTAL)
data.portalTokenExpiryTime = 0 data.portalTokenExpiryTime = 0
login() login()
} }
ERROR_LIBRUS_API_ACCESS_DENIED, ERROR_LIBRUS_API_ACCESS_DENIED,
ERROR_LIBRUS_API_TOKEN_EXPIRED -> { ERROR_LIBRUS_API_TOKEN_EXPIRED -> {
data.loginMethods.remove(LOGIN_METHOD_LIBRUS_API) data.loginMethods.remove(LoginMethod.LIBRUS_API)
data.prepareFor(librusLoginMethods, LOGIN_METHOD_LIBRUS_API) data.prepareFor(LoginMethod.LIBRUS_API)
data.apiTokenExpiryTime = 0 data.apiTokenExpiryTime = 0
login() login()
} }
ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED -> { ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED -> {
data.loginMethods.remove(LOGIN_METHOD_LIBRUS_SYNERGIA) data.loginMethods.remove(LoginMethod.LIBRUS_SYNERGIA)
data.prepareFor(librusLoginMethods, LOGIN_METHOD_LIBRUS_SYNERGIA) data.prepareFor(LoginMethod.LIBRUS_SYNERGIA)
data.synergiaSessionIdExpiryTime = 0 data.synergiaSessionIdExpiryTime = 0
login() login()
} }
ERROR_LIBRUS_MESSAGES_ACCESS_DENIED -> { ERROR_LIBRUS_MESSAGES_ACCESS_DENIED -> {
data.loginMethods.remove(LOGIN_METHOD_LIBRUS_MESSAGES) data.loginMethods.remove(LoginMethod.LIBRUS_MESSAGES)
data.prepareFor(librusLoginMethods, LOGIN_METHOD_LIBRUS_MESSAGES) data.prepareFor(LoginMethod.LIBRUS_MESSAGES)
data.messagesSessionIdExpiryTime = 0 data.messagesSessionIdExpiryTime = 0
login() login()
} }

View File

@ -4,8 +4,10 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.librus package pl.szczodrzynski.edziennik.data.api.edziennik.librus
import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.models.Feature import pl.szczodrzynski.edziennik.data.api.models.Feature
import pl.szczodrzynski.edziennik.data.db.enums.FeatureType
import pl.szczodrzynski.edziennik.data.db.enums.LoginMethod
import pl.szczodrzynski.edziennik.data.db.enums.LoginType
const val ENDPOINT_LIBRUS_API_ME = 1001 const val ENDPOINT_LIBRUS_API_ME = 1001
const val ENDPOINT_LIBRUS_API_SCHOOLS = 1002 const val ENDPOINT_LIBRUS_API_SCHOOLS = 1002
@ -58,14 +60,14 @@ const val ENDPOINT_LIBRUS_MESSAGES_TRASH = 3030
val LibrusFeatures = listOf( val LibrusFeatures = listOf(
Feature(LOGIN_TYPE_LIBRUS, FEATURE_ALWAYS_NEEDED, listOf( Feature(LoginType.LIBRUS, FeatureType.ALWAYS_NEEDED, listOf(
ENDPOINT_LIBRUS_API_LESSONS to LOGIN_METHOD_LIBRUS_API ENDPOINT_LIBRUS_API_LESSONS to LoginMethod.LIBRUS_API
), listOf(LOGIN_METHOD_LIBRUS_API)), )),
// push config // push config
Feature(LOGIN_TYPE_LIBRUS, FEATURE_PUSH_CONFIG, listOf( Feature(LoginType.LIBRUS, FeatureType.PUSH_CONFIG, listOf(
ENDPOINT_LIBRUS_API_PUSH_CONFIG to LOGIN_METHOD_LIBRUS_API ENDPOINT_LIBRUS_API_PUSH_CONFIG to LoginMethod.LIBRUS_API
), listOf(LOGIN_METHOD_LIBRUS_API)).withShouldSync { data -> )).withShouldSync { data ->
(data as DataLibrus).isPremium && !data.app.config.sync.tokenLibrusList.contains(data.profileId) (data as DataLibrus).isPremium && !data.app.config.sync.tokenLibrusList.contains(data.profileId)
}, },
@ -76,72 +78,72 @@ val LibrusFeatures = listOf(
/** /**
* Timetable - using API. * Timetable - using API.
*/ */
Feature(LOGIN_TYPE_LIBRUS, FEATURE_TIMETABLE, listOf( Feature(LoginType.LIBRUS, FeatureType.TIMETABLE, listOf(
ENDPOINT_LIBRUS_API_TIMETABLES to LOGIN_METHOD_LIBRUS_API, ENDPOINT_LIBRUS_API_TIMETABLES to LoginMethod.LIBRUS_API,
ENDPOINT_LIBRUS_API_SUBSTITUTIONS to LOGIN_METHOD_LIBRUS_API ENDPOINT_LIBRUS_API_SUBSTITUTIONS to LoginMethod.LIBRUS_API
), listOf(LOGIN_METHOD_LIBRUS_API)), )),
/** /**
* Agenda - using API. * Agenda - using API.
* Events, Parent-teacher meetings, free days (teacher/school/class). * Events, Parent-teacher meetings, free days (teacher/school/class).
*/ */
Feature(LOGIN_TYPE_LIBRUS, FEATURE_AGENDA, listOf( Feature(LoginType.LIBRUS, FeatureType.AGENDA, listOf(
ENDPOINT_LIBRUS_API_EVENTS to LOGIN_METHOD_LIBRUS_API, ENDPOINT_LIBRUS_API_EVENTS to LoginMethod.LIBRUS_API,
ENDPOINT_LIBRUS_API_EVENT_TYPES to LOGIN_METHOD_LIBRUS_API, ENDPOINT_LIBRUS_API_EVENT_TYPES to LoginMethod.LIBRUS_API,
ENDPOINT_LIBRUS_API_PT_MEETINGS to LOGIN_METHOD_LIBRUS_API, ENDPOINT_LIBRUS_API_PT_MEETINGS to LoginMethod.LIBRUS_API,
ENDPOINT_LIBRUS_API_TEACHER_FREE_DAY_TYPES to LOGIN_METHOD_LIBRUS_API, ENDPOINT_LIBRUS_API_TEACHER_FREE_DAY_TYPES to LoginMethod.LIBRUS_API,
ENDPOINT_LIBRUS_API_TEACHER_FREE_DAYS to LOGIN_METHOD_LIBRUS_API, ENDPOINT_LIBRUS_API_TEACHER_FREE_DAYS to LoginMethod.LIBRUS_API,
ENDPOINT_LIBRUS_API_SCHOOL_FREE_DAYS to LOGIN_METHOD_LIBRUS_API, ENDPOINT_LIBRUS_API_SCHOOL_FREE_DAYS to LoginMethod.LIBRUS_API,
ENDPOINT_LIBRUS_API_CLASS_FREE_DAYS to LOGIN_METHOD_LIBRUS_API ENDPOINT_LIBRUS_API_CLASS_FREE_DAYS to LoginMethod.LIBRUS_API
), listOf(LOGIN_METHOD_LIBRUS_API)), )),
/** /**
* Grades - using API. * Grades - using API.
* All grades + categories. * All grades + categories.
*/ */
Feature(LOGIN_TYPE_LIBRUS, FEATURE_GRADES, listOf( Feature(LoginType.LIBRUS, FeatureType.GRADES, listOf(
ENDPOINT_LIBRUS_API_NORMAL_GRADE_CATEGORIES to LOGIN_METHOD_LIBRUS_API, ENDPOINT_LIBRUS_API_NORMAL_GRADE_CATEGORIES to LoginMethod.LIBRUS_API,
ENDPOINT_LIBRUS_API_POINT_GRADE_CATEGORIES to LOGIN_METHOD_LIBRUS_API, ENDPOINT_LIBRUS_API_POINT_GRADE_CATEGORIES to LoginMethod.LIBRUS_API,
ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADE_CATEGORIES to LOGIN_METHOD_LIBRUS_API, ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADE_CATEGORIES to LoginMethod.LIBRUS_API,
// Commented out, because TextGrades/Categories is the same as Grades/Categories // Commented out, because TextGrades/Categories is the same as Grades/Categories
/* ENDPOINT_LIBRUS_API_TEXT_GRADE_CATEGORIES to LOGIN_METHOD_LIBRUS_API, */ /* ENDPOINT_LIBRUS_API_TEXT_GRADE_CATEGORIES to LoginMethod.LIBRUS_API, */
ENDPOINT_LIBRUS_API_DESCRIPTIVE_TEXT_GRADE_CATEGORIES to LOGIN_METHOD_LIBRUS_API, ENDPOINT_LIBRUS_API_DESCRIPTIVE_TEXT_GRADE_CATEGORIES to LoginMethod.LIBRUS_API,
ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_CATEGORIES to LOGIN_METHOD_LIBRUS_API, ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_CATEGORIES to LoginMethod.LIBRUS_API,
ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS to LOGIN_METHOD_LIBRUS_API, ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS to LoginMethod.LIBRUS_API,
ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_COMMENTS to LOGIN_METHOD_LIBRUS_API, ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_COMMENTS to LoginMethod.LIBRUS_API,
ENDPOINT_LIBRUS_API_NORMAL_GRADES to LOGIN_METHOD_LIBRUS_API, ENDPOINT_LIBRUS_API_NORMAL_GRADES to LoginMethod.LIBRUS_API,
ENDPOINT_LIBRUS_API_POINT_GRADES to LOGIN_METHOD_LIBRUS_API, ENDPOINT_LIBRUS_API_POINT_GRADES to LoginMethod.LIBRUS_API,
ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADES to LOGIN_METHOD_LIBRUS_API, ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADES to LoginMethod.LIBRUS_API,
ENDPOINT_LIBRUS_API_TEXT_GRADES to LOGIN_METHOD_LIBRUS_API, ENDPOINT_LIBRUS_API_TEXT_GRADES to LoginMethod.LIBRUS_API,
ENDPOINT_LIBRUS_API_DESCRIPTIVE_TEXT_GRADES to LOGIN_METHOD_LIBRUS_API, ENDPOINT_LIBRUS_API_DESCRIPTIVE_TEXT_GRADES to LoginMethod.LIBRUS_API,
ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADES to LOGIN_METHOD_LIBRUS_API ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADES to LoginMethod.LIBRUS_API
), listOf(LOGIN_METHOD_LIBRUS_API)), )),
/** /**
* Homework - using API. * Homework - using API.
* Sync only if account has premium access. * Sync only if account has premium access.
*/ */
/*Feature(LOGIN_TYPE_LIBRUS, FEATURE_HOMEWORK, listOf( /*Feature(LoginType.LIBRUS, FeatureType.HOMEWORK, listOf(
ENDPOINT_LIBRUS_API_HOMEWORK to LOGIN_METHOD_LIBRUS_API ENDPOINT_LIBRUS_API_HOMEWORK to LoginMethod.LIBRUS_API
), listOf(LOGIN_METHOD_LIBRUS_API)).withShouldSync { data -> )).withShouldSync { data ->
(data as DataLibrus).isPremium (data as DataLibrus).isPremium
},*/ },*/
/** /**
* Behaviour - using API. * Behaviour - using API.
*/ */
Feature(LOGIN_TYPE_LIBRUS, FEATURE_BEHAVIOUR, listOf( Feature(LoginType.LIBRUS, FeatureType.BEHAVIOUR, listOf(
ENDPOINT_LIBRUS_API_NOTICES to LOGIN_METHOD_LIBRUS_API ENDPOINT_LIBRUS_API_NOTICES to LoginMethod.LIBRUS_API
), listOf(LOGIN_METHOD_LIBRUS_API)), )),
/** /**
* Attendance - using API. * Attendance - using API.
*/ */
Feature(LOGIN_TYPE_LIBRUS, FEATURE_ATTENDANCE, listOf( Feature(LoginType.LIBRUS, FeatureType.ATTENDANCE, listOf(
ENDPOINT_LIBRUS_API_ATTENDANCE_TYPES to LOGIN_METHOD_LIBRUS_API, ENDPOINT_LIBRUS_API_ATTENDANCE_TYPES to LoginMethod.LIBRUS_API,
ENDPOINT_LIBRUS_API_ATTENDANCES to LOGIN_METHOD_LIBRUS_API ENDPOINT_LIBRUS_API_ATTENDANCES to LoginMethod.LIBRUS_API
), listOf(LOGIN_METHOD_LIBRUS_API)), )),
/** /**
* Announcements - using API. * Announcements - using API.
*/ */
Feature(LOGIN_TYPE_LIBRUS, FEATURE_ANNOUNCEMENTS, listOf( Feature(LoginType.LIBRUS, FeatureType.ANNOUNCEMENTS, listOf(
ENDPOINT_LIBRUS_API_ANNOUNCEMENTS to LOGIN_METHOD_LIBRUS_API ENDPOINT_LIBRUS_API_ANNOUNCEMENTS to LoginMethod.LIBRUS_API
), listOf(LOGIN_METHOD_LIBRUS_API)), )),
@ -150,99 +152,99 @@ val LibrusFeatures = listOf(
/** /**
* Student info - using API. * Student info - using API.
*/ */
Feature(LOGIN_TYPE_LIBRUS, FEATURE_STUDENT_INFO, listOf( Feature(LoginType.LIBRUS, FeatureType.STUDENT_INFO, listOf(
ENDPOINT_LIBRUS_API_ME to LOGIN_METHOD_LIBRUS_API ENDPOINT_LIBRUS_API_ME to LoginMethod.LIBRUS_API
), listOf(LOGIN_METHOD_LIBRUS_API)), )),
/** /**
* School info - using API. * School info - using API.
*/ */
Feature(LOGIN_TYPE_LIBRUS, FEATURE_SCHOOL_INFO, listOf( Feature(LoginType.LIBRUS, FeatureType.SCHOOL_INFO, listOf(
ENDPOINT_LIBRUS_API_SCHOOLS to LOGIN_METHOD_LIBRUS_API, ENDPOINT_LIBRUS_API_SCHOOLS to LoginMethod.LIBRUS_API,
ENDPOINT_LIBRUS_API_UNITS to LOGIN_METHOD_LIBRUS_API ENDPOINT_LIBRUS_API_UNITS to LoginMethod.LIBRUS_API
), listOf(LOGIN_METHOD_LIBRUS_API)), )),
/** /**
* Class info - using API. * Class info - using API.
*/ */
Feature(LOGIN_TYPE_LIBRUS, FEATURE_CLASS_INFO, listOf( Feature(LoginType.LIBRUS, FeatureType.CLASS_INFO, listOf(
ENDPOINT_LIBRUS_API_CLASSES to LOGIN_METHOD_LIBRUS_API ENDPOINT_LIBRUS_API_CLASSES to LoginMethod.LIBRUS_API
), listOf(LOGIN_METHOD_LIBRUS_API)), )),
/** /**
* Team info - using API. * Team info - using API.
*/ */
Feature(LOGIN_TYPE_LIBRUS, FEATURE_TEAM_INFO, listOf( Feature(LoginType.LIBRUS, FeatureType.TEAM_INFO, listOf(
ENDPOINT_LIBRUS_API_VIRTUAL_CLASSES to LOGIN_METHOD_LIBRUS_API ENDPOINT_LIBRUS_API_VIRTUAL_CLASSES to LoginMethod.LIBRUS_API
), listOf(LOGIN_METHOD_LIBRUS_API)), )),
/** /**
* Lucky number - using API. * Lucky number - using API.
*/ */
Feature(LOGIN_TYPE_LIBRUS, FEATURE_LUCKY_NUMBER, listOf( Feature(LoginType.LIBRUS, FeatureType.LUCKY_NUMBER, listOf(
ENDPOINT_LIBRUS_API_LUCKY_NUMBER to LOGIN_METHOD_LIBRUS_API ENDPOINT_LIBRUS_API_LUCKY_NUMBER to LoginMethod.LIBRUS_API
), listOf(LOGIN_METHOD_LIBRUS_API)).withShouldSync { data -> data.shouldSyncLuckyNumber() }, )).withShouldSync { data -> data.shouldSyncLuckyNumber() },
/** /**
* Teacher list - using API. * Teacher list - using API.
*/ */
Feature(LOGIN_TYPE_LIBRUS, FEATURE_TEACHERS, listOf( Feature(LoginType.LIBRUS, FeatureType.TEACHERS, listOf(
ENDPOINT_LIBRUS_API_USERS to LOGIN_METHOD_LIBRUS_API ENDPOINT_LIBRUS_API_USERS to LoginMethod.LIBRUS_API
), listOf(LOGIN_METHOD_LIBRUS_API)), )),
/** /**
* Subject list - using API. * Subject list - using API.
*/ */
Feature(LOGIN_TYPE_LIBRUS, FEATURE_SUBJECTS, listOf( Feature(LoginType.LIBRUS, FeatureType.SUBJECTS, listOf(
ENDPOINT_LIBRUS_API_SUBJECTS to LOGIN_METHOD_LIBRUS_API ENDPOINT_LIBRUS_API_SUBJECTS to LoginMethod.LIBRUS_API
), listOf(LOGIN_METHOD_LIBRUS_API)), )),
/** /**
* Classroom list - using API. * Classroom list - using API.
*/ */
Feature(LOGIN_TYPE_LIBRUS, FEATURE_CLASSROOMS, listOf( Feature(LoginType.LIBRUS, FeatureType.CLASSROOMS, listOf(
ENDPOINT_LIBRUS_API_CLASSROOMS to LOGIN_METHOD_LIBRUS_API ENDPOINT_LIBRUS_API_CLASSROOMS to LoginMethod.LIBRUS_API
), listOf(LOGIN_METHOD_LIBRUS_API)), )),
/** /**
* Student info - using synergia scrapper. * Student info - using synergia scrapper.
*/ */
Feature(LOGIN_TYPE_LIBRUS, FEATURE_STUDENT_INFO, listOf( Feature(LoginType.LIBRUS, FeatureType.STUDENT_INFO, listOf(
ENDPOINT_LIBRUS_SYNERGIA_INFO to LOGIN_METHOD_LIBRUS_SYNERGIA ENDPOINT_LIBRUS_SYNERGIA_INFO to LoginMethod.LIBRUS_SYNERGIA
), listOf(LOGIN_METHOD_LIBRUS_SYNERGIA)), )),
/** /**
* Student number - using synergia scrapper. * Student number - using synergia scrapper.
*/ */
Feature(LOGIN_TYPE_LIBRUS, FEATURE_STUDENT_NUMBER, listOf( Feature(LoginType.LIBRUS, FeatureType.STUDENT_NUMBER, listOf(
ENDPOINT_LIBRUS_SYNERGIA_INFO to LOGIN_METHOD_LIBRUS_SYNERGIA ENDPOINT_LIBRUS_SYNERGIA_INFO to LoginMethod.LIBRUS_SYNERGIA
), listOf(LOGIN_METHOD_LIBRUS_SYNERGIA)), )),
/** /**
* Grades - using API + synergia scrapper. * Grades - using API + synergia scrapper.
*/ */
/*Feature(LOGIN_TYPE_LIBRUS, FEATURE_GRADES, listOf( /*Feature(LoginType.LIBRUS, FeatureType.GRADES, listOf(
ENDPOINT_LIBRUS_API_NORMAL_GC to LOGIN_METHOD_LIBRUS_API, ENDPOINT_LIBRUS_API_NORMAL_GC to LoginMethod.LIBRUS_API,
ENDPOINT_LIBRUS_API_NORMAL_GRADES to LOGIN_METHOD_LIBRUS_API, ENDPOINT_LIBRUS_API_NORMAL_GRADES to LoginMethod.LIBRUS_API,
ENDPOINT_LIBRUS_SYNERGIA_GRADES to LOGIN_METHOD_LIBRUS_SYNERGIA ENDPOINT_LIBRUS_SYNERGIA_GRADES to LoginMethod.LIBRUS_SYNERGIA
), listOf(LOGIN_METHOD_LIBRUS_API, LOGIN_METHOD_LIBRUS_SYNERGIA)),*/ )),*/
/*Endpoint(LOGIN_TYPE_LIBRUS, FEATURE_GRADES, listOf( /*Endpoint(LoginType.LIBRUS, FeatureType.GRADES, listOf(
ENDPOINT_LIBRUS_SYNERGIA_GRADES to LOGIN_METHOD_LIBRUS_SYNERGIA ENDPOINT_LIBRUS_SYNERGIA_GRADES to LoginMethod.LIBRUS_SYNERGIA
), listOf(LOGIN_METHOD_LIBRUS_SYNERGIA)),*/ )),*/
/** /**
* Homework - using scrapper. * Homework - using scrapper.
* Sync only if account has not premium access. * Sync only if account has not premium access.
*/ */
Feature(LOGIN_TYPE_LIBRUS, FEATURE_HOMEWORK, listOf( Feature(LoginType.LIBRUS, FeatureType.HOMEWORK, listOf(
ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK to LOGIN_METHOD_LIBRUS_SYNERGIA ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK to LoginMethod.LIBRUS_SYNERGIA
), listOf(LOGIN_METHOD_LIBRUS_SYNERGIA))/*.withShouldSync { data -> ))/*.withShouldSync { data ->
!(data as DataLibrus).isPremium !(data as DataLibrus).isPremium
}*/, }*/,
/** /**
* Messages inbox - using messages website. * Messages inbox - using messages website.
*/ */
Feature(LOGIN_TYPE_LIBRUS, FEATURE_MESSAGES_INBOX, listOf( Feature(LoginType.LIBRUS, FeatureType.MESSAGES_INBOX, listOf(
ENDPOINT_LIBRUS_MESSAGES_RECEIVED to LOGIN_METHOD_LIBRUS_MESSAGES ENDPOINT_LIBRUS_MESSAGES_RECEIVED to LoginMethod.LIBRUS_MESSAGES
), listOf(LOGIN_METHOD_LIBRUS_MESSAGES)), )),
/** /**
* Messages sent - using messages website. * Messages sent - using messages website.
*/ */
Feature(LOGIN_TYPE_LIBRUS, FEATURE_MESSAGES_SENT, listOf( Feature(LoginType.LIBRUS, FeatureType.MESSAGES_SENT, listOf(
ENDPOINT_LIBRUS_MESSAGES_SENT to LOGIN_METHOD_LIBRUS_MESSAGES ENDPOINT_LIBRUS_MESSAGES_SENT to LoginMethod.LIBRUS_MESSAGES
), listOf(LOGIN_METHOD_LIBRUS_MESSAGES)) ))
) )

View File

@ -24,7 +24,7 @@ class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) {
} }
private fun nextEndpoint(onSuccess: () -> Unit) { private fun nextEndpoint(onSuccess: () -> Unit) {
if (data.targetEndpointIds.isEmpty()) { if (data.targetEndpoints.isEmpty()) {
onSuccess() onSuccess()
return return
} }
@ -32,8 +32,8 @@ class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) {
onSuccess() onSuccess()
return return
} }
val id = data.targetEndpointIds.firstKey() val id = data.targetEndpoints.firstKey()
val lastSync = data.targetEndpointIds.remove(id) val lastSync = data.targetEndpoints.remove(id)
useEndpoint(id, lastSync) { endpointId -> useEndpoint(id, lastSync) { endpointId ->
data.progress(data.progressStep) data.progress(data.progressStep)
nextEndpoint(onSuccess) nextEndpoint(onSuccess)

View File

@ -12,6 +12,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
import pl.szczodrzynski.edziennik.data.api.events.AnnouncementGetEvent import pl.szczodrzynski.edziennik.data.api.events.AnnouncementGetEvent
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
class LibrusApiAnnouncementMarkAsRead(override val data: DataLibrus, class LibrusApiAnnouncementMarkAsRead(override val data: DataLibrus,
@ -34,7 +35,7 @@ class LibrusApiAnnouncementMarkAsRead(override val data: DataLibrus,
data.setSeenMetadataList.add(Metadata( data.setSeenMetadataList.add(Metadata(
profileId, profileId,
Metadata.TYPE_ANNOUNCEMENT, MetadataType.ANNOUNCEMENT,
announcement.id, announcement.id,
announcement.seen, announcement.seen,
announcement.notified announcement.notified

View File

@ -11,6 +11,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
import pl.szczodrzynski.edziennik.data.db.entity.Announcement import pl.szczodrzynski.edziennik.data.db.entity.Announcement
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
@ -54,7 +55,7 @@ class LibrusApiAnnouncements(override val data: DataLibrus,
data.announcementList.add(announcementObject) data.announcementList.add(announcementObject)
data.setSeenMetadataList.add(Metadata( data.setSeenMetadataList.add(Metadata(
profileId, profileId,
Metadata.TYPE_ANNOUNCEMENT, MetadataType.ANNOUNCEMENT,
id, id,
read, read,
profile.empty || read profile.empty || read

View File

@ -12,6 +12,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
import pl.szczodrzynski.edziennik.data.db.entity.Attendance import pl.szczodrzynski.edziennik.data.db.entity.Attendance
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
@ -76,7 +77,7 @@ class LibrusApiAttendances(override val data: DataLibrus,
if(type?.baseType != Attendance.TYPE_PRESENT) { if(type?.baseType != Attendance.TYPE_PRESENT) {
data.metadataList.add(Metadata( data.metadataList.add(Metadata(
profileId, profileId,
Metadata.TYPE_ATTENDANCE, MetadataType.ATTENDANCE,
id, id,
profile?.empty ?: false || type?.baseType == Attendance.TYPE_PRESENT_CUSTOM || type?.baseType == Attendance.TYPE_UNKNOWN, profile?.empty ?: false || type?.baseType == Attendance.TYPE_PRESENT_CUSTOM || type?.baseType == Attendance.TYPE_UNKNOWN,
profile?.empty ?: false || type?.baseType == Attendance.TYPE_PRESENT_CUSTOM || type?.baseType == Attendance.TYPE_UNKNOWN profile?.empty ?: false || type?.baseType == Attendance.TYPE_PRESENT_CUSTOM || type?.baseType == Attendance.TYPE_UNKNOWN

View File

@ -14,6 +14,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_POINT_SUM
import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
import java.text.DecimalFormat import java.text.DecimalFormat
@ -63,7 +64,7 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
data.gradeList.add(semester1StartGradeObject) data.gradeList.add(semester1StartGradeObject)
data.metadataList.add(Metadata( data.metadataList.add(Metadata(
profileId, profileId,
Metadata.TYPE_GRADE, MetadataType.GRADE,
semester1StartGradeObject.id, semester1StartGradeObject.id,
true, true,
true true
@ -91,7 +92,7 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
data.gradeList.add(semester2StartGradeObject) data.gradeList.add(semester2StartGradeObject)
data.metadataList.add(Metadata( data.metadataList.add(Metadata(
profileId, profileId,
Metadata.TYPE_GRADE, MetadataType.GRADE,
semester2StartGradeObject.id, semester2StartGradeObject.id,
true, true,
true true
@ -165,7 +166,7 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
data.gradeList.add(gradeObject) data.gradeList.add(gradeObject)
data.metadataList.add(Metadata( data.metadataList.add(Metadata(
profileId, profileId,
Metadata.TYPE_GRADE, MetadataType.GRADE,
id, id,
profile.empty, profile.empty,
profile.empty profile.empty

View File

@ -15,6 +15,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_TEXT
import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
@ -73,7 +74,7 @@ class LibrusApiDescriptiveGrades(override val data: DataLibrus,
data.gradeList.add(gradeObject) data.gradeList.add(gradeObject)
data.metadataList.add(Metadata( data.metadataList.add(Metadata(
profileId, profileId,
Metadata.TYPE_GRADE, MetadataType.GRADE,
id, id,
profile.empty, profile.empty,
profile.empty profile.empty

View File

@ -13,6 +13,7 @@ import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
import pl.szczodrzynski.edziennik.data.db.entity.Event import pl.szczodrzynski.edziennik.data.db.entity.Event
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.*
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
@ -71,7 +72,7 @@ class LibrusApiEvents(override val data: DataLibrus,
data.metadataList.add( data.metadataList.add(
Metadata( Metadata(
profileId, profileId,
Metadata.TYPE_EVENT, MetadataType.EVENT,
id, id,
profile?.empty ?: false, profile?.empty ?: false,
profile?.empty ?: false profile?.empty ?: false

View File

@ -4,7 +4,6 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi

View File

@ -16,6 +16,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_YEAR_PROPO
import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.utils.Utils import pl.szczodrzynski.edziennik.utils.Utils
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
@ -97,7 +98,7 @@ class LibrusApiGrades(override val data: DataLibrus,
data.metadataList.add( data.metadataList.add(
Metadata( Metadata(
profileId, profileId,
Metadata.TYPE_GRADE, MetadataType.GRADE,
id, id,
profile.empty, profile.empty,
profile.empty profile.empty

View File

@ -12,6 +12,7 @@ import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
import pl.szczodrzynski.edziennik.data.db.entity.Event import pl.szczodrzynski.edziennik.data.db.entity.Event
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
@ -51,7 +52,7 @@ class LibrusApiHomework(override val data: DataLibrus,
data.eventList.add(eventObject) data.eventList.add(eventObject)
data.metadataList.add(Metadata( data.metadataList.add(Metadata(
profileId, profileId,
Metadata.TYPE_HOMEWORK, MetadataType.HOMEWORK,
id, id,
profile?.empty ?: false, profile?.empty ?: false,
profile?.empty ?: false profile?.empty ?: false

View File

@ -4,7 +4,6 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_LESSONS import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_LESSONS
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi

View File

@ -9,6 +9,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
import pl.szczodrzynski.edziennik.data.db.entity.LuckyNumber import pl.szczodrzynski.edziennik.data.db.entity.LuckyNumber
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.*
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
@ -47,7 +48,7 @@ class LibrusApiLuckyNumber(override val data: DataLibrus,
data.metadataList.add( data.metadataList.add(
Metadata( Metadata(
profileId, profileId,
Metadata.TYPE_LUCKY_NUMBER, MetadataType.LUCKY_NUMBER,
luckyNumberObject.date.value.toLong(), luckyNumberObject.date.value.toLong(),
true, true,
profile?.empty ?: false profile?.empty ?: false

View File

@ -12,6 +12,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.Notice import pl.szczodrzynski.edziennik.data.db.entity.Notice
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
@ -35,7 +36,7 @@ class LibrusApiNotices(override val data: DataLibrus,
val id = note.getLong("Id") ?: return@forEach val id = note.getLong("Id") ?: return@forEach
val text = note.getString("Text") ?: "" val text = note.getString("Text") ?: ""
val categoryId = note.getJsonObject("Category")?.getLong("Id") ?: -1 val categoryId = note.getJsonObject("Category")?.getLong("Id") ?: -1
val teacherId = note.getJsonObject("AddedBy")?.getLong("Id") ?: -1 val teacherId = note.getJsonObject("Teacher")?.getLong("Id") ?: -1
val addedDate = note.getString("Date")?.let { Date.fromY_m_d(it) } ?: return@forEach val addedDate = note.getString("Date")?.let { Date.fromY_m_d(it) } ?: return@forEach
val type = when (note.getInt("Positive")) { val type = when (note.getInt("Positive")) {
@ -62,7 +63,7 @@ class LibrusApiNotices(override val data: DataLibrus,
data.metadataList.add( data.metadataList.add(
Metadata( Metadata(
profileId, profileId,
Metadata.TYPE_NOTICE, MetadataType.NOTICE,
id, id,
profile?.empty ?: false, profile?.empty ?: false,
profile?.empty ?: false profile?.empty ?: false

View File

@ -14,6 +14,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_POINT_AVG
import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
@ -66,7 +67,7 @@ class LibrusApiPointGrades(override val data: DataLibrus,
data.gradeList.add(gradeObject) data.gradeList.add(gradeObject)
data.metadataList.add(Metadata( data.metadataList.add(Metadata(
profileId, profileId,
Metadata.TYPE_GRADE, MetadataType.GRADE,
id, id,
profile.empty, profile.empty,
profile.empty profile.empty

View File

@ -11,6 +11,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
import pl.szczodrzynski.edziennik.data.db.entity.Event import pl.szczodrzynski.edziennik.data.db.entity.Event
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.*
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
@ -56,7 +57,7 @@ class LibrusApiPtMeetings(override val data: DataLibrus,
data.metadataList.add( data.metadataList.add(
Metadata( Metadata(
profileId, profileId,
Metadata.TYPE_EVENT, MetadataType.EVENT,
id, id,
profile?.empty ?: false, profile?.empty ?: false,
profile?.empty ?: false profile?.empty ?: false

View File

@ -4,14 +4,12 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_SCHOOLS import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_SCHOOLS
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
import pl.szczodrzynski.edziennik.data.db.entity.LessonRange import pl.szczodrzynski.edziennik.data.db.entity.LessonRange
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.utils.models.Time import pl.szczodrzynski.edziennik.utils.models.Time
import java.util.*
class LibrusApiSchools(override val data: DataLibrus, class LibrusApiSchools(override val data: DataLibrus,
override val lastSync: Long?, override val lastSync: Long?,

View File

@ -4,7 +4,6 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_SUBJECTS import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_SUBJECTS
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi

View File

@ -5,13 +5,13 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
import androidx.core.util.isEmpty import androidx.core.util.isEmpty
import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_AGENDA
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_TEACHER_FREE_DAYS import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_TEACHER_FREE_DAYS
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.TeacherAbsence import pl.szczodrzynski.edziennik.data.db.entity.TeacherAbsence
import pl.szczodrzynski.edziennik.data.db.enums.FeatureType
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.*
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
@ -56,14 +56,14 @@ class LibrusApiTeacherFreeDays(override val data: DataLibrus,
data.teacherAbsenceList.add(teacherAbsenceObject) data.teacherAbsenceList.add(teacherAbsenceObject)
data.metadataList.add(Metadata( data.metadataList.add(Metadata(
profileId, profileId,
Metadata.TYPE_TEACHER_ABSENCE, MetadataType.TEACHER_ABSENCE,
id, id,
true, true,
profile?.empty ?: false profile?.empty ?: false
)) ))
} }
data.setSyncNext(ENDPOINT_LIBRUS_API_TEACHER_FREE_DAYS, 6* HOUR, DRAWER_ITEM_AGENDA) data.setSyncNext(ENDPOINT_LIBRUS_API_TEACHER_FREE_DAYS, 6* HOUR, FeatureType.AGENDA)
onSuccess(ENDPOINT_LIBRUS_API_TEACHER_FREE_DAYS) onSuccess(ENDPOINT_LIBRUS_API_TEACHER_FREE_DAYS)
} }
} }

View File

@ -14,6 +14,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_DESCRIPTIV
import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
@ -68,7 +69,7 @@ class LibrusApiTextGrades(override val data: DataLibrus,
data.gradeList.add(gradeObject) data.gradeList.add(gradeObject)
data.metadataList.add(Metadata( data.metadataList.add(Metadata(
profileId, profileId,
Metadata.TYPE_GRADE, MetadataType.GRADE,
id, id,
profile.empty, profile.empty,
profile.empty profile.empty

View File

@ -14,6 +14,7 @@ import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
import pl.szczodrzynski.edziennik.data.db.entity.Lesson import pl.szczodrzynski.edziennik.data.db.entity.Lesson
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.utils.Utils.d import pl.szczodrzynski.edziennik.utils.Utils.d
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
@ -189,6 +190,7 @@ class LibrusApiTimetables(override val data: DataLibrus,
} }
lessonObject.id = lessonObject.buildId() lessonObject.id = lessonObject.buildId()
lessonObject.ownerId = lessonObject.buildOwnerId()
val seen = profile.empty || lessonDate < Date.getToday() val seen = profile.empty || lessonDate < Date.getToday()
@ -196,7 +198,7 @@ class LibrusApiTimetables(override val data: DataLibrus,
data.metadataList.add( data.metadataList.add(
Metadata( Metadata(
profileId, profileId,
Metadata.TYPE_LESSON_CHANGE, MetadataType.LESSON_CHANGE,
lessonObject.id, lessonObject.id,
seen, seen,
seen seen

View File

@ -4,7 +4,6 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_MESSAGES
import pl.szczodrzynski.edziennik.data.api.ERROR_NOT_IMPLEMENTED import pl.szczodrzynski.edziennik.data.api.ERROR_NOT_IMPLEMENTED
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_MESSAGES_RECEIVED import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_MESSAGES_RECEIVED
@ -12,6 +11,8 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_MESS
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusMessages import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusMessages
import pl.szczodrzynski.edziennik.data.db.entity.* import pl.szczodrzynski.edziennik.data.db.entity.*
import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED
import pl.szczodrzynski.edziennik.data.db.enums.FeatureType
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.DAY import pl.szczodrzynski.edziennik.ext.DAY
import pl.szczodrzynski.edziennik.ext.fixName import pl.szczodrzynski.edziennik.ext.fixName
import pl.szczodrzynski.edziennik.ext.singleOrNull import pl.szczodrzynski.edziennik.ext.singleOrNull
@ -65,16 +66,17 @@ class LibrusMessagesGetList(override val data: DataLibrus,
val recipientId = data.teacherList.singleOrNull { val recipientId = data.teacherList.singleOrNull {
it.name == recipientFirstName && it.surname == recipientLastName it.name == recipientFirstName && it.surname == recipientLastName
}?.id ?: { }?.id ?: run {
val teacherObject = Teacher( val teacherObject = Teacher(
profileId, profileId,
-1 * Utils.crc16("$recipientFirstName $recipientLastName".toByteArray()).toLong(), -1 * Utils.crc16("$recipientFirstName $recipientLastName".toByteArray())
.toLong(),
recipientFirstName, recipientFirstName,
recipientLastName recipientLastName
) )
data.teacherList.put(teacherObject.id, teacherObject) data.teacherList.put(teacherObject.id, teacherObject)
teacherObject.id teacherObject.id
}.invoke() }
val senderId = when (type) { val senderId = when (type) {
TYPE_RECEIVED -> recipientId TYPE_RECEIVED -> recipientId
@ -118,7 +120,7 @@ class LibrusMessagesGetList(override val data: DataLibrus,
data.messageRecipientList.add(messageRecipientObject) data.messageRecipientList.add(messageRecipientObject)
data.setSeenMetadataList.add(Metadata( data.setSeenMetadataList.add(Metadata(
profileId, profileId,
Metadata.TYPE_MESSAGE, MetadataType.MESSAGE,
id, id,
notified, notified,
notified notified
@ -127,7 +129,7 @@ class LibrusMessagesGetList(override val data: DataLibrus,
when (type) { when (type) {
TYPE_RECEIVED -> data.setSyncNext(ENDPOINT_LIBRUS_MESSAGES_RECEIVED, SYNC_ALWAYS) TYPE_RECEIVED -> data.setSyncNext(ENDPOINT_LIBRUS_MESSAGES_RECEIVED, SYNC_ALWAYS)
Message.TYPE_SENT -> data.setSyncNext(ENDPOINT_LIBRUS_MESSAGES_SENT, DAY, DRAWER_ITEM_MESSAGES) Message.TYPE_SENT -> data.setSyncNext(ENDPOINT_LIBRUS_MESSAGES_SENT, DAY, FeatureType.MESSAGES_SENT)
} }
onSuccess(endpointId) onSuccess(endpointId)
} }

View File

@ -13,6 +13,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED
import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.Teacher import pl.szczodrzynski.edziennik.data.db.entity.Teacher
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.data.db.full.MessageFull import pl.szczodrzynski.edziennik.data.db.full.MessageFull
import pl.szczodrzynski.edziennik.data.db.full.MessageRecipientFull import pl.szczodrzynski.edziennik.data.db.full.MessageRecipientFull
import pl.szczodrzynski.edziennik.ext.fixName import pl.szczodrzynski.edziennik.ext.fixName
@ -124,7 +125,7 @@ class LibrusMessagesGetMessage(override val data: DataLibrus,
val receiverId = teacher?.id ?: -1 val receiverId = teacher?.id ?: -1
teacher?.loginId = receiverLoginId teacher?.loginId = receiverLoginId
val readDateText = message.select("readed").text() val readDateText = receiver.select("readed").text()
val readDate = when (readDateText.isNotNullNorEmpty()) { val readDate = when (readDateText.isNotNullNorEmpty()) {
true -> Date.fromIso(readDateText) true -> Date.fromIso(readDateText)
else -> 0 else -> 0
@ -147,7 +148,7 @@ class LibrusMessagesGetMessage(override val data: DataLibrus,
if (!messageObject.seen) { if (!messageObject.seen) {
data.setSeenMetadataList.add(Metadata( data.setSeenMetadataList.add(Metadata(
messageObject.profileId, messageObject.profileId,
Metadata.TYPE_MESSAGE, MetadataType.MESSAGE,
messageObject.id, messageObject.id,
true, true,
true true

View File

@ -16,7 +16,7 @@ import pl.szczodrzynski.edziennik.ext.getLong
import pl.szczodrzynski.edziennik.ext.getString import pl.szczodrzynski.edziennik.ext.getString
class LibrusMessagesSendMessage(override val data: DataLibrus, class LibrusMessagesSendMessage(override val data: DataLibrus,
val recipients: List<Teacher>, val recipients: Set<Teacher>,
val subject: String, val subject: String,
val text: String, val text: String,
val onSuccess: () -> Unit val onSuccess: () -> Unit

View File

@ -8,6 +8,7 @@ import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent
import pl.szczodrzynski.edziennik.data.db.entity.Message import pl.szczodrzynski.edziennik.data.db.entity.Message
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.Teacher import pl.szczodrzynski.edziennik.data.db.entity.Teacher
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.data.db.full.MessageFull import pl.szczodrzynski.edziennik.data.db.full.MessageFull
import pl.szczodrzynski.edziennik.data.db.full.MessageRecipientFull import pl.szczodrzynski.edziennik.data.db.full.MessageRecipientFull
import pl.szczodrzynski.edziennik.ext.get import pl.szczodrzynski.edziennik.ext.get
@ -139,7 +140,7 @@ class LibrusSynergiaGetMessage(override val data: DataLibrus,
if (!messageObject.seen) { if (!messageObject.seen) {
data.setSeenMetadataList.add(Metadata( data.setSeenMetadataList.add(Metadata(
messageObject.profileId, messageObject.profileId,
Metadata.TYPE_MESSAGE, MetadataType.MESSAGE,
messageObject.id, messageObject.id,
true, true,
true true

View File

@ -1,12 +1,13 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia
import org.jsoup.Jsoup import org.jsoup.Jsoup
import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.ERROR_NOT_IMPLEMENTED import pl.szczodrzynski.edziennik.data.api.ERROR_NOT_IMPLEMENTED
import pl.szczodrzynski.edziennik.data.api.Regexes import pl.szczodrzynski.edziennik.data.api.Regexes
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.* import pl.szczodrzynski.edziennik.data.api.edziennik.librus.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusSynergia import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusSynergia
import pl.szczodrzynski.edziennik.data.db.entity.* import pl.szczodrzynski.edziennik.data.db.entity.*
import pl.szczodrzynski.edziennik.data.db.enums.FeatureType
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.utils.Utils import pl.szczodrzynski.edziennik.utils.Utils
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
@ -96,7 +97,7 @@ class LibrusSynergiaGetMessages(override val data: DataLibrus,
data.messageRecipientList.add(messageRecipientObject) data.messageRecipientList.add(messageRecipientObject)
data.setSeenMetadataList.add(Metadata( data.setSeenMetadataList.add(Metadata(
profileId, profileId,
Metadata.TYPE_MESSAGE, MetadataType.MESSAGE,
id, id,
notified, notified,
notified notified
@ -105,7 +106,7 @@ class LibrusSynergiaGetMessages(override val data: DataLibrus,
when (type) { when (type) {
Message.TYPE_RECEIVED -> data.setSyncNext(ENDPOINT_LIBRUS_MESSAGES_RECEIVED, SYNC_ALWAYS) Message.TYPE_RECEIVED -> data.setSyncNext(ENDPOINT_LIBRUS_MESSAGES_RECEIVED, SYNC_ALWAYS)
Message.TYPE_SENT -> data.setSyncNext(ENDPOINT_LIBRUS_MESSAGES_SENT, DAY, MainActivity.DRAWER_ITEM_MESSAGES) Message.TYPE_SENT -> data.setSyncNext(ENDPOINT_LIBRUS_MESSAGES_SENT, DAY, FeatureType.MESSAGES_SENT)
} }
onSuccess(endpointId) onSuccess(endpointId)
} }

View File

@ -5,7 +5,6 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia
import org.jsoup.Jsoup import org.jsoup.Jsoup
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_HOMEWORK
import pl.szczodrzynski.edziennik.data.api.POST import pl.szczodrzynski.edziennik.data.api.POST
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK
@ -13,8 +12,11 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusSynergia
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
import pl.szczodrzynski.edziennik.data.db.entity.Event import pl.szczodrzynski.edziennik.data.db.entity.Event
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.enums.FeatureType
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.HOUR import pl.szczodrzynski.edziennik.ext.HOUR
import pl.szczodrzynski.edziennik.ext.get import pl.szczodrzynski.edziennik.ext.get
import pl.szczodrzynski.edziennik.ext.getSemesterStart
import pl.szczodrzynski.edziennik.ext.singleOrNull import pl.szczodrzynski.edziennik.ext.singleOrNull
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
@ -84,7 +86,7 @@ class LibrusSynergiaHomework(override val data: DataLibrus,
data.eventList.add(eventObject) data.eventList.add(eventObject)
data.metadataList.add(Metadata( data.metadataList.add(Metadata(
profileId, profileId,
Metadata.TYPE_HOMEWORK, MetadataType.HOMEWORK,
id, id,
seen, seen,
seen seen
@ -95,7 +97,7 @@ class LibrusSynergiaHomework(override val data: DataLibrus,
data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_HOMEWORK)) data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_HOMEWORK))
// because this requires a synergia login (2 more requests!!!) sync this every few hours or if explicit :D // because this requires a synergia login (2 more requests!!!) sync this every few hours or if explicit :D
data.setSyncNext(ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK, 5 * HOUR, DRAWER_ITEM_HOMEWORK) data.setSyncNext(ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK, 5 * HOUR, FeatureType.HOMEWORK)
onSuccess(ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK) onSuccess(ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK)
} }
} ?: onSuccess(ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK) } } ?: onSuccess(ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK) }

View File

@ -7,6 +7,7 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusSynergia import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusSynergia
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
class LibrusSynergiaMarkAllAnnouncementsAsRead(override val data: DataLibrus, class LibrusSynergiaMarkAllAnnouncementsAsRead(override val data: DataLibrus,
val onSuccess: () -> Unit val onSuccess: () -> Unit
@ -17,7 +18,7 @@ class LibrusSynergiaMarkAllAnnouncementsAsRead(override val data: DataLibrus,
init { init {
synergiaGet(TAG, "ogloszenia") { synergiaGet(TAG, "ogloszenia") {
data.app.db.metadataDao().setAllSeen(profileId, Metadata.TYPE_ANNOUNCEMENT, true) data.app.db.metadataDao().setAllSeen(profileId, MetadataType.ANNOUNCEMENT, true)
onSuccess() onSuccess()
} }
} }

View File

@ -11,6 +11,8 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLoginPor
import pl.szczodrzynski.edziennik.data.api.events.FirstLoginFinishedEvent import pl.szczodrzynski.edziennik.data.api.events.FirstLoginFinishedEvent
import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.db.entity.Profile import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.db.enums.LoginMode
import pl.szczodrzynski.edziennik.data.db.enums.LoginType
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.*
class LibrusFirstLogin(val data: DataLibrus, val onSuccess: () -> Unit) { class LibrusFirstLogin(val data: DataLibrus, val onSuccess: () -> Unit) {
@ -23,11 +25,9 @@ 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 var firstProfileId = data.loginStore.id
val loginStoreType = LOGIN_TYPE_LIBRUS
var firstProfileId = loginStoreId
if (data.loginStore.mode == LOGIN_MODE_LIBRUS_EMAIL) { if (data.loginStore.mode == LoginMode.LIBRUS_EMAIL) {
// email login: use Portal for account list // email login: use Portal for account list
LibrusLoginPortal(data) { LibrusLoginPortal(data) {
portal.portalGet(TAG, if (data.fakeLogin) FAKE_LIBRUS_ACCOUNTS else LIBRUS_ACCOUNTS_URL) { json, response -> portal.portalGet(TAG, if (data.fakeLogin) FAKE_LIBRUS_ACCOUNTS else LIBRUS_ACCOUNTS_URL) { json, response ->
@ -66,8 +66,8 @@ class LibrusFirstLogin(val data: DataLibrus, val onSuccess: () -> Unit) {
val profile = Profile( val profile = Profile(
firstProfileId++, firstProfileId++,
loginStoreId, data.loginStore.id,
loginStoreType, LoginType.LIBRUS,
studentNameLong, studentNameLong,
data.portalEmail, data.portalEmail,
studentNameLong, studentNameLong,
@ -107,8 +107,8 @@ class LibrusFirstLogin(val data: DataLibrus, val onSuccess: () -> Unit) {
val profile = Profile( val profile = Profile(
firstProfileId++, firstProfileId++,
loginStoreId, data.loginStore.id,
loginStoreType, LoginType.LIBRUS,
studentNameLong, studentNameLong,
login, login,
studentNameLong, studentNameLong,

View File

@ -5,11 +5,8 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.login package pl.szczodrzynski.edziennik.data.api.edziennik.librus.login
import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_LIBRUS_API
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_LIBRUS_MESSAGES
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_LIBRUS_PORTAL
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_LIBRUS_SYNERGIA
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.db.enums.LoginMethod
import pl.szczodrzynski.edziennik.utils.Utils import pl.szczodrzynski.edziennik.utils.Utils
class LibrusLogin(val data: DataLibrus, val onSuccess: () -> Unit) { class LibrusLogin(val data: DataLibrus, val onSuccess: () -> Unit) {
@ -24,7 +21,7 @@ class LibrusLogin(val data: DataLibrus, val onSuccess: () -> Unit) {
} }
private fun nextLoginMethod(onSuccess: () -> Unit) { private fun nextLoginMethod(onSuccess: () -> Unit) {
if (data.targetLoginMethodIds.isEmpty()) { if (data.targetLoginMethods.isEmpty()) {
onSuccess() onSuccess()
return return
} }
@ -32,38 +29,39 @@ class LibrusLogin(val data: DataLibrus, val onSuccess: () -> Unit) {
onSuccess() onSuccess()
return return
} }
useLoginMethod(data.targetLoginMethodIds.removeAt(0)) { usedMethodId -> useLoginMethod(data.targetLoginMethods.removeAt(0)) { usedMethod ->
data.progress(data.progressStep) data.progress(data.progressStep)
if (usedMethodId != -1) if (usedMethod != null)
data.loginMethods.add(usedMethodId) data.loginMethods.add(usedMethod)
nextLoginMethod(onSuccess) nextLoginMethod(onSuccess)
} }
} }
private fun useLoginMethod(loginMethodId: Int, onSuccess: (usedMethodId: Int) -> Unit) { private fun useLoginMethod(loginMethod: LoginMethod, onSuccess: (usedMethod: LoginMethod?) -> Unit) {
// this should never be true // this should never be true
if (data.loginMethods.contains(loginMethodId)) { if (data.loginMethods.contains(loginMethod)) {
onSuccess(-1) onSuccess(null)
return return
} }
Utils.d(TAG, "Using login method $loginMethodId") Utils.d(TAG, "Using login method $loginMethod")
when (loginMethodId) { when (loginMethod) {
LOGIN_METHOD_LIBRUS_PORTAL -> { LoginMethod.LIBRUS_PORTAL -> {
data.startProgress(R.string.edziennik_progress_login_librus_portal) data.startProgress(R.string.edziennik_progress_login_librus_portal)
LibrusLoginPortal(data) { onSuccess(loginMethodId) } LibrusLoginPortal(data) { onSuccess(loginMethod) }
} }
LOGIN_METHOD_LIBRUS_API -> { LoginMethod.LIBRUS_API -> {
data.startProgress(R.string.edziennik_progress_login_librus_api) data.startProgress(R.string.edziennik_progress_login_librus_api)
LibrusLoginApi(data) { onSuccess(loginMethodId) } LibrusLoginApi(data) { onSuccess(loginMethod) }
} }
LOGIN_METHOD_LIBRUS_SYNERGIA -> { LoginMethod.LIBRUS_SYNERGIA -> {
data.startProgress(R.string.edziennik_progress_login_librus_synergia) data.startProgress(R.string.edziennik_progress_login_librus_synergia)
LibrusLoginSynergia(data) { onSuccess(loginMethodId) } LibrusLoginSynergia(data) { onSuccess(loginMethod) }
} }
LOGIN_METHOD_LIBRUS_MESSAGES -> { LoginMethod.LIBRUS_MESSAGES -> {
data.startProgress(R.string.edziennik_progress_login_librus_messages) data.startProgress(R.string.edziennik_progress_login_librus_messages)
LibrusLoginMessages(data) { onSuccess(loginMethodId) } LibrusLoginMessages(data) { onSuccess(loginMethod) }
} }
else -> {}
} }
} }
} }

View File

@ -12,6 +12,8 @@ import im.wangchao.mhttp.callback.JsonCallbackHandler
import pl.szczodrzynski.edziennik.data.api.* import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.db.enums.LoginMethod
import pl.szczodrzynski.edziennik.data.db.enums.LoginMode
import pl.szczodrzynski.edziennik.ext.getInt import pl.szczodrzynski.edziennik.ext.getInt
import pl.szczodrzynski.edziennik.ext.getString import pl.szczodrzynski.edziennik.ext.getString
import pl.szczodrzynski.edziennik.ext.getUnixDate import pl.szczodrzynski.edziennik.ext.getUnixDate
@ -32,7 +34,7 @@ class LibrusLoginApi {
this.data = data this.data = data
this.onSuccess = onSuccess this.onSuccess = onSuccess
if (data.loginStore.mode == LOGIN_MODE_LIBRUS_EMAIL && data.profile == null) { if (data.loginStore.mode == LoginMode.LIBRUS_EMAIL && data.profile == null) {
data.error(ApiError(TAG, ERROR_PROFILE_MISSING)) data.error(ApiError(TAG, ERROR_PROFILE_MISSING))
return return
} }
@ -42,9 +44,9 @@ class LibrusLoginApi {
} }
else { else {
when (data.loginStore.mode) { when (data.loginStore.mode) {
LOGIN_MODE_LIBRUS_EMAIL -> loginWithPortal() LoginMode.LIBRUS_EMAIL -> loginWithPortal()
LOGIN_MODE_LIBRUS_SYNERGIA -> loginWithSynergia() LoginMode.LIBRUS_SYNERGIA -> loginWithSynergia()
LOGIN_MODE_LIBRUS_JST -> loginWithJst() LoginMode.LIBRUS_JST -> loginWithJst()
else -> { else -> {
data.error(ApiError(TAG, ERROR_INVALID_LOGIN_MODE)) data.error(ApiError(TAG, ERROR_INVALID_LOGIN_MODE))
} }
@ -53,7 +55,7 @@ class LibrusLoginApi {
} }
private fun loginWithPortal() { private fun loginWithPortal() {
if (!data.loginMethods.contains(LOGIN_METHOD_LIBRUS_PORTAL)) { if (!data.loginMethods.contains(LoginMethod.LIBRUS_PORTAL)) {
data.error(ApiError(TAG, ERROR_LOGIN_METHOD_NOT_SATISFIED)) data.error(ApiError(TAG, ERROR_LOGIN_METHOD_NOT_SATISFIED))
return return
} }

View File

@ -12,6 +12,7 @@ import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.LibrusRecaptchaHelper import pl.szczodrzynski.edziennik.data.api.edziennik.librus.LibrusRecaptchaHelper
import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.db.enums.LoginMethod
import pl.szczodrzynski.edziennik.ext.getUnixDate import pl.szczodrzynski.edziennik.ext.getUnixDate
import pl.szczodrzynski.edziennik.utils.Utils.d import pl.szczodrzynski.edziennik.utils.Utils.d
import java.io.StringWriter import java.io.StringWriter
@ -91,7 +92,7 @@ class LibrusLoginMessages(val data: DataLibrus, val onSuccess: () -> Unit) {
} }
else { else {
data.app.cookieJar.clear("wiadomosci.librus.pl") data.app.cookieJar.clear("wiadomosci.librus.pl")
if (data.loginMethods.contains(LOGIN_METHOD_LIBRUS_SYNERGIA)) { if (data.loginMethods.contains(LoginMethod.LIBRUS_SYNERGIA)) {
loginWithSynergia() loginWithSynergia()
} }
else if (data.apiLogin != null && data.apiPassword != null && false) { else if (data.apiLogin != null && data.apiPassword != null && false) {

View File

@ -10,7 +10,9 @@ import im.wangchao.mhttp.callback.TextCallbackHandler
import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.* import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.events.UserActionRequiredEvent
import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.db.enums.LoginMode
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.utils.Utils.d import pl.szczodrzynski.edziennik.utils.Utils.d
import java.net.HttpURLConnection.* import java.net.HttpURLConnection.*
@ -22,8 +24,11 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
private const val TAG = "LoginLibrusPortal" private const val TAG = "LoginLibrusPortal"
} }
// loop failsafe
private var loginPerformed = false
init { run { init { run {
if (data.loginStore.mode != LOGIN_MODE_LIBRUS_EMAIL) { if (data.loginStore.mode != LoginMode.LIBRUS_EMAIL) {
data.error(ApiError(TAG, ERROR_INVALID_LOGIN_MODE)) data.error(ApiError(TAG, ERROR_INVALID_LOGIN_MODE))
return@run return@run
} }
@ -31,6 +36,7 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
data.error(ApiError(TAG, ERROR_LOGIN_DATA_MISSING)) data.error(ApiError(TAG, ERROR_LOGIN_DATA_MISSING))
return@run return@run
} }
loginPerformed = false
// succeed having a non-expired access token and a refresh token // succeed having a non-expired access token and a refresh token
if (data.isPortalLoginValid()) { if (data.isPortalLoginValid()) {
@ -56,18 +62,23 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
} }
}} }}
private fun authorize(url: String?) { private fun authorize(url: String, referer: String? = null) {
d(TAG, "Request: Librus/Login/Portal - $url") d(TAG, "Request: Librus/Login/Portal - $url")
Request.builder() Request.builder()
.url(url) .url(url)
.userAgent(LIBRUS_USER_AGENT) .userAgent(LIBRUS_USER_AGENT)
.also {
if (referer != null)
it.addHeader("Referer", referer)
}
.addHeader("X-Requested-With", LIBRUS_HEADER)
.withClient(data.app.httpLazy) .withClient(data.app.httpLazy)
.callback(object : TextCallbackHandler() { .callback(object : TextCallbackHandler() {
override fun onSuccess(text: String, response: Response) { override fun onSuccess(text: String, response: Response) {
val location = response.headers().get("Location") val location = response.headers().get("Location")
if (location != null) { if (location != null) {
val authMatcher = Pattern.compile("$LIBRUS_REDIRECT_URL\\?code=([A-z0-9]+?)$", Pattern.DOTALL or Pattern.MULTILINE).matcher(location) val authMatcher = Pattern.compile("$LIBRUS_REDIRECT_URL\\?code=([^&?]+)", Pattern.DOTALL or Pattern.MULTILINE).matcher(location)
when { when {
authMatcher.find() -> { authMatcher.find() -> {
accessToken(authMatcher.group(1), null) accessToken(authMatcher.group(1), null)
@ -81,16 +92,31 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
authorize(location) authorize(location)
} }
} }
} else { return
val csrfMatcher = Pattern.compile("name=\"csrf-token\" content=\"([A-z0-9=+/\\-_]+?)\"", Pattern.DOTALL).matcher(text) }
if (csrfMatcher.find()) {
login(csrfMatcher.group(1) ?: "") if (checkError(text, response))
} else { return
data.error(ApiError(TAG, ERROR_LOGIN_LIBRUS_PORTAL_CSRF_MISSING)
.withResponse(response) var loginUrl = if (data.fakeLogin) FAKE_LIBRUS_LOGIN else LIBRUS_LOGIN_URL
.withApiResponse(text)) val csrfToken = Regexes.HTML_CSRF_TOKEN.find(text)?.get(1) ?: ""
for (match in Regexes.HTML_FORM_ACTION.findAll(text)) {
val form = match.value.lowercase()
if ("login" in form && "post" in form) {
loginUrl = match[1]
} }
} }
val params = mutableMapOf<String, String>()
for (match in Regexes.HTML_INPUT_HIDDEN.findAll(text)) {
val input = match.value
val name = Regexes.HTML_INPUT_NAME.find(input)?.get(1) ?: continue
val value = Regexes.HTML_INPUT_VALUE.find(input)?.get(1) ?: continue
params[name] = value
}
login(url = loginUrl, referer = url, csrfToken, params)
} }
override fun onFailure(response: Response, throwable: Throwable) { override fun onFailure(response: Response, throwable: Throwable) {
@ -103,8 +129,54 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
.enqueue() .enqueue()
} }
private fun login(csrfToken: String) { private fun checkError(text: String, response: Response): Boolean {
d(TAG, "Request: Librus/Login/Portal - ${if (data.fakeLogin) FAKE_LIBRUS_LOGIN else LIBRUS_LOGIN_URL}") when {
text.contains("librus_account_settings_main") -> return false
text.contains("Sesja logowania wygasła") -> ERROR_LOGIN_LIBRUS_PORTAL_CSRF_EXPIRED
text.contains("Upewnij się, że nie") -> ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN
text.contains("Podany adres e-mail jest nieprawidłowy.") -> ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN
else -> null // no error for now
}?.let { errorCode ->
data.error(ApiError(TAG, errorCode)
.withApiResponse(text)
.withResponse(response))
return true
}
if ("robotem" in text || "g-recaptcha" in text || "captchaValidate" in text) {
val siteKey = Regexes.HTML_RECAPTCHA_KEY.find(text)?.get(1)
if (siteKey == null) {
data.error(ApiError(TAG, ERROR_LOGIN_LIBRUS_PORTAL_ACTION_ERROR)
.withApiResponse(text)
.withResponse(response))
return true
}
data.requireUserAction(
type = UserActionRequiredEvent.Type.RECAPTCHA,
params = Bundle(
"siteKey" to siteKey,
"referer" to response.request().url().toString(),
"userAgent" to LIBRUS_USER_AGENT,
),
errorText = R.string.notification_user_action_required_captcha_librus,
)
return true
}
return false
}
private fun login(
url: String,
referer: String,
csrfToken: String?,
params: Map<String, String>,
) {
if (loginPerformed) {
data.error(ApiError(TAG, ERROR_LOGIN_LIBRUS_PORTAL_ACTION_ERROR))
return
}
d(TAG, "Request: Librus/Login/Portal - $url")
val recaptchaCode = data.arguments?.getString("recaptchaCode") ?: data.loginStore.getLoginData("recaptchaCode", null) val recaptchaCode = data.arguments?.getString("recaptchaCode") ?: data.loginStore.getLoginData("recaptchaCode", null)
val recaptchaTime = data.arguments?.getLong("recaptchaTime") ?: data.loginStore.getLoginData("recaptchaTime", 0L) val recaptchaTime = data.arguments?.getLong("recaptchaTime") ?: data.loginStore.getLoginData("recaptchaTime", 0L)
@ -114,62 +186,46 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
Request.builder() Request.builder()
.url(if (data.fakeLogin) FAKE_LIBRUS_LOGIN else LIBRUS_LOGIN_URL) .url(if (data.fakeLogin) FAKE_LIBRUS_LOGIN else LIBRUS_LOGIN_URL)
.userAgent(LIBRUS_USER_AGENT) .userAgent(LIBRUS_USER_AGENT)
.addHeader("X-Requested-With", LIBRUS_HEADER)
.addHeader("Referer", referer)
.withClient(data.app.httpLazy)
.addParameter("email", data.portalEmail) .addParameter("email", data.portalEmail)
.addParameter("password", data.portalPassword) .addParameter("password", data.portalPassword)
.also { .also {
if (recaptchaCode != null && System.currentTimeMillis() - recaptchaTime < 2*60*1000 /* 2 minutes */) if (recaptchaCode != null && System.currentTimeMillis() - recaptchaTime < 2*60*1000 /* 2 minutes */)
it.addParameter("g-recaptcha-response", recaptchaCode) it.addParameter("g-recaptcha-response", recaptchaCode)
if (csrfToken != null)
it.addHeader("X-CSRF-TOKEN", csrfToken)
for ((key, value) in params) {
it.addParameter(key, value)
} }
.addHeader("X-CSRF-TOKEN", csrfToken) }
.allowErrorCode(HTTP_BAD_REQUEST) .contentType(MediaTypeUtils.APPLICATION_FORM)
.allowErrorCode(HTTP_FORBIDDEN)
.contentType(MediaTypeUtils.APPLICATION_JSON)
.post() .post()
.callback(object : JsonCallbackHandler() { .callback(object : TextCallbackHandler() {
override fun onSuccess(json: JsonObject?, response: Response) { override fun onSuccess(text: String?, response: Response) {
loginPerformed = true
val location = response.headers()?.get("Location") val location = response.headers()?.get("Location")
if (location == "$LIBRUS_REDIRECT_URL?command=close") { if (location == "$LIBRUS_REDIRECT_URL?command=close") {
data.error(ApiError(TAG, ERROR_LIBRUS_PORTAL_MAINTENANCE) data.error(ApiError(TAG, ERROR_LIBRUS_PORTAL_MAINTENANCE)
.withApiResponse(json) .withApiResponse(text)
.withResponse(response))
return
}
if (json == null) {
if (response.parserErrorBody?.contains("wciąż nieaktywne") == true) {
data.error(ApiError(TAG, ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED)
.withResponse(response)) .withResponse(response))
return return
} }
if (text == null) {
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY) data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
.withResponse(response)) .withResponse(response))
return return
} }
val error = if (response.code() == 200) null else
json.getJsonArray("errors")?.getString(0) authorize(
?: json.getJsonObject("errors")?.entrySet()?.firstOrNull()?.value?.asString url = location
error?.let { code -> ?: if (data.fakeLogin)
when { FAKE_LIBRUS_AUTHORIZE
code.contains("Sesja logowania wygasła") -> ERROR_LOGIN_LIBRUS_PORTAL_CSRF_EXPIRED else
code.contains("Upewnij się, że nie") -> ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN LIBRUS_AUTHORIZE_URL,
// this doesn't work anyway: `errors` is an object with `g-recaptcha-response` set referer = referer,
code.contains("robotem") -> ERROR_CAPTCHA_LIBRUS_PORTAL )
code.contains("Podany adres e-mail jest nieprawidłowy.") -> ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN
else -> ERROR_LOGIN_LIBRUS_PORTAL_ACTION_ERROR
}.let { errorCode ->
data.error(ApiError(TAG, errorCode)
.withApiResponse(json)
.withResponse(response))
return
}
}
if (json.getBoolean("captchaRequired") == true) {
data.error(ApiError(TAG, ERROR_CAPTCHA_LIBRUS_PORTAL)
.withResponse(response)
.withApiResponse(json))
return
}
authorize(json.getString("redirect", LIBRUS_AUTHORIZE_URL))
} }
override fun onFailure(response: Response, throwable: Throwable) { override fun onFailure(response: Response, throwable: Throwable) {

View File

@ -12,6 +12,7 @@ import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.db.enums.LoginMethod
import pl.szczodrzynski.edziennik.ext.getString import pl.szczodrzynski.edziennik.ext.getString
import pl.szczodrzynski.edziennik.ext.getUnixDate import pl.szczodrzynski.edziennik.ext.getUnixDate
import pl.szczodrzynski.edziennik.utils.Utils.d import pl.szczodrzynski.edziennik.utils.Utils.d
@ -34,7 +35,7 @@ class LibrusLoginSynergia(override val data: DataLibrus, val onSuccess: () -> Un
} }
else { else {
data.app.cookieJar.clear("synergia.librus.pl") data.app.cookieJar.clear("synergia.librus.pl")
if (data.loginMethods.contains(LOGIN_METHOD_LIBRUS_API)) { if (data.loginMethods.contains(LoginMethod.LIBRUS_API)) {
loginWithApi() loginWithApi()
} }
else if (data.apiLogin != null && data.apiPassword != null && false) { else if (data.apiLogin != null && data.apiPassword != null && false) {

View File

@ -7,6 +7,7 @@ import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusPortal import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusPortal
import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.db.enums.LoginMode
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.utils.Utils.d import pl.szczodrzynski.edziennik.utils.Utils.d
@ -16,7 +17,7 @@ class SynergiaTokenExtractor(override val data: DataLibrus, val onSuccess: () ->
} }
init { run { init { run {
if (data.loginStore.mode != LOGIN_MODE_LIBRUS_EMAIL) { if (data.loginStore.mode != LoginMode.LIBRUS_EMAIL) {
data.error(ApiError(TAG, ERROR_INVALID_LOGIN_MODE)) data.error(ApiError(TAG, ERROR_INVALID_LOGIN_MODE))
return@run return@run
} }

View File

@ -6,14 +6,14 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik
import android.util.LongSparseArray import android.util.LongSparseArray
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_MOBIDZIENNIK_WEB
import pl.szczodrzynski.edziennik.data.api.Regexes
import pl.szczodrzynski.edziennik.data.api.models.Data import pl.szczodrzynski.edziennik.data.api.models.Data
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
import pl.szczodrzynski.edziennik.data.db.entity.Profile import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.db.enums.LoginMethod
import pl.szczodrzynski.edziennik.ext.currentTimeUnix import pl.szczodrzynski.edziennik.ext.currentTimeUnix
import pl.szczodrzynski.edziennik.ext.get import pl.szczodrzynski.edziennik.ext.getStudentData
import pl.szczodrzynski.edziennik.ext.isNotNullNorEmpty import pl.szczodrzynski.edziennik.ext.isNotNullNorEmpty
import pl.szczodrzynski.edziennik.ext.set
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
@ -31,7 +31,7 @@ class DataMobidziennik(app: App, profile: Profile?, loginStore: LoginStore) : Da
override fun satisfyLoginMethods() { override fun satisfyLoginMethods() {
loginMethods.clear() loginMethods.clear()
if (isWebLoginValid()) { if (isWebLoginValid()) {
loginMethods += LOGIN_METHOD_MOBIDZIENNIK_WEB loginMethods += LoginMethod.MOBIDZIENNIK_WEB
} }
} }
@ -87,7 +87,7 @@ class DataMobidziennik(app: App, profile: Profile?, loginStore: LoginStore) : Da
private var mStudentId: Int? = null private var mStudentId: Int? = null
var studentId: Int var studentId: Int
get() { mStudentId = mStudentId ?: profile?.getStudentData("studentId", 0); return mStudentId ?: 0 } get() { mStudentId = mStudentId ?: profile?.getStudentData("studentId", 0); return mStudentId ?: 0 }
set(value) { profile?.putStudentData("studentId", value) ?: return; mStudentId = value } set(value) { profile["studentId"] = value; mStudentId = value }
/* __ __ _ /* __ __ _
\ \ / / | | \ \ / / | |
@ -127,7 +127,7 @@ class DataMobidziennik(app: App, profile: Profile?, loginStore: LoginStore) : Da
*/ */
var globalId: String? var globalId: String?
get() { mGlobalId = mGlobalId ?: profile?.getStudentData("globalId", null); return mGlobalId } get() { mGlobalId = mGlobalId ?: profile?.getStudentData("globalId", null); return mGlobalId }
set(value) { profile?.putStudentData("globalId", value) ?: return; mGlobalId = value } set(value) { profile["globalId"] = value; mGlobalId = value }
private var mGlobalId: String? = null private var mGlobalId: String? = null
/** /**
@ -137,7 +137,7 @@ class DataMobidziennik(app: App, profile: Profile?, loginStore: LoginStore) : Da
*/ */
var loginEmail: String? var loginEmail: String?
get() { mLoginEmail = mLoginEmail ?: profile?.getStudentData("email", null); return mLoginEmail } get() { mLoginEmail = mLoginEmail ?: profile?.getStudentData("email", null); return mLoginEmail }
set(value) { profile?.putStudentData("email", value); mLoginEmail = value } set(value) { profile["email"] = value; mLoginEmail = value }
private var mLoginEmail: String? = null private var mLoginEmail: String? = null
/** /**
@ -146,7 +146,7 @@ class DataMobidziennik(app: App, profile: Profile?, loginStore: LoginStore) : Da
*/ */
var loginId: String? var loginId: String?
get() { mLoginId = mLoginId ?: profile?.getStudentData("loginId", null); return mLoginId } get() { mLoginId = mLoginId ?: profile?.getStudentData("loginId", null); return mLoginId }
set(value) { profile?.putStudentData("loginId", value) ?: return; mLoginId = value } set(value) { profile["loginId"] = value; mLoginId = value }
private var mLoginId: String? = null private var mLoginId: String? = null
/** /**
@ -154,7 +154,7 @@ class DataMobidziennik(app: App, profile: Profile?, loginStore: LoginStore) : Da
*/ */
var ciasteczkoAutoryzacji: String? var ciasteczkoAutoryzacji: String?
get() { mCiasteczkoAutoryzacji = mCiasteczkoAutoryzacji ?: profile?.getStudentData("ciasteczkoAutoryzacji", null); return mCiasteczkoAutoryzacji } get() { mCiasteczkoAutoryzacji = mCiasteczkoAutoryzacji ?: profile?.getStudentData("ciasteczkoAutoryzacji", null); return mCiasteczkoAutoryzacji }
set(value) { profile?.putStudentData("ciasteczkoAutoryzacji", value) ?: return; mCiasteczkoAutoryzacji = value } set(value) { profile["ciasteczkoAutoryzacji"] = value; mCiasteczkoAutoryzacji = value }
private var mCiasteczkoAutoryzacji: String? = null private var mCiasteczkoAutoryzacji: String? = null

View File

@ -11,12 +11,15 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.Mobidzien
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web.* import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web.*
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.firstlogin.MobidziennikFirstLogin import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.firstlogin.MobidziennikFirstLogin
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.login.MobidziennikLogin import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.login.MobidziennikLogin
import pl.szczodrzynski.edziennik.data.api.events.UserActionRequiredEvent
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
import pl.szczodrzynski.edziennik.data.db.entity.Profile import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.db.entity.Teacher import pl.szczodrzynski.edziennik.data.db.entity.Teacher
import pl.szczodrzynski.edziennik.data.db.enums.FeatureType
import pl.szczodrzynski.edziennik.data.db.enums.LoginMethod
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
import pl.szczodrzynski.edziennik.data.db.full.EventFull import pl.szczodrzynski.edziennik.data.db.full.EventFull
import pl.szczodrzynski.edziennik.data.db.full.MessageFull import pl.szczodrzynski.edziennik.data.db.full.MessageFull
@ -53,19 +56,19 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_| |_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
__/ | __/ |
|__*/ |__*/
override fun sync(featureIds: List<Int>, viewId: Int?, onlyEndpoints: List<Int>?, arguments: JsonObject?) { override fun sync(featureTypes: Set<FeatureType>?, onlyEndpoints: Set<Int>?, arguments: JsonObject?) {
data.arguments = arguments data.arguments = arguments
data.prepare(mobidziennikLoginMethods, MobidziennikFeatures, featureIds, viewId, onlyEndpoints) data.prepare(MobidziennikFeatures, featureTypes, onlyEndpoints)
login() login()
} }
private fun login(loginMethodId: Int? = null, afterLogin: (() -> Unit)? = null) { private fun login(loginMethod: LoginMethod? = null, afterLogin: (() -> Unit)? = null) {
d(TAG, "Trying to login with ${data.targetLoginMethodIds}") d(TAG, "Trying to login with ${data.targetLoginMethods}")
if (internalErrorList.isNotEmpty()) { if (internalErrorList.isNotEmpty()) {
d(TAG, " - Internal errors:") d(TAG, " - Internal errors:")
internalErrorList.forEach { d(TAG, " - code $it") } internalErrorList.forEach { d(TAG, " - code $it") }
} }
loginMethodId?.let { data.prepareFor(mobidziennikLoginMethods, it) } loginMethod?.let { data.prepareFor(it) }
afterLogin?.let { this.afterLogin = it } afterLogin?.let { this.afterLogin = it }
MobidziennikLogin(data) { MobidziennikLogin(data) {
data() data()
@ -73,7 +76,7 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
} }
private fun data() { private fun data() {
d(TAG, "Endpoint IDs: ${data.targetEndpointIds}") d(TAG, "Endpoint IDs: ${data.targetEndpoints}")
if (internalErrorList.isNotEmpty()) { if (internalErrorList.isNotEmpty()) {
d(TAG, " - Internal errors:") d(TAG, " - Internal errors:")
internalErrorList.forEach { d(TAG, " - code $it") } internalErrorList.forEach { d(TAG, " - code $it") }
@ -84,15 +87,15 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
} }
override fun getMessage(message: MessageFull) { override fun getMessage(message: MessageFull) {
login(LOGIN_METHOD_MOBIDZIENNIK_WEB) { login(LoginMethod.MOBIDZIENNIK_WEB) {
MobidziennikWebGetMessage(data, message) { MobidziennikWebGetMessage(data, message) {
completed() completed()
} }
} }
} }
override fun sendMessage(recipients: List<Teacher>, subject: String, text: String) { override fun sendMessage(recipients: Set<Teacher>, subject: String, text: String) {
login(LOGIN_METHOD_MOBIDZIENNIK_WEB) { login(LoginMethod.MOBIDZIENNIK_WEB) {
MobidziennikWebSendMessage(data, recipients, subject, text) { MobidziennikWebSendMessage(data, recipients, subject, text) {
completed() completed()
} }
@ -103,7 +106,7 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
override fun getAnnouncement(announcement: AnnouncementFull) {} override fun getAnnouncement(announcement: AnnouncementFull) {}
override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) { override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) {
login(LOGIN_METHOD_MOBIDZIENNIK_WEB) { login(LoginMethod.MOBIDZIENNIK_WEB) {
MobidziennikWebGetAttachment(data, owner, attachmentId, attachmentName) { MobidziennikWebGetAttachment(data, owner, attachmentId, attachmentName) {
completed() completed()
} }
@ -111,7 +114,7 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
} }
override fun getRecipientList() { override fun getRecipientList() {
login(LOGIN_METHOD_MOBIDZIENNIK_WEB) { login(LoginMethod.MOBIDZIENNIK_WEB) {
MobidziennikWebGetRecipientList(data) { MobidziennikWebGetRecipientList(data) {
completed() completed()
} }
@ -119,7 +122,7 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
} }
override fun getEvent(eventFull: EventFull) { override fun getEvent(eventFull: EventFull) {
login(LOGIN_METHOD_MOBIDZIENNIK_WEB) { login(LoginMethod.MOBIDZIENNIK_WEB) {
if (eventFull.isHomework) { if (eventFull.isHomework) {
MobidziennikWebGetHomework(data, eventFull) { MobidziennikWebGetHomework(data, eventFull) {
completed() completed()
@ -142,6 +145,7 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
private fun wrapCallback(callback: EdziennikCallback): EdziennikCallback { private fun wrapCallback(callback: EdziennikCallback): EdziennikCallback {
return object : EdziennikCallback { return object : EdziennikCallback {
override fun onCompleted() { callback.onCompleted() } override fun onCompleted() { callback.onCompleted() }
override fun onRequiresUserAction(event: UserActionRequiredEvent) { callback.onRequiresUserAction(event) }
override fun onProgress(step: Float) { callback.onProgress(step) } override fun onProgress(step: Float) { callback.onProgress(step) }
override fun onStartProgress(stringRes: Int) { callback.onStartProgress(stringRes) } override fun onStartProgress(stringRes: Int) { callback.onStartProgress(stringRes) }
override fun onError(apiError: ApiError) { override fun onError(apiError: ApiError) {
@ -156,8 +160,8 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
ERROR_MOBIDZIENNIK_WEB_NO_SESSION_KEY, ERROR_MOBIDZIENNIK_WEB_NO_SESSION_KEY,
ERROR_MOBIDZIENNIK_WEB_NO_SESSION_VALUE, ERROR_MOBIDZIENNIK_WEB_NO_SESSION_VALUE,
ERROR_MOBIDZIENNIK_WEB_NO_SERVER_ID -> { ERROR_MOBIDZIENNIK_WEB_NO_SERVER_ID -> {
data.loginMethods.remove(LOGIN_METHOD_MOBIDZIENNIK_WEB) data.loginMethods.remove(LoginMethod.MOBIDZIENNIK_WEB)
data.prepareFor(mobidziennikLoginMethods, LOGIN_METHOD_MOBIDZIENNIK_WEB) data.prepareFor(LoginMethod.MOBIDZIENNIK_WEB)
data.webSessionIdExpiryTime = 0 data.webSessionIdExpiryTime = 0
login() login()
} }

View File

@ -4,8 +4,10 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik
import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.models.Feature import pl.szczodrzynski.edziennik.data.api.models.Feature
import pl.szczodrzynski.edziennik.data.db.enums.FeatureType
import pl.szczodrzynski.edziennik.data.db.enums.LoginMethod
import pl.szczodrzynski.edziennik.data.db.enums.LoginType
const val ENDPOINT_MOBIDZIENNIK_API_MAIN = 1000 const val ENDPOINT_MOBIDZIENNIK_API_MAIN = 1000
const val ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_INBOX = 2011 const val ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_INBOX = 2011
@ -23,15 +25,15 @@ const val ENDPOINT_MOBIDZIENNIK_API2_MAIN = 3000
val MobidziennikFeatures = listOf( val MobidziennikFeatures = listOf(
// always synced // always synced
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_ALWAYS_NEEDED, listOf( Feature(LoginType.MOBIDZIENNIK, FeatureType.ALWAYS_NEEDED, listOf(
ENDPOINT_MOBIDZIENNIK_API_MAIN to LOGIN_METHOD_MOBIDZIENNIK_WEB, ENDPOINT_MOBIDZIENNIK_API_MAIN to LoginMethod.MOBIDZIENNIK_WEB,
ENDPOINT_MOBIDZIENNIK_WEB_ACCOUNT_EMAIL to LOGIN_METHOD_MOBIDZIENNIK_WEB ENDPOINT_MOBIDZIENNIK_WEB_ACCOUNT_EMAIL to LoginMethod.MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)), // TODO divide features into separate view IDs (all with API_MAIN) )), // TODO divide features into separate view IDs (all with API_MAIN)
// push config // push config
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_PUSH_CONFIG, listOf( Feature(LoginType.MOBIDZIENNIK, FeatureType.PUSH_CONFIG, listOf(
ENDPOINT_MOBIDZIENNIK_API2_MAIN to LOGIN_METHOD_MOBIDZIENNIK_API2 ENDPOINT_MOBIDZIENNIK_API2_MAIN to LoginMethod.MOBIDZIENNIK_API2
), listOf(LOGIN_METHOD_MOBIDZIENNIK_API2)).withShouldSync { data -> )).withShouldSync { data ->
!data.app.config.sync.tokenMobidziennikList.contains(data.profileId) !data.app.config.sync.tokenMobidziennikList.contains(data.profileId)
}, },
@ -42,36 +44,36 @@ val MobidziennikFeatures = listOf(
/** /**
* Timetable - web scraping - does nothing if the API_MAIN timetable is enough. * Timetable - web scraping - does nothing if the API_MAIN timetable is enough.
*/ */
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_TIMETABLE, listOf( Feature(LoginType.MOBIDZIENNIK, FeatureType.TIMETABLE, listOf(
ENDPOINT_MOBIDZIENNIK_WEB_TIMETABLE to LOGIN_METHOD_MOBIDZIENNIK_WEB ENDPOINT_MOBIDZIENNIK_WEB_TIMETABLE to LoginMethod.MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB, LOGIN_METHOD_MOBIDZIENNIK_WEB)), )),
/** /**
* Agenda - "API" + web scraping. * Agenda - "API" + web scraping.
*/ */
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_AGENDA, listOf( Feature(LoginType.MOBIDZIENNIK, FeatureType.AGENDA, listOf(
ENDPOINT_MOBIDZIENNIK_API_MAIN to LOGIN_METHOD_MOBIDZIENNIK_WEB, ENDPOINT_MOBIDZIENNIK_API_MAIN to LoginMethod.MOBIDZIENNIK_WEB,
ENDPOINT_MOBIDZIENNIK_WEB_CALENDAR to LOGIN_METHOD_MOBIDZIENNIK_WEB ENDPOINT_MOBIDZIENNIK_WEB_CALENDAR to LoginMethod.MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB, LOGIN_METHOD_MOBIDZIENNIK_WEB)), )),
/** /**
* Grades - "API" + web scraping. * Grades - "API" + web scraping.
*/ */
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_GRADES, listOf( Feature(LoginType.MOBIDZIENNIK, FeatureType.GRADES, listOf(
ENDPOINT_MOBIDZIENNIK_API_MAIN to LOGIN_METHOD_MOBIDZIENNIK_WEB, ENDPOINT_MOBIDZIENNIK_API_MAIN to LoginMethod.MOBIDZIENNIK_WEB,
ENDPOINT_MOBIDZIENNIK_WEB_GRADES to LOGIN_METHOD_MOBIDZIENNIK_WEB ENDPOINT_MOBIDZIENNIK_WEB_GRADES to LoginMethod.MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB, LOGIN_METHOD_MOBIDZIENNIK_WEB)), )),
/** /**
* Behaviour - "API" + web scraping. * Behaviour - "API" + web scraping.
*/ */
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_BEHAVIOUR, listOf( Feature(LoginType.MOBIDZIENNIK, FeatureType.BEHAVIOUR, listOf(
ENDPOINT_MOBIDZIENNIK_API_MAIN to LOGIN_METHOD_MOBIDZIENNIK_WEB, ENDPOINT_MOBIDZIENNIK_API_MAIN to LoginMethod.MOBIDZIENNIK_WEB,
ENDPOINT_MOBIDZIENNIK_WEB_NOTICES to LOGIN_METHOD_MOBIDZIENNIK_WEB ENDPOINT_MOBIDZIENNIK_WEB_NOTICES to LoginMethod.MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB, LOGIN_METHOD_MOBIDZIENNIK_WEB)), )),
/** /**
* Attendance - only web scraping. * Attendance - only web scraping.
*/ */
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_ATTENDANCE, listOf( Feature(LoginType.MOBIDZIENNIK, FeatureType.ATTENDANCE, listOf(
ENDPOINT_MOBIDZIENNIK_WEB_ATTENDANCE to LOGIN_METHOD_MOBIDZIENNIK_WEB ENDPOINT_MOBIDZIENNIK_WEB_ATTENDANCE to LoginMethod.MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)), )),
@ -80,38 +82,38 @@ val MobidziennikFeatures = listOf(
/** /**
* Messages inbox - using web scraper. * Messages inbox - using web scraper.
*/ */
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_MESSAGES_INBOX, listOf( Feature(LoginType.MOBIDZIENNIK, FeatureType.MESSAGES_INBOX, listOf(
ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_INBOX to LOGIN_METHOD_MOBIDZIENNIK_WEB, ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_INBOX to LoginMethod.MOBIDZIENNIK_WEB,
ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_ALL to LOGIN_METHOD_MOBIDZIENNIK_WEB ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_ALL to LoginMethod.MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)), )),
/** /**
* Messages sent - using web scraper. * Messages sent - using web scraper.
*/ */
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_MESSAGES_SENT, listOf( Feature(LoginType.MOBIDZIENNIK, FeatureType.MESSAGES_SENT, listOf(
ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_SENT to LOGIN_METHOD_MOBIDZIENNIK_WEB, ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_SENT to LoginMethod.MOBIDZIENNIK_WEB,
ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_ALL to LOGIN_METHOD_MOBIDZIENNIK_WEB ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_ALL to LoginMethod.MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)) ))
// lucky number possibilities // lucky number possibilities
// all endpoints that may supply the lucky number // all endpoints that may supply the lucky number
/*Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_LUCKY_NUMBER, listOf( /*Feature(LoginType.MOBIDZIENNIK, FeatureType.LUCKY_NUMBER, listOf(
ENDPOINT_MOBIDZIENNIK_WEB_MANUALS to LOGIN_METHOD_MOBIDZIENNIK_WEB ENDPOINT_MOBIDZIENNIK_WEB_MANUALS to LoginMethod.MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)).apply { priority = 10 }, )).apply { priority = 10 },
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_LUCKY_NUMBER, listOf( Feature(LoginType.MOBIDZIENNIK, FeatureType.LUCKY_NUMBER, listOf(
ENDPOINT_MOBIDZIENNIK_WEB_CALENDAR to LOGIN_METHOD_MOBIDZIENNIK_WEB ENDPOINT_MOBIDZIENNIK_WEB_CALENDAR to LoginMethod.MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)).apply { priority = 3 }, )).apply { priority = 3 },
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_LUCKY_NUMBER, listOf( Feature(LoginType.MOBIDZIENNIK, FeatureType.LUCKY_NUMBER, listOf(
ENDPOINT_MOBIDZIENNIK_WEB_GRADES to LOGIN_METHOD_MOBIDZIENNIK_WEB ENDPOINT_MOBIDZIENNIK_WEB_GRADES to LoginMethod.MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)).apply { priority = 2 }, )).apply { priority = 2 },
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_LUCKY_NUMBER, listOf( Feature(LoginType.MOBIDZIENNIK, FeatureType.LUCKY_NUMBER, listOf(
ENDPOINT_MOBIDZIENNIK_WEB_NOTICES to LOGIN_METHOD_MOBIDZIENNIK_WEB ENDPOINT_MOBIDZIENNIK_WEB_NOTICES to LoginMethod.MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)).apply { priority = 1 }, )).apply { priority = 1 },
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_LUCKY_NUMBER, listOf( Feature(LoginType.MOBIDZIENNIK, FeatureType.LUCKY_NUMBER, listOf(
ENDPOINT_MOBIDZIENNIK_WEB_ATTENDANCE to LOGIN_METHOD_MOBIDZIENNIK_WEB ENDPOINT_MOBIDZIENNIK_WEB_ATTENDANCE to LoginMethod.MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)).apply { priority = 4 }*/ )).apply { priority = 4 }*/
) )

View File

@ -21,7 +21,7 @@ class MobidziennikData(val data: DataMobidziennik, val onSuccess: () -> Unit) {
} }
private fun nextEndpoint(onSuccess: () -> Unit) { private fun nextEndpoint(onSuccess: () -> Unit) {
if (data.targetEndpointIds.isEmpty()) { if (data.targetEndpoints.isEmpty()) {
onSuccess() onSuccess()
return return
} }
@ -29,8 +29,8 @@ class MobidziennikData(val data: DataMobidziennik, val onSuccess: () -> Unit) {
onSuccess() onSuccess()
return return
} }
val id = data.targetEndpointIds.firstKey() val id = data.targetEndpoints.firstKey()
val lastSync = data.targetEndpointIds.remove(id) val lastSync = data.targetEndpoints.remove(id)
useEndpoint(id, lastSync) { endpointId -> useEndpoint(id, lastSync) { endpointId ->
data.progress(data.progressStep) data.progress(data.progressStep)
nextEndpoint(onSuccess) nextEndpoint(onSuccess)

View File

@ -11,6 +11,8 @@ import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_ABSEN
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_PRESENT import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_PRESENT
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_RELEASED import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_RELEASED
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.dateToSemester
class MobidziennikApiAttendance(val data: DataMobidziennik, rows: List<String>) { class MobidziennikApiAttendance(val data: DataMobidziennik, rows: List<String>) {
init { run { init { run {
@ -70,7 +72,7 @@ class MobidziennikApiAttendance(val data: DataMobidziennik, rows: List<String>)
data.metadataList.add( data.metadataList.add(
Metadata( Metadata(
data.profileId, data.profileId,
Metadata.TYPE_ATTENDANCE, MetadataType.ATTENDANCE,
id, id,
data.profile?.empty ?: false || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == Attendance.TYPE_UNKNOWN, data.profile?.empty ?: false || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == Attendance.TYPE_UNKNOWN,
data.profile?.empty ?: false || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == Attendance.TYPE_UNKNOWN data.profile?.empty ?: false || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == Attendance.TYPE_UNKNOWN

View File

@ -10,6 +10,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidzienn
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
import pl.szczodrzynski.edziennik.data.db.entity.Event import pl.szczodrzynski.edziennik.data.db.entity.Event
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
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 java.text.ParseException import java.text.ParseException
@ -68,7 +69,7 @@ class MobidziennikApiEvents(val data: DataMobidziennik, rows: List<String>) {
data.metadataList.add( data.metadataList.add(
Metadata( Metadata(
data.profileId, data.profileId,
Metadata.TYPE_EVENT, MetadataType.EVENT,
id, id,
data.profile?.empty ?: false, data.profile?.empty ?: false,
data.profile?.empty ?: false data.profile?.empty ?: false

View File

@ -15,6 +15,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_SEMESTER2_
import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_YEAR_FINAL import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_YEAR_FINAL
import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_YEAR_PROPOSED import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_YEAR_PROPOSED
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
class MobidziennikApiGrades(val data: DataMobidziennik, rows: List<String>) { class MobidziennikApiGrades(val data: DataMobidziennik, rows: List<String>) {
init { data.profile?.also { profile -> run { init { data.profile?.also { profile -> run {
@ -91,7 +92,7 @@ class MobidziennikApiGrades(val data: DataMobidziennik, rows: List<String>) {
data.metadataList.add( data.metadataList.add(
Metadata( Metadata(
data.profileId, data.profileId,
Metadata.TYPE_GRADE, MetadataType.GRADE,
id, id,
data.profile?.empty ?: false, data.profile?.empty ?: false,
data.profile?.empty ?: false data.profile?.empty ?: false

View File

@ -9,6 +9,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidzienn
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
import pl.szczodrzynski.edziennik.data.db.entity.Event import pl.szczodrzynski.edziennik.data.db.entity.Event
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.utils.html.BetterHtml import pl.szczodrzynski.edziennik.utils.html.BetterHtml
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
@ -47,7 +48,7 @@ class MobidziennikApiHomework(val data: DataMobidziennik, rows: List<String>) {
data.metadataList.add( data.metadataList.add(
Metadata( Metadata(
data.profileId, data.profileId,
Metadata.TYPE_HOMEWORK, MetadataType.HOMEWORK,
id, id,
data.profile?.empty ?: false, data.profile?.empty ?: false,
data.profile?.empty ?: false data.profile?.empty ?: false

View File

@ -7,6 +7,7 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.Notice import pl.szczodrzynski.edziennik.data.db.entity.Notice
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
class MobidziennikApiNotices(val data: DataMobidziennik, rows: List<String>) { class MobidziennikApiNotices(val data: DataMobidziennik, rows: List<String>) {
@ -48,7 +49,7 @@ class MobidziennikApiNotices(val data: DataMobidziennik, rows: List<String>) {
data.metadataList.add( data.metadataList.add(
Metadata( Metadata(
data.profileId, data.profileId,
Metadata.TYPE_NOTICE, MetadataType.NOTICE,
id, id,
data.profile?.empty ?: false, data.profile?.empty ?: false,
data.profile?.empty ?: false data.profile?.empty ?: false

View File

@ -11,6 +11,7 @@ import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
import pl.szczodrzynski.edziennik.data.db.entity.Lesson import pl.szczodrzynski.edziennik.data.db.entity.Lesson
import pl.szczodrzynski.edziennik.data.db.entity.LessonRange import pl.szczodrzynski.edziennik.data.db.entity.LessonRange
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.fixName import pl.szczodrzynski.edziennik.ext.fixName
import pl.szczodrzynski.edziennik.ext.keys import pl.szczodrzynski.edziennik.ext.keys
import pl.szczodrzynski.edziennik.ext.singleOrNull import pl.szczodrzynski.edziennik.ext.singleOrNull
@ -87,6 +88,7 @@ class MobidziennikApiTimetable(val data: DataMobidziennik, rows: List<String>) {
} }
it.id = it.buildId() it.id = it.buildId()
it.ownerId = it.buildOwnerId()
val seen = profile.empty || date < Date.getToday() val seen = profile.empty || date < Date.getToday()
@ -94,7 +96,7 @@ class MobidziennikApiTimetable(val data: DataMobidziennik, rows: List<String>) {
data.metadataList.add( data.metadataList.add(
Metadata( Metadata(
data.profileId, data.profileId,
Metadata.TYPE_LESSON_CHANGE, MetadataType.LESSON_CHANGE,
it.id, it.id,
seen, seen,
seen seen

View File

@ -8,6 +8,7 @@ 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.entity.LuckyNumber import pl.szczodrzynski.edziennik.data.db.entity.LuckyNumber
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
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) {
@ -26,7 +27,7 @@ class MobidziennikLuckyNumberExtractor(val data: DataMobidziennik, text: String)
data.metadataList.add( data.metadataList.add(
Metadata( Metadata(
data.profileId, data.profileId,
Metadata.TYPE_LUCKY_NUMBER, MetadataType.LUCKY_NUMBER,
luckyNumberObject.date.value.toLong(), luckyNumberObject.date.value.toLong(),
true, true,
data.profile?.empty ?: false data.profile?.empty ?: false

View File

@ -10,6 +10,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBID
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
import pl.szczodrzynski.edziennik.ext.DAY import pl.szczodrzynski.edziennik.ext.DAY
import pl.szczodrzynski.edziennik.ext.get import pl.szczodrzynski.edziennik.ext.get
import pl.szczodrzynski.edziennik.ext.isNotNullNorBlank
class MobidziennikWebAccountEmail(override val data: DataMobidziennik, class MobidziennikWebAccountEmail(override val data: DataMobidziennik,
override val lastSync: Long?, override val lastSync: Long?,
@ -24,6 +25,7 @@ class MobidziennikWebAccountEmail(override val data: DataMobidziennik,
MobidziennikLuckyNumberExtractor(data, text) MobidziennikLuckyNumberExtractor(data, text)
val email = Regexes.MOBIDZIENNIK_ACCOUNT_EMAIL.find(text)?.let { it[1] } val email = Regexes.MOBIDZIENNIK_ACCOUNT_EMAIL.find(text)?.let { it[1] }
if (email.isNotNullNorBlank())
data.loginEmail = email data.loginEmail = email
data.setSyncNext(ENDPOINT_MOBIDZIENNIK_WEB_ACCOUNT_EMAIL, if (email == null) 3* DAY else 7* DAY) data.setSyncNext(ENDPOINT_MOBIDZIENNIK_WEB_ACCOUNT_EMAIL, if (email == null) 3* DAY else 7* DAY)

View File

@ -20,6 +20,8 @@ import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_RELEA
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_UNKNOWN import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_UNKNOWN
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.dateToSemester
import pl.szczodrzynski.edziennik.ext.fixName import pl.szczodrzynski.edziennik.ext.fixName
import pl.szczodrzynski.edziennik.ext.get import pl.szczodrzynski.edziennik.ext.get
import pl.szczodrzynski.edziennik.ext.singleOrNull import pl.szczodrzynski.edziennik.ext.singleOrNull
@ -246,7 +248,7 @@ class MobidziennikWebAttendance(override val data: DataMobidziennik,
data.metadataList.add( data.metadataList.add(
Metadata( Metadata(
data.profileId, data.profileId,
Metadata.TYPE_ATTENDANCE, MetadataType.ATTENDANCE,
id, id,
data.profile?.empty ?: false || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == TYPE_UNKNOWN, data.profile?.empty ?: false || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == TYPE_UNKNOWN,
data.profile?.empty ?: false || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == TYPE_UNKNOWN data.profile?.empty ?: false || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == TYPE_UNKNOWN

View File

@ -12,6 +12,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.Mobidzien
import pl.szczodrzynski.edziennik.data.db.entity.Event import pl.szczodrzynski.edziennik.data.db.entity.Event
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.getString import pl.szczodrzynski.edziennik.ext.getString
import pl.szczodrzynski.edziennik.utils.Utils.crc16 import pl.szczodrzynski.edziennik.utils.Utils.crc16
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
@ -86,7 +87,7 @@ class MobidziennikWebCalendar(override val data: DataMobidziennik,
data.metadataList.add( data.metadataList.add(
Metadata( Metadata(
profileId, profileId,
Metadata.TYPE_EVENT, MetadataType.EVENT,
eventObject.id, eventObject.id,
profile?.empty ?: false, profile?.empty ?: false,
profile?.empty ?: false profile?.empty ?: false

View File

@ -11,6 +11,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidzienn
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.events.MessageGetEvent import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.data.db.full.MessageFull import pl.szczodrzynski.edziennik.data.db.full.MessageFull
import pl.szczodrzynski.edziennik.data.db.full.MessageRecipientFull import pl.szczodrzynski.edziennik.data.db.full.MessageRecipientFull
import pl.szczodrzynski.edziennik.ext.fixName import pl.szczodrzynski.edziennik.ext.fixName
@ -133,7 +134,7 @@ class MobidziennikWebGetMessage(override val data: DataMobidziennik,
if (!message.seen) { // TODO discover why this monstrosity instead of MetadataDao.setSeen if (!message.seen) { // TODO discover why this monstrosity instead of MetadataDao.setSeen
data.setSeenMetadataList.add(Metadata( data.setSeenMetadataList.add(Metadata(
message.profileId, message.profileId,
Metadata.TYPE_MESSAGE, MetadataType.MESSAGE,
message.id, message.id,
true, true,
true true

View File

@ -14,6 +14,8 @@ import pl.szczodrzynski.edziennik.data.db.entity.Grade
import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_NORMAL import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_NORMAL
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.dateToSemester
import pl.szczodrzynski.edziennik.ext.fixWhiteSpaces import pl.szczodrzynski.edziennik.ext.fixWhiteSpaces
import pl.szczodrzynski.edziennik.ext.get import pl.szczodrzynski.edziennik.ext.get
import pl.szczodrzynski.edziennik.ext.singleOrNull import pl.szczodrzynski.edziennik.ext.singleOrNull
@ -135,7 +137,7 @@ class MobidziennikWebGrades(override val data: DataMobidziennik,
data.metadataList.add( data.metadataList.add(
Metadata( Metadata(
profileId, profileId,
Metadata.TYPE_GRADE, MetadataType.GRADE,
gradeObject.id, gradeObject.id,
profile.empty, profile.empty,
profile.empty profile.empty

View File

@ -13,6 +13,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED
import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT
import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.DAY import pl.szczodrzynski.edziennik.ext.DAY
import pl.szczodrzynski.edziennik.ext.fixName import pl.szczodrzynski.edziennik.ext.fixName
import pl.szczodrzynski.edziennik.ext.singleOrNull import pl.szczodrzynski.edziennik.ext.singleOrNull
@ -84,7 +85,7 @@ class MobidziennikWebMessagesAll(override val data: DataMobidziennik,
) )
data.messageList.add(message) data.messageList.add(message)
data.metadataList.add(Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true)) data.metadataList.add(Metadata(profileId, MetadataType.MESSAGE, message.id, true, true))
} }
// sync every 7 days as we probably don't expect more than // sync every 7 days as we probably don't expect more than

View File

@ -12,6 +12,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.Message
import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.fixName import pl.szczodrzynski.edziennik.ext.fixName
import pl.szczodrzynski.edziennik.ext.singleOrNull import pl.szczodrzynski.edziennik.ext.singleOrNull
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
@ -83,7 +84,7 @@ class MobidziennikWebMessagesInbox(override val data: DataMobidziennik,
data.setSeenMetadataList.add( data.setSeenMetadataList.add(
Metadata( Metadata(
profileId, profileId,
Metadata.TYPE_MESSAGE, MetadataType.MESSAGE,
message.id, message.id,
isRead, isRead,
isRead || profile?.empty ?: false isRead || profile?.empty ?: false

View File

@ -5,7 +5,6 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web
import org.jsoup.Jsoup import org.jsoup.Jsoup
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_MESSAGES
import pl.szczodrzynski.edziennik.data.api.Regexes 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.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_SENT import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_SENT
@ -14,6 +13,8 @@ import pl.szczodrzynski.edziennik.data.db.entity.Message
import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.data.db.enums.FeatureType
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.DAY import pl.szczodrzynski.edziennik.ext.DAY
import pl.szczodrzynski.edziennik.ext.fixName import pl.szczodrzynski.edziennik.ext.fixName
import pl.szczodrzynski.edziennik.ext.get import pl.szczodrzynski.edziennik.ext.get
@ -100,14 +101,14 @@ class MobidziennikWebMessagesSent(override val data: DataMobidziennik,
data.setSeenMetadataList.add( data.setSeenMetadataList.add(
Metadata( Metadata(
profileId, profileId,
Metadata.TYPE_MESSAGE, MetadataType.MESSAGE,
message.id, message.id,
true, true,
true true
)) ))
} }
data.setSyncNext(ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_SENT, 1* DAY, DRAWER_ITEM_MESSAGES) data.setSyncNext(ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_SENT, 1* DAY, FeatureType.MESSAGES_SENT)
onSuccess(ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_SENT) onSuccess(ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_SENT)
} }
} }

View File

@ -11,9 +11,10 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.Mobidzien
import pl.szczodrzynski.edziennik.data.api.events.MessageSentEvent import pl.szczodrzynski.edziennik.data.api.events.MessageSentEvent
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.Teacher import pl.szczodrzynski.edziennik.data.db.entity.Teacher
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
class MobidziennikWebSendMessage(override val data: DataMobidziennik, class MobidziennikWebSendMessage(override val data: DataMobidziennik,
val recipients: List<Teacher>, val recipients: Set<Teacher>,
val subject: String, val subject: String,
val text: String, val text: String,
val onSuccess: () -> Unit val onSuccess: () -> Unit
@ -43,7 +44,7 @@ class MobidziennikWebSendMessage(override val data: DataMobidziennik,
// TODO create MobidziennikWebMessagesSent and replace this // TODO create MobidziennikWebMessagesSent and replace this
MobidziennikWebMessagesAll(data, null) { MobidziennikWebMessagesAll(data, null) {
val message = data.messageList.firstOrNull { it.isSent && it.subject == subject } val message = data.messageList.firstOrNull { it.isSent && it.subject == subject }
val metadata = data.metadataList.firstOrNull { it.thingType == Metadata.TYPE_MESSAGE && it.thingId == message?.id } val metadata = data.metadataList.firstOrNull { it.thingType == MetadataType.MESSAGE && it.thingId == message?.id }
val event = MessageSentEvent(data.profileId, message, message?.addedDate) val event = MessageSentEvent(data.profileId, message, message?.addedDate)
EventBus.getDefault().postSticky(event) EventBus.getDefault().postSticky(event)

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