Compare commits

...

84 Commits
0.6.2 ... 0.7.3

Author SHA1 Message Date
c2ab53cfeb Version 0.7.3 2019-03-26 19:46:59 +01:00
87268b3ef6 Fix rejected execution in sync worker (#305) 2019-03-26 16:47:14 +01:00
b3cd7e8ac1 Fix undeliverable network exceptions (#306)
* Remove unnecessary this
2019-03-26 14:32:23 +01:00
5a997dacb7 Version 0.7.2 2019-03-24 22:42:09 +01:00
ed9458d9a5 Fix more than one current semester in database (#304) 2019-03-24 20:21:05 +01:00
3656d3161f Fix crash on duplicate items (#303) 2019-03-24 17:31:39 +01:00
d178c15d2f Update dependencies (#302) 2019-03-24 16:03:51 +01:00
1f65b8465e Add logging to sync worker (#300) 2019-03-23 18:35:56 +01:00
6bb03b3be8 Fix day navigation unevenition (#301) 2019-03-23 17:29:34 +01:00
68b9847927 Fix reselecting root fragments (#299) 2019-03-23 16:35:33 +01:00
e1a83927c4 Fix reset button in timetable widget (#298) 2019-03-23 14:44:52 +01:00
fc9981aa5d Fix issues when loading lucky number (#297) 2019-03-23 13:01:01 +01:00
2d6610e05c Set max concurrency in sync worker (#296) 2019-03-23 01:12:17 +01:00
316cd2f7f9 Add checking current student in background services (#295) 2019-03-23 00:37:13 +01:00
36785f019a Fix restoring the grade fragment (#293) 2019-03-22 23:54:58 +01:00
4b78862486 Remove retry sync work when completed lessons is disabled (#294) 2019-03-22 23:41:41 +01:00
20d0abba29 Fix empty container id in grade fragemnt adapter (#289) 2019-03-21 22:34:41 +01:00
5add95ece1 Version 0.7.1 2019-03-20 21:02:09 +01:00
575e244b3a Add swipe refresh to grade fragment (#287) 2019-03-20 20:45:26 +01:00
8db73e9459 Fix the application finish after selecting an account (#286) 2019-03-19 18:14:55 +01:00
040857ba20 Change grade weightValue type to double (#285) 2019-03-19 13:23:52 +01:00
4b0f0de52c Version 0.7.0 2019-03-17 21:20:37 +01:00
ba76453e45 Add replying to messages (#263) 2019-03-17 21:02:41 +01:00
824ed3f282 Centre the login form (#283) 2019-03-17 19:57:25 +01:00
d27d069ce2 Change homework view to weekly (#284) 2019-03-17 00:17:16 +01:00
38aa26a3ff Add homepage button in about fragment (#280) 2019-03-16 14:22:51 +01:00
be807cb6c8 Change settings for checking the internet connection (#282) 2019-03-15 21:33:14 +01:00
35f1fe8d61 Follow current grade scheme in stats chart (#277) 2019-03-12 17:34:04 +01:00
2621e5680d Improve the display of changes in the timetable (#275)
Closes #264
2019-03-11 20:56:47 +01:00
475e7dd6a3 Update dependencies (#274) 2019-03-10 20:18:40 +01:00
feb38b97e4 Change login progress bars (#272) 2019-03-10 11:57:11 +01:00
f773310cdb Disable swipe to refresh on data loading (#270) 2019-03-09 21:40:20 +01:00
f21feabc49 Add debug notification for worker (#271) 2019-03-09 20:34:30 +01:00
ca23f92096 Add missing text when no grade description (#269) 2019-03-09 17:16:30 +01:00
919680c766 Migration to WorkManager (#254)
Closes #241
2019-03-09 10:13:36 +01:00
722f8d691a Fix timetable widget automatic day switching (#267) 2019-03-07 16:38:34 +01:00
4f0021919c Fix grade stats loading issues (#266) 2019-03-07 13:08:59 +01:00
1b7db4bfbb Mitigate disappearing room numbers in timetable (#265) 2019-03-07 13:08:11 +01:00
dcab8df4b9 Add grade statistics (#251) 2019-03-04 12:13:37 +01:00
cae4f140e6 Add option to change grade (background) color scheme (#259) 2019-03-03 15:11:20 +01:00
1b30b00bb8 Settings rename view section (#262) 2019-03-02 19:55:32 +01:00
514d1e11aa Update grade colors (#231) 2019-03-02 19:41:38 +01:00
66bd566526 Update login error message (#260) 2019-03-02 19:18:26 +01:00
e910c7a48e Mitigate notifications from old grades (#258)
Fixes #257
2019-03-02 19:15:37 +01:00
f8ee5cb062 Add lucky number logging (#256) 2019-02-24 19:23:03 +01:00
c72c301039 Add sending messages (#232) 2019-02-24 15:11:32 +01:00
5ba12cf8c6 Fill login credentials with default values upon fakelog selection (#255)
Resolves #245
2019-02-23 14:39:22 +01:00
82d7cf94e8 Mark as read items older than student registration date (#253) 2019-02-20 15:34:24 +01:00
c365564a77 Login form style fix (#252) 2019-02-17 19:15:26 +01:00
5526691cb6 Fix timetable widget crash on update (#250) 2019-02-17 17:32:22 +01:00
1d7585071d Update login form to Material Design 2 (#229) 2019-02-17 00:42:09 +01:00
11b6c00e4a Entities unification (#248)
* Remove default entieties params

* Change var to vals

* Fix indent in data classes

* Change message unread to val

* Make all fields in Message non-nullable

* Add destructive db migrations #246

* Fix password decrypting

* Fix tests

* Fix student logout

* Use orEmpty() on nullable strings

* Use var in Student password and Message unread
2019-02-16 21:20:23 +01:00
c56cfec564 Apply ripple effect on grade details header only if item is expandable (#239)
Resolves #234
2019-02-14 22:23:52 +01:00
f305a7a599 Sort repositories (#244) 2019-02-13 21:44:40 +01:00
ad9b6d42f0 Fix no current student (#243) 2019-02-13 20:49:19 +01:00
297502056c Add completed lessons (#236) 2019-02-13 19:21:27 +01:00
52ed7dcb6c Fix lucky number crash (#242) 2019-02-13 14:10:21 +01:00
9fcf245ecd Fix uninitialized fragment after restoring the activity (#237) 2019-02-12 00:41:02 +01:00
1b1f2ae3bb Split login form for two fragments (#230) 2019-02-11 02:04:24 +01:00
2f87779647 Add Firebase Analytics for the loaded lucky number (#233) 2019-02-05 18:18:49 +01:00
79093ca6f2 Merge branch '0.6.x' 2019-01-26 00:04:11 +01:00
7f162441e2 Version 0.6.6 2019-01-25 22:12:19 +01:00
4da812af39 Add lucky numbers (#216) 2019-01-25 20:54:27 +01:00
43f6048c27 Upgrade to Gradle Play Publisher v2 (#228) 2019-01-25 20:41:03 +01:00
ffc2ef9a4e Remove renaming source file in R8 (#227) 2019-01-25 19:20:13 +01:00
d3c13b8fc3 Fix empty fragment list in fragment manager (#226) 2019-01-24 21:16:22 +01:00
c78fb83774 Fix receiving a lot of notifications after turning them off for a while (#225) 2019-01-24 18:32:51 +01:00
941765a3a3 Fix empty Maybe in student repository (#224) 2019-01-23 18:28:51 +01:00
189830e0f4 Version 0.6.5 2019-01-20 23:38:02 +01:00
2061d6408f Change icon of semester switch (#223) 2019-01-20 23:36:16 +01:00
e29886560e Disable obfuscate in R8 (#222) 2019-01-20 22:43:50 +01:00
20d9313257 Version 0.6.4 2019-01-20 15:39:11 +01:00
8476f0e62e Update dependencies (#221) 2019-01-20 15:00:33 +01:00
a174ae998d Add api initialization to the message repository (#220) 2019-01-20 14:16:24 +01:00
c5bab52fa2 Add more logging (#219) 2019-01-19 23:15:14 +01:00
e6d60e670e Fix crash on duplicate notes (#218) 2019-01-18 19:10:14 +01:00
c0ddd82e03 Fix exam_no_items english translation (#217)
Changed `exam_no_items` from **No exams in this week** to **No exams this week**
2019-01-18 12:41:11 +01:00
28f1430be0 Fix crash on Meizu devices (#215) 2019-01-13 23:53:01 +01:00
840b21a213 Fix dialog state (#214) 2019-01-13 23:25:07 +01:00
65230a31ec Version 0.6.3 2019-01-12 14:41:23 +01:00
c2bcbfaaa9 Add grade id to equals (#213) 2019-01-12 14:16:59 +01:00
c3d354cd5b Add chucker okhttp inspector (#205) 2019-01-10 17:10:10 +01:00
ed49eb4c9c Fix stable id in grade fragment (#211) 2019-01-09 17:30:31 +01:00
7d1866c304 Fix NPE on error dialog (#212) 2019-01-09 17:29:55 +01:00
374 changed files with 8447 additions and 2520 deletions

View File

@ -159,7 +159,7 @@ jobs:
openssl aes-256-cbc -d -in ./app/upload-key-encrypted.jks -k $ENCRYPT_KEY >> ./app/upload-key.jks
- run:
name: Publish release
command: ./gradlew publishRelease --no-daemon --stacktrace --console=plain -PenableCrashlytics -PdisablePreDex
command: ./gradlew publish --no-daemon --stacktrace --console=plain -PenableCrashlytics -PdisablePreDex
workflows:
version: 2

View File

@ -19,7 +19,7 @@
<option name="CONTINUATION_INDENT_IN_SUPERTYPE_LISTS" value="false" />
<option name="CONTINUATION_INDENT_IN_IF_CONDITIONS" value="false" />
<option name="CONTINUATION_INDENT_IN_ELVIS" value="false" />
<option name="WRAP_EXPRESSION_BODY_FUNCTIONS" value="1" />
<option name="WRAP_ELVIS_EXPRESSIONS" value="0" />
</JetCodeStyleSettings>
<Objective-C-extensions>
<file>

View File

@ -11,6 +11,11 @@ cache:
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/
#branches:
# only:
# - master
# - 0.7.x
android:
licenses:
- android-sdk-preview-license-.+
@ -41,7 +46,7 @@ before_script:
- "curl -H 'Cache-Control: no-cache' https://raw.githubusercontent.com/fossas/fossa-cli/master/install.sh | sudo bash"
script:
- ./gradlew build -x test -x lint -x fabricGenerateResourcesRelease -x packageRelease --stacktrace --daemon
- ./gradlew dependencies --stacktrace --daemon
- fossa --no-ansi || true
- ./gradlew lint -x fabricGenerateResourcesRelease --stacktrace --daemon
- ./gradlew test -x fabricGenerateResourcesRelease --stacktrace --daemon
@ -56,7 +61,7 @@ script:
gpg --yes --batch --passphrase=$SERVICES_ENCRYPT_KEY ./app/src/release/google-services.json.gpg;
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/key.p12.gpg;
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/upload-key.jks.gpg;
./gradlew publishRelease -PenableCrashlytics --stacktrace;
./gradlew publish -PenableCrashlytics --stacktrace;
fi
after_success:

View File

@ -6,12 +6,12 @@
[![Codecov](https://img.shields.io/codecov/c/github/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://codecov.io/gh/wulkanowy/wulkanowy)
[![BCH compliance](https://bettercodehub.com/edge/badge/wulkanowy/wulkanowy?branch=master)](https://bettercodehub.com/)
[![Sonarcloud](https://sonarcloud.io/api/project_badges/measure?project=io.github.wulkanowy%3Aapp&metric=sqale_rating)](https://sonarcloud.io/dashboard?id=io.github.wulkanowy%3Aapp)
[![FOSSA Status](https://app.fossa.io/api/projects/custom%2B5644%2Fgit%40github.com%3Awulkanowy%2Fwulkanowy.git.svg?type=shield)](https://app.fossa.io/projects/custom%2B5644%2Fgit%40github.com%3Awulkanowy%2Fwulkanowy.git?ref=badge_shield)
[![FOSSA Status](https://app.fossa.com/api/projects/custom%2B5644%2Fgithub.com%2Fwulkanowy%2Fwulkanowy.svg?type=shield)](https://app.fossa.com/projects/custom%2B5644%2Fgithub.com%2Fwulkanowy%2Fwulkanowy?ref=badge_shield)
[![Discord](https://img.shields.io/discord/390889354199040011.svg?style=flat-square)](https://discord.gg/vccAQBr)
[Pobierz wersję beta z Google Play](https://play.google.com/store/apps/details?id=io.github.wulkanowy&amp;utm_source=vcs)
[Pobierz wersję DEV](https://bitrise-redirector.herokuapp.com/v0.1/apps/daeff1893f3c8128/builds/master/artifacts/0)
[Pobierz wersję DEV](https://bitrise-redirector.herokuapp.com/v0.1/apps/f841f20d8f8b1dc8/builds/master/artifacts/0)
[(Więcej wersji DEV)](https://wulkanowy.github.io/dev.html)
Androidowy klient dziennika VULCAN UONET+.
@ -19,4 +19,4 @@ Androidowy klient dziennika VULCAN UONET+.
## License
[![FOSSA Status](https://app.fossa.io/api/projects/custom%2B5644%2Fgit%40github.com%3Awulkanowy%2Fwulkanowy.git.svg?type=large)](https://app.fossa.io/projects/custom%2B5644%2Fgit%40github.com%3Awulkanowy%2Fwulkanowy.git?ref=badge_large)
[![FOSSA Status](https://app.fossa.com/api/projects/custom%2B5644%2Fgithub.com%2Fwulkanowy%2Fwulkanowy.svg?type=large)](https://app.fossa.com/projects/custom%2B5644%2Fgithub.com%2Fwulkanowy%2Fwulkanowy?ref=badge_large)

View File

@ -11,24 +11,16 @@ android {
compileSdkVersion 28
buildToolsVersion '28.0.3'
playAccountConfigs {
defaultAccountConfig {
serviceAccountEmail = System.getenv("PLAY_SERVICE_ACCOUNT_EMAIL")
pk12File = file('key.p12')
}
}
defaultConfig {
applicationId "io.github.wulkanowy"
testApplicationId "io.github.tests.wulkanowy"
minSdkVersion 15
targetSdkVersion 28
versionCode 21
versionName "0.6.2"
versionCode 29
versionName "0.7.3"
multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
playAccountConfig = playAccountConfigs.defaultAccountConfig
manifestPlaceholders = [
fabric_api_key: System.getenv("FABRIC_API_KEY") ?: "null",
crashlytics_enabled: project.hasProperty("enableCrashlytics")
@ -48,7 +40,6 @@ android {
release {
buildConfigField "boolean", "CRASHLYTICS_ENABLED", "true"
minifyEnabled true
useProguard false
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
@ -66,6 +57,11 @@ android {
lintOptions {
disable 'HardwareIds'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
androidExtensions {
@ -73,62 +69,74 @@ androidExtensions {
}
play {
serviceAccountEmail = System.getenv("PLAY_SERVICE_ACCOUNT_EMAIL") ?: "jan@fakelog.cf"
serviceAccountCredentials = file('key.p12')
defaultToAppBundles = true
track = 'alpha'
uploadImages = false
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
implementation('io.github.wulkanowy:api:0.6.2') { exclude module: "threetenbp" }
implementation('io.github.wulkanowy:api:0.7.3') { exclude module: "threetenbp" }
implementation "androidx.legacy:legacy-support-v4:1.0.0"
implementation "androidx.appcompat:appcompat:1.0.2"
implementation "androidx.cardview:cardview:1.0.0"
implementation "com.google.android.material:material:1.0.0"
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.multidex:multidex:2.0.1'
implementation "androidx.work:work-runtime:2.0.0"
implementation "androidx.work:work-rxjava2:2.0.0"
implementation "androidx.room:room-runtime:2.1.0-alpha06"
implementation "androidx.room:room-rxjava2:2.1.0-alpha06"
kapt "androidx.room:room-compiler:2.1.0-alpha06"
implementation 'com.takisoft.preferencex:preferencex:1.0.0'
implementation "com.mikepenz:aboutlibraries:6.2.0"
implementation "com.firebase:firebase-jobdispatcher:0.8.5"
implementation "com.google.dagger:dagger-android-support:2.19"
kapt "com.google.dagger:dagger-compiler:2.19"
kapt "com.google.dagger:dagger-android-processor:2.19"
implementation 'com.squareup.inject:assisted-inject-annotations-dagger2:0.3.3'
kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.3.3'
implementation "androidx.room:room-runtime:2.1.0-alpha03"
implementation "androidx.room:room-rxjava2:2.1.0-alpha03"
kapt "androidx.room:room-compiler:2.1.0-alpha03"
implementation "com.google.dagger:dagger-android-support:2.21"
kapt "com.google.dagger:dagger-compiler:2.21"
kapt "com.google.dagger:dagger-android-processor:2.21"
implementation "eu.davidea:flexible-adapter:5.1.0"
implementation "eu.davidea:flexible-adapter-ui:1.0.0"
implementation "com.aurelhubert:ahbottomnavigation:2.3.4"
implementation 'com.ncapdevi:frag-nav:3.2.0'
implementation "com.aurelhubert:ahbottomnavigation:2.2.0"
implementation 'com.ncapdevi:frag-nav:3.0.0'
implementation 'com.github.wulkanowy:MaterialChipsInput:b72fd0ee6f'
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
implementation 'com.github.pwittchen:reactivenetwork-rx2:3.0.1'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
implementation "io.reactivex.rxjava2:rxjava:2.2.4"
implementation "com.jakewharton.threetenabp:threetenabp:1.1.0"
implementation 'com.github.pwittchen:reactivenetwork-rx2:3.0.2'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation "io.reactivex.rxjava2:rxjava:2.2.7"
implementation "com.jakewharton.threetenabp:threetenabp:1.2.0"
implementation "com.jakewharton.timber:timber:4.7.1"
implementation "at.favre.lib:slf4j-timber:1.0.1"
implementation "com.mikepenz:aboutlibraries:6.2.3"
implementation 'com.google.firebase:firebase-core:16.0.6'
implementation 'com.crashlytics.sdk.android:crashlytics:2.9.8'
implementation 'com.google.firebase:firebase-core:16.0.8'
implementation 'com.crashlytics.sdk.android:crashlytics:2.9.9'
debugImplementation "com.amitshekhar.android:debug-db:1.0.4"
releaseImplementation 'fr.o80.chucker:library-no-op:2.0.4'
debugImplementation 'fr.o80.chucker:library:2.0.4'
debugImplementation "com.amitshekhar.android:debug-db:1.0.6"
testImplementation "junit:junit:4.12"
testImplementation "io.mockk:mockk:1.8.13.kotlin13"
testImplementation "org.mockito:mockito-inline:2.23.4"
testImplementation "io.mockk:mockk:1.9.2"
testImplementation "org.mockito:mockito-inline:2.25.1"
testImplementation 'org.threeten:threetenbp:1.3.8'
androidTestImplementation 'androidx.test:core:1.1.0'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
androidTestImplementation 'org.mockito:mockito-android:2.23.4'
androidTestImplementation "io.mockk:mockk-android:1.9.2"
androidTestImplementation 'org.mockito:mockito-android:2.25.1'
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
}

View File

@ -1,7 +1,7 @@
apply plugin: "jacoco"
jacoco {
toolVersion "0.8.2"
toolVersion "0.8.3"
reportsDir = file("$buildDir/reports")
}

View File

@ -5,6 +5,7 @@
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
-dontpreverify
-dontobfuscate
-allowaccessmodification
-repackageclasses ''
-verbose
@ -13,7 +14,6 @@
#Config for anallitycs
-keepattributes *Annotation*
-keepattributes SourceFile,LineNumberTable
-renamesourcefileattribute SourceFile
-keep class com.crashlytics.** {*;}
-keep public class * extends java.lang.Exception
-dontwarn com.crashlytics.**
@ -32,5 +32,8 @@
-dontwarn rx.internal.util.**
-dontwarn sun.misc.Unsafe
#Config for MPAndroidChart
-keep class com.github.mikephil.charting.** { *; }
#Config for API
-keep class io.github.wulkanowy.api.** {*;}

View File

@ -0,0 +1,19 @@
package io.github.wulkanowy.data.repositories
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingStrategy
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.error.ErrorHandler
import io.reactivex.Observable
import io.reactivex.Single
class TestInternetObservingStrategy : InternetObservingStrategy {
override fun checkInternetConnectivity(host: String?, port: Int, timeoutInMs: Int, httpResponse: Int, errorHandler: ErrorHandler?): Single<Boolean> {
return Single.just(true)
}
override fun observeInternetConnectivity(initialIntervalInMs: Int, intervalInMs: Int, host: String?, port: Int, timeoutInMs: Int, httpResponse: Int, errorHandler: ErrorHandler?): Observable<Boolean> {
return Observable.just(true)
}
override fun getDefaultPingHost() = "localhost"
}

View File

@ -1,4 +1,4 @@
package io.github.wulkanowy.data.repositories.local
package io.github.wulkanowy.data.repositories.attendance
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
@ -34,13 +34,13 @@ class AttendanceLocalTest {
@Test
fun saveAndReadTest() {
attendanceLocal.saveAttendance(listOf(
Attendance(1, 2, LocalDate.of(2018, 9, 10), 0, "", ""),
Attendance(1, 2, LocalDate.of(2018, 9, 14), 0, "", ""),
Attendance(1, 2, LocalDate.of(2018, 9, 17), 0, "", "")
Attendance(1, 2, LocalDate.of(2018, 9, 10), 0, "", "", false, false, false, false, false, false),
Attendance(1, 2, LocalDate.of(2018, 9, 14), 0, "", "", false, false, false, false, false, false),
Attendance(1, 2, LocalDate.of(2018, 9, 17), 0, "", "", false, false, false, false, false, false)
))
val attendance = attendanceLocal
.getAttendance(Semester(1, 1, 2, "", 3, 1),
.getAttendance(Semester(1, 2, "", 1, 3, true, 1, 1),
LocalDate.of(2018, 9, 10),
LocalDate.of(2018, 9, 14)
)

View File

@ -0,0 +1,57 @@
package io.github.wulkanowy.data.repositories.completedlessons
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import io.github.wulkanowy.data.db.AppDatabase
import io.github.wulkanowy.data.db.entities.CompletedLesson
import io.github.wulkanowy.data.db.entities.Semester
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.threeten.bp.LocalDate
import kotlin.test.assertEquals
@RunWith(AndroidJUnit4::class)
class CompletedLessonsLocalTest {
private lateinit var completedLessonsLocal: CompletedLessonsLocal
private lateinit var testDb: AppDatabase
@Before
fun createDb() {
testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
.build()
completedLessonsLocal = CompletedLessonsLocal(testDb.completedLessonsDao)
}
@After
fun closeDb() {
testDb.close()
}
@Test
fun saveAndReadTest() {
completedLessonsLocal.saveCompletedLessons(listOf(
getCompletedLesson(LocalDate.of(2018, 9, 10), 1),
getCompletedLesson(LocalDate.of(2018, 9, 14), 2),
getCompletedLesson(LocalDate.of(2018, 9, 17), 3)
))
val completed = completedLessonsLocal
.getCompletedLessons(Semester(1, 2, "", 1, 3, true, 1, 1),
LocalDate.of(2018, 9, 10),
LocalDate.of(2018, 9, 14)
)
.blockingGet()
assertEquals(2, completed.size)
assertEquals(completed[0].date, LocalDate.of(2018, 9, 10))
assertEquals(completed[1].date, LocalDate.of(2018, 9, 14))
}
private fun getCompletedLesson(date: LocalDate, number: Int): CompletedLesson {
return CompletedLesson(1, 2, date, number, "", "", "", "", "", "", "")
}
}

View File

@ -1,4 +1,4 @@
package io.github.wulkanowy.data.repositories.local
package io.github.wulkanowy.data.repositories.exam
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
@ -40,7 +40,7 @@ class ExamLocalTest {
))
val exams = examLocal
.getExams(Semester(1, 1, 2, "", 3, 1),
.getExams(Semester(1, 2, "", 1, 3, true, 1, 1),
LocalDate.of(2018, 9, 10),
LocalDate.of(2018, 9, 14)
)

View File

@ -0,0 +1,50 @@
package io.github.wulkanowy.data.repositories.grade
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import io.github.wulkanowy.data.db.AppDatabase
import io.github.wulkanowy.data.db.entities.Semester
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.threeten.bp.LocalDate
import kotlin.test.assertEquals
@RunWith(AndroidJUnit4::class)
class GradeLocalTest {
private lateinit var gradeLocal: GradeLocal
private lateinit var testDb: AppDatabase
@Before
fun createDb() {
testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
.build()
gradeLocal = GradeLocal(testDb.gradeDao)
}
@After
fun closeDb() {
testDb.close()
}
@Test
fun saveAndReadTest() {
gradeLocal.saveGrades(listOf(
createGradeLocal(5, 3.0, LocalDate.of(2018, 9, 10), "", 1),
createGradeLocal(4, 4.0, LocalDate.of(2019, 2, 27), "", 2),
createGradeLocal(3, 5.0, LocalDate.of(2019, 2, 28), "", 2)
))
val grades = gradeLocal
.getGrades(Semester(1, 2, "", 2, 3, true, 1, 1))
.blockingGet()
assertEquals(2, grades.size)
assertEquals(grades[0].date, LocalDate.of(2019, 2, 27))
assertEquals(grades[1].date, LocalDate.of(2019, 2, 28))
}
}

View File

@ -0,0 +1,112 @@
package io.github.wulkanowy.data.repositories.grade
import android.os.Build.VERSION_CODES.P
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SdkSuppress
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.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.repositories.TestInternetObservingStrategy
import io.mockk.MockKAnnotations
import io.mockk.every
import io.mockk.impl.annotations.MockK
import io.mockk.impl.annotations.SpyK
import io.reactivex.Single
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.threeten.bp.LocalDate.of
import org.threeten.bp.LocalDateTime
import kotlin.test.assertFalse
import kotlin.test.assertTrue
import io.github.wulkanowy.api.grades.Grade as GradeApi
@SdkSuppress(minSdkVersion = P)
@RunWith(AndroidJUnit4::class)
class GradeRepositoryTest {
@SpyK
private var mockApi = Api()
private val settings = InternetObservingSettings.builder()
.strategy(TestInternetObservingStrategy())
.build()
@MockK
private lateinit var semesterMock: Semester
@MockK
private lateinit var studentMock: Student
private lateinit var gradeRemote: GradeRemote
private lateinit var gradeLocal: GradeLocal
private lateinit var testDb: AppDatabase
@Before
fun initApi() {
MockKAnnotations.init(this)
testDb = Room.inMemoryDatabaseBuilder(getApplicationContext(), AppDatabase::class.java).build()
gradeLocal = GradeLocal(testDb.gradeDao)
gradeRemote = GradeRemote(mockApi)
every { mockApi.diaryId } returns 1
every { studentMock.registrationDate } returns LocalDateTime.of(2019, 2, 27, 12, 0)
every { semesterMock.studentId } returns 1
every { semesterMock.semesterId } returns 1
every { semesterMock.diaryId } returns 1
}
@After
fun closeDb() {
testDb.close()
}
@Test
fun markOlderThanRegisterDateAsRead() {
every { mockApi.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, 26), "przed zalogowanie w aplikacji"),
createGradeApi(5, 4.0, of(2019, 2, 27), "Ocena z dnia logowania"),
createGradeApi(5, 4.0, of(2019, 2, 28), "Ocena jeszcze nowsza")
))
val grades = GradeRepository(settings, gradeLocal, gradeRemote)
.getGrades(studentMock, semesterMock, true).blockingGet().sortedByDescending { it.date }
assertFalse { grades[0].isRead }
assertFalse { grades[1].isRead }
assertTrue { grades[2].isRead }
assertTrue { grades[3].isRead }
}
@Test
fun mitigateOldGradesNotifications() {
gradeLocal.saveGrades(listOf(
createGradeLocal(5, 3.0, of(2019, 2, 25), "Jedna ocena"),
createGradeLocal(4, 4.0, of(2019, 2, 26), "Druga"),
createGradeLocal(3, 5.0, of(2019, 2, 27), "Trzecia")
))
every { mockApi.getGrades(1) } returns Single.just(listOf(
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(3, 4.0, of(2019, 2, 27), "Ta jest z tego samego dnia co ostatnia lokalnie"),
createGradeApi(2, 5.0, of(2019, 2, 28), "Ta jest już w ogóle nowa")
))
val grades = GradeRepository(settings, gradeLocal, gradeRemote)
.getGrades(studentMock, semesterMock, true).blockingGet().sortedByDescending { it.date }
assertFalse { grades[0].isRead }
assertFalse { grades[1].isRead }
assertTrue { grades[2].isRead }
assertTrue { grades[3].isRead }
}
}

View File

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

View File

@ -0,0 +1,68 @@
package io.github.wulkanowy.data.repositories.gradestatistics
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import io.github.wulkanowy.data.db.AppDatabase
import io.github.wulkanowy.data.db.entities.GradeStatistics
import io.github.wulkanowy.data.db.entities.Semester
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import kotlin.test.assertEquals
@RunWith(AndroidJUnit4::class)
class GradeStatisticsLocalTest {
private lateinit var gradeStatisticsLocal: GradeStatisticsLocal
private lateinit var testDb: AppDatabase
@Before
fun createDb() {
testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
.build()
gradeStatisticsLocal = GradeStatisticsLocal(testDb.gradeStatistics)
}
@After
fun closeDb() {
testDb.close()
}
@Test
fun saveAndRead_subject() {
gradeStatisticsLocal.saveGradesStatistics(listOf(
getGradeStatistics("Matematyka", 2, 1),
getGradeStatistics("Fizyka", 1, 2)
))
val stats = gradeStatisticsLocal.getGradesStatistics(
Semester(2, 2, "", 1, 2, true, 1, 1), false,
"Matematyka"
).blockingGet()
assertEquals(1, stats.size)
assertEquals(stats[0].subject, "Matematyka")
}
@Test
fun saveAndRead_all() {
gradeStatisticsLocal.saveGradesStatistics(listOf(
getGradeStatistics("Matematyka", 2, 1),
getGradeStatistics("Chemia", 2, 1),
getGradeStatistics("Fizyka", 1, 2)
))
val stats = gradeStatisticsLocal.getGradesStatistics(
Semester(2, 2, "", 1, 2, true, 1, 1), false,
"Wszystkie"
).blockingGet()
assertEquals(1, stats.size)
assertEquals(stats[0].subject, "Wszystkie")
}
private fun getGradeStatistics(subject: String, studentId: Int, semesterId: Int): GradeStatistics {
return GradeStatistics(studentId, semesterId, subject, 5, 5, false)
}
}

View File

@ -0,0 +1,47 @@
package io.github.wulkanowy.data.repositories.luckynumber
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import io.github.wulkanowy.data.db.AppDatabase
import io.github.wulkanowy.data.db.entities.LuckyNumber
import io.github.wulkanowy.data.db.entities.Semester
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.threeten.bp.LocalDate
import kotlin.test.assertEquals
@RunWith(AndroidJUnit4::class)
class LuckyNumberLocalTest {
private lateinit var luckyNumberLocal: LuckyNumberLocal
private lateinit var testDb: AppDatabase
@Before
fun createDb() {
testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
.build()
luckyNumberLocal = LuckyNumberLocal(testDb.luckyNumberDao)
}
@After
fun closeDb() {
testDb.close()
}
@Test
fun saveAndReadTest() {
luckyNumberLocal.saveLuckyNumber(LuckyNumber(1, LocalDate.of(2019, 1, 20), 14))
val luckyNumber = luckyNumberLocal.getLuckyNumber(Semester(1, 1, "", 1, 3, true, 1, 1),
LocalDate.of(2019, 1, 20)
).blockingGet()
assertEquals(1, luckyNumber.studentId)
assertEquals(LocalDate.of(2019, 1, 20), luckyNumber.date)
assertEquals(14, luckyNumber.luckyNumber)
}
}

View File

@ -0,0 +1,60 @@
package io.github.wulkanowy.data.repositories.recipient
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import io.github.wulkanowy.data.db.AppDatabase
import io.github.wulkanowy.data.db.entities.Recipient
import io.github.wulkanowy.data.db.entities.ReportingUnit
import io.github.wulkanowy.data.db.entities.Student
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.threeten.bp.LocalDateTime
import kotlin.test.assertEquals
@RunWith(AndroidJUnit4::class)
class RecipientLocalTest {
private lateinit var recipientLocal: RecipientLocal
private lateinit var testDb: AppDatabase
@Before
fun createDb() {
testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
.build()
recipientLocal = RecipientLocal(testDb.recipientDao)
}
@After
fun closeDb() {
testDb.close()
}
@Test
fun saveAndReadTest() {
recipientLocal.saveRecipients(listOf(
Recipient(1, "2rPracownik", "Kowalski Jan", "Kowalski Jan [KJ] - Pracownik (Fake123456)", 3, 4, 2, "hash"),
Recipient(1, "3rPracownik", "Kowalska Karolina", "Kowalska Karolina [KK] - Pracownik (Fake123456)", 4, 4, 2, "hash"),
Recipient(1, "4rPracownik", "Krupa Stanisław", "Krupa Stanisław [KS] - Uczeń (Fake123456)", 5, 4, 1, "hash")
))
val recipients = recipientLocal.getRecipients(
Student("fakelog.cf", "AUTO", "", "", "", 1, "", "", "", true, LocalDateTime.now()),
2,
ReportingUnit(1, 4, "", 0, "", emptyList())
).blockingGet()
assertEquals(2, recipients.size)
assertEquals(1, recipients[0].studentId)
assertEquals("3rPracownik", recipients[1].realId)
assertEquals("Kowalski Jan", recipients[0].name)
assertEquals("Kowalska Karolina [KK] - Pracownik (Fake123456)", recipients[1].realName)
assertEquals(3, recipients[0].loginId)
assertEquals(4, recipients[1].unitId)
assertEquals(2, recipients[0].role)
assertEquals("hash", recipients[1].hash)
}
}

View File

@ -1,4 +1,4 @@
package io.github.wulkanowy.data.repositories.local
package io.github.wulkanowy.data.repositories.student
import android.content.Context
import androidx.room.Room
@ -11,6 +11,7 @@ import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.threeten.bp.LocalDateTime.now
import kotlin.test.assertEquals
@RunWith(AndroidJUnit4::class)
@ -28,7 +29,7 @@ class StudentLocalTest {
testDb = Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java)
.build()
sharedHelper = SharedPrefHelper(context.getSharedPreferences("TEST", Context.MODE_PRIVATE))
studentLocal = StudentLocal(testDb.studentDao, sharedHelper, context)
studentLocal = StudentLocal(testDb.studentDao, context)
}
@After
@ -38,9 +39,8 @@ class StudentLocalTest {
@Test
fun saveAndReadTest() {
studentLocal.saveStudent(Student(email = "test", password = "test123", schoolSymbol = "23", endpoint = "fakelog.cf", loginType = "AUTO", isCurrent = true))
studentLocal.saveStudent(Student(email = "test", password = "test123", schoolSymbol = "23", endpoint = "fakelog.cf", loginType = "AUTO", isCurrent = true, studentName = "", schoolName = "", studentId = 0, symbol = "", registrationDate = now()))
.blockingGet()
assert(studentLocal.isStudentSaved)
val student = studentLocal.getCurrentStudent(true).blockingGet()
assertEquals("23", student.schoolSymbol)

View File

@ -0,0 +1,45 @@
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.now
import io.github.wulkanowy.api.timetable.Timetable as TimetableRemote
import io.github.wulkanowy.data.db.entities.Timetable as TimetableLocal
fun createTimetableLocal(number: Int, start: LocalDateTime, room: String = "", subject: String = ""): TimetableLocal {
return TimetableLocal(
studentId = 1,
diaryId = 2,
number = number,
start = start,
end = now(),
date = start.toLocalDate(),
subject = subject,
subjectOld = "",
group = "",
room = room,
roomOld = "",
teacher = "",
teacherOld = "",
info = "",
changes = false,
canceled = false
)
}
fun createTimetableRemote(number: Int, start: LocalDateTime, room: String, subject: String = ""): TimetableRemote {
return TimetableRemote(
number = number,
start = start.toDate(),
end = start.plusMinutes(45).toDate(),
date = start.toLocalDate().toDate(),
subject = subject,
group = "",
room = room,
teacher = "",
info = "",
changes = false,
canceled = false
)
}

View File

@ -1,17 +1,16 @@
package io.github.wulkanowy.data.repositories.local
package io.github.wulkanowy.data.repositories.timetable
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import io.github.wulkanowy.data.db.AppDatabase
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Timetable
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.threeten.bp.LocalDate
import org.threeten.bp.LocalDateTime
import org.threeten.bp.LocalDateTime.of
import kotlin.test.assertEquals
@RunWith(AndroidJUnit4::class)
@ -23,7 +22,8 @@ class TimetableLocalTest {
@Before
fun createDb() {
testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java).build()
testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
.build()
timetableDb = TimetableLocal(testDb.timetableDao)
}
@ -35,19 +35,17 @@ class TimetableLocalTest {
@Test
fun saveAndReadTest() {
timetableDb.saveTimetable(listOf(
Timetable(1, 2, 1, LocalDateTime.now(), LocalDateTime.now(),
LocalDate.of(2018, 9, 10), "", "", "", "", ""),
Timetable(1, 2, 1, LocalDateTime.now(), LocalDateTime.now(),
LocalDate.of(2018, 9, 14), "", "", "", "", ""),
Timetable(1, 2, 1, LocalDateTime.now(), LocalDateTime.now(),
LocalDate.of(2018, 9, 17), "", "", "", "", "")
createTimetableLocal(1, of(2018, 9, 10, 0, 0, 0)),
createTimetableLocal(1, of(2018, 9, 14, 0, 0, 0)),
createTimetableLocal(1, of(2018, 9, 17, 0, 0, 0))
))
val exams = timetableDb.getTimetable(
Semester(0, 1, 2, "3", 1, 1),
LocalDate.of(2018, 9, 10),
LocalDate.of(2018, 9, 14)
Semester(1, 2, "", 1, 1, true, 1, 1),
LocalDate.of(2018, 9, 10),
LocalDate.of(2018, 9, 14)
).blockingGet()
assertEquals(2, exams.size)
assertEquals(exams[0].date, LocalDate.of(2018, 9, 10))
assertEquals(exams[1].date, LocalDate.of(2018, 9, 14))

View File

@ -0,0 +1,85 @@
package io.github.wulkanowy.data.repositories.timetable
import android.os.Build.VERSION_CODES.P
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SdkSuppress
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.entities.Semester
import io.github.wulkanowy.data.repositories.TestInternetObservingStrategy
import io.mockk.MockKAnnotations
import io.mockk.every
import io.mockk.impl.annotations.MockK
import io.mockk.impl.annotations.SpyK
import io.reactivex.Single
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.threeten.bp.LocalDate
import org.threeten.bp.LocalDateTime.of
import kotlin.test.assertEquals
@SdkSuppress(minSdkVersion = P)
@RunWith(AndroidJUnit4::class)
class TimetableRepositoryTest {
@SpyK
private var mockApi = Api()
private val settings = InternetObservingSettings.builder()
.strategy(TestInternetObservingStrategy())
.build()
@MockK
private lateinit var semesterMock: Semester
private lateinit var timetableRemote: TimetableRemote
private lateinit var timetableLocal: TimetableLocal
private lateinit var testDb: AppDatabase
@Before
fun initApi() {
MockKAnnotations.init(this)
testDb = Room.inMemoryDatabaseBuilder(getApplicationContext(), AppDatabase::class.java).build()
timetableLocal = TimetableLocal(testDb.timetableDao)
timetableRemote = TimetableRemote(mockApi)
every { semesterMock.studentId } returns 1
every { semesterMock.diaryId } returns 2
}
@After
fun closeDb() {
testDb.close()
}
@Test
fun copyDetailsToCompletedFromPrevious() {
timetableLocal.saveTimetable(listOf(
createTimetableLocal(1, of(2019, 3, 5, 8, 0), "123", "Przyroda"),
createTimetableLocal(1, of(2019, 3, 5, 8, 50), "321", "Religia"),
createTimetableLocal(1, of(2019, 3, 5, 9, 40), "213", "W-F")
))
every { mockApi.getTimetable(any(), any()) } returns Single.just(listOf(
createTimetableRemote(1, of(2019, 3, 5, 8, 0), "", "Przyroda"),
createTimetableRemote(1, of(2019, 3, 5, 8, 50), "", "Religia"),
createTimetableRemote(1, of(2019, 3, 5, 9, 40), "", "W-F")
))
val lessons = TimetableRepository(settings, timetableLocal, timetableRemote)
.getTimetable(semesterMock, LocalDate.of(2019, 3, 5), LocalDate.of(2019, 3, 5), true)
.blockingGet()
assertEquals(3, lessons.size)
assertEquals("123", lessons[0].room)
assertEquals("321", lessons[1].room)
assertEquals("213", lessons[2].room)
}
}

View File

@ -4,6 +4,8 @@
package="io.github.wulkanowy"
android:installLocation="internalOnly">
<uses-sdk tools:overrideLibrary="com.readystatesoftware.chuck" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
@ -18,14 +20,13 @@
android:supportsRtl="false"
android:theme="@style/WulkanowyTheme"
android:usesCleartextTraffic="true"
tools:ignore="GoogleAppIndexingWarning">
tools:ignore="GoogleAppIndexingWarning,UnusedAttribute">
<activity
android:name=".ui.modules.splash.SplashActivity"
android:screenOrientation="portrait"
android:theme="@style/WulkanowyTheme.SplashScreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
@ -39,20 +40,19 @@
android:configChanges="orientation|screenSize"
android:label="@string/main_title"
android:theme="@style/WulkanowyTheme.NoActionBar" />
<activity
android:name=".ui.modules.message.send.SendMessageActivity"
android:configChanges="orientation|screenSize"
android:label="@string/send_message_title"
android:theme="@style/WulkanowyTheme.NoActionBar" />
<service
android:name=".services.job.SyncWorker"
android:exported="false">
<intent-filter>
<action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE" />
</intent-filter>
</service>
<service
android:name=".services.widgets.TimetableWidgetService"
android:permission="android.permission.BIND_REMOTEVIEWS" />
<receiver
android:name=".ui.widgets.timetable.TimetableWidgetProvider"
android:exported="true"
android:label="@string/timetable_title">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
@ -62,6 +62,12 @@
android:resource="@xml/provider_widget_timetable" />
</receiver>
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="${applicationId}.workmanager-init"
android:exported="false"
tools:node="remove" />
<meta-data
android:name="io.fabric.ApiKey"
android:value="${fabric_api_key}" />

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View File

@ -3,6 +3,8 @@ package io.github.wulkanowy
import android.content.Context
import androidx.appcompat.app.AppCompatDelegate
import androidx.multidex.MultiDex
import androidx.work.Configuration
import androidx.work.WorkManager
import com.crashlytics.android.Crashlytics
import com.crashlytics.android.core.CrashlyticsCore
import com.jakewharton.threetenabp.AndroidThreeTen
@ -12,11 +14,16 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.utils.Log
import io.fabric.sdk.android.Fabric
import io.github.wulkanowy.BuildConfig.DEBUG
import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
import io.github.wulkanowy.di.DaggerAppComponent
import io.github.wulkanowy.services.sync.SyncWorkerFactory
import io.github.wulkanowy.utils.CrashlyticsTree
import io.github.wulkanowy.utils.DebugLogTree
import io.reactivex.exceptions.UndeliverableException
import io.reactivex.plugins.RxJavaPlugins
import timber.log.Timber
import java.io.IOException
import java.lang.Exception
import javax.inject.Inject
class WulkanowyApp : DaggerApplication() {
@ -24,6 +31,9 @@ class WulkanowyApp : DaggerApplication() {
@Inject
lateinit var prefRepository: PreferencesRepository
@Inject
lateinit var workerFactory: SyncWorkerFactory
override fun attachBaseContext(base: Context?) {
super.attachBaseContext(base)
MultiDex.install(this)
@ -35,6 +45,8 @@ class WulkanowyApp : DaggerApplication() {
initializeFabric()
if (DEBUG) enableDebugLog()
AppCompatDelegate.setDefaultNightMode(prefRepository.currentTheme)
WorkManager.initialize(this, Configuration.Builder().setWorkerFactory(workerFactory).build())
RxJavaPlugins.setErrorHandler(::onError)
}
private fun enableDebugLog() {
@ -49,6 +61,12 @@ class WulkanowyApp : DaggerApplication() {
Timber.plant(CrashlyticsTree())
}
private fun onError(t: Throwable) {
if (t is UndeliverableException && t.cause is IOException || t.cause is InterruptedException) {
Timber.e(t.cause, "An undeliverable error occurred")
} else throw t
}
override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
return DaggerAppComponent.builder().create(this)
}

View File

@ -14,14 +14,20 @@ class ApiHelper @Inject constructor(private val api: Api) {
symbol = student.symbol
schoolSymbol = student.schoolSymbol
studentId = student.studentId
useNewStudent = false
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) {
initApi(Student(email = email, password = password, symbol = symbol, endpoint = endpoint, loginType = "AUTO"))
api.apply {
this.email = email
this.password = password
this.symbol = symbol
host = URL(endpoint).run { host + ":$port".removeSuffix(":-1") }
ssl = endpoint.startsWith("https")
}
}
}

View File

@ -5,11 +5,15 @@ import android.content.SharedPreferences
import android.content.res.Resources
import androidx.preference.PreferenceManager
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.strategy.SocketInternetObservingStrategy
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.strategy.WalledGardenInternetObservingStrategy
import com.readystatesoftware.chuck.api.ChuckCollector
import com.readystatesoftware.chuck.api.ChuckInterceptor
import com.readystatesoftware.chuck.api.RetentionManager
import dagger.Module
import dagger.Provides
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.AppDatabase
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
import okhttp3.logging.HttpLoggingInterceptor
import okhttp3.logging.HttpLoggingInterceptor.Level.BASIC
import okhttp3.logging.HttpLoggingInterceptor.Level.NONE
@ -23,22 +27,32 @@ internal class RepositoryModule {
@Provides
fun provideInternetObservingSettings(): InternetObservingSettings {
return InternetObservingSettings.builder()
.strategy(SocketInternetObservingStrategy())
.host("www.google.com")
.strategy(WalledGardenInternetObservingStrategy())
.build()
}
@Singleton
@Provides
fun provideApi(): Api {
fun provideApi(chuckCollector: ChuckCollector, context: Context): Api {
return Api().apply {
logLevel = NONE
androidVersion = android.os.Build.VERSION.RELEASE
buildTag = android.os.Build.MODEL
setInterceptor(HttpLoggingInterceptor(HttpLoggingInterceptor.Logger { Timber.d(it) }).setLevel(BASIC))
// for debug only
setInterceptor(ChuckInterceptor(context, chuckCollector).maxContentLength(250000L), true, 0)
}
}
@Singleton
@Provides
fun provideChuckCollector(context: Context, prefRepository: PreferencesRepository): ChuckCollector {
return ChuckCollector(context)
.showNotification(prefRepository.isDebugNotificationEnable)
.retentionManager(RetentionManager(context, ChuckCollector.Period.ONE_HOUR))
}
@Singleton
@Provides
fun provideDatabase(context: Context) = AppDatabase.newInstance(context)
@ -67,6 +81,10 @@ internal class RepositoryModule {
@Provides
fun provideGradeSummaryDao(database: AppDatabase) = database.gradeSummaryDao
@Singleton
@Provides
fun provideGradeStatisticsDao(database: AppDatabase) = database.gradeStatistics
@Singleton
@Provides
fun provideMessagesDao(database: AppDatabase) = database.messagesDao
@ -98,4 +116,20 @@ internal class RepositoryModule {
@Singleton
@Provides
fun provideSubjectDao(database: AppDatabase) = database.subjectDao
@Singleton
@Provides
fun provideLuckyNumberDao(database: AppDatabase) = database.luckyNumberDao
@Singleton
@Provides
fun provideCompletedLessonsDao(database: AppDatabase) = database.completedLessonsDao
@Singleton
@Provides
fun provideReportingUnitDao(database: AppDatabase) = database.reportingUnitDao
@Singleton
@Provides
fun provideRecipientDao(database: AppDatabase) = database.recipientDao
}

View File

@ -8,28 +8,48 @@ import androidx.room.RoomDatabase.JournalMode.TRUNCATE
import androidx.room.TypeConverters
import io.github.wulkanowy.data.db.dao.AttendanceDao
import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao
import io.github.wulkanowy.data.db.dao.CompletedLessonsDao
import io.github.wulkanowy.data.db.dao.ExamDao
import io.github.wulkanowy.data.db.dao.GradeDao
import io.github.wulkanowy.data.db.dao.GradeStatisticsDao
import io.github.wulkanowy.data.db.dao.GradeSummaryDao
import io.github.wulkanowy.data.db.dao.MessagesDao
import io.github.wulkanowy.data.db.dao.HomeworkDao
import io.github.wulkanowy.data.db.dao.LuckyNumberDao
import io.github.wulkanowy.data.db.dao.MessagesDao
import io.github.wulkanowy.data.db.dao.NoteDao
import io.github.wulkanowy.data.db.dao.RecipientDao
import io.github.wulkanowy.data.db.dao.ReportingUnitDao
import io.github.wulkanowy.data.db.dao.SemesterDao
import io.github.wulkanowy.data.db.dao.StudentDao
import io.github.wulkanowy.data.db.dao.SubjectDao
import io.github.wulkanowy.data.db.dao.TimetableDao
import io.github.wulkanowy.data.db.entities.Attendance
import io.github.wulkanowy.data.db.entities.AttendanceSummary
import io.github.wulkanowy.data.db.entities.CompletedLesson
import io.github.wulkanowy.data.db.entities.Exam
import io.github.wulkanowy.data.db.entities.Grade
import io.github.wulkanowy.data.db.entities.GradeStatistics
import io.github.wulkanowy.data.db.entities.GradeSummary
import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.Homework
import io.github.wulkanowy.data.db.entities.LuckyNumber
import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.Note
import io.github.wulkanowy.data.db.entities.Recipient
import io.github.wulkanowy.data.db.entities.ReportingUnit
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.db.entities.Subject
import io.github.wulkanowy.data.db.entities.Timetable
import io.github.wulkanowy.data.db.migrations.Migration10
import io.github.wulkanowy.data.db.migrations.Migration11
import io.github.wulkanowy.data.db.migrations.Migration2
import io.github.wulkanowy.data.db.migrations.Migration3
import io.github.wulkanowy.data.db.migrations.Migration4
import io.github.wulkanowy.data.db.migrations.Migration5
import io.github.wulkanowy.data.db.migrations.Migration6
import io.github.wulkanowy.data.db.migrations.Migration7
import io.github.wulkanowy.data.db.migrations.Migration8
import io.github.wulkanowy.data.db.migrations.Migration9
import javax.inject.Singleton
@Singleton
@ -43,21 +63,42 @@ import javax.inject.Singleton
AttendanceSummary::class,
Grade::class,
GradeSummary::class,
GradeStatistics::class,
Message::class,
Note::class,
Homework::class,
Subject::class
Subject::class,
LuckyNumber::class,
CompletedLesson::class,
ReportingUnit::class,
Recipient::class
],
version = 1,
version = AppDatabase.VERSION_SCHEMA,
exportSchema = false
)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {
companion object {
const val VERSION_SCHEMA = 11
fun newInstance(context: Context): AppDatabase {
return Room.databaseBuilder(context, AppDatabase::class.java, "wulkanowy_database")
.setJournalMode(TRUNCATE)
.fallbackToDestructiveMigrationFrom(VERSION_SCHEMA + 1)
.fallbackToDestructiveMigrationOnDowngrade()
.addMigrations(
Migration2(),
Migration3(),
Migration4(),
Migration5(),
Migration6(),
Migration7(),
Migration8(),
Migration9(),
Migration10(),
Migration11()
)
.build()
}
}
@ -78,6 +119,8 @@ abstract class AppDatabase : RoomDatabase() {
abstract val gradeSummaryDao: GradeSummaryDao
abstract val gradeStatistics: GradeStatisticsDao
abstract val messagesDao: MessagesDao
abstract val noteDao: NoteDao
@ -85,4 +128,12 @@ abstract class AppDatabase : RoomDatabase() {
abstract val homeworkDao: HomeworkDao
abstract val subjectDao: SubjectDao
abstract val luckyNumberDao: LuckyNumberDao
abstract val completedLessonsDao: CompletedLessonsDao
abstract val reportingUnitDao: ReportingUnitDao
abstract val recipientDao: RecipientDao
}

View File

@ -1,6 +1,8 @@
package io.github.wulkanowy.data.db
import androidx.room.TypeConverter
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import org.threeten.bp.DateTimeUtils
import org.threeten.bp.Instant
import org.threeten.bp.LocalDate
@ -36,4 +38,14 @@ class Converters {
@TypeConverter
fun intToMonth(value: Int?) = value?.let { Month.of(it) }
@TypeConverter
fun intListToGson(list: List<Int>): String {
return Gson().toJson(list)
}
@TypeConverter
fun gsonToIntList(value: String): List<Int> {
return Gson().fromJson(value, object : TypeToken<List<Int>>() {}.type)
}
}

View File

@ -19,14 +19,6 @@ class SharedPrefHelper @Inject constructor(private val sharedPref: SharedPrefere
return sharedPref.getLong(key, defaultValue)
}
fun putBoolean(key: String, value: Boolean) {
sharedPref.edit().putBoolean(key, value).apply()
}
fun getBoolean(key: String, defaultValue: Boolean): Boolean {
return sharedPref.getBoolean(key, defaultValue)
}
fun delete(key: String) {
sharedPref.edit().remove(key).apply()
}

View File

@ -0,0 +1,24 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.CompletedLesson
import io.reactivex.Maybe
import org.threeten.bp.LocalDate
import javax.inject.Singleton
@Singleton
@Dao
interface CompletedLessonsDao {
@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")
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe<List<CompletedLesson>>
}

View File

@ -16,9 +16,6 @@ interface GradeDao {
@Insert
fun insertAll(grades: List<Grade>)
@Update
fun update(grade: Grade)
@Update
fun updateAll(grade: List<Grade>)
@ -28,6 +25,4 @@ interface GradeDao {
@Query("SELECT * FROM Grades WHERE semester_id = :semesterId AND student_id = :studentId")
fun loadAll(semesterId: Int, studentId: Int): Maybe<List<Grade>>
@Query("SELECT * FROM Grades WHERE is_read = 0 AND semester_id = :semesterId AND student_id = :studentId")
fun loadAllNew(semesterId: Int, studentId: Int): Maybe<List<Grade>>
}

View File

@ -0,0 +1,26 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.GradeStatistics
import io.reactivex.Maybe
import javax.inject.Singleton
@Singleton
@Dao
interface GradeStatisticsDao {
@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")
fun loadSubject(semesterId: Int, studentId: Int, subjectName: String, isSemester: Boolean): Maybe<List<GradeStatistics>>
@Query("SELECT * FROM GradesStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND is_semester = :isSemester")
fun loadAll(semesterId: Int, studentId: Int, isSemester: Boolean): Maybe<List<GradeStatistics>>
}

View File

@ -18,6 +18,6 @@ interface GradeSummaryDao {
@Delete
fun deleteAll(gradesSummary: List<GradeSummary>)
@Query("SELECT * FROM grades_summary 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>>
}

View File

@ -19,6 +19,6 @@ interface HomeworkDao {
@Delete
fun deleteAll(homework: List<Homework>)
@Query("SELECT * FROM Homework WHERE semester_id = :semesterId AND student_id = :studentId AND date = :date")
fun loadAll(semesterId: Int, studentId: Int, date: LocalDate): Maybe<List<Homework>>
@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>>
}

View File

@ -0,0 +1,29 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
import io.github.wulkanowy.data.db.entities.LuckyNumber
import io.reactivex.Maybe
import org.threeten.bp.LocalDate
import javax.inject.Singleton
@Singleton
@Dao
interface LuckyNumberDao {
@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")
fun load(studentId: Int, date: LocalDate): Maybe<LuckyNumber>
}

View File

@ -12,26 +12,20 @@ import io.reactivex.Maybe
interface MessagesDao {
@Insert
fun insertAll(messages: List<Message>): List<Long>
fun insertAll(messages: List<Message>)
@Delete
fun deleteAll(messages: List<Message>)
@Update
fun update(message: Message)
@Update
fun updateAll(messages: List<Message>)
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND real_id = :id")
fun loadOne(studentId: Int, id: Int): Maybe<Message>
@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>>
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND folder_id = :folder ORDER BY date DESC")
fun load(studentId: Int, folder: Int): Maybe<List<Message>>
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND real_id = :id")
fun load(studentId: Int, id: Int): Maybe<Message>
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND removed = 1 ORDER BY date DESC")
fun loadDeleted(studentId: Int): Maybe<List<Message>>
@Query("SELECT * FROM Messages WHERE unread = 1 AND student_id = :studentId")
fun loadNewMessages(studentId: Int): Maybe<List<Message>>
}

View File

@ -16,18 +16,13 @@ interface NoteDao {
@Insert
fun insertAll(notes: List<Note>)
@Update
fun update(note: Note)
@Update
fun updateAll(notes: List<Note>)
@Delete
fun deleteAll(notes: List<Note>)
@Query("SELECT * FROM Notes WHERE semester_id = :semesterId AND student_id = :studentId")
fun loadAll(semesterId: Int, studentId: Int): Maybe<List<Note>>
@Query("SELECT * FROM Notes WHERE student_id = :studentId")
fun loadAll(studentId: Int): Maybe<List<Note>>
@Query("SELECT * FROM Notes WHERE is_read = 0 AND semester_id = :semesterId AND student_id = :studentId")
fun loadNew(semesterId: Int, studentId: Int): Maybe<List<Note>>
}

View File

@ -0,0 +1,23 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Recipient
import io.reactivex.Maybe
import javax.inject.Singleton
@Singleton
@Dao
interface RecipientDao {
@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")
fun load(studentId: Int, role: Int, unitId: Int): Maybe<List<Recipient>>
}

View File

@ -0,0 +1,26 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.ReportingUnit
import io.reactivex.Maybe
import javax.inject.Singleton
@Singleton
@Dao
interface ReportingUnitDao {
@Insert
fun insertAll(reportingUnits: List<ReportingUnit>)
@Delete
fun deleteAll(reportingUnits: List<ReportingUnit>)
@Query("SELECT * FROM ReportingUnits WHERE student_id = :studentId")
fun load(studentId: Int): Maybe<List<ReportingUnit>>
@Query("SELECT * FROM ReportingUnits WHERE student_id = :studentId AND real_id = :unitId")
fun loadOne(studentId: Int, unitId: Int): Maybe<ReportingUnit>
}

View File

@ -1,8 +1,8 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy.IGNORE
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Semester
import io.reactivex.Maybe
@ -12,15 +12,12 @@ import javax.inject.Singleton
@Dao
interface SemesterDao {
@Insert(onConflict = IGNORE)
@Insert
fun insertAll(semester: List<Semester>)
@Delete
fun deleteAll(semester: List<Semester>)
@Query("SELECT * FROM Semesters WHERE student_id = :studentId")
fun loadAll(studentId: Int): Maybe<List<Semester>>
@Query("UPDATE Semesters SET is_current = 1 WHERE semester_id = :semesterId AND diary_id = :diaryId")
fun updateCurrent(semesterId: Int, diaryId: Int)
@Query("UPDATE Semesters SET is_current = 0 WHERE student_id = :studentId")
fun resetCurrent(studentId: Int)
}

View File

@ -3,7 +3,7 @@ package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy.FAIL
import androidx.room.OnConflictStrategy.ABORT
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Student
import io.reactivex.Maybe
@ -13,7 +13,7 @@ import javax.inject.Singleton
@Dao
interface StudentDao {
@Insert(onConflict = FAIL)
@Insert(onConflict = ABORT)
fun insert(student: Student): Long
@Delete

View File

@ -10,30 +10,30 @@ import java.io.Serializable
data class Attendance(
@ColumnInfo(name = "student_id")
var studentId: Int,
val studentId: Int,
@ColumnInfo(name = "diary_id")
var diaryId: Int,
val diaryId: Int,
var date: LocalDate,
val date: LocalDate,
var number: Int,
val number: Int,
var subject: String,
val subject: String,
var name: String,
val name: String,
var presence: Boolean = false,
val presence: Boolean,
var absence: Boolean = false,
val absence: Boolean,
var exemption: Boolean = false,
val exemption: Boolean,
var lateness: Boolean = false,
val lateness: Boolean,
var excused: Boolean = false,
val excused: Boolean,
var deleted: Boolean = false
val deleted: Boolean
) : Serializable {
@PrimaryKey(autoGenerate = true)

View File

@ -10,13 +10,13 @@ import java.io.Serializable
data class AttendanceSummary(
@ColumnInfo(name = "student_id")
var studentId: Int,
val studentId: Int,
@ColumnInfo(name = "diary_id")
var diaryId: Int,
val diaryId: Int,
@ColumnInfo(name = "subject_id")
var subjectId: Int = 0,
val subjectId: Int,
val month: Month,

View File

@ -0,0 +1,40 @@
package io.github.wulkanowy.data.db.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import org.threeten.bp.LocalDate
import java.io.Serializable
@Entity(tableName = "CompletedLesson")
data class CompletedLesson(
@ColumnInfo(name = "student_id")
val studentId: Int,
@ColumnInfo(name = "diary_id")
val diaryId: Int,
val date: LocalDate,
val number: Int,
val subject: String,
val topic: String,
val teacher: String,
@ColumnInfo(name = "teacher_symbol")
val teacherSymbol: String,
val substitution: String,
val absence: String,
val resources: String
) : Serializable {
@PrimaryKey(autoGenerate = true)
var id: Long = 0
}

View File

@ -9,29 +9,29 @@ import java.io.Serializable
@Entity(tableName = "Exams")
data class Exam(
@ColumnInfo(name = "student_id")
var studentId: Int,
@ColumnInfo(name = "student_id")
val studentId: Int,
@ColumnInfo(name = "diary_id")
var diaryId: Int,
@ColumnInfo(name = "diary_id")
val diaryId: Int,
var date: LocalDate,
val date: LocalDate,
@ColumnInfo(name = "entry_date")
var entryDate: LocalDate = LocalDate.now(),
@ColumnInfo(name = "entry_date")
val entryDate: LocalDate,
var subject: String,
val subject: String,
var group: String,
val group: String,
var type: String,
val type: String,
var description: String,
val description: String,
var teacher: String,
val teacher: String,
@ColumnInfo(name = "teacher_symbol")
var teacherSymbol: String
@ColumnInfo(name = "teacher_symbol")
val teacherSymbol: String
) : Serializable {
@PrimaryKey(autoGenerate = true)

View File

@ -10,35 +10,35 @@ import java.io.Serializable
data class Grade(
@ColumnInfo(name = "semester_id")
var semesterId: Int,
val semesterId: Int,
@ColumnInfo(name = "student_id")
var studentId: Int,
val studentId: Int,
var subject: String,
val subject: String,
var entry: String,
val entry: String,
var value: Int,
val value: Int,
var modifier: Double,
val modifier: Double,
var comment: String,
val comment: String,
var color: String,
val color: String,
@ColumnInfo(name = "grade_symbol")
var gradeSymbol: String,
val gradeSymbol: String,
var description: String,
val description: String,
var weight: String,
val weight: String,
var weightValue: Int,
val weightValue: Double,
var date: LocalDate,
val date: LocalDate,
var teacher: String
val teacher: String
) : Serializable {
@PrimaryKey(autoGenerate = true)

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
@Entity(tableName = "GradesStatistics")
data class GradeStatistics(
@ColumnInfo(name = "student_id")
val studentId: Int,
@ColumnInfo(name = "semester_id")
val semesterId: Int,
val subject: String,
val grade: Int,
val amount: Int,
@ColumnInfo(name = "is_semester")
val semester: Boolean
) {
@PrimaryKey(autoGenerate = true)
var id: Long = 0
}

View File

@ -4,22 +4,21 @@ import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "Grades_Summary")
@Entity(tableName = "GradesSummary")
data class GradeSummary(
@ColumnInfo(name = "semester_id")
var semesterId: Int,
@ColumnInfo(name = "semester_id")
val semesterId: Int,
@ColumnInfo(name = "student_id")
var studentId: Int,
@ColumnInfo(name = "student_id")
val studentId: Int,
var subject: String,
val subject: String,
var predictedGrade: String,
val predictedGrade: String,
var finalGrade: String
val finalGrade: String
) {
@PrimaryKey(autoGenerate = true)
var id: Long = 0
}

View File

@ -10,24 +10,24 @@ import java.io.Serializable
data class Homework(
@ColumnInfo(name = "semester_id")
var semesterId: Int,
val semesterId: Int,
@ColumnInfo(name = "student_id")
var studentId: Int,
val studentId: Int,
var date: LocalDate,
val date: LocalDate,
@ColumnInfo(name = "entry_date")
var entryDate: LocalDate,
val entryDate: LocalDate,
var subject: String,
val subject: String,
var content: String,
val content: String,
var teacher: String,
val teacher: String,
@ColumnInfo(name = "teacher_symbol")
var teacherSymbol: String
val teacherSymbol: String
) : Serializable {

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 org.threeten.bp.LocalDate
import java.io.Serializable
@Entity(tableName = "LuckyNumbers")
data class LuckyNumber (
@ColumnInfo(name = "student_id")
val studentId: Int,
val date: LocalDate,
@ColumnInfo(name = "lucky_number")
val luckyNumber: Int
) : Serializable {
@PrimaryKey(autoGenerate = true)
var id: Long = 0
@ColumnInfo(name = "is_notified")
var isNotified: Boolean = true
}

View File

@ -10,40 +10,39 @@ import java.io.Serializable
data class Message(
@ColumnInfo(name = "student_id")
var studentId: Int? = null,
val studentId: Int,
@ColumnInfo(name = "real_id")
val realId: Int? = null,
val realId: Int,
@ColumnInfo(name = "message_id")
val messageId: Int? = null,
val messageId: Int,
@ColumnInfo(name = "sender_name")
val sender: String? = null,
val sender: String,
@ColumnInfo(name = "sender_id")
val senderId: Int? = null,
@ColumnInfo(name = "recipient_id")
val recipientId: Int? = null,
val senderId: Int,
@ColumnInfo(name = "recipient_name")
val recipient: String? = "",
val recipient: String,
val subject: String = "",
val subject: String,
val date: LocalDateTime? = null,
val date: LocalDateTime,
@ColumnInfo(name = "folder_id")
val folderId: Int = 0,
val folderId: Int,
var unread: Boolean? = false,
var unread: Boolean,
val unreadBy: Int? = 0,
@ColumnInfo(name = "unread_by")
val unreadBy: Int,
val readBy: Int? = 0,
@ColumnInfo(name = "read_by")
val readBy: Int,
val removed: Boolean = false
val removed: Boolean
) : Serializable {
@PrimaryKey(autoGenerate = true)

View File

@ -9,26 +9,23 @@ import java.io.Serializable
@Entity(tableName = "Notes")
data class Note(
@ColumnInfo(name = "semester_id")
var semesterId: Int,
@ColumnInfo(name = "student_id")
var studentId: Int,
val studentId: Int,
var date: LocalDate,
val date: LocalDate,
var teacher: String,
val teacher: String,
var category: String,
val category: String,
var content: String
val content: String
) : Serializable {
@PrimaryKey(autoGenerate = true)
var id: Long = 0
@ColumnInfo(name = "is_read")
var isRead: Boolean = false
var isRead: Boolean = true
@ColumnInfo(name = "is_notified")
var isNotified: Boolean = true

View File

@ -0,0 +1,38 @@
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 = "Recipients")
data class Recipient(
@ColumnInfo(name = "student_id")
val studentId: Int,
@ColumnInfo(name = "real_id")
val realId: String,
val name: String,
@ColumnInfo(name = "real_name")
val realName: String,
@ColumnInfo(name = "login_id")
val loginId: Int,
@ColumnInfo(name = "unit_id")
val unitId: Int,
val role: Int,
val hash: String
) : Serializable {
@PrimaryKey(autoGenerate = true)
var id: Long = 0
override fun toString() = name
}

View File

@ -0,0 +1,32 @@
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 = "ReportingUnits")
data class ReportingUnit(
@ColumnInfo(name = "student_id")
val studentId: Int,
@ColumnInfo(name = "real_id")
val realId: Int,
@ColumnInfo(name = "short")
val shortName: String,
@ColumnInfo(name = "sender_id")
val senderId: Int,
@ColumnInfo(name = "sender_name")
val senderName: String,
val roles: List<Int>
) : Serializable {
@PrimaryKey(autoGenerate = true)
var id: Long = 0
}

View File

@ -8,24 +8,31 @@ import androidx.room.PrimaryKey
@Entity(tableName = "Semesters", indices = [Index(value = ["student_id", "diary_id", "semester_id"], unique = true)])
data class Semester(
@PrimaryKey(autoGenerate = true)
var id: Long = 0,
@ColumnInfo(name = "student_id")
var studentId: Int,
val studentId: Int,
@ColumnInfo(name = "diary_id")
var diaryId: Int,
val diaryId: Int,
@ColumnInfo(name = "diary_name")
var diaryName: String,
val diaryName: String,
@ColumnInfo(name = "semester_id")
var semesterId: Int,
val semesterId: Int,
@ColumnInfo(name = "semester_name")
var semesterName: Int,
val semesterName: Int,
@ColumnInfo(name = "is_current")
var isCurrent: Boolean = false
)
val isCurrent: Boolean,
@ColumnInfo(name = "class_id")
val classId: Int,
@ColumnInfo(name = "unit_id")
val unitId: Int
) {
@PrimaryKey(autoGenerate = true)
var id: Long = 0
}

View File

@ -4,35 +4,41 @@ import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
import org.threeten.bp.LocalDateTime
import java.io.Serializable
@Entity(tableName = "Students", indices = [Index(value = ["email", "symbol", "student_id", "school_id"], unique = true)])
data class Student(
@PrimaryKey(autoGenerate = true)
var id: Long = 0,
val endpoint: String,
var endpoint: String,
val loginType: String,
var loginType: String,
var email: String,
val email: String,
var password: String,
var symbol: String = "",
val symbol: String,
@ColumnInfo(name = "student_id")
var studentId: Int = 0,
val studentId: Int,
@ColumnInfo(name = "student_name")
var studentName: String = "",
val studentName: String,
@ColumnInfo(name = "school_id")
var schoolSymbol: String = "",
val schoolSymbol: String,
@ColumnInfo(name = "school_name")
var schoolName: String = "",
val schoolName: String,
@ColumnInfo(name = "is_current")
var isCurrent: Boolean = false
)
val isCurrent: Boolean,
@ColumnInfo(name = "registration_date")
val registrationDate: LocalDateTime
) : Serializable {
@PrimaryKey(autoGenerate = true)
var id: Long = 0
}

View File

@ -9,15 +9,15 @@ import java.io.Serializable
data class Subject(
@ColumnInfo(name = "student_id")
var studentId: Int,
val studentId: Int,
@ColumnInfo(name = "diary_id")
var diaryId: Int,
val diaryId: Int,
@ColumnInfo(name = "real_id")
var realId: Int,
val realId: Int,
var name: String
val name: String
) : Serializable {
@PrimaryKey(autoGenerate = true)

View File

@ -10,33 +10,39 @@ import java.io.Serializable
@Entity(tableName = "Timetable")
data class Timetable(
@ColumnInfo(name = "student_id")
var studentId: Int,
@ColumnInfo(name = "student_id")
val studentId: Int,
@ColumnInfo(name = "diary_id")
var diaryId: Int,
@ColumnInfo(name = "diary_id")
val diaryId: Int,
val number: Int = 0,
val number: Int,
val start: LocalDateTime = LocalDateTime.now(),
val start: LocalDateTime,
val end: LocalDateTime = LocalDateTime.now(),
val end: LocalDateTime,
val date: LocalDate,
val date: LocalDate,
val subject: String,
val subject: String,
val group: String,
val subjectOld: String,
val room: String,
val group: String,
val teacher: String,
val room: String,
val info: String,
val roomOld: String,
val changes: Boolean = false,
val teacher: String,
val canceled: Boolean = false
val teacherOld: String,
val info: String,
val changes: Boolean,
val canceled: Boolean
) : Serializable {
@PrimaryKey(autoGenerate = true)

View File

@ -0,0 +1,11 @@
package io.github.wulkanowy.data.db.migrations
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
class Migration10 : Migration(9, 10) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE Grades_Summary RENAME TO GradesSummary")
}
}

View File

@ -0,0 +1,34 @@
package io.github.wulkanowy.data.db.migrations
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
class Migration11 : Migration(10, 11) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("""
CREATE TABLE IF NOT EXISTS Grades_temp (
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 INTEGER 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
)
""")
database.execSQL("INSERT INTO Grades_temp SELECT * FROM Grades")
database.execSQL("DROP TABLE Grades")
database.execSQL("ALTER TABLE Grades_temp RENAME TO Grades")
}
}

View File

@ -0,0 +1,18 @@
package io.github.wulkanowy.data.db.migrations
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
class Migration2 : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("""
CREATE TABLE IF NOT EXISTS LuckyNumbers (
id INTEGER PRIMARY KEY NOT NULL,
is_notified INTEGER NOT NULL,
student_id INTEGER NOT NULL,
date INTEGER NOT NULL,
lucky_number INTEGER NOT NULL)
""")
}
}

View File

@ -0,0 +1,25 @@
package io.github.wulkanowy.data.db.migrations
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
class Migration3 : Migration(2, 3) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("""
CREATE TABLE IF NOT EXISTS CompletedLesson (
id INTEGER PRIMARY KEY NOT NULL,
student_id INTEGER NOT NULL,
diary_id INTEGER NOT NULL,
date INTEGER NOT NULL,
number INTEGER NOT NULL,
subject TEXT NOT NULL,
topic TEXT NOT NULL,
teacher TEXT NOT NULL,
teacher_symbol TEXT NOT NULL,
substitution TEXT NOT NULL,
absence TEXT NOT NULL,
resources TEXT NOT NULL)
""")
}
}

View File

@ -0,0 +1,31 @@
package io.github.wulkanowy.data.db.migrations
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
class Migration4 : Migration(3, 4) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("DROP TABLE IF EXISTS Messages")
database.execSQL("""
CREATE TABLE IF NOT EXISTS Messages (
id INTEGER PRIMARY KEY NOT NULL,
is_notified INTEGER NOT NULL,
content TEXT,
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_id INTEGER NOT NULL,
recipient_name TEXT NOT NULL,
subject TEXT NOT NULL,
date INTEGER NOT NULL,
folder_id INTEGER NOT NULL,
unread INTEGER NOT NULL,
unreadBy INTEGER NOT NULL,
readBy INTEGER NOT NULL,
removed INTEGER NOT NULL)
""")
}
}

View File

@ -0,0 +1,26 @@
package io.github.wulkanowy.data.db.migrations
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import org.threeten.bp.LocalDateTime.now
import org.threeten.bp.ZoneOffset
class Migration5 : Migration(4, 5) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE Students ADD COLUMN registration_date INTEGER DEFAULT 0 NOT NULL")
database.execSQL("UPDATE Students SET registration_date = '${now().atZone(ZoneOffset.UTC).toInstant().toEpochMilli()}'")
database.execSQL("DROP TABLE IF EXISTS Notes")
database.execSQL("""
CREATE TABLE IF NOT EXISTS Notes (
id INTEGER PRIMARY KEY NOT NULL,
is_read INTEGER NOT NULL,
is_notified INTEGER NOT NULL,
student_id INTEGER NOT NULL,
date INTEGER NOT NULL,
teacher TEXT NOT NULL,
category TEXT NOT NULL,
content TEXT NOT NULL)
""")
}
}

View File

@ -0,0 +1,37 @@
package io.github.wulkanowy.data.db.migrations
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
class Migration6 : Migration(5, 6) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("""
CREATE TABLE IF NOT EXISTS ReportingUnits (
id INTEGER PRIMARY KEY NOT NULL,
student_id INTEGER NOT NULL,
real_id INTEGER NOT NULL,
short TEXT NOT NULL,
sender_id INTEGER NOT NULL,
sender_name TEXT NOT NULL,
roles TEXT NOT NULL)
""")
database.execSQL("""
CREATE TABLE IF NOT EXISTS Recipients (
id INTEGER PRIMARY KEY NOT NULL,
student_id INTEGER NOT NULL,
real_id TEXT NOT NULL,
name TEXT NOT NULL,
real_name TEXT NOT NULL,
login_id INTEGER NOT NULL,
unit_id INTEGER NOT NULL,
role INTEGER NOT NULL,
hash TEXT NOT NULL)
""")
database.execSQL("DELETE FROM Semesters WHERE 1")
database.execSQL("ALTER TABLE Semesters ADD COLUMN class_id INTEGER DEFAULT 0 NOT NULL")
database.execSQL("ALTER TABLE Semesters ADD COLUMN unit_id INTEGER DEFAULT 0 NOT NULL")
}
}

View File

@ -0,0 +1,20 @@
package io.github.wulkanowy.data.db.migrations
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
class Migration7 : Migration(6, 7) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("""
CREATE TABLE IF NOT EXISTS GradesStatistics (
id INTEGER PRIMARY KEY NOT NULL,
student_id INTEGER NOT NULL,
semester_id INTEGER NOT NULL,
subject TEXT NOT NULL,
grade INTEGER NOT NULL,
amount INTEGER NOT NULL,
is_semester INTEGER NOT NULL)
""")
}
}

View File

@ -0,0 +1,13 @@
package io.github.wulkanowy.data.db.migrations
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
class Migration8 : Migration(7, 8) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE Timetable ADD COLUMN subjectOld TEXT DEFAULT \"\" NOT NULL")
database.execSQL("ALTER TABLE Timetable ADD COLUMN roomOld TEXT DEFAULT \"\" NOT NULL")
database.execSQL("ALTER TABLE Timetable ADD COLUMN teacherOld TEXT DEFAULT \"\" NOT NULL")
}
}

View File

@ -0,0 +1,30 @@
package io.github.wulkanowy.data.db.migrations
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
class Migration9 : Migration(8, 9) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("DROP TABLE IF EXISTS Messages")
database.execSQL("""
CREATE TABLE IF NOT EXISTS Messages (
id INTEGER PRIMARY KEY 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,
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,
is_notified INTEGER NOT NULL,
content TEXT)
""")
}
}

View File

@ -1,36 +0,0 @@
package io.github.wulkanowy.data.repositories
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.Homework
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.repositories.local.HomeworkLocal
import io.github.wulkanowy.data.repositories.remote.HomeworkRemote
import io.reactivex.Single
import org.threeten.bp.LocalDate
import java.net.UnknownHostException
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class HomeworkRepository @Inject constructor(
private val settings: InternetObservingSettings,
private val local: HomeworkLocal,
private val remote: HomeworkRemote
) {
fun getHomework(semester: Semester, date: LocalDate, forceRefresh: Boolean = false): Single<List<Homework>> {
return local.getHomework(semester, date).filter { !forceRefresh }
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
.flatMap {
if (it) remote.getHomework(semester, date)
else Single.error(UnknownHostException())
}.flatMap { newGrades ->
local.getHomework(semester, date).toSingle(emptyList())
.doOnSuccess { oldGrades ->
local.deleteHomework(oldGrades - newGrades)
local.saveHomework(newGrades - oldGrades)
}
}.flatMap { local.getHomework(semester, date).toSingle(emptyList()) })
}
}

View File

@ -1,79 +0,0 @@
package io.github.wulkanowy.data.repositories
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.Message
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.repositories.local.MessagesLocal
import io.github.wulkanowy.data.repositories.remote.MessagesRemote
import io.reactivex.Completable
import io.reactivex.Single
import java.net.UnknownHostException
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class MessagesRepository @Inject constructor(
private val settings: InternetObservingSettings,
private val local: MessagesLocal,
private val remote: MessagesRemote
) {
enum class MessageFolder(val id: Int = 1) {
RECEIVED(1),
SENT(2),
TRASHED(3)
}
fun getMessages(studentId: Int, folder: MessageFolder, forceRefresh: Boolean = false, notify: Boolean = false): Single<List<Message>> {
return local.getMessages(studentId, folder).filter { !forceRefresh }
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
.flatMap {
if (it) remote.getMessages(studentId, folder)
else Single.error(UnknownHostException())
}.flatMap { new ->
local.getMessages(studentId, folder).toSingle(emptyList())
.doOnSuccess { old ->
local.deleteMessages(old - new)
local.saveMessages((new - old)
.onEach {
it.isNotified = !notify
})
}
}.flatMap { local.getMessages(studentId, folder).toSingle(emptyList()) }
)
}
fun getMessage(studentId: Int, messageId: Int, markAsRead: Boolean = false): Single<Message> {
return local.getMessage(studentId, messageId)
.filter { !it.content.isNullOrEmpty() }
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
.flatMap {
if (it) local.getMessage(studentId, messageId).toSingle()
else Single.error(UnknownHostException())
}
.flatMap { dbMessage ->
remote.getMessagesContent(dbMessage, markAsRead).doOnSuccess {
local.updateMessage(dbMessage.copy(unread = false).apply {
id = dbMessage.id
content = it
})
}
}.flatMap {
local.getMessage(studentId, messageId).toSingle()
}
)
}
fun getNewMessages(student: Student): Single<List<Message>> {
return local.getNewMessages(student).toSingle(emptyList())
}
fun updateMessage(message: Message): Completable {
return Completable.fromCallable { local.updateMessage(message) }
}
fun updateMessages(messages: List<Message>): Completable {
return Completable.fromCallable { local.updateMessages(messages) }
}
}

View File

@ -1,46 +0,0 @@
package io.github.wulkanowy.data.repositories
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.Timetable
import io.github.wulkanowy.data.repositories.local.TimetableLocal
import io.github.wulkanowy.data.repositories.remote.TimetableRemote
import io.github.wulkanowy.utils.friday
import io.github.wulkanowy.utils.monday
import io.reactivex.Single
import org.threeten.bp.LocalDate
import java.net.UnknownHostException
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class TimetableRepository @Inject constructor(
private val settings: InternetObservingSettings,
private val local: TimetableLocal,
private val remote: TimetableRemote
) {
fun getTimetable(semester: Semester, startDate: LocalDate, endDate: LocalDate, forceRefresh: Boolean = false)
: Single<List<Timetable>> {
return Single.fromCallable { startDate.monday to endDate.friday }
.flatMap { dates ->
local.getTimetable(semester, dates.first, dates.second).filter { !forceRefresh }
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
.flatMap {
if (it) remote.getTimetable(semester, dates.first, dates.second)
else Single.error(UnknownHostException())
}.flatMap { newTimetable ->
local.getTimetable(semester, dates.first, dates.second)
.toSingle(emptyList())
.doOnSuccess { oldTimetable ->
local.deleteTimetable(oldTimetable - newTimetable)
local.saveTimetable(newTimetable - oldTimetable)
}
}.flatMap {
local.getTimetable(semester, dates.first, dates.second)
.toSingle(emptyList())
}).map { list -> list.filter { it.date in startDate..endDate } }
}
}
}

View File

@ -1,4 +1,4 @@
package io.github.wulkanowy.data.repositories.local
package io.github.wulkanowy.data.repositories.attendance
import io.github.wulkanowy.data.db.dao.AttendanceDao
import io.github.wulkanowy.data.db.entities.Attendance
@ -6,14 +6,11 @@ import io.github.wulkanowy.data.db.entities.Semester
import io.reactivex.Maybe
import org.threeten.bp.LocalDate
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class AttendanceLocal @Inject constructor(private val attendanceDb: AttendanceDao) {
fun getAttendance(semester: Semester, startDate: LocalDate, endDate: LocalDate): Maybe<List<Attendance>> {
return attendanceDb.loadAll(semester.diaryId, semester.studentId, startDate, endDate)
.filter { !it.isEmpty() }
}
fun saveAttendance(attendance: List<Attendance>) {
attendanceDb.insertAll(attendance)
}
@ -21,4 +18,8 @@ class AttendanceLocal @Inject constructor(private val attendanceDb: AttendanceDa
fun deleteAttendance(attendance: List<Attendance>) {
attendanceDb.deleteAll(attendance)
}
fun getAttendance(semester: Semester, startDate: LocalDate, endDate: LocalDate): Maybe<List<Attendance>> {
return attendanceDb.loadAll(semester.diaryId, semester.studentId, startDate, endDate).filter { it.isNotEmpty() }
}
}

View File

@ -1,4 +1,4 @@
package io.github.wulkanowy.data.repositories.remote
package io.github.wulkanowy.data.repositories.attendance
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.entities.Attendance

View File

@ -1,11 +1,9 @@
package io.github.wulkanowy.data.repositories
package io.github.wulkanowy.data.repositories.attendance
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.Attendance
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.repositories.local.AttendanceLocal
import io.github.wulkanowy.data.repositories.remote.AttendanceRemote
import io.github.wulkanowy.utils.friday
import io.github.wulkanowy.utils.monday
import io.reactivex.Single

View File

@ -1,17 +1,15 @@
package io.github.wulkanowy.data.repositories.local
package io.github.wulkanowy.data.repositories.attendancesummary
import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao
import io.github.wulkanowy.data.db.entities.AttendanceSummary
import io.github.wulkanowy.data.db.entities.Semester
import io.reactivex.Maybe
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class AttendanceSummaryLocal @Inject constructor(private val attendanceDb: AttendanceSummaryDao) {
fun getAttendanceSummary(semester: Semester, subjectId: Int): Maybe<List<AttendanceSummary>> {
return attendanceDb.loadAll(semester.diaryId, semester.studentId, subjectId).filter { !it.isEmpty() }
}
fun saveAttendanceSummary(attendance: List<AttendanceSummary>) {
attendanceDb.insertAll(attendance)
}
@ -19,4 +17,8 @@ class AttendanceSummaryLocal @Inject constructor(private val attendanceDb: Atten
fun deleteAttendanceSummary(attendance: List<AttendanceSummary>) {
attendanceDb.deleteAll(attendance)
}
fun getAttendanceSummary(semester: Semester, subjectId: Int): Maybe<List<AttendanceSummary>> {
return attendanceDb.loadAll(semester.diaryId, semester.studentId, subjectId).filter { it.isNotEmpty() }
}
}

View File

@ -1,4 +1,4 @@
package io.github.wulkanowy.data.repositories.remote
package io.github.wulkanowy.data.repositories.attendancesummary
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.entities.AttendanceSummary

View File

@ -1,11 +1,9 @@
package io.github.wulkanowy.data.repositories
package io.github.wulkanowy.data.repositories.attendancesummary
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.AttendanceSummary
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.repositories.local.AttendanceSummaryLocal
import io.github.wulkanowy.data.repositories.remote.AttendanceSummaryRemote
import io.reactivex.Single
import java.net.UnknownHostException
import javax.inject.Inject
@ -18,7 +16,7 @@ class AttendanceSummaryRepository @Inject constructor(
private val remote: AttendanceSummaryRemote
) {
fun getAttendanceSummary(semester: Semester, subjectId: Int, forceRefresh: Boolean = false): Single<List<AttendanceSummary>>? {
fun getAttendanceSummary(semester: Semester, subjectId: Int, forceRefresh: Boolean = false): Single<List<AttendanceSummary>> {
return local.getAttendanceSummary(semester, subjectId).filter { !forceRefresh }
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
.flatMap {

View File

@ -0,0 +1,25 @@
package io.github.wulkanowy.data.repositories.completedlessons
import io.github.wulkanowy.data.db.dao.CompletedLessonsDao
import io.github.wulkanowy.data.db.entities.CompletedLesson
import io.github.wulkanowy.data.db.entities.Semester
import io.reactivex.Maybe
import org.threeten.bp.LocalDate
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class CompletedLessonsLocal @Inject constructor(private val completedLessonsDb: CompletedLessonsDao) {
fun saveCompletedLessons(completedLessons: List<CompletedLesson>) {
completedLessonsDb.insertAll(completedLessons)
}
fun deleteCompleteLessons(completedLessons: List<CompletedLesson>) {
completedLessonsDb.deleteAll(completedLessons)
}
fun getCompletedLessons(semester: Semester, start: LocalDate, end: LocalDate): Maybe<List<CompletedLesson>> {
return completedLessonsDb.loadAll(semester.diaryId, semester.studentId, start, end).filter { it.isNotEmpty() }
}
}

View File

@ -0,0 +1,37 @@
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.Semester
import io.reactivex.Single
import org.threeten.bp.LocalDate
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class CompletedLessonsRemote @Inject constructor(private val api: Api) {
fun getCompletedLessons(semester: Semester, startDate: LocalDate, endDate: LocalDate): Single<List<CompletedLesson>> {
return Single.just(api.apply { diaryId = semester.diaryId })
.flatMap { it.getCompletedLessons(startDate, endDate) }
.map { lessons ->
lessons.map {
it.absence
CompletedLesson(
studentId = semester.studentId,
diaryId = semester.diaryId,
date = it.date.toLocalDate(),
number = it.number,
subject = it.subject,
topic = it.topic,
teacher = it.teacher,
teacherSymbol = it.teacherSymbol,
substitution = it.substitution,
absence = it.absence,
resources = it.resources
)
}
}
}
}

View File

@ -0,0 +1,43 @@
package io.github.wulkanowy.data.repositories.completedlessons
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.CompletedLesson
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.utils.friday
import io.github.wulkanowy.utils.monday
import io.reactivex.Single
import org.threeten.bp.LocalDate
import java.net.UnknownHostException
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class CompletedLessonsRepository @Inject constructor(
private val settings: InternetObservingSettings,
private val local: CompletedLessonsLocal,
private val remote: CompletedLessonsRemote
) {
fun getCompletedLessons(semester: Semester, startDate: LocalDate, endDate: LocalDate, forceRefresh: Boolean = false): Single<List<CompletedLesson>> {
return Single.fromCallable { startDate.monday to endDate.friday }
.flatMap { dates ->
local.getCompletedLessons(semester, dates.first, dates.second).filter { !forceRefresh }
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
.flatMap {
if (it) remote.getCompletedLessons(semester, dates.first, dates.second)
else Single.error(UnknownHostException())
}.flatMap { new ->
local.getCompletedLessons(semester, dates.first, dates.second)
.toSingle(emptyList())
.doOnSuccess { old ->
local.deleteCompleteLessons(old - new)
local.saveCompletedLessons(new - old)
}
}.flatMap {
local.getCompletedLessons(semester, dates.first, dates.second)
.toSingle(emptyList())
}).map { list -> list.filter { it.date in startDate..endDate } }
}
}
}

View File

@ -1,4 +1,4 @@
package io.github.wulkanowy.data.repositories.local
package io.github.wulkanowy.data.repositories.exam
import io.github.wulkanowy.data.db.dao.ExamDao
import io.github.wulkanowy.data.db.entities.Exam
@ -6,7 +6,9 @@ import io.github.wulkanowy.data.db.entities.Semester
import io.reactivex.Maybe
import org.threeten.bp.LocalDate
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class ExamLocal @Inject constructor(private val examDb: ExamDao) {
fun getExams(semester: Semester, startDate: LocalDate, endDate: LocalDate): Maybe<List<Exam>> {

View File

@ -1,4 +1,4 @@
package io.github.wulkanowy.data.repositories.remote
package io.github.wulkanowy.data.repositories.exam
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.entities.Exam
@ -7,7 +7,9 @@ import io.github.wulkanowy.utils.toLocalDate
import io.reactivex.Single
import org.threeten.bp.LocalDate
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class ExamRemote @Inject constructor(private val api: Api) {
fun getExams(semester: Semester, startDate: LocalDate, endDate: LocalDate): Single<List<Exam>> {

View File

@ -1,11 +1,9 @@
package io.github.wulkanowy.data.repositories
package io.github.wulkanowy.data.repositories.exam
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.Exam
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.repositories.local.ExamLocal
import io.github.wulkanowy.data.repositories.remote.ExamRemote
import io.github.wulkanowy.utils.friday
import io.github.wulkanowy.utils.monday
import io.reactivex.Single

View File

@ -1,9 +1,8 @@
package io.github.wulkanowy.data.repositories.local
package io.github.wulkanowy.data.repositories.grade
import io.github.wulkanowy.data.db.dao.GradeDao
import io.github.wulkanowy.data.db.entities.Grade
import io.github.wulkanowy.data.db.entities.Semester
import io.reactivex.Completable
import io.reactivex.Maybe
import javax.inject.Inject
import javax.inject.Singleton
@ -11,27 +10,19 @@ import javax.inject.Singleton
@Singleton
class GradeLocal @Inject constructor(private val gradeDb: GradeDao) {
fun getGrades(semester: Semester): Maybe<List<Grade>> {
return gradeDb.loadAll(semester.semesterId, semester.studentId).filter { !it.isEmpty() }
}
fun getNewGrades(semester: Semester): Maybe<List<Grade>> {
return gradeDb.loadAllNew(semester.semesterId, semester.studentId)
}
fun saveGrades(grades: List<Grade>) {
gradeDb.insertAll(grades)
}
fun updateGrade(grade: Grade): Completable {
return Completable.fromCallable { gradeDb.update(grade) }
}
fun updateGrades(grades: List<Grade>): Completable {
return Completable.fromCallable { gradeDb.updateAll(grades) }
}
fun deleteGrades(grades: List<Grade>) {
gradeDb.deleteAll(grades)
}
fun updateGrades(grades: List<Grade>) {
gradeDb.updateAll(grades)
}
fun getGrades(semester: Semester): Maybe<List<Grade>> {
return gradeDb.loadAll(semester.semesterId, semester.studentId).filter { it.isNotEmpty() }
}
}

View File

@ -1,4 +1,4 @@
package io.github.wulkanowy.data.repositories.remote
package io.github.wulkanowy.data.repositories.grade
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.entities.Grade
@ -25,8 +25,8 @@ class GradeRemote @Inject constructor(private val api: Api) {
modifier = it.modifier,
comment = it.comment,
color = it.color,
gradeSymbol = it.symbol ?: "",
description = it.description,
gradeSymbol = it.symbol.orEmpty(),
description = it.description.orEmpty(),
weight = it.weight,
weightValue = it.weightValue,
date = it.date.toLocalDate(),

View File

@ -1,11 +1,10 @@
package io.github.wulkanowy.data.repositories
package io.github.wulkanowy.data.repositories.grade
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.Grade
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.repositories.local.GradeLocal
import io.github.wulkanowy.data.repositories.remote.GradeRemote
import io.github.wulkanowy.data.db.entities.Student
import io.reactivex.Completable
import io.reactivex.Single
import java.net.UnknownHostException
@ -19,7 +18,7 @@ class GradeRepository @Inject constructor(
private val remote: GradeRemote
) {
fun getGrades(semester: Semester, forceRefresh: Boolean = false, notify: Boolean = false): Single<List<Grade>> {
fun getGrades(student: Student, semester: Semester, forceRefresh: Boolean = false, notify: Boolean = false): Single<List<Grade>> {
return local.getGrades(semester).filter { !forceRefresh }
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
.flatMap {
@ -28,25 +27,33 @@ class GradeRepository @Inject constructor(
}.flatMap { newGrades ->
local.getGrades(semester).toSingle(emptyList())
.doOnSuccess { oldGrades ->
val notifyBreakDate = oldGrades.maxBy { it.date }?.date
?: student.registrationDate.toLocalDate()
local.deleteGrades(oldGrades - newGrades)
local.saveGrades((newGrades - oldGrades)
.onEach {
if (oldGrades.isNotEmpty()) it.isRead = false
if (notify) it.isNotified = false
if (it.date >= notifyBreakDate) it.apply {
isRead = false
if (notify) isNotified = false
}
})
}
}.flatMap { local.getGrades(semester).toSingle(emptyList()) })
}
fun getNewGrades(semester: Semester): Single<List<Grade>> {
return local.getNewGrades(semester).toSingle(emptyList())
fun getUnreadGrades(semester: Semester): Single<List<Grade>> {
return local.getGrades(semester).map { it.filter { grade -> !grade.isRead } }.toSingle(emptyList())
}
fun getNotNotifiedGrades(semester: Semester): Single<List<Grade>> {
return local.getGrades(semester).map { it.filter { grade -> !grade.isNotified } }.toSingle(emptyList())
}
fun updateGrade(grade: Grade): Completable {
return local.updateGrade(grade)
return Completable.fromCallable { local.updateGrades(listOf(grade)) }
}
fun updateGrades(grades: List<Grade>): Completable {
return local.updateGrades(grades)
return Completable.fromCallable { local.updateGrades(grades) }
}
}

View File

@ -1,4 +1,4 @@
package io.github.wulkanowy.data.repositories.local
package io.github.wulkanowy.data.repositories.gradessummary
import io.github.wulkanowy.data.db.dao.GradeSummaryDao
import io.github.wulkanowy.data.db.entities.GradeSummary
@ -10,11 +10,6 @@ import javax.inject.Singleton
@Singleton
class GradeSummaryLocal @Inject constructor(private val gradeSummaryDb: GradeSummaryDao) {
fun getGradesSummary(semester: Semester): Maybe<List<GradeSummary>> {
return gradeSummaryDb.loadAll(semester.semesterId, semester.studentId)
.filter { !it.isEmpty() }
}
fun saveGradesSummary(gradesSummary: List<GradeSummary>) {
gradeSummaryDb.insertAll(gradesSummary)
}
@ -22,4 +17,8 @@ class GradeSummaryLocal @Inject constructor(private val gradeSummaryDb: GradeSum
fun deleteGradesSummary(gradesSummary: List<GradeSummary>) {
gradeSummaryDb.deleteAll(gradesSummary)
}
fun getGradesSummary(semester: Semester): Maybe<List<GradeSummary>> {
return gradeSummaryDb.loadAll(semester.semesterId, semester.studentId).filter { it.isNotEmpty() }
}
}

View File

@ -1,4 +1,4 @@
package io.github.wulkanowy.data.repositories.remote
package io.github.wulkanowy.data.repositories.gradessummary
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.entities.GradeSummary

View File

@ -1,11 +1,9 @@
package io.github.wulkanowy.data.repositories
package io.github.wulkanowy.data.repositories.gradessummary
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.GradeSummary
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.repositories.local.GradeSummaryLocal
import io.github.wulkanowy.data.repositories.remote.GradeSummaryRemote
import io.reactivex.Single
import java.net.UnknownHostException
import javax.inject.Inject

View File

@ -0,0 +1,34 @@
package io.github.wulkanowy.data.repositories.gradestatistics
import io.github.wulkanowy.data.db.dao.GradeStatisticsDao
import io.github.wulkanowy.data.db.entities.GradeStatistics
import io.github.wulkanowy.data.db.entities.Semester
import io.reactivex.Maybe
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class GradeStatisticsLocal @Inject constructor(private val gradeStatisticsDb: GradeStatisticsDao) {
fun getGradesStatistics(semester: Semester, isSemester: Boolean): Maybe<List<GradeStatistics>> {
return gradeStatisticsDb.loadAll(semester.semesterId, semester.studentId, isSemester)
.filter { !it.isEmpty() }
}
fun getGradesStatistics(semester: Semester, isSemester: Boolean, subjectName: String): Maybe<List<GradeStatistics>> {
return (if ("Wszystkie" == subjectName) gradeStatisticsDb.loadAll(semester.semesterId, semester.studentId, isSemester).map { list ->
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.isEmpty() }
}
fun saveGradesStatistics(gradesStatistics: List<GradeStatistics>) {
gradeStatisticsDb.insertAll(gradesStatistics)
}
fun deleteGradesStatistics(gradesStatistics: List<GradeStatistics>) {
gradeStatisticsDb.deleteAll(gradesStatistics)
}
}

View File

@ -0,0 +1,29 @@
package io.github.wulkanowy.data.repositories.gradestatistics
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.entities.GradeStatistics
import io.github.wulkanowy.data.db.entities.Semester
import io.reactivex.Single
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class GradeStatisticsRemote @Inject constructor(private val api: Api) {
fun getGradeStatistics(semester: Semester, isSemester: Boolean): Single<List<GradeStatistics>> {
return Single.just(api.apply { diaryId = semester.diaryId })
.flatMap { it.getGradesStatistics(semester.semesterId, isSemester) }
.map { gradeStatistics ->
gradeStatistics.map {
GradeStatistics(
semesterId = semester.semesterId,
studentId = semester.studentId,
subject = it.subject,
grade = it.gradeValue,
amount = it.amount ?: 0,
semester = isSemester
)
}
}
}
}

View File

@ -0,0 +1,33 @@
package io.github.wulkanowy.data.repositories.gradestatistics
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.GradeStatistics
import io.github.wulkanowy.data.db.entities.Semester
import io.reactivex.Single
import java.net.UnknownHostException
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class GradeStatisticsRepository @Inject constructor(
private val settings: InternetObservingSettings,
private val local: GradeStatisticsLocal,
private val remote: GradeStatisticsRemote
) {
fun getGradesStatistics(semester: Semester, subjectName: String, isSemester: Boolean, forceRefresh: Boolean = false): Single<List<GradeStatistics>> {
return local.getGradesStatistics(semester, isSemester, subjectName).filter { !forceRefresh }
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
.flatMap {
if (it) remote.getGradeStatistics(semester, isSemester)
else Single.error(UnknownHostException())
}.flatMap { newGradesStats ->
local.getGradesStatistics(semester, isSemester).toSingle(emptyList())
.doOnSuccess { oldGradesStats ->
local.deleteGradesStatistics(oldGradesStats - newGradesStats)
local.saveGradesStatistics(newGradesStats - oldGradesStats)
}
}.flatMap { local.getGradesStatistics(semester, isSemester, subjectName).toSingle(emptyList()) })
}
}

View File

@ -1,4 +1,4 @@
package io.github.wulkanowy.data.repositories.local
package io.github.wulkanowy.data.repositories.homework
import io.github.wulkanowy.data.db.dao.HomeworkDao
import io.github.wulkanowy.data.db.entities.Homework
@ -11,10 +11,6 @@ import javax.inject.Singleton
@Singleton
class HomeworkLocal @Inject constructor(private val homeworkDb: HomeworkDao) {
fun getHomework(semester: Semester, date: LocalDate): Maybe<List<Homework>> {
return homeworkDb.loadAll(semester.semesterId, semester.studentId, date).filter { !it.isEmpty() }
}
fun saveHomework(homework: List<Homework>) {
homeworkDb.insertAll(homework)
}
@ -22,4 +18,9 @@ class HomeworkLocal @Inject constructor(private val homeworkDb: HomeworkDao) {
fun deleteHomework(homework: List<Homework>) {
homeworkDb.deleteAll(homework)
}
fun getHomework(semester: Semester, startDate: LocalDate, endDate: LocalDate): Maybe<List<Homework>> {
return homeworkDb.loadAll(semester.semesterId, semester.studentId, startDate, endDate)
.filter { it.isNotEmpty() }
}
}

View File

@ -1,4 +1,4 @@
package io.github.wulkanowy.data.repositories.remote
package io.github.wulkanowy.data.repositories.homework
import io.github.wulkanowy.api.Api
import io.github.wulkanowy.data.db.entities.Homework
@ -12,9 +12,9 @@ import javax.inject.Singleton
@Singleton
class HomeworkRemote @Inject constructor(private val api: Api) {
fun getHomework(semester: Semester, date: LocalDate): Single<List<Homework>> {
fun getHomework(semester: Semester, startDate: LocalDate, endDate: LocalDate): Single<List<Homework>> {
return Single.just(api.apply { diaryId = semester.diaryId })
.flatMap { it.getHomework(date, date) }
.flatMap { it.getHomework(startDate, endDate) }
.map { homework ->
homework.map {
Homework(

View File

@ -0,0 +1,38 @@
package io.github.wulkanowy.data.repositories.homework
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.Homework
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.utils.friday
import io.github.wulkanowy.utils.monday
import io.reactivex.Single
import org.threeten.bp.LocalDate
import java.net.UnknownHostException
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class HomeworkRepository @Inject constructor(
private val settings: InternetObservingSettings,
private val local: HomeworkLocal,
private val remote: HomeworkRemote
) {
fun getHomework(semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean = false): Single<List<Homework>> {
return Single.fromCallable { start.monday to end.friday }.flatMap { (monday, friday) ->
local.getHomework(semester, monday, friday).filter { !forceRefresh }
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
.flatMap {
if (it) remote.getHomework(semester, monday, friday)
else Single.error(UnknownHostException())
}.flatMap { newGrades ->
local.getHomework(semester, monday, friday).toSingle(emptyList())
.doOnSuccess { oldGrades ->
local.deleteHomework(oldGrades - newGrades)
local.saveHomework(newGrades - oldGrades)
}
}.flatMap { local.getHomework(semester, monday, friday).toSingle(emptyList()) })
}
}
}

View File

@ -1,44 +0,0 @@
package io.github.wulkanowy.data.repositories.local
import io.github.wulkanowy.data.db.dao.MessagesDao
import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.repositories.MessagesRepository
import io.reactivex.Maybe
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class MessagesLocal @Inject constructor(private val messagesDb: MessagesDao) {
fun getMessage(studentId: Int, id: Int): Maybe<Message> {
return messagesDb.loadOne(studentId, id)
}
fun getMessages(studentId: Int, folder: MessagesRepository.MessageFolder): Maybe<List<Message>> {
return when (folder) {
MessagesRepository.MessageFolder.TRASHED -> messagesDb.loadDeleted(studentId)
else -> messagesDb.load(studentId, folder.id)
}.filter { !it.isEmpty() }
}
fun getNewMessages(student: Student): Maybe<List<Message>> {
return messagesDb.loadNewMessages(student.studentId)
}
fun saveMessages(messages: List<Message>): List<Long> {
return messagesDb.insertAll(messages)
}
fun updateMessage(message: Message) {
return messagesDb.update(message)
}
fun updateMessages(messages: List<Message>) {
return messagesDb.updateAll(messages)
}
fun deleteMessages(messages: List<Message>) {
messagesDb.deleteAll(messages)
}
}

View File

@ -1,37 +0,0 @@
package io.github.wulkanowy.data.repositories.local
import io.github.wulkanowy.data.db.dao.NoteDao
import io.github.wulkanowy.data.db.entities.Note
import io.github.wulkanowy.data.db.entities.Semester
import io.reactivex.Completable
import io.reactivex.Maybe
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class NoteLocal @Inject constructor(private val noteDb: NoteDao) {
fun getNotes(semester: Semester): Maybe<List<Note>> {
return noteDb.loadAll(semester.semesterId, semester.studentId).filter { !it.isEmpty() }
}
fun getNewNotes(semester: Semester): Maybe<List<Note>> {
return noteDb.loadNew(semester.semesterId, semester.studentId)
}
fun saveNotes(notes: List<Note>) {
noteDb.insertAll(notes)
}
fun updateNote(note: Note): Completable {
return Completable.fromCallable { noteDb.update(note) }
}
fun updateNotes(notes: List<Note>): Completable {
return Completable.fromCallable { noteDb.updateAll(notes) }
}
fun deleteNotes(notes: List<Note>) {
noteDb.deleteAll(notes)
}
}

View File

@ -0,0 +1,29 @@
package io.github.wulkanowy.data.repositories.luckynumber
import io.github.wulkanowy.data.db.dao.LuckyNumberDao
import io.github.wulkanowy.data.db.entities.LuckyNumber
import io.github.wulkanowy.data.db.entities.Semester
import io.reactivex.Maybe
import org.threeten.bp.LocalDate
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class LuckyNumberLocal @Inject constructor(private val luckyNumberDb: LuckyNumberDao) {
fun saveLuckyNumber(luckyNumber: LuckyNumber) {
luckyNumberDb.insert(luckyNumber)
}
fun updateLuckyNumber(luckyNumber: LuckyNumber) {
luckyNumberDb.update(luckyNumber)
}
fun deleteLuckyNumber(luckyNumber: LuckyNumber) {
luckyNumberDb.delete(luckyNumber)
}
fun getLuckyNumber(semester: Semester, date: LocalDate): Maybe<LuckyNumber> {
return luckyNumberDb.load(semester.studentId, date)
}
}

View File

@ -0,0 +1,26 @@
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.Semester
import io.reactivex.Maybe
import io.reactivex.Single
import org.threeten.bp.LocalDate
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class LuckyNumberRemote @Inject constructor(private val api: Api) {
fun getLuckyNumber(semester: Semester): Maybe<LuckyNumber> {
return Single.just(api.apply { diaryId = semester.diaryId })
.flatMapMaybe { it.getLuckyNumber() }
.map {
LuckyNumber(
studentId = semester.studentId,
date = LocalDate.now(),
luckyNumber = it
)
}
}
}

View File

@ -0,0 +1,54 @@
package io.github.wulkanowy.data.repositories.luckynumber
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.LuckyNumber
import io.github.wulkanowy.data.db.entities.Semester
import io.reactivex.Completable
import io.reactivex.Maybe
import org.threeten.bp.LocalDate
import java.net.UnknownHostException
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class LuckyNumberRepository @Inject constructor(
private val settings: InternetObservingSettings,
private val local: LuckyNumberLocal,
private val remote: LuckyNumberRemote
) {
fun getLuckyNumber(semester: Semester, forceRefresh: Boolean = false, notify: Boolean = false): Maybe<LuckyNumber> {
return local.getLuckyNumber(semester, LocalDate.now()).filter { !forceRefresh }
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
.flatMapMaybe {
if (it) remote.getLuckyNumber(semester)
else Maybe.error(UnknownHostException())
}.flatMap { new ->
local.getLuckyNumber(semester, LocalDate.now())
.doOnSuccess { old ->
if (new != old) {
local.deleteLuckyNumber(old)
local.saveLuckyNumber(new.apply {
if (notify) isNotified = false
})
}
}
.doOnComplete {
local.saveLuckyNumber(new.apply {
if (notify) isNotified = false
})
}
}.flatMap({ local.getLuckyNumber(semester, LocalDate.now()) }, { Maybe.error(it) },
{ local.getLuckyNumber(semester, LocalDate.now()) })
)
}
fun getNotNotifiedLuckyNumber(semester: Semester): Maybe<LuckyNumber> {
return local.getLuckyNumber(semester, LocalDate.now()).filter { !it.isNotified }
}
fun updateLuckyNumber(luckyNumber: LuckyNumber): Completable {
return Completable.fromCallable { local.updateLuckyNumber(luckyNumber) }
}
}

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