Compare commits

...

96 Commits

Author SHA1 Message Date
4d9c9368dd
merge with latest Szkolny.eu changes (TODO) 2024-06-13 10:55:14 +02:00
c123b28652
fix missing Intent receiver flags for Tiramisu+ 2024-06-13 09:44:42 +02:00
225070abd9
update dependencies 2024-06-12 21:33:34 +02:00
1540a6cfcd
fix M3 UI code & upgrade kotlin 2024-06-12 21:12:02 +02:00
Adam Kasprzycki
9915150c33
wielki powrót pr m3 do szkolnego (nie czytajcie tego kodu) 2023-11-27 17:08:17 +01:00
Kuba Szczodrzyński
cefb0deba8
[Actions] Rename changelog output name. 2023-03-25 10:09:36 +01:00
Kuba Szczodrzyński
90a151c129
[4.13.6] Update build.gradle, signing and changelog. 2023-03-24 22:27:27 +01:00
Kuba Szczodrzyński
9fd9721ae7
[UI] Hide Debugging menu without dev mode. 2023-03-24 22:24:33 +01:00
Kuba Szczodrzyński
ceca75ef4b
[UI/Timetable] Add option to sync current week. 2023-03-24 22:16:34 +01:00
Kuba Szczodrzyński
21c00bbe53
[API] Fix detecting session cookies. Remove expired cookies. 2023-03-24 22:09:31 +01:00
Kuba Szczodrzyński
db00566ebf
[UI/Login] Fallback reCAPTCHA to WebView activity. 2023-03-24 22:09:31 +01:00
B.O.S.S
07ab1b984f
[API/Librus] Fix login. (#176) 2023-03-24 22:09:03 +01:00
Kuba Szczodrzyński
8177d4aa2d
[Widgets] Fix pending intents mutability. Hide timetable sync button. 2023-03-24 11:13:00 +01:00
Kuba Szczodrzyński
beff1b6460
[App] Fix cookie persistence. 2023-03-24 10:56:35 +01:00
Kuba Szczodrzyński
31b569b02e
[4.13.5] Update build.gradle, signing and changelog. 2023-03-22 23:16:28 +01:00
Kuba Szczodrzyński
8bf77817d2
[UI] Fix writing files on Android 13 and newer. 2023-03-22 23:15:45 +01:00
Kuba Szczodrzyński
27b61adf1d
[Actions] Fix Play release publishing workflow. 2022-12-27 12:30:03 +01:00
Kuba Szczodrzyński
a0244841ad
[4.13.4] Update build.gradle, signing and changelog. 2022-12-26 14:45:29 +01:00
Kuba Szczodrzyński
12c0c6f2ec
[UI] Always show event subject dropdown for university school. 2022-12-26 14:43:42 +01:00
Kuba Szczodrzyński
aaa3b8626e
[UI] Update event types for university school. 2022-12-26 14:01:25 +01:00
Kuba Szczodrzyński
48c9e2dfe3
[4.13.3] Update build.gradle, signing and changelog. 2022-12-06 10:35:23 +01:00
Kuba Szczodrzyński
81d4801d27
[UI] Add snowfall to CounterActivity. Enable in February as well. 2022-12-06 10:34:12 +01:00
Kuba Szczodrzyński
5f8016061d
[API/Vulcan] Fix wrong serializing of null in JSON causing API error. 2022-12-06 10:22:47 +01:00
Kuba Szczodrzyński
5007587192
[UI/Agenda] Allow prioritizing event subject over event type. 2022-11-30 11:29:43 +01:00
Kuba Szczodrzyński
dfd1083e41
[UI/Timetable] Show lesson replacing notes in all places. 2022-11-30 10:41:43 +01:00
Kuba Szczodrzyński
678baf46e5
[4.13.2] Update build.gradle, signing and changelog. 2022-11-28 20:30:11 +01:00
Kuba Szczodrzyński
4077fe448d
[4.13.2-rc.4] Update build.gradle, signing and changelog. 2022-11-25 16:52:16 +01:00
Kuba Szczodrzyński
f085e17ef7
[API/Vulcan] Once again fix ignoring 404 response on Addressbook. 2022-11-25 16:51:35 +01:00
Kuba Szczodrzyński
7fd2cad46b
[4.13.2-rc.3] Update build.gradle, signing and changelog. 2022-11-25 16:13:58 +01:00
Kuba Szczodrzyński
93dc2ac9ab
[API/Vulcan] Fix ignoring 404 response on Addressbook. 2022-11-25 16:11:50 +01:00
Kuba Szczodrzyński
ac53e267fc
[4.13.2-rc.2] Update build.gradle, signing and changelog. 2022-11-25 14:55:49 +01:00
Kuba Szczodrzyński
86eb1a0f42
[API/Vulcan] Actually ignore 404 response on Addressbook. 2022-11-25 14:54:05 +01:00
Kuba Szczodrzyński
710d82da27
[4.13.2-rc.1] Update build.gradle, signing and changelog. 2022-11-25 14:40:39 +01:00
Kuba Szczodrzyński
0123f50810
[API/Vulcan] Ignore 404 response on Addressbook. 2022-11-25 14:20:22 +01:00
Kuba Szczodrzyński
6d3eb65445
[API/Mobidziennik] Do not clear email field if not set. 2022-11-15 22:20:00 +01:00
Kuba Szczodrzyński
a9a0630226
[4.13.1] Update build.gradle, signing and changelog. 2022-11-03 22:59:40 +01:00
Kuba Szczodrzyński
ec7577f999
[App] Revert to use old devMode config key. 2022-11-03 22:29:22 +01:00
Kuba Szczodrzyński
05c7c0012c
[UI] Fix home cards order not saving. 2022-11-03 22:28:59 +01:00
B.O.S.S
d65c6db954
[API/Librus] Fix getting read date in messages for multiple receivers. (#154) 2022-11-03 21:53:01 +01:00
Oskar
771dc437e6
[Strings] Translate home timetable card "all lessons" to English. (#152) 2022-10-30 12:45:27 +01:00
B.O.S.S
3d5d3847cc
[API/Librus] Fix getting teacher name in notices. (#151) 2022-10-30 12:44:59 +01:00
Kuba Szczodrzyński
18cc60a80b
[4.13] Update build.gradle, signing and changelog. 2022-10-26 20:55:50 +02:00
Kuba Szczodrzyński
fedde9f739
[UI/Home] Show all next lessons before school day start. 2022-10-26 20:34:48 +02:00
kuba2k2
9fde97bef0
[App] Share Lesson and Event notes to specific team only. 2022-10-26 11:14:32 +02:00
kuba2k2
742bd03e9e
[Lab] Fix JSON page crashing because of serializing AppDb. 2022-10-26 10:31:03 +02:00
Kuba Szczodrzyński
62ffc652ab
[4.13-rc.5] Update build.gradle, signing and changelog. 2022-10-25 20:50:19 +02:00
Kuba Szczodrzyński
bfd2e9883a
[App] Refactor getting profile config. 2022-10-25 20:48:10 +02:00
Kuba Szczodrzyński
00e077d01f
[UI] Fix notes not showing in note list dialog. 2022-10-25 20:07:48 +02:00
Kuba Szczodrzyński
c21d89cf60
[UI] Fix SettingsAboutCard having duplicate items. 2022-10-25 19:58:26 +02:00
Kuba Szczodrzyński
f52cc1b197
[UI] Make shared notes for lessons use a stable ID. 2022-10-25 19:58:09 +02:00
kuba2k2
c90ad97f55
[UI] Remove "enable shared events" setting. Reorder settings a bit. 2022-10-25 17:33:38 +02:00
Kuba Szczodrzyński
845e09d875
[API/Usos] Add prefixes to classroom and building names. 2022-10-25 12:36:11 +02:00
Kuba Szczodrzyński
158b69a8d3
[Lab] Fix full sync buttons. 2022-10-25 12:35:51 +02:00
Kuba Szczodrzyński
9535f53563
[App] Refactor profile methods as extensions. 2022-10-25 12:19:59 +02:00
Kuba Szczodrzyński
eeb3fc4621
[4.13-rc.4] Update build.gradle, signing and changelog. 2022-10-24 23:33:54 +02:00
Kuba Szczodrzyński
41693a9fc8
[App] Respect user setting before notifying about updates. 2022-10-24 23:33:02 +02:00
Kuba Szczodrzyński
d3599b8c89
[UI] Fix DateDropdown next week Friday not visible. 2022-10-24 23:32:21 +02:00
Kuba Szczodrzyński
ffd81f8b82
[UI] Add setting to share events/notes by default. 2022-10-24 23:32:09 +02:00
Kuba Szczodrzyński
2c34924052
[UI] Mark Firebase-received events as manual. Update legend icons. 2022-10-24 22:41:15 +02:00
Kuba Szczodrzyński
26ad6373e6
[4.13-rc.3] Update build.gradle, signing and changelog. 2022-10-23 23:16:23 +02:00
Kuba Szczodrzyński
cac8f94407
[Gradle] Update Chucker to fix Android 12 crash issue. 2022-10-23 23:16:08 +02:00
Kuba Szczodrzyński
6628b97faf
[API/Usos] Fix detecting term start and end date. 2022-10-23 23:11:49 +02:00
Kuba Szczodrzyński
8424414317
[Login] Fix configOverrides NPE during login. 2022-10-23 23:11:20 +02:00
Kuba Szczodrzyński
d8bb927703
[4.13-rc.2] Update build.gradle, signing and changelog. 2022-10-22 22:34:24 +02:00
Kuba Szczodrzyński
c8e8c172a2
[App] Rework update handling. 2022-10-22 22:10:04 +02:00
Kuba Szczodrzyński
0d4dee765a
[Lab] Allow setting custom API key. 2022-10-22 12:56:15 +02:00
Kuba Szczodrzyński
fd407b2b03
[Config] Set highest data version by default. 2022-10-22 12:31:40 +02:00
Kuba Szczodrzyński
40ed5a221f
[App] Fix crashes while deserializing AppData and Config. 2022-10-22 12:19:23 +02:00
Kuba Szczodrzyński
5150467372
[4.13-rc.1] Update build.gradle, signing and changelog. 2022-10-22 00:02:57 +02:00
Kuba Szczodrzyński
63c5720f63
[App] Move per-register settings to JSON resource. Rewrite Config to use delegates. (#150)
* [App] Add base for AppData loading.

* [UI] Fix timetable widget date navigation.

* [UI] Migrate register-specific behavior to use AppData.

* [App] Implement new delegate-based config base.

* [Config] Migrate config and profile config.

* [Config] Remove defaults from migrations.

* [App] Apply event types and config overrides from AppData.

* [Events] Change default event types for university type school.
2022-10-21 23:59:53 +02:00
Kuba Szczodrzyński
6c93cd4217
[4.13-beta.3] Update build.gradle, signing and changelog. 2022-10-20 22:02:01 +02:00
Kuba Szczodrzyński
649d4f619a
[UI] Hide unavailable settings depending on LoginType. 2022-10-20 21:59:01 +02:00
Kuba Szczodrzyński
ba10d10a10
[API] Refactor integer-based types to enum classes. (#145)
* [App] Add enum classes for common IDs.

* [App] Rename enum package names.

* [App] Migrate code to use new enums.

* [DB] Migrate loginStoreMode IDs to be unique.

* [UI] Fix minor issues after refactor.

* [API] Update sync method signature.

* [UI] Correct pop-to-home and back button drawer behavior.

* [App] Update Bundle extensions usage.

* [App] Migrate notification types to enum.

* [UI] Make Lab fragment compatible with enums.

* [API] Make EndpointTimer use FeatureType.

* [App] Migrate config & API lists to sets.
2022-10-20 21:58:10 +02:00
Kuba Szczodrzyński
1450d63fcb
[4.13-beta.2] Update build.gradle, signing and changelog. 2022-10-18 22:06:18 +02:00
Kuba Szczodrzyński
2ec06bc39a
[UI] Fix timetable lesson height. Add missing timetable settings. 2022-10-18 11:49:46 +02:00
Kuba Szczodrzyński
6f12227c2e
[4.13-beta.1] Update build.gradle, signing and changelog. 2022-10-17 22:56:22 +02:00
Kuba Szczodrzyński
3a91f87ccd
Merge pull request #142 from szkolny-eu/feature/usos
[API] Add USOS API support.
2022-10-17 22:52:08 +02:00
Kuba Szczodrzyński
52a53334ca
[Strings] Add USOS error descriptions. 2022-10-17 22:30:23 +02:00
Kuba Szczodrzyński
3ab9602865
[API/Usos] Fix re-logging in after user action. 2022-10-17 16:06:29 +02:00
kuba2k2
dc19043f73
[API/Usos] Implement basic error handling. 2022-10-17 12:56:07 +02:00
Kuba Szczodrzyński
cf25507850
[API/Usos] Save lecturers as teachers. Add team class. 2022-10-16 18:41:37 +02:00
Kuba Szczodrzyński
044cedff99
[Usos] Override lesson colors by activity type. 2022-10-16 18:13:22 +02:00
Kuba Szczodrzyński
4de066bf5f
[API/Usos] Implement Timetable. 2022-10-16 17:21:36 +02:00
Kuba Szczodrzyński
8d174bda01
Merge remote-tracking branch 'origin/develop' into feature/usos 2022-10-16 16:54:44 +02:00
Kuba Szczodrzyński
e2fd714070
[UI/Timetable] Show subject-based lesson colors. (#141)
* [UI/Timetable] Add timetable config dialog and implement UI options.

* [UI/Timetable] Fix reloading timetable after changing config.

* [UI/Timetable] Fix calculating lesson range boundaries.

* [UI/Timetable] Add coloring subject names.
2022-10-16 12:47:54 +02:00
Kuba Szczodrzyński
8097e8d06d
[API/Usos] Add syncing Courses and Terms. 2022-10-16 00:09:51 +02:00
Kuba Szczodrzyński
93ccdbdeb7
[API/Login] Make user action handling more universal. 2022-10-15 21:24:30 +02:00
Kuba Szczodrzyński
7ded400a30
[API/Usos] Implement first login. 2022-10-15 19:07:12 +02:00
Kuba Szczodrzyński
2ff784066e
[API/Usos] Implement OAuth authorization flow. 2022-10-14 21:44:58 +02:00
Kuba Szczodrzyński
6c96875c83
[API/Login] Allow passing LoginStore params in user action requests. 2022-10-14 19:44:22 +02:00
kuba2k2
9f3aaf6e86
[API] Move register platforms to new endpoint. 2022-10-14 14:43:40 +02:00
Kuba Szczodrzyński
55369eaa8b
[UI/Timetable] Add Timetable settings. (#140)
* [UI/Timetable] Add timetable config dialog and implement UI options.

* [UI/Timetable] Fix reloading timetable after changing config.

* [UI/Timetable] Fix calculating lesson range boundaries.
2022-10-14 00:25:22 +02:00
Adam Kasprzycki
c983c16907
[UI] Request notifications permission on API >= 33. (#143)
* Added requesting notifications permission on Android 13 devices

* Move permission check to PermissionManager

* Request permission on home screen
2022-10-14 00:24:00 +02:00
kuba2k2
c7362bce12
[API/Usos] Add base rest API class. 2022-10-13 21:27:55 +02:00
kuba2k2
7935d0f097
[API] Pass parameters to user action required errors. 2022-10-13 11:45:17 +02:00
Kuba Szczodrzyński
4b64277948
[API/Usos] Add basic USOS API structure. 2022-10-11 23:23:11 +02:00
481 changed files with 16138 additions and 6106 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

@ -36,6 +36,8 @@ android {
arguments { arguments {
arg("room.schemaLocation", "$projectDir/schemas") arg("room.schemaLocation", "$projectDir/schemas")
} }
correctErrorTypes true
} }
} }
@ -110,6 +112,8 @@ android {
lint { lint {
checkReleaseBuilds false checkReleaseBuilds false
} }
namespace 'pl.szczodrzynski.edziennik'
} }
tasks.whenTaskAdded { task -> tasks.whenTaskAdded { task ->
@ -141,32 +145,32 @@ tasks.whenTaskAdded { task ->
dependencies { dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs') implementation fileTree(include: ['*.jar'], dir: 'libs')
// 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.6.1" 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
@ -174,12 +178,13 @@ 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"
// Szkolny.eu libraries/forks // Szkolny.eu libraries/forks
implementation "com.github.santoni0:NavLib:323288f"
implementation "eu.szkolny:android-snowfall:1ca9ea2da3" implementation "eu.szkolny:android-snowfall:1ca9ea2da3"
implementation "eu.szkolny:agendacalendarview:1.0.4" implementation "eu.szkolny:agendacalendarview:1.0.4"
implementation "eu.szkolny:cafebar:5bf0c618de" implementation "eu.szkolny:cafebar:5bf0c618de"
@ -190,7 +195,7 @@ dependencies {
implementation "eu.szkolny.selective-dao:annotation:27f8f3f194" implementation "eu.szkolny.selective-dao:annotation:27f8f3f194"
officialImplementation "eu.szkolny:ssl-provider:1.0.0" officialImplementation "eu.szkolny:ssl-provider:1.0.0"
unofficialImplementation "eu.szkolny:ssl-provider:1.0.0" unofficialImplementation "eu.szkolny:ssl-provider:1.0.0"
implementation "pl.szczodrzynski:navlib:0.8.0"
implementation "pl.szczodrzynski:numberslidingpicker:2921225f76" implementation "pl.szczodrzynski:numberslidingpicker:2921225f76"
implementation "pl.szczodrzynski:recyclertablayout:700f980584" implementation "pl.szczodrzynski:recyclertablayout:700f980584"
implementation "pl.szczodrzynski:tachyon:551943a6b5" implementation "pl.szczodrzynski:tachyon:551943a6b5"
@ -200,6 +205,7 @@ dependencies {
implementation "com.mikepenz:iconics-core:5.3.2" implementation "com.mikepenz:iconics-core:5.3.2"
implementation "com.mikepenz:iconics-views:5.3.2" implementation "com.mikepenz:iconics-views:5.3.2"
implementation "com.mikepenz:community-material-typeface:5.8.55.0-kotlin@aar" implementation "com.mikepenz:community-material-typeface:5.8.55.0-kotlin@aar"
implementation 'com.mikepenz:google-material-typeface:4.0.0.2-kotlin@aar'
implementation "eu.szkolny:szkolny-font:77e33acc2a" implementation "eu.szkolny:szkolny-font:77e33acc2a"
// Other dependencies // Other dependencies
@ -208,7 +214,7 @@ dependencies {
implementation "com.daimajia.swipelayout:library:1.2.0@aar" implementation "com.daimajia.swipelayout:library:1.2.0@aar"
implementation "com.github.Applandeo:Material-Calendar-View:15de569cbc" // https://github.com/Applandeo/Material-Calendar-View implementation "com.github.Applandeo:Material-Calendar-View:15de569cbc" // https://github.com/Applandeo/Material-Calendar-View
implementation "com.github.CanHub:Android-Image-Cropper:2.2.2" // https://github.com/CanHub/Android-Image-Cropper implementation "com.github.CanHub:Android-Image-Cropper:2.2.2" // https://github.com/CanHub/Android-Image-Cropper
implementation "com.github.ChuckerTeam.Chucker:library:3.0.1" // https://github.com/ChuckerTeam/chucker implementation "com.github.ChuckerTeam.Chucker:library:3.5.2" // https://github.com/ChuckerTeam/chucker
implementation "com.github.antonKozyriatskyi:CircularProgressIndicator:1.2.2" // https://github.com/antonKozyriatskyi/CircularProgressIndicator implementation "com.github.antonKozyriatskyi:CircularProgressIndicator:1.2.2" // https://github.com/antonKozyriatskyi/CircularProgressIndicator
implementation "com.github.bassaer:chatmessageview:2.0.1" // https://github.com/bassaer/ChatMessageView implementation "com.github.bassaer:chatmessageview:2.0.1" // https://github.com/bassaer/ChatMessageView
implementation "com.github.hypertrack:hyperlog-android:0.0.10" // https://github.com/hypertrack/hyperlog-android implementation "com.github.hypertrack:hyperlog-android:0.0.10" // https://github.com/hypertrack/hyperlog-android
@ -227,4 +233,28 @@ dependencies {
// Debug-only dependencies // Debug-only dependencies
debugImplementation "com.github.amitshekhariitbhu.Android-Debug-Database:debug-db:v1.0.6" debugImplementation "com.github.amitshekhariitbhu.Android-Debug-Database:debug-db:v1.0.6"
// NavLib required dependencies
debugImplementation "com.mikepenz:iconics-views:5.3.2"
debugImplementation "com.mikepenz:iconics-typeface-api:5.3.2"
debugImplementation "com.mikepenz:community-material-typeface:5.8.55.0-kotlin@aar"
debugImplementation "com.balysv:material-ripple:1.0.2"
debugApi "com.mikepenz:materialize:1.2.1"
debugApi "com.mikepenz:materialdrawer:9.0.1"
debugApi "com.mikepenz:iconics-core:5.3.2"
debugApi "com.mikepenz:itemanimators:1.1.0"
// agencacalendarview required dependencies
debugApi 'eu.szkolny:StickyListHeaders:2.7.1'
debugImplementation 'io.reactivex:rxjava:1.1.1'
// material-about-library required dependencies
androidTestImplementation('androidx.test.espresso:espresso-core:3.3.0-alpha04', {
exclude group: 'com.android.support', module: 'support-annotations'
})
debugImplementation 'net.yslibrary.licenseadapter:licenseadapter:3.0.0'
testImplementation 'junit:junit:4.13.2'
} }

View File

@ -5,7 +5,7 @@
buildscript { buildscript {
repositories { repositories {
google() google()
jcenter() mavenCentral()
} }
dependencies { dependencies {
classpath "org.eclipse.jgit:org.eclipse.jgit:5.5.+" classpath "org.eclipse.jgit:org.eclipse.jgit:5.5.+"

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

View File

@ -137,6 +137,7 @@
"columnNames": [ "columnNames": [
"profileId" "profileId"
], ],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_grades_profileId` ON `${TABLE_NAME}` (`profileId`)" "createSql": "CREATE INDEX IF NOT EXISTS `index_grades_profileId` ON `${TABLE_NAME}` (`profileId`)"
} }
], ],
@ -290,6 +291,7 @@
"columnNames": [ "columnNames": [
"profileId" "profileId"
], ],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_teacherAbsence_profileId` ON `${TABLE_NAME}` (`profileId`)" "createSql": "CREATE INDEX IF NOT EXISTS `index_teacherAbsence_profileId` ON `${TABLE_NAME}` (`profileId`)"
} }
], ],
@ -452,6 +454,7 @@
"columnNames": [ "columnNames": [
"profileId" "profileId"
], ],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_notices_profileId` ON `${TABLE_NAME}` (`profileId`)" "createSql": "CREATE INDEX IF NOT EXISTS `index_notices_profileId` ON `${TABLE_NAME}` (`profileId`)"
} }
], ],
@ -629,6 +632,7 @@
"columnNames": [ "columnNames": [
"profileId" "profileId"
], ],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_attendances_profileId` ON `${TABLE_NAME}` (`profileId`)" "createSql": "CREATE INDEX IF NOT EXISTS `index_attendances_profileId` ON `${TABLE_NAME}` (`profileId`)"
} }
], ],
@ -781,6 +785,7 @@
"eventDate", "eventDate",
"eventTime" "eventTime"
], ],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_events_profileId_eventDate_eventTime` ON `${TABLE_NAME}` (`profileId`, `eventDate`, `eventTime`)" "createSql": "CREATE INDEX IF NOT EXISTS `index_events_profileId_eventDate_eventTime` ON `${TABLE_NAME}` (`profileId`, `eventDate`, `eventTime`)"
}, },
{ {
@ -790,6 +795,7 @@
"profileId", "profileId",
"eventType" "eventType"
], ],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_events_profileId_eventType` ON `${TABLE_NAME}` (`profileId`, `eventType`)" "createSql": "CREATE INDEX IF NOT EXISTS `index_events_profileId_eventType` ON `${TABLE_NAME}` (`profileId`, `eventType`)"
} }
], ],
@ -1166,6 +1172,7 @@
"columnNames": [ "columnNames": [
"profileId" "profileId"
], ],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_announcements_profileId` ON `${TABLE_NAME}` (`profileId`)" "createSql": "CREATE INDEX IF NOT EXISTS `index_announcements_profileId` ON `${TABLE_NAME}` (`profileId`)"
} }
], ],
@ -1407,6 +1414,7 @@
"profileId", "profileId",
"messageType" "messageType"
], ],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_messages_profileId_messageType` ON `${TABLE_NAME}` (`profileId`, `messageType`)" "createSql": "CREATE INDEX IF NOT EXISTS `index_messages_profileId_messageType` ON `${TABLE_NAME}` (`profileId`, `messageType`)"
} }
], ],
@ -1918,6 +1926,7 @@
"type", "type",
"date" "date"
], ],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_timetable_profileId_type_date` ON `${TABLE_NAME}` (`profileId`, `type`, `date`)" "createSql": "CREATE INDEX IF NOT EXISTS `index_timetable_profileId_type_date` ON `${TABLE_NAME}` (`profileId`, `type`, `date`)"
}, },
{ {
@ -1928,6 +1937,7 @@
"type", "type",
"oldDate" "oldDate"
], ],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_timetable_profileId_type_oldDate` ON `${TABLE_NAME}` (`profileId`, `type`, `oldDate`)" "createSql": "CREATE INDEX IF NOT EXISTS `index_timetable_profileId_type_oldDate` ON `${TABLE_NAME}` (`profileId`, `type`, `oldDate`)"
} }
], ],
@ -2015,6 +2025,7 @@
"columnNames": [ "columnNames": [
"profileId" "profileId"
], ],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_librusLessons_profileId` ON `${TABLE_NAME}` (`profileId`)" "createSql": "CREATE INDEX IF NOT EXISTS `index_librusLessons_profileId` ON `${TABLE_NAME}` (`profileId`)"
} }
], ],
@ -2117,6 +2128,7 @@
"profileId", "profileId",
"date" "date"
], ],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_timetableManual_profileId_date` ON `${TABLE_NAME}` (`profileId`, `date`)" "createSql": "CREATE INDEX IF NOT EXISTS `index_timetableManual_profileId_date` ON `${TABLE_NAME}` (`profileId`, `date`)"
}, },
{ {
@ -2126,6 +2138,7 @@
"profileId", "profileId",
"weekDay" "weekDay"
], ],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_timetableManual_profileId_weekDay` ON `${TABLE_NAME}` (`profileId`, `weekDay`)" "createSql": "CREATE INDEX IF NOT EXISTS `index_timetableManual_profileId_weekDay` ON `${TABLE_NAME}` (`profileId`, `weekDay`)"
} }
], ],
@ -2217,6 +2230,7 @@
"noteOwnerType", "noteOwnerType",
"noteOwnerId" "noteOwnerId"
], ],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_notes_profileId_noteOwnerType_noteOwnerId` ON `${TABLE_NAME}` (`profileId`, `noteOwnerType`, `noteOwnerId`)" "createSql": "CREATE INDEX IF NOT EXISTS `index_notes_profileId_noteOwnerType_noteOwnerId` ON `${TABLE_NAME}` (`profileId`, `noteOwnerType`, `noteOwnerId`)"
} }
], ],
@ -2278,6 +2292,7 @@
"thingType", "thingType",
"thingId" "thingId"
], ],
"orders": [],
"createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_metadata_profileId_thingType_thingId` ON `${TABLE_NAME}` (`profileId`, `thingType`, `thingId`)" "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_metadata_profileId_thingType_thingId` ON `${TABLE_NAME}` (`profileId`, `thingType`, `thingId`)"
} }
], ],

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools">
package="pl.szczodrzynski.edziennik">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
@ -10,8 +9,10 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<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" />
<!-- 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" />
@ -84,7 +85,7 @@
android:resource="@xml/widget_timetable_info" /> android:resource="@xml/widget_timetable_info" />
</receiver> </receiver>
<service android:name=".ui.widgets.timetable.WidgetTimetableService" <service android:name=".ui.widgets.timetable.WidgetTimetableService"
android:permission="android.permission.BIND_REMOTEVIEWS" /> android:permission="android.permission.BIND_REMOTEVIEWS" android:foregroundServiceType="dataSync"/>
<activity android:name=".ui.widgets.LessonDialogActivity" <activity android:name=".ui.widgets.LessonDialogActivity"
android:label="" android:label=""
android:configChanges="orientation|keyboardHidden" android:configChanges="orientation|keyboardHidden"
@ -105,7 +106,7 @@
android:resource="@xml/widget_notifications_info" /> android:resource="@xml/widget_notifications_info" />
</receiver> </receiver>
<service android:name=".ui.widgets.notifications.WidgetNotificationsService" <service android:name=".ui.widgets.notifications.WidgetNotificationsService"
android:permission="android.permission.BIND_REMOTEVIEWS" /> android:permission="android.permission.BIND_REMOTEVIEWS" android:foregroundServiceType="dataSync"/>
<!-- LUCKY NUMBER --> <!-- LUCKY NUMBER -->
<receiver android:name=".ui.widgets.luckynumber.WidgetLuckyNumberProvider" <receiver android:name=".ui.widgets.luckynumber.WidgetLuckyNumberProvider"
android:label="@string/widget_lucky_number_title" android:label="@string/widget_lucky_number_title"
@ -157,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" />
@ -194,15 +203,15 @@
____) | __/ | \ V /| | (_| __/\__ \ ____) | __/ | \ V /| | (_| __/\__ \
|_____/ \___|_| \_/ |_|\___\___||___/ |_____/ \___|_| \_/ |_|\___\___||___/
--> -->
<service android:name=".data.api.ApiService" /> <service android:name=".data.api.ApiService" android:foregroundServiceType="dataSync"/>
<service android:name=".data.firebase.MyFirebaseService" <service android:name=".data.firebase.MyFirebaseService"
android:exported="false"> android:exported="false" android:foregroundServiceType="dataSync">
<intent-filter android:priority="10000000"> <intent-filter android:priority="10000000">
<action android:name="com.google.firebase.MESSAGING_EVENT" /> <action android:name="com.google.firebase.MESSAGING_EVENT" />
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" /> <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter> </intent-filter>
</service> </service>
<service android:name=".sync.UpdateDownloaderService" /> <service android:name=".sync.UpdateDownloaderService" android:foregroundServiceType="dataSync"/>
<!-- <!--
_____ _ _ _____ _ _

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

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,
NavTarget.AGENDA,
NavTarget.GRADES,
NavTarget.MESSAGES,
NavTarget.HOMEWORK,
NavTarget.SETTINGS
)
}
var openDrawerOnBackPressed by base.config<Boolean>(false)
private var mMiniMenuVisible: Boolean? = null var bottomSheetOpened by base.config<Boolean>(false)
var miniMenuVisible: Boolean var snowfall by base.config<Boolean>(false)
get() { mMiniMenuVisible = mMiniMenuVisible ?: config.values.get("miniMenuVisible", false); return mMiniMenuVisible ?: false } var eggfall by base.config<Boolean>(false)
set(value) { config.set("miniMenuVisible", value); mMiniMenuVisible = value }
private var mMiniMenuButtons: List<Int>? = null
var miniMenuButtons: List<Int>
get() { mMiniMenuButtons = mMiniMenuButtons ?: config.values.getIntList("miniMenuButtons", listOf()); return mMiniMenuButtons ?: listOf() }
set(value) { config.set("miniMenuButtons", value); mMiniMenuButtons = value }
private var mOpenDrawerOnBackPressed: Boolean? = null
var openDrawerOnBackPressed: Boolean
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")
@ -25,4 +25,4 @@ interface ConfigDao {
@Query("DELETE FROM config WHERE profileId = :profileId") @Query("DELETE FROM config WHERE profileId = :profileId")
fun clear(profileId: Int) fun clear(profileId: Int)
} }

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)) { EventBus.getDefault().postSticky(ApiTaskErrorEvent(apiError))
app.userActionManager.sendToUser(apiError) errorList.add(apiError)
} apiError.throwable?.printStackTrace()
else {
EventBus.getDefault().postSticky(ApiTaskErrorEvent(apiError))
errorList.add(apiError)
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()
// add all endpoint IDs and required login methods, filtering using timers
.onEach { feature -> for (feature in possibleFeatures) {
feature.endpointIds.forEach { endpoint -> // add all endpoint IDs and required login methods, filtering using timers
if (onlyEndpoints?.contains(endpoint.first) == false) feature.endpoints.forEach { endpoint ->
return@forEach if (onlyEndpoints?.contains(endpoint.first) == false)
(data.endpointTimers return@forEach
.singleOrNull { it.endpointId == endpoint.first } ?: EndpointTimer(data.profile?.id val timer = this.endpointTimers
?: -1, endpoint.first)) .singleOrNull { it.endpointId == endpoint.first }
.let { timer -> ?: EndpointTimer(this.profileId, endpoint.first)
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

@ -39,6 +39,7 @@ class LibrusRecaptchaHelper(
private var timedOut = false private var timedOut = false
inner class WebViewClient : android.webkit.WebViewClient() { inner class WebViewClient : android.webkit.WebViewClient() {
@Deprecated("Deprecated in Java")
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean { override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
timeout?.cancel() timeout?.cancel()
if (!timedOut) { if (!timedOut) {

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())
recipientFirstName, .toLong(),
recipientLastName recipientFirstName,
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) .contentType(MediaTypeUtils.APPLICATION_FORM)
.allowErrorCode(HTTP_BAD_REQUEST)
.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)) .withResponse(response))
return return
} }
if (text == null) {
if (json == null) {
if (response.parserErrorBody?.contains("wciąż nieaktywne") == true) {
data.error(ApiError(TAG, ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED)
.withResponse(response))
return
}
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,7 +25,8 @@ 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] }
data.loginEmail = email if (email.isNotNullNorBlank())
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)
onSuccess(ENDPOINT_MOBIDZIENNIK_WEB_ACCOUNT_EMAIL) onSuccess(ENDPOINT_MOBIDZIENNIK_WEB_ACCOUNT_EMAIL)

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

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