Compare commits
No commits in common. "2.2.4" and "1.7.4" have entirely different histories.
481 changed files with 5059 additions and 27916 deletions
8
.github/workflows/deploy-store.yml
vendored
8
.github/workflows/deploy-store.yml
vendored
|
@ -13,10 +13,10 @@ jobs:
|
||||||
environment: google-play
|
environment: google-play
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-java@v3
|
- uses: actions/setup-java@v2
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
distribution: 'zulu'
|
||||||
java-version: 17
|
java-version: 11
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
|
@ -49,10 +49,10 @@ jobs:
|
||||||
environment: app-gallery
|
environment: app-gallery
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-java@v3
|
- uses: actions/setup-java@v2
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
distribution: 'zulu'
|
||||||
java-version: 17
|
java-version: 11
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
|
|
8
.github/workflows/deploy-test.yml
vendored
8
.github/workflows/deploy-test.yml
vendored
|
@ -19,10 +19,10 @@ jobs:
|
||||||
environment: app-center
|
environment: app-center
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-java@v3
|
- uses: actions/setup-java@v2
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
distribution: 'zulu'
|
||||||
java-version: 17
|
java-version: 11
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
|
@ -89,10 +89,10 @@ jobs:
|
||||||
if: github.event_name != 'pull_request_target'
|
if: github.event_name != 'pull_request_target'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-java@v3
|
- uses: actions/setup-java@v2
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
distribution: 'zulu'
|
||||||
java-version: 17
|
java-version: 11
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
|
|
18
.github/workflows/test.yml
vendored
18
.github/workflows/test.yml
vendored
|
@ -2,12 +2,10 @@ name: Tests
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches: [ master, develop ]
|
||||||
- master
|
|
||||||
- develop
|
|
||||||
- 'hotfix/**'
|
|
||||||
tags: [ '*' ]
|
tags: [ '*' ]
|
||||||
pull_request:
|
pull_request:
|
||||||
|
branches: [ master, develop ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
|
@ -19,10 +17,10 @@ jobs:
|
||||||
- uses: fkirc/skip-duplicate-actions@master
|
- uses: fkirc/skip-duplicate-actions@master
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: gradle/wrapper-validation-action@v1
|
- uses: gradle/wrapper-validation-action@v1
|
||||||
- uses: actions/setup-java@v3
|
- uses: actions/setup-java@v2
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
distribution: 'zulu'
|
||||||
java-version: 17
|
java-version: 11
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
|
@ -45,10 +43,10 @@ jobs:
|
||||||
- uses: fkirc/skip-duplicate-actions@master
|
- uses: fkirc/skip-duplicate-actions@master
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: gradle/wrapper-validation-action@v1
|
- uses: gradle/wrapper-validation-action@v1
|
||||||
- uses: actions/setup-java@v3
|
- uses: actions/setup-java@v2
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
distribution: 'zulu'
|
||||||
java-version: 17
|
java-version: 11
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
|
@ -71,10 +69,10 @@ jobs:
|
||||||
- uses: fkirc/skip-duplicate-actions@master
|
- uses: fkirc/skip-duplicate-actions@master
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: gradle/wrapper-validation-action@v1
|
- uses: gradle/wrapper-validation-action@v1
|
||||||
- uses: actions/setup-java@v3
|
- uses: actions/setup-java@v2
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
distribution: 'zulu'
|
||||||
java-version: 17
|
java-version: 11
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -119,4 +119,3 @@ Thumbs.db
|
||||||
app/src/release/agconnect-services.json
|
app/src/release/agconnect-services.json
|
||||||
app/src/release/agconnect-credentials.json
|
app/src/release/agconnect-credentials.json
|
||||||
.idea/deploymentTargetDropDown.xml
|
.idea/deploymentTargetDropDown.xml
|
||||||
.idea/kotlinc.xml
|
|
||||||
|
|
2
LICENSE
2
LICENSE
|
@ -186,7 +186,7 @@
|
||||||
same "printed page" as the copyright notice for easier
|
same "printed page" as the copyright notice for easier
|
||||||
identification within third-party archives.
|
identification within third-party archives.
|
||||||
|
|
||||||
Copyright 2023 Wulkanowy
|
Copyright 2022 Wulkanowy
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
|
15
README.cs.md
15
README.cs.md
|
@ -1,13 +1,18 @@
|
||||||
Česká verze / [Deutsche Version](README.de.md) / [English version](README.en.md) / [Polska wersja](README.md) / [Slovenská verzia](README.sk.md)
|
[English version of README](README.en.md)
|
||||||
|
|
||||||
|
[Deutsche Version von README](README.de.md)
|
||||||
|
|
||||||
|
[Polska wersja README](README.md)
|
||||||
|
|
||||||
|
[Slovenská verzia README](README.sk.md)
|
||||||
|
|
||||||
# Wulkanowy
|
# Wulkanowy
|
||||||
|
|
||||||
[](https://github.com/wulkanowy/wulkanowy/actions)
|
[](https://github.com/wulkanowy/wulkanowy/actions)
|
||||||
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
||||||
[](https://discord.gg/vccAQBr)
|
[](https://discord.gg/vccAQBr)
|
||||||
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
||||||
[](https://github.com/wulkanowy/wulkanowy/releases)
|
[](https://github.com/wulkanowy/wulkanowy/releases)
|
||||||
[](https://translate.wulkanowy.net.pl)
|
|
||||||
|
|
||||||
Neoficiální klient deníku VULCAN UONET+ pro žáka a rodiče
|
Neoficiální klient deníku VULCAN UONET+ pro žáka a rodiče
|
||||||
|
|
||||||
|
@ -34,7 +39,7 @@ Neoficiální klient deníku VULCAN UONET+ pro žáka a rodiče
|
||||||
* podpora více účtů s možností přejmenování žáků
|
* podpora více účtů s možností přejmenování žáků
|
||||||
* tmavý a černý (AMOLED) motiv
|
* tmavý a černý (AMOLED) motiv
|
||||||
* offline režim
|
* offline režim
|
||||||
* volitelné reklamy na podporu projektu
|
* žádné reklamy
|
||||||
|
|
||||||
## Stáhnout
|
## Stáhnout
|
||||||
|
|
||||||
|
@ -52,7 +57,7 @@ Aktuální verzi si můžete stáhnout z Google Play, F-Droid nebo Huawei AppGal
|
||||||
|
|
||||||
Můžete si také stáhnout [vývojovou verzi](https://wulkanowy.github.io/#download), která zahrnuje nové funkce připravované pro příští vydání
|
Můžete si také stáhnout [vývojovou verzi](https://wulkanowy.github.io/#download), která zahrnuje nové funkce připravované pro příští vydání
|
||||||
|
|
||||||
## Postaveno s pomocí
|
## Postaveno s
|
||||||
|
|
||||||
|
|
||||||
* [Wulkanowy SDK](https://github.com/wulkanowy/sdk)
|
* [Wulkanowy SDK](https://github.com/wulkanowy/sdk)
|
||||||
|
|
11
README.de.md
11
README.de.md
|
@ -1,13 +1,14 @@
|
||||||
[Česká verze](README.cs.md) / Deutsche Version / [English version](README.en.md) / [Polska wersja](README.md) / [Slovenská verzia](README.sk.md)
|
[Polska wersja README](README.md)
|
||||||
|
|
||||||
|
[English version of README](README.en.md)
|
||||||
|
|
||||||
# Wulkanowy
|
# Wulkanowy
|
||||||
|
|
||||||
[](https://github.com/wulkanowy/wulkanowy/actions)
|
[](https://github.com/wulkanowy/wulkanowy/actions)
|
||||||
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
||||||
[](https://discord.gg/vccAQBr)
|
[](https://discord.gg/vccAQBr)
|
||||||
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
||||||
[](https://github.com/wulkanowy/wulkanowy/releases)
|
[](https://github.com/wulkanowy/wulkanowy/releases)
|
||||||
[](https://translate.wulkanowy.net.pl)
|
|
||||||
|
|
||||||
Inoffizieller Android VULCAN UONET+ Registrierungsclient für Schüler und ihre Eltern
|
Inoffizieller Android VULCAN UONET+ Registrierungsclient für Schüler und ihre Eltern
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ Inoffizieller Android VULCAN UONET+ Registrierungsclient für Schüler und ihre
|
||||||
* Prozentsatz der Anwesenheit
|
* Prozentsatz der Anwesenheit
|
||||||
* Prüfungen
|
* Prüfungen
|
||||||
* Stundenplan
|
* Stundenplan
|
||||||
* abgeschlossene Unterrichtsstunden
|
* Unterricht abgeschlossen
|
||||||
* Nachrichten
|
* Nachrichten
|
||||||
* Hausaufgaben
|
* Hausaufgaben
|
||||||
* Anmerkungen
|
* Anmerkungen
|
||||||
|
@ -34,7 +35,7 @@ Inoffizieller Android VULCAN UONET+ Registrierungsclient für Schüler und ihre
|
||||||
* Unterstützung für mehrere Konten mit der Möglichkeit, den Namen des Schülers zu ändern
|
* Unterstützung für mehrere Konten mit der Möglichkeit, den Namen des Schülers zu ändern
|
||||||
* dunkles und schwarzes (AMOLED) Thema
|
* dunkles und schwarzes (AMOLED) Thema
|
||||||
* Offline-Modus
|
* Offline-Modus
|
||||||
* optionale Werbungen, die es uns ermöglichen das Projekt zu unterstützen
|
* keine Werbung
|
||||||
|
|
||||||
## Herunterladen
|
## Herunterladen
|
||||||
|
|
||||||
|
|
13
README.en.md
13
README.en.md
|
@ -1,13 +1,18 @@
|
||||||
[Česká verze](README.cs.md) / [Deutsche Version](README.de.md) / English version / [Polska wersja](README.md) / [Slovenská verzia](README.sk.md)
|
[Polska wersja README](README.md)
|
||||||
|
|
||||||
|
[Deutsche Version von README](README.de.md)
|
||||||
|
|
||||||
|
[Česká verze README](README.cs.md)
|
||||||
|
|
||||||
|
[Slovenská verzia README](README.sk.md)
|
||||||
|
|
||||||
# Wulkanowy
|
# Wulkanowy
|
||||||
|
|
||||||
[](https://github.com/wulkanowy/wulkanowy/actions)
|
[](https://github.com/wulkanowy/wulkanowy/actions)
|
||||||
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
||||||
[](https://discord.gg/vccAQBr)
|
[](https://discord.gg/vccAQBr)
|
||||||
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
||||||
[](https://github.com/wulkanowy/wulkanowy/releases)
|
[](https://github.com/wulkanowy/wulkanowy/releases)
|
||||||
[](https://translate.wulkanowy.net.pl)
|
|
||||||
|
|
||||||
Unofficial android VULCAN UONET+ register client for both students and their parents
|
Unofficial android VULCAN UONET+ register client for both students and their parents
|
||||||
|
|
||||||
|
@ -34,7 +39,7 @@ Unofficial android VULCAN UONET+ register client for both students and their par
|
||||||
* support for multiple accounts with the ability to rename students
|
* support for multiple accounts with the ability to rename students
|
||||||
* dark and black (AMOLED) theme
|
* dark and black (AMOLED) theme
|
||||||
* offline mode
|
* offline mode
|
||||||
* optional ads which allow to support the project
|
* no ads
|
||||||
|
|
||||||
## Download
|
## Download
|
||||||
|
|
||||||
|
|
13
README.md
13
README.md
|
@ -1,13 +1,18 @@
|
||||||
[Česká verze](README.cs.md) / [Deutsche Version](README.de.md) / [English version](README.en.md) / Polska wersja / [Slovenská verzia](README.sk.md)
|
[English version of README](README.en.md)
|
||||||
|
|
||||||
|
[Deutsche Version von README](README.de.md)
|
||||||
|
|
||||||
|
[Česká verze README](README.cs.md)
|
||||||
|
|
||||||
|
[Slovenská verzia README](README.sk.md)
|
||||||
|
|
||||||
# Wulkanowy
|
# Wulkanowy
|
||||||
|
|
||||||
[](https://github.com/wulkanowy/wulkanowy/actions)
|
[](https://github.com/wulkanowy/wulkanowy/actions)
|
||||||
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
||||||
[](https://discord.gg/vccAQBr)
|
[](https://discord.gg/vccAQBr)
|
||||||
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
||||||
[](https://github.com/wulkanowy/wulkanowy/releases)
|
[](https://github.com/wulkanowy/wulkanowy/releases)
|
||||||
[](https://translate.wulkanowy.net.pl)
|
|
||||||
|
|
||||||
Nieoficjalny klient dziennika VULCAN UONET+ dla ucznia i rodzica
|
Nieoficjalny klient dziennika VULCAN UONET+ dla ucznia i rodzica
|
||||||
|
|
||||||
|
@ -34,7 +39,7 @@ Nieoficjalny klient dziennika VULCAN UONET+ dla ucznia i rodzica
|
||||||
* obsługa wielu kont wraz z możliwością zmiany nazwy ucznia
|
* obsługa wielu kont wraz z możliwością zmiany nazwy ucznia
|
||||||
* ciemny i czarny (AMOLED) motyw
|
* ciemny i czarny (AMOLED) motyw
|
||||||
* tryb offline
|
* tryb offline
|
||||||
* opcjonalne reklamy umożliwiające wsparcie projektu
|
* brak reklam
|
||||||
|
|
||||||
## Pobierz
|
## Pobierz
|
||||||
|
|
||||||
|
|
15
README.sk.md
15
README.sk.md
|
@ -1,13 +1,18 @@
|
||||||
[Česká verze](README.cs.md) / [Deutsche Version](README.de.md) / [English version](README.en.md) / [Polska wersja](README.md) / Slovenská verzia
|
[English version of README](README.en.md)
|
||||||
|
|
||||||
|
[Deutsche Version von README](README.de.md)
|
||||||
|
|
||||||
|
[Polska wersja README](README.md)
|
||||||
|
|
||||||
|
[Česká verze README](README.cs.md)
|
||||||
|
|
||||||
# Wulkanowy
|
# Wulkanowy
|
||||||
|
|
||||||
[](https://github.com/wulkanowy/wulkanowy/actions)
|
[](https://github.com/wulkanowy/wulkanowy/actions)
|
||||||
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
||||||
[](https://discord.gg/vccAQBr)
|
[](https://discord.gg/vccAQBr)
|
||||||
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
||||||
[](https://github.com/wulkanowy/wulkanowy/releases)
|
[](https://github.com/wulkanowy/wulkanowy/releases)
|
||||||
[](https://translate.wulkanowy.net.pl)
|
|
||||||
|
|
||||||
Neoficiálny klient denníka VULCAN UONET+ pre žiaka a rodičov
|
Neoficiálny klient denníka VULCAN UONET+ pre žiaka a rodičov
|
||||||
|
|
||||||
|
@ -34,7 +39,7 @@ Neoficiálny klient denníka VULCAN UONET+ pre žiaka a rodičov
|
||||||
* podpora viacerých účtov s možnosťou premenovania žiakov
|
* podpora viacerých účtov s možnosťou premenovania žiakov
|
||||||
* tmavý a čierny (AMOLED) motív
|
* tmavý a čierny (AMOLED) motív
|
||||||
* offline režim
|
* offline režim
|
||||||
* voliteľné reklamy na podporu projektu
|
* žiadne reklamy
|
||||||
|
|
||||||
## Stiahnuť
|
## Stiahnuť
|
||||||
|
|
||||||
|
@ -52,7 +57,7 @@ Aktuálnu verziu si môžete stiahnuť z Google Play, F-Droid alebo Huawei AppGa
|
||||||
|
|
||||||
Môžete si tiež stiahnuť [vývojovú verziu](https://wulkanowy.github.io/#download), ktorá zahrňuje nové funkcie pripravované pre budúce vydanie
|
Môžete si tiež stiahnuť [vývojovú verziu](https://wulkanowy.github.io/#download), ktorá zahrňuje nové funkcie pripravované pre budúce vydanie
|
||||||
|
|
||||||
## Postavené s pomocou
|
## Postavené s
|
||||||
|
|
||||||
|
|
||||||
* [Wulkanowy SDK](https://github.com/wulkanowy/sdk)
|
* [Wulkanowy SDK](https://github.com/wulkanowy/sdk)
|
||||||
|
|
137
app/build.gradle
137
app/build.gradle
|
@ -1,11 +1,8 @@
|
||||||
import com.github.triplet.gradle.androidpublisher.ReleaseStatus
|
|
||||||
import ru.cian.huawei.publish.ReleaseNote
|
|
||||||
|
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
apply plugin: 'kotlinx-serialization'
|
apply plugin: 'kotlinx-serialization'
|
||||||
apply plugin: 'kotlin-parcelize'
|
apply plugin: 'kotlin-parcelize'
|
||||||
apply plugin: 'com.google.devtools.ksp'
|
apply plugin: 'kotlin-kapt'
|
||||||
apply plugin: 'dagger.hilt.android.plugin'
|
apply plugin: 'dagger.hilt.android.plugin'
|
||||||
apply plugin: 'com.google.gms.google-services'
|
apply plugin: 'com.google.gms.google-services'
|
||||||
apply plugin: 'com.google.firebase.crashlytics'
|
apply plugin: 'com.google.firebase.crashlytics'
|
||||||
|
@ -13,29 +10,37 @@ apply plugin: 'com.github.triplet.play'
|
||||||
apply plugin: 'ru.cian.huawei-publish'
|
apply plugin: 'ru.cian.huawei-publish'
|
||||||
apply plugin: 'com.mikepenz.aboutlibraries.plugin'
|
apply plugin: 'com.mikepenz.aboutlibraries.plugin'
|
||||||
apply plugin: 'com.huawei.agconnect'
|
apply plugin: 'com.huawei.agconnect'
|
||||||
apply plugin: 'kotlin-kapt'
|
|
||||||
apply from: 'jacoco.gradle'
|
apply from: 'jacoco.gradle'
|
||||||
apply from: 'sonarqube.gradle'
|
apply from: 'sonarqube.gradle'
|
||||||
apply from: 'hooks.gradle'
|
apply from: 'hooks.gradle'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace 'io.github.wulkanowy'
|
namespace 'io.github.wulkanowy'
|
||||||
compileSdk 34
|
compileSdkVersion 32
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "io.github.wulkanowy"
|
applicationId "io.github.wulkanowy"
|
||||||
testApplicationId "io.github.tests.wulkanowy"
|
testApplicationId "io.github.tests.wulkanowy"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 34
|
targetSdkVersion 32
|
||||||
versionCode 136
|
versionCode 113
|
||||||
versionName "2.2.4"
|
versionName "1.7.4"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
resValue "string", "app_name", "Wulkanowy"
|
resValue "string", "app_name", "Wulkanowy"
|
||||||
|
|
||||||
manifestPlaceholders = [
|
manifestPlaceholders = [
|
||||||
firebase_enabled: project.hasProperty("enableFirebase"),
|
firebase_enabled: project.hasProperty("enableFirebase"),
|
||||||
admob_project_id: ""
|
admob_project_id: ""
|
||||||
]
|
]
|
||||||
|
javaCompileOptions {
|
||||||
|
annotationProcessorOptions {
|
||||||
|
arguments += [
|
||||||
|
"room.schemaLocation": "$projectDir/schemas".toString(),
|
||||||
|
"room.incremental" : "true"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
buildConfigField "String", "SINGLE_SUPPORT_AD_ID", "null"
|
buildConfigField "String", "SINGLE_SUPPORT_AD_ID", "null"
|
||||||
buildConfigField "String", "DASHBOARD_TILE_AD_ID", "null"
|
buildConfigField "String", "DASHBOARD_TILE_AD_ID", "null"
|
||||||
|
@ -68,7 +73,6 @@ android {
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
signingConfig signingConfigs.release
|
signingConfig signingConfigs.release
|
||||||
buildConfigField "String", "MESSAGES_BASE_URL", "\"https://messages.wulkanowy.net.pl\""
|
buildConfigField "String", "MESSAGES_BASE_URL", "\"https://messages.wulkanowy.net.pl\""
|
||||||
buildConfigField "String", "SCHOOLS_BASE_URL", '"https://schools.wulkanowy.net.pl"'
|
|
||||||
}
|
}
|
||||||
debug {
|
debug {
|
||||||
minifyEnabled false
|
minifyEnabled false
|
||||||
|
@ -78,11 +82,10 @@ android {
|
||||||
versionNameSuffix "-dev"
|
versionNameSuffix "-dev"
|
||||||
ext.enableCrashlytics = project.hasProperty("enableFirebase")
|
ext.enableCrashlytics = project.hasProperty("enableFirebase")
|
||||||
buildConfigField "String", "MESSAGES_BASE_URL", "\"https://messages.wulkanowy.net.pl\""
|
buildConfigField "String", "MESSAGES_BASE_URL", "\"https://messages.wulkanowy.net.pl\""
|
||||||
buildConfigField "String", "SCHOOLS_BASE_URL", '"https://schools.wulkanowy.net.pl"'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flavorDimensions += "platform"
|
flavorDimensions "platform"
|
||||||
|
|
||||||
productFlavors {
|
productFlavors {
|
||||||
hms {
|
hms {
|
||||||
|
@ -121,20 +124,20 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
testOptions {
|
testOptions.unitTests {
|
||||||
unitTests.includeAndroidResources = true
|
includeAndroidResources = true
|
||||||
// workaround HMS test errors https://github.com/robolectric/robolectric/issues/2750
|
// workaround HMS test errors https://github.com/robolectric/robolectric/issues/2750
|
||||||
unitTests.all { jvmArgs '-noverify' }
|
all { jvmArgs '-noverify' }
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
coreLibraryDesugaringEnabled true
|
coreLibraryDesugaringEnabled true
|
||||||
sourceCompatibility JavaVersion.VERSION_17
|
sourceCompatibility JavaVersion.VERSION_11
|
||||||
targetCompatibility JavaVersion.VERSION_17
|
targetCompatibility JavaVersion.VERSION_11
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "17"
|
jvmTarget = "11"
|
||||||
freeCompilerArgs += ["-opt-in=kotlin.RequiresOptIn", "-Xjvm-default=all"]
|
freeCompilerArgs += ["-opt-in=kotlin.RequiresOptIn", "-Xjvm-default=all"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,16 +156,13 @@ android {
|
||||||
kapt {
|
kapt {
|
||||||
correctErrorTypes true
|
correctErrorTypes true
|
||||||
}
|
}
|
||||||
ksp {
|
|
||||||
arg("room.schemaLocation", "$projectDir/schemas".toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
play {
|
play {
|
||||||
defaultToAppBundles = false
|
defaultToAppBundles = false
|
||||||
track = 'production'
|
track = 'production'
|
||||||
releaseStatus = ReleaseStatus.IN_PROGRESS
|
// releaseStatus = com.github.triplet.gradle.androidpublisher.ReleaseStatus.IN_PROGRESS
|
||||||
userFraction = 0.01d
|
// userFraction = 0.05d
|
||||||
updatePriority = 0
|
updatePriority = 5
|
||||||
enabled.set(false)
|
enabled.set(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,60 +171,54 @@ huaweiPublish {
|
||||||
hmsRelease {
|
hmsRelease {
|
||||||
credentialsPath = "$rootDir/app/src/release/agconnect-credentials.json"
|
credentialsPath = "$rootDir/app/src/release/agconnect-credentials.json"
|
||||||
buildFormat = "aab"
|
buildFormat = "aab"
|
||||||
deployType = "publish"
|
deployType = "draft"
|
||||||
releaseNotes = [
|
|
||||||
new ReleaseNote(
|
|
||||||
"pl-PL",
|
|
||||||
"$projectDir/src/main/play/release-notes/pl-PL/default.txt"
|
|
||||||
)
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
work_manager = "2.8.1"
|
work_manager = "2.7.1"
|
||||||
android_hilt = "1.0.0"
|
android_hilt = "1.0.0"
|
||||||
room = "2.6.0"
|
room = "2.4.3"
|
||||||
chucker = "3.5.2"
|
chucker = "3.5.2"
|
||||||
mockk = "1.13.8"
|
mockk = "1.12.7"
|
||||||
coroutines = "1.7.3"
|
coroutines = "1.6.4"
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'io.github.wulkanowy:sdk:2.2.4'
|
implementation "io.github.wulkanowy:sdk:1.7.4"
|
||||||
|
|
||||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
|
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.8'
|
||||||
|
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0"
|
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.0"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines"
|
||||||
|
|
||||||
implementation 'androidx.core:core-ktx:1.12.0'
|
implementation "androidx.core:core-ktx:1.8.0"
|
||||||
implementation 'androidx.core:core-splashscreen:1.0.1'
|
implementation 'androidx.core:core-splashscreen:1.0.0'
|
||||||
implementation "androidx.activity:activity-ktx:1.8.0"
|
implementation "androidx.activity:activity-ktx:1.5.1"
|
||||||
implementation "androidx.appcompat:appcompat:1.6.1"
|
implementation "androidx.appcompat:appcompat:1.5.0"
|
||||||
implementation "androidx.fragment:fragment-ktx:1.6.1"
|
implementation "androidx.fragment:fragment-ktx:1.5.2"
|
||||||
implementation "androidx.annotation:annotation:1.7.0"
|
implementation "androidx.annotation:annotation:1.4.0"
|
||||||
|
|
||||||
implementation "androidx.preference:preference-ktx:1.2.1"
|
implementation "androidx.preference:preference-ktx:1.2.0"
|
||||||
implementation "androidx.recyclerview:recyclerview:1.3.2"
|
implementation "androidx.recyclerview:recyclerview:1.2.1"
|
||||||
implementation "androidx.viewpager2:viewpager2:1.1.0-beta02"
|
implementation "androidx.viewpager2:viewpager2:1.1.0-beta01"
|
||||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
|
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
|
||||||
implementation "androidx.constraintlayout:constraintlayout:2.1.4"
|
implementation "androidx.constraintlayout:constraintlayout:2.1.4"
|
||||||
implementation "androidx.coordinatorlayout:coordinatorlayout:1.2.0"
|
implementation "androidx.coordinatorlayout:coordinatorlayout:1.2.0"
|
||||||
implementation "com.google.android.material:material:1.10.0"
|
implementation "com.google.android.material:material:1.6.1"
|
||||||
implementation "com.github.wulkanowy:material-chips-input:2.3.1"
|
implementation "com.github.wulkanowy:material-chips-input:2.3.1"
|
||||||
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
|
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
|
||||||
implementation 'com.github.lopspower:CircularImageView:4.3.0'
|
implementation 'com.github.lopspower:CircularImageView:4.2.0'
|
||||||
|
|
||||||
implementation "androidx.work:work-runtime-ktx:$work_manager"
|
implementation "androidx.work:work-runtime-ktx:$work_manager"
|
||||||
playImplementation "androidx.work:work-gcm:$work_manager"
|
playImplementation "androidx.work:work-gcm:$work_manager"
|
||||||
|
|
||||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.2"
|
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.5.1"
|
||||||
|
|
||||||
implementation "androidx.room:room-runtime:$room"
|
implementation "androidx.room:room-runtime:$room"
|
||||||
implementation "androidx.room:room-ktx:$room"
|
implementation "androidx.room:room-ktx:$room"
|
||||||
ksp "androidx.room:room-compiler:$room"
|
kapt "androidx.room:room-compiler:$room"
|
||||||
|
|
||||||
implementation "com.google.dagger:hilt-android:$hilt_version"
|
implementation "com.google.dagger:hilt-android:$hilt_version"
|
||||||
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
|
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
|
||||||
|
@ -235,31 +229,28 @@ dependencies {
|
||||||
implementation "com.github.YarikSOffice:lingver:1.3.0"
|
implementation "com.github.YarikSOffice:lingver:1.3.0"
|
||||||
|
|
||||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||||
implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0"
|
implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0"
|
||||||
implementation "com.squareup.okhttp3:logging-interceptor:4.12.0"
|
implementation "com.squareup.okhttp3:logging-interceptor:4.10.0"
|
||||||
|
|
||||||
implementation "com.jakewharton.timber:timber:5.0.1"
|
implementation "com.jakewharton.timber:timber:5.0.1"
|
||||||
implementation "at.favre.lib:slf4j-timber:1.0.1"
|
implementation "at.favre.lib:slf4j-timber:1.0.1"
|
||||||
implementation 'com.github.bastienpaulfr:Treessence:1.1.2'
|
implementation 'com.github.bastienpaulfr:Treessence:1.0.5'
|
||||||
implementation "com.mikepenz:aboutlibraries-core:$about_libraries"
|
implementation "com.mikepenz:aboutlibraries-core:$about_libraries"
|
||||||
implementation "io.coil-kt:coil:2.4.0"
|
implementation "io.coil-kt:coil:2.2.0"
|
||||||
implementation "io.github.wulkanowy:AppKillerManager:3.0.1"
|
implementation "io.github.wulkanowy:AppKillerManager:3.0.0"
|
||||||
implementation 'me.xdrop:fuzzywuzzy:1.4.0'
|
implementation 'me.xdrop:fuzzywuzzy:1.4.0'
|
||||||
implementation 'com.fredporciuncula:flow-preferences:1.9.1'
|
implementation 'com.fredporciuncula:flow-preferences:1.8.0'
|
||||||
implementation 'org.apache.commons:commons-text:1.10.0'
|
|
||||||
|
|
||||||
playImplementation platform('com.google.firebase:firebase-bom:32.4.0')
|
playImplementation platform('com.google.firebase:firebase-bom:30.3.2')
|
||||||
playImplementation 'com.google.firebase:firebase-analytics-ktx'
|
playImplementation 'com.google.firebase:firebase-analytics-ktx'
|
||||||
playImplementation 'com.google.firebase:firebase-messaging:'
|
playImplementation 'com.google.firebase:firebase-messaging:'
|
||||||
playImplementation 'com.google.firebase:firebase-crashlytics:'
|
playImplementation 'com.google.firebase:firebase-crashlytics:'
|
||||||
playImplementation 'com.google.firebase:firebase-config-ktx'
|
playImplementation 'com.google.android.play:core:1.10.3'
|
||||||
playImplementation 'com.google.android.gms:play-services-ads:22.4.0'
|
playImplementation 'com.google.android.play:core-ktx:1.8.1'
|
||||||
playImplementation "com.google.android.play:integrity:1.2.0"
|
playImplementation 'com.google.android.gms:play-services-ads:21.1.0'
|
||||||
playImplementation 'com.google.android.play:app-update-ktx:2.1.0'
|
|
||||||
playImplementation 'com.google.android.play:review-ktx:2.0.1'
|
|
||||||
|
|
||||||
hmsImplementation 'com.huawei.hms:hianalytics:6.12.0.300'
|
hmsImplementation 'com.huawei.hms:hianalytics:6.7.0.300'
|
||||||
hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.9.1.301'
|
hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.7.1.300'
|
||||||
|
|
||||||
releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker"
|
releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker"
|
||||||
|
|
||||||
|
@ -272,17 +263,17 @@ dependencies {
|
||||||
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines"
|
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines"
|
||||||
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||||
|
|
||||||
testImplementation 'org.robolectric:robolectric:4.10.3'
|
testImplementation 'org.robolectric:robolectric:4.8.2'
|
||||||
testImplementation "androidx.test:runner:1.5.2"
|
testImplementation "androidx.test:runner:1.4.0"
|
||||||
testImplementation "androidx.test.ext:junit:1.1.5"
|
testImplementation "androidx.test.ext:junit:1.1.3"
|
||||||
testImplementation "androidx.test:core:1.5.0"
|
testImplementation "androidx.test:core:1.4.0"
|
||||||
testImplementation "androidx.room:room-testing:$room"
|
testImplementation "androidx.room:room-testing:$room"
|
||||||
testImplementation "com.google.dagger:hilt-android-testing:$hilt_version"
|
testImplementation "com.google.dagger:hilt-android-testing:$hilt_version"
|
||||||
kaptTest "com.google.dagger:hilt-android-compiler:$hilt_version"
|
kaptTest "com.google.dagger:hilt-android-compiler:$hilt_version"
|
||||||
|
|
||||||
androidTestImplementation "androidx.test:core:1.5.0"
|
androidTestImplementation "androidx.test:core:1.4.0"
|
||||||
androidTestImplementation "androidx.test:runner:1.5.2"
|
androidTestImplementation "androidx.test:runner:1.4.0"
|
||||||
androidTestImplementation "androidx.test.ext:junit:1.1.5"
|
androidTestImplementation "androidx.test.ext:junit:1.1.3"
|
||||||
androidTestImplementation "io.mockk:mockk-android:$mockk"
|
androidTestImplementation "io.mockk:mockk-android:$mockk"
|
||||||
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
apply plugin: "jacoco"
|
apply plugin: "jacoco"
|
||||||
|
|
||||||
jacoco {
|
jacoco {
|
||||||
toolVersion "0.8.10"
|
toolVersion "0.8.7"
|
||||||
reportsDirectory.set(file("$buildDir/reports"))
|
reportsDirectory.set(file("$buildDir/reports"))
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(Test).configureEach {
|
tasks.withType(Test) {
|
||||||
jacoco.includeNoLocationClasses = true
|
jacoco.includeNoLocationClasses = true
|
||||||
jacoco.excludes = ['jdk.internal.*']
|
jacoco.excludes = ['jdk.internal.*']
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register('jacocoTestReport', JacocoReport) {
|
task jacocoTestReport(type: JacocoReport) {
|
||||||
|
|
||||||
group = "Reporting"
|
group = "Reporting"
|
||||||
description = "Generate Jacoco coverage reports"
|
description = "Generate Jacoco coverage reports"
|
||||||
|
@ -33,19 +33,19 @@ tasks.register('jacocoTestReport', JacocoReport) {
|
||||||
'**/*_Factory.*']
|
'**/*_Factory.*']
|
||||||
|
|
||||||
classDirectories.setFrom(fileTree(
|
classDirectories.setFrom(fileTree(
|
||||||
dir: "$buildDir/intermediates/classes/debug",
|
dir: "$buildDir/intermediates/classes/debug",
|
||||||
excludes: excludes
|
excludes: excludes
|
||||||
) + fileTree(
|
) + fileTree(
|
||||||
dir: "$buildDir/tmp/kotlin-classes/fdroidDebug",
|
dir: "$buildDir/tmp/kotlin-classes/fdroidDebug",
|
||||||
excludes: excludes
|
excludes: excludes
|
||||||
))
|
))
|
||||||
|
|
||||||
sourceDirectories.setFrom(files([
|
sourceDirectories.setFrom(files([
|
||||||
"src/main/java",
|
"src/main/java",
|
||||||
"src/fdroid/java"
|
"src/fdroid/java"
|
||||||
]))
|
]))
|
||||||
executionData.setFrom(fileTree(
|
executionData.setFrom(fileTree(
|
||||||
dir: project.projectDir,
|
dir: project.projectDir,
|
||||||
includes: ["**/*.exec", "**/*.ec"]
|
includes: ["**/*.exec", "**/*.ec"]
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
16
app/proguard-rules.pro
vendored
16
app/proguard-rules.pro
vendored
|
@ -1,6 +1,5 @@
|
||||||
# General
|
# General
|
||||||
-dontobfuscate
|
-dontobfuscate
|
||||||
-ignorewarnings
|
|
||||||
|
|
||||||
|
|
||||||
#Config for wulkanowy
|
#Config for wulkanowy
|
||||||
|
@ -25,18 +24,3 @@
|
||||||
|
|
||||||
#Config for Material Components
|
#Config for Material Components
|
||||||
-keep class com.google.android.material.tabs.** { *; }
|
-keep class com.google.android.material.tabs.** { *; }
|
||||||
|
|
||||||
|
|
||||||
#Config for HMS SDK
|
|
||||||
-keepattributes *Annotation*
|
|
||||||
-keepattributes Exceptions
|
|
||||||
-keepattributes InnerClasses
|
|
||||||
-keepattributes Signature
|
|
||||||
-keep class com.huawei.agconnect.**{*;}
|
|
||||||
-keep class com.huawei.hianalytics.**{*;}
|
|
||||||
-keep class com.huawei.updatesdk.**{*;}
|
|
||||||
-keep class com.huawei.hms.**{*;}
|
|
||||||
|
|
||||||
|
|
||||||
#Config for Wulkanowy SDK
|
|
||||||
-keep,allowobfuscation,allowshrinking class retrofit2.Response
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@color/colorIcon" />
|
<background android:drawable="@color/colorPrimary" />
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground_dev" />
|
<foreground android:drawable="@drawable/ic_launcher_foreground_dev" />
|
||||||
<monochrome android:drawable="@drawable/ic_launcher_foreground_dev_mono" />
|
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/colorPrimary" />
|
||||||
|
<foreground android:drawable="@drawable/ic_launcher_foreground_dev" />
|
||||||
|
</adaptive-icon>
|
BIN
app/src/debug/res/mipmap-hdpi/ic_launcher_round.png
Normal file
BIN
app/src/debug/res/mipmap-hdpi/ic_launcher_round.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.3 KiB |
BIN
app/src/debug/res/mipmap-mdpi/ic_launcher_round.png
Normal file
BIN
app/src/debug/res/mipmap-mdpi/ic_launcher_round.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
BIN
app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png
Normal file
BIN
app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6 KiB |
BIN
app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png
Normal file
BIN
app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.4 KiB |
BIN
app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png
Normal file
BIN
app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
|
@ -8,7 +8,15 @@ import javax.inject.Singleton
|
||||||
@Suppress("UNUSED_PARAMETER")
|
@Suppress("UNUSED_PARAMETER")
|
||||||
class AnalyticsHelper @Inject constructor() {
|
class AnalyticsHelper @Inject constructor() {
|
||||||
|
|
||||||
fun logEvent(name: String, vararg params: Pair<String, Any?>) = Unit
|
fun logEvent(name: String, vararg params: Pair<String, Any?>) {
|
||||||
fun setCurrentScreen(activity: Activity, name: String?) = Unit
|
// do nothing
|
||||||
fun popCurrentScreen(name: String?) = Unit
|
}
|
||||||
|
|
||||||
|
fun setCurrentScreen(activity: Activity, name: String?) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
fun popCurrentScreen(name: String?) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
package io.github.wulkanowy.utils
|
|
||||||
|
|
||||||
import android.view.View
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class InAppUpdateHelper @Inject constructor() {
|
|
||||||
|
|
||||||
lateinit var messageContainer: View
|
|
||||||
|
|
||||||
fun checkAndInstallUpdates() {}
|
|
||||||
|
|
||||||
fun onResume() {}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
package io.github.wulkanowy.utils
|
|
||||||
|
|
||||||
import javax.inject.Inject
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
class IntegrityHelper @Inject constructor() {
|
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
|
||||||
fun getIntegrityToken(requestId: String): String? = null
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
package io.github.wulkanowy.utils
|
|
||||||
|
|
||||||
import javax.inject.Inject
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
class RemoteConfigHelper @Inject constructor() : BaseRemoteConfigHelper()
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package io.github.wulkanowy.utils
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.view.View
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@Suppress("UNUSED_PARAMETER")
|
||||||
|
class UpdateHelper @Inject constructor() {
|
||||||
|
|
||||||
|
lateinit var messageContainer: View
|
||||||
|
|
||||||
|
fun checkAndInstallUpdates(activity: Activity) {}
|
||||||
|
|
||||||
|
fun onActivityResult(requestCode: Int, resultCode: Int) {}
|
||||||
|
|
||||||
|
fun onResume(activity: Activity) {}
|
||||||
|
}
|
|
@ -3,38 +3,26 @@ package io.github.wulkanowy.utils
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import com.huawei.agconnect.crash.AGConnectCrash
|
|
||||||
import com.huawei.hms.analytics.HiAnalytics
|
import com.huawei.hms.analytics.HiAnalytics
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class AnalyticsHelper @Inject constructor(
|
class AnalyticsHelper @Inject constructor(
|
||||||
@ApplicationContext private val context: Context,
|
@ApplicationContext private val context: Context
|
||||||
preferencesRepository: PreferencesRepository,
|
|
||||||
appInfo: AppInfo,
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val analytics by lazy { HiAnalytics.getInstance(context) }
|
private val analytics by lazy { HiAnalytics.getInstance(context) }
|
||||||
|
|
||||||
private val connectCrash by lazy { AGConnectCrash.getInstance() }
|
|
||||||
|
|
||||||
init {
|
|
||||||
if (!appInfo.isDebug) {
|
|
||||||
connectCrash.setUserId(preferencesRepository.installationId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun logEvent(name: String, vararg params: Pair<String, Any?>) {
|
fun logEvent(name: String, vararg params: Pair<String, Any?>) {
|
||||||
Bundle().apply {
|
Bundle().apply {
|
||||||
params.forEach { (key, value) ->
|
params.forEach {
|
||||||
if (value == null) return@forEach
|
if (it.second == null) return@forEach
|
||||||
when (value) {
|
when (it.second) {
|
||||||
is String -> putString(key, value)
|
is String, is String? -> putString(it.first, it.second as String)
|
||||||
is Int -> putInt(key, value)
|
is Int, is Int? -> putInt(it.first, it.second as Int)
|
||||||
is Boolean -> putBoolean(key, value)
|
is Boolean, is Boolean? -> putBoolean(it.first, it.second as Boolean)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
analytics.onEvent(name, this)
|
analytics.onEvent(name, this)
|
||||||
|
|
|
@ -2,8 +2,7 @@ package io.github.wulkanowy.utils
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.huawei.agconnect.crash.AGConnectCrash
|
import com.huawei.agconnect.crash.AGConnectCrash
|
||||||
import fr.bipi.treessence.base.FormatterPriorityTree
|
import fr.bipi.tressence.base.FormatterPriorityTree
|
||||||
import fr.bipi.treessence.common.StackTraceRecorder
|
|
||||||
|
|
||||||
class CrashLogTree : FormatterPriorityTree(Log.VERBOSE) {
|
class CrashLogTree : FormatterPriorityTree(Log.VERBOSE) {
|
||||||
|
|
||||||
|
@ -23,10 +22,16 @@ class CrashLogExceptionTree : FormatterPriorityTree(Log.ERROR, ExceptionFilter)
|
||||||
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
|
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
|
||||||
if (skipLog(priority, tag, message, t)) return
|
if (skipLog(priority, tag, message, t)) return
|
||||||
|
|
||||||
|
// Disabled due to a bug in the Huawei library
|
||||||
|
|
||||||
|
/*connectCrash.setCustomKey("priority", priority)
|
||||||
|
connectCrash.setCustomKey("tag", tag.orEmpty())
|
||||||
|
connectCrash.setCustomKey("message", message)
|
||||||
|
|
||||||
if (t != null) {
|
if (t != null) {
|
||||||
connectCrash.recordException(t)
|
connectCrash.recordException(t)
|
||||||
} else {
|
} else {
|
||||||
connectCrash.recordException(StackTraceRecorder(format(priority, tag, message)))
|
connectCrash.recordException(StackTraceRecorder(format(priority, tag, message)))
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
package io.github.wulkanowy.utils
|
|
||||||
|
|
||||||
import android.view.View
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class InAppUpdateHelper @Inject constructor() {
|
|
||||||
|
|
||||||
lateinit var messageContainer: View
|
|
||||||
|
|
||||||
fun checkAndInstallUpdates() {}
|
|
||||||
|
|
||||||
fun onResume() {}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
package io.github.wulkanowy.utils
|
|
||||||
|
|
||||||
import javax.inject.Inject
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
class IntegrityHelper @Inject constructor() {
|
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
|
||||||
fun getIntegrityToken(requestId: String): String? = null
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
package io.github.wulkanowy.utils
|
|
||||||
|
|
||||||
import javax.inject.Inject
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
class RemoteConfigHelper @Inject constructor() : BaseRemoteConfigHelper()
|
|
17
app/src/hms/java/io/github/wulkanowy/utils/UpdateHelper.kt
Normal file
17
app/src/hms/java/io/github/wulkanowy/utils/UpdateHelper.kt
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
package io.github.wulkanowy.utils
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.view.View
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@Suppress("UNUSED_PARAMETER")
|
||||||
|
class UpdateHelper @Inject constructor() {
|
||||||
|
|
||||||
|
lateinit var messageContainer: View
|
||||||
|
|
||||||
|
fun checkAndInstallUpdates(activity: Activity) {}
|
||||||
|
|
||||||
|
fun onActivityResult(requestCode: Int, resultCode: Int) {}
|
||||||
|
|
||||||
|
fun onResume(activity: Activity) {}
|
||||||
|
}
|
|
@ -8,8 +8,7 @@
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
|
||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
|
||||||
|
|
||||||
<queries>
|
<queries>
|
||||||
<intent>
|
<intent>
|
||||||
|
@ -37,14 +36,13 @@
|
||||||
<application
|
<application
|
||||||
android:name=".WulkanowyApp"
|
android:name=".WulkanowyApp"
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
|
||||||
android:enableOnBackInvokedCallback="true"
|
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:networkSecurityConfig="@xml/network_security_config"
|
android:networkSecurityConfig="@xml/network_security_config"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="false"
|
android:supportsRtl="false"
|
||||||
android:theme="@style/WulkanowyTheme"
|
android:theme="@style/WulkanowyTheme"
|
||||||
tools:ignore="DataExtractionRules,UnusedAttribute">
|
tools:ignore="GoogleAppIndexingWarning,UnusedAttribute">
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.modules.splash.SplashActivity"
|
android:name=".ui.modules.splash.SplashActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
@ -72,7 +70,7 @@
|
||||||
android:name=".ui.modules.message.send.SendMessageActivity"
|
android:name=".ui.modules.message.send.SendMessageActivity"
|
||||||
android:configChanges="orientation|screenSize"
|
android:configChanges="orientation|screenSize"
|
||||||
android:label="@string/send_message_title"
|
android:label="@string/send_message_title"
|
||||||
android:theme="@style/WulkanowyTheme.NoActionBar"
|
android:theme="@style/WulkanowyTheme.MessageSend"
|
||||||
android:windowSoftInputMode="adjustResize" />
|
android:windowSoftInputMode="adjustResize" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.modules.timetablewidget.TimetableWidgetConfigureActivity"
|
android:name=".ui.modules.timetablewidget.TimetableWidgetConfigureActivity"
|
||||||
|
|
|
@ -50,9 +50,5 @@
|
||||||
{
|
{
|
||||||
"displayName": "Tomasz F.",
|
"displayName": "Tomasz F.",
|
||||||
"githubUsername": "Pengwius"
|
"githubUsername": "Pengwius"
|
||||||
},
|
|
||||||
{
|
|
||||||
"displayName": "Antoni Paduch",
|
|
||||||
"githubUsername": "janAte1"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -6,7 +6,7 @@ import androidx.hilt.work.HiltWorkerFactory
|
||||||
import androidx.work.Configuration
|
import androidx.work.Configuration
|
||||||
import com.yariksoffice.lingver.Lingver
|
import com.yariksoffice.lingver.Lingver
|
||||||
import dagger.hilt.android.HiltAndroidApp
|
import dagger.hilt.android.HiltAndroidApp
|
||||||
import fr.bipi.treessence.file.FileLoggerTree
|
import fr.bipi.tressence.file.FileLoggerTree
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||||
import io.github.wulkanowy.ui.base.ThemeManager
|
import io.github.wulkanowy.ui.base.ThemeManager
|
||||||
import io.github.wulkanowy.utils.*
|
import io.github.wulkanowy.utils.*
|
||||||
|
@ -34,15 +34,11 @@ class WulkanowyApp : Application(), Configuration.Provider {
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var adsHelper: AdsHelper
|
lateinit var adsHelper: AdsHelper
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var remoteConfigHelper: RemoteConfigHelper
|
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
initializeAppLanguage()
|
initializeAppLanguage()
|
||||||
themeManager.applyDefaultTheme()
|
themeManager.applyDefaultTheme()
|
||||||
adsHelper.initialize()
|
adsHelper.initialize()
|
||||||
remoteConfigHelper.initialize()
|
|
||||||
initLogging()
|
initLogging()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,12 @@ import dagger.hilt.InstallIn
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import dagger.hilt.components.SingletonComponent
|
import dagger.hilt.components.SingletonComponent
|
||||||
import io.github.wulkanowy.data.api.AdminMessageService
|
import io.github.wulkanowy.data.api.AdminMessageService
|
||||||
import io.github.wulkanowy.data.api.SchoolsService
|
|
||||||
import io.github.wulkanowy.data.db.AppDatabase
|
import io.github.wulkanowy.data.db.AppDatabase
|
||||||
import io.github.wulkanowy.data.db.SharedPrefProvider
|
import io.github.wulkanowy.data.db.SharedPrefProvider
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.AppInfo
|
import io.github.wulkanowy.utils.AppInfo
|
||||||
import io.github.wulkanowy.utils.RemoteConfigHelper
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import okhttp3.MediaType.Companion.toMediaType
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
@ -37,11 +36,10 @@ internal class DataModule {
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideSdk(chuckerInterceptor: ChuckerInterceptor, remoteConfig: RemoteConfigHelper) =
|
fun provideSdk(chuckerInterceptor: ChuckerInterceptor) =
|
||||||
Sdk().apply {
|
Sdk().apply {
|
||||||
androidVersion = android.os.Build.VERSION.RELEASE
|
androidVersion = android.os.Build.VERSION.RELEASE
|
||||||
buildTag = android.os.Build.MODEL
|
buildTag = android.os.Build.MODEL
|
||||||
userAgentTemplate = remoteConfig.userAgentTemplate
|
|
||||||
setSimpleHttpLogger { Timber.d(it) }
|
setSimpleHttpLogger { Timber.d(it) }
|
||||||
|
|
||||||
// for debug only
|
// for debug only
|
||||||
|
@ -81,31 +79,22 @@ internal class DataModule {
|
||||||
.readTimeout(30, TimeUnit.SECONDS)
|
.readTimeout(30, TimeUnit.SECONDS)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideAdminMessageService(
|
fun provideRetrofit(
|
||||||
okHttpClient: OkHttpClient,
|
okHttpClient: OkHttpClient,
|
||||||
json: Json,
|
json: Json,
|
||||||
appInfo: AppInfo
|
appInfo: AppInfo
|
||||||
): AdminMessageService = Retrofit.Builder()
|
): Retrofit = Retrofit.Builder()
|
||||||
.baseUrl(appInfo.messagesBaseUrl)
|
.baseUrl(appInfo.messagesBaseUrl)
|
||||||
.client(okHttpClient)
|
.client(okHttpClient)
|
||||||
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
|
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
|
||||||
.build()
|
.build()
|
||||||
.create()
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideSchoolsService(
|
fun provideAdminMessageService(retrofit: Retrofit): AdminMessageService = retrofit.create()
|
||||||
okHttpClient: OkHttpClient,
|
|
||||||
json: Json,
|
|
||||||
appInfo: AppInfo,
|
|
||||||
): SchoolsService = Retrofit.Builder()
|
|
||||||
.baseUrl(appInfo.schoolsBaseUrl)
|
|
||||||
.client(okHttpClient)
|
|
||||||
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
|
|
||||||
.build()
|
|
||||||
.create()
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
|
|
|
@ -49,8 +49,8 @@ fun <T, U> Resource<T>.mapData(block: (T) -> U) = when (this) {
|
||||||
|
|
||||||
fun <T> Flow<Resource<T>>.logResourceStatus(name: String, showData: Boolean = false) = onEach {
|
fun <T> Flow<Resource<T>>.logResourceStatus(name: String, showData: Boolean = false) = onEach {
|
||||||
val description = when (it) {
|
val description = when (it) {
|
||||||
is Resource.Intermediate -> "intermediate data received" + if (showData) " (data: `${it.data}`)" else ""
|
|
||||||
is Resource.Loading -> "started"
|
is Resource.Loading -> "started"
|
||||||
|
is Resource.Intermediate -> "intermediate data received" + if (showData) " (data: `${it.data}`)" else ""
|
||||||
is Resource.Success -> "success" + if (showData) " (data: `${it.data}`)" else ""
|
is Resource.Success -> "success" + if (showData) " (data: `${it.data}`)" else ""
|
||||||
is Resource.Error -> "exception occurred: ${it.error}"
|
is Resource.Error -> "exception occurred: ${it.error}"
|
||||||
}
|
}
|
||||||
|
@ -148,7 +148,7 @@ inline fun <ResultType, RequestType, T> networkBoundResource(
|
||||||
crossinline saveFetchResult: suspend (old: ResultType, new: RequestType) -> Unit,
|
crossinline saveFetchResult: suspend (old: ResultType, new: RequestType) -> Unit,
|
||||||
crossinline onFetchFailed: (Throwable) -> Unit = { },
|
crossinline onFetchFailed: (Throwable) -> Unit = { },
|
||||||
crossinline shouldFetch: (ResultType) -> Boolean = { true },
|
crossinline shouldFetch: (ResultType) -> Boolean = { true },
|
||||||
crossinline mapResult: (ResultType) -> T,
|
crossinline mapResult: (ResultType) -> T
|
||||||
) = flow {
|
) = flow {
|
||||||
emit(Resource.Loading())
|
emit(Resource.Loading())
|
||||||
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
package io.github.wulkanowy.data.api
|
|
||||||
|
|
||||||
import io.github.wulkanowy.data.pojos.IntegrityRequest
|
|
||||||
import io.github.wulkanowy.data.pojos.LoginEvent
|
|
||||||
import retrofit2.http.Body
|
|
||||||
import retrofit2.http.POST
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
interface SchoolsService {
|
|
||||||
|
|
||||||
@POST("/log/loginEvent")
|
|
||||||
suspend fun logLoginEvent(@Body request: IntegrityRequest<LoginEvent>)
|
|
||||||
}
|
|
|
@ -47,10 +47,6 @@ import javax.inject.Singleton
|
||||||
AutoMigration(from = 44, to = 45),
|
AutoMigration(from = 44, to = 45),
|
||||||
AutoMigration(from = 46, to = 47),
|
AutoMigration(from = 46, to = 47),
|
||||||
AutoMigration(from = 47, to = 48),
|
AutoMigration(from = 47, to = 48),
|
||||||
AutoMigration(from = 51, to = 52),
|
|
||||||
AutoMigration(from = 54, to = 55, spec = Migration55::class),
|
|
||||||
AutoMigration(from = 55, to = 56),
|
|
||||||
AutoMigration(from = 56, to = 57, spec = Migration57::class),
|
|
||||||
],
|
],
|
||||||
version = AppDatabase.VERSION_SCHEMA,
|
version = AppDatabase.VERSION_SCHEMA,
|
||||||
exportSchema = true
|
exportSchema = true
|
||||||
|
@ -59,7 +55,7 @@ import javax.inject.Singleton
|
||||||
abstract class AppDatabase : RoomDatabase() {
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val VERSION_SCHEMA = 57
|
const val VERSION_SCHEMA = 51
|
||||||
|
|
||||||
fun getMigrations(sharedPrefProvider: SharedPrefProvider, appInfo: AppInfo) = arrayOf(
|
fun getMigrations(sharedPrefProvider: SharedPrefProvider, appInfo: AppInfo) = arrayOf(
|
||||||
Migration2(),
|
Migration2(),
|
||||||
|
@ -109,8 +105,6 @@ abstract class AppDatabase : RoomDatabase() {
|
||||||
Migration49(),
|
Migration49(),
|
||||||
Migration50(),
|
Migration50(),
|
||||||
Migration51(),
|
Migration51(),
|
||||||
Migration53(),
|
|
||||||
Migration54(),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
fun newInstance(
|
fun newInstance(
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package io.github.wulkanowy.data.db
|
package io.github.wulkanowy.data.db
|
||||||
|
|
||||||
import androidx.room.TypeConverter
|
import androidx.room.TypeConverter
|
||||||
import io.github.wulkanowy.data.enums.MessageType
|
|
||||||
import io.github.wulkanowy.ui.modules.Destination
|
import io.github.wulkanowy.ui.modules.Destination
|
||||||
import io.github.wulkanowy.utils.toTimestamp
|
import io.github.wulkanowy.utils.toTimestamp
|
||||||
import kotlinx.serialization.SerializationException
|
import kotlinx.serialization.SerializationException
|
||||||
|
@ -69,9 +68,4 @@ class Converters {
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun stringToDestination(destination: String): Destination = json.decodeFromString(destination)
|
fun stringToDestination(destination: String): Destination = json.decodeFromString(destination)
|
||||||
|
|
||||||
@TypeConverter
|
|
||||||
fun messageTypesToString(types: List<MessageType>): String = json.encodeToString(types)
|
|
||||||
|
|
||||||
@TypeConverter
|
|
||||||
fun stringToMessageTypes(text: String): List<MessageType> = json.decodeFromString(text)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,16 +3,12 @@ package io.github.wulkanowy.data.db.dao
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.Mailbox
|
import io.github.wulkanowy.data.db.entities.Mailbox
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Dao
|
@Dao
|
||||||
interface MailboxDao : BaseDao<Mailbox> {
|
interface MailboxDao : BaseDao<Mailbox> {
|
||||||
|
|
||||||
@Query("SELECT * FROM Mailboxes WHERE email = :email")
|
@Query("SELECT * FROM Mailboxes WHERE userLoginId = :userLoginId ")
|
||||||
suspend fun loadAll(email: String): List<Mailbox>
|
suspend fun loadAll(userLoginId: Int): List<Mailbox>
|
||||||
|
|
||||||
@Query("SELECT * FROM Mailboxes WHERE email = :email AND symbol = :symbol AND schoolId = :schoolId")
|
|
||||||
fun loadAll(email: String, symbol: String, schoolId: String): Flow<List<Mailbox>>
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,4 @@ interface MessagesDao : BaseDao<Message> {
|
||||||
|
|
||||||
@Query("SELECT * FROM Messages WHERE mailbox_key = :mailboxKey AND folder_id = :folder ORDER BY date DESC")
|
@Query("SELECT * FROM Messages WHERE mailbox_key = :mailboxKey AND folder_id = :folder ORDER BY date DESC")
|
||||||
fun loadAll(mailboxKey: String, folder: Int): Flow<List<Message>>
|
fun loadAll(mailboxKey: String, folder: Int): Flow<List<Message>>
|
||||||
|
|
||||||
@Query("SELECT * FROM Messages WHERE email = :email AND folder_id = :folder ORDER BY date DESC")
|
|
||||||
fun loadAll(folder: Int, email: String): Flow<List<Message>>
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
package io.github.wulkanowy.data.db.dao
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
import androidx.room.*
|
import androidx.room.*
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import androidx.room.OnConflictStrategy.ABORT
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.db.entities.StudentName
|
|
||||||
import io.github.wulkanowy.data.db.entities.StudentNickAndAvatar
|
import io.github.wulkanowy.data.db.entities.StudentNickAndAvatar
|
||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
@ -12,7 +11,7 @@ import javax.inject.Singleton
|
||||||
@Dao
|
@Dao
|
||||||
abstract class StudentDao {
|
abstract class StudentDao {
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.ABORT)
|
@Insert(onConflict = ABORT)
|
||||||
abstract suspend fun insertAll(student: List<Student>): List<Long>
|
abstract suspend fun insertAll(student: List<Student>): List<Long>
|
||||||
|
|
||||||
@Delete
|
@Delete
|
||||||
|
@ -21,9 +20,6 @@ abstract class StudentDao {
|
||||||
@Update(entity = Student::class)
|
@Update(entity = Student::class)
|
||||||
abstract suspend fun update(studentNickAndAvatar: StudentNickAndAvatar)
|
abstract suspend fun update(studentNickAndAvatar: StudentNickAndAvatar)
|
||||||
|
|
||||||
@Update(entity = Student::class)
|
|
||||||
abstract suspend fun update(studentName: StudentName)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM Students WHERE is_current = 1")
|
@Query("SELECT * FROM Students WHERE is_current = 1")
|
||||||
abstract suspend fun loadCurrent(): Student?
|
abstract suspend fun loadCurrent(): Student?
|
||||||
|
|
||||||
|
@ -34,12 +30,12 @@ abstract class StudentDao {
|
||||||
abstract suspend fun loadAll(): List<Student>
|
abstract suspend fun loadAll(): List<Student>
|
||||||
|
|
||||||
@Transaction
|
@Transaction
|
||||||
@Query("SELECT * FROM Students JOIN Semesters ON Students.student_id = Semesters.student_id AND Students.class_id = Semesters.class_id")
|
@Query("SELECT * FROM Students")
|
||||||
abstract suspend fun loadStudentsWithSemesters(): Map<Student, List<Semester>>
|
abstract suspend fun loadStudentsWithSemesters(): List<StudentWithSemesters>
|
||||||
|
|
||||||
@Transaction
|
@Transaction
|
||||||
@Query("SELECT * FROM Students JOIN Semesters ON Students.student_id = Semesters.student_id AND Students.class_id = Semesters.class_id WHERE Students.id = :id")
|
@Query("SELECT * FROM Students WHERE id = :id")
|
||||||
abstract suspend fun loadStudentWithSemestersById(id: Long): Map<Student, List<Semester>>
|
abstract suspend fun loadStudentWithSemestersById(id: Long): StudentWithSemesters?
|
||||||
|
|
||||||
@Query("UPDATE Students SET is_current = 1 WHERE id = :id")
|
@Query("UPDATE Students SET is_current = 1 WHERE id = :id")
|
||||||
abstract suspend fun updateCurrent(id: Long)
|
abstract suspend fun updateCurrent(id: Long)
|
||||||
|
|
|
@ -13,7 +13,4 @@ interface TimetableDao : BaseDao<Timetable> {
|
||||||
|
|
||||||
@Query("SELECT * FROM Timetable WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
@Query("SELECT * FROM Timetable WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
||||||
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow<List<Timetable>>
|
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow<List<Timetable>>
|
||||||
|
|
||||||
@Query("SELECT * FROM Timetable WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
|
||||||
fun load(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): List<Timetable>
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ package io.github.wulkanowy.data.db.entities
|
||||||
import androidx.room.ColumnInfo
|
import androidx.room.ColumnInfo
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import io.github.wulkanowy.data.enums.MessageType
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
@ -34,8 +33,7 @@ data class AdminMessage(
|
||||||
|
|
||||||
val priority: String,
|
val priority: String,
|
||||||
|
|
||||||
@ColumnInfo(name = "types", defaultValue = "[]")
|
val type: String,
|
||||||
val types: List<MessageType> = emptyList(),
|
|
||||||
|
|
||||||
@ColumnInfo(name = "is_dismissible")
|
@ColumnInfo(name = "is_dismissible")
|
||||||
val isDismissible: Boolean = false
|
val isDismissible: Boolean = false
|
||||||
|
|
|
@ -22,7 +22,6 @@ data class Exam(
|
||||||
|
|
||||||
val subject: String,
|
val subject: String,
|
||||||
|
|
||||||
@Deprecated("not available anymore")
|
|
||||||
val group: String,
|
val group: String,
|
||||||
|
|
||||||
val type: String,
|
val type: String,
|
||||||
|
|
|
@ -1,27 +1,20 @@
|
||||||
package io.github.wulkanowy.data.db.entities
|
package io.github.wulkanowy.data.db.entities
|
||||||
|
|
||||||
import android.os.Parcelable
|
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import kotlinx.parcelize.Parcelize
|
|
||||||
|
|
||||||
@Parcelize
|
|
||||||
@Entity(tableName = "Mailboxes")
|
@Entity(tableName = "Mailboxes")
|
||||||
data class Mailbox(
|
data class Mailbox(
|
||||||
|
|
||||||
@PrimaryKey
|
@PrimaryKey
|
||||||
val globalKey: String,
|
val globalKey: String,
|
||||||
|
|
||||||
val email: String,
|
|
||||||
val symbol: String,
|
|
||||||
val schoolId: String,
|
|
||||||
|
|
||||||
val fullName: String,
|
val fullName: String,
|
||||||
val userName: String,
|
val userName: String,
|
||||||
|
val userLoginId: Int,
|
||||||
val studentName: String,
|
val studentName: String,
|
||||||
val schoolNameShort: String,
|
val schoolNameShort: String,
|
||||||
val type: MailboxType,
|
val type: MailboxType,
|
||||||
) : java.io.Serializable, Parcelable
|
)
|
||||||
|
|
||||||
enum class MailboxType {
|
enum class MailboxType {
|
||||||
STUDENT,
|
STUDENT,
|
||||||
|
|
|
@ -9,9 +9,6 @@ import java.time.Instant
|
||||||
@Entity(tableName = "Messages")
|
@Entity(tableName = "Messages")
|
||||||
data class Message(
|
data class Message(
|
||||||
|
|
||||||
@ColumnInfo(name = "email")
|
|
||||||
val email: String,
|
|
||||||
|
|
||||||
@ColumnInfo(name = "message_global_key")
|
@ColumnInfo(name = "message_global_key")
|
||||||
val messageGlobalKey: String,
|
val messageGlobalKey: String,
|
||||||
|
|
||||||
|
@ -32,12 +29,6 @@ data class Message(
|
||||||
|
|
||||||
var unread: Boolean,
|
var unread: Boolean,
|
||||||
|
|
||||||
@ColumnInfo(name = "read_by")
|
|
||||||
val readBy: Int?,
|
|
||||||
|
|
||||||
@ColumnInfo(name = "unread_by")
|
|
||||||
val unreadBy: Int?,
|
|
||||||
|
|
||||||
@ColumnInfo(name = "has_attachments")
|
@ColumnInfo(name = "has_attachments")
|
||||||
val hasAttachments: Boolean
|
val hasAttachments: Boolean
|
||||||
) : Serializable {
|
) : Serializable {
|
||||||
|
|
|
@ -2,14 +2,16 @@ package io.github.wulkanowy.data.db.entities
|
||||||
|
|
||||||
import androidx.room.ColumnInfo
|
import androidx.room.ColumnInfo
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
@Entity(
|
@Entity(tableName = "MessageAttachments")
|
||||||
tableName = "MessageAttachments",
|
|
||||||
primaryKeys = ["message_global_key", "url", "filename"],
|
|
||||||
)
|
|
||||||
data class MessageAttachment(
|
data class MessageAttachment(
|
||||||
|
|
||||||
|
@PrimaryKey
|
||||||
|
@ColumnInfo(name = "real_id")
|
||||||
|
val realId: Int,
|
||||||
|
|
||||||
@ColumnInfo(name = "message_global_key")
|
@ColumnInfo(name = "message_global_key")
|
||||||
val messageGlobalKey: String,
|
val messageGlobalKey: String,
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,6 @@ data class Student(
|
||||||
@ColumnInfo(name = "scrapper_base_url")
|
@ColumnInfo(name = "scrapper_base_url")
|
||||||
val scrapperBaseUrl: String,
|
val scrapperBaseUrl: String,
|
||||||
|
|
||||||
@ColumnInfo(name = "scrapper_domain_suffix", defaultValue = "")
|
|
||||||
val scrapperDomainSuffix: String,
|
|
||||||
|
|
||||||
@ColumnInfo(name = "mobile_base_url")
|
@ColumnInfo(name = "mobile_base_url")
|
||||||
val mobileBaseUrl: String,
|
val mobileBaseUrl: String,
|
||||||
|
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.entities
|
|
||||||
|
|
||||||
import androidx.room.ColumnInfo
|
|
||||||
import androidx.room.Entity
|
|
||||||
import androidx.room.PrimaryKey
|
|
||||||
import java.io.Serializable
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
data class StudentName(
|
|
||||||
|
|
||||||
@ColumnInfo(name = "student_name")
|
|
||||||
val studentName: String
|
|
||||||
|
|
||||||
) : Serializable {
|
|
||||||
|
|
||||||
@PrimaryKey
|
|
||||||
var id: Long = 0
|
|
||||||
}
|
|
|
@ -1,8 +1,13 @@
|
||||||
package io.github.wulkanowy.data.db.entities
|
package io.github.wulkanowy.data.db.entities
|
||||||
|
|
||||||
|
import androidx.room.Embedded
|
||||||
|
import androidx.room.Relation
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
data class StudentWithSemesters(
|
data class StudentWithSemesters(
|
||||||
|
@Embedded
|
||||||
val student: Student,
|
val student: Student,
|
||||||
|
|
||||||
|
@Relation(parentColumn = "student_id", entityColumn = "student_id")
|
||||||
val semesters: List<Semester>
|
val semesters: List<Semester>
|
||||||
) : Serializable
|
) : Serializable
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.migrations
|
|
||||||
|
|
||||||
import androidx.room.migration.Migration
|
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
|
||||||
|
|
||||||
class Migration53 : Migration(52, 53) {
|
|
||||||
|
|
||||||
override fun migrate(database: SupportSQLiteDatabase) {
|
|
||||||
createMailboxTable(database)
|
|
||||||
recreateMessagesTable(database)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createMailboxTable(database: SupportSQLiteDatabase) {
|
|
||||||
database.execSQL("DROP TABLE IF EXISTS Mailboxes")
|
|
||||||
database.execSQL(
|
|
||||||
"""
|
|
||||||
CREATE TABLE IF NOT EXISTS `Mailboxes` (
|
|
||||||
`globalKey` TEXT NOT NULL,
|
|
||||||
`email` TEXT NOT NULL,
|
|
||||||
`symbol` TEXT NOT NULL,
|
|
||||||
`schoolId` TEXT NOT NULL,
|
|
||||||
`fullName` TEXT NOT NULL,
|
|
||||||
`userName` TEXT NOT NULL,
|
|
||||||
`studentName` TEXT NOT NULL,
|
|
||||||
`schoolNameShort` TEXT NOT NULL,
|
|
||||||
`type` TEXT NOT NULL,
|
|
||||||
PRIMARY KEY(`globalKey`)
|
|
||||||
)""".trimIndent()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun recreateMessagesTable(database: SupportSQLiteDatabase) {
|
|
||||||
database.execSQL("DROP TABLE IF EXISTS Messages")
|
|
||||||
database.execSQL(
|
|
||||||
"""
|
|
||||||
CREATE TABLE IF NOT EXISTS `Messages` (
|
|
||||||
`email` TEXT NOT NULL,
|
|
||||||
`message_global_key` TEXT NOT NULL,
|
|
||||||
`mailbox_key` TEXT NOT NULL,
|
|
||||||
`message_id` INTEGER NOT NULL,
|
|
||||||
`correspondents` TEXT NOT NULL,
|
|
||||||
`subject` TEXT NOT NULL,
|
|
||||||
`date` INTEGER NOT NULL,
|
|
||||||
`folder_id` INTEGER NOT NULL,
|
|
||||||
`unread` INTEGER NOT NULL,
|
|
||||||
`read_by` INTEGER,
|
|
||||||
`unread_by` INTEGER,
|
|
||||||
`has_attachments` INTEGER NOT NULL,
|
|
||||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
||||||
`is_notified` INTEGER NOT NULL,
|
|
||||||
`content` TEXT NOT NULL,
|
|
||||||
`sender` TEXT,
|
|
||||||
`recipients` TEXT
|
|
||||||
)""".trimIndent()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.migrations
|
|
||||||
|
|
||||||
import androidx.room.migration.Migration
|
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
|
||||||
|
|
||||||
class Migration54 : Migration(53, 54) {
|
|
||||||
|
|
||||||
override fun migrate(database: SupportSQLiteDatabase) {
|
|
||||||
migrateResman(database)
|
|
||||||
removeTomaszowMazowieckiStudents(database)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun migrateResman(database: SupportSQLiteDatabase) {
|
|
||||||
database.execSQL("""
|
|
||||||
UPDATE Students SET
|
|
||||||
scrapper_base_url = 'https://vulcan.net.pl',
|
|
||||||
login_type = 'ADFSLightScoped',
|
|
||||||
symbol = 'rzeszowprojekt'
|
|
||||||
WHERE scrapper_base_url = 'https://resman.pl'
|
|
||||||
""".trimIndent())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun removeTomaszowMazowieckiStudents(database: SupportSQLiteDatabase) {
|
|
||||||
database.execSQL("DELETE FROM Students WHERE symbol = 'tomaszowmazowiecki'")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.migrations
|
|
||||||
|
|
||||||
import androidx.room.DeleteColumn
|
|
||||||
import androidx.room.migration.AutoMigrationSpec
|
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
|
||||||
|
|
||||||
@DeleteColumn(
|
|
||||||
tableName = "MessageAttachments",
|
|
||||||
columnName = "real_id",
|
|
||||||
)
|
|
||||||
class Migration55 : AutoMigrationSpec {
|
|
||||||
|
|
||||||
override fun onPostMigrate(db: SupportSQLiteDatabase) {
|
|
||||||
db.execSQL("DELETE FROM Messages")
|
|
||||||
db.execSQL("DELETE FROM MessageAttachments")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.migrations
|
|
||||||
|
|
||||||
import androidx.room.DeleteColumn
|
|
||||||
import androidx.room.migration.AutoMigrationSpec
|
|
||||||
|
|
||||||
@DeleteColumn(
|
|
||||||
tableName = "AdminMessages",
|
|
||||||
columnName = "type",
|
|
||||||
)
|
|
||||||
class Migration57 : AutoMigrationSpec
|
|
|
@ -1,9 +0,0 @@
|
||||||
package io.github.wulkanowy.data.enums
|
|
||||||
|
|
||||||
enum class MessageType {
|
|
||||||
GENERAL_MESSAGE,
|
|
||||||
DASHBOARD_MESSAGE,
|
|
||||||
LOGIN_MESSAGE,
|
|
||||||
PASS_RESET_MESSAGE,
|
|
||||||
ERROR_OVERRIDE,
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
package io.github.wulkanowy.data.enums
|
|
||||||
|
|
||||||
enum class TimetableGapsMode(val value: String) {
|
|
||||||
NO_GAPS("no_gaps"),
|
|
||||||
BETWEEN_LESSONS("between"),
|
|
||||||
BETWEEN_AND_BEFORE_LESSONS("before_and_between");
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun getByValue(value: String) = entries.find { it.value == value } ?: BETWEEN_LESSONS
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,22 +3,17 @@ package io.github.wulkanowy.data.mappers
|
||||||
import io.github.wulkanowy.data.db.entities.Attendance
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
import io.github.wulkanowy.data.db.entities.AttendanceSummary
|
import io.github.wulkanowy.data.db.entities.AttendanceSummary
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Timetable
|
|
||||||
import io.github.wulkanowy.sdk.pojo.Attendance as SdkAttendance
|
import io.github.wulkanowy.sdk.pojo.Attendance as SdkAttendance
|
||||||
import io.github.wulkanowy.sdk.pojo.AttendanceSummary as SdkAttendanceSummary
|
import io.github.wulkanowy.sdk.pojo.AttendanceSummary as SdkAttendanceSummary
|
||||||
|
|
||||||
fun List<SdkAttendance>.mapToEntities(semester: Semester, lessons: List<Timetable>) = map {
|
fun List<SdkAttendance>.mapToEntities(semester: Semester) = map {
|
||||||
Attendance(
|
Attendance(
|
||||||
studentId = semester.studentId,
|
studentId = semester.studentId,
|
||||||
diaryId = semester.diaryId,
|
diaryId = semester.diaryId,
|
||||||
date = it.date,
|
date = it.date,
|
||||||
timeId = it.timeId,
|
timeId = it.timeId,
|
||||||
number = it.number,
|
number = it.number,
|
||||||
subject = it.subject.ifBlank {
|
subject = it.subject,
|
||||||
lessons.find { lesson ->
|
|
||||||
lesson.date == it.date && lesson.number == it.number
|
|
||||||
}?.subject.orEmpty()
|
|
||||||
},
|
|
||||||
name = it.name,
|
name = it.name,
|
||||||
presence = it.presence,
|
presence = it.presence,
|
||||||
absence = it.absence,
|
absence = it.absence,
|
||||||
|
|
|
@ -10,9 +10,9 @@ fun List<SdkConference>.mapToEntities(semester: Semester) = map {
|
||||||
diaryId = semester.diaryId,
|
diaryId = semester.diaryId,
|
||||||
agenda = it.agenda,
|
agenda = it.agenda,
|
||||||
conferenceId = it.id,
|
conferenceId = it.id,
|
||||||
date = it.date.toInstant(),
|
date = it.dateZoned.toInstant(),
|
||||||
presentOnConference = it.presentOnConference,
|
presentOnConference = it.presentOnConference,
|
||||||
subject = it.topic,
|
subject = it.subject,
|
||||||
title = it.place,
|
title = it.title
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ fun List<SdkExam>.mapToEntities(semester: Semester) = map {
|
||||||
date = it.date,
|
date = it.date,
|
||||||
entryDate = it.entryDate,
|
entryDate = it.entryDate,
|
||||||
subject = it.subject,
|
subject = it.subject,
|
||||||
group = "",
|
group = it.group,
|
||||||
type = it.type,
|
type = it.type,
|
||||||
description = it.description,
|
description = it.description,
|
||||||
teacher = it.teacher,
|
teacher = it.teacher,
|
||||||
|
|
|
@ -10,11 +10,9 @@ fun List<SdkMailbox>.mapToEntities(student: Student) = map {
|
||||||
globalKey = it.globalKey,
|
globalKey = it.globalKey,
|
||||||
fullName = it.fullName,
|
fullName = it.fullName,
|
||||||
userName = it.userName,
|
userName = it.userName,
|
||||||
|
userLoginId = student.userLoginId,
|
||||||
studentName = it.studentName,
|
studentName = it.studentName,
|
||||||
schoolNameShort = it.schoolNameShort,
|
schoolNameShort = it.schoolNameShort,
|
||||||
type = MailboxType.valueOf(it.type.name),
|
type = MailboxType.valueOf(it.type.name),
|
||||||
email = student.email,
|
|
||||||
symbol = student.symbol,
|
|
||||||
schoolId = student.schoolSymbol,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,36 +2,21 @@ package io.github.wulkanowy.data.mappers
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.*
|
import io.github.wulkanowy.data.db.entities.*
|
||||||
import io.github.wulkanowy.sdk.pojo.MailboxType
|
import io.github.wulkanowy.sdk.pojo.MailboxType
|
||||||
import timber.log.Timber
|
|
||||||
import io.github.wulkanowy.sdk.pojo.Message as SdkMessage
|
import io.github.wulkanowy.sdk.pojo.Message as SdkMessage
|
||||||
import io.github.wulkanowy.sdk.pojo.MessageAttachment as SdkMessageAttachment
|
import io.github.wulkanowy.sdk.pojo.MessageAttachment as SdkMessageAttachment
|
||||||
import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient
|
import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient
|
||||||
|
|
||||||
fun List<SdkMessage>.mapToEntities(
|
fun List<SdkMessage>.mapToEntities(mailbox: Mailbox) = map {
|
||||||
student: Student,
|
|
||||||
mailbox: Mailbox?,
|
|
||||||
allMailboxes: List<Mailbox>
|
|
||||||
): List<Message> = map {
|
|
||||||
Message(
|
Message(
|
||||||
messageGlobalKey = it.globalKey,
|
messageGlobalKey = it.globalKey,
|
||||||
mailboxKey = mailbox?.globalKey ?: allMailboxes.find { box ->
|
mailboxKey = mailbox.globalKey,
|
||||||
box.fullName == it.mailbox
|
|
||||||
}?.globalKey.let { mailboxKey ->
|
|
||||||
if (mailboxKey == null) {
|
|
||||||
Timber.e("Can't find ${it.mailbox} in $allMailboxes")
|
|
||||||
"unknown"
|
|
||||||
} else mailboxKey
|
|
||||||
},
|
|
||||||
email = student.email,
|
|
||||||
messageId = it.id,
|
messageId = it.id,
|
||||||
correspondents = it.correspondents,
|
correspondents = it.correspondents,
|
||||||
subject = it.subject.trim(),
|
subject = it.subject.trim(),
|
||||||
date = it.date.toInstant(),
|
date = it.dateZoned.toInstant(),
|
||||||
folderId = it.folderId,
|
folderId = it.folderId,
|
||||||
unread = it.unread,
|
unread = it.unread,
|
||||||
unreadBy = it.unreadBy,
|
hasAttachments = it.hasAttachments
|
||||||
readBy = it.readBy,
|
|
||||||
hasAttachments = it.hasAttachments,
|
|
||||||
).apply {
|
).apply {
|
||||||
content = it.content.orEmpty()
|
content = it.content.orEmpty()
|
||||||
}
|
}
|
||||||
|
@ -40,6 +25,7 @@ fun List<SdkMessage>.mapToEntities(
|
||||||
fun List<SdkMessageAttachment>.mapToEntities(messageGlobalKey: String) = map {
|
fun List<SdkMessageAttachment>.mapToEntities(messageGlobalKey: String) = map {
|
||||||
MessageAttachment(
|
MessageAttachment(
|
||||||
messageGlobalKey = messageGlobalKey,
|
messageGlobalKey = messageGlobalKey,
|
||||||
|
realId = it.url.hashCode(),
|
||||||
url = it.url,
|
url = it.url,
|
||||||
filename = it.filename
|
filename = it.filename
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,7 +9,7 @@ import io.github.wulkanowy.sdk.pojo.Token as SdkToken
|
||||||
fun List<SdkDevice>.mapToEntities(student: Student) = map {
|
fun List<SdkDevice>.mapToEntities(student: Student) = map {
|
||||||
MobileDevice(
|
MobileDevice(
|
||||||
userLoginId = student.userLoginId,
|
userLoginId = student.userLoginId,
|
||||||
date = it.createDate.toInstant(),
|
date = it.createDateZoned.toInstant(),
|
||||||
deviceId = it.id,
|
deviceId = it.id,
|
||||||
name = it.name
|
name = it.name
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,90 +0,0 @@
|
||||||
package io.github.wulkanowy.data.mappers
|
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
|
||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
|
||||||
import io.github.wulkanowy.data.pojos.*
|
|
||||||
import java.time.Instant
|
|
||||||
import io.github.wulkanowy.sdk.pojo.RegisterStudent as SdkRegisterStudent
|
|
||||||
import io.github.wulkanowy.sdk.pojo.RegisterUser as SdkRegisterUser
|
|
||||||
|
|
||||||
fun SdkRegisterUser.mapToPojo(password: String?) = RegisterUser(
|
|
||||||
email = email,
|
|
||||||
login = login,
|
|
||||||
password = password,
|
|
||||||
scrapperBaseUrl = scrapperBaseUrl,
|
|
||||||
loginMode = loginMode,
|
|
||||||
loginType = loginType,
|
|
||||||
symbols = symbols.map { registerSymbol ->
|
|
||||||
RegisterSymbol(
|
|
||||||
symbol = registerSymbol.symbol,
|
|
||||||
error = registerSymbol.error,
|
|
||||||
hebeBaseUrl = registerSymbol.hebeBaseUrl,
|
|
||||||
keyId = registerSymbol.keyId,
|
|
||||||
privatePem = registerSymbol.privatePem,
|
|
||||||
userName = registerSymbol.userName,
|
|
||||||
schools = registerSymbol.schools.map {
|
|
||||||
RegisterUnit(
|
|
||||||
userLoginId = it.userLoginId,
|
|
||||||
schoolId = it.schoolId,
|
|
||||||
schoolName = it.schoolName,
|
|
||||||
schoolShortName = it.schoolShortName,
|
|
||||||
parentIds = it.parentIds,
|
|
||||||
studentIds = it.studentIds,
|
|
||||||
employeeIds = it.employeeIds,
|
|
||||||
error = it.error,
|
|
||||||
students = it.subjects
|
|
||||||
.filterIsInstance<SdkRegisterStudent>()
|
|
||||||
.map { registerSubject ->
|
|
||||||
RegisterStudent(
|
|
||||||
studentId = registerSubject.studentId,
|
|
||||||
studentName = registerSubject.studentName,
|
|
||||||
studentSecondName = registerSubject.studentSecondName,
|
|
||||||
studentSurname = registerSubject.studentSurname,
|
|
||||||
className = registerSubject.className,
|
|
||||||
classId = registerSubject.classId,
|
|
||||||
isParent = registerSubject.isParent,
|
|
||||||
semesters = registerSubject.semesters
|
|
||||||
.mapToEntities(registerSubject.studentId),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
fun RegisterStudent.mapToStudentWithSemesters(
|
|
||||||
user: RegisterUser,
|
|
||||||
scrapperDomainSuffix: String,
|
|
||||||
symbol: RegisterSymbol,
|
|
||||||
unit: RegisterUnit,
|
|
||||||
colors: List<Long>,
|
|
||||||
): StudentWithSemesters = StudentWithSemesters(
|
|
||||||
semesters = semesters,
|
|
||||||
student = Student(
|
|
||||||
email = user.login, // for compatibility
|
|
||||||
userName = symbol.userName,
|
|
||||||
userLoginId = unit.userLoginId,
|
|
||||||
isParent = isParent,
|
|
||||||
className = className,
|
|
||||||
classId = classId,
|
|
||||||
studentId = studentId,
|
|
||||||
symbol = symbol.symbol,
|
|
||||||
loginType = user.loginType?.name.orEmpty(),
|
|
||||||
schoolName = unit.schoolName,
|
|
||||||
schoolShortName = unit.schoolShortName,
|
|
||||||
schoolSymbol = unit.schoolId,
|
|
||||||
studentName = "$studentName $studentSurname",
|
|
||||||
loginMode = user.loginMode.name,
|
|
||||||
scrapperBaseUrl = user.scrapperBaseUrl.orEmpty(),
|
|
||||||
scrapperDomainSuffix = scrapperDomainSuffix,
|
|
||||||
mobileBaseUrl = symbol.hebeBaseUrl.orEmpty(),
|
|
||||||
certificateKey = symbol.keyId.orEmpty(),
|
|
||||||
privateKey = symbol.privatePem.orEmpty(),
|
|
||||||
password = user.password.orEmpty(),
|
|
||||||
isCurrent = false,
|
|
||||||
registrationDate = Instant.now(),
|
|
||||||
).apply {
|
|
||||||
avatarColor = colors.random()
|
|
||||||
},
|
|
||||||
)
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
package io.github.wulkanowy.data.mappers
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||||
|
import java.time.Instant
|
||||||
|
import io.github.wulkanowy.sdk.pojo.Student as SdkStudent
|
||||||
|
|
||||||
|
fun List<SdkStudent>.mapToEntities(password: String = "", colors: List<Long>) = map {
|
||||||
|
StudentWithSemesters(
|
||||||
|
student = Student(
|
||||||
|
email = it.email,
|
||||||
|
password = password,
|
||||||
|
isParent = it.isParent,
|
||||||
|
symbol = it.symbol,
|
||||||
|
studentId = it.studentId,
|
||||||
|
userLoginId = it.userLoginId,
|
||||||
|
userName = it.userName,
|
||||||
|
studentName = it.studentName + " " + it.studentSurname,
|
||||||
|
schoolSymbol = it.schoolSymbol,
|
||||||
|
schoolShortName = it.schoolShortName,
|
||||||
|
schoolName = it.schoolName,
|
||||||
|
className = it.className,
|
||||||
|
classId = it.classId,
|
||||||
|
scrapperBaseUrl = it.scrapperBaseUrl,
|
||||||
|
loginType = it.loginType.name,
|
||||||
|
isCurrent = false,
|
||||||
|
registrationDate = Instant.now(),
|
||||||
|
mobileBaseUrl = it.mobileBaseUrl,
|
||||||
|
privateKey = it.privateKey,
|
||||||
|
certificateKey = it.certificateKey,
|
||||||
|
loginMode = it.loginMode.name,
|
||||||
|
).apply {
|
||||||
|
avatarColor = colors.random()
|
||||||
|
},
|
||||||
|
semesters = it.semesters.mapToEntities(it.studentId)
|
||||||
|
)
|
||||||
|
}
|
|
@ -5,10 +5,10 @@ import io.github.wulkanowy.data.db.entities.Timetable
|
||||||
import io.github.wulkanowy.data.db.entities.TimetableAdditional
|
import io.github.wulkanowy.data.db.entities.TimetableAdditional
|
||||||
import io.github.wulkanowy.data.db.entities.TimetableHeader
|
import io.github.wulkanowy.data.db.entities.TimetableHeader
|
||||||
import io.github.wulkanowy.data.pojos.TimetableFull
|
import io.github.wulkanowy.data.pojos.TimetableFull
|
||||||
import io.github.wulkanowy.sdk.pojo.Timetable as SdkTimetableFull
|
import io.github.wulkanowy.sdk.pojo.TimetableFull as SdkTimetableFull
|
||||||
import io.github.wulkanowy.sdk.pojo.TimetableDayHeader as SdkTimetableHeader
|
import io.github.wulkanowy.sdk.pojo.TimetableDayHeader as SdkTimetableHeader
|
||||||
import io.github.wulkanowy.sdk.pojo.Lesson as SdkLesson
|
import io.github.wulkanowy.sdk.pojo.Timetable as SdkTimetable
|
||||||
import io.github.wulkanowy.sdk.pojo.LessonAdditional as SdkTimetableAdditional
|
import io.github.wulkanowy.sdk.pojo.TimetableAdditional as SdkTimetableAdditional
|
||||||
|
|
||||||
fun SdkTimetableFull.mapToEntities(semester: Semester) = TimetableFull(
|
fun SdkTimetableFull.mapToEntities(semester: Semester) = TimetableFull(
|
||||||
lessons = lessons.mapToEntities(semester),
|
lessons = lessons.mapToEntities(semester),
|
||||||
|
@ -16,13 +16,13 @@ fun SdkTimetableFull.mapToEntities(semester: Semester) = TimetableFull(
|
||||||
headers = headers.mapToEntities(semester)
|
headers = headers.mapToEntities(semester)
|
||||||
)
|
)
|
||||||
|
|
||||||
fun List<SdkLesson>.mapToEntities(semester: Semester) = map {
|
fun List<SdkTimetable>.mapToEntities(semester: Semester) = map {
|
||||||
Timetable(
|
Timetable(
|
||||||
studentId = semester.studentId,
|
studentId = semester.studentId,
|
||||||
diaryId = semester.diaryId,
|
diaryId = semester.diaryId,
|
||||||
number = it.number,
|
number = it.number,
|
||||||
start = it.start.toInstant(),
|
start = it.startZoned.toInstant(),
|
||||||
end = it.end.toInstant(),
|
end = it.endZoned.toInstant(),
|
||||||
date = it.date,
|
date = it.date,
|
||||||
subject = it.subject,
|
subject = it.subject,
|
||||||
subjectOld = it.subjectOld,
|
subjectOld = it.subjectOld,
|
||||||
|
@ -45,8 +45,8 @@ fun List<SdkTimetableAdditional>.mapToEntities(semester: Semester) = map {
|
||||||
diaryId = semester.diaryId,
|
diaryId = semester.diaryId,
|
||||||
subject = it.subject,
|
subject = it.subject,
|
||||||
date = it.date,
|
date = it.date,
|
||||||
start = it.start.toInstant(),
|
start = it.startZoned.toInstant(),
|
||||||
end = it.end.toInstant(),
|
end = it.endZoned.toInstant(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
package io.github.wulkanowy.data.pojos
|
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class LoginEvent(
|
|
||||||
val uuid: String,
|
|
||||||
val schoolName: String,
|
|
||||||
val schoolShort: String,
|
|
||||||
val schoolAddress: String,
|
|
||||||
val scraperBaseUrl: String,
|
|
||||||
val symbol: String,
|
|
||||||
val schoolId: String,
|
|
||||||
val loginType: String,
|
|
||||||
)
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class IntegrityRequest<T>(
|
|
||||||
val tokenString: String,
|
|
||||||
val data: T,
|
|
||||||
)
|
|
|
@ -1,48 +0,0 @@
|
||||||
package io.github.wulkanowy.data.pojos
|
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
|
||||||
import io.github.wulkanowy.sdk.scrapper.Scrapper
|
|
||||||
|
|
||||||
data class RegisterUser(
|
|
||||||
val email: String,
|
|
||||||
val password: String?,
|
|
||||||
val login: String, // may be the same as email
|
|
||||||
val scrapperBaseUrl: String?,
|
|
||||||
val loginType: Scrapper.LoginType?,
|
|
||||||
val loginMode: Sdk.Mode,
|
|
||||||
val symbols: List<RegisterSymbol>,
|
|
||||||
) : java.io.Serializable
|
|
||||||
|
|
||||||
data class RegisterSymbol(
|
|
||||||
val symbol: String,
|
|
||||||
val error: Throwable?,
|
|
||||||
val hebeBaseUrl: String?,
|
|
||||||
val keyId: String?,
|
|
||||||
val privatePem: String?,
|
|
||||||
val userName: String,
|
|
||||||
val schools: List<RegisterUnit>,
|
|
||||||
) : java.io.Serializable
|
|
||||||
|
|
||||||
data class RegisterUnit(
|
|
||||||
val userLoginId: Int,
|
|
||||||
val schoolId: String,
|
|
||||||
val schoolName: String,
|
|
||||||
val schoolShortName: String,
|
|
||||||
val parentIds: List<Int>,
|
|
||||||
val studentIds: List<Int>,
|
|
||||||
val employeeIds: List<Int>,
|
|
||||||
val error: Throwable?,
|
|
||||||
val students: List<RegisterStudent>,
|
|
||||||
) : java.io.Serializable
|
|
||||||
|
|
||||||
data class RegisterStudent(
|
|
||||||
val studentId: Int,
|
|
||||||
val studentName: String,
|
|
||||||
val studentSecondName: String,
|
|
||||||
val studentSurname: String,
|
|
||||||
val className: String,
|
|
||||||
val classId: Int,
|
|
||||||
val isParent: Boolean,
|
|
||||||
val semesters: List<Semester>,
|
|
||||||
) : java.io.Serializable
|
|
|
@ -1,11 +1,10 @@
|
||||||
package io.github.wulkanowy.data.repositories
|
package io.github.wulkanowy.data.repositories
|
||||||
|
|
||||||
import io.github.wulkanowy.data.Resource
|
|
||||||
import io.github.wulkanowy.data.api.AdminMessageService
|
import io.github.wulkanowy.data.api.AdminMessageService
|
||||||
import io.github.wulkanowy.data.db.dao.AdminMessageDao
|
import io.github.wulkanowy.data.db.dao.AdminMessageDao
|
||||||
import io.github.wulkanowy.data.db.entities.AdminMessage
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.networkBoundResource
|
import io.github.wulkanowy.data.networkBoundResource
|
||||||
import kotlinx.coroutines.flow.Flow
|
import io.github.wulkanowy.utils.AppInfo
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
@ -14,20 +13,34 @@ import javax.inject.Singleton
|
||||||
class AdminMessageRepository @Inject constructor(
|
class AdminMessageRepository @Inject constructor(
|
||||||
private val adminMessageService: AdminMessageService,
|
private val adminMessageService: AdminMessageService,
|
||||||
private val adminMessageDao: AdminMessageDao,
|
private val adminMessageDao: AdminMessageDao,
|
||||||
|
private val appInfo: AppInfo
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val saveFetchResultMutex = Mutex()
|
private val saveFetchResultMutex = Mutex()
|
||||||
|
|
||||||
fun getAdminMessages(): Flow<Resource<List<AdminMessage>>> =
|
suspend fun getAdminMessages(student: Student) = networkBoundResource(
|
||||||
networkBoundResource(
|
mutex = saveFetchResultMutex,
|
||||||
mutex = saveFetchResultMutex,
|
isResultEmpty = { it == null },
|
||||||
isResultEmpty = { false },
|
query = { adminMessageDao.loadAll() },
|
||||||
query = { adminMessageDao.loadAll() },
|
fetch = { adminMessageService.getAdminMessages() },
|
||||||
fetch = { adminMessageService.getAdminMessages() },
|
shouldFetch = { true },
|
||||||
shouldFetch = { true },
|
saveFetchResult = { oldItems, newItems ->
|
||||||
saveFetchResult = { oldItems, newItems ->
|
adminMessageDao.removeOldAndSaveNew(oldItems, newItems)
|
||||||
adminMessageDao.removeOldAndSaveNew(oldItems, newItems)
|
},
|
||||||
},
|
showSavedOnLoading = false,
|
||||||
showSavedOnLoading = false,
|
mapResult = { adminMessages ->
|
||||||
)
|
adminMessages.filter { adminMessage ->
|
||||||
|
val isCorrectRegister = adminMessage.targetRegisterHost?.let {
|
||||||
|
student.scrapperBaseUrl.contains(it, true)
|
||||||
|
} ?: true
|
||||||
|
val isCorrectFlavor =
|
||||||
|
adminMessage.targetFlavor?.equals(appInfo.buildFlavor, true) ?: true
|
||||||
|
val isCorrectMaxVersion =
|
||||||
|
adminMessage.versionMax?.let { it >= appInfo.versionCode } ?: true
|
||||||
|
val isCorrectMinVersion =
|
||||||
|
adminMessage.versionMin?.let { it <= appInfo.versionCode } ?: true
|
||||||
|
|
||||||
|
isCorrectRegister && isCorrectFlavor && isCorrectMaxVersion && isCorrectMinVersion
|
||||||
|
}.maxByOrNull { it.id }
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ class AppCreatorRepository @Inject constructor(
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@OptIn(ExperimentalSerializationApi::class)
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
|
@Suppress("BlockingMethodInNonBlockingContext")
|
||||||
suspend fun getAppCreators() = withContext(dispatchers.io) {
|
suspend fun getAppCreators() = withContext(dispatchers.io) {
|
||||||
val inputStream = context.assets.open("contributors.json").buffered()
|
val inputStream = context.assets.open("contributors.json").buffered()
|
||||||
json.decodeFromStream<List<Contributor>>(inputStream)
|
json.decodeFromStream<List<Contributor>>(inputStream)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package io.github.wulkanowy.data.repositories
|
package io.github.wulkanowy.data.repositories
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.dao.AttendanceDao
|
import io.github.wulkanowy.data.db.dao.AttendanceDao
|
||||||
import io.github.wulkanowy.data.db.dao.TimetableDao
|
|
||||||
import io.github.wulkanowy.data.db.entities.Attendance
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
@ -10,10 +9,8 @@ import io.github.wulkanowy.data.networkBoundResource
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.sdk.pojo.Absent
|
import io.github.wulkanowy.sdk.pojo.Absent
|
||||||
import io.github.wulkanowy.utils.*
|
import io.github.wulkanowy.utils.*
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.LocalTime
|
import java.time.LocalTime
|
||||||
|
@ -23,7 +20,6 @@ import javax.inject.Singleton
|
||||||
@Singleton
|
@Singleton
|
||||||
class AttendanceRepository @Inject constructor(
|
class AttendanceRepository @Inject constructor(
|
||||||
private val attendanceDb: AttendanceDao,
|
private val attendanceDb: AttendanceDao,
|
||||||
private val timetableDb: TimetableDao,
|
|
||||||
private val sdk: Sdk,
|
private val sdk: Sdk,
|
||||||
private val refreshHelper: AutoRefreshHelper,
|
private val refreshHelper: AutoRefreshHelper,
|
||||||
) {
|
) {
|
||||||
|
@ -52,15 +48,10 @@ class AttendanceRepository @Inject constructor(
|
||||||
attendanceDb.loadAll(semester.diaryId, semester.studentId, start.monday, end.sunday)
|
attendanceDb.loadAll(semester.diaryId, semester.studentId, start.monday, end.sunday)
|
||||||
},
|
},
|
||||||
fetch = {
|
fetch = {
|
||||||
val lessons = withContext(Dispatchers.IO) {
|
|
||||||
timetableDb.load(
|
|
||||||
semester.diaryId, semester.studentId, start.monday, end.sunday
|
|
||||||
)
|
|
||||||
}
|
|
||||||
sdk.init(student)
|
sdk.init(student)
|
||||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.getAttendance(start.monday, end.sunday)
|
.getAttendance(start.monday, end.sunday, semester.semesterId)
|
||||||
.mapToEntities(semester, lessons)
|
.mapToEntities(semester)
|
||||||
},
|
},
|
||||||
saveFetchResult = { old, new ->
|
saveFetchResult = { old, new ->
|
||||||
attendanceDb.deleteAll(old uniqueSubtract new)
|
attendanceDb.deleteAll(old uniqueSubtract new)
|
||||||
|
|
|
@ -52,7 +52,7 @@ class ExamRepository @Inject constructor(
|
||||||
fetch = {
|
fetch = {
|
||||||
sdk.init(student)
|
sdk.init(student)
|
||||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.getExams(start.startExamsDay, start.endExamsDay)
|
.getExams(start.startExamsDay, start.endExamsDay, semester.semesterId)
|
||||||
.mapToEntities(semester)
|
.mapToEntities(semester)
|
||||||
},
|
},
|
||||||
saveFetchResult = { old, new ->
|
saveFetchResult = { old, new ->
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
package io.github.wulkanowy.data.repositories
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.db.dao.MailboxDao
|
||||||
|
import io.github.wulkanowy.data.db.entities.Mailbox
|
||||||
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
|
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||||
|
import io.github.wulkanowy.utils.getRefreshKey
|
||||||
|
import io.github.wulkanowy.utils.init
|
||||||
|
import io.github.wulkanowy.utils.uniqueSubtract
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class MailboxRepository @Inject constructor(
|
||||||
|
private val mailboxDao: MailboxDao,
|
||||||
|
private val sdk: Sdk,
|
||||||
|
private val refreshHelper: AutoRefreshHelper,
|
||||||
|
) {
|
||||||
|
private val cacheKey = "mailboxes"
|
||||||
|
|
||||||
|
suspend fun refreshMailboxes(student: Student) {
|
||||||
|
val new = sdk.init(student).getMailboxes().mapToEntities(student)
|
||||||
|
val old = mailboxDao.loadAll(student.userLoginId)
|
||||||
|
|
||||||
|
mailboxDao.deleteAll(old uniqueSubtract new)
|
||||||
|
mailboxDao.insertAll(new uniqueSubtract old)
|
||||||
|
|
||||||
|
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, student))
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getMailbox(student: Student): Mailbox {
|
||||||
|
val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, student))
|
||||||
|
val mailboxes = mailboxDao.loadAll(student.userLoginId)
|
||||||
|
val mailbox = mailboxes.filterByStudent(student)
|
||||||
|
|
||||||
|
return if (isExpired || mailbox == null) {
|
||||||
|
refreshMailboxes(student)
|
||||||
|
val newMailbox = mailboxDao.loadAll(student.userLoginId).filterByStudent(student)
|
||||||
|
|
||||||
|
requireNotNull(newMailbox) {
|
||||||
|
"Mailbox for ${student.userName} - ${student.studentName} not found! Saved mailboxes: $mailboxes"
|
||||||
|
}
|
||||||
|
|
||||||
|
newMailbox
|
||||||
|
} else mailbox
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun List<Mailbox>.filterByStudent(student: Student): Mailbox? {
|
||||||
|
val normalizedStudentName = student.studentName.normalizeStudentName()
|
||||||
|
|
||||||
|
return find {
|
||||||
|
it.studentName.normalizeStudentName() == normalizedStudentName
|
||||||
|
} ?: singleOrNull {
|
||||||
|
it.studentName.getFirstAndLastPart() == normalizedStudentName.getFirstAndLastPart()
|
||||||
|
} ?: singleOrNull {
|
||||||
|
it.studentName.getUnauthorizedVersion() == normalizedStudentName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun String.normalizeStudentName(): String {
|
||||||
|
return trim().split(" ").joinToString(" ") { part ->
|
||||||
|
part.lowercase().replaceFirstChar { it.uppercase() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun String.getFirstAndLastPart(): String {
|
||||||
|
val parts = normalizeStudentName().split(" ")
|
||||||
|
|
||||||
|
val endParts = parts.filterIndexed { i, _ ->
|
||||||
|
i == 0 || parts.size == i - 1
|
||||||
|
}
|
||||||
|
return endParts.joinToString(" ")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun String.getUnauthorizedVersion(): String {
|
||||||
|
return normalizeStudentName().split(" ")
|
||||||
|
.joinToString(" ") {
|
||||||
|
it.first() + "*".repeat(it.length - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,25 +5,16 @@ import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.Resource
|
import io.github.wulkanowy.data.Resource
|
||||||
import io.github.wulkanowy.data.db.SharedPrefProvider
|
import io.github.wulkanowy.data.db.SharedPrefProvider
|
||||||
import io.github.wulkanowy.data.db.dao.MailboxDao
|
|
||||||
import io.github.wulkanowy.data.db.dao.MessageAttachmentDao
|
import io.github.wulkanowy.data.db.dao.MessageAttachmentDao
|
||||||
import io.github.wulkanowy.data.db.dao.MessagesDao
|
import io.github.wulkanowy.data.db.dao.MessagesDao
|
||||||
import io.github.wulkanowy.data.db.entities.Mailbox
|
import io.github.wulkanowy.data.db.entities.*
|
||||||
import io.github.wulkanowy.data.db.entities.Message
|
|
||||||
import io.github.wulkanowy.data.db.entities.MessageWithAttachment
|
|
||||||
import io.github.wulkanowy.data.db.entities.Recipient
|
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
|
||||||
import io.github.wulkanowy.data.enums.MessageFolder
|
import io.github.wulkanowy.data.enums.MessageFolder
|
||||||
import io.github.wulkanowy.data.enums.MessageFolder.RECEIVED
|
import io.github.wulkanowy.data.enums.MessageFolder.RECEIVED
|
||||||
import io.github.wulkanowy.data.enums.MessageFolder.TRASHED
|
import io.github.wulkanowy.data.enums.MessageFolder.TRASHED
|
||||||
import io.github.wulkanowy.data.mappers.mapFromEntities
|
import io.github.wulkanowy.data.mappers.mapFromEntities
|
||||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.data.networkBoundResource
|
import io.github.wulkanowy.data.networkBoundResource
|
||||||
import io.github.wulkanowy.data.onResourceError
|
|
||||||
import io.github.wulkanowy.data.onResourceSuccess
|
|
||||||
import io.github.wulkanowy.data.pojos.MessageDraft
|
import io.github.wulkanowy.data.pojos.MessageDraft
|
||||||
import io.github.wulkanowy.data.waitForResult
|
|
||||||
import io.github.wulkanowy.domain.messages.GetMailboxByStudentUseCase
|
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.sdk.pojo.Folder
|
import io.github.wulkanowy.sdk.pojo.Folder
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||||
|
@ -33,6 +24,7 @@ import io.github.wulkanowy.utils.uniqueSubtract
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
|
import kotlinx.serialization.decodeFromString
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
@ -48,18 +40,16 @@ class MessageRepository @Inject constructor(
|
||||||
private val refreshHelper: AutoRefreshHelper,
|
private val refreshHelper: AutoRefreshHelper,
|
||||||
private val sharedPrefProvider: SharedPrefProvider,
|
private val sharedPrefProvider: SharedPrefProvider,
|
||||||
private val json: Json,
|
private val json: Json,
|
||||||
private val mailboxDao: MailboxDao,
|
|
||||||
private val getMailboxByStudentUseCase: GetMailboxByStudentUseCase,
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val saveFetchResultMutex = Mutex()
|
private val saveFetchResultMutex = Mutex()
|
||||||
|
|
||||||
private val messagesCacheKey = "message"
|
private val cacheKey = "message"
|
||||||
private val mailboxCacheKey = "mailboxes"
|
|
||||||
|
|
||||||
|
@Suppress("UNUSED_PARAMETER")
|
||||||
fun getMessages(
|
fun getMessages(
|
||||||
student: Student,
|
student: Student,
|
||||||
mailbox: Mailbox?,
|
mailbox: Mailbox,
|
||||||
folder: MessageFolder,
|
folder: MessageFolder,
|
||||||
forceRefresh: Boolean,
|
forceRefresh: Boolean,
|
||||||
notify: Boolean = false,
|
notify: Boolean = false,
|
||||||
|
@ -68,20 +58,16 @@ class MessageRepository @Inject constructor(
|
||||||
isResultEmpty = { it.isEmpty() },
|
isResultEmpty = { it.isEmpty() },
|
||||||
shouldFetch = {
|
shouldFetch = {
|
||||||
val isExpired = refreshHelper.shouldBeRefreshed(
|
val isExpired = refreshHelper.shouldBeRefreshed(
|
||||||
key = getRefreshKey(messagesCacheKey, mailbox, folder)
|
key = getRefreshKey(cacheKey, student, folder)
|
||||||
)
|
)
|
||||||
it.isEmpty() || forceRefresh || isExpired
|
it.isEmpty() || forceRefresh || isExpired
|
||||||
},
|
},
|
||||||
query = {
|
query = { messagesDb.loadAll(mailbox.globalKey, folder.id) },
|
||||||
if (mailbox == null) {
|
|
||||||
messagesDb.loadAll(folder.id, student.email)
|
|
||||||
} else messagesDb.loadAll(mailbox.globalKey, folder.id)
|
|
||||||
},
|
|
||||||
fetch = {
|
fetch = {
|
||||||
sdk.init(student).getMessages(
|
sdk.init(student).getMessages(
|
||||||
folder = Folder.valueOf(folder.name),
|
folder = Folder.valueOf(folder.name),
|
||||||
mailboxKey = mailbox?.globalKey,
|
mailboxKey = mailbox.globalKey,
|
||||||
).mapToEntities(student, mailbox, mailboxDao.loadAll(student.email))
|
).mapToEntities(mailbox)
|
||||||
},
|
},
|
||||||
saveFetchResult = { old, new ->
|
saveFetchResult = { old, new ->
|
||||||
messagesDb.deleteAll(old uniqueSubtract new)
|
messagesDb.deleteAll(old uniqueSubtract new)
|
||||||
|
@ -89,9 +75,7 @@ class MessageRepository @Inject constructor(
|
||||||
it.isNotified = !notify
|
it.isNotified = !notify
|
||||||
})
|
})
|
||||||
|
|
||||||
refreshHelper.updateLastRefreshTimestamp(
|
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, student, folder))
|
||||||
getRefreshKey(messagesCacheKey, mailbox, folder)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -104,26 +88,18 @@ class MessageRepository @Inject constructor(
|
||||||
shouldFetch = {
|
shouldFetch = {
|
||||||
checkNotNull(it) { "This message no longer exist!" }
|
checkNotNull(it) { "This message no longer exist!" }
|
||||||
Timber.d("Message content in db empty: ${it.message.content.isBlank()}")
|
Timber.d("Message content in db empty: ${it.message.content.isBlank()}")
|
||||||
(it.message.unread && markAsRead) || it.message.content.isBlank()
|
it.message.unread || it.message.content.isBlank()
|
||||||
},
|
|
||||||
query = {
|
|
||||||
messagesDb.loadMessageWithAttachment(message.messageGlobalKey)
|
|
||||||
},
|
},
|
||||||
|
query = { messagesDb.loadMessageWithAttachment(message.messageGlobalKey) },
|
||||||
fetch = {
|
fetch = {
|
||||||
sdk.init(student).getMessageDetails(
|
sdk.init(student).getMessageDetails(it!!.message.messageGlobalKey, markAsRead)
|
||||||
messageKey = it!!.message.messageGlobalKey,
|
|
||||||
markAsRead = message.unread && markAsRead,
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
saveFetchResult = { old, new ->
|
saveFetchResult = { old, new ->
|
||||||
checkNotNull(old) { "Fetched message no longer exist!" }
|
checkNotNull(old) { "Fetched message no longer exist!" }
|
||||||
messagesDb.updateAll(
|
messagesDb.updateAll(
|
||||||
listOf(old.message.apply {
|
listOf(old.message.apply {
|
||||||
id = message.id
|
id = message.id
|
||||||
unread = when {
|
unread = !markAsRead
|
||||||
markAsRead -> false
|
|
||||||
else -> unread
|
|
||||||
}
|
|
||||||
sender = new.sender
|
sender = new.sender
|
||||||
recipients = new.recipients.singleOrNull() ?: "Wielu adresatów"
|
recipients = new.recipients.singleOrNull() ?: "Wielu adresatów"
|
||||||
content = content.ifBlank { new.content }
|
content = content.ifBlank { new.content }
|
||||||
|
@ -133,14 +109,12 @@ class MessageRepository @Inject constructor(
|
||||||
items = new.attachments.mapToEntities(message.messageGlobalKey),
|
items = new.attachments.mapToEntities(message.messageGlobalKey),
|
||||||
)
|
)
|
||||||
|
|
||||||
Timber.d("Message ${message.messageId} with blank content: ${old.message.content.isBlank()}, marked as read: $markAsRead")
|
Timber.d("Message ${message.messageId} with blank content: ${old.message.content.isBlank()}, marked as read")
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
fun getMessagesFromDatabase(student: Student, mailbox: Mailbox?): Flow<List<Message>> {
|
fun getMessagesFromDatabase(mailbox: Mailbox): Flow<List<Message>> {
|
||||||
return if (mailbox == null) {
|
return messagesDb.loadAll(mailbox.globalKey, RECEIVED.id)
|
||||||
messagesDb.loadAll(RECEIVED.id, student.email)
|
|
||||||
} else messagesDb.loadAll(mailbox.globalKey, RECEIVED.id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updateMessages(messages: List<Message>) {
|
suspend fun updateMessages(messages: List<Message>) {
|
||||||
|
@ -162,7 +136,7 @@ class MessageRepository @Inject constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun deleteMessages(student: Student, mailbox: Mailbox?, messages: List<Message>) {
|
suspend fun deleteMessages(student: Student, mailbox: Mailbox, messages: List<Message>) {
|
||||||
val firstMessage = messages.first()
|
val firstMessage = messages.first()
|
||||||
sdk.init(student).deleteMessages(
|
sdk.init(student).deleteMessages(
|
||||||
messages = messages.map { it.messageGlobalKey },
|
messages = messages.map { it.messageGlobalKey },
|
||||||
|
@ -191,44 +165,10 @@ class MessageRepository @Inject constructor(
|
||||||
).first()
|
).first()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun deleteMessage(student: Student, mailbox: Mailbox?, message: Message) {
|
suspend fun deleteMessage(student: Student, mailbox: Mailbox, message: Message) {
|
||||||
deleteMessages(student, mailbox, listOf(message))
|
deleteMessages(student, mailbox, listOf(message))
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getMailboxes(student: Student, forceRefresh: Boolean) = networkBoundResource(
|
|
||||||
mutex = saveFetchResultMutex,
|
|
||||||
isResultEmpty = { it.isEmpty() },
|
|
||||||
shouldFetch = {
|
|
||||||
val isExpired = refreshHelper.shouldBeRefreshed(
|
|
||||||
key = getRefreshKey(mailboxCacheKey, student),
|
|
||||||
)
|
|
||||||
it.isEmpty() || isExpired || forceRefresh
|
|
||||||
},
|
|
||||||
query = { mailboxDao.loadAll(student.email, student.symbol, student.schoolSymbol) },
|
|
||||||
fetch = {
|
|
||||||
sdk.init(student).getMailboxes().mapToEntities(student)
|
|
||||||
},
|
|
||||||
saveFetchResult = { old, new ->
|
|
||||||
mailboxDao.deleteAll(old uniqueSubtract new)
|
|
||||||
mailboxDao.insertAll(new uniqueSubtract old)
|
|
||||||
|
|
||||||
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(mailboxCacheKey, student))
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
suspend fun getMailboxByStudent(student: Student): Mailbox? {
|
|
||||||
val mailbox = getMailboxByStudentUseCase(student)
|
|
||||||
|
|
||||||
return if (mailbox == null) {
|
|
||||||
getMailboxes(student, forceRefresh = true)
|
|
||||||
.onResourceError { throw it }
|
|
||||||
.onResourceSuccess { Timber.i("Found ${it.size} new mailboxes") }
|
|
||||||
.waitForResult()
|
|
||||||
|
|
||||||
getMailboxByStudentUseCase(student)
|
|
||||||
} else mailbox
|
|
||||||
}
|
|
||||||
|
|
||||||
var draftMessage: MessageDraft?
|
var draftMessage: MessageDraft?
|
||||||
get() = sharedPrefProvider.getString(context.getString(R.string.pref_key_message_draft))
|
get() = sharedPrefProvider.getString(context.getString(R.string.pref_key_message_draft))
|
||||||
?.let { json.decodeFromString(it) }
|
?.let { json.decodeFromString(it) }
|
||||||
|
|
|
@ -42,7 +42,7 @@ class NoteRepository @Inject constructor(
|
||||||
fetch = {
|
fetch = {
|
||||||
sdk.init(student)
|
sdk.init(student)
|
||||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.getNotes()
|
.getNotes(semester.semesterId)
|
||||||
.mapToEntities(semester)
|
.mapToEntities(semester)
|
||||||
},
|
},
|
||||||
saveFetchResult = { old, new ->
|
saveFetchResult = { old, new ->
|
||||||
|
|
|
@ -2,26 +2,25 @@ package io.github.wulkanowy.data.repositories
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import androidx.annotation.StringRes
|
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
import com.fredporciuncula.flow.preferences.FlowSharedPreferences
|
import com.fredporciuncula.flow.preferences.FlowSharedPreferences
|
||||||
import com.fredporciuncula.flow.preferences.Preference
|
import com.fredporciuncula.flow.preferences.Preference
|
||||||
import com.fredporciuncula.flow.preferences.Serializer
|
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.enums.*
|
import io.github.wulkanowy.data.enums.*
|
||||||
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
|
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
|
||||||
import io.github.wulkanowy.ui.modules.grade.GradeAverageMode
|
import io.github.wulkanowy.ui.modules.grade.GradeAverageMode
|
||||||
import io.github.wulkanowy.ui.modules.settings.appearance.menuorder.AppMenuItem
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.serialization.decodeFromString
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.util.*
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
@Singleton
|
@Singleton
|
||||||
class PreferencesRepository @Inject constructor(
|
class PreferencesRepository @Inject constructor(
|
||||||
@ApplicationContext val context: Context,
|
@ApplicationContext val context: Context,
|
||||||
|
@ -30,35 +29,29 @@ class PreferencesRepository @Inject constructor(
|
||||||
private val json: Json,
|
private val json: Json,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
val startMenuIndex: Int
|
||||||
|
get() = getString(R.string.pref_key_start_menu, R.string.pref_default_startup).toInt()
|
||||||
|
|
||||||
val isShowPresent: Boolean
|
val isShowPresent: Boolean
|
||||||
get() = getBoolean(
|
get() = getBoolean(
|
||||||
R.string.pref_key_attendance_present,
|
R.string.pref_key_attendance_present,
|
||||||
R.bool.pref_default_attendance_present
|
R.bool.pref_default_attendance_present
|
||||||
)
|
)
|
||||||
|
|
||||||
private val gradeAverageModePref: Preference<GradeAverageMode>
|
val gradeAverageMode: GradeAverageMode
|
||||||
get() = getObjectFlow(
|
get() = GradeAverageMode.getByValue(
|
||||||
R.string.pref_key_grade_average_mode,
|
getString(
|
||||||
R.string.pref_default_grade_average_mode,
|
R.string.pref_key_grade_average_mode,
|
||||||
object : Serializer<GradeAverageMode> {
|
R.string.pref_default_grade_average_mode
|
||||||
override fun serialize(value: GradeAverageMode) = value.value
|
)
|
||||||
override fun deserialize(serialized: String) =
|
|
||||||
GradeAverageMode.getByValue(serialized)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
val gradeAverageModeFlow: Flow<GradeAverageMode>
|
val gradeAverageForceCalc: Boolean
|
||||||
get() = gradeAverageModePref.asFlow()
|
get() = getBoolean(
|
||||||
|
R.string.pref_key_grade_average_force_calc,
|
||||||
private val gradeAverageForceCalcPref: Preference<Boolean>
|
R.bool.pref_default_grade_average_force_calc
|
||||||
get() = flowSharedPref.getBoolean(
|
|
||||||
context.getString(R.string.pref_key_grade_average_force_calc),
|
|
||||||
context.resources.getBoolean(R.bool.pref_default_grade_average_force_calc)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
val gradeAverageForceCalcFlow: Flow<Boolean>
|
|
||||||
get() = gradeAverageForceCalcPref.asFlow()
|
|
||||||
|
|
||||||
val gradeExpandMode: GradeExpandMode
|
val gradeExpandMode: GradeExpandMode
|
||||||
get() = GradeExpandMode.getByValue(
|
get() = GradeExpandMode.getByValue(
|
||||||
getString(
|
getString(
|
||||||
|
@ -148,24 +141,12 @@ class PreferencesRepository @Inject constructor(
|
||||||
R.string.pref_default_grade_modifier_plus
|
R.string.pref_default_grade_modifier_plus
|
||||||
).toDouble()
|
).toDouble()
|
||||||
|
|
||||||
val gradePlusModifierFlow: Flow<Double>
|
|
||||||
get() = getStringFlow(
|
|
||||||
R.string.pref_key_grade_modifier_plus,
|
|
||||||
R.string.pref_default_grade_modifier_plus
|
|
||||||
).asFlow().map { it.toDouble() }
|
|
||||||
|
|
||||||
val gradeMinusModifier: Double
|
val gradeMinusModifier: Double
|
||||||
get() = getString(
|
get() = getString(
|
||||||
R.string.pref_key_grade_modifier_minus,
|
R.string.pref_key_grade_modifier_minus,
|
||||||
R.string.pref_default_grade_modifier_minus
|
R.string.pref_default_grade_modifier_minus
|
||||||
).toDouble()
|
).toDouble()
|
||||||
|
|
||||||
val gradeMinusModifierFlow: Flow<Double>
|
|
||||||
get() = getStringFlow(
|
|
||||||
R.string.pref_key_grade_modifier_minus,
|
|
||||||
R.string.pref_default_grade_modifier_minus
|
|
||||||
).asFlow().map { it.toDouble() }
|
|
||||||
|
|
||||||
val fillMessageContent: Boolean
|
val fillMessageContent: Boolean
|
||||||
get() = getBoolean(
|
get() = getBoolean(
|
||||||
R.string.pref_key_fill_message_content,
|
R.string.pref_key_fill_message_content,
|
||||||
|
@ -194,25 +175,30 @@ class PreferencesRepository @Inject constructor(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
val showTimetableGaps: TimetableGapsMode
|
val showTimetableTimers: Boolean
|
||||||
get() = TimetableGapsMode.getByValue(
|
get() = getBoolean(
|
||||||
getString(
|
R.string.pref_key_timetable_show_timers,
|
||||||
R.string.pref_key_timetable_show_gaps,
|
R.bool.pref_default_timetable_show_timers
|
||||||
R.string.pref_default_timetable_show_gaps
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var isHomeworkFullscreen: Boolean
|
||||||
|
get() = getBoolean(
|
||||||
|
R.string.pref_key_homework_fullscreen,
|
||||||
|
R.bool.pref_default_homework_fullscreen
|
||||||
|
)
|
||||||
|
set(value) = sharedPref.edit().putBoolean("homework_fullscreen", value).apply()
|
||||||
|
|
||||||
val showSubjectsWithoutGrades: Boolean
|
val showSubjectsWithoutGrades: Boolean
|
||||||
get() = getBoolean(
|
get() = getBoolean(
|
||||||
R.string.pref_key_subjects_without_grades,
|
R.string.pref_key_subjects_without_grades,
|
||||||
R.bool.pref_default_subjects_without_grades
|
R.bool.pref_default_subjects_without_grades
|
||||||
)
|
)
|
||||||
|
|
||||||
val isOptionalArithmeticAverageFlow: Flow<Boolean>
|
val isOptionalArithmeticAverage: Boolean
|
||||||
get() = flowSharedPref.getBoolean(
|
get() = getBoolean(
|
||||||
context.getString(R.string.pref_key_optional_arithmetic_average),
|
R.string.pref_key_optional_arithmetic_average,
|
||||||
context.resources.getBoolean(R.bool.pref_default_optional_arithmetic_average)
|
R.bool.pref_default_optional_arithmetic_average
|
||||||
).asFlow()
|
)
|
||||||
|
|
||||||
var lasSyncDate: Instant?
|
var lasSyncDate: Instant?
|
||||||
get() = getLong(R.string.pref_key_last_sync_date, R.string.pref_default_last_sync_date)
|
get() = getLong(R.string.pref_key_last_sync_date, R.string.pref_default_last_sync_date)
|
||||||
|
@ -330,56 +316,11 @@ class PreferencesRepository @Inject constructor(
|
||||||
putBoolean(context.getString(R.string.pref_key_ads_enabled), value)
|
putBoolean(context.getString(R.string.pref_key_ads_enabled), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
var appMenuItemOrder: List<AppMenuItem>
|
|
||||||
get() {
|
|
||||||
val value = sharedPref.getString(PREF_KEY_APP_MENU_ITEM_ORDER, null)
|
|
||||||
?: return AppMenuItem.defaultAppMenuItemList
|
|
||||||
|
|
||||||
return json.decodeFromString(value)
|
|
||||||
}
|
|
||||||
set(value) = sharedPref.edit {
|
|
||||||
putString(
|
|
||||||
PREF_KEY_APP_MENU_ITEM_ORDER,
|
|
||||||
json.encodeToString(value)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
var isIncognitoMode: Boolean
|
|
||||||
get() = getBoolean(R.string.pref_key_incognito_moge, R.bool.pref_default_incognito_mode)
|
|
||||||
set(value) = sharedPref.edit {
|
|
||||||
putBoolean(context.getString(R.string.pref_key_incognito_moge), value)
|
|
||||||
}
|
|
||||||
|
|
||||||
var installationId: String
|
|
||||||
get() = sharedPref.getString(PREF_KEY_INSTALLATION_ID, null).orEmpty()
|
|
||||||
private set(value) = sharedPref.edit { putString(PREF_KEY_INSTALLATION_ID, value) }
|
|
||||||
|
|
||||||
init {
|
|
||||||
if (installationId.isEmpty()) {
|
|
||||||
installationId = UUID.randomUUID().toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getLong(id: Int, default: Int) = getLong(context.getString(id), default)
|
private fun getLong(id: Int, default: Int) = getLong(context.getString(id), default)
|
||||||
|
|
||||||
private fun getLong(id: String, default: Int) =
|
private fun getLong(id: String, default: Int) =
|
||||||
sharedPref.getLong(id, context.resources.getString(default).toLong())
|
sharedPref.getLong(id, context.resources.getString(default).toLong())
|
||||||
|
|
||||||
private fun getStringFlow(id: Int, default: Int) =
|
|
||||||
flowSharedPref.getString(context.getString(id), context.getString(default))
|
|
||||||
|
|
||||||
private fun <T : Any> getObjectFlow(
|
|
||||||
@StringRes id: Int,
|
|
||||||
@StringRes default: Int,
|
|
||||||
serializer: Serializer<T>
|
|
||||||
): Preference<T> = flowSharedPref.getObject(
|
|
||||||
key = context.getString(id),
|
|
||||||
serializer = serializer,
|
|
||||||
defaultValue = serializer.deserialize(
|
|
||||||
flowSharedPref.getString(context.getString(default)).get()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun getString(id: Int, default: Int) = getString(context.getString(id), default)
|
private fun getString(id: Int, default: Int) = getString(context.getString(id), default)
|
||||||
|
|
||||||
private fun getString(id: String, default: Int) =
|
private fun getString(id: String, default: Int) =
|
||||||
|
@ -390,15 +331,23 @@ class PreferencesRepository @Inject constructor(
|
||||||
private fun getBoolean(id: String, default: Int) =
|
private fun getBoolean(id: String, default: Int) =
|
||||||
sharedPref.getBoolean(id, context.resources.getBoolean(default))
|
sharedPref.getBoolean(id, context.resources.getBoolean(default))
|
||||||
|
|
||||||
|
private fun getBoolean(id: Int, default: Boolean) =
|
||||||
|
sharedPref.getBoolean(context.getString(id), default)
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
private const val PREF_KEY_APP_MENU_ITEM_ORDER = "app_menu_item_order"
|
|
||||||
private const val PREF_KEY_INSTALLATION_ID = "installation_id"
|
|
||||||
private const val PREF_KEY_DASHBOARD_ITEMS_POSITION = "dashboard_items_position"
|
private const val PREF_KEY_DASHBOARD_ITEMS_POSITION = "dashboard_items_position"
|
||||||
|
|
||||||
private const val PREF_KEY_IN_APP_REVIEW_COUNT = "in_app_review_count"
|
private const val PREF_KEY_IN_APP_REVIEW_COUNT = "in_app_review_count"
|
||||||
|
|
||||||
private const val PREF_KEY_IN_APP_REVIEW_DATE = "in_app_review_date"
|
private const val PREF_KEY_IN_APP_REVIEW_DATE = "in_app_review_date"
|
||||||
|
|
||||||
private const val PREF_KEY_IN_APP_REVIEW_DONE = "in_app_review_done"
|
private const val PREF_KEY_IN_APP_REVIEW_DONE = "in_app_review_done"
|
||||||
|
|
||||||
private const val PREF_KEY_APP_SUPPORT_SHOWN = "app_support_shown"
|
private const val PREF_KEY_APP_SUPPORT_SHOWN = "app_support_shown"
|
||||||
|
|
||||||
private const val PREF_KEY_PERSONALIZED_ADS_ENABLED = "personalized_ads_enabled"
|
private const val PREF_KEY_PERSONALIZED_ADS_ENABLED = "personalized_ads_enabled"
|
||||||
|
|
||||||
private const val PREF_KEY_ADMIN_DISMISSED_MESSAGE_IDS = "admin_message_dismissed_ids"
|
private const val PREF_KEY_ADMIN_DISMISSED_MESSAGE_IDS = "admin_message_dismissed_ids"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,11 +33,9 @@ class RecipientRepository @Inject constructor(
|
||||||
|
|
||||||
suspend fun getRecipients(
|
suspend fun getRecipients(
|
||||||
student: Student,
|
student: Student,
|
||||||
mailbox: Mailbox?,
|
mailbox: Mailbox,
|
||||||
type: MailboxType,
|
type: MailboxType
|
||||||
): List<Recipient> {
|
): List<Recipient> {
|
||||||
mailbox ?: return emptyList()
|
|
||||||
|
|
||||||
val cached = recipientDb.loadAll(type, mailbox.globalKey)
|
val cached = recipientDb.loadAll(type, mailbox.globalKey)
|
||||||
|
|
||||||
val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, student))
|
val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, student))
|
||||||
|
@ -49,15 +47,11 @@ class RecipientRepository @Inject constructor(
|
||||||
|
|
||||||
suspend fun getMessageSender(
|
suspend fun getMessageSender(
|
||||||
student: Student,
|
student: Student,
|
||||||
mailbox: Mailbox?,
|
mailbox: Mailbox,
|
||||||
message: Message,
|
message: Message
|
||||||
): List<Recipient> {
|
): List<Recipient> = sdk.init(student)
|
||||||
mailbox ?: return emptyList()
|
.getMessageReplayDetails(message.messageGlobalKey)
|
||||||
|
.sender
|
||||||
return sdk.init(student)
|
.let(::listOf)
|
||||||
.getMessageReplayDetails(message.messageGlobalKey)
|
.mapToEntities(mailbox.globalKey)
|
||||||
.sender
|
|
||||||
.let(::listOf)
|
|
||||||
.mapToEntities(mailbox.globalKey)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
package io.github.wulkanowy.data.repositories
|
|
||||||
|
|
||||||
import io.github.wulkanowy.data.api.SchoolsService
|
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
|
||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
|
||||||
import io.github.wulkanowy.data.pojos.IntegrityRequest
|
|
||||||
import io.github.wulkanowy.data.pojos.LoginEvent
|
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
|
||||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
|
||||||
import io.github.wulkanowy.utils.IntegrityHelper
|
|
||||||
import io.github.wulkanowy.utils.getCurrentOrLast
|
|
||||||
import io.github.wulkanowy.utils.init
|
|
||||||
import kotlinx.coroutines.withTimeout
|
|
||||||
import timber.log.Timber
|
|
||||||
import java.util.UUID
|
|
||||||
import javax.inject.Inject
|
|
||||||
import javax.inject.Singleton
|
|
||||||
import kotlin.time.Duration.Companion.seconds
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
class SchoolsRepository @Inject constructor(
|
|
||||||
private val integrityHelper: IntegrityHelper,
|
|
||||||
private val schoolsService: SchoolsService,
|
|
||||||
private val sdk: Sdk,
|
|
||||||
) {
|
|
||||||
|
|
||||||
suspend fun logSchoolLogin(loginData: LoginData, students: List<StudentWithSemesters>) {
|
|
||||||
students.forEach {
|
|
||||||
runCatching {
|
|
||||||
withTimeout(10.seconds) {
|
|
||||||
logLogin(loginData, it.student, it.semesters.getCurrentOrLast())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.onFailure { Timber.e(it) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun logLogin(loginData: LoginData, student: Student, semester: Semester) {
|
|
||||||
val requestId = UUID.randomUUID().toString()
|
|
||||||
val token = integrityHelper.getIntegrityToken(requestId) ?: return
|
|
||||||
|
|
||||||
val schoolInfo = sdk
|
|
||||||
.init(student.copy(password = loginData.password))
|
|
||||||
.switchDiary(
|
|
||||||
diaryId = semester.diaryId,
|
|
||||||
kindergartenDiaryId = semester.kindergartenDiaryId,
|
|
||||||
schoolYear = semester.schoolYear
|
|
||||||
)
|
|
||||||
.getSchool()
|
|
||||||
|
|
||||||
schoolsService.logLoginEvent(
|
|
||||||
IntegrityRequest(
|
|
||||||
tokenString = token,
|
|
||||||
data = LoginEvent(
|
|
||||||
uuid = requestId,
|
|
||||||
schoolAddress = schoolInfo.address,
|
|
||||||
schoolName = schoolInfo.name,
|
|
||||||
schoolShort = student.schoolShortName,
|
|
||||||
scraperBaseUrl = student.scrapperBaseUrl,
|
|
||||||
loginType = student.loginType,
|
|
||||||
symbol = student.symbol,
|
|
||||||
schoolId = student.schoolSymbol,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -40,8 +40,8 @@ class SemesterRepository @Inject constructor(
|
||||||
val isNoSemesters = semesters.isEmpty()
|
val isNoSemesters = semesters.isEmpty()
|
||||||
|
|
||||||
val isRefreshOnModeChangeRequired = when {
|
val isRefreshOnModeChangeRequired = when {
|
||||||
Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.HEBE -> {
|
Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API -> {
|
||||||
semesters.firstOrNull { it.isCurrent() }?.let {
|
semesters.firstOrNull { it.isCurrent }?.let {
|
||||||
0 == it.diaryId && 0 == it.kindergartenDiaryId
|
0 == it.diaryId && 0 == it.kindergartenDiaryId
|
||||||
} == true
|
} == true
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ class SemesterRepository @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
val isRefreshOnNoCurrentAppropriate =
|
val isRefreshOnNoCurrentAppropriate =
|
||||||
refreshOnNoCurrent && !semesters.any { semester -> semester.isCurrent() }
|
refreshOnNoCurrent && !semesters.any { semester -> semester.isCurrent }
|
||||||
|
|
||||||
return forceRefresh || isNoSemesters || isRefreshOnModeChangeRequired || isRefreshOnNoCurrentAppropriate
|
return forceRefresh || isNoSemesters || isRefreshOnModeChangeRequired || isRefreshOnNoCurrentAppropriate
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,17 +6,14 @@ import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import io.github.wulkanowy.data.db.AppDatabase
|
import io.github.wulkanowy.data.db.AppDatabase
|
||||||
import io.github.wulkanowy.data.db.dao.SemesterDao
|
import io.github.wulkanowy.data.db.dao.SemesterDao
|
||||||
import io.github.wulkanowy.data.db.dao.StudentDao
|
import io.github.wulkanowy.data.db.dao.StudentDao
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.db.entities.StudentName
|
|
||||||
import io.github.wulkanowy.data.db.entities.StudentNickAndAvatar
|
import io.github.wulkanowy.data.db.entities.StudentNickAndAvatar
|
||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||||
import io.github.wulkanowy.data.exceptions.NoCurrentStudentException
|
import io.github.wulkanowy.data.exceptions.NoCurrentStudentException
|
||||||
import io.github.wulkanowy.data.mappers.mapToPojo
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.data.pojos.RegisterUser
|
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
|
import io.github.wulkanowy.utils.AppInfo
|
||||||
import io.github.wulkanowy.utils.DispatchersProvider
|
import io.github.wulkanowy.utils.DispatchersProvider
|
||||||
import io.github.wulkanowy.utils.init
|
|
||||||
import io.github.wulkanowy.utils.security.decrypt
|
import io.github.wulkanowy.utils.security.decrypt
|
||||||
import io.github.wulkanowy.utils.security.encrypt
|
import io.github.wulkanowy.utils.security.encrypt
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
@ -30,61 +27,55 @@ class StudentRepository @Inject constructor(
|
||||||
private val studentDb: StudentDao,
|
private val studentDb: StudentDao,
|
||||||
private val semesterDb: SemesterDao,
|
private val semesterDb: SemesterDao,
|
||||||
private val sdk: Sdk,
|
private val sdk: Sdk,
|
||||||
|
private val appInfo: AppInfo,
|
||||||
private val appDatabase: AppDatabase
|
private val appDatabase: AppDatabase
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
suspend fun isStudentSaved() = getSavedStudents(false).isNotEmpty()
|
||||||
|
|
||||||
suspend fun isCurrentStudentSet() = studentDb.loadCurrent()?.isCurrent ?: false
|
suspend fun isCurrentStudentSet() = studentDb.loadCurrent()?.isCurrent ?: false
|
||||||
|
|
||||||
suspend fun getStudentsApi(
|
suspend fun getStudentsApi(
|
||||||
pin: String,
|
pin: String,
|
||||||
symbol: String,
|
symbol: String,
|
||||||
token: String
|
token: String
|
||||||
): RegisterUser = sdk
|
): List<StudentWithSemesters> =
|
||||||
.getStudentsFromHebe(token, pin, symbol, "")
|
sdk.getStudentsFromMobileApi(token, pin, symbol, "")
|
||||||
.mapToPojo(null)
|
.mapToEntities(colors = appInfo.defaultColorsForAvatar)
|
||||||
|
|
||||||
suspend fun getUserSubjectsFromScrapper(
|
suspend fun getStudentsScrapper(
|
||||||
email: String,
|
email: String,
|
||||||
password: String,
|
password: String,
|
||||||
scrapperBaseUrl: String,
|
scrapperBaseUrl: String,
|
||||||
domainSuffix: String,
|
|
||||||
symbol: String
|
symbol: String
|
||||||
): RegisterUser = sdk
|
): List<StudentWithSemesters> =
|
||||||
.getUserSubjectsFromScrapper(email, password, scrapperBaseUrl, domainSuffix, symbol)
|
sdk.getStudentsFromScrapper(email, password, scrapperBaseUrl, symbol)
|
||||||
.mapToPojo(password)
|
.mapToEntities(password, appInfo.defaultColorsForAvatar)
|
||||||
|
|
||||||
suspend fun getStudentsHybrid(
|
suspend fun getStudentsHybrid(
|
||||||
email: String,
|
email: String,
|
||||||
password: String,
|
password: String,
|
||||||
scrapperBaseUrl: String,
|
scrapperBaseUrl: String,
|
||||||
symbol: String
|
symbol: String
|
||||||
): RegisterUser = sdk
|
): List<StudentWithSemesters> =
|
||||||
.getStudentsHybrid(email, password, scrapperBaseUrl, "", symbol)
|
sdk.getStudentsHybrid(email, password, scrapperBaseUrl, "", symbol)
|
||||||
.mapToPojo(password)
|
.mapToEntities(password, appInfo.defaultColorsForAvatar)
|
||||||
|
|
||||||
suspend fun getSavedStudents(decryptPass: Boolean = true): List<StudentWithSemesters> {
|
suspend fun getSavedStudents(decryptPass: Boolean = true) =
|
||||||
return studentDb.loadStudentsWithSemesters().map { (student, semesters) ->
|
studentDb.loadStudentsWithSemesters()
|
||||||
StudentWithSemesters(
|
.map {
|
||||||
student = student.apply {
|
it.apply {
|
||||||
if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.HEBE) {
|
if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) {
|
||||||
student.password = withContext(dispatchers.io) {
|
student.password = withContext(dispatchers.io) {
|
||||||
decrypt(student.password)
|
decrypt(student.password)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
semesters = semesters,
|
}
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getSavedStudentById(id: Long, decryptPass: Boolean = true): StudentWithSemesters? =
|
suspend fun getSavedStudentById(id: Long, decryptPass: Boolean = true) =
|
||||||
studentDb.loadStudentWithSemestersById(id).let { res ->
|
studentDb.loadStudentWithSemestersById(id)?.apply {
|
||||||
StudentWithSemesters(
|
if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) {
|
||||||
student = res.keys.firstOrNull() ?: return null,
|
|
||||||
semesters = res.values.first(),
|
|
||||||
)
|
|
||||||
}.apply {
|
|
||||||
if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.HEBE) {
|
|
||||||
student.password = withContext(dispatchers.io) {
|
student.password = withContext(dispatchers.io) {
|
||||||
decrypt(student.password)
|
decrypt(student.password)
|
||||||
}
|
}
|
||||||
|
@ -94,7 +85,7 @@ class StudentRepository @Inject constructor(
|
||||||
suspend fun getStudentById(id: Long, decryptPass: Boolean = true): Student {
|
suspend fun getStudentById(id: Long, decryptPass: Boolean = true): Student {
|
||||||
val student = studentDb.loadById(id) ?: throw NoCurrentStudentException()
|
val student = studentDb.loadById(id) ?: throw NoCurrentStudentException()
|
||||||
|
|
||||||
if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.HEBE) {
|
if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) {
|
||||||
student.password = withContext(dispatchers.io) {
|
student.password = withContext(dispatchers.io) {
|
||||||
decrypt(student.password)
|
decrypt(student.password)
|
||||||
}
|
}
|
||||||
|
@ -105,7 +96,7 @@ class StudentRepository @Inject constructor(
|
||||||
suspend fun getCurrentStudent(decryptPass: Boolean = true): Student {
|
suspend fun getCurrentStudent(decryptPass: Boolean = true): Student {
|
||||||
val student = studentDb.loadCurrent() ?: throw NoCurrentStudentException()
|
val student = studentDb.loadCurrent() ?: throw NoCurrentStudentException()
|
||||||
|
|
||||||
if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.HEBE) {
|
if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) {
|
||||||
student.password = withContext(dispatchers.io) {
|
student.password = withContext(dispatchers.io) {
|
||||||
decrypt(student.password)
|
decrypt(student.password)
|
||||||
}
|
}
|
||||||
|
@ -118,7 +109,7 @@ class StudentRepository @Inject constructor(
|
||||||
val students = studentsWithSemesters.map { it.student }
|
val students = studentsWithSemesters.map { it.student }
|
||||||
.map {
|
.map {
|
||||||
it.apply {
|
it.apply {
|
||||||
if (Sdk.Mode.valueOf(it.loginMode) != Sdk.Mode.HEBE) {
|
if (Sdk.Mode.valueOf(it.loginMode) != Sdk.Mode.API) {
|
||||||
password = withContext(dispatchers.io) {
|
password = withContext(dispatchers.io) {
|
||||||
encrypt(password, context)
|
encrypt(password, context)
|
||||||
}
|
}
|
||||||
|
@ -149,21 +140,4 @@ class StudentRepository @Inject constructor(
|
||||||
|
|
||||||
suspend fun isOneUniqueStudent() = getSavedStudents(false)
|
suspend fun isOneUniqueStudent() = getSavedStudents(false)
|
||||||
.distinctBy { it.student.studentName }.size == 1
|
.distinctBy { it.student.studentName }.size == 1
|
||||||
|
|
||||||
suspend fun authorizePermission(student: Student, semester: Semester, pesel: String) =
|
|
||||||
sdk.init(student)
|
|
||||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
|
||||||
.authorizePermission(pesel)
|
|
||||||
|
|
||||||
suspend fun refreshStudentName(student: Student, semester: Semester) {
|
|
||||||
val newCurrentApiStudent = sdk.init(student)
|
|
||||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
|
||||||
.getCurrentStudent() ?: return
|
|
||||||
|
|
||||||
val studentName = StudentName(
|
|
||||||
studentName = "${newCurrentApiStudent.studentName} ${newCurrentApiStudent.studentSurname}"
|
|
||||||
).apply { id = student.id }
|
|
||||||
|
|
||||||
studentDb.update(studentName)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ class TeacherRepository @Inject constructor(
|
||||||
fetch = {
|
fetch = {
|
||||||
sdk.init(student)
|
sdk.init(student)
|
||||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.getTeachers()
|
.getTeachers(semester.semesterId)
|
||||||
.mapToEntities(semester)
|
.mapToEntities(semester)
|
||||||
},
|
},
|
||||||
saveFetchResult = { old, new ->
|
saveFetchResult = { old, new ->
|
||||||
|
|
|
@ -13,7 +13,6 @@ import io.github.wulkanowy.utils.*
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import java.time.Instant
|
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
@ -66,7 +65,7 @@ class TimetableRepository @Inject constructor(
|
||||||
fetch = {
|
fetch = {
|
||||||
val timetableFull = sdk.init(student)
|
val timetableFull = sdk.init(student)
|
||||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.getTimetable(start.monday, end.sunday)
|
.getTimetableFull(start.monday, end.sunday)
|
||||||
|
|
||||||
timetableFull.mapToEntities(semester)
|
timetableFull.mapToEntities(semester)
|
||||||
},
|
},
|
||||||
|
@ -165,11 +164,6 @@ class TimetableRepository @Inject constructor(
|
||||||
timetableHeaderDb.insertAll(new uniqueSubtract old)
|
timetableHeaderDb.insertAll(new uniqueSubtract old)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getLastRefreshTimestamp(semester: Semester, start: LocalDate, end: LocalDate): Instant {
|
|
||||||
val refreshKey = getRefreshKey(cacheKey, semester, start, end)
|
|
||||||
return refreshHelper.getLastRefreshTimestamp(refreshKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun saveAdditionalList(additionalList: List<TimetableAdditional>) =
|
suspend fun saveAdditionalList(additionalList: List<TimetableAdditional>) =
|
||||||
timetableAdditionalDb.insertAll(additionalList)
|
timetableAdditionalDb.insertAll(additionalList)
|
||||||
|
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
package io.github.wulkanowy.domain.adminmessage
|
|
||||||
|
|
||||||
import io.github.wulkanowy.data.Resource
|
|
||||||
import io.github.wulkanowy.data.db.entities.AdminMessage
|
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
|
||||||
import io.github.wulkanowy.data.enums.MessageType
|
|
||||||
import io.github.wulkanowy.data.mapResourceData
|
|
||||||
import io.github.wulkanowy.data.repositories.AdminMessageRepository
|
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
|
||||||
import io.github.wulkanowy.utils.AppInfo
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class GetAppropriateAdminMessageUseCase @Inject constructor(
|
|
||||||
private val adminMessageRepository: AdminMessageRepository,
|
|
||||||
private val preferencesRepository: PreferencesRepository,
|
|
||||||
private val appInfo: AppInfo
|
|
||||||
) {
|
|
||||||
|
|
||||||
operator fun invoke(student: Student, type: MessageType): Flow<Resource<AdminMessage?>> {
|
|
||||||
return invoke(student.scrapperBaseUrl, type)
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun invoke(scrapperBaseUrl: String, type: MessageType): Flow<Resource<AdminMessage?>> {
|
|
||||||
return adminMessageRepository.getAdminMessages().mapResourceData { adminMessages ->
|
|
||||||
adminMessages
|
|
||||||
.asSequence()
|
|
||||||
.filter { it.isNotDismissed() }
|
|
||||||
.filter { it.isVersionMatch() }
|
|
||||||
.filter { it.isRegisterHostMatch(scrapperBaseUrl) }
|
|
||||||
.filter { it.isFlavorMatch() }
|
|
||||||
.filter { it.isTypeMatch(type) }
|
|
||||||
.maxByOrNull { it.id }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun AdminMessage.isNotDismissed(): Boolean {
|
|
||||||
return id !in preferencesRepository.dismissedAdminMessageIds
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun AdminMessage.isRegisterHostMatch(scrapperBaseUrl: String): Boolean {
|
|
||||||
return targetRegisterHost?.let {
|
|
||||||
scrapperBaseUrl.contains(it, true)
|
|
||||||
} ?: true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun AdminMessage.isFlavorMatch(): Boolean {
|
|
||||||
return targetFlavor?.equals(appInfo.buildFlavor, true) ?: true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun AdminMessage.isVersionMatch(): Boolean {
|
|
||||||
val isCorrectMaxVersion = versionMax?.let { it >= appInfo.versionCode } ?: true
|
|
||||||
val isCorrectMinVersion = versionMin?.let { it <= appInfo.versionCode } ?: true
|
|
||||||
|
|
||||||
return isCorrectMaxVersion && isCorrectMinVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun AdminMessage.isTypeMatch(messageType: MessageType): Boolean {
|
|
||||||
if (messageType in types) return true
|
|
||||||
if (MessageType.GENERAL_MESSAGE in types) return true
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
package io.github.wulkanowy.domain.messages
|
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.dao.MailboxDao
|
|
||||||
import io.github.wulkanowy.data.db.entities.Mailbox
|
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class GetMailboxByStudentUseCase @Inject constructor(
|
|
||||||
private val mailboxDao: MailboxDao,
|
|
||||||
) {
|
|
||||||
|
|
||||||
suspend operator fun invoke(student: Student): Mailbox? {
|
|
||||||
return mailboxDao.loadAll(student.email)
|
|
||||||
.filterByStudent(student)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun List<Mailbox>.filterByStudent(student: Student): Mailbox? {
|
|
||||||
val normalizedStudentName = student.studentName.normalizeStudentName()
|
|
||||||
|
|
||||||
return singleOrNull {
|
|
||||||
it.studentName.normalizeStudentName() == normalizedStudentName
|
|
||||||
} ?: singleOrNull {
|
|
||||||
it.studentName.normalizeStudentName() == normalizedStudentName
|
|
||||||
&& it.schoolNameShort == student.schoolShortName
|
|
||||||
} ?: singleOrNull {
|
|
||||||
it.studentName.getFirstAndLastPart() == normalizedStudentName.getFirstAndLastPart()
|
|
||||||
} ?: singleOrNull {
|
|
||||||
it.studentName.getReversedName() == normalizedStudentName
|
|
||||||
} ?: singleOrNull {
|
|
||||||
it.studentName.getUnauthorizedVersion() == normalizedStudentName
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun String.normalizeStudentName(): String {
|
|
||||||
return trim().split(" ")
|
|
||||||
.filter { it.isNotBlank() }
|
|
||||||
.joinToString(" ") { part ->
|
|
||||||
part.lowercase().replaceFirstChar { it.uppercase() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun String.getFirstAndLastPart(): String {
|
|
||||||
val parts = normalizeStudentName().split(" ")
|
|
||||||
|
|
||||||
val endParts = parts.filterIndexed { i, _ ->
|
|
||||||
i == 0 || parts.size - 1 == i
|
|
||||||
}
|
|
||||||
return endParts.joinToString(" ")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun String.getReversedName(): String {
|
|
||||||
val parts = normalizeStudentName().split(" ")
|
|
||||||
|
|
||||||
return parts
|
|
||||||
.asReversed()
|
|
||||||
.joinToString(" ")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun String.getUnauthorizedVersion(): String {
|
|
||||||
return normalizeStudentName().split(" ")
|
|
||||||
.joinToString(" ") {
|
|
||||||
it.first() + "*".repeat(it.length - 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,12 +4,18 @@ import android.os.Build.VERSION.SDK_INT
|
||||||
import android.os.Build.VERSION_CODES.O
|
import android.os.Build.VERSION_CODES.O
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import androidx.lifecycle.asFlow
|
import androidx.lifecycle.asFlow
|
||||||
import androidx.work.*
|
|
||||||
import androidx.work.BackoffPolicy.EXPONENTIAL
|
import androidx.work.BackoffPolicy.EXPONENTIAL
|
||||||
|
import androidx.work.Constraints
|
||||||
|
import androidx.work.Data
|
||||||
import androidx.work.ExistingPeriodicWorkPolicy.KEEP
|
import androidx.work.ExistingPeriodicWorkPolicy.KEEP
|
||||||
import androidx.work.ExistingPeriodicWorkPolicy.UPDATE
|
import androidx.work.ExistingPeriodicWorkPolicy.REPLACE
|
||||||
|
import androidx.work.ExistingWorkPolicy
|
||||||
import androidx.work.NetworkType.CONNECTED
|
import androidx.work.NetworkType.CONNECTED
|
||||||
import androidx.work.NetworkType.UNMETERED
|
import androidx.work.NetworkType.UNMETERED
|
||||||
|
import androidx.work.OneTimeWorkRequestBuilder
|
||||||
|
import androidx.work.PeriodicWorkRequestBuilder
|
||||||
|
import androidx.work.WorkInfo
|
||||||
|
import androidx.work.WorkManager
|
||||||
import io.github.wulkanowy.data.db.SharedPrefProvider
|
import io.github.wulkanowy.data.db.SharedPrefProvider
|
||||||
import io.github.wulkanowy.data.db.SharedPrefProvider.Companion.APP_VERSION_CODE_KEY
|
import io.github.wulkanowy.data.db.SharedPrefProvider.Companion.APP_VERSION_CODE_KEY
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||||
|
@ -54,7 +60,7 @@ class SyncManager @Inject constructor(
|
||||||
val serviceInterval = preferencesRepository.servicesInterval
|
val serviceInterval = preferencesRepository.servicesInterval
|
||||||
|
|
||||||
workManager.enqueueUniquePeriodicWork(
|
workManager.enqueueUniquePeriodicWork(
|
||||||
SyncWorker::class.java.simpleName, if (restart) UPDATE else KEEP,
|
SyncWorker::class.java.simpleName, if (restart) REPLACE else KEEP,
|
||||||
PeriodicWorkRequestBuilder<SyncWorker>(serviceInterval, MINUTES)
|
PeriodicWorkRequestBuilder<SyncWorker>(serviceInterval, MINUTES)
|
||||||
.setInitialDelay(10, MINUTES)
|
.setInitialDelay(10, MINUTES)
|
||||||
.setBackoffCriteria(EXPONENTIAL, 30, MINUTES)
|
.setBackoffCriteria(EXPONENTIAL, 30, MINUTES)
|
||||||
|
|
|
@ -8,6 +8,7 @@ import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.pojos.GroupNotificationData
|
import io.github.wulkanowy.data.pojos.GroupNotificationData
|
||||||
import io.github.wulkanowy.data.pojos.NotificationData
|
import io.github.wulkanowy.data.pojos.NotificationData
|
||||||
import io.github.wulkanowy.ui.modules.Destination
|
import io.github.wulkanowy.ui.modules.Destination
|
||||||
|
import io.github.wulkanowy.ui.modules.splash.SplashActivity
|
||||||
import io.github.wulkanowy.utils.descriptionRes
|
import io.github.wulkanowy.utils.descriptionRes
|
||||||
import io.github.wulkanowy.utils.getPlural
|
import io.github.wulkanowy.utils.getPlural
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
|
@ -21,9 +22,8 @@ class NewAttendanceNotification @Inject constructor(
|
||||||
suspend fun notify(items: List<Attendance>, student: Student) {
|
suspend fun notify(items: List<Attendance>, student: Student) {
|
||||||
val lines = items.filterNot { it.presence || it.name == "UNKNOWN" }
|
val lines = items.filterNot { it.presence || it.name == "UNKNOWN" }
|
||||||
.map {
|
.map {
|
||||||
val lesson = it.subject.ifBlank { "Lekcja ${it.number}" }
|
|
||||||
val description = context.getString(it.descriptionRes)
|
val description = context.getString(it.descriptionRes)
|
||||||
"${it.date.toFormattedString("dd.MM")} - $lesson: $description"
|
"${it.date.toFormattedString("dd.MM")} - ${it.subject}: $description"
|
||||||
}
|
}
|
||||||
.ifEmpty { return }
|
.ifEmpty { return }
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.pojos.GroupNotificationData
|
import io.github.wulkanowy.data.pojos.GroupNotificationData
|
||||||
import io.github.wulkanowy.data.pojos.NotificationData
|
import io.github.wulkanowy.data.pojos.NotificationData
|
||||||
import io.github.wulkanowy.ui.modules.Destination
|
import io.github.wulkanowy.ui.modules.Destination
|
||||||
|
import io.github.wulkanowy.ui.modules.splash.SplashActivity
|
||||||
import io.github.wulkanowy.utils.getPlural
|
import io.github.wulkanowy.utils.getPlural
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.services.sync.works
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.enums.MessageFolder.RECEIVED
|
import io.github.wulkanowy.data.enums.MessageFolder.RECEIVED
|
||||||
|
import io.github.wulkanowy.data.repositories.MailboxRepository
|
||||||
import io.github.wulkanowy.data.repositories.MessageRepository
|
import io.github.wulkanowy.data.repositories.MessageRepository
|
||||||
import io.github.wulkanowy.data.waitForResult
|
import io.github.wulkanowy.data.waitForResult
|
||||||
import io.github.wulkanowy.services.sync.notifications.NewMessageNotification
|
import io.github.wulkanowy.services.sync.notifications.NewMessageNotification
|
||||||
|
@ -11,11 +12,12 @@ import javax.inject.Inject
|
||||||
|
|
||||||
class MessageWork @Inject constructor(
|
class MessageWork @Inject constructor(
|
||||||
private val messageRepository: MessageRepository,
|
private val messageRepository: MessageRepository,
|
||||||
|
private val mailboxRepository: MailboxRepository,
|
||||||
private val newMessageNotification: NewMessageNotification,
|
private val newMessageNotification: NewMessageNotification,
|
||||||
) : Work {
|
) : Work {
|
||||||
|
|
||||||
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
|
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
|
||||||
val mailbox = messageRepository.getMailboxByStudent(student)
|
val mailbox = mailboxRepository.getMailbox(student)
|
||||||
messageRepository.getMessages(
|
messageRepository.getMessages(
|
||||||
student = student,
|
student = student,
|
||||||
mailbox = mailbox,
|
mailbox = mailbox,
|
||||||
|
@ -24,7 +26,7 @@ class MessageWork @Inject constructor(
|
||||||
notify = notify
|
notify = notify
|
||||||
).waitForResult()
|
).waitForResult()
|
||||||
|
|
||||||
messageRepository.getMessagesFromDatabase(student, mailbox).first()
|
messageRepository.getMessagesFromDatabase(mailbox).first()
|
||||||
.filter { !it.isNotified && it.unread }.let {
|
.filter { !it.isNotified && it.unread }.let {
|
||||||
if (it.isNotEmpty()) newMessageNotification.notify(it, student)
|
if (it.isNotEmpty()) newMessageNotification.notify(it, student)
|
||||||
messageRepository.updateMessages(it.onEach { message -> message.isNotified = true })
|
messageRepository.updateMessages(it.onEach { message -> message.isNotified = true })
|
||||||
|
|
|
@ -1,23 +1,22 @@
|
||||||
package io.github.wulkanowy.services.sync.works
|
package io.github.wulkanowy.services.sync.works
|
||||||
|
|
||||||
import io.github.wulkanowy.data.dataOrNull
|
|
||||||
import io.github.wulkanowy.data.db.entities.MailboxType
|
import io.github.wulkanowy.data.db.entities.MailboxType
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.repositories.MessageRepository
|
import io.github.wulkanowy.data.repositories.MailboxRepository
|
||||||
import io.github.wulkanowy.data.repositories.RecipientRepository
|
import io.github.wulkanowy.data.repositories.RecipientRepository
|
||||||
import io.github.wulkanowy.data.toFirstResult
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class RecipientWork @Inject constructor(
|
class RecipientWork @Inject constructor(
|
||||||
private val messageRepository: MessageRepository,
|
private val mailboxRepository: MailboxRepository,
|
||||||
private val recipientRepository: RecipientRepository
|
private val recipientRepository: RecipientRepository
|
||||||
) : Work {
|
) : Work {
|
||||||
|
|
||||||
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
|
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
|
||||||
val mailboxes = messageRepository.getMailboxes(student, forceRefresh = true).toFirstResult()
|
mailboxRepository.refreshMailboxes(student)
|
||||||
mailboxes.dataOrNull?.forEach {
|
|
||||||
recipientRepository.refreshRecipients(student, it, MailboxType.EMPLOYEE)
|
val mailbox = mailboxRepository.getMailbox(student)
|
||||||
}
|
|
||||||
|
recipientRepository.refreshRecipients(student, mailbox, MailboxType.EMPLOYEE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,21 +25,13 @@ class TimetableWidgetService : RemoteViewsService() {
|
||||||
lateinit var semesterRepo: SemesterRepository
|
lateinit var semesterRepo: SemesterRepository
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var sharedPref: SharedPrefProvider
|
lateinit var prefRepository: PreferencesRepository
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var prefRepository: PreferencesRepository
|
lateinit var sharedPref: SharedPrefProvider
|
||||||
|
|
||||||
override fun onGetViewFactory(intent: Intent?): RemoteViewsFactory {
|
override fun onGetViewFactory(intent: Intent?): RemoteViewsFactory {
|
||||||
Timber.d("TimetableWidgetFactory created")
|
Timber.d("TimetableWidgetFactory created")
|
||||||
return TimetableWidgetFactory(
|
return TimetableWidgetFactory(timetableRepo, studentRepo, semesterRepo, prefRepository, sharedPref, applicationContext, intent)
|
||||||
timetableRepository = timetableRepo,
|
|
||||||
studentRepository = studentRepo,
|
|
||||||
semesterRepository = semesterRepo,
|
|
||||||
sharedPref = sharedPref,
|
|
||||||
prefRepository = prefRepository,
|
|
||||||
context = applicationContext,
|
|
||||||
intent = intent,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,12 @@ import android.app.ActivityManager
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.viewbinding.ViewBinding
|
import androidx.viewbinding.ViewBinding
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.google.android.material.snackbar.Snackbar.LENGTH_LONG
|
import com.google.android.material.snackbar.Snackbar.LENGTH_LONG
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.ui.modules.auth.AuthDialog
|
|
||||||
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
||||||
import io.github.wulkanowy.utils.FragmentLifecycleLogger
|
import io.github.wulkanowy.utils.FragmentLifecycleLogger
|
||||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||||
|
@ -31,8 +30,6 @@ abstract class BaseActivity<T : BasePresenter<out BaseView>, VB : ViewBinding> :
|
||||||
|
|
||||||
protected var messageContainer: View? = null
|
protected var messageContainer: View? = null
|
||||||
|
|
||||||
protected var messageAnchor: View? = null
|
|
||||||
|
|
||||||
abstract var presenter: T
|
abstract var presenter: T
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
@ -51,7 +48,6 @@ abstract class BaseActivity<T : BasePresenter<out BaseView>, VB : ViewBinding> :
|
||||||
if (messageContainer != null) {
|
if (messageContainer != null) {
|
||||||
Snackbar.make(messageContainer!!, text, LENGTH_LONG)
|
Snackbar.make(messageContainer!!, text, LENGTH_LONG)
|
||||||
.setAction(R.string.all_details) { showErrorDetailsDialog(error) }
|
.setAction(R.string.all_details) { showErrorDetailsDialog(error) }
|
||||||
.apply { messageAnchor?.let { anchorView = it } }
|
|
||||||
.show()
|
.show()
|
||||||
} else showMessage(text)
|
} else showMessage(text)
|
||||||
}
|
}
|
||||||
|
@ -61,15 +57,12 @@ abstract class BaseActivity<T : BasePresenter<out BaseView>, VB : ViewBinding> :
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showMessage(text: String) {
|
override fun showMessage(text: String) {
|
||||||
if (messageContainer != null) {
|
if (messageContainer != null) Snackbar.make(messageContainer!!, text, LENGTH_LONG).show()
|
||||||
Snackbar.make(messageContainer!!, text, LENGTH_LONG)
|
else Toast.makeText(this, text, Toast.LENGTH_LONG).show()
|
||||||
.apply { messageAnchor?.let { anchorView = it } }
|
|
||||||
.show()
|
|
||||||
} else Toast.makeText(this, text, Toast.LENGTH_LONG).show()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showExpiredDialog() {
|
override fun showExpiredDialog() {
|
||||||
MaterialAlertDialogBuilder(this)
|
AlertDialog.Builder(this)
|
||||||
.setTitle(R.string.main_session_expired)
|
.setTitle(R.string.main_session_expired)
|
||||||
.setMessage(R.string.main_session_relogin)
|
.setMessage(R.string.main_session_relogin)
|
||||||
.setPositiveButton(R.string.main_log_in) { _, _ -> presenter.onExpiredLoginSelected() }
|
.setPositiveButton(R.string.main_log_in) { _, _ -> presenter.onExpiredLoginSelected() }
|
||||||
|
@ -77,15 +70,10 @@ abstract class BaseActivity<T : BasePresenter<out BaseView>, VB : ViewBinding> :
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showAuthDialog() {
|
|
||||||
AuthDialog.newInstance().show(supportFragmentManager, "auth_dialog")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showChangePasswordSnackbar(redirectUrl: String) {
|
override fun showChangePasswordSnackbar(redirectUrl: String) {
|
||||||
messageContainer?.let {
|
messageContainer?.let {
|
||||||
Snackbar.make(it, R.string.error_password_change_required, LENGTH_LONG)
|
Snackbar.make(it, R.string.error_password_change_required, LENGTH_LONG)
|
||||||
.setAction(R.string.all_change) { openInternetBrowser(redirectUrl) }
|
.setAction(R.string.all_change) { openInternetBrowser(redirectUrl) }
|
||||||
.apply { messageAnchor?.let { anchorView = it } }
|
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,8 @@
|
||||||
package io.github.wulkanowy.ui.base
|
package io.github.wulkanowy.ui.base
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import androidx.viewbinding.ViewBinding
|
import androidx.viewbinding.ViewBinding
|
||||||
import com.google.android.material.elevation.SurfaceColors
|
|
||||||
import io.github.wulkanowy.ui.modules.auth.AuthDialog
|
|
||||||
import io.github.wulkanowy.utils.AnalyticsHelper
|
import io.github.wulkanowy.utils.AnalyticsHelper
|
||||||
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -40,25 +34,10 @@ abstract class BaseDialogFragment<VB : ViewBinding> : DialogFragment(), BaseView
|
||||||
(activity as? BaseActivity<*, *>)?.showChangePasswordSnackbar(redirectUrl)
|
(activity as? BaseActivity<*, *>)?.showChangePasswordSnackbar(redirectUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showAuthDialog() {
|
|
||||||
AuthDialog.newInstance().show(childFragmentManager, "auth_dialog")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showErrorDetailsDialog(error: Throwable) {
|
override fun showErrorDetailsDialog(error: Throwable) {
|
||||||
ErrorDialog.newInstance(error).show(childFragmentManager, error.toString())
|
ErrorDialog.newInstance(error).show(childFragmentManager, error.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
view.setBackgroundColor(SurfaceColors.SURFACE_3.getColor(requireContext()))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateView(
|
|
||||||
inflater: LayoutInflater,
|
|
||||||
container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?
|
|
||||||
) = binding.root
|
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
analyticsHelper.setCurrentScreen(requireActivity(), this::class.simpleName)
|
analyticsHelper.setCurrentScreen(requireActivity(), this::class.simpleName)
|
||||||
|
|
|
@ -7,7 +7,6 @@ import androidx.viewbinding.ViewBinding
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.google.android.material.snackbar.Snackbar.LENGTH_LONG
|
import com.google.android.material.snackbar.Snackbar.LENGTH_LONG
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.ui.modules.auth.AuthDialog
|
|
||||||
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
||||||
|
|
||||||
abstract class BaseFragment<VB : ViewBinding>(@LayoutRes layoutId: Int) : Fragment(layoutId),
|
abstract class BaseFragment<VB : ViewBinding>(@LayoutRes layoutId: Int) : Fragment(layoutId),
|
||||||
|
@ -43,10 +42,6 @@ abstract class BaseFragment<VB : ViewBinding>(@LayoutRes layoutId: Int) : Fragme
|
||||||
(activity as? BaseActivity<*, *>)?.showExpiredDialog()
|
(activity as? BaseActivity<*, *>)?.showExpiredDialog()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showAuthDialog() {
|
|
||||||
AuthDialog.newInstance().show(childFragmentManager, "auth_dialog")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun openClearLoginView() {
|
override fun openClearLoginView() {
|
||||||
(activity as? BaseActivity<*, *>)?.openClearLoginView()
|
(activity as? BaseActivity<*, *>)?.openClearLoginView()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,10 @@
|
||||||
package io.github.wulkanowy.ui.base
|
package io.github.wulkanowy.ui.base
|
||||||
|
|
||||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
|
||||||
import kotlinx.coroutines.SupervisorJob
|
|
||||||
import kotlinx.coroutines.cancelChildren
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.catch
|
import kotlinx.coroutines.flow.catch
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
open class BasePresenter<T : BaseView>(
|
open class BasePresenter<T : BaseView>(
|
||||||
|
@ -31,7 +26,6 @@ open class BasePresenter<T : BaseView>(
|
||||||
onSessionExpired = view::showExpiredDialog
|
onSessionExpired = view::showExpiredDialog
|
||||||
onNoCurrentStudent = view::openClearLoginView
|
onNoCurrentStudent = view::openClearLoginView
|
||||||
onPasswordChangeRequired = view::showChangePasswordSnackbar
|
onPasswordChangeRequired = view::showChangePasswordSnackbar
|
||||||
onAuthorizationRequired = view::showAuthDialog
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue