1
0

Compare commits

..

127 Commits

Author SHA1 Message Date
4f60673e4e Merge branch 'release/0.14.0' 2019-12-25 16:52:28 +01:00
7bd4fd7cbd Version 0.14.0 2019-12-25 16:52:17 +01:00
65995cdc6c Change Wulkanowy API link to SDK in README (#626) 2019-12-24 16:51:35 +01:00
9d27723f30 Don't copy teacher from previous lesson with changes if new one… (#622) 2019-12-22 20:19:31 +01:00
2e7d2b66f8 Fix lucky number empty screen (#623) 2019-12-22 20:18:48 +01:00
304c49d61e Migration to Wulkanowy SDK (#336) 2019-12-22 00:14:46 +01:00
826ea32fc0 Bump room from 2.2.2 to 2.2.3 (#618) 2019-12-20 10:18:00 +00:00
d70c4fa9fe Bump work_manager from 2.3.0-beta01 to 2.3.0-beta02 (#620) 2019-12-20 09:46:28 +00:00
bc43359467 Bump mockito-inline from 3.2.0 to 3.2.4 (#621) 2019-12-20 09:44:18 +00:00
cf286f3c23 Bump mockito-android from 3.2.0 to 3.2.4 (#619) 2019-12-20 09:27:14 +00:00
57abd43214 Bump fragment-ktx from 1.2.0-rc03 to 1.2.0-rc04 (#617) 2019-12-20 09:24:51 +00:00
90bdc9d157 Bump material from 1.1.0-beta02 to 1.1.0-rc01 (#616) 2019-12-20 09:13:34 +00:00
93bce685bd Bump dagger from 2.25.2 to 2.25.3 (#614) 2019-12-20 09:07:39 +00:00
4639a075b0 Bump rxjava from 2.2.15 to 2.2.16 (#615) 2019-12-20 09:06:52 +00:00
91f63da6d0 Fixed capitalization in the about tab (en) (#613) 2019-12-09 17:35:18 +01:00
3894c9d48e Fixed letter capitalization in the About tab (pl) (#612) 2019-12-09 17:34:58 +01:00
fb40701962 Merge tag '0.13.0' into develop
Version 0.13.0
2019-12-07 23:04:39 +01:00
ff1e794820 Merge branch 'release/0.13.0' 2019-12-07 23:04:26 +01:00
ceba5f7fe8 Version 0.13.0 2019-12-07 23:04:17 +01:00
f570acbed6 Add FAQ link (#611) 2019-12-07 22:06:15 +01:00
2a7a472d90 Bump fragment-ktx from 1.2.0-rc02 to 1.2.0-rc03 (#610) 2019-12-07 16:07:36 +00:00
138fbe5bf5 Bump activity-ktx from 1.1.0-rc02 to 1.1.0-rc03 (#608) 2019-12-07 12:51:40 +00:00
ad99cc75eb Bump gradle from 3.5.2 to 3.5.3 (#609) 2019-12-07 12:51:24 +00:00
f6606e7a4f Bump coordinatorlayout from 1.1.0-rc01 to 1.1.0 (#607) 2019-12-07 12:51:09 +00:00
3690deef1e Bump mockito-android from 3.1.0 to 3.2.0 (#605) 2019-12-02 16:19:20 +00:00
cd1438587d Bump kotlin_version from 1.3.60 to 1.3.61 (#606) 2019-12-02 16:18:56 +00:00
8193a57227 Bump mockito-inline from 3.1.0 to 3.2.0 (#604) 2019-12-02 16:18:27 +00:00
8467f39ad9 Add russian language (#595) 2019-11-29 20:43:37 +01:00
0fc293f47a Bump assisted-inject-processor-dagger2 from 0.5.1 to 0.5.2 (#601) 2019-11-25 17:15:23 +00:00
9b063edb0b Bump rxjava from 2.2.14 to 2.2.15 (#603) 2019-11-25 16:48:56 +00:00
5d852eee87 Bump assisted-inject-annotations-dagger2 from 0.5.1 to 0.5.2 (#602) 2019-11-25 16:48:07 +00:00
54ab408135 Add error view showing on first loading in fragment view (#590) 2019-11-24 17:05:09 +01:00
41aa326f42 Add 0,00 grade modifier (#596) 2019-11-21 17:41:41 +01:00
24f605c71c Bump work_manager from 2.3.0-alpha03 to 2.3.0-beta01 (#600) 2019-11-21 11:00:11 +00:00
5c52dcc74f Bump room from 2.2.1 to 2.2.2 (#599) 2019-11-21 10:31:14 +00:00
667659fbe6 Bump core-ktx from 1.2.0-beta02 to 1.2.0-rc01 (#598) 2019-11-21 10:30:51 +00:00
d467bf096f Bump recyclerview from 1.1.0-rc01 to 1.1.0 (#597) 2019-11-21 10:28:54 +00:00
98d556bcd5 Bump kotlin_version from 1.3.50 to 1.3.60 (#594) 2019-11-18 10:57:50 +01:00
8c730be635 Bump google-services from 4.3.2 to 4.3.3 (#591) 2019-11-18 08:58:17 +00:00
377d24fbb4 Bump sonarqube-gradle-plugin from 2.8 to 2.8.0.1969 (#593) 2019-11-18 08:26:46 +00:00
bde810e031 Fix screens loading state (#589) 2019-11-17 01:07:43 +01:00
2f18d42c86 Update material design components (#587) 2019-11-10 16:45:53 +01:00
c708b0c20e Bump activity-ktx from 1.1.0-rc01 to 1.1.0-rc02 (#586) 2019-11-09 13:35:59 +00:00
ff8d55d4f8 Bump fragment-ktx from 1.2.0-rc01 to 1.2.0-rc02 (#585) 2019-11-09 13:08:02 +00:00
49bf911c84 Bump core-ktx from 1.2.0-beta01 to 1.2.0-beta02 (#584) 2019-11-09 13:07:27 +00:00
9e33ef419f Fix LuckyNumberWidget not showing ThemeDialog (#583) 2019-11-09 13:59:33 +01:00
40e95eac1e Add BaseDao interface (#581) 2019-11-06 23:52:14 +01:00
19e76a0b5d Bump rxjava from 2.2.13 to 2.2.14 (#580) 2019-11-04 19:23:50 +00:00
5feafe3907 Update gradle wrapper (#579) 2019-11-03 15:07:32 +01:00
b7206ed714 Add DatePicker to Timetable and Attendance modules. (#522) 2019-11-03 14:52:35 +01:00
38370d647d Add language change settings (#577) 2019-11-03 12:37:03 +01:00
323bc188b1 Bump assisted-inject-annotations-dagger2 from 0.5.0 to 0.5.1 (#576) 2019-11-01 20:20:09 +00:00
b17356591a Bump assisted-inject-processor-dagger2 from 0.5.0 to 0.5.1 (#575) 2019-11-01 19:50:28 +00:00
a02c444cf5 Merge tag '0.12.0' into develop
0.12.0
2019-10-29 00:25:17 +01:00
87a133beb9 Merge branch 'release/0.12.0' 2019-10-29 00:25:12 +01:00
1f4a208857 Version 0.12.0 2019-10-29 00:25:03 +01:00
a7c472989c Add support for edu.lublin.eu (#571) 2019-10-28 21:10:58 +01:00
747696e386 Bump firebase-core from 17.2.0 to 17.2.1 (#572) 2019-10-28 14:58:10 +00:00
a71a183160 Add school quick actions (#570) 2019-10-27 00:36:39 +02:00
125a010f03 Fix restoring state in exposed dropdown menu (#569) 2019-10-24 22:56:49 +02:00
5c5993cc2a Change FAB to extended FAB in messages (#536) 2019-10-24 18:45:05 +02:00
f234b71932 Bump dagger from 2.24 to 2.25.2 (#564) 2019-10-24 18:24:22 +02:00
497a3391d4 Bump fragment-ktx from 1.2.0-beta02 to 1.2.0-rc01 (#568) 2019-10-24 06:58:42 +00:00
a72c743c6f Bump work_manager from 2.3.0-alpha02 to 2.3.0-alpha03 (#563) 2019-10-24 06:37:24 +00:00
98fdfd001a Bump recyclerview from 1.1.0-beta05 to 1.1.0-rc01 (#566) 2019-10-24 06:17:11 +00:00
994b162ae3 Bump activity-ktx from 1.1.0-beta01 to 1.1.0-rc01 (#567) 2019-10-24 06:16:51 +00:00
90c60f399b Bump coordinatorlayout from 1.1.0-beta01 to 1.1.0-rc01 (#565) 2019-10-24 06:15:58 +00:00
b16b225a1a Bump room from 2.2.0 to 2.2.1 (#562) 2019-10-24 05:55:08 +00:00
7a4cf694ca Add school info (#557)
* Add db layer to school info

* Add base classes

* Add database migration

* Add base view

* Update icon

* Fix textviews height

* Handle error and empty results

* Improve school info look

* Add strings

* Fix action bar elevation in school fragment

* Add missing blank lines

* Reorganize strings

* Make field title first in order

* Make fields views selectable

* Rename SchoolInfo to School
2019-10-21 21:25:15 +02:00
1b492d50fe Bump aboutlibraries from 7.0.3 to 7.0.4 (#559) 2019-10-21 19:23:41 +00:00
d9b5e000f8 Bump gradle from 1.31.1 to 1.31.2 (#560) 2019-10-21 19:23:13 +00:00
7e30524876 Contact info after failed login (#556) 2019-10-20 19:10:32 +02:00
ce9b12eb93 Add system theme setting for Android 10 (#554) 2019-10-16 22:27:16 +02:00
b602657d55 Move default preferences values to separate file (#555) 2019-10-16 20:10:24 +02:00
360dfbcdb5 Update androidx dependencies (#553) 2019-10-15 19:15:28 +02:00
f466497970 Bump recyclerview from 1.1.0-beta04 to 1.1.0-beta05 (#551) 2019-10-11 21:56:19 +00:00
184a7ab200 Bump room from 2.2.0-rc01 to 2.2.0 (#552) 2019-10-11 21:55:28 +00:00
2e5ef7dfa2 Merge tag '0.11.0' into develop
Version 0.11.0
2019-10-07 00:11:59 +02:00
8f617f4ca1 Merge branch 'release/0.11.0' 2019-10-07 00:11:52 +02:00
fe5f96a394 Version 0.11.0 2019-10-07 00:11:33 +02:00
cb9c35d772 Add navigate up to login view (#547) 2019-10-06 22:43:16 +02:00
7cf7977cc6 Bump gson from 2.8.5 to 2.8.6 (#549) 2019-10-06 20:15:53 +00:00
1de747fa35 Add mark as read button enable logic (#534) 2019-10-06 21:25:24 +02:00
93750829d7 Fix duplicate percentage in attendance summary (#548) 2019-10-06 18:21:56 +02:00
798688e7dd Fix multidex in debug variant (#545) 2019-10-05 22:32:55 +02:00
6ab9c1d737 Update mockito to last version from maven central (#546) 2019-10-03 22:47:49 +02:00
b074ce99b7 Bump sonarqube-gradle-plugin from 2.7.1 to 2.8 (#543) 2019-10-03 20:21:43 +00:00
b03fd86be5 Bump gradle from 3.5.0 to 3.5.1 (#542) 2019-10-03 20:08:32 +00:00
3de2f5ff88 Bump githook from 1.1.0 to 1.2.0 (#539) 2019-10-03 19:54:16 +00:00
35adf83154 Bump rxjava from 2.2.12 to 2.2.13 (#538) 2019-10-03 19:43:12 +00:00
0162c8bbee Add better timetable changes display (#513) 2019-10-03 21:13:01 +02:00
736d570f26 Change timetable widget date format (#530) 2019-10-03 15:29:33 +02:00
5b0901e311 Clear Semesters table (#535) 2019-10-03 14:00:07 +02:00
f9474af39e Add points to class grades statistics (#512) 2019-10-03 00:46:08 +02:00
d411d86355 Add click to copy function (#531) 2019-10-02 23:42:38 +02:00
a50c6707cb Update readme badges (#532) 2019-10-01 22:19:28 +02:00
6991c68d3a Bump mockito-core from 3.0.8 to 3.0.11 (#525) 2019-09-30 10:31:07 +00:00
8b1e6f7bd6 Bump play-publisher from 2.4.1 to 2.4.2 (#528) 2019-09-30 10:16:38 +00:00
943fd9c622 Bump logging-interceptor from 3.12.5 to 3.12.6 (#529) 2019-09-30 10:09:57 +00:00
838e2781c0 Bump mockito-inline from 3.0.8 to 3.0.11 (#526) 2019-09-30 10:05:54 +00:00
66cfd7b52c Bump mockito-android from 3.0.8 to 3.0.11 (#527) 2019-09-30 10:04:50 +00:00
a45bc0eef6 Add teachers (#489) 2019-09-29 18:09:53 +02:00
ed7996299e Improve date navigation (#519) 2019-09-28 20:37:14 +02:00
d4b73fb73e Add dark theme for app widgets (#509) 2019-09-25 22:44:55 +02:00
d6ece78eff Bump mockito-android from 3.0.7 to 3.0.8 (#518) 2019-09-22 11:03:41 +00:00
2f44f3c4ba Bump gradle from 1.31.0 to 1.31.1 (#517) 2019-09-22 10:55:34 +00:00
23b49e4b8c Bump mockito-inline from 3.0.7 to 3.0.8 (#516) 2019-09-22 10:50:21 +00:00
5d33cefe1d Bump mockito-core from 3.0.7 to 3.0.8 (#515) 2019-09-22 10:49:39 +00:00
6089df9462 Fix wrong index in form host value (#507) 2019-09-16 23:27:58 +02:00
3ee98e2bd0 Fix privacy link position on small screens (#508) 2019-09-16 23:13:46 +02:00
53a5d02051 Fix attendance_excused_lateness pl typo (#511) 2019-09-16 23:06:37 +02:00
e332fd9cf9 Bump logging-interceptor from 3.12.4 to 3.12.5 (#510) 2019-09-16 08:29:32 +00:00
7232938c12 Update API 28 to API 29 (#506) 2019-09-12 16:36:32 +02:00
fd02f2253b Merge tag '0.10.2' into develop
Version 0.10.2
2019-09-10 13:01:52 +02:00
12046ef0a0 Merge branch 'release/0.10.2' 2019-09-10 13:01:38 +02:00
dfc84b4208 Version 0.10.2 2019-09-10 12:58:27 +02:00
f5f11d5130 Fix login in symbol view (#493) 2019-09-10 12:25:08 +02:00
81ce328abd Bump recyclerview from 1.1.0-beta03 to 1.1.0-beta04 (#504) 2019-09-09 14:05:04 +00:00
867951136a Bump gradle-play-publisher from cdaeb61 to 2.4.0 (#501) 2019-09-09 13:43:55 +00:00
8b41ab27bd Bump mockito-core from 3.0.6 to 3.0.7 (#502) 2019-09-09 09:25:52 +00:00
e542ef003c Bump mockito-android from 3.0.6 to 3.0.7 (#503) 2019-09-09 08:54:03 +00:00
a5f212e6be Bump room from 2.2.0-beta01 to 2.2.0-rc01 (#499) 2019-09-09 08:39:39 +00:00
385a320536 Bump google-services from 4.3.1 to 4.3.2 (#498) 2019-09-09 08:25:51 +00:00
e65000ec2c Bump mockito-inline from 3.0.6 to 3.0.7 (#497) 2019-09-09 08:25:29 +00:00
c87de7b3c2 Bump logging-interceptor from 3.12.3 to 3.12.4 (#496) 2019-09-09 08:23:22 +00:00
bb6023709f Fix grade details header unread info (#494) 2019-09-08 15:10:29 +02:00
e998e54d3e Merge tag '0.10.1' into develop
Version 0.10.1
2019-09-07 02:25:22 +02:00
330 changed files with 14137 additions and 1608 deletions

View File

@ -98,7 +98,7 @@ jobs:
command: yes | sdkmanager --licenses && yes | sdkmanager --update command: yes | sdkmanager --licenses && yes | sdkmanager --update
- run: - run:
name: Setup emulator name: Setup emulator
command: sdkmanager "system-images;android-19;default;armeabi-v7a" && echo "no" | avdmanager create avd -n test -k "system-images;android-19;default;armeabi-v7a" command: sdkmanager "system-images;android-22;default;armeabi-v7a" && echo "no" | avdmanager create avd -n test -k "system-images;android-22;default;armeabi-v7a"
- run: - run:
name: Launch emulator name: Launch emulator
command: export LD_LIBRARY_PATH=${ANDROID_HOME}/emulator/lib64:${ANDROID_HOME}/emulator/lib64/qt/lib && emulator64-arm -avd test -noaudio -no-boot-anim -no-window -accel on command: export LD_LIBRARY_PATH=${ANDROID_HOME}/emulator/lib64:${ANDROID_HOME}/emulator/lib64/qt/lib && emulator64-arm -avd test -noaudio -no-boot-anim -no-window -accel on
@ -116,7 +116,7 @@ jobs:
adb shell input keyevent 82 adb shell input keyevent 82
- run: - run:
name: Run instrumented tests name: Run instrumented tests
command: ./gradlew clean createPlayDebugCoverageReport jacocoTestReport --no-daemon --stacktrace --console=plain -PdisablePreDex command: ./gradlew clean createFdroidDebugCoverageReport jacocoTestReport --no-daemon --stacktrace --console=plain -PdisablePreDex
- run: - run:
name: Collect logs from emulator name: Collect logs from emulator
command: adb logcat -d > ./app/build/reports/logcat_emulator.txt command: adb logcat -d > ./app/build/reports/logcat_emulator.txt

3
.gitignore vendored
View File

@ -110,4 +110,5 @@ Thumbs.db
### AndroidStudio Patch ### ### AndroidStudio Patch ###
!/gradle/wrapper/gradle-wrapper.jar !/gradle/wrapper/gradle-wrapper.jar
.idea/jarRepositories.xml

View File

@ -1,6 +1,9 @@
<component name="ProjectCodeStyleConfiguration"> <component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173"> <code_scheme name="Project" version="173">
<option name="LINE_SEPARATOR" value="&#10;" /> <option name="LINE_SEPARATOR" value="&#10;" />
<AndroidXmlCodeStyleSettings>
<option name="ARRANGEMENT_SETTINGS_MIGRATED_TO_191" value="true" />
</AndroidXmlCodeStyleSettings>
<JetCodeStyleSettings> <JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS"> <option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value> <value>

View File

@ -3,8 +3,8 @@ jdk: oraclejdk8
env: env:
global: global:
- ANDROID_API_LEVEL=28 - ANDROID_API_LEVEL=29
- ANDROID_BUILD_TOOLS_VERSION=28.0.3 - ANDROID_BUILD_TOOLS_VERSION=29.0.2
cache: cache:
directories: directories:
@ -14,7 +14,7 @@ cache:
branches: branches:
only: only:
- develop - develop
- 0.10.1 - 0.14.0
android: android:
licenses: licenses:
@ -34,12 +34,12 @@ android:
- extra-android-m2repository - extra-android-m2repository
- addon-google_apis-google-$ANDROID_API_LEVEL - addon-google_apis-google-$ANDROID_API_LEVEL
# Android emulator # Android emulator
- android-19 - android-22
- sys-img-armeabi-v7a-android-19 - sys-img-armeabi-v7a-android-22
before_script: before_script:
# Launch emulator before the execution # Launch emulator before the execution
- echo no | android create avd --force -n test -t android-19 --abi armeabi-v7a - echo no | android create avd --force -n test -t android-22 --abi armeabi-v7a
- emulator -avd test -no-audio -no-window & - emulator -avd test -no-audio -no-window &
- android-wait-for-emulator - android-wait-for-emulator
- adb shell input keyevent 82 & - adb shell input keyevent 82 &
@ -50,7 +50,7 @@ script:
- fossa --no-ansi || true - fossa --no-ansi || true
#- ./gradlew lintPlayRelease -x fabricGenerateResourcesPlayRelease --stacktrace --daemon #- ./gradlew lintPlayRelease -x fabricGenerateResourcesPlayRelease --stacktrace --daemon
- ./gradlew testPlayDebugUnitTest -x fabricGenerateResourcesPlay --stacktrace --daemon - ./gradlew testPlayDebugUnitTest -x fabricGenerateResourcesPlay --stacktrace --daemon
- ./gradlew createPlayDebugCoverageReport --stacktrace --daemon - ./gradlew createFdroidDebugCoverageReport --stacktrace --daemon
- ./gradlew jacocoTestReport --stacktrace --daemon - ./gradlew jacocoTestReport --stacktrace --daemon
- if [ -z ${SONAR_HOST+x} ]; then echo "sonar scan skipped"; else - if [ -z ${SONAR_HOST+x} ]; then echo "sonar scan skipped"; else
git fetch --unshallow; git fetch --unshallow;

View File

@ -4,8 +4,8 @@
[![Travis](https://img.shields.io/travis/com/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://travis-ci.com/wulkanowy/wulkanowy) [![Travis](https://img.shields.io/travis/com/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://travis-ci.com/wulkanowy/wulkanowy)
[![Codecov](https://img.shields.io/codecov/c/github/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://codecov.io/gh/wulkanowy/wulkanowy) [![Codecov](https://img.shields.io/codecov/c/github/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://codecov.io/gh/wulkanowy/wulkanowy)
[![Discord](https://img.shields.io/discord/390889354199040011.svg?style=flat-square)](https://discord.gg/vccAQBr) [![Discord](https://img.shields.io/discord/390889354199040011.svg?style=flat-square)](https://discord.gg/vccAQBr)
[![F-Droid](https://img.shields.io/f-droid/v/io.github.wulkanowy.svg)](https://f-droid.org/packages/io.github.wulkanowy/) [![F-Droid](https://img.shields.io/f-droid/v/io.github.wulkanowy.svg?style=flat-square)](https://f-droid.org/packages/io.github.wulkanowy/)
[![Last release](https://img.shields.io/github/release/wulkanowy/wulkanowy.svg?logo=github)](https://github.com/wulkanowy/wulkanowy/releases) [![Last release](https://img.shields.io/github/release/wulkanowy/wulkanowy.svg?logo=github&style=flat-square)](https://github.com/wulkanowy/wulkanowy/releases)
Unofficial android VULCAN UONET+ register client for student and parent Unofficial android VULCAN UONET+ register client for student and parent
@ -46,7 +46,7 @@ You can also download a [development version](https://wulkanowy.github.io/#downl
## Built With ## Built With
* [Wulkanowy API](https://github.com/wulkanowy/api) * [Wulkanowy SDK](https://github.com/wulkanowy/sdk)
* [RxJava 2](https://github.com/ReactiveX/RxJava) * [RxJava 2](https://github.com/ReactiveX/RxJava)
* [Dagger 2](https://github.com/google/dagger) * [Dagger 2](https://github.com/google/dagger)
* [Room](https://developer.android.com/topic/libraries/architecture/room) * [Room](https://developer.android.com/topic/libraries/architecture/room)

View File

@ -4,8 +4,8 @@
[![Travis](https://img.shields.io/travis/com/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://travis-ci.com/wulkanowy/wulkanowy) [![Travis](https://img.shields.io/travis/com/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://travis-ci.com/wulkanowy/wulkanowy)
[![Codecov](https://img.shields.io/codecov/c/github/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://codecov.io/gh/wulkanowy/wulkanowy) [![Codecov](https://img.shields.io/codecov/c/github/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://codecov.io/gh/wulkanowy/wulkanowy)
[![Discord](https://img.shields.io/discord/390889354199040011.svg?style=flat-square)](https://discord.gg/vccAQBr) [![Discord](https://img.shields.io/discord/390889354199040011.svg?style=flat-square)](https://discord.gg/vccAQBr)
[![F-Droid](https://img.shields.io/f-droid/v/io.github.wulkanowy.svg)](https://f-droid.org/packages/io.github.wulkanowy/) [![F-Droid](https://img.shields.io/f-droid/v/io.github.wulkanowy.svg?style=flat-square)](https://f-droid.org/packages/io.github.wulkanowy/)
[![Last release](https://img.shields.io/github/release/wulkanowy/wulkanowy.svg?logo=github)](https://github.com/wulkanowy/wulkanowy/releases) [![Last release](https://img.shields.io/github/release/wulkanowy/wulkanowy.svg?logo=github&style=flat-square)](https://github.com/wulkanowy/wulkanowy/releases)
Nieoficjalny klient dziennika VULCAN UONET+ dla ucznia i rodzica Nieoficjalny klient dziennika VULCAN UONET+ dla ucznia i rodzica
@ -47,7 +47,7 @@ Możesz także pobrać [wersję rozwojową](https://wulkanowy.github.io/#downloa
## Zbudowana za pomocą ## Zbudowana za pomocą
* [Wulkanowy API](https://github.com/wulkanowy/api) * [Wulkanowy SDK](https://github.com/wulkanowy/SDK)
* [RxJava 2](https://github.com/ReactiveX/RxJava) * [RxJava 2](https://github.com/ReactiveX/RxJava)
* [Dagger 2](https://github.com/google/dagger) * [Dagger 2](https://github.com/google/dagger)
* [Room](https://developer.android.com/topic/libraries/architecture/room) * [Room](https://developer.android.com/topic/libraries/architecture/room)

View File

@ -9,16 +9,16 @@ apply from: 'sonarqube.gradle'
apply from: 'hooks.gradle' apply from: 'hooks.gradle'
android { android {
compileSdkVersion 28 compileSdkVersion 29
buildToolsVersion '28.0.3' buildToolsVersion '29.0.2'
defaultConfig { defaultConfig {
applicationId "io.github.wulkanowy" applicationId "io.github.wulkanowy"
testApplicationId "io.github.tests.wulkanowy" testApplicationId "io.github.tests.wulkanowy"
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 28 targetSdkVersion 29
versionCode 44 versionCode 49
versionName "0.10.1" versionName "0.14.0"
multiDexEnabled true multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
@ -28,8 +28,10 @@ android {
] ]
javaCompileOptions { javaCompileOptions {
annotationProcessorOptions { annotationProcessorOptions {
arguments = ["room.schemaLocation": "$projectDir/schemas".toString(), arguments = [
"room.incremental" : "true"] "room.schemaLocation": "$projectDir/schemas".toString(),
"room.incremental" : "true"
]
} }
} }
} }
@ -61,7 +63,6 @@ android {
versionNameSuffix "-dev" versionNameSuffix "-dev"
testCoverageEnabled = true testCoverageEnabled = true
ext.enableCrashlytics = project.hasProperty("enableCrashlytics") ext.enableCrashlytics = project.hasProperty("enableCrashlytics")
multiDexKeepProguard file('proguard-multidex-rules.pro')
} }
} }
@ -109,38 +110,36 @@ play {
} }
ext { ext {
work_manager = "2.2.0" work_manager = "2.3.0-beta02"
room = "2.2.0-beta01" room = "2.2.3"
dagger = "2.24" dagger = "2.25.3"
chucker = "2.0.4" chucker = "2.0.4"
mockk = "1.9.2" mockk = "1.9.2"
mockito_core = "3.0.6"
} }
configurations.all { configurations.all {
resolutionStrategy.force "androidx.constraintlayout:constraintlayout:1.1.3" resolutionStrategy.force "androidx.constraintlayout:constraintlayout:1.1.3"
resolutionStrategy.force "com.google.android.material:material:1.1.0-alpha07"
} }
dependencies { dependencies {
implementation "io.github.wulkanowy:api:0.10.1" implementation "io.github.wulkanowy:sdk:0.14.0"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation "androidx.core:core-ktx:1.1.0" implementation "androidx.core:core-ktx:1.2.0-rc01"
implementation "androidx.activity:activity-ktx:1.0.0" implementation "androidx.activity:activity-ktx:1.1.0-rc03"
implementation "androidx.appcompat:appcompat:1.1.0" implementation "androidx.appcompat:appcompat:1.1.0"
implementation "androidx.appcompat:appcompat-resources:1.1.0" implementation "androidx.appcompat:appcompat-resources:1.1.0"
implementation "androidx.fragment:fragment-ktx:1.1.0" implementation "androidx.fragment:fragment-ktx:1.2.0-rc04"
implementation "androidx.annotation:annotation:1.1.0" implementation "androidx.annotation:annotation:1.1.0"
implementation "androidx.multidex:multidex:2.0.1" implementation "androidx.multidex:multidex:2.0.1"
implementation "androidx.preference:preference-ktx:1.1.0" implementation "androidx.preference:preference-ktx:1.1.0"
implementation "androidx.recyclerview:recyclerview:1.1.0-beta03" implementation "androidx.recyclerview:recyclerview:1.1.0"
implementation "androidx.viewpager:viewpager:1.0.0" implementation "androidx.viewpager:viewpager:1.0.0"
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha03"
implementation "androidx.constraintlayout:constraintlayout:1.1.3" implementation "androidx.constraintlayout:constraintlayout:1.1.3"
implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0-beta01" implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"
implementation "com.google.android.material:material:1.1.0-alpha07" implementation "com.google.android.material:material:1.1.0-rc01"
implementation "com.github.wulkanowy:material-chips-input:2.0.1" implementation "com.github.wulkanowy:material-chips-input:2.0.1"
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0" implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
implementation "me.zhanghai.android.materialprogressbar:library:1.6.1" implementation "me.zhanghai.android.materialprogressbar:library:1.6.1"
@ -157,26 +156,28 @@ dependencies {
implementation "com.google.dagger:dagger-android-support:$dagger" implementation "com.google.dagger:dagger-android-support:$dagger"
kapt "com.google.dagger:dagger-compiler:$dagger" kapt "com.google.dagger:dagger-compiler:$dagger"
kapt "com.google.dagger:dagger-android-processor:$dagger" kapt "com.google.dagger:dagger-android-processor:$dagger"
implementation "com.squareup.inject:assisted-inject-annotations-dagger2:0.5.0" implementation "com.squareup.inject:assisted-inject-annotations-dagger2:0.5.2"
kapt "com.squareup.inject:assisted-inject-processor-dagger2:0.5.0" kapt "com.squareup.inject:assisted-inject-processor-dagger2:0.5.2"
implementation "eu.davidea:flexible-adapter:5.1.0" implementation "eu.davidea:flexible-adapter:5.1.0"
implementation "eu.davidea:flexible-adapter-ui:1.0.0" implementation "eu.davidea:flexible-adapter-ui:1.0.0"
implementation "com.aurelhubert:ahbottomnavigation:2.3.4" implementation "com.aurelhubert:ahbottomnavigation:2.3.4"
implementation "com.ncapdevi:frag-nav:3.3.0" implementation "com.ncapdevi:frag-nav:3.3.0"
implementation "com.github.YarikSOffice:lingver:1.1.0"
implementation "com.github.pwittchen:reactivenetwork-rx2:3.0.6" implementation "com.github.pwittchen:reactivenetwork-rx2:3.0.6"
implementation "io.reactivex.rxjava2:rxandroid:2.1.1" implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
implementation "io.reactivex.rxjava2:rxjava:2.2.12" implementation "io.reactivex.rxjava2:rxjava:2.2.16"
implementation "com.google.code.gson:gson:2.8.5" implementation "com.google.code.gson:gson:2.8.6"
implementation "com.jakewharton.threetenabp:threetenabp:1.2.1" implementation "com.jakewharton.threetenabp:threetenabp:1.2.1"
implementation "com.jakewharton.timber:timber:4.7.1" implementation "com.jakewharton.timber:timber:4.7.1"
implementation "at.favre.lib:slf4j-timber:1.0.1" implementation "at.favre.lib:slf4j-timber:1.0.1"
implementation "com.squareup.okhttp3:logging-interceptor:3.12.3" implementation "com.squareup.okhttp3:logging-interceptor:3.12.6"
implementation "com.mikepenz:aboutlibraries:7.0.3" implementation "com.mikepenz:aboutlibraries:7.0.4"
implementation 'com.wdullaer:materialdatetimepicker:4.2.3'
playImplementation "com.google.firebase:firebase-core:17.2.0" playImplementation "com.google.firebase:firebase-core:17.2.1"
playImplementation "com.crashlytics.sdk.android:crashlytics:2.10.1" playImplementation "com.crashlytics.sdk.android:crashlytics:2.10.1"
releaseImplementation "fr.o80.chucker:library-no-op:$chucker" releaseImplementation "fr.o80.chucker:library-no-op:$chucker"
@ -187,10 +188,7 @@ dependencies {
testImplementation "junit:junit:4.12" testImplementation "junit:junit:4.12"
testImplementation "io.mockk:mockk:$mockk" testImplementation "io.mockk:mockk:$mockk"
testImplementation "org.threeten:threetenbp:1.4.0" testImplementation "org.threeten:threetenbp:1.4.0"
testImplementation "org.mockito:mockito-core:$mockito_core" testImplementation "org.mockito:mockito-inline:3.2.4"
testImplementation("org.mockito:mockito-inline:3.0.6") {
exclude group: "org.mockito", module: "mockito-core"
}
androidTestImplementation "androidx.test:core:1.2.0" androidTestImplementation "androidx.test:core:1.2.0"
androidTestImplementation "androidx.test:runner:1.2.0" androidTestImplementation "androidx.test:runner:1.2.0"
@ -198,10 +196,7 @@ dependencies {
androidTestImplementation "io.mockk:mockk-android:$mockk" androidTestImplementation "io.mockk:mockk-android:$mockk"
androidTestImplementation "androidx.room:room-testing:$room" androidTestImplementation "androidx.room:room-testing:$room"
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version" androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
androidTestImplementation "org.mockito:mockito-core:$mockito_core" androidTestImplementation "org.mockito:mockito-android:3.2.4"
androidTestImplementation("org.mockito:mockito-android:3.0.6") {
exclude group: 'org.mockito', module: 'mockito-core'
}
} }
apply plugin: 'com.google.gms.google-services' apply plugin: 'com.google.gms.google-services'

View File

@ -1,3 +0,0 @@
-keep class android.support.test.internal** { *; }
-keep class org.junit.** { *; }
-keep public class io.github.wulkanowy** { *; }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,13 @@
package io.github.wulkanowy.data.db.migrations package io.github.wulkanowy.data.db.migrations
import androidx.preference.PreferenceManager
import androidx.room.Room import androidx.room.Room
import androidx.room.testing.MigrationTestHelper import androidx.room.testing.MigrationTestHelper
import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
import androidx.test.core.app.ApplicationProvider import androidx.test.core.app.ApplicationProvider
import androidx.test.platform.app.InstrumentationRegistry import androidx.test.platform.app.InstrumentationRegistry
import io.github.wulkanowy.data.db.AppDatabase import io.github.wulkanowy.data.db.AppDatabase
import io.github.wulkanowy.data.db.SharedPrefProvider
import org.junit.Rule import org.junit.Rule
abstract class AbstractMigrationTest { abstract class AbstractMigrationTest {
@ -22,11 +24,8 @@ abstract class AbstractMigrationTest {
fun getMigratedRoomDatabase(): AppDatabase { fun getMigratedRoomDatabase(): AppDatabase {
val database = Room.databaseBuilder(ApplicationProvider.getApplicationContext(), val database = Room.databaseBuilder(ApplicationProvider.getApplicationContext(),
AppDatabase::class.java, dbName) AppDatabase::class.java, dbName)
.addMigrations( .addMigrations(*AppDatabase.getMigrations(SharedPrefProvider(PreferenceManager
Migration12(), .getDefaultSharedPreferences(ApplicationProvider.getApplicationContext())))
Migration13(),
Migration14(),
Migration15()
) )
.build() .build()
// close the database and release any stream resources when the test finishes // close the database and release any stream resources when the test finishes

View File

@ -3,10 +3,14 @@ package io.github.wulkanowy.data.db.migrations
import android.content.ContentValues import android.content.ContentValues
import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteDatabase
import androidx.sqlite.db.SupportSQLiteDatabase import androidx.sqlite.db.SupportSQLiteDatabase
import io.github.wulkanowy.data.db.Converters
import io.github.wulkanowy.data.db.entities.Semester
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue
import org.junit.Test import org.junit.Test
import org.threeten.bp.LocalDate.now
import org.threeten.bp.LocalDate.of import org.threeten.bp.LocalDate.of
import kotlin.test.assertFalse
import kotlin.test.assertTrue import kotlin.test.assertTrue
class Migration13Test : AbstractMigrationTest() { class Migration13Test : AbstractMigrationTest() {
@ -97,11 +101,9 @@ class Migration13Test : AbstractMigrationTest() {
close() close()
} }
helper.runMigrationsAndValidate(dbName, 13, true, Migration13()) val db = helper.runMigrationsAndValidate(dbName, 13, true, Migration13())
val db = getMigratedRoomDatabase() val semesters1 = getSemesters(db, "SELECT * FROM Semesters WHERE student_id = 1 AND class_id = 5")
val semesters1 = db.semesterDao.loadAll(1, 5).blockingGet()
assertTrue { semesters1.single { it.isCurrent }.isCurrent } assertTrue { semesters1.single { it.isCurrent }.isCurrent }
semesters1[0].run { semesters1[0].run {
assertFalse(isCurrent) assertFalse(isCurrent)
@ -119,7 +121,7 @@ class Migration13Test : AbstractMigrationTest() {
assertEquals(2, diaryId) assertEquals(2, diaryId)
} }
db.semesterDao.loadAll(2, 5).blockingGet().let { getSemesters(db, "SELECT * FROM Semesters WHERE student_id = 2 AND class_id = 5").let {
assertTrue { it.single { it.isCurrent }.isCurrent } assertTrue { it.single { it.isCurrent }.isCurrent }
assertEquals(1970, it[0].schoolYear) assertEquals(1970, it[0].schoolYear)
assertEquals(of(1970, 1, 1), it[0].end) assertEquals(of(1970, 1, 1), it[0].end)
@ -130,7 +132,7 @@ class Migration13Test : AbstractMigrationTest() {
assertTrue(it[3].isCurrent) assertTrue(it[3].isCurrent)
} }
db.semesterDao.loadAll(2, 5).blockingGet().let { getSemesters(db, "SELECT * FROM Semesters WHERE student_id = 2 AND class_id = 5").let {
assertTrue { it.single { it.isCurrent }.isCurrent } assertTrue { it.single { it.isCurrent }.isCurrent }
assertFalse(it[0].isCurrent) assertFalse(it[0].isCurrent)
assertFalse(it[1].isCurrent) assertFalse(it[1].isCurrent)
@ -139,6 +141,30 @@ class Migration13Test : AbstractMigrationTest() {
} }
} }
private fun getSemesters(db: SupportSQLiteDatabase, query: String): List<Semester> {
val semesters = mutableListOf<Semester>()
val cursor = db.query(query)
if (cursor.moveToFirst()) {
do {
semesters.add(Semester(
studentId = cursor.getInt(1),
diaryId = cursor.getInt(2),
diaryName = cursor.getString(3),
semesterId = cursor.getInt(4),
semesterName = cursor.getInt(5),
isCurrent = cursor.getInt(6) == 1,
classId = cursor.getInt(7),
unitId = cursor.getInt(8),
schoolYear = cursor.getInt(9),
start = Converters().timestampToDate(cursor.getLong(10))!!,
end = Converters().timestampToDate(cursor.getLong(11))!!
))
} while (cursor.moveToNext())
}
return semesters.toList()
}
private fun createStudent(db: SupportSQLiteDatabase, studentId: Int, schoolName: String = "", classId: Int = -1, schoolId: Int = 123) { private fun createStudent(db: SupportSQLiteDatabase, studentId: Int, schoolName: String = "", classId: Int = -1, schoolId: Int = 123) {
db.insert("Students", SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply { db.insert("Students", SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply {
put("endpoint", "https://fakelog.cf") put("endpoint", "https://fakelog.cf")

View File

@ -6,15 +6,18 @@ import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SdkSuppress import androidx.test.filters.SdkSuppress
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
import io.github.wulkanowy.api.Api import io.github.wulkanowy.data.SdkHelper
import io.github.wulkanowy.data.db.AppDatabase import io.github.wulkanowy.data.db.AppDatabase
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.repositories.TestInternetObservingStrategy import io.github.wulkanowy.data.repositories.TestInternetObservingStrategy
import io.github.wulkanowy.sdk.Sdk
import io.mockk.MockKAnnotations import io.mockk.MockKAnnotations
import io.mockk.every import io.mockk.every
import io.mockk.impl.annotations.MockK import io.mockk.impl.annotations.MockK
import io.mockk.impl.annotations.SpyK import io.mockk.impl.annotations.SpyK
import io.mockk.just
import io.mockk.runs
import io.reactivex.Single import io.reactivex.Single
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
@ -25,14 +28,13 @@ import org.threeten.bp.LocalDateTime
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertFalse import kotlin.test.assertFalse
import kotlin.test.assertTrue import kotlin.test.assertTrue
import io.github.wulkanowy.api.grades.Grade as GradeApi
@SdkSuppress(minSdkVersion = P) @SdkSuppress(minSdkVersion = P)
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
class GradeRepositoryTest { class GradeRepositoryTest {
@SpyK @MockK
private var mockApi = Api() private lateinit var mockSdk: Sdk
private val settings = InternetObservingSettings.builder() private val settings = InternetObservingSettings.builder()
.strategy(TestInternetObservingStrategy()) .strategy(TestInternetObservingStrategy())
@ -55,13 +57,14 @@ class GradeRepositoryTest {
MockKAnnotations.init(this) MockKAnnotations.init(this)
testDb = Room.inMemoryDatabaseBuilder(getApplicationContext(), AppDatabase::class.java).build() testDb = Room.inMemoryDatabaseBuilder(getApplicationContext(), AppDatabase::class.java).build()
gradeLocal = GradeLocal(testDb.gradeDao) gradeLocal = GradeLocal(testDb.gradeDao)
gradeRemote = GradeRemote(mockApi) gradeRemote = GradeRemote(mockSdk)
every { mockApi.diaryId } returns 1
every { studentMock.registrationDate } returns LocalDateTime.of(2019, 2, 27, 12, 0) every { studentMock.registrationDate } returns LocalDateTime.of(2019, 2, 27, 12, 0)
every { semesterMock.studentId } returns 1 every { semesterMock.studentId } returns 1
every { semesterMock.semesterId } returns 1
every { semesterMock.diaryId } returns 1 every { semesterMock.diaryId } returns 1
every { semesterMock.schoolYear } returns 2019
every { semesterMock.semesterId } returns 1
every { mockSdk.switchDiary(any(), any()) } returns mockSdk
} }
@After @After
@ -71,7 +74,7 @@ class GradeRepositoryTest {
@Test @Test
fun markOlderThanRegisterDateAsRead() { fun markOlderThanRegisterDateAsRead() {
every { mockApi.getGrades(1) } returns Single.just(listOf( every { mockSdk.getGrades(1) } returns Single.just(listOf(
createGradeApi(5, 4.0, of(2019, 2, 25), "Ocena pojawiła się"), createGradeApi(5, 4.0, of(2019, 2, 25), "Ocena pojawiła się"),
createGradeApi(5, 4.0, of(2019, 2, 26), "przed zalogowanie w aplikacji"), createGradeApi(5, 4.0, of(2019, 2, 26), "przed zalogowanie w aplikacji"),
createGradeApi(5, 4.0, of(2019, 2, 27), "Ocena z dnia logowania"), createGradeApi(5, 4.0, of(2019, 2, 27), "Ocena z dnia logowania"),
@ -95,7 +98,7 @@ class GradeRepositoryTest {
createGradeLocal(3, 5.0, of(2019, 2, 27), "Trzecia") createGradeLocal(3, 5.0, of(2019, 2, 27), "Trzecia")
)) ))
every { mockApi.getGrades(1) } returns Single.just(listOf( every { mockSdk.getGrades(1) } returns Single.just(listOf(
createGradeApi(5, 2.0, of(2019, 2, 25), "Ocena ma datę, jest inna, ale nie zostanie powiadomiona"), createGradeApi(5, 2.0, of(2019, 2, 25), "Ocena ma datę, jest inna, ale nie zostanie powiadomiona"),
createGradeApi(4, 3.0, of(2019, 2, 26), "starszą niż ostatnia lokalnie"), createGradeApi(4, 3.0, of(2019, 2, 26), "starszą niż ostatnia lokalnie"),
createGradeApi(3, 4.0, of(2019, 2, 27), "Ta jest z tego samego dnia co ostatnia lokalnie"), createGradeApi(3, 4.0, of(2019, 2, 27), "Ta jest z tego samego dnia co ostatnia lokalnie"),
@ -119,7 +122,7 @@ class GradeRepositoryTest {
createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena") createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
)) ))
every { mockApi.getGrades(1) } returns Single.just(listOf( every { mockSdk.getGrades(1) } returns Single.just(listOf(
createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"), createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
createGradeApi(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena") createGradeApi(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
)) ))
@ -137,7 +140,7 @@ class GradeRepositoryTest {
createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena") createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
)) ))
every { mockApi.getGrades(1) } returns Single.just(listOf( every { mockSdk.getGrades(1) } returns Single.just(listOf(
createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"), createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"), createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
createGradeApi(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena") createGradeApi(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
@ -153,7 +156,7 @@ class GradeRepositoryTest {
fun emptyLocal() { fun emptyLocal() {
gradeLocal.saveGrades(listOf()) gradeLocal.saveGrades(listOf())
every { mockApi.getGrades(1) } returns Single.just(listOf( every { mockSdk.getGrades(1) } returns Single.just(listOf(
createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"), createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"), createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
createGradeApi(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena") createGradeApi(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
@ -172,7 +175,7 @@ class GradeRepositoryTest {
createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena") createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
)) ))
every { mockApi.getGrades(1) } returns Single.just(listOf()) every { mockSdk.getGrades(1) } returns Single.just(listOf())
val grades = GradeRepository(settings, gradeLocal, gradeRemote) val grades = GradeRepository(settings, gradeLocal, gradeRemote)
.getGrades(studentMock, semesterMock, true).blockingGet() .getGrades(studentMock, semesterMock, true).blockingGet()

View File

@ -1,8 +1,7 @@
package io.github.wulkanowy.data.repositories.grade package io.github.wulkanowy.data.repositories.grade
import io.github.wulkanowy.api.toDate
import org.threeten.bp.LocalDate import org.threeten.bp.LocalDate
import io.github.wulkanowy.api.grades.Grade as GradeRemote import io.github.wulkanowy.sdk.pojo.Grade as GradeRemote
import io.github.wulkanowy.data.db.entities.Grade as GradeLocal import io.github.wulkanowy.data.db.entities.Grade as GradeLocal
fun createGradeLocal(value: Int, weight: Double, date: LocalDate, desc: String, semesterId: Int = 1): GradeLocal { fun createGradeLocal(value: Int, weight: Double, date: LocalDate, desc: String, semesterId: Int = 1): GradeLocal {
@ -18,17 +17,25 @@ fun createGradeLocal(value: Int, weight: Double, date: LocalDate, desc: String,
description = desc, description = desc,
entry = "", entry = "",
gradeSymbol = "", gradeSymbol = "",
value = value, value = value.toDouble(),
weight = "", weight = "",
weightValue = weight weightValue = weight
) )
} }
fun createGradeApi(value: Int, weight: Double, date: LocalDate, desc: String): GradeRemote { fun createGradeApi(value: Int, weight: Double, date: LocalDate, desc: String): GradeRemote {
return GradeRemote().apply { return GradeRemote(
this.value = value subject = "",
this.weightValue = weight color = "",
this.date = date.toDate() comment = "",
this.description = desc date = date,
} description = desc,
entry = "",
modifier = .0,
symbol = "",
teacher = "",
value = value.toDouble(),
weight = weight.toString(),
weightValue = weight
)
} }

View File

@ -4,6 +4,7 @@ import androidx.room.Room
import androidx.test.core.app.ApplicationProvider import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import io.github.wulkanowy.data.db.AppDatabase import io.github.wulkanowy.data.db.AppDatabase
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
import io.github.wulkanowy.data.db.entities.GradeStatistics import io.github.wulkanowy.data.db.entities.GradeStatistics
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import org.junit.After import org.junit.After
@ -24,7 +25,7 @@ class GradeStatisticsLocalTest {
fun createDb() { fun createDb() {
testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java) testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
.build() .build()
gradeStatisticsLocal = GradeStatisticsLocal(testDb.gradeStatistics) gradeStatisticsLocal = GradeStatisticsLocal(testDb.gradeStatistics, testDb.gradePointsStatistics)
} }
@After @After
@ -63,7 +64,52 @@ class GradeStatisticsLocalTest {
assertEquals(stats[0].subject, "Wszystkie") assertEquals(stats[0].subject, "Wszystkie")
} }
@Test
fun saveAndRead_points() {
gradeStatisticsLocal.saveGradesPointsStatistics(listOf(
getGradePointsStatistics("Matematyka", 2, 1),
getGradePointsStatistics("Chemia", 2, 1),
getGradePointsStatistics("Fizyka", 1, 2)
))
val stats = gradeStatisticsLocal.getGradesPointsStatistics(
Semester(2, 2, "", 2019, 1, 2, true, LocalDate.now(), LocalDate.now(), 1, 1),
"Matematyka"
).blockingGet()
with(stats) {
assertEquals(subject, "Matematyka")
assertEquals(others, 5.0)
assertEquals(student, 5.0)
}
}
@Test
fun saveAndRead_subjectEmpty() {
gradeStatisticsLocal.saveGradesPointsStatistics(listOf())
val stats = gradeStatisticsLocal.getGradesPointsStatistics(
Semester(2, 2, "", 2019, 1, 2, true, LocalDate.now(), LocalDate.now(), 1, 1),
"Matematyka"
).blockingGet()
assertEquals(null, stats)
}
@Test
fun saveAndRead_allEmpty() {
gradeStatisticsLocal.saveGradesPointsStatistics(listOf())
val stats = gradeStatisticsLocal.getGradesPointsStatistics(
Semester(2, 2, "", 2019, 1, 2, true, LocalDate.now(), LocalDate.now(), 1, 1),
"Wszystkie"
).blockingGet()
assertEquals(null, stats)
}
private fun getGradeStatistics(subject: String, studentId: Int, semesterId: Int): GradeStatistics { private fun getGradeStatistics(subject: String, studentId: Int, semesterId: Int): GradeStatistics {
return GradeStatistics(studentId, semesterId, subject, 5, 5, false) return GradeStatistics(studentId, semesterId, subject, 5, 5, false)
} }
private fun getGradePointsStatistics(subject: String, studentId: Int, semesterId: Int): GradePointsStatistics {
return GradePointsStatistics(studentId, semesterId, subject, 5.0, 5.0)
}
} }

View File

@ -42,7 +42,7 @@ class RecipientLocalTest {
)) ))
val recipients = recipientLocal.getRecipients( val recipients = recipientLocal.getRecipients(
Student("fakelog.cf", "AUTO", "", "", "", 1, "", "", "", "", 1, true, LocalDateTime.now()), Student("fakelog.cf", "AUTO", "", "", "", "", false, "", "", "", 1, 0, "", "", "", "", 1, true, LocalDateTime.now()),
2, 2,
ReportingUnit(1, 4, "", 0, "", emptyList()) ReportingUnit(1, 4, "", 0, "", emptyList())
).blockingGet() ).blockingGet()

View File

@ -39,7 +39,7 @@ class StudentLocalTest {
@Test @Test
fun saveAndReadTest() { fun saveAndReadTest() {
studentLocal.saveStudents(listOf(Student(email = "test", password = "test123", schoolSymbol = "23", endpoint = "fakelog.cf", loginType = "AUTO", isCurrent = true, studentName = "", schoolName = "", studentId = 0, classId = 1, symbol = "", registrationDate = now(), className = ""))) studentLocal.saveStudents(listOf(Student(email = "test", password = "test123", schoolSymbol = "23", scrapperBaseUrl = "fakelog.cf", loginType = "AUTO", isCurrent = true, studentName = "", schoolName = "", studentId = 0, classId = 1, symbol = "", registrationDate = now(), className = "", loginMode = "API", certificateKey = "", privateKey = "", mobileBaseUrl = "", userLoginId = 0, isParent = false)))
.blockingGet() .blockingGet()
val student = studentLocal.getCurrentStudent(true).blockingGet() val student = studentLocal.getCurrentStudent(true).blockingGet()

View File

@ -1,13 +1,11 @@
package io.github.wulkanowy.data.repositories.timetable package io.github.wulkanowy.data.repositories.timetable
import io.github.wulkanowy.api.toDate
import io.github.wulkanowy.utils.toDate
import org.threeten.bp.LocalDateTime import org.threeten.bp.LocalDateTime
import org.threeten.bp.LocalDateTime.now import org.threeten.bp.LocalDateTime.now
import io.github.wulkanowy.api.timetable.Timetable as TimetableRemote import io.github.wulkanowy.sdk.pojo.Timetable as TimetableRemote
import io.github.wulkanowy.data.db.entities.Timetable as TimetableLocal import io.github.wulkanowy.data.db.entities.Timetable as TimetableLocal
fun createTimetableLocal(number: Int, start: LocalDateTime, room: String = "", subject: String = "", teacher: String = "", changes: Boolean = false): TimetableLocal { fun createTimetableLocal(start: LocalDateTime, number: Int, room: String = "", subject: String = "", teacher: String = "", changes: Boolean = false): TimetableLocal {
return TimetableLocal( return TimetableLocal(
studentId = 1, studentId = 1,
diaryId = 2, diaryId = 2,
@ -28,18 +26,22 @@ fun createTimetableLocal(number: Int, start: LocalDateTime, room: String = "", s
) )
} }
fun createTimetableRemote(number: Int, start: LocalDateTime, room: String, subject: String = "", teacher: String = "", changes: Boolean = false): TimetableRemote { fun createTimetableRemote(start: LocalDateTime, number: Int = 1, room: String = "", subject: String = "", teacher: String = "", changes: Boolean = false): TimetableRemote {
return TimetableRemote( return TimetableRemote(
number = number, number = number,
start = start.toDate(), start = start,
end = start.plusMinutes(45).toDate(), end = start.plusMinutes(45),
date = start.toLocalDate().toDate(), date = start.toLocalDate(),
subject = subject, subject = subject,
group = "", group = "",
room = room, room = room,
teacher = teacher, teacher = teacher,
info = "", info = "",
changes = changes, changes = changes,
canceled = false canceled = false,
roomOld = "",
subjectOld = "",
teacherOld = "",
studentPlan = true
) )
} }

View File

@ -35,9 +35,9 @@ class TimetableLocalTest {
@Test @Test
fun saveAndReadTest() { fun saveAndReadTest() {
timetableDb.saveTimetable(listOf( timetableDb.saveTimetable(listOf(
createTimetableLocal(1, of(2018, 9, 10, 0, 0, 0)), createTimetableLocal(of(2018, 9, 10, 0, 0, 0), 1),
createTimetableLocal(1, of(2018, 9, 14, 0, 0, 0)), createTimetableLocal(of(2018, 9, 14, 0, 0, 0), 1),
createTimetableLocal(1, of(2018, 9, 17, 0, 0, 0)) createTimetableLocal(of(2018, 9, 17, 0, 0, 0), 1)
)) ))
val exams = timetableDb.getTimetable( val exams = timetableDb.getTimetable(

View File

@ -6,14 +6,13 @@ import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SdkSuppress import androidx.test.filters.SdkSuppress
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.AppDatabase import io.github.wulkanowy.data.db.AppDatabase
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.repositories.TestInternetObservingStrategy import io.github.wulkanowy.data.repositories.TestInternetObservingStrategy
import io.github.wulkanowy.sdk.Sdk
import io.mockk.MockKAnnotations import io.mockk.MockKAnnotations
import io.mockk.every import io.mockk.every
import io.mockk.impl.annotations.MockK import io.mockk.impl.annotations.MockK
import io.mockk.impl.annotations.SpyK
import io.reactivex.Single import io.reactivex.Single
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
@ -27,8 +26,8 @@ import kotlin.test.assertEquals
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
class TimetableRepositoryTest { class TimetableRepositoryTest {
@SpyK @MockK
private var mockApi = Api() private lateinit var mockSdk: Sdk
private val settings = InternetObservingSettings.builder() private val settings = InternetObservingSettings.builder()
.strategy(TestInternetObservingStrategy()) .strategy(TestInternetObservingStrategy())
@ -48,10 +47,13 @@ class TimetableRepositoryTest {
MockKAnnotations.init(this) MockKAnnotations.init(this)
testDb = Room.inMemoryDatabaseBuilder(getApplicationContext(), AppDatabase::class.java).build() testDb = Room.inMemoryDatabaseBuilder(getApplicationContext(), AppDatabase::class.java).build()
timetableLocal = TimetableLocal(testDb.timetableDao) timetableLocal = TimetableLocal(testDb.timetableDao)
timetableRemote = TimetableRemote(mockApi) timetableRemote = TimetableRemote(mockSdk)
every { semesterMock.studentId } returns 1 every { semesterMock.studentId } returns 1
every { semesterMock.diaryId } returns 2 every { semesterMock.diaryId } returns 2
every { semesterMock.schoolYear } returns 2019
every { semesterMock.semesterId } returns 1
every { mockSdk.switchDiary(any(), any()) } returns mockSdk
} }
@After @After
@ -62,17 +64,17 @@ class TimetableRepositoryTest {
@Test @Test
fun copyRoomToCompletedFromPrevious() { fun copyRoomToCompletedFromPrevious() {
timetableLocal.saveTimetable(listOf( timetableLocal.saveTimetable(listOf(
createTimetableLocal(1, of(2019, 3, 5, 8, 0), "123", "Przyroda"), createTimetableLocal(of(2019, 3, 5, 8, 0), 1, "123", "Przyroda"),
createTimetableLocal(2, of(2019, 3, 5, 8, 50), "321", "Religia"), createTimetableLocal(of(2019, 3, 5, 8, 50), 2, "321", "Religia"),
createTimetableLocal(3, of(2019, 3, 5, 9, 40), "213", "W-F"), createTimetableLocal(of(2019, 3, 5, 9, 40), 3, "213", "W-F"),
createTimetableLocal(4, of(2019, 3, 5, 10, 30), "213", "W-F", "Jan Kowalski") createTimetableLocal(of(2019, 3, 5, 10, 30),3, "213", "W-F", "Jan Kowalski")
)) ))
every { mockApi.getTimetable(any(), any()) } returns Single.just(listOf( every { mockSdk.getTimetable(any(), any()) } returns Single.just(listOf(
createTimetableRemote(1, of(2019, 3, 5, 8, 0), "", "Przyroda"), createTimetableRemote(of(2019, 3, 5, 8, 0), 1, "", "Przyroda"),
createTimetableRemote(2, of(2019, 3, 5, 8, 50), "", "Religia"), createTimetableRemote(of(2019, 3, 5, 8, 50), 2, "", "Religia"),
createTimetableRemote(3, of(2019, 3, 5, 9, 40), "", "W-F"), createTimetableRemote(of(2019, 3, 5, 9, 40), 3, "", "W-F"),
createTimetableRemote(4, of(2019, 3, 5, 10, 30), "", "W-F") createTimetableRemote(of(2019, 3, 5, 10, 30), 4, "", "W-F")
)) ))
val lessons = TimetableRepository(settings, timetableLocal, timetableRemote) val lessons = TimetableRepository(settings, timetableLocal, timetableRemote)
@ -88,27 +90,58 @@ class TimetableRepositoryTest {
@Test @Test
fun copyTeacherToCompletedFromPrevious() { fun copyTeacherToCompletedFromPrevious() {
timetableLocal.saveTimetable(listOf( timetableLocal.saveTimetable(listOf(
createTimetableLocal(1, of(2019, 3, 5, 8, 0), "123", "Przyroda", "Jan Garnkiewicz", false), createTimetableLocal(of(2019, 12, 23, 8, 0), 1, "123", "Matematyka", "Paweł Poniedziałkowski", false),
createTimetableLocal(2, of(2019, 3, 5, 8, 50), "321", "Religia", "Paweł Jumper", false), createTimetableLocal(of(2019, 12, 23, 8, 50), 2, "124", "Matematyka", "Paweł Poniedziałkowski", false),
createTimetableLocal(3, of(2019, 3, 5, 9, 40), "213", "W-F", "", true), createTimetableLocal(of(2019, 12, 23, 9, 40), 3, "125", "Język polski", "Joanna Wtorkowska", true),
createTimetableLocal(4, of(2019, 3, 5, 10, 30), "213", "W-F", "", false) createTimetableLocal(of(2019, 12, 23, 10, 40), 4, "126", "Język polski", "Joanna Wtorkowska", true),
createTimetableLocal(of(2019, 12, 24, 8, 0), 1, "123", "Język polski", "Joanna Wtorkowska", false),
createTimetableLocal(of(2019, 12, 24, 8, 50), 2, "124", "Język polski", "Joanna Wtorkowska", false),
createTimetableLocal(of(2019, 12, 24, 9, 40), 3, "125", "Język polski", "Joanna Środowska", true),
createTimetableLocal(of(2019, 12, 24, 10, 40), 4, "126", "Język polski", "Joanna Środowska", true),
createTimetableLocal(of(2019, 12, 25, 8, 0), 1, "123", "Matematyka", "", false),
createTimetableLocal(of(2019, 12, 25, 8, 50), 2, "124", "Matematyka", "", false),
createTimetableLocal(of(2019, 12, 25, 9, 40), 3, "125", "Matematyka", "", true),
createTimetableLocal(of(2019, 12, 25, 10, 40), 4, "126", "Matematyka", "", true)
)) ))
every { mockApi.getTimetable(any(), any()) } returns Single.just(listOf( every { mockSdk.getTimetable(any(), any()) } returns Single.just(listOf(
createTimetableRemote(1, of(2019, 3, 5, 8, 0), "", "Przyroda", "", true), // should override local createTimetableRemote(of(2019, 12, 23, 8, 0), 1, "123", "Matematyka", "Paweł Poniedziałkowski", false),
createTimetableRemote(2, of(2019, 3, 5, 8, 50), "", "Religia", "", false), createTimetableRemote(of(2019, 12, 23, 8, 50), 2, "124", "Matematyka", "Jakub Wtorkowski", true),
createTimetableRemote(3, of(2019, 3, 5, 9, 40), "", "W-F", "Jan Garnkiewicz", false), createTimetableRemote(of(2019, 12, 23, 9, 40), 3, "125", "Język polski", "Joanna Poniedziałkowska", false),
createTimetableRemote(4, of(2019, 3, 5, 10, 30), "", "W-F", "Paweł Jumper", false) createTimetableRemote(of(2019, 12, 23, 10, 40), 4, "126", "Język polski", "Joanna Wtorkowska", true),
createTimetableRemote(of(2019, 12, 24, 8, 0), 1, "123", "Język polski", "", false),
createTimetableRemote(of(2019, 12, 24, 8, 50), 2, "124", "Język polski", "", true),
createTimetableRemote(of(2019, 12, 24, 9, 40), 3, "125", "Język polski", "", false),
createTimetableRemote(of(2019, 12, 24, 10, 40), 4, "126", "Język polski", "", true),
createTimetableRemote(of(2019, 12, 25, 8, 0), 1, "123", "Matematyka", "Paweł Środowski", false),
createTimetableRemote(of(2019, 12, 25, 8, 50), 2, "124", "Matematyka", "Paweł Czwartkowski", true),
createTimetableRemote(of(2019, 12, 25, 9, 40), 3, "125", "Matematyka", "Paweł Środowski", false),
createTimetableRemote(of(2019, 12, 25, 10, 40), 4, "126", "Matematyka", "Paweł Czwartkowski", true)
)) ))
val lessons = TimetableRepository(settings, timetableLocal, timetableRemote) val lessons = TimetableRepository(settings, timetableLocal, timetableRemote)
.getTimetable(semesterMock, LocalDate.of(2019, 3, 5), LocalDate.of(2019, 3, 5), true) .getTimetable(semesterMock, LocalDate.of(2019, 12, 23), LocalDate.of(2019, 12, 25), true)
.blockingGet() .blockingGet()
assertEquals(4, lessons.size) assertEquals(12, lessons.size)
assertEquals("", lessons[0].teacher)
assertEquals("Paweł Jumper", lessons[1].teacher) assertEquals("Paweł Poniedziałkowski", lessons[0].teacher)
assertEquals("Jan Garnkiewicz", lessons[2].teacher) assertEquals("Jakub Wtorkowski", lessons[1].teacher)
assertEquals("Paweł Jumper", lessons[3].teacher) assertEquals("Joanna Poniedziałkowska", lessons[2].teacher)
assertEquals("Joanna Wtorkowska", lessons[3].teacher)
assertEquals("Joanna Wtorkowska", lessons[4].teacher)
assertEquals("", lessons[5].teacher)
assertEquals("", lessons[6].teacher)
assertEquals("", lessons[7].teacher)
assertEquals("Paweł Środowski", lessons[8].teacher)
assertEquals("Paweł Czwartkowski", lessons[9].teacher)
assertEquals("Paweł Środowski", lessons[10].teacher)
assertEquals("Paweł Czwartkowski", lessons[11].teacher)
} }
} }

View File

@ -1,3 +0,0 @@
<resources>
<string name="app_name">Wulkanowy DEV</string>
</resources>

View File

@ -6,6 +6,7 @@ import android.util.Log.VERBOSE
import androidx.multidex.MultiDex import androidx.multidex.MultiDex
import androidx.work.Configuration import androidx.work.Configuration
import com.jakewharton.threetenabp.AndroidThreeTen import com.jakewharton.threetenabp.AndroidThreeTen
import com.yariksoffice.lingver.Lingver
import dagger.android.AndroidInjector import dagger.android.AndroidInjector
import dagger.android.support.DaggerApplication import dagger.android.support.DaggerApplication
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
@ -44,6 +45,7 @@ class WulkanowyApp : DaggerApplication(), Configuration.Provider {
super.onCreate() super.onCreate()
AndroidThreeTen.init(this) AndroidThreeTen.init(this)
RxJavaPlugins.setErrorHandler(::onError) RxJavaPlugins.setErrorHandler(::onError)
Lingver.init(this)
themeManager.applyDefaultTheme() themeManager.applyDefaultTheme()
initLogging() initLogging()

View File

@ -1,35 +0,0 @@
package io.github.wulkanowy.data
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.entities.Student
import java.net.URL
import javax.inject.Inject
class ApiHelper @Inject constructor(private val api: Api) {
fun initApi(student: Student) {
api.apply {
email = student.email
password = student.password
symbol = student.symbol
schoolSymbol = student.schoolSymbol
studentId = student.studentId
classId = student.classId
host = URL(student.endpoint).run { host + ":$port".removeSuffix(":-1") }
ssl = student.endpoint.startsWith("https")
loginType = Api.LoginType.valueOf(student.loginType)
useNewStudent = true
}
}
fun initApi(email: String, password: String, symbol: String, endpoint: String) {
api.apply {
this.email = email
this.password = password
this.symbol = symbol
host = URL(endpoint).run { host + ":$port".removeSuffix(":-1") }
ssl = endpoint.startsWith("https")
useNewStudent = true
}
}
}

View File

@ -11,12 +11,10 @@ import com.readystatesoftware.chuck.api.ChuckInterceptor
import com.readystatesoftware.chuck.api.RetentionManager import com.readystatesoftware.chuck.api.RetentionManager
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.AppDatabase import io.github.wulkanowy.data.db.AppDatabase
import io.github.wulkanowy.data.db.SharedPrefProvider
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
import okhttp3.logging.HttpLoggingInterceptor import io.github.wulkanowy.sdk.Sdk
import okhttp3.logging.HttpLoggingInterceptor.Level.BASIC
import okhttp3.logging.HttpLoggingInterceptor.Level.NONE
import timber.log.Timber import timber.log.Timber
import javax.inject.Singleton import javax.inject.Singleton
@ -33,15 +31,14 @@ internal class RepositoryModule {
@Singleton @Singleton
@Provides @Provides
fun provideApi(chuckCollector: ChuckCollector, context: Context): Api { fun provideSdk(chuckCollector: ChuckCollector, context: Context): Sdk {
return Api().apply { return Sdk().apply {
logLevel = NONE
androidVersion = android.os.Build.VERSION.RELEASE androidVersion = android.os.Build.VERSION.RELEASE
buildTag = android.os.Build.MODEL buildTag = android.os.Build.MODEL
setInterceptor(HttpLoggingInterceptor(HttpLoggingInterceptor.Logger { Timber.d(it) }).setLevel(BASIC)) setSimpleHttpLogger { Timber.d(it) }
// for debug only // for debug only
setInterceptor(ChuckInterceptor(context, chuckCollector).maxContentLength(250000L), true, 0) addInterceptor(ChuckInterceptor(context, chuckCollector).maxContentLength(250000L), true)
} }
} }
@ -55,7 +52,7 @@ internal class RepositoryModule {
@Singleton @Singleton
@Provides @Provides
fun provideDatabase(context: Context) = AppDatabase.newInstance(context) fun provideDatabase(context: Context, sharedPrefProvider: SharedPrefProvider) = AppDatabase.newInstance(context, sharedPrefProvider)
@Singleton @Singleton
@Provides @Provides
@ -85,6 +82,10 @@ internal class RepositoryModule {
@Provides @Provides
fun provideGradeStatisticsDao(database: AppDatabase) = database.gradeStatistics fun provideGradeStatisticsDao(database: AppDatabase) = database.gradeStatistics
@Singleton
@Provides
fun provideGradePointsStatisticsDao(database: AppDatabase) = database.gradePointsStatistics
@Singleton @Singleton
@Provides @Provides
fun provideMessagesDao(database: AppDatabase) = database.messagesDao fun provideMessagesDao(database: AppDatabase) = database.messagesDao
@ -136,4 +137,12 @@ internal class RepositoryModule {
@Singleton @Singleton
@Provides @Provides
fun provideMobileDevicesDao(database: AppDatabase) = database.mobileDeviceDao fun provideMobileDevicesDao(database: AppDatabase) = database.mobileDeviceDao
@Singleton
@Provides
fun provideTeacherDao(database: AppDatabase) = database.teacherDao
@Singleton
@Provides
fun provideSchoolInfoDao(database: AppDatabase) = database.schoolDao
} }

View File

@ -0,0 +1,30 @@
package io.github.wulkanowy.data
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.sdk.Sdk
import javax.inject.Inject
class SdkHelper @Inject constructor(private val sdk: Sdk) {
fun init(student: Student) {
sdk.apply {
email = student.email
password = student.password
symbol = student.symbol
schoolSymbol = student.schoolSymbol
studentId = student.studentId
classId = student.classId
if (Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) {
scrapperBaseUrl = student.scrapperBaseUrl
loginType = Sdk.ScrapperLoginType.valueOf(student.loginType)
}
loginId = student.userLoginId
mode = Sdk.Mode.valueOf(student.loginMode)
mobileBaseUrl = student.mobileBaseUrl
certKey = student.certificateKey
privateKey = student.privateKey
}
}
}

View File

@ -6,11 +6,13 @@ import androidx.room.Room
import androidx.room.RoomDatabase import androidx.room.RoomDatabase
import androidx.room.RoomDatabase.JournalMode.TRUNCATE import androidx.room.RoomDatabase.JournalMode.TRUNCATE
import androidx.room.TypeConverters import androidx.room.TypeConverters
import androidx.room.migration.Migration
import io.github.wulkanowy.data.db.dao.AttendanceDao import io.github.wulkanowy.data.db.dao.AttendanceDao
import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao
import io.github.wulkanowy.data.db.dao.CompletedLessonsDao import io.github.wulkanowy.data.db.dao.CompletedLessonsDao
import io.github.wulkanowy.data.db.dao.ExamDao import io.github.wulkanowy.data.db.dao.ExamDao
import io.github.wulkanowy.data.db.dao.GradeDao import io.github.wulkanowy.data.db.dao.GradeDao
import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao
import io.github.wulkanowy.data.db.dao.GradeStatisticsDao import io.github.wulkanowy.data.db.dao.GradeStatisticsDao
import io.github.wulkanowy.data.db.dao.GradeSummaryDao import io.github.wulkanowy.data.db.dao.GradeSummaryDao
import io.github.wulkanowy.data.db.dao.HomeworkDao import io.github.wulkanowy.data.db.dao.HomeworkDao
@ -20,15 +22,18 @@ import io.github.wulkanowy.data.db.dao.MobileDeviceDao
import io.github.wulkanowy.data.db.dao.NoteDao import io.github.wulkanowy.data.db.dao.NoteDao
import io.github.wulkanowy.data.db.dao.RecipientDao import io.github.wulkanowy.data.db.dao.RecipientDao
import io.github.wulkanowy.data.db.dao.ReportingUnitDao import io.github.wulkanowy.data.db.dao.ReportingUnitDao
import io.github.wulkanowy.data.db.dao.SchoolDao
import io.github.wulkanowy.data.db.dao.SemesterDao import io.github.wulkanowy.data.db.dao.SemesterDao
import io.github.wulkanowy.data.db.dao.StudentDao import io.github.wulkanowy.data.db.dao.StudentDao
import io.github.wulkanowy.data.db.dao.SubjectDao import io.github.wulkanowy.data.db.dao.SubjectDao
import io.github.wulkanowy.data.db.dao.TeacherDao
import io.github.wulkanowy.data.db.dao.TimetableDao import io.github.wulkanowy.data.db.dao.TimetableDao
import io.github.wulkanowy.data.db.entities.Attendance import io.github.wulkanowy.data.db.entities.Attendance
import io.github.wulkanowy.data.db.entities.AttendanceSummary import io.github.wulkanowy.data.db.entities.AttendanceSummary
import io.github.wulkanowy.data.db.entities.CompletedLesson import io.github.wulkanowy.data.db.entities.CompletedLesson
import io.github.wulkanowy.data.db.entities.Exam import io.github.wulkanowy.data.db.entities.Exam
import io.github.wulkanowy.data.db.entities.Grade import io.github.wulkanowy.data.db.entities.Grade
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
import io.github.wulkanowy.data.db.entities.GradeStatistics import io.github.wulkanowy.data.db.entities.GradeStatistics
import io.github.wulkanowy.data.db.entities.GradeSummary import io.github.wulkanowy.data.db.entities.GradeSummary
import io.github.wulkanowy.data.db.entities.Homework import io.github.wulkanowy.data.db.entities.Homework
@ -38,9 +43,11 @@ import io.github.wulkanowy.data.db.entities.MobileDevice
import io.github.wulkanowy.data.db.entities.Note import io.github.wulkanowy.data.db.entities.Note
import io.github.wulkanowy.data.db.entities.Recipient import io.github.wulkanowy.data.db.entities.Recipient
import io.github.wulkanowy.data.db.entities.ReportingUnit import io.github.wulkanowy.data.db.entities.ReportingUnit
import io.github.wulkanowy.data.db.entities.School
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.db.entities.Subject import io.github.wulkanowy.data.db.entities.Subject
import io.github.wulkanowy.data.db.entities.Teacher
import io.github.wulkanowy.data.db.entities.Timetable import io.github.wulkanowy.data.db.entities.Timetable
import io.github.wulkanowy.data.db.migrations.Migration10 import io.github.wulkanowy.data.db.migrations.Migration10
import io.github.wulkanowy.data.db.migrations.Migration11 import io.github.wulkanowy.data.db.migrations.Migration11
@ -48,6 +55,10 @@ import io.github.wulkanowy.data.db.migrations.Migration12
import io.github.wulkanowy.data.db.migrations.Migration13 import io.github.wulkanowy.data.db.migrations.Migration13
import io.github.wulkanowy.data.db.migrations.Migration14 import io.github.wulkanowy.data.db.migrations.Migration14
import io.github.wulkanowy.data.db.migrations.Migration15 import io.github.wulkanowy.data.db.migrations.Migration15
import io.github.wulkanowy.data.db.migrations.Migration16
import io.github.wulkanowy.data.db.migrations.Migration17
import io.github.wulkanowy.data.db.migrations.Migration18
import io.github.wulkanowy.data.db.migrations.Migration19
import io.github.wulkanowy.data.db.migrations.Migration2 import io.github.wulkanowy.data.db.migrations.Migration2
import io.github.wulkanowy.data.db.migrations.Migration3 import io.github.wulkanowy.data.db.migrations.Migration3
import io.github.wulkanowy.data.db.migrations.Migration4 import io.github.wulkanowy.data.db.migrations.Migration4
@ -70,6 +81,7 @@ import javax.inject.Singleton
Grade::class, Grade::class,
GradeSummary::class, GradeSummary::class,
GradeStatistics::class, GradeStatistics::class,
GradePointsStatistics::class,
Message::class, Message::class,
Note::class, Note::class,
Homework::class, Homework::class,
@ -78,7 +90,9 @@ import javax.inject.Singleton
CompletedLesson::class, CompletedLesson::class,
ReportingUnit::class, ReportingUnit::class,
Recipient::class, Recipient::class,
MobileDevice::class MobileDevice::class,
Teacher::class,
School::class
], ],
version = AppDatabase.VERSION_SCHEMA, version = AppDatabase.VERSION_SCHEMA,
exportSchema = true exportSchema = true
@ -87,29 +101,37 @@ import javax.inject.Singleton
abstract class AppDatabase : RoomDatabase() { abstract class AppDatabase : RoomDatabase() {
companion object { companion object {
const val VERSION_SCHEMA = 15 const val VERSION_SCHEMA = 19
fun newInstance(context: Context): AppDatabase { fun getMigrations(sharedPrefProvider: SharedPrefProvider): Array<Migration> {
return arrayOf(
Migration2(),
Migration3(),
Migration4(),
Migration5(),
Migration6(),
Migration7(),
Migration8(),
Migration9(),
Migration10(),
Migration11(),
Migration12(),
Migration13(),
Migration14(),
Migration15(),
Migration16(),
Migration17(),
Migration18(),
Migration19(sharedPrefProvider)
)
}
fun newInstance(context: Context, sharedPrefProvider: SharedPrefProvider): AppDatabase {
return Room.databaseBuilder(context, AppDatabase::class.java, "wulkanowy_database") return Room.databaseBuilder(context, AppDatabase::class.java, "wulkanowy_database")
.setJournalMode(TRUNCATE) .setJournalMode(TRUNCATE)
.fallbackToDestructiveMigrationFrom(VERSION_SCHEMA + 1) .fallbackToDestructiveMigrationFrom(VERSION_SCHEMA + 1)
.fallbackToDestructiveMigrationOnDowngrade() .fallbackToDestructiveMigrationOnDowngrade()
.addMigrations( .addMigrations(*getMigrations(sharedPrefProvider))
Migration2(),
Migration3(),
Migration4(),
Migration5(),
Migration6(),
Migration7(),
Migration8(),
Migration9(),
Migration10(),
Migration11(),
Migration12(),
Migration13(),
Migration14(),
Migration15()
)
.build() .build()
} }
} }
@ -132,6 +154,8 @@ abstract class AppDatabase : RoomDatabase() {
abstract val gradeStatistics: GradeStatisticsDao abstract val gradeStatistics: GradeStatisticsDao
abstract val gradePointsStatistics: GradePointsStatisticsDao
abstract val messagesDao: MessagesDao abstract val messagesDao: MessagesDao
abstract val noteDao: NoteDao abstract val noteDao: NoteDao
@ -149,4 +173,8 @@ abstract class AppDatabase : RoomDatabase() {
abstract val recipientDao: RecipientDao abstract val recipientDao: RecipientDao
abstract val mobileDeviceDao: MobileDeviceDao abstract val mobileDeviceDao: MobileDeviceDao
abstract val teacherDao: TeacherDao
abstract val schoolDao: SchoolDao
} }

View File

@ -8,12 +8,22 @@ import javax.inject.Singleton
@Singleton @Singleton
class SharedPrefProvider @Inject constructor(private val sharedPref: SharedPreferences) { class SharedPrefProvider @Inject constructor(private val sharedPref: SharedPreferences) {
companion object {
const val APP_VERSION_CODE_KEY = "app_version_code"
}
fun putLong(key: String, value: Long, sync: Boolean = false) { fun putLong(key: String, value: Long, sync: Boolean = false) {
sharedPref.edit(sync) { putLong(key, value) } sharedPref.edit(sync) { putLong(key, value) }
} }
fun getLong(key: String, defaultValue: Long) = sharedPref.getLong(key, defaultValue) fun getLong(key: String, defaultValue: Long) = sharedPref.getLong(key, defaultValue)
fun getString(key: String, defaultValue: String): String = sharedPref.getString(key, defaultValue) ?: defaultValue
fun putString(key: String, value: String, sync: Boolean = false) {
sharedPref.edit(sync) { putString(key, value) }
}
fun delete(key: String) { fun delete(key: String) {
sharedPref.edit().remove(key).apply() sharedPref.edit().remove(key).apply()
} }

View File

@ -1,8 +1,6 @@
package io.github.wulkanowy.data.db.dao package io.github.wulkanowy.data.db.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Attendance import io.github.wulkanowy.data.db.entities.Attendance
import io.reactivex.Maybe import io.reactivex.Maybe
@ -11,13 +9,7 @@ import javax.inject.Singleton
@Singleton @Singleton
@Dao @Dao
interface AttendanceDao { interface AttendanceDao : BaseDao<Attendance> {
@Insert
fun insertAll(exams: List<Attendance>): List<Long>
@Delete
fun deleteAll(exams: List<Attendance>)
@Query("SELECT * FROM Attendance WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end") @Query("SELECT * FROM Attendance WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe<List<Attendance>> fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe<List<Attendance>>

View File

@ -1,20 +1,12 @@
package io.github.wulkanowy.data.db.dao package io.github.wulkanowy.data.db.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import io.github.wulkanowy.data.db.entities.AttendanceSummary import io.github.wulkanowy.data.db.entities.AttendanceSummary
import io.reactivex.Maybe import io.reactivex.Maybe
@Dao @Dao
interface AttendanceSummaryDao { interface AttendanceSummaryDao : BaseDao<AttendanceSummary> {
@Insert
fun insertAll(exams: List<AttendanceSummary>): List<Long>
@Delete
fun deleteAll(exams: List<AttendanceSummary>)
@Query("SELECT * FROM AttendanceSummary WHERE diary_id = :diaryId AND student_id = :studentId AND subject_id = :subjectId") @Query("SELECT * FROM AttendanceSummary WHERE diary_id = :diaryId AND student_id = :studentId AND subject_id = :subjectId")
fun loadAll(diaryId: Int, studentId: Int, subjectId: Int): Maybe<List<AttendanceSummary>> fun loadAll(diaryId: Int, studentId: Int, subjectId: Int): Maybe<List<AttendanceSummary>>

View File

@ -0,0 +1,17 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Update
interface BaseDao<T> {
@Insert
fun insertAll(items: List<T>): List<Long>
@Update
fun updateAll(items: List<T>)
@Delete
fun deleteAll(items: List<T>)
}

View File

@ -1,8 +1,6 @@
package io.github.wulkanowy.data.db.dao package io.github.wulkanowy.data.db.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import io.github.wulkanowy.data.db.entities.CompletedLesson import io.github.wulkanowy.data.db.entities.CompletedLesson
import io.reactivex.Maybe import io.reactivex.Maybe
@ -11,13 +9,7 @@ import javax.inject.Singleton
@Singleton @Singleton
@Dao @Dao
interface CompletedLessonsDao { interface CompletedLessonsDao : BaseDao<CompletedLesson> {
@Insert
fun insertAll(exams: List<CompletedLesson>)
@Delete
fun deleteAll(exams: List<CompletedLesson>)
@Query("SELECT * FROM CompletedLesson WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end") @Query("SELECT * FROM CompletedLesson WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe<List<CompletedLesson>> fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe<List<CompletedLesson>>

View File

@ -1,8 +1,6 @@
package io.github.wulkanowy.data.db.dao package io.github.wulkanowy.data.db.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Exam import io.github.wulkanowy.data.db.entities.Exam
import io.reactivex.Maybe import io.reactivex.Maybe
@ -11,13 +9,7 @@ import javax.inject.Singleton
@Singleton @Singleton
@Dao @Dao
interface ExamDao { interface ExamDao : BaseDao<Exam> {
@Insert
fun insertAll(exams: List<Exam>): List<Long>
@Delete
fun deleteAll(exams: List<Exam>)
@Query("SELECT * FROM Exams WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end") @Query("SELECT * FROM Exams WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe<List<Exam>> fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe<List<Exam>>

View File

@ -1,26 +1,14 @@
package io.github.wulkanowy.data.db.dao package io.github.wulkanowy.data.db.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import androidx.room.Update
import io.github.wulkanowy.data.db.entities.Grade import io.github.wulkanowy.data.db.entities.Grade
import io.reactivex.Maybe import io.reactivex.Maybe
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
@Dao @Dao
interface GradeDao { interface GradeDao : BaseDao<Grade> {
@Insert
fun insertAll(grades: List<Grade>)
@Update
fun updateAll(grade: List<Grade>)
@Delete
fun deleteAll(grades: List<Grade>)
@Query("SELECT * FROM Grades WHERE semester_id = :semesterId AND student_id = :studentId") @Query("SELECT * FROM Grades WHERE semester_id = :semesterId AND student_id = :studentId")
fun loadAll(semesterId: Int, studentId: Int): Maybe<List<Grade>> fun loadAll(semesterId: Int, studentId: Int): Maybe<List<Grade>>

View File

@ -0,0 +1,18 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
import io.reactivex.Maybe
import javax.inject.Singleton
@Singleton
@Dao
interface GradePointsStatisticsDao : BaseDao<GradePointsStatistics> {
@Query("SELECT * FROM GradesPointsStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND subject = :subjectName")
fun loadSubject(semesterId: Int, studentId: Int, subjectName: String): Maybe<GradePointsStatistics>
@Query("SELECT * FROM GradesPointsStatistics WHERE student_id = :studentId AND semester_id = :semesterId")
fun loadAll(semesterId: Int, studentId: Int): Maybe<List<GradePointsStatistics>>
}

View File

@ -1,8 +1,6 @@
package io.github.wulkanowy.data.db.dao package io.github.wulkanowy.data.db.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import io.github.wulkanowy.data.db.entities.GradeStatistics import io.github.wulkanowy.data.db.entities.GradeStatistics
import io.reactivex.Maybe import io.reactivex.Maybe
@ -10,13 +8,7 @@ import javax.inject.Singleton
@Singleton @Singleton
@Dao @Dao
interface GradeStatisticsDao { interface GradeStatisticsDao : BaseDao<GradeStatistics> {
@Insert
fun insertAll(gradesStatistics: List<GradeStatistics>)
@Delete
fun deleteAll(gradesStatistics: List<GradeStatistics>)
@Query("SELECT * FROM GradesStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND subject = :subjectName AND is_semester = :isSemester") @Query("SELECT * FROM GradesStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND subject = :subjectName AND is_semester = :isSemester")
fun loadSubject(semesterId: Int, studentId: Int, subjectName: String, isSemester: Boolean): Maybe<List<GradeStatistics>> fun loadSubject(semesterId: Int, studentId: Int, subjectName: String, isSemester: Boolean): Maybe<List<GradeStatistics>>

View File

@ -1,8 +1,6 @@
package io.github.wulkanowy.data.db.dao package io.github.wulkanowy.data.db.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import io.github.wulkanowy.data.db.entities.GradeSummary import io.github.wulkanowy.data.db.entities.GradeSummary
import io.reactivex.Maybe import io.reactivex.Maybe
@ -10,13 +8,7 @@ import javax.inject.Singleton
@Singleton @Singleton
@Dao @Dao
interface GradeSummaryDao { interface GradeSummaryDao : BaseDao<GradeSummary> {
@Insert
fun insertAll(gradesSummary: List<GradeSummary>)
@Delete
fun deleteAll(gradesSummary: List<GradeSummary>)
@Query("SELECT * FROM GradesSummary WHERE student_id = :studentId AND semester_id = :semesterId") @Query("SELECT * FROM GradesSummary WHERE student_id = :studentId AND semester_id = :semesterId")
fun loadAll(semesterId: Int, studentId: Int): Maybe<List<GradeSummary>> fun loadAll(semesterId: Int, studentId: Int): Maybe<List<GradeSummary>>

View File

@ -1,8 +1,6 @@
package io.github.wulkanowy.data.db.dao package io.github.wulkanowy.data.db.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Homework import io.github.wulkanowy.data.db.entities.Homework
import io.reactivex.Maybe import io.reactivex.Maybe
@ -11,13 +9,7 @@ import javax.inject.Singleton
@Singleton @Singleton
@Dao @Dao
interface HomeworkDao { interface HomeworkDao : BaseDao<Homework> {
@Insert
fun insertAll(homework: List<Homework>)
@Delete
fun deleteAll(homework: List<Homework>)
@Query("SELECT * FROM Homework WHERE semester_id = :semesterId AND student_id = :studentId AND date >= :from AND date <= :end") @Query("SELECT * FROM Homework WHERE semester_id = :semesterId AND student_id = :studentId AND date >= :from AND date <= :end")
fun loadAll(semesterId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe<List<Homework>> fun loadAll(semesterId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe<List<Homework>>

View File

@ -1,10 +1,7 @@
package io.github.wulkanowy.data.db.dao package io.github.wulkanowy.data.db.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import androidx.room.Update
import io.github.wulkanowy.data.db.entities.LuckyNumber import io.github.wulkanowy.data.db.entities.LuckyNumber
import io.reactivex.Maybe import io.reactivex.Maybe
import org.threeten.bp.LocalDate import org.threeten.bp.LocalDate
@ -12,18 +9,8 @@ import javax.inject.Singleton
@Singleton @Singleton
@Dao @Dao
interface LuckyNumberDao { interface LuckyNumberDao : BaseDao<LuckyNumber> {
@Insert
fun insert(luckyNumber: LuckyNumber)
@Update
fun update(luckyNumber: LuckyNumber)
@Delete
fun delete(luckyNumber: LuckyNumber)
@Query("SELECT * FROM LuckyNumbers WHERE student_id = :studentId AND date = :date") @Query("SELECT * FROM LuckyNumbers WHERE student_id = :studentId AND date = :date")
fun load(studentId: Int, date: LocalDate): Maybe<LuckyNumber> fun load(studentId: Int, date: LocalDate): Maybe<LuckyNumber>
} }

View File

@ -1,24 +1,12 @@
package io.github.wulkanowy.data.db.dao package io.github.wulkanowy.data.db.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import androidx.room.Update
import io.github.wulkanowy.data.db.entities.Message import io.github.wulkanowy.data.db.entities.Message
import io.reactivex.Maybe import io.reactivex.Maybe
@Dao @Dao
interface MessagesDao { interface MessagesDao : BaseDao<Message> {
@Insert
fun insertAll(messages: List<Message>)
@Delete
fun deleteAll(messages: List<Message>)
@Update
fun updateAll(messages: List<Message>)
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND folder_id = :folder AND removed = 0 ORDER BY date DESC") @Query("SELECT * FROM Messages WHERE student_id = :studentId AND folder_id = :folder AND removed = 0 ORDER BY date DESC")
fun loadAll(studentId: Int, folder: Int): Maybe<List<Message>> fun loadAll(studentId: Int, folder: Int): Maybe<List<Message>>

View File

@ -1,20 +1,12 @@
package io.github.wulkanowy.data.db.dao package io.github.wulkanowy.data.db.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import io.github.wulkanowy.data.db.entities.MobileDevice import io.github.wulkanowy.data.db.entities.MobileDevice
import io.reactivex.Maybe import io.reactivex.Maybe
@Dao @Dao
interface MobileDeviceDao { interface MobileDeviceDao : BaseDao<MobileDevice> {
@Insert
fun insertAll(devices: List<MobileDevice>)
@Delete
fun deleteAll(devices: List<MobileDevice>)
@Query("SELECT * FROM MobileDevices WHERE student_id = :studentId ORDER BY date DESC") @Query("SELECT * FROM MobileDevices WHERE student_id = :studentId ORDER BY date DESC")
fun loadAll(studentId: Int): Maybe<List<MobileDevice>> fun loadAll(studentId: Int): Maybe<List<MobileDevice>>

View File

@ -1,28 +1,15 @@
package io.github.wulkanowy.data.db.dao package io.github.wulkanowy.data.db.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import androidx.room.Update
import io.github.wulkanowy.data.db.entities.Note import io.github.wulkanowy.data.db.entities.Note
import io.reactivex.Maybe import io.reactivex.Maybe
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
@Dao @Dao
interface NoteDao { interface NoteDao : BaseDao<Note> {
@Insert
fun insertAll(notes: List<Note>)
@Update
fun updateAll(notes: List<Note>)
@Delete
fun deleteAll(notes: List<Note>)
@Query("SELECT * FROM Notes WHERE student_id = :studentId") @Query("SELECT * FROM Notes WHERE student_id = :studentId")
fun loadAll(studentId: Int): Maybe<List<Note>> fun loadAll(studentId: Int): Maybe<List<Note>>
} }

View File

@ -1,8 +1,6 @@
package io.github.wulkanowy.data.db.dao package io.github.wulkanowy.data.db.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Recipient import io.github.wulkanowy.data.db.entities.Recipient
import io.reactivex.Maybe import io.reactivex.Maybe
@ -10,13 +8,7 @@ import javax.inject.Singleton
@Singleton @Singleton
@Dao @Dao
interface RecipientDao { interface RecipientDao : BaseDao<Recipient> {
@Insert
fun insertAll(messages: List<Recipient>)
@Delete
fun deleteAll(messages: List<Recipient>)
@Query("SELECT * FROM Recipients WHERE student_id = :studentId AND role = :role AND unit_id = :unitId") @Query("SELECT * FROM Recipients WHERE student_id = :studentId AND role = :role AND unit_id = :unitId")
fun load(studentId: Int, role: Int, unitId: Int): Maybe<List<Recipient>> fun load(studentId: Int, role: Int, unitId: Int): Maybe<List<Recipient>>

View File

@ -1,8 +1,6 @@
package io.github.wulkanowy.data.db.dao package io.github.wulkanowy.data.db.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import io.github.wulkanowy.data.db.entities.ReportingUnit import io.github.wulkanowy.data.db.entities.ReportingUnit
import io.reactivex.Maybe import io.reactivex.Maybe
@ -10,13 +8,7 @@ import javax.inject.Singleton
@Singleton @Singleton
@Dao @Dao
interface ReportingUnitDao { interface ReportingUnitDao : BaseDao<ReportingUnit> {
@Insert
fun insertAll(reportingUnits: List<ReportingUnit>)
@Delete
fun deleteAll(reportingUnits: List<ReportingUnit>)
@Query("SELECT * FROM ReportingUnits WHERE student_id = :studentId") @Query("SELECT * FROM ReportingUnits WHERE student_id = :studentId")
fun load(studentId: Int): Maybe<List<ReportingUnit>> fun load(studentId: Int): Maybe<List<ReportingUnit>>

View File

@ -0,0 +1,15 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.School
import io.reactivex.Maybe
import javax.inject.Singleton
@Singleton
@Dao
interface SchoolDao : BaseDao<School> {
@Query("SELECT * FROM School WHERE student_id = :studentId AND class_id = :classId")
fun load(studentId: Int, classId: Int): Maybe<School>
}

View File

@ -1,8 +1,6 @@
package io.github.wulkanowy.data.db.dao package io.github.wulkanowy.data.db.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.reactivex.Maybe import io.reactivex.Maybe
@ -10,13 +8,7 @@ import javax.inject.Singleton
@Singleton @Singleton
@Dao @Dao
interface SemesterDao { interface SemesterDao : BaseDao<Semester> {
@Insert
fun insertAll(semester: List<Semester>)
@Delete
fun deleteAll(semester: List<Semester>)
@Query("SELECT * FROM Semesters WHERE student_id = :studentId AND class_id = :classId") @Query("SELECT * FROM Semesters WHERE student_id = :studentId AND class_id = :classId")
fun loadAll(studentId: Int, classId: Int): Maybe<List<Semester>> fun loadAll(studentId: Int, classId: Int): Maybe<List<Semester>>

View File

@ -1,20 +1,12 @@
package io.github.wulkanowy.data.db.dao package io.github.wulkanowy.data.db.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Subject import io.github.wulkanowy.data.db.entities.Subject
import io.reactivex.Maybe import io.reactivex.Maybe
@Dao @Dao
interface SubjectDao { interface SubjectDao : BaseDao<Subject> {
@Insert
fun insertAll(subjects: List<Subject>): List<Long>
@Delete
fun deleteAll(subjects: List<Subject>)
@Query("SELECT * FROM Subjects WHERE diary_id = :diaryId AND student_id = :studentId") @Query("SELECT * FROM Subjects WHERE diary_id = :diaryId AND student_id = :studentId")
fun loadAll(diaryId: Int, studentId: Int): Maybe<List<Subject>> fun loadAll(diaryId: Int, studentId: Int): Maybe<List<Subject>>

View File

@ -0,0 +1,15 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Teacher
import io.reactivex.Maybe
import javax.inject.Singleton
@Singleton
@Dao
interface TeacherDao : BaseDao<Teacher> {
@Query("SELECT * FROM Teachers WHERE student_id = :studentId AND class_id = :classId")
fun loadAll(studentId: Int, classId: Int): Maybe<List<Teacher>>
}

View File

@ -1,8 +1,6 @@
package io.github.wulkanowy.data.db.dao package io.github.wulkanowy.data.db.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Timetable import io.github.wulkanowy.data.db.entities.Timetable
import io.reactivex.Maybe import io.reactivex.Maybe
@ -11,13 +9,7 @@ import javax.inject.Singleton
@Singleton @Singleton
@Dao @Dao
interface TimetableDao { interface TimetableDao : BaseDao<Timetable> {
@Insert
fun insertAll(exams: List<Timetable>): List<Long>
@Delete
fun deleteAll(exams: List<Timetable>)
@Query("SELECT * FROM Timetable WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end") @Query("SELECT * FROM Timetable WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe<List<Timetable>> fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe<List<Timetable>>

View File

@ -19,7 +19,7 @@ data class Grade(
val entry: String, val entry: String,
val value: Int, val value: Double,
val modifier: Double, val modifier: Double,

View File

@ -0,0 +1,24 @@
package io.github.wulkanowy.data.db.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "GradesPointsStatistics")
data class GradePointsStatistics(
@ColumnInfo(name = "student_id")
val studentId: Int,
@ColumnInfo(name = "semester_id")
val semesterId: Int,
val subject: String,
val others: Double,
val student: Double
) {
@PrimaryKey(autoGenerate = true)
var id: Long = 0
}

View File

@ -29,6 +29,8 @@ data class Message(
val subject: String, val subject: String,
var content: String,
val date: LocalDateTime, val date: LocalDateTime,
@ColumnInfo(name = "folder_id") @ColumnInfo(name = "folder_id")
@ -50,6 +52,4 @@ data class Message(
@ColumnInfo(name = "is_notified") @ColumnInfo(name = "is_notified")
var isNotified: Boolean = true var isNotified: Boolean = true
var content: String? = null
} }

View File

@ -0,0 +1,30 @@
package io.github.wulkanowy.data.db.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import java.io.Serializable
@Entity(tableName = "School")
data class School(
@ColumnInfo(name = "student_id")
val studentId: Int,
@ColumnInfo(name = "class_id")
val classId: Int,
val name: String,
val address: String,
val contact: String,
val headmaster: String,
val pedagogue: String
) : Serializable {
@PrimaryKey(autoGenerate = true)
var id: Long = 0
}

View File

@ -10,10 +10,27 @@ import java.io.Serializable
@Entity(tableName = "Students", indices = [Index(value = ["email", "symbol", "student_id", "school_id", "class_id"], unique = true)]) @Entity(tableName = "Students", indices = [Index(value = ["email", "symbol", "student_id", "school_id", "class_id"], unique = true)])
data class Student( data class Student(
val endpoint: String, @ColumnInfo(name = "scrapper_base_url")
val scrapperBaseUrl: String,
@ColumnInfo(name = "mobile_base_url")
val mobileBaseUrl: String,
@ColumnInfo(name = "login_type")
val loginType: String, val loginType: String,
@ColumnInfo(name = "login_mode")
val loginMode: String,
@ColumnInfo(name = "certificate_key")
val certificateKey: String,
@ColumnInfo(name = "private_key")
val privateKey: String,
@ColumnInfo(name = "is_parent")
val isParent: Boolean,
val email: String, val email: String,
var password: String, var password: String,
@ -23,6 +40,9 @@ data class Student(
@ColumnInfo(name = "student_id") @ColumnInfo(name = "student_id")
val studentId: Int, val studentId: Int,
@ColumnInfo(name = "user_login_id")
val userLoginId: Int,
@ColumnInfo(name = "student_name") @ColumnInfo(name = "student_name")
val studentName: String, val studentName: String,

View File

@ -0,0 +1,27 @@
package io.github.wulkanowy.data.db.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import java.io.Serializable
@Entity(tableName = "Teachers")
data class Teacher(
@ColumnInfo(name = "student_id")
val studentId: Int,
@ColumnInfo(name = "class_id")
val classId: Int,
val subject: String,
val name: String,
@ColumnInfo(name = "short_name")
val shortName: String
) : Serializable {
@PrimaryKey(autoGenerate = true)
var id: Long = 0
}

View File

@ -0,0 +1,20 @@
package io.github.wulkanowy.data.db.migrations
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
class Migration16 : Migration(15, 16) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("""
CREATE TABLE IF NOT EXISTS Teachers (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
student_id INTEGER NOT NULL,
class_id INTEGER NOT NULL,
subject TEXT NOT NULL,
name TEXT NOT NULL,
short_name TEXT NOT NULL
)
""")
}
}

View File

@ -0,0 +1,29 @@
package io.github.wulkanowy.data.db.migrations
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
class Migration17 : Migration(16, 17) {
override fun migrate(database: SupportSQLiteDatabase) {
createGradesPointsStatisticsTable(database)
truncateSemestersTable(database)
}
private fun createGradesPointsStatisticsTable(database: SupportSQLiteDatabase) {
database.execSQL("""
CREATE TABLE IF NOT EXISTS GradesPointsStatistics(
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
student_id INTEGER NOT NULL,
semester_id INTEGER NOT NULL,
subject TEXT NOT NULL,
others REAL NOT NULL,
student REAL NOT NULL
)
""")
}
private fun truncateSemestersTable(database: SupportSQLiteDatabase) {
database.execSQL("DELETE FROM Semesters")
}
}

View File

@ -0,0 +1,22 @@
package io.github.wulkanowy.data.db.migrations
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
class Migration18 : Migration(17, 18) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("""
CREATE TABLE IF NOT EXISTS School (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
student_id INTEGER NOT NULL,
class_id INTEGER NOT NULL,
name TEXT NOT NULL,
address TEXT NOT NULL,
contact TEXT NOT NULL,
headmaster TEXT NOT NULL,
pedagogue TEXT NOT NULL
)
""")
}
}

View File

@ -0,0 +1,119 @@
package io.github.wulkanowy.data.db.migrations
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import io.github.wulkanowy.data.db.SharedPrefProvider
class Migration19(private val sharedPrefProvider: SharedPrefProvider) : Migration(18, 19) {
override fun migrate(database: SupportSQLiteDatabase) {
migrateMessages(database)
migrateGrades(database)
migrateStudents(database)
migrateSharedPreferences()
}
private fun migrateMessages(database: SupportSQLiteDatabase) {
database.execSQL("DROP TABLE Messages")
database.execSQL("""
CREATE TABLE IF NOT EXISTS Messages (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
is_notified INTEGER NOT NULL,
student_id INTEGER NOT NULL,
real_id INTEGER NOT NULL,
message_id INTEGER NOT NULL,
sender_name TEXT NOT NULL,
sender_id INTEGER NOT NULL,
recipient_name TEXT NOT NULL,
subject TEXT NOT NULL,
content TEXT NOT NULL,
date INTEGER NOT NULL,
folder_id INTEGER NOT NULL,
unread INTEGER NOT NULL,
unread_by INTEGER NOT NULL,
read_by INTEGER NOT NULL,
removed INTEGER NOT NULL
)
""")
}
private fun migrateGrades(database: SupportSQLiteDatabase) {
database.execSQL("DROP TABLE Grades")
database.execSQL("""
CREATE TABLE IF NOT EXISTS Grades (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
is_read INTEGER NOT NULL,
is_notified INTEGER NOT NULL,
semester_id INTEGER NOT NULL,
student_id INTEGER NOT NULL,
subject TEXT NOT NULL,
entry TEXT NOT NULL,
value REAL NOT NULL,
modifier REAL NOT NULL,
comment TEXT NOT NULL,
color TEXT NOT NULL,
grade_symbol TEXT NOT NULL,
description TEXT NOT NULL,
weight TEXT NOT NULL,
weightValue REAL NOT NULL,
date INTEGER NOT NULL,
teacher TEXT NOT NULL
)
""")
}
private fun migrateStudents(database: SupportSQLiteDatabase) {
database.execSQL("""
CREATE TABLE IF NOT EXISTS Students_tmp (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
scrapper_base_url TEXT NOT NULL,
mobile_base_url TEXT NOT NULL,
is_parent INTEGER NOT NULL,
login_type TEXT NOT NULL,
login_mode TEXT NOT NULL,
certificate_key TEXT NOT NULL,
private_key TEXT NOT NULL,
email TEXT NOT NULL,
password TEXT NOT NULL,
symbol TEXT NOT NULL,
student_id INTEGER NOT NULL,
user_login_id INTEGER NOT NULL,
student_name TEXT NOT NULL,
school_id TEXT NOT NULL,
school_name TEXT NOT NULL,
class_name TEXT NOT NULL,
class_id INTEGER NOT NULL,
is_current INTEGER NOT NULL,
registration_date INTEGER NOT NULL
)
""")
database.execSQL("ALTER TABLE Students ADD COLUMN scrapperBaseUrl TEXT NOT NULL DEFAULT \"\";")
database.execSQL("ALTER TABLE Students ADD COLUMN apiBaseUrl TEXT NOT NULL DEFAULT \"\";")
database.execSQL("ALTER TABLE Students ADD COLUMN is_parent INT NOT NULL DEFAULT 0;")
database.execSQL("ALTER TABLE Students ADD COLUMN loginMode TEXT NOT NULL DEFAULT \"\";")
database.execSQL("ALTER TABLE Students ADD COLUMN certificateKey TEXT NOT NULL DEFAULT \"\";")
database.execSQL("ALTER TABLE Students ADD COLUMN privateKey TEXT NOT NULL DEFAULT \"\";")
database.execSQL("ALTER TABLE Students ADD COLUMN user_login_id INTEGER NOT NULL DEFAULT 0;")
database.execSQL("""
INSERT INTO Students_tmp(
id, scrapper_base_url, mobile_base_url, is_parent, login_type, login_mode, certificate_key, private_key, email, password, symbol, student_id, user_login_id, student_name, school_id, school_name, school_id, school_name, class_name, class_id, is_current, registration_date)
SELECT
id, endpoint, apiBaseUrl, is_parent, loginType, "SCRAPPER", certificateKey, privateKey, email, password, symbol, student_id, user_login_id, student_name, school_id, school_name, school_id, school_name, class_name, class_id, is_current, registration_date
FROM Students
""")
database.execSQL("DROP TABLE Students")
database.execSQL("ALTER TABLE Students_tmp RENAME TO Students")
database.execSQL("CREATE UNIQUE INDEX index_Students_email_symbol_student_id_school_id_class_id ON Students (email, symbol, student_id, school_id, class_id)")
}
private fun migrateSharedPreferences() {
if (sharedPrefProvider.getString("grade_modifier_plus", "0.0") == "0.0") {
sharedPrefProvider.putString("grade_modifier_plus", "0.33")
}
if (sharedPrefProvider.getString("grade_modifier_minus", "0.0") == "0.0") {
sharedPrefProvider.putString("grade_modifier_minus", "0.33")
}
}
}

View File

@ -1,25 +1,24 @@
package io.github.wulkanowy.data.repositories.attendance package io.github.wulkanowy.data.repositories.attendance
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.entities.Attendance import io.github.wulkanowy.data.db.entities.Attendance
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.utils.toLocalDate import io.github.wulkanowy.sdk.Sdk
import io.reactivex.Single import io.reactivex.Single
import org.threeten.bp.LocalDate import org.threeten.bp.LocalDate
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class AttendanceRemote @Inject constructor(private val api: Api) { class AttendanceRemote @Inject constructor(private val sdk: Sdk) {
fun getAttendance(semester: Semester, startDate: LocalDate, endDate: LocalDate): Single<List<Attendance>> { fun getAttendance(semester: Semester, startDate: LocalDate, endDate: LocalDate): Single<List<Attendance>> {
return Single.just(api.apply { diaryId = semester.diaryId }) return sdk.switchDiary(semester.diaryId, semester.schoolYear).getAttendance(startDate, endDate, semester.semesterId)
.flatMap { it.getAttendance(startDate, endDate) }.map { attendance -> .map { attendance ->
attendance.map { attendance.map {
Attendance( Attendance(
studentId = semester.studentId, studentId = semester.studentId,
diaryId = semester.diaryId, diaryId = semester.diaryId,
date = it.date.toLocalDate(), date = it.date,
number = it.number, number = it.number,
subject = it.subject, subject = it.subject,
name = it.name, name = it.name,

View File

@ -1,18 +1,18 @@
package io.github.wulkanowy.data.repositories.attendancesummary package io.github.wulkanowy.data.repositories.attendancesummary
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.entities.AttendanceSummary import io.github.wulkanowy.data.db.entities.AttendanceSummary
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.sdk.Sdk
import io.reactivex.Single import io.reactivex.Single
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class AttendanceSummaryRemote @Inject constructor(private val api: Api) { class AttendanceSummaryRemote @Inject constructor(private val sdk: Sdk) {
fun getAttendanceSummary(semester: Semester, subjectId: Int): Single<List<AttendanceSummary>> { fun getAttendanceSummary(semester: Semester, subjectId: Int): Single<List<AttendanceSummary>> {
return Single.just(api.apply { diaryId = semester.diaryId }) return sdk.switchDiary(semester.diaryId, semester.schoolYear).getAttendanceSummary(subjectId)
.flatMap { api.getAttendanceSummary(subjectId) }.map { attendance -> .map { attendance ->
attendance.map { attendance.map {
AttendanceSummary( AttendanceSummary(
studentId = semester.studentId, studentId = semester.studentId,

View File

@ -1,27 +1,25 @@
package io.github.wulkanowy.data.repositories.completedlessons package io.github.wulkanowy.data.repositories.completedlessons
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.api.toLocalDate
import io.github.wulkanowy.data.db.entities.CompletedLesson import io.github.wulkanowy.data.db.entities.CompletedLesson
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.sdk.Sdk
import io.reactivex.Single import io.reactivex.Single
import org.threeten.bp.LocalDate import org.threeten.bp.LocalDate
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class CompletedLessonsRemote @Inject constructor(private val api: Api) { class CompletedLessonsRemote @Inject constructor(private val sdk: Sdk) {
fun getCompletedLessons(semester: Semester, startDate: LocalDate, endDate: LocalDate): Single<List<CompletedLesson>> { fun getCompletedLessons(semester: Semester, startDate: LocalDate, endDate: LocalDate): Single<List<CompletedLesson>> {
return Single.just(api.apply { diaryId = semester.diaryId }) return sdk.switchDiary(semester.diaryId, semester.schoolYear).getCompletedLessons(startDate, endDate)
.flatMap { it.getCompletedLessons(startDate, endDate) }
.map { lessons -> .map { lessons ->
lessons.map { lessons.map {
it.absence it.absence
CompletedLesson( CompletedLesson(
studentId = semester.studentId, studentId = semester.studentId,
diaryId = semester.diaryId, diaryId = semester.diaryId,
date = it.date.toLocalDate(), date = it.date,
number = it.number, number = it.number,
subject = it.subject, subject = it.subject,
topic = it.topic, topic = it.topic,

View File

@ -1,26 +1,25 @@
package io.github.wulkanowy.data.repositories.exam package io.github.wulkanowy.data.repositories.exam
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.entities.Exam import io.github.wulkanowy.data.db.entities.Exam
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.utils.toLocalDate import io.github.wulkanowy.sdk.Sdk
import io.reactivex.Single import io.reactivex.Single
import org.threeten.bp.LocalDate import org.threeten.bp.LocalDate
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class ExamRemote @Inject constructor(private val api: Api) { class ExamRemote @Inject constructor(private val sdk: Sdk) {
fun getExams(semester: Semester, startDate: LocalDate, endDate: LocalDate): Single<List<Exam>> { fun getExams(semester: Semester, startDate: LocalDate, endDate: LocalDate): Single<List<Exam>> {
return Single.just(api.apply { diaryId = semester.diaryId }) return sdk.switchDiary(semester.diaryId, semester.schoolYear).getExams(startDate, endDate, semester.semesterId)
.flatMap { it.getExams(startDate, endDate) }.map { exams -> .map { exams ->
exams.map { exams.map {
Exam( Exam(
studentId = semester.studentId, studentId = semester.studentId,
diaryId = semester.diaryId, diaryId = semester.diaryId,
date = it.date.toLocalDate(), date = it.date,
entryDate = it.entryDate.toLocalDate(), entryDate = it.entryDate,
subject = it.subject, subject = it.subject,
group = it.group, group = it.group,
type = it.type, type = it.type,

View File

@ -1,35 +1,33 @@
package io.github.wulkanowy.data.repositories.grade package io.github.wulkanowy.data.repositories.grade
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.entities.Grade import io.github.wulkanowy.data.db.entities.Grade
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.utils.toLocalDate import io.github.wulkanowy.sdk.Sdk
import io.reactivex.Single import io.reactivex.Single
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class GradeRemote @Inject constructor(private val api: Api) { class GradeRemote @Inject constructor(private val sdk: Sdk) {
fun getGrades(semester: Semester): Single<List<Grade>> { fun getGrades(semester: Semester): Single<List<Grade>> {
return Single.just(api.apply { diaryId = semester.diaryId }) return sdk.switchDiary(semester.diaryId, semester.schoolYear).getGrades(semester.semesterId)
.flatMap { it.getGrades(semester.semesterId) }
.map { grades -> .map { grades ->
grades.map { grades.map {
Grade( Grade(
semesterId = semester.semesterId,
studentId = semester.studentId, studentId = semester.studentId,
semesterId = semester.semesterId,
subject = it.subject, subject = it.subject,
entry = it.entry, entry = it.entry,
value = it.value, value = it.value,
modifier = it.modifier, modifier = it.modifier,
comment = it.comment, comment = it.comment,
color = it.color, color = it.color,
gradeSymbol = it.symbol.orEmpty(), gradeSymbol = it.symbol,
description = it.description.orEmpty(), description = it.description,
weight = it.weight, weight = it.weight,
weightValue = it.weightValue, weightValue = it.weightValue,
date = it.date.toLocalDate(), date = it.date,
teacher = it.teacher teacher = it.teacher
) )
} }

View File

@ -1,24 +1,23 @@
package io.github.wulkanowy.data.repositories.gradessummary package io.github.wulkanowy.data.repositories.gradessummary
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.entities.GradeSummary import io.github.wulkanowy.data.db.entities.GradeSummary
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.sdk.Sdk
import io.reactivex.Single import io.reactivex.Single
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class GradeSummaryRemote @Inject constructor(private val api: Api) { class GradeSummaryRemote @Inject constructor(private val sdk: Sdk) {
fun getGradeSummary(semester: Semester): Single<List<GradeSummary>> { fun getGradeSummary(semester: Semester): Single<List<GradeSummary>> {
return Single.just(api.apply { diaryId = semester.diaryId }) return sdk.switchDiary(semester.diaryId, semester.schoolYear).getGradesSummary(semester.semesterId)
.flatMap { it.getGradesSummary(semester.semesterId) }
.map { gradesSummary -> .map { gradesSummary ->
gradesSummary.map { gradesSummary.map {
GradeSummary( GradeSummary(
semesterId = semester.semesterId, semesterId = semester.semesterId,
studentId = semester.studentId, studentId = semester.studentId,
position = it.order, position = 0,
subject = it.name, subject = it.name,
predictedGrade = it.predicted, predictedGrade = it.predicted,
finalGrade = it.final, finalGrade = it.final,

View File

@ -1,6 +1,8 @@
package io.github.wulkanowy.data.repositories.gradestatistics package io.github.wulkanowy.data.repositories.gradestatistics
import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao
import io.github.wulkanowy.data.db.dao.GradeStatisticsDao import io.github.wulkanowy.data.db.dao.GradeStatisticsDao
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
import io.github.wulkanowy.data.db.entities.GradeStatistics import io.github.wulkanowy.data.db.entities.GradeStatistics
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.reactivex.Maybe import io.reactivex.Maybe
@ -8,27 +10,57 @@ import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class GradeStatisticsLocal @Inject constructor(private val gradeStatisticsDb: GradeStatisticsDao) { class GradeStatisticsLocal @Inject constructor(
private val gradeStatisticsDb: GradeStatisticsDao,
private val gradePointsStatisticsDb: GradePointsStatisticsDao
) {
fun getGradesStatistics(semester: Semester, isSemester: Boolean): Maybe<List<GradeStatistics>> { fun getGradesStatistics(semester: Semester, isSemester: Boolean): Maybe<List<GradeStatistics>> {
return gradeStatisticsDb.loadAll(semester.semesterId, semester.studentId, isSemester) return gradeStatisticsDb.loadAll(semester.semesterId, semester.studentId, isSemester).filter { it.isNotEmpty() }
.filter { !it.isEmpty() } }
fun getGradesPointsStatistics(semester: Semester): Maybe<List<GradePointsStatistics>> {
return gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId).filter { it.isNotEmpty() }
} }
fun getGradesStatistics(semester: Semester, isSemester: Boolean, subjectName: String): Maybe<List<GradeStatistics>> { fun getGradesStatistics(semester: Semester, isSemester: Boolean, subjectName: String): Maybe<List<GradeStatistics>> {
return (if ("Wszystkie" == subjectName) gradeStatisticsDb.loadAll(semester.semesterId, semester.studentId, isSemester).map { list -> return when (subjectName) {
list.groupBy { it.grade }.map { "Wszystkie" -> gradeStatisticsDb.loadAll(semester.semesterId, semester.studentId, isSemester).map { list ->
GradeStatistics(semester.studentId, semester.semesterId, subjectName, it.key, it.value.fold(0) { acc, e -> acc + e.amount }, false) list.groupBy { it.grade }.map {
GradeStatistics(semester.studentId, semester.semesterId, subjectName, it.key,
it.value.fold(0) { acc, e -> acc + e.amount }, false)
}
} }
else -> gradeStatisticsDb.loadSubject(semester.semesterId, semester.studentId, subjectName, isSemester)
}.filter { it.isNotEmpty() }
}
fun getGradesPointsStatistics(semester: Semester, subjectName: String): Maybe<GradePointsStatistics> {
return when (subjectName) {
"Wszystkie" -> gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId).flatMap { list ->
if (list.isEmpty()) return@flatMap Maybe.empty<GradePointsStatistics>()
Maybe.just(GradePointsStatistics(semester.studentId, semester.semesterId, subjectName,
list.fold(.0) { acc, e -> acc + e.others },
list.fold(.0) { acc, e -> acc + e.student })
)
}
else -> gradePointsStatisticsDb.loadSubject(semester.semesterId, semester.studentId, subjectName)
} }
else gradeStatisticsDb.loadSubject(semester.semesterId, semester.studentId, subjectName, isSemester)).filter { !it.isEmpty() }
} }
fun saveGradesStatistics(gradesStatistics: List<GradeStatistics>) { fun saveGradesStatistics(gradesStatistics: List<GradeStatistics>) {
gradeStatisticsDb.insertAll(gradesStatistics) gradeStatisticsDb.insertAll(gradesStatistics)
} }
fun saveGradesPointsStatistics(gradePointsStatistics: List<GradePointsStatistics>) {
gradePointsStatisticsDb.insertAll(gradePointsStatistics)
}
fun deleteGradesStatistics(gradesStatistics: List<GradeStatistics>) { fun deleteGradesStatistics(gradesStatistics: List<GradeStatistics>) {
gradeStatisticsDb.deleteAll(gradesStatistics) gradeStatisticsDb.deleteAll(gradesStatistics)
} }
fun deleteGradesPointsStatistics(gradesPointsStatistics: List<GradePointsStatistics>) {
gradePointsStatisticsDb.deleteAll(gradesPointsStatistics)
}
} }

View File

@ -1,27 +1,44 @@
package io.github.wulkanowy.data.repositories.gradestatistics package io.github.wulkanowy.data.repositories.gradestatistics
import io.github.wulkanowy.api.Api import io.github.wulkanowy.data.db.entities.GradePointsStatistics
import io.github.wulkanowy.data.db.entities.GradeStatistics import io.github.wulkanowy.data.db.entities.GradeStatistics
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.sdk.Sdk
import io.reactivex.Single import io.reactivex.Single
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class GradeStatisticsRemote @Inject constructor(private val api: Api) { class GradeStatisticsRemote @Inject constructor(private val sdk: Sdk) {
fun getGradeStatistics(semester: Semester, isSemester: Boolean): Single<List<GradeStatistics>> { fun getGradeStatistics(semester: Semester, isSemester: Boolean): Single<List<GradeStatistics>> {
return Single.just(api.apply { diaryId = semester.diaryId }) return sdk.switchDiary(semester.diaryId, semester.schoolYear).let {
.flatMap { it.getGradesStatistics(semester.semesterId, isSemester) } if (isSemester) it.getGradesAnnualStatistics(semester.semesterId)
.map { gradeStatistics -> else it.getGradesPartialStatistics(semester.semesterId)
gradeStatistics.map { }.map { gradeStatistics ->
GradeStatistics( gradeStatistics.map {
GradeStatistics(
semesterId = semester.semesterId,
studentId = semester.studentId,
subject = it.subject,
grade = it.gradeValue,
amount = it.amount,
semester = isSemester
)
}
}
}
fun getGradePointsStatistics(semester: Semester): Single<List<GradePointsStatistics>> {
return sdk.switchDiary(semester.diaryId, semester.schoolYear).getGradesPointsStatistics(semester.semesterId)
.map { gradePointsStatistics ->
gradePointsStatistics.map {
GradePointsStatistics(
semesterId = semester.semesterId, semesterId = semester.semesterId,
studentId = semester.studentId, studentId = semester.studentId,
subject = it.subject, subject = it.subject,
grade = it.gradeValue, others = it.others,
amount = it.amount ?: 0, student = it.student
semester = isSemester
) )
} }
} }

View File

@ -2,9 +2,11 @@ package io.github.wulkanowy.data.repositories.gradestatistics
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
import io.github.wulkanowy.data.db.entities.GradeStatistics import io.github.wulkanowy.data.db.entities.GradeStatistics
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.utils.uniqueSubtract import io.github.wulkanowy.utils.uniqueSubtract
import io.reactivex.Maybe
import io.reactivex.Single import io.reactivex.Single
import java.net.UnknownHostException import java.net.UnknownHostException
import javax.inject.Inject import javax.inject.Inject
@ -31,4 +33,19 @@ class GradeStatisticsRepository @Inject constructor(
} }
}.flatMap { local.getGradesStatistics(semester, isSemester, subjectName).toSingle(emptyList()) }) }.flatMap { local.getGradesStatistics(semester, isSemester, subjectName).toSingle(emptyList()) })
} }
fun getGradesPointsStatistics(semester: Semester, subjectName: String, forceRefresh: Boolean): Maybe<GradePointsStatistics> {
return local.getGradesPointsStatistics(semester, subjectName).filter { !forceRefresh }
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
.flatMapMaybe {
if (it) remote.getGradePointsStatistics(semester).toMaybe()
else Maybe.error(UnknownHostException())
}.flatMap { new ->
local.getGradesPointsStatistics(semester).defaultIfEmpty(emptyList())
.doOnSuccess { old ->
local.deleteGradesPointsStatistics(old.uniqueSubtract(new))
local.saveGradesPointsStatistics(new.uniqueSubtract(old))
}
}.flatMap { local.getGradesPointsStatistics(semester, subjectName) })
}
} }

View File

@ -1,27 +1,25 @@
package io.github.wulkanowy.data.repositories.homework package io.github.wulkanowy.data.repositories.homework
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.entities.Homework import io.github.wulkanowy.data.db.entities.Homework
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.utils.toLocalDate import io.github.wulkanowy.sdk.Sdk
import io.reactivex.Single import io.reactivex.Single
import org.threeten.bp.LocalDate import org.threeten.bp.LocalDate
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class HomeworkRemote @Inject constructor(private val api: Api) { class HomeworkRemote @Inject constructor(private val sdk: Sdk) {
fun getHomework(semester: Semester, startDate: LocalDate, endDate: LocalDate): Single<List<Homework>> { fun getHomework(semester: Semester, startDate: LocalDate, endDate: LocalDate): Single<List<Homework>> {
return Single.just(api.apply { diaryId = semester.diaryId }) return sdk.switchDiary(semester.diaryId, semester.schoolYear).getHomework(startDate, endDate)
.flatMap { it.getHomework(startDate, endDate) }
.map { homework -> .map { homework ->
homework.map { homework.map {
Homework( Homework(
semesterId = semester.semesterId, semesterId = semester.semesterId,
studentId = semester.studentId, studentId = semester.studentId,
date = it.date.toLocalDate(), date = it.date,
entryDate = it.entryDate.toLocalDate(), entryDate = it.entryDate,
subject = it.subject, subject = it.subject,
content = it.content, content = it.content,
teacher = it.teacher, teacher = it.teacher,

View File

@ -12,15 +12,15 @@ import javax.inject.Singleton
class LuckyNumberLocal @Inject constructor(private val luckyNumberDb: LuckyNumberDao) { class LuckyNumberLocal @Inject constructor(private val luckyNumberDb: LuckyNumberDao) {
fun saveLuckyNumber(luckyNumber: LuckyNumber) { fun saveLuckyNumber(luckyNumber: LuckyNumber) {
luckyNumberDb.insert(luckyNumber) luckyNumberDb.insertAll(listOf(luckyNumber))
} }
fun updateLuckyNumber(luckyNumber: LuckyNumber) { fun updateLuckyNumber(luckyNumber: LuckyNumber) {
luckyNumberDb.update(luckyNumber) luckyNumberDb.updateAll(listOf(luckyNumber))
} }
fun deleteLuckyNumber(luckyNumber: LuckyNumber) { fun deleteLuckyNumber(luckyNumber: LuckyNumber) {
luckyNumberDb.delete(luckyNumber) luckyNumberDb.deleteAll(listOf(luckyNumber))
} }
fun getLuckyNumber(semester: Semester, date: LocalDate): Maybe<LuckyNumber> { fun getLuckyNumber(semester: Semester, date: LocalDate): Maybe<LuckyNumber> {

View File

@ -1,20 +1,18 @@
package io.github.wulkanowy.data.repositories.luckynumber package io.github.wulkanowy.data.repositories.luckynumber
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.entities.LuckyNumber import io.github.wulkanowy.data.db.entities.LuckyNumber
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.sdk.Sdk
import io.reactivex.Maybe import io.reactivex.Maybe
import io.reactivex.Single
import org.threeten.bp.LocalDate import org.threeten.bp.LocalDate
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class LuckyNumberRemote @Inject constructor(private val api: Api) { class LuckyNumberRemote @Inject constructor(private val sdk: Sdk) {
fun getLuckyNumber(semester: Semester): Maybe<LuckyNumber> { fun getLuckyNumber(semester: Semester): Maybe<LuckyNumber> {
return Single.just(api.apply { diaryId = semester.diaryId }) return sdk.getLuckyNumber()
.flatMapMaybe { it.getLuckyNumber() }
.map { .map {
LuckyNumber( LuckyNumber(
studentId = semester.studentId, studentId = semester.studentId,

View File

@ -1,24 +1,23 @@
package io.github.wulkanowy.data.repositories.message package io.github.wulkanowy.data.repositories.message
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.api.messages.Folder
import io.github.wulkanowy.api.messages.SentMessage
import io.github.wulkanowy.data.db.entities.Message import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.Recipient import io.github.wulkanowy.data.db.entities.Recipient
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.utils.toLocalDateTime import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.sdk.pojo.Folder
import io.github.wulkanowy.sdk.pojo.SentMessage
import io.reactivex.Single import io.reactivex.Single
import org.threeten.bp.LocalDateTime.now import org.threeten.bp.LocalDateTime.now
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
import io.github.wulkanowy.api.messages.Message as ApiMessage import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient
import io.github.wulkanowy.api.messages.Recipient as ApiRecipient
@Singleton @Singleton
class MessageRemote @Inject constructor(private val api: Api) { class MessageRemote @Inject constructor(private val sdk: Sdk) {
fun getMessages(student: Student, folder: MessageFolder): Single<List<Message>> { fun getMessages(student: Student, semester: Semester, folder: MessageFolder): Single<List<Message>> {
return api.getMessages(Folder.valueOf(folder.name)).map { messages -> return sdk.getMessages(Folder.valueOf(folder.name), semester.start.atStartOfDay(), semester.end.atStartOfDay()).map { messages ->
messages.map { messages.map {
Message( Message(
studentId = student.id.toInt(), studentId = student.id.toInt(),
@ -28,7 +27,8 @@ class MessageRemote @Inject constructor(private val api: Api) {
senderId = it.senderId ?: 0, senderId = it.senderId ?: 0,
recipient = it.recipient.orEmpty(), recipient = it.recipient.orEmpty(),
subject = it.subject.trim(), subject = it.subject.trim(),
date = it.date?.toLocalDateTime() ?: now(), date = it.date ?: now(),
content = it.content.orEmpty(),
folderId = it.folderId, folderId = it.folderId,
unread = it.unread ?: false, unread = it.unread ?: false,
unreadBy = it.unreadBy ?: 0, unreadBy = it.unreadBy ?: 0,
@ -40,27 +40,28 @@ class MessageRemote @Inject constructor(private val api: Api) {
} }
fun getMessagesContent(message: Message, markAsRead: Boolean = false): Single<String> { fun getMessagesContent(message: Message, markAsRead: Boolean = false): Single<String> {
return api.getMessageContent(message.messageId, message.folderId, markAsRead, message.realId) return sdk.getMessageContent(message.messageId, message.folderId, markAsRead, message.realId)
} }
fun sendMessage(subject: String, content: String, recipients: List<Recipient>): Single<SentMessage> { fun sendMessage(subject: String, content: String, recipients: List<Recipient>): Single<SentMessage> {
return api.sendMessage( return sdk.sendMessage(
subject = subject, subject = subject,
content = content, content = content,
recipients = recipients.map { recipients = recipients.map {
ApiRecipient( SdkRecipient(
id = it.realId, id = it.realId,
name = it.realName, name = it.realName,
loginId = it.loginId, loginId = it.loginId,
reportingUnitId = it.unitId, reportingUnitId = it.unitId,
role = it.role, role = it.role,
hash = it.hash hash = it.hash,
shortName = it.name
) )
} }
) )
} }
fun deleteMessage(message: Message): Single<Boolean> { fun deleteMessage(message: Message): Single<Boolean> {
return api.deleteMessages(listOf(Pair(message.realId, message.folderId))) return sdk.deleteMessages(listOf(Pair(message.realId, message.folderId)))
} }
} }

View File

@ -2,12 +2,13 @@ package io.github.wulkanowy.data.repositories.message
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
import io.github.wulkanowy.api.messages.SentMessage import io.github.wulkanowy.data.SdkHelper
import io.github.wulkanowy.data.ApiHelper
import io.github.wulkanowy.data.db.entities.Message import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.Recipient import io.github.wulkanowy.data.db.entities.Recipient
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.repositories.message.MessageFolder.RECEIVED import io.github.wulkanowy.data.repositories.message.MessageFolder.RECEIVED
import io.github.wulkanowy.sdk.pojo.SentMessage
import io.github.wulkanowy.utils.uniqueSubtract import io.github.wulkanowy.utils.uniqueSubtract
import io.reactivex.Completable import io.reactivex.Completable
import io.reactivex.Maybe import io.reactivex.Maybe
@ -21,16 +22,16 @@ class MessageRepository @Inject constructor(
private val settings: InternetObservingSettings, private val settings: InternetObservingSettings,
private val local: MessageLocal, private val local: MessageLocal,
private val remote: MessageRemote, private val remote: MessageRemote,
private val apiHelper: ApiHelper private val sdkHelper: SdkHelper
) { ) {
fun getMessages(student: Student, folder: MessageFolder, forceRefresh: Boolean = false, notify: Boolean = false): Single<List<Message>> { fun getMessages(student: Student, semester: Semester, folder: MessageFolder, forceRefresh: Boolean = false, notify: Boolean = false): Single<List<Message>> {
return Single.just(apiHelper.initApi(student)) return Single.just(sdkHelper.init(student))
.flatMap { _ -> .flatMap { _ ->
local.getMessages(student, folder).filter { !forceRefresh } local.getMessages(student, folder).filter { !forceRefresh }
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
.flatMap { .flatMap {
if (it) remote.getMessages(student, folder) if (it) remote.getMessages(student, semester, folder)
else Single.error(UnknownHostException()) else Single.error(UnknownHostException())
}.flatMap { new -> }.flatMap { new ->
local.getMessages(student, folder).toSingle(emptyList()) local.getMessages(student, folder).toSingle(emptyList())
@ -47,10 +48,10 @@ class MessageRepository @Inject constructor(
} }
fun getMessage(student: Student, messageDbId: Long, markAsRead: Boolean = false): Single<Message> { fun getMessage(student: Student, messageDbId: Long, markAsRead: Boolean = false): Single<Message> {
return Single.just(apiHelper.initApi(student)) return Single.just(sdkHelper.init(student))
.flatMap { _ -> .flatMap { _ ->
local.getMessage(messageDbId) local.getMessage(messageDbId)
.filter { !it.content.isNullOrEmpty() } .filter { it.content.isNotEmpty() }
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
.flatMap { .flatMap {
if (it) local.getMessage(messageDbId).toSingle() if (it) local.getMessage(messageDbId).toSingle()
@ -60,7 +61,7 @@ class MessageRepository @Inject constructor(
remote.getMessagesContent(dbMessage, markAsRead).doOnSuccess { remote.getMessagesContent(dbMessage, markAsRead).doOnSuccess {
local.updateMessages(listOf(dbMessage.copy(unread = false).apply { local.updateMessages(listOf(dbMessage.copy(unread = false).apply {
id = dbMessage.id id = dbMessage.id
content = it content = content.ifBlank { it }
})) }))
} }
}.flatMap { }.flatMap {

View File

@ -3,7 +3,6 @@ package io.github.wulkanowy.data.repositories.mobiledevice
import io.github.wulkanowy.data.db.dao.MobileDeviceDao import io.github.wulkanowy.data.db.dao.MobileDeviceDao
import io.github.wulkanowy.data.db.entities.MobileDevice import io.github.wulkanowy.data.db.entities.MobileDevice
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import io.reactivex.Maybe import io.reactivex.Maybe
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton

View File

@ -1,25 +1,23 @@
package io.github.wulkanowy.data.repositories.mobiledevice package io.github.wulkanowy.data.repositories.mobiledevice
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.entities.MobileDevice import io.github.wulkanowy.data.db.entities.MobileDevice
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.pojos.MobileDeviceToken import io.github.wulkanowy.data.pojos.MobileDeviceToken
import io.github.wulkanowy.utils.toLocalDateTime import io.github.wulkanowy.sdk.Sdk
import io.reactivex.Single import io.reactivex.Single
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class MobileDeviceRemote @Inject constructor(private val api: Api) { class MobileDeviceRemote @Inject constructor(private val sdk: Sdk) {
fun getDevices(semester: Semester): Single<List<MobileDevice>> { fun getDevices(semester: Semester): Single<List<MobileDevice>> {
return Single.just(api.apply { diaryId = semester.diaryId }) return sdk.switchDiary(semester.diaryId, semester.schoolYear).getRegisteredDevices()
.flatMap { api.getRegisteredDevices() }
.map { devices -> .map { devices ->
devices.map { devices.map {
MobileDevice( MobileDevice(
studentId = semester.studentId, studentId = semester.studentId,
date = it.date.toLocalDateTime(), date = it.date,
deviceId = it.id, deviceId = it.id,
name = it.name name = it.name
) )
@ -28,13 +26,11 @@ class MobileDeviceRemote @Inject constructor(private val api: Api) {
} }
fun unregisterDevice(semester: Semester, device: MobileDevice): Single<Boolean> { fun unregisterDevice(semester: Semester, device: MobileDevice): Single<Boolean> {
return Single.just(api.apply { diaryId = semester.diaryId }) return sdk.switchDiary(semester.diaryId, semester.schoolYear).unregisterDevice(device.deviceId)
.flatMap { api.unregisterDevice(device.deviceId) }
} }
fun getToken(semester: Semester): Single<MobileDeviceToken> { fun getToken(semester: Semester): Single<MobileDeviceToken> {
return Single.just(api.apply { diaryId = semester.diaryId }) return sdk.switchDiary(semester.diaryId, semester.schoolYear).getToken()
.flatMap { api.getToken() }
.map { .map {
MobileDeviceToken( MobileDeviceToken(
token = it.token, token = it.token,

View File

@ -1,24 +1,22 @@
package io.github.wulkanowy.data.repositories.note package io.github.wulkanowy.data.repositories.note
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.entities.Note import io.github.wulkanowy.data.db.entities.Note
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.utils.toLocalDate import io.github.wulkanowy.sdk.Sdk
import io.reactivex.Single import io.reactivex.Single
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class NoteRemote @Inject constructor(private val api: Api) { class NoteRemote @Inject constructor(private val sdk: Sdk) {
fun getNotes(semester: Semester): Single<List<Note>> { fun getNotes(semester: Semester): Single<List<Note>> {
return Single.just(api.apply { diaryId = semester.diaryId }) return sdk.switchDiary(semester.diaryId, semester.schoolYear).getNotes(semester.semesterId)
.flatMap { it.getNotes() }
.map { notes -> .map { notes ->
notes.map { notes.map {
Note( Note(
studentId = semester.studentId, studentId = semester.studentId,
date = it.date.toLocalDate(), date = it.date,
teacher = it.teacher, teacher = it.teacher,
category = it.category, category = it.category,
content = it.content content = it.content

View File

@ -12,52 +12,64 @@ class PreferencesRepository @Inject constructor(
val context: Context val context: Context
) { ) {
val startMenuIndex: Int val startMenuIndex: Int
get() = sharedPref.getString(context.getString(R.string.pref_key_start_menu), "0")?.toIntOrNull() ?: 0 get() = getString(R.string.pref_key_start_menu, R.string.pref_default_startup).toInt()
val isShowPresent: Boolean val isShowPresent: Boolean
get() = sharedPref.getBoolean(context.getString(R.string.pref_key_attendance_present), true) get() = getBoolean(R.string.pref_key_attendance_present, R.bool.pref_default_attendance_present)
val gradeAverageMode: String val gradeAverageMode: String
get() = sharedPref.getString(context.getString(R.string.pref_key_grade_average_mode), "only_one_semester") ?: "only_one_semester" get() = getString(R.string.pref_key_grade_average_mode, R.string.pref_default_grade_average_mode)
val gradeAverageForceCalc: Boolean val gradeAverageForceCalc: Boolean
get() = sharedPref.getBoolean(context.getString(R.string.pref_key_grade_average_force_calc), false) get() = getBoolean(R.string.pref_key_grade_average_force_calc, R.bool.pref_default_grade_average_force_calc)
val isGradeExpandable: Boolean val isGradeExpandable: Boolean
get() = !sharedPref.getBoolean(context.getString(R.string.pref_key_expand_grade), false) get() = !getBoolean(R.string.pref_key_expand_grade, R.bool.pref_default_expand_grade)
val appThemeKey: String = context.getString(R.string.pref_key_app_theme) val appThemeKey = context.getString(R.string.pref_key_app_theme)
val appTheme: String val appTheme: String
get() = sharedPref.getString(appThemeKey, "light") ?: "light" get() = getString(appThemeKey, R.string.pref_default_app_theme)
val gradeColorTheme: String val gradeColorTheme: String
get() = sharedPref.getString(context.getString(R.string.pref_key_grade_color_scheme), "vulcan") ?: "vulcan" get() = getString(R.string.pref_key_grade_color_scheme, R.string.pref_default_grade_color_scheme)
val serviceEnableKey: String = context.getString(R.string.pref_key_services_enable) val appLanguageKey = context.getString(R.string.pref_key_app_language)
val appLanguage
get() = getString(appLanguageKey, R.string.pref_default_app_language)
val serviceEnableKey = context.getString(R.string.pref_key_services_enable)
val isServiceEnabled: Boolean val isServiceEnabled: Boolean
get() = sharedPref.getBoolean(serviceEnableKey, true) get() = getBoolean(serviceEnableKey, R.bool.pref_default_services_enable)
val servicesIntervalKey: String = context.getString(R.string.pref_key_services_interval) val servicesIntervalKey = context.getString(R.string.pref_key_services_interval)
val servicesInterval: Long val servicesInterval: Long
get() = sharedPref.getString(servicesIntervalKey, "60")?.toLongOrNull() ?: 60 get() = getString(servicesIntervalKey, R.string.pref_default_services_interval).toLong()
val servicesOnlyWifiKey: String = context.getString(R.string.pref_key_services_wifi_only) val servicesOnlyWifiKey = context.getString(R.string.pref_key_services_wifi_only)
val isServicesOnlyWifi: Boolean val isServicesOnlyWifi: Boolean
get() = sharedPref.getBoolean(servicesOnlyWifiKey, false) get() = getBoolean(servicesOnlyWifiKey, R.bool.pref_default_services_wifi_only)
val isNotificationsEnable: Boolean val isNotificationsEnable: Boolean
get() = sharedPref.getBoolean(context.getString(R.string.pref_key_notifications_enable), true) get() = getBoolean(R.string.pref_key_notifications_enable, R.bool.pref_default_notifications_enable)
val isDebugNotificationEnableKey: String = context.getString(R.string.pref_key_notification_debug) val isDebugNotificationEnableKey = context.getString(R.string.pref_key_notification_debug)
val isDebugNotificationEnable: Boolean val isDebugNotificationEnable: Boolean
get() = sharedPref.getBoolean(isDebugNotificationEnableKey, false) get() = getBoolean(isDebugNotificationEnableKey, R.bool.pref_default_notification_debug)
val gradePlusModifier: Double val gradePlusModifier: Double
get() = sharedPref.getString(context.getString(R.string.pref_key_grade_modifier_plus), "0.0")?.toDouble() ?: 0.0 get() = getString(R.string.pref_key_grade_modifier_plus, R.string.pref_default_grade_modifier_plus).toDouble()
val gradeMinusModifier: Double val gradeMinusModifier: Double
get() = sharedPref.getString(context.getString(R.string.pref_key_grade_modifier_minus), "0.0")?.toDouble() ?: 0.0 get() = getString(R.string.pref_key_grade_modifier_minus, R.string.pref_default_grade_modifier_minus).toDouble()
val fillMessageContent: Boolean val fillMessageContent: Boolean
get() = sharedPref.getBoolean(context.getString(R.string.pref_key_fill_message_content), true) get() = getBoolean(R.string.pref_key_fill_message_content, R.bool.pref_default_fill_message_content)
private fun getString(id: Int, default: Int) = getString(context.getString(id), default)
private fun getString(id: String, default: Int) = sharedPref.getString(id, context.getString(default)) ?: context.getString(default)
private fun getBoolean(id: Int, default: Int) = getBoolean(context.getString(id), default)
private fun getBoolean(id: String, default: Int) = sharedPref.getBoolean(id, context.resources.getBoolean(default))
} }

View File

@ -15,7 +15,7 @@ class RecipientLocal @Inject constructor(private val recipientDb: RecipientDao)
return recipientDb.load(student.studentId, role, unit.realId).filter { !it.isEmpty() } return recipientDb.load(student.studentId, role, unit.realId).filter { !it.isEmpty() }
} }
fun saveRecipients(recipients: List<Recipient>) { fun saveRecipients(recipients: List<Recipient>): List<Long> {
return recipientDb.insertAll(recipients) return recipientDb.insertAll(recipients)
} }

View File

@ -1,34 +1,34 @@
package io.github.wulkanowy.data.repositories.recipient package io.github.wulkanowy.data.repositories.recipient
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.entities.Message import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.Recipient import io.github.wulkanowy.data.db.entities.Recipient
import io.github.wulkanowy.data.db.entities.ReportingUnit import io.github.wulkanowy.data.db.entities.ReportingUnit
import io.github.wulkanowy.sdk.Sdk
import io.reactivex.Single import io.reactivex.Single
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
import io.github.wulkanowy.api.messages.Recipient as ApiRecipient import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient
@Singleton @Singleton
class RecipientRemote @Inject constructor(private val api: Api) { class RecipientRemote @Inject constructor(private val sdk: Sdk) {
fun getRecipients(role: Int, unit: ReportingUnit): Single<List<Recipient>> { fun getRecipients(role: Int, unit: ReportingUnit): Single<List<Recipient>> {
return api.getRecipients(unit.realId, role) return sdk.getRecipients(unit.realId, role)
.map { recipients -> .map { recipients ->
recipients.map { it.toRecipient() } recipients.map { it.toRecipient() }
} }
} }
fun getMessageRecipients(message: Message): Single<List<Recipient>> { fun getMessageRecipients(message: Message): Single<List<Recipient>> {
return api.getMessageRecipients(message.messageId, message.senderId) return sdk.getMessageRecipients(message.messageId, message.senderId)
.map { recipients -> .map { recipients ->
recipients.map { it.toRecipient() } recipients.map { it.toRecipient() }
} }
} }
private fun ApiRecipient.toRecipient(): Recipient { private fun SdkRecipient.toRecipient(): Recipient {
return Recipient( return Recipient(
studentId = api.studentId, studentId = sdk.studentId,
realId = id, realId = id,
realName = name, realName = name,
name = shortName, name = shortName,

View File

@ -2,7 +2,7 @@ package io.github.wulkanowy.data.repositories.recipient
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
import io.github.wulkanowy.data.ApiHelper import io.github.wulkanowy.data.SdkHelper
import io.github.wulkanowy.data.db.entities.Message import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.Recipient import io.github.wulkanowy.data.db.entities.Recipient
import io.github.wulkanowy.data.db.entities.ReportingUnit import io.github.wulkanowy.data.db.entities.ReportingUnit
@ -18,11 +18,11 @@ class RecipientRepository @Inject constructor(
private val settings: InternetObservingSettings, private val settings: InternetObservingSettings,
private val local: RecipientLocal, private val local: RecipientLocal,
private val remote: RecipientRemote, private val remote: RecipientRemote,
private val apiHelper: ApiHelper private val sdkHelper: SdkHelper
) { ) {
fun getRecipients(student: Student, role: Int, unit: ReportingUnit, forceRefresh: Boolean = false): Single<List<Recipient>> { fun getRecipients(student: Student, role: Int, unit: ReportingUnit, forceRefresh: Boolean = false): Single<List<Recipient>> {
return Single.just(apiHelper.initApi(student)) return Single.just(sdkHelper.init(student))
.flatMap { _ -> .flatMap { _ ->
local.getRecipients(student, role, unit).filter { !forceRefresh } local.getRecipients(student, role, unit).filter { !forceRefresh }
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
@ -43,7 +43,7 @@ class RecipientRepository @Inject constructor(
} }
fun getMessageRecipients(student: Student, message: Message): Single<List<Recipient>> { fun getMessageRecipients(student: Student, message: Message): Single<List<Recipient>> {
return Single.just(apiHelper.initApi(student)) return Single.just(sdkHelper.init(student))
.flatMap { ReactiveNetwork.checkInternetConnectivity(settings) } .flatMap { ReactiveNetwork.checkInternetConnectivity(settings) }
.flatMap { .flatMap {
if (it) remote.getMessageRecipients(message) if (it) remote.getMessageRecipients(message)

View File

@ -18,7 +18,7 @@ class ReportingUnitLocal @Inject constructor(private val reportingUnitDb: Report
return reportingUnitDb.loadOne(student.studentId, unitId) return reportingUnitDb.loadOne(student.studentId, unitId)
} }
fun saveReportingUnits(reportingUnits: List<ReportingUnit>) { fun saveReportingUnits(reportingUnits: List<ReportingUnit>): List<Long> {
return reportingUnitDb.insertAll(reportingUnits) return reportingUnitDb.insertAll(reportingUnits)
} }

View File

@ -1,19 +1,19 @@
package io.github.wulkanowy.data.repositories.reportingunit package io.github.wulkanowy.data.repositories.reportingunit
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.entities.ReportingUnit import io.github.wulkanowy.data.db.entities.ReportingUnit
import io.github.wulkanowy.sdk.Sdk
import io.reactivex.Single import io.reactivex.Single
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class ReportingUnitRemote @Inject constructor(private val api: Api) { class ReportingUnitRemote @Inject constructor(private val sdk: Sdk) {
fun getReportingUnits(): Single<List<ReportingUnit>> { fun getReportingUnits(): Single<List<ReportingUnit>> {
return api.getReportingUnits().map { return sdk.getReportingUnits().map {
it.map { unit -> it.map { unit ->
ReportingUnit( ReportingUnit(
studentId = api.studentId, studentId = sdk.studentId,
realId = unit.id, realId = unit.id,
roles = unit.roles, roles = unit.roles,
senderId = unit.senderId, senderId = unit.senderId,

View File

@ -2,7 +2,7 @@ package io.github.wulkanowy.data.repositories.reportingunit
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
import io.github.wulkanowy.data.ApiHelper import io.github.wulkanowy.data.SdkHelper
import io.github.wulkanowy.data.db.entities.ReportingUnit import io.github.wulkanowy.data.db.entities.ReportingUnit
import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.utils.uniqueSubtract import io.github.wulkanowy.utils.uniqueSubtract
@ -17,11 +17,11 @@ class ReportingUnitRepository @Inject constructor(
private val settings: InternetObservingSettings, private val settings: InternetObservingSettings,
private val local: ReportingUnitLocal, private val local: ReportingUnitLocal,
private val remote: ReportingUnitRemote, private val remote: ReportingUnitRemote,
private val apiHelper: ApiHelper private val sdkHelper: SdkHelper
) { ) {
fun getReportingUnits(student: Student, forceRefresh: Boolean = false): Single<List<ReportingUnit>> { fun getReportingUnits(student: Student, forceRefresh: Boolean = false): Single<List<ReportingUnit>> {
return Single.just(apiHelper.initApi(student)) return Single.just(sdkHelper.init(student))
.flatMap { _ -> .flatMap { _ ->
local.getReportingUnits(student).filter { !forceRefresh } local.getReportingUnits(student).filter { !forceRefresh }
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
@ -40,7 +40,7 @@ class ReportingUnitRepository @Inject constructor(
} }
fun getReportingUnit(student: Student, unitId: Int): Maybe<ReportingUnit> { fun getReportingUnit(student: Student, unitId: Int): Maybe<ReportingUnit> {
return Maybe.just(apiHelper.initApi(student)) return Maybe.just(sdkHelper.init(student))
.flatMap { _ -> .flatMap { _ ->
local.getReportingUnit(student, unitId) local.getReportingUnit(student, unitId)
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)

View File

@ -0,0 +1,22 @@
package io.github.wulkanowy.data.repositories.school
import io.github.wulkanowy.data.db.dao.SchoolDao
import io.github.wulkanowy.data.db.entities.School
import io.github.wulkanowy.data.db.entities.Semester
import io.reactivex.Maybe
import javax.inject.Inject
class SchoolLocal @Inject constructor(private val schoolDb: SchoolDao) {
fun saveSchool(school: School) {
schoolDb.insertAll(listOf(school))
}
fun deleteSchool(school: School) {
schoolDb.deleteAll(listOf(school))
}
fun getSchool(semester: Semester): Maybe<School> {
return schoolDb.load(semester.studentId, semester.classId)
}
}

View File

@ -0,0 +1,25 @@
package io.github.wulkanowy.data.repositories.school
import io.github.wulkanowy.data.db.entities.School
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.sdk.Sdk
import io.reactivex.Single
import javax.inject.Inject
class SchoolRemote @Inject constructor(private val sdk: Sdk) {
fun getSchoolInfo(semester: Semester): Single<School> {
return sdk.switchDiary(semester.diaryId, semester.schoolYear).getSchool()
.map {
School(
studentId = semester.studentId,
classId = semester.classId,
name = it.name,
address = it.address,
contact = it.contact,
headmaster = it.headmaster,
pedagogue = it.pedagogue
)
}
}
}

View File

@ -0,0 +1,41 @@
package io.github.wulkanowy.data.repositories.school
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
import io.github.wulkanowy.data.db.entities.School
import io.github.wulkanowy.data.db.entities.Semester
import io.reactivex.Maybe
import io.reactivex.Single
import java.net.UnknownHostException
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class SchoolRepository @Inject constructor(
private val settings: InternetObservingSettings,
private val local: SchoolLocal,
private val remote: SchoolRemote
) {
fun getSchoolInfo(semester: Semester, forceRefresh: Boolean = false): Maybe<School> {
return local.getSchool(semester).filter { !forceRefresh }
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
.flatMap {
if (it) remote.getSchoolInfo(semester)
else Single.error(UnknownHostException())
}.flatMapMaybe { new ->
local.getSchool(semester)
.doOnSuccess { old ->
if (new != old) {
local.deleteSchool(old)
local.saveSchool(new)
}
}
.doOnComplete {
local.saveSchool(new)
}
}.flatMap({ local.getSchool(semester) }, { Maybe.error(it) },
{ local.getSchool(semester) })
)
}
}

View File

@ -1,35 +1,32 @@
package io.github.wulkanowy.data.repositories.semester package io.github.wulkanowy.data.repositories.semester
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.sdk.Sdk
import io.reactivex.Single import io.reactivex.Single
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class SemesterRemote @Inject constructor(private val api: Api) { class SemesterRemote @Inject constructor(private val sdk: Sdk) {
fun getSemesters(student: Student): Single<List<Semester>> { fun getSemesters(student: Student): Single<List<Semester>> {
return api.getSemesters().map { semesters -> return sdk.getSemesters().map { semesters ->
semesters.map { semester -> semesters.map {
Semester( Semester(
studentId = student.studentId, studentId = student.studentId,
diaryId = semester.diaryId, diaryId = it.diaryId,
diaryName = semester.diaryName, diaryName = it.diaryName,
schoolYear = semester.schoolYear, schoolYear = it.schoolYear,
semesterId = semester.semesterId, semesterId = it.semesterId,
semesterName = semester.semesterNumber, semesterName = it.semesterNumber,
isCurrent = semester.current, isCurrent = it.current,
start = semester.start, start = it.start,
end = semester.end, end = it.end,
classId = semester.classId, classId = it.classId,
unitId = semester.unitId unitId = it.unitId
) )
} }
} }
} }
} }

View File

@ -2,7 +2,7 @@ package io.github.wulkanowy.data.repositories.semester
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
import io.github.wulkanowy.data.ApiHelper import io.github.wulkanowy.data.SdkHelper
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.utils.uniqueSubtract import io.github.wulkanowy.utils.uniqueSubtract
@ -18,11 +18,11 @@ class SemesterRepository @Inject constructor(
private val remote: SemesterRemote, private val remote: SemesterRemote,
private val local: SemesterLocal, private val local: SemesterLocal,
private val settings: InternetObservingSettings, private val settings: InternetObservingSettings,
private val apiHelper: ApiHelper private val sdkHelper: SdkHelper
) { ) {
fun getSemesters(student: Student, forceRefresh: Boolean = false): Single<List<Semester>> { fun getSemesters(student: Student, forceRefresh: Boolean = false): Single<List<Semester>> {
return Maybe.just(apiHelper.initApi(student)) return Maybe.just(sdkHelper.init(student))
.flatMap { local.getSemesters(student).filter { !forceRefresh } } .flatMap { local.getSemesters(student).filter { !forceRefresh } }
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
.flatMap { .flatMap {

View File

@ -3,6 +3,7 @@ package io.github.wulkanowy.data.repositories.student
import android.content.Context import android.content.Context
import io.github.wulkanowy.data.db.dao.StudentDao import io.github.wulkanowy.data.db.dao.StudentDao
import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.utils.security.decrypt import io.github.wulkanowy.utils.security.decrypt
import io.github.wulkanowy.utils.security.encrypt import io.github.wulkanowy.utils.security.encrypt
import io.reactivex.Completable import io.reactivex.Completable
@ -18,17 +19,26 @@ class StudentLocal @Inject constructor(
) { ) {
fun saveStudents(students: List<Student>): Single<List<Long>> { fun saveStudents(students: List<Student>): Single<List<Long>> {
return Single.fromCallable { studentDb.insertAll(students.map { it.copy(password = encrypt(it.password, context)) }) } return Single.fromCallable {
studentDb.insertAll(students.map {
if (Sdk.Mode.valueOf(it.loginMode) != Sdk.Mode.API) it.copy(password = encrypt(it.password, context))
else it
})
}
} }
fun getStudents(decryptPass: Boolean): Maybe<List<Student>> { fun getStudents(decryptPass: Boolean): Maybe<List<Student>> {
return studentDb.loadAll() return studentDb.loadAll()
.map { list -> list.map { it.apply { if (decryptPass) password = decrypt(password) } } } .map { list -> list.map { it.apply { if (decryptPass) password = decrypt(password) } } }
.filter { !it.isEmpty() } .filter { it.isNotEmpty() }
} }
fun getCurrentStudent(decryptPass: Boolean): Maybe<Student> { fun getCurrentStudent(decryptPass: Boolean): Maybe<Student> {
return studentDb.loadCurrent().map { it.apply { if (decryptPass) password = decrypt(password) } } return studentDb.loadCurrent().map {
it.apply {
if (decryptPass && Sdk.Mode.valueOf(loginMode) != Sdk.Mode.API) password = decrypt(password)
}
}
} }
fun setCurrentStudent(student: Student): Completable { fun setCurrentStudent(student: Student): Completable {

View File

@ -1,34 +1,51 @@
package io.github.wulkanowy.data.repositories.student package io.github.wulkanowy.data.repositories.student
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.sdk.Sdk
import io.reactivex.Single import io.reactivex.Single
import org.threeten.bp.LocalDateTime.now import org.threeten.bp.LocalDateTime.now
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
import io.github.wulkanowy.sdk.pojo.Student as SdkStudent
@Singleton @Singleton
class StudentRemote @Inject constructor(private val api: Api) { class StudentRemote @Inject constructor(private val sdk: Sdk) {
fun getStudents(email: String, password: String, endpoint: String): Single<List<Student>> { private fun mapStudents(students: List<SdkStudent>, email: String, password: String): List<Student> {
return api.getStudents().map { students -> return students.map { student ->
students.map { student -> Student(
Student( email = email,
email = email, password = password,
password = password, isParent = student.isParent,
symbol = student.symbol, symbol = student.symbol,
studentId = student.studentId, studentId = student.studentId,
studentName = student.studentName, userLoginId = student.userLoginId,
schoolSymbol = student.schoolSymbol, studentName = student.studentName,
schoolName = student.schoolName, schoolSymbol = student.schoolSymbol,
className = student.className, schoolName = student.schoolName,
classId = student.classId, className = student.className,
endpoint = endpoint, classId = student.classId,
loginType = student.loginType.name, scrapperBaseUrl = student.scrapperBaseUrl,
isCurrent = false, loginType = student.loginType.name,
registrationDate = now() isCurrent = false,
) registrationDate = now(),
} mobileBaseUrl = student.mobileBaseUrl,
privateKey = student.privateKey,
certificateKey = student.certificateKey,
loginMode = student.loginMode.name
)
} }
} }
fun getStudentsMobileApi(token: String, pin: String, symbol: String): Single<List<Student>> {
return sdk.getStudentsFromMobileApi(token, pin, symbol).map { mapStudents(it, "", "") }
}
fun getStudentsScrapper(email: String, password: String, scrapperBaseUrl: String, symbol: String): Single<List<Student>> {
return sdk.getStudentsFromScrapper(email, password, scrapperBaseUrl, symbol).map { mapStudents(it, email, password) }
}
fun getStudentsHybrid(email: String, password: String, scrapperBaseUrl: String, symbol: String): Single<List<Student>> {
return sdk.getStudentsHybrid(email, password, scrapperBaseUrl, symbol).map { mapStudents(it, email, password) }
}
} }

View File

@ -2,7 +2,6 @@ package io.github.wulkanowy.data.repositories.student
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
import io.github.wulkanowy.data.ApiHelper
import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.exceptions.NoCurrentStudentException import io.github.wulkanowy.data.exceptions.NoCurrentStudentException
import io.reactivex.Completable import io.reactivex.Completable
@ -16,21 +15,32 @@ import javax.inject.Singleton
class StudentRepository @Inject constructor( class StudentRepository @Inject constructor(
private val local: StudentLocal, private val local: StudentLocal,
private val remote: StudentRemote, private val remote: StudentRemote,
private val settings: InternetObservingSettings, private val settings: InternetObservingSettings
private val apiHelper: ApiHelper
) { ) {
fun isStudentSaved(): Single<Boolean> = local.getStudents(false).isEmpty.map { !it } fun isStudentSaved(): Single<Boolean> = local.getStudents(false).isEmpty.map { !it }
fun isCurrentStudentSet(): Single<Boolean> = local.getCurrentStudent(false).isEmpty.map { !it } fun isCurrentStudentSet(): Single<Boolean> = local.getCurrentStudent(false).isEmpty.map { !it }
fun getStudents(email: String, password: String, endpoint: String, symbol: String = ""): Single<List<Student>> { fun getStudentsApi(pin: String, symbol: String, token: String): Single<List<Student>> {
return ReactiveNetwork.checkInternetConnectivity(settings) return ReactiveNetwork.checkInternetConnectivity(settings).flatMap {
.flatMap { if (it) remote.getStudentsMobileApi(token, pin, symbol)
apiHelper.initApi(email, password, symbol, endpoint) else Single.error(UnknownHostException("No internet connection"))
if (it) remote.getStudents(email, password, endpoint) }
else Single.error(UnknownHostException("No internet connection")) }
}
fun getStudentsScrapper(email: String, password: String, endpoint: String, symbol: String = ""): Single<List<Student>> {
return ReactiveNetwork.checkInternetConnectivity(settings).flatMap {
if (it) remote.getStudentsScrapper(email, password, endpoint, symbol)
else Single.error(UnknownHostException("No internet connection"))
}
}
fun getStudentsHybrid(email: String, password: String, endpoint: String, symbol: String): Single<List<Student>> {
return ReactiveNetwork.checkInternetConnectivity(settings).flatMap {
if (it) remote.getStudentsHybrid(email, password, endpoint, symbol)
else Single.error(UnknownHostException("No internet connection"))
}
} }
fun getSavedStudents(decryptPass: Boolean = true): Single<List<Student>> { fun getSavedStudents(decryptPass: Boolean = true): Single<List<Student>> {

View File

@ -1,25 +1,24 @@
package io.github.wulkanowy.data.repositories.subject package io.github.wulkanowy.data.repositories.subject
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Subject import io.github.wulkanowy.data.db.entities.Subject
import io.github.wulkanowy.sdk.Sdk
import io.reactivex.Single import io.reactivex.Single
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class SubjectRemote @Inject constructor(private val api: Api) { class SubjectRemote @Inject constructor(private val sdk: Sdk) {
fun getSubjects(semester: Semester): Single<List<Subject>> { fun getSubjects(semester: Semester): Single<List<Subject>> {
return Single.just(api.apply { diaryId = semester.diaryId }) return sdk.switchDiary(semester.diaryId, semester.schoolYear).getSubjects()
.flatMap { api.getSubjects() }
.map { subjects -> .map { subjects ->
subjects.map { subjects.map {
Subject( Subject(
studentId = semester.studentId, studentId = semester.studentId,
diaryId = semester.diaryId, diaryId = semester.diaryId,
name = it.name, name = it.name,
realId = it.value realId = it.id
) )
} }
} }

View File

@ -0,0 +1,22 @@
package io.github.wulkanowy.data.repositories.teacher
import io.github.wulkanowy.data.db.dao.TeacherDao
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Teacher
import io.reactivex.Maybe
import javax.inject.Inject
class TeacherLocal @Inject constructor(private val teacherDb: TeacherDao) {
fun saveTeachers(teachers: List<Teacher>) {
teacherDb.insertAll(teachers)
}
fun deleteTeachers(teachers: List<Teacher>) {
teacherDb.deleteAll(teachers)
}
fun getTeachers(semester: Semester): Maybe<List<Teacher>> {
return teacherDb.loadAll(semester.studentId, semester.classId).filter { it.isNotEmpty() }
}
}

View File

@ -0,0 +1,27 @@
package io.github.wulkanowy.data.repositories.teacher
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Teacher
import io.github.wulkanowy.sdk.Sdk
import io.reactivex.Single
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class TeacherRemote @Inject constructor(private val sdk: Sdk) {
fun getTeachers(semester: Semester): Single<List<Teacher>> {
return sdk.switchDiary(semester.diaryId, semester.schoolYear).getTeachers(semester.semesterId)
.map { teachers ->
teachers.map {
Teacher(
studentId = semester.studentId,
name = it.name,
subject = it.subject,
shortName = it.short,
classId = semester.classId
)
}
}
}
}

View File

@ -0,0 +1,34 @@
package io.github.wulkanowy.data.repositories.teacher
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Teacher
import io.github.wulkanowy.utils.uniqueSubtract
import io.reactivex.Single
import java.net.UnknownHostException
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class TeacherRepository @Inject constructor(
private val settings: InternetObservingSettings,
private val local: TeacherLocal,
private val remote: TeacherRemote
) {
fun getTeachers(semester: Semester, forceRefresh: Boolean = false): Single<List<Teacher>> {
return local.getTeachers(semester).filter { !forceRefresh }
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
.flatMap {
if (it) remote.getTeachers(semester)
else Single.error(UnknownHostException())
}.flatMap { new ->
local.getTeachers(semester).toSingle(emptyList())
.doOnSuccess { old ->
local.deleteTeachers(old.uniqueSubtract(new))
local.saveTeachers(new.uniqueSubtract(old))
}
}.flatMap { local.getTeachers(semester).toSingle(emptyList()) })
}
}

View File

@ -1,30 +1,27 @@
package io.github.wulkanowy.data.repositories.timetable package io.github.wulkanowy.data.repositories.timetable
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Timetable import io.github.wulkanowy.data.db.entities.Timetable
import io.github.wulkanowy.utils.toLocalDate import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.utils.toLocalDateTime
import io.reactivex.Single import io.reactivex.Single
import org.threeten.bp.LocalDate import org.threeten.bp.LocalDate
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class TimetableRemote @Inject constructor(private val api: Api) { class TimetableRemote @Inject constructor(private val sdk: Sdk) {
fun getTimetable(semester: Semester, startDate: LocalDate, endDate: LocalDate): Single<List<Timetable>> { fun getTimetable(semester: Semester, startDate: LocalDate, endDate: LocalDate): Single<List<Timetable>> {
return Single.just(api.apply { diaryId = semester.diaryId }) return sdk.switchDiary(semester.diaryId, semester.schoolYear).getTimetable(startDate, endDate)
.flatMap { it.getTimetable(startDate, endDate) }
.map { lessons -> .map { lessons ->
lessons.map { lessons.map {
Timetable( Timetable(
studentId = semester.studentId, studentId = semester.studentId,
diaryId = semester.diaryId, diaryId = semester.diaryId,
number = it.number, number = it.number,
start = it.start.toLocalDateTime(), start = it.start,
end = it.end.toLocalDateTime(), end = it.end,
date = it.date.toLocalDate(), date = it.date,
subject = it.subject, subject = it.subject,
subjectOld = it.subjectOld, subjectOld = it.subjectOld,
group = it.group, group = it.group,

View File

@ -36,7 +36,7 @@ class TimetableRepository @Inject constructor(
old.singleOrNull { new.start == it.start }?.let { old -> old.singleOrNull { new.start == it.start }?.let { old ->
return@map new.copy( return@map new.copy(
room = if (new.room.isEmpty()) old.room else new.room, room = if (new.room.isEmpty()) old.room else new.room,
teacher = if (new.teacher.isEmpty() && !new.changes) old.teacher else new.teacher teacher = if (new.teacher.isEmpty() && !new.changes && !old.changes) old.teacher else new.teacher
) )
} }
} }

View File

@ -2,6 +2,7 @@ package io.github.wulkanowy.di
import android.appwidget.AppWidgetManager import android.appwidget.AppWidgetManager
import android.content.Context import android.content.Context
import com.yariksoffice.lingver.Lingver
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
@ -32,4 +33,8 @@ internal class AppModule {
@Singleton @Singleton
@Provides @Provides
fun provideAppInfo() = AppInfo() fun provideAppInfo() = AppInfo()
@Singleton
@Provides
fun provideLingver() = Lingver.getInstance()
} }

View File

@ -21,6 +21,7 @@ import io.github.wulkanowy.services.sync.works.LuckyNumberWork
import io.github.wulkanowy.services.sync.works.MessageWork import io.github.wulkanowy.services.sync.works.MessageWork
import io.github.wulkanowy.services.sync.works.NoteWork import io.github.wulkanowy.services.sync.works.NoteWork
import io.github.wulkanowy.services.sync.works.RecipientWork import io.github.wulkanowy.services.sync.works.RecipientWork
import io.github.wulkanowy.services.sync.works.TeacherWork
import io.github.wulkanowy.services.sync.works.TimetableWork import io.github.wulkanowy.services.sync.works.TimetableWork
import io.github.wulkanowy.services.sync.works.Work import io.github.wulkanowy.services.sync.works.Work
import io.github.wulkanowy.services.widgets.TimetableWidgetService import io.github.wulkanowy.services.widgets.TimetableWidgetService
@ -28,17 +29,15 @@ import javax.inject.Singleton
@Suppress("unused") @Suppress("unused")
@AssistedModule @AssistedModule
@Module(includes = [AssistedInject_ServicesModule::class]) @Module(includes = [AssistedInject_ServicesModule::class, ServicesModule.Static::class])
abstract class ServicesModule { abstract class ServicesModule {
@Module @Module
companion object { object Static {
@JvmStatic
@Provides @Provides
fun provideWorkManager(context: Context) = WorkManager.getInstance(context) fun provideWorkManager(context: Context) = WorkManager.getInstance(context)
@JvmStatic
@Singleton @Singleton
@Provides @Provides
fun provideNotificationManager(context: Context) = NotificationManagerCompat.from(context) fun provideNotificationManager(context: Context) = NotificationManagerCompat.from(context)
@ -75,6 +74,10 @@ abstract class ServicesModule {
@IntoSet @IntoSet
abstract fun provideTimetableWork(work: TimetableWork): Work abstract fun provideTimetableWork(work: TimetableWork): Work
@Binds
@IntoSet
abstract fun provideTeacherWork(work: TeacherWork): Work
@Binds @Binds
@IntoSet @IntoSet
abstract fun provideLuckyNumberWork(work: LuckyNumberWork): Work abstract fun provideLuckyNumberWork(work: LuckyNumberWork): Work

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