Compare commits
No commits in common. "1.9.0" and "1.5.0" have entirely different histories.
383 changed files with 5740 additions and 28809 deletions
|
@ -1,12 +0,0 @@
|
||||||
[*]
|
|
||||||
charset=utf-8
|
|
||||||
end_of_line=lf
|
|
||||||
insert_final_newline=true
|
|
||||||
indent_style=space
|
|
||||||
indent_size=4
|
|
||||||
|
|
||||||
[*.json]
|
|
||||||
indent_size=2
|
|
||||||
|
|
||||||
[*.{kt,kts}]
|
|
||||||
disabled_rules=import-ordering,no-wildcard-imports
|
|
21
.github/workflows/deploy-store.yml
vendored
21
.github/workflows/deploy-store.yml
vendored
|
@ -1,4 +1,4 @@
|
||||||
name: Deploy release
|
name: Deploy to app stores
|
||||||
|
|
||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
|
@ -7,17 +7,16 @@ on:
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
deploy-google-play:
|
deploy-google-play:
|
||||||
name: Google Play
|
name: Deploy to google play
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
environment: google-play
|
environment: google-play
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-java@v2
|
- uses: actions/setup-java@v1
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: 11
|
java-version: 11
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.gradle/caches
|
~/.gradle/caches
|
||||||
|
@ -38,22 +37,20 @@ jobs:
|
||||||
ANDROID_PUBLISHER_CREDENTIALS: ${{ secrets.ANDROID_PUBLISHER_CREDENTIALS }}
|
ANDROID_PUBLISHER_CREDENTIALS: ${{ secrets.ANDROID_PUBLISHER_CREDENTIALS }}
|
||||||
ADMOB_PROJECT_ID: ${{ secrets.ADMOB_PROJECT_ID }}
|
ADMOB_PROJECT_ID: ${{ secrets.ADMOB_PROJECT_ID }}
|
||||||
SINGLE_SUPPORT_AD_ID: ${{ secrets.SINGLE_SUPPORT_AD_ID }}
|
SINGLE_SUPPORT_AD_ID: ${{ secrets.SINGLE_SUPPORT_AD_ID }}
|
||||||
DASHBOARD_TILE_AD_ID: ${{ secrets.DASHBOARD_TILE_AD_ID }}
|
|
||||||
SET_BUILD_TIMESTAMP: ${{ secrets.SET_BUILD_TIMESTAMP }}
|
SET_BUILD_TIMESTAMP: ${{ secrets.SET_BUILD_TIMESTAMP }}
|
||||||
run: ./gradlew publishPlayReleaseApps -PenableFirebase --stacktrace;
|
run: ./gradlew publishPlayReleaseApps -PenableFirebase --stacktrace;
|
||||||
|
|
||||||
deploy-app-gallery:
|
deploy-app-gallery:
|
||||||
name: AppGallery
|
name: Deploy to AppGallery
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
environment: app-gallery
|
environment: app-gallery
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-java@v2
|
- uses: actions/setup-java@v1
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: 11
|
java-version: 11
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.gradle/caches
|
~/.gradle/caches
|
||||||
|
|
20
.github/workflows/deploy-test.yml
vendored
20
.github/workflows/deploy-test.yml
vendored
|
@ -1,4 +1,4 @@
|
||||||
name: Deploy DEV
|
name: Deploy to app tests
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
@ -18,12 +18,11 @@ jobs:
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
environment: app-center
|
environment: app-center
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-java@v2
|
- uses: actions/setup-java@v1
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: 11
|
java-version: 11
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.gradle/caches
|
~/.gradle/caches
|
||||||
|
@ -67,7 +66,7 @@ jobs:
|
||||||
BITRISE_KEY_PASSWORD: ${{ secrets.BITRISE_KEY_PASSWORD }}
|
BITRISE_KEY_PASSWORD: ${{ secrets.BITRISE_KEY_PASSWORD }}
|
||||||
run: ./gradlew assembleFdroidDebug --stacktrace
|
run: ./gradlew assembleFdroidDebug --stacktrace
|
||||||
- name: Upload apk to github artifacts
|
- name: Upload apk to github artifacts
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: wulkanowyDEV-${{ env.RUN_NUMBER }}.apk
|
name: wulkanowyDEV-${{ env.RUN_NUMBER }}.apk
|
||||||
path: app/build/outputs/apk/fdroid/debug/app-fdroid-debug.apk
|
path: app/build/outputs/apk/fdroid/debug/app-fdroid-debug.apk
|
||||||
|
@ -88,12 +87,11 @@ jobs:
|
||||||
environment: app-distribution
|
environment: app-distribution
|
||||||
if: github.event_name != 'pull_request_target'
|
if: github.event_name != 'pull_request_target'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-java@v2
|
- uses: actions/setup-java@v1
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: 11
|
java-version: 11
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.gradle/caches
|
~/.gradle/caches
|
||||||
|
@ -133,7 +131,7 @@ jobs:
|
||||||
BITRISE_KEY_PASSWORD: ${{ secrets.BITRISE_KEY_PASSWORD }}
|
BITRISE_KEY_PASSWORD: ${{ secrets.BITRISE_KEY_PASSWORD }}
|
||||||
run: ./gradlew assemblePlayDebug -PenableFirebase --stacktrace
|
run: ./gradlew assemblePlayDebug -PenableFirebase --stacktrace
|
||||||
- name: Upload apk to github artifacts
|
- name: Upload apk to github artifacts
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: wulkanowyDEV-${{ env.RUN_NUMBER }}-dev.apk
|
name: wulkanowyDEV-${{ env.RUN_NUMBER }}-dev.apk
|
||||||
path: app/build/outputs/apk/play/debug/app-play-debug.apk
|
path: app/build/outputs/apk/play/debug/app-play-debug.apk
|
||||||
|
|
72
.github/workflows/test.yml
vendored
72
.github/workflows/test.yml
vendored
|
@ -2,28 +2,24 @@ name: Tests
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches: [ master, develop ]
|
||||||
- master
|
|
||||||
- develop
|
|
||||||
- 'hotfix/**'
|
|
||||||
tags: [ '*' ]
|
tags: [ '*' ]
|
||||||
pull_request:
|
pull_request:
|
||||||
|
branches: [ master, develop ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
unit-tests:
|
||||||
tests-fdroid:
|
name: Unit tests
|
||||||
name: F-Droid
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
steps:
|
steps:
|
||||||
- uses: fkirc/skip-duplicate-actions@master
|
- uses: fkirc/skip-duplicate-actions@master
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v2
|
||||||
- uses: gradle/wrapper-validation-action@v1
|
- uses: gradle/wrapper-validation-action@v1
|
||||||
- uses: actions/setup-java@v2
|
- uses: actions/setup-java@v1
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: 11
|
java-version: 11
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.gradle/caches
|
~/.gradle/caches
|
||||||
|
@ -33,58 +29,6 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
./gradlew testFdroidDebugUnitTest --stacktrace
|
./gradlew testFdroidDebugUnitTest --stacktrace
|
||||||
./gradlew jacocoTestReport --stacktrace
|
./gradlew jacocoTestReport --stacktrace
|
||||||
- uses: codecov/codecov-action@v3
|
- uses: codecov/codecov-action@v1
|
||||||
with:
|
|
||||||
flags: unit
|
|
||||||
|
|
||||||
tests-play:
|
|
||||||
name: Play
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 10
|
|
||||||
steps:
|
|
||||||
- uses: fkirc/skip-duplicate-actions@master
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: gradle/wrapper-validation-action@v1
|
|
||||||
- uses: actions/setup-java@v2
|
|
||||||
with:
|
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: 11
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.gradle/caches
|
|
||||||
~/.gradle/wrapper
|
|
||||||
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}
|
|
||||||
- name: Unit tests
|
|
||||||
run: |
|
|
||||||
./gradlew testPlayDebugUnitTest --stacktrace
|
|
||||||
./gradlew jacocoTestReport --stacktrace
|
|
||||||
- uses: codecov/codecov-action@v3
|
|
||||||
with:
|
|
||||||
flags: unit
|
|
||||||
|
|
||||||
tests-hms:
|
|
||||||
name: HMS
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 10
|
|
||||||
steps:
|
|
||||||
- uses: fkirc/skip-duplicate-actions@master
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: gradle/wrapper-validation-action@v1
|
|
||||||
- uses: actions/setup-java@v2
|
|
||||||
with:
|
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: 11
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.gradle/caches
|
|
||||||
~/.gradle/wrapper
|
|
||||||
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}
|
|
||||||
- name: Unit tests
|
|
||||||
run: |
|
|
||||||
./gradlew testHmsDebugUnitTest --stacktrace
|
|
||||||
./gradlew jacocoTestReport --stacktrace
|
|
||||||
- uses: codecov/codecov-action@v3
|
|
||||||
with:
|
with:
|
||||||
flags: unit
|
flags: unit
|
||||||
|
|
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 2021 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)
|
||||||
|
|
13
README.de.md
13
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
|
||||||
|
|
||||||
|
@ -50,7 +51,7 @@ Die aktuelle Version können Sie von der Google Play, F-Droid oder Huawei AppGal
|
||||||
alt="Explore it on AppGallery"
|
alt="Explore it on AppGallery"
|
||||||
height="80">](https://appgallery.cloud.huawei.com/ag/n/app/C101440411?channelId=Badge&id=1b3f7fbb700849a9be0dba6b520b2282&s=EB1D3BF9ED9D1564D869B7B94B18016D3CABFCA5AEFB8E29F675FA04E0DC131D&detailType=0&v=)
|
height="80">](https://appgallery.cloud.huawei.com/ag/n/app/C101440411?channelId=Badge&id=1b3f7fbb700849a9be0dba6b520b2282&s=EB1D3BF9ED9D1564D869B7B94B18016D3CABFCA5AEFB8E29F675FA04E0DC131D&detailType=0&v=)
|
||||||
|
|
||||||
Sie können auch eine [Entwicklungsversion herunterladen](https://wulkanowy.github.io/#download) die beinhaltet neue Funktionen, die für die nächste Version vorbereitet werden
|
Sie können auch ein [Entwicklungsversion herunterladen](https://wulkanowy.github.io/#download) das beinhaltet neue Funktionen, die für die nächste Version vorbereitet werden
|
||||||
|
|
||||||
## Gebaut mit
|
## Gebaut mit
|
||||||
|
|
||||||
|
|
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)
|
||||||
|
|
110
app/build.gradle
110
app/build.gradle
|
@ -15,35 +15,33 @@ apply from: 'sonarqube.gradle'
|
||||||
apply from: 'hooks.gradle'
|
apply from: 'hooks.gradle'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace 'io.github.wulkanowy'
|
compileSdkVersion 31
|
||||||
compileSdkVersion 33
|
|
||||||
|
|
||||||
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 33
|
targetSdkVersion 31
|
||||||
versionCode 119
|
versionCode 103
|
||||||
versionName "1.9.0"
|
versionName "1.5.0"
|
||||||
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 {
|
javaCompileOptions {
|
||||||
annotationProcessorOptions {
|
annotationProcessorOptions {
|
||||||
arguments += [
|
arguments += [
|
||||||
"room.schemaLocation": "$projectDir/schemas".toString(),
|
"room.schemaLocation": "$projectDir/schemas".toString(),
|
||||||
"room.incremental" : "true"
|
"room.incremental" : "true"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buildConfigField "String", "SINGLE_SUPPORT_AD_ID", "null"
|
buildConfigField "String", "SINGLE_SUPPORT_AD_ID", "null"
|
||||||
buildConfigField "String", "DASHBOARD_TILE_AD_ID", "null"
|
|
||||||
|
|
||||||
if (System.env.SET_BUILD_TIMESTAMP) {
|
if (System.env.SET_BUILD_TIMESTAMP) {
|
||||||
buildConfigField "long", "BUILD_TIMESTAMP", String.valueOf(System.currentTimeMillis())
|
buildConfigField "long", "BUILD_TIMESTAMP", String.valueOf(System.currentTimeMillis())
|
||||||
|
@ -75,8 +73,6 @@ android {
|
||||||
buildConfigField "String", "MESSAGES_BASE_URL", "\"https://messages.wulkanowy.net.pl\""
|
buildConfigField "String", "MESSAGES_BASE_URL", "\"https://messages.wulkanowy.net.pl\""
|
||||||
}
|
}
|
||||||
debug {
|
debug {
|
||||||
minifyEnabled false
|
|
||||||
shrinkResources false
|
|
||||||
resValue "string", "app_name", "Wulkanowy DEV"
|
resValue "string", "app_name", "Wulkanowy DEV"
|
||||||
applicationIdSuffix ".dev"
|
applicationIdSuffix ".dev"
|
||||||
versionNameSuffix "-dev"
|
versionNameSuffix "-dev"
|
||||||
|
@ -96,12 +92,10 @@ android {
|
||||||
play {
|
play {
|
||||||
dimension "platform"
|
dimension "platform"
|
||||||
manifestPlaceholders = [
|
manifestPlaceholders = [
|
||||||
install_channel : "Google Play",
|
install_channel : "Google Play",
|
||||||
admob_project_id: System.getenv("ADMOB_PROJECT_ID") ?: "ca-app-pub-3940256099942544~3347511713"
|
admob_project_id: System.getenv("ADMOB_PROJECT_ID") ?: "ca-app-pub-3940256099942544~3347511713"
|
||||||
]
|
]
|
||||||
buildConfigField "String", "SINGLE_SUPPORT_AD_ID", "\"${System.getenv("SINGLE_SUPPORT_AD_ID") ?: "ca-app-pub-3940256099942544/5354046379"}\""
|
buildConfigField "String", "SINGLE_SUPPORT_AD_ID", "\"${System.getenv("SINGLE_SUPPORT_AD_ID") ?: "ca-app-pub-3940256099942544/5354046379"}\""
|
||||||
buildConfigField "String", "DASHBOARD_TILE_AD_ID", "\"${System.getenv("DASHBOARD_TILE_AD_ID") ?: "ca-app-pub-3940256099942544/6300978111"}\""
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fdroid {
|
fdroid {
|
||||||
|
@ -126,8 +120,6 @@ android {
|
||||||
|
|
||||||
testOptions.unitTests {
|
testOptions.unitTests {
|
||||||
includeAndroidResources = true
|
includeAndroidResources = true
|
||||||
// workaround HMS test errors https://github.com/robolectric/robolectric/issues/2750
|
|
||||||
all { jvmArgs '-noverify' }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
|
@ -138,14 +130,12 @@ android {
|
||||||
|
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "11"
|
jvmTarget = "11"
|
||||||
freeCompilerArgs += ["-opt-in=kotlin.RequiresOptIn", "-Xjvm-default=all"]
|
freeCompilerArgs += ["-Xopt-in=kotlin.RequiresOptIn", "-Xjvm-default=all"]
|
||||||
}
|
}
|
||||||
|
|
||||||
packagingOptions {
|
packagingOptions {
|
||||||
resources {
|
exclude 'META-INF/library_release.kotlin_module'
|
||||||
excludes += ['META-INF/library_release.kotlin_module',
|
exclude 'META-INF/library-core_release.kotlin_module'
|
||||||
'META-INF/library-core_release.kotlin_module']
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
aboutLibraries {
|
aboutLibraries {
|
||||||
|
@ -161,7 +151,7 @@ play {
|
||||||
defaultToAppBundles = false
|
defaultToAppBundles = false
|
||||||
track = 'production'
|
track = 'production'
|
||||||
releaseStatus = com.github.triplet.gradle.androidpublisher.ReleaseStatus.IN_PROGRESS
|
releaseStatus = com.github.triplet.gradle.androidpublisher.ReleaseStatus.IN_PROGRESS
|
||||||
userFraction = 0.10d
|
userFraction = 0.25d
|
||||||
updatePriority = 1
|
updatePriority = 1
|
||||||
enabled.set(false)
|
enabled.set(false)
|
||||||
}
|
}
|
||||||
|
@ -179,42 +169,42 @@ huaweiPublish {
|
||||||
ext {
|
ext {
|
||||||
work_manager = "2.7.1"
|
work_manager = "2.7.1"
|
||||||
android_hilt = "1.0.0"
|
android_hilt = "1.0.0"
|
||||||
room = "2.4.3"
|
room = "2.4.0"
|
||||||
chucker = "3.5.2"
|
chucker = "3.5.2"
|
||||||
mockk = "1.13.3"
|
mockk = "1.12.1"
|
||||||
coroutines = "1.6.4"
|
coroutines = "1.6.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "io.github.wulkanowy:sdk:1.9.0"
|
implementation "io.github.wulkanowy:sdk:1.5.0"
|
||||||
|
|
||||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.8'
|
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
||||||
|
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1"
|
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines"
|
||||||
|
|
||||||
implementation "androidx.core:core-ktx:1.9.0"
|
implementation "androidx.core:core-ktx:1.7.0"
|
||||||
implementation 'androidx.core:core-splashscreen:1.0.0'
|
implementation 'androidx.core:core-splashscreen:1.0.0-alpha02'
|
||||||
implementation "androidx.activity:activity-ktx:1.6.1"
|
implementation "androidx.activity:activity-ktx:1.4.0"
|
||||||
implementation "androidx.appcompat:appcompat:1.5.1"
|
implementation "androidx.appcompat:appcompat:1.4.0"
|
||||||
implementation "androidx.fragment:fragment-ktx:1.5.5"
|
implementation "androidx.fragment:fragment-ktx:1.4.0"
|
||||||
implementation "androidx.annotation:annotation:1.5.0"
|
implementation "androidx.annotation:annotation:1.3.0"
|
||||||
|
|
||||||
implementation "androidx.preference:preference-ktx:1.2.0"
|
implementation "androidx.preference:preference-ktx:1.1.1"
|
||||||
implementation "androidx.recyclerview:recyclerview:1.2.1"
|
implementation "androidx.recyclerview:recyclerview:1.2.1"
|
||||||
implementation "androidx.viewpager2:viewpager2:1.1.0-beta01"
|
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.2"
|
||||||
implementation "androidx.coordinatorlayout:coordinatorlayout:1.2.0"
|
implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"
|
||||||
implementation "com.google.android.material:material:1.7.0"
|
implementation "com.google.android.material:material:1.4.0"
|
||||||
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.5.1"
|
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.4.0"
|
||||||
|
|
||||||
implementation "androidx.room:room-runtime:$room"
|
implementation "androidx.room:room-runtime:$room"
|
||||||
implementation "androidx.room:room-ktx:$room"
|
implementation "androidx.room:room-ktx:$room"
|
||||||
|
@ -230,51 +220,49 @@ dependencies {
|
||||||
|
|
||||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||||
implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0"
|
implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0"
|
||||||
implementation "com.squareup.okhttp3:logging-interceptor:4.10.0"
|
implementation "com.squareup.okhttp3:logging-interceptor:4.9.3"
|
||||||
|
|
||||||
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.0.5'
|
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.2.2"
|
implementation "io.coil-kt:coil:1.4.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.3.1'
|
||||||
implementation 'com.fredporciuncula:flow-preferences:1.8.0'
|
implementation 'com.fredporciuncula:flow-preferences:1.6.0'
|
||||||
implementation 'org.apache.commons:commons-text:1.10.0'
|
|
||||||
|
|
||||||
playImplementation platform('com.google.firebase:firebase-bom:31.1.1')
|
playImplementation platform('com.google.firebase:firebase-bom:29.0.3')
|
||||||
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.android.play:core:1.10.3'
|
playImplementation 'com.google.android.play:core:1.10.2'
|
||||||
playImplementation 'com.google.android.play:core-ktx:1.8.1'
|
playImplementation 'com.google.android.play:core-ktx:1.8.1'
|
||||||
playImplementation 'com.google.android.gms:play-services-ads:21.4.0'
|
playImplementation 'com.google.android.gms:play-services-ads:20.5.0'
|
||||||
|
|
||||||
hmsImplementation 'com.huawei.hms:hianalytics:6.9.0.301'
|
hmsImplementation 'com.huawei.hms:hianalytics:6.3.2.300'
|
||||||
hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.7.3.302'
|
hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.6.3.200'
|
||||||
|
|
||||||
releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker"
|
releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker"
|
||||||
|
|
||||||
debugImplementation "com.github.ChuckerTeam.Chucker:library:$chucker"
|
debugImplementation "com.github.ChuckerTeam.Chucker:library:$chucker"
|
||||||
debugImplementation 'com.github.amitshekhariitbhu.Android-Debug-Database:debug-db:1.0.6'
|
debugImplementation 'com.github.amitshekhariitbhu.Android-Debug-Database:debug-db:1.0.6'
|
||||||
debugImplementation 'com.github.haroldadmin:WhatTheStack:1.0.0-alpha04'
|
|
||||||
|
|
||||||
testImplementation "junit:junit:4.13.2"
|
testImplementation "junit:junit:4.13.2"
|
||||||
testImplementation "io.mockk:mockk:$mockk"
|
testImplementation "io.mockk:mockk:$mockk"
|
||||||
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.9.1'
|
testImplementation 'org.robolectric:robolectric:4.7.3'
|
||||||
testImplementation "androidx.test:runner:1.5.1"
|
testImplementation "androidx.test:runner:1.4.0"
|
||||||
testImplementation "androidx.test.ext:junit:1.1.4"
|
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.1"
|
androidTestImplementation "androidx.test:runner:1.4.0"
|
||||||
androidTestImplementation "androidx.test.ext:junit:1.1.4"
|
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"
|
||||||
}
|
}
|
||||||
|
|
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
File diff suppressed because it is too large
Load diff
|
@ -1,92 +1,33 @@
|
||||||
{
|
{
|
||||||
"agcgw": {
|
"agcgw":{
|
||||||
"backurl": "connect-dre.hispace.hicloud.com",
|
"backurl":"connect-dre.dbankcloud.cn",
|
||||||
"url": "connect-dre.dbankcloud.cn",
|
"url":"connect-dre.hispace.hicloud.com"
|
||||||
"websocketbackurl": "connect-ws-dre.hispace.dbankcloud.com",
|
},
|
||||||
"websocketurl": "connect-ws-dre.hispace.dbankcloud.cn"
|
"client":{
|
||||||
},
|
"cp_id":"890048000024105546",
|
||||||
"agcgw_all": {
|
"product_id":"",
|
||||||
"CN": "connect-drcn.dbankcloud.cn",
|
"client_id":"",
|
||||||
"CN_back": "connect-drcn.hispace.hicloud.com",
|
"client_secret":"",
|
||||||
"DE": "connect-dre.dbankcloud.cn",
|
"app_id":"101440411",
|
||||||
"DE_back": "connect-dre.hispace.hicloud.com",
|
"package_name":"io.github.wulkanowy.dev",
|
||||||
"RU": "connect-drru.hispace.dbankcloud.ru",
|
"api_key":""
|
||||||
"RU_back": "connect-drru.hispace.dbankcloud.cn",
|
},
|
||||||
"SG": "connect-dra.dbankcloud.cn",
|
"service":{
|
||||||
"SG_back": "connect-dra.hispace.hicloud.com"
|
"analytics":{
|
||||||
},
|
"collector_url":"datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn",
|
||||||
"websocketgw_all": {
|
"resource_id":"p1",
|
||||||
"CN": "connect-ws-drcn.hispace.dbankcloud.cn",
|
"channel_id":""
|
||||||
"CN_back": "connect-ws-drcn.hispace.dbankcloud.com",
|
},
|
||||||
"DE": "connect-ws-dre.hispace.dbankcloud.cn",
|
|
||||||
"DE_back": "connect-ws-dre.hispace.dbankcloud.com",
|
|
||||||
"RU": "connect-ws-drru.hispace.dbankcloud.ru",
|
|
||||||
"RU_back": "connect-ws-drru.hispace.dbankcloud.cn",
|
|
||||||
"SG": "connect-ws-dra.hispace.dbankcloud.cn",
|
|
||||||
"SG_back": "connect-ws-dra.hispace.dbankcloud.com"
|
|
||||||
},
|
|
||||||
"client": {
|
|
||||||
"cp_id": "890048000024105546",
|
|
||||||
"product_id": "736430079244736562",
|
|
||||||
"client_id": "514530959291319360",
|
|
||||||
"client_secret": "C42522DBF17D3D4BBE9D9C1783A54484B7E6844B388B7A67502D36A633A4186B",
|
|
||||||
"project_id": "736430079244736562",
|
|
||||||
"app_id": "106552551",
|
|
||||||
"api_key": "CgB6e3x9BUNiq+r8ebCHNojjjYsMT4pJSjjNDOkm9owtBb6rVI6LjnASoZBRxbjjhObcrV5gANo99fI/eKZDTbWS",
|
|
||||||
"package_name": "io.github.wulkanowy.dev"
|
|
||||||
},
|
|
||||||
"oauth_client": {
|
|
||||||
"client_id": "106552551",
|
|
||||||
"client_type": 1
|
|
||||||
},
|
|
||||||
"app_info": {
|
|
||||||
"app_id": "106552551",
|
|
||||||
"package_name": "io.github.wulkanowy.dev"
|
|
||||||
},
|
|
||||||
"service": {
|
|
||||||
"analytics": {
|
|
||||||
"collector_url": "datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn",
|
|
||||||
"collector_url_ru": "datacollector-drru.dt.dbankcloud.ru,datacollector-drru.dt.hicloud.com",
|
|
||||||
"collector_url_sg": "datacollector-dra.dt.hicloud.com,datacollector-dra.dt.dbankcloud.cn",
|
|
||||||
"collector_url_de": "datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn",
|
|
||||||
"collector_url_cn": "datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn",
|
|
||||||
"resource_id": "p1",
|
|
||||||
"channel_id": ""
|
|
||||||
},
|
|
||||||
"search":{
|
"search":{
|
||||||
"url":"https://search-dre.cloud.huawei.com"
|
"url":"https://search-dre.cloud.huawei.com"
|
||||||
},
|
},
|
||||||
"cloudstorage": {
|
"cloudstorage":{
|
||||||
"storage_url_sg_back": "https://agc-storage-dra.cloud.huawei.asia",
|
"storage_url":"https://ops-dre.agcstorage.link"
|
||||||
"storage_url_ru_back": "https://agc-storage-drru.cloud.huawei.ru",
|
},
|
||||||
"storage_url_ru": "https://agc-storage-drru.cloud.huawei.ru",
|
"ml":{
|
||||||
"storage_url_de_back": "https://agc-storage-dre.cloud.huawei.eu",
|
"mlservice_url":"ml-api-dre.ai.dbankcloud.com,ml-api-dre.ai.dbankcloud.cn"
|
||||||
"storage_url_de": "https://ops-dre.agcstorage.link",
|
}
|
||||||
"storage_url": "https://agc-storage-drcn.platform.dbankcloud.cn",
|
},
|
||||||
"storage_url_sg": "https://ops-dra.agcstorage.link",
|
"region":"DE",
|
||||||
"storage_url_cn_back": "https://agc-storage-drcn.cloud.huawei.com.cn",
|
"configuration_version":"1.0"
|
||||||
"storage_url_cn": "https://agc-storage-drcn.platform.dbankcloud.cn"
|
|
||||||
},
|
|
||||||
"ml": {
|
|
||||||
"mlservice_url": "ml-api-dre.ai.dbankcloud.com,ml-api-dre.ai.dbankcloud.cn"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"region": "DE",
|
|
||||||
"configuration_version": "3.0",
|
|
||||||
"appInfos": [
|
|
||||||
{
|
|
||||||
"package_name": "io.github.wulkanowy.dev",
|
|
||||||
"client": {
|
|
||||||
"app_id": "106552551"
|
|
||||||
},
|
|
||||||
"app_info": {
|
|
||||||
"package_name": "io.github.wulkanowy.dev",
|
|
||||||
"app_id": "106552551"
|
|
||||||
},
|
|
||||||
"oauth_client": {
|
|
||||||
"client_type": 1,
|
|
||||||
"client_id": "106552551"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,5 +2,4 @@
|
||||||
<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/colorPrimary" />
|
<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 |
|
@ -1,28 +0,0 @@
|
||||||
package io.github.wulkanowy.utils
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.view.View
|
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
|
||||||
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
class AdsHelper @Inject constructor(
|
|
||||||
@ApplicationContext private val context: Context,
|
|
||||||
private val preferencesRepository: PreferencesRepository
|
|
||||||
) {
|
|
||||||
|
|
||||||
fun initialize() {
|
|
||||||
preferencesRepository.isAdsEnabled = false
|
|
||||||
preferencesRepository.isAgreeToProcessData = false
|
|
||||||
preferencesRepository.selectedDashboardTiles -= DashboardItem.Tile.ADS
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("RedundantSuspendModifier", "UNUSED_PARAMETER")
|
|
||||||
suspend fun getDashboardTileAdBanner(width: Int): AdBanner {
|
|
||||||
throw IllegalStateException("Can't get ad banner (F-droid)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class AdBanner(val view: View)
|
|
|
@ -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,28 +0,0 @@
|
||||||
package io.github.wulkanowy.utils
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.view.View
|
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
|
||||||
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
class AdsHelper @Inject constructor(
|
|
||||||
@ApplicationContext private val context: Context,
|
|
||||||
private val preferencesRepository: PreferencesRepository
|
|
||||||
) {
|
|
||||||
|
|
||||||
fun initialize() {
|
|
||||||
preferencesRepository.isAdsEnabled = false
|
|
||||||
preferencesRepository.isAgreeToProcessData = false
|
|
||||||
preferencesRepository.selectedDashboardTiles -= DashboardItem.Tile.ADS
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("RedundantSuspendModifier", "UNUSED_PARAMETER")
|
|
||||||
suspend fun getDashboardTileAdBanner(width: Int): AdBanner {
|
|
||||||
throw IllegalStateException("Can't get ad banner (HMS)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class AdBanner(val view: View)
|
|
|
@ -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)
|
||||||
|
|
|
@ -3,7 +3,6 @@ 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.tressence.base.FormatterPriorityTree
|
import fr.bipi.tressence.base.FormatterPriorityTree
|
||||||
import fr.bipi.tressence.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)))
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Suppress("UNUSED_PARAMETER", "unused")
|
|
||||||
class InAppReviewHelper @Inject constructor(
|
class InAppReviewHelper @Inject constructor(
|
||||||
@ApplicationContext private val context: Context
|
@ApplicationContext private val context: Context
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
package="io.github.wulkanowy"
|
||||||
android:installLocation="internalOnly">
|
android:installLocation="internalOnly">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
@ -8,8 +9,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 +37,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"
|
||||||
|
|
|
@ -31,14 +31,10 @@ class WulkanowyApp : Application(), Configuration.Provider {
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var analyticsHelper: AnalyticsHelper
|
lateinit var analyticsHelper: AnalyticsHelper
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var adsHelper: AdsHelper
|
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
initializeAppLanguage()
|
initializeAppLanguage()
|
||||||
themeManager.applyDefaultTheme()
|
themeManager.applyDefaultTheme()
|
||||||
adsHelper.initialize()
|
|
||||||
initLogging()
|
initLogging()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ 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 kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.serialization.ExperimentalSerializationApi
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import okhttp3.MediaType.Companion.toMediaType
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
|
@ -109,6 +110,7 @@ internal class DataModule {
|
||||||
fun provideSharedPref(@ApplicationContext context: Context): SharedPreferences =
|
fun provideSharedPref(@ApplicationContext context: Context): SharedPreferences =
|
||||||
PreferenceManager.getDefaultSharedPreferences(context)
|
PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideFlowSharedPref(sharedPreferences: SharedPreferences) =
|
fun provideFlowSharedPref(sharedPreferences: SharedPreferences) =
|
||||||
|
@ -195,7 +197,7 @@ internal class DataModule {
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideMailboxesDao(database: AppDatabase) = database.mailboxDao
|
fun provideReportingUnitDao(database: AppDatabase) = database.reportingUnitDao
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
|
|
|
@ -1,173 +1,23 @@
|
||||||
package io.github.wulkanowy.data
|
package io.github.wulkanowy.data
|
||||||
|
|
||||||
import kotlinx.coroutines.flow.*
|
data class Resource<T>(val status: Status, val data: T?, val error: Throwable?) {
|
||||||
import kotlinx.coroutines.sync.Mutex
|
companion object {
|
||||||
import kotlinx.coroutines.sync.withLock
|
fun <T> success(data: T?): Resource<T> {
|
||||||
import timber.log.Timber
|
return Resource(Status.SUCCESS, data, null)
|
||||||
|
|
||||||
sealed class Resource<T> {
|
|
||||||
|
|
||||||
open class Loading<T> : Resource<T>()
|
|
||||||
|
|
||||||
data class Intermediate<T>(val data: T) : Loading<T>()
|
|
||||||
|
|
||||||
data class Success<T>(val data: T) : Resource<T>()
|
|
||||||
|
|
||||||
data class Error<T>(val error: Throwable) : Resource<T>()
|
|
||||||
}
|
|
||||||
|
|
||||||
val <T> Resource<T>.dataOrNull: T?
|
|
||||||
get() = when (this) {
|
|
||||||
is Resource.Success -> this.data
|
|
||||||
is Resource.Intermediate -> this.data
|
|
||||||
is Resource.Loading -> null
|
|
||||||
is Resource.Error -> null
|
|
||||||
}
|
|
||||||
|
|
||||||
val <T> Resource<T>.errorOrNull: Throwable?
|
|
||||||
get() = when (this) {
|
|
||||||
is Resource.Error -> this.error
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> resourceFlow(block: suspend () -> T) = flow {
|
|
||||||
emit(Resource.Loading())
|
|
||||||
emit(Resource.Success(block()))
|
|
||||||
}.catch { emit(Resource.Error(it)) }
|
|
||||||
|
|
||||||
fun <T> flatResourceFlow(block: suspend () -> Flow<Resource<T>>) = flow {
|
|
||||||
emit(Resource.Loading())
|
|
||||||
emitAll(block().filter { it is Resource.Intermediate || it !is Resource.Loading })
|
|
||||||
}.catch { emit(Resource.Error(it)) }
|
|
||||||
|
|
||||||
fun <T, U> Resource<T>.mapData(block: (T) -> U) = when (this) {
|
|
||||||
is Resource.Success -> Resource.Success(block(this.data))
|
|
||||||
is Resource.Intermediate -> Resource.Intermediate(block(this.data))
|
|
||||||
is Resource.Loading -> Resource.Loading()
|
|
||||||
is Resource.Error -> Resource.Error(this.error)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> Flow<Resource<T>>.logResourceStatus(name: String, showData: Boolean = false) = onEach {
|
|
||||||
val description = when (it) {
|
|
||||||
is Resource.Intermediate -> "intermediate data received" + if (showData) " (data: `${it.data}`)" else ""
|
|
||||||
is Resource.Loading -> "started"
|
|
||||||
is Resource.Success -> "success" + if (showData) " (data: `${it.data}`)" else ""
|
|
||||||
is Resource.Error -> "exception occurred: ${it.error}"
|
|
||||||
}
|
|
||||||
Timber.i("$name: $description")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T, U> Flow<Resource<T>>.mapResourceData(block: (T) -> U) = map {
|
|
||||||
it.mapData(block)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> Flow<Resource<T>>.onResourceData(block: suspend (T) -> Unit) = onEach {
|
|
||||||
when (it) {
|
|
||||||
is Resource.Success -> block(it.data)
|
|
||||||
is Resource.Intermediate -> block(it.data)
|
|
||||||
is Resource.Error,
|
|
||||||
is Resource.Loading -> Unit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> Flow<Resource<T>>.onResourceLoading(block: suspend () -> Unit) = onEach {
|
|
||||||
if (it is Resource.Loading) {
|
|
||||||
block()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> Flow<Resource<T>>.onResourceIntermediate(block: suspend (T) -> Unit) = onEach {
|
|
||||||
if (it is Resource.Intermediate) {
|
|
||||||
block(it.data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> Flow<Resource<T>>.onResourceSuccess(block: suspend (T) -> Unit) = onEach {
|
|
||||||
if (it is Resource.Success) {
|
|
||||||
block(it.data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> Flow<Resource<T>>.onResourceError(block: (Throwable) -> Unit) = onEach {
|
|
||||||
if (it is Resource.Error) {
|
|
||||||
block(it.error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> Flow<Resource<T>>.onResourceNotLoading(block: () -> Unit) = onEach {
|
|
||||||
if (it !is Resource.Loading) {
|
|
||||||
block()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun <T> Flow<Resource<T>>.toFirstResult() = filter { it !is Resource.Loading }.first()
|
|
||||||
|
|
||||||
suspend fun <T> Flow<Resource<T>>.waitForResult() = takeWhile { it is Resource.Loading }.collect()
|
|
||||||
|
|
||||||
inline fun <ResultType, RequestType> networkBoundResource(
|
|
||||||
mutex: Mutex = Mutex(),
|
|
||||||
showSavedOnLoading: Boolean = true,
|
|
||||||
crossinline isResultEmpty: (ResultType) -> Boolean,
|
|
||||||
crossinline query: () -> Flow<ResultType>,
|
|
||||||
crossinline fetch: suspend (ResultType) -> RequestType,
|
|
||||||
crossinline saveFetchResult: suspend (old: ResultType, new: RequestType) -> Unit,
|
|
||||||
crossinline onFetchFailed: (Throwable) -> Unit = { },
|
|
||||||
crossinline shouldFetch: (ResultType) -> Boolean = { true },
|
|
||||||
crossinline filterResult: (ResultType) -> ResultType = { it }
|
|
||||||
) = flow {
|
|
||||||
emit(Resource.Loading())
|
|
||||||
|
|
||||||
val data = query().first()
|
|
||||||
emitAll(if (shouldFetch(data)) {
|
|
||||||
val filteredResult = filterResult(data)
|
|
||||||
|
|
||||||
if (showSavedOnLoading && !isResultEmpty(filteredResult)) {
|
|
||||||
emit(Resource.Intermediate(filteredResult))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
fun <T> error(error: Throwable?, data: T? = null): Resource<T> {
|
||||||
val newData = fetch(data)
|
return Resource(Status.ERROR, data, error)
|
||||||
mutex.withLock { saveFetchResult(query().first(), newData) }
|
|
||||||
query().map { Resource.Success(filterResult(it)) }
|
|
||||||
} catch (throwable: Throwable) {
|
|
||||||
onFetchFailed(throwable)
|
|
||||||
query().map { Resource.Error(throwable) }
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
query().map { Resource.Success(filterResult(it)) }
|
fun <T> loading(data: T? = null): Resource<T> {
|
||||||
})
|
return Resource(Status.LOADING, data, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmName("networkBoundResourceWithMap")
|
enum class Status {
|
||||||
inline fun <ResultType, RequestType, T> networkBoundResource(
|
LOADING,
|
||||||
mutex: Mutex = Mutex(),
|
SUCCESS,
|
||||||
showSavedOnLoading: Boolean = true,
|
ERROR
|
||||||
crossinline isResultEmpty: (T) -> Boolean,
|
|
||||||
crossinline query: () -> Flow<ResultType>,
|
|
||||||
crossinline fetch: suspend (ResultType) -> RequestType,
|
|
||||||
crossinline saveFetchResult: suspend (old: ResultType, new: RequestType) -> Unit,
|
|
||||||
crossinline onFetchFailed: (Throwable) -> Unit = { },
|
|
||||||
crossinline shouldFetch: (ResultType) -> Boolean = { true },
|
|
||||||
crossinline mapResult: (ResultType) -> T
|
|
||||||
) = flow {
|
|
||||||
emit(Resource.Loading())
|
|
||||||
|
|
||||||
val data = query().first()
|
|
||||||
emitAll(if (shouldFetch(data)) {
|
|
||||||
val mappedResult = mapResult(data)
|
|
||||||
|
|
||||||
if (showSavedOnLoading && !isResultEmpty(mappedResult)) {
|
|
||||||
emit(Resource.Intermediate(mappedResult))
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
val newData = fetch(data)
|
|
||||||
mutex.withLock { saveFetchResult(query().first(), newData) }
|
|
||||||
query().map { Resource.Success(mapResult(it)) }
|
|
||||||
} catch (throwable: Throwable) {
|
|
||||||
onFetchFailed(throwable)
|
|
||||||
query().map { Resource.Error(throwable) }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
query().map { Resource.Success(mapResult(it)) }
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,72 @@
|
||||||
package io.github.wulkanowy.data.db
|
package io.github.wulkanowy.data.db
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.room.*
|
import androidx.room.AutoMigration
|
||||||
|
import androidx.room.Database
|
||||||
|
import androidx.room.Room
|
||||||
|
import androidx.room.RoomDatabase
|
||||||
import androidx.room.RoomDatabase.JournalMode.TRUNCATE
|
import androidx.room.RoomDatabase.JournalMode.TRUNCATE
|
||||||
import io.github.wulkanowy.data.db.dao.*
|
import androidx.room.TypeConverters
|
||||||
import io.github.wulkanowy.data.db.entities.*
|
import io.github.wulkanowy.data.db.dao.AdminMessageDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.AttendanceDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.CompletedLessonsDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.ConferenceDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.ExamDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.GradeDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.GradePartialStatisticsDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.GradeSemesterStatisticsDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.GradeSummaryDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.HomeworkDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.LuckyNumberDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.MessageAttachmentDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.MessagesDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.MobileDeviceDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.NoteDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.NotificationDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.RecipientDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.ReportingUnitDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.SchoolAnnouncementDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.SchoolDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.SemesterDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.StudentDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.StudentInfoDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.SubjectDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.TeacherDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.TimetableAdditionalDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.TimetableDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.TimetableHeaderDao
|
||||||
|
import io.github.wulkanowy.data.db.entities.AdminMessage
|
||||||
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
|
import io.github.wulkanowy.data.db.entities.AttendanceSummary
|
||||||
|
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
||||||
|
import io.github.wulkanowy.data.db.entities.Conference
|
||||||
|
import io.github.wulkanowy.data.db.entities.Exam
|
||||||
|
import io.github.wulkanowy.data.db.entities.Grade
|
||||||
|
import io.github.wulkanowy.data.db.entities.GradePartialStatistics
|
||||||
|
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
||||||
|
import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics
|
||||||
|
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||||
|
import io.github.wulkanowy.data.db.entities.Homework
|
||||||
|
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
||||||
|
import io.github.wulkanowy.data.db.entities.Message
|
||||||
|
import io.github.wulkanowy.data.db.entities.MessageAttachment
|
||||||
|
import io.github.wulkanowy.data.db.entities.MobileDevice
|
||||||
|
import io.github.wulkanowy.data.db.entities.Note
|
||||||
|
import io.github.wulkanowy.data.db.entities.Notification
|
||||||
|
import io.github.wulkanowy.data.db.entities.Recipient
|
||||||
|
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||||
|
import io.github.wulkanowy.data.db.entities.School
|
||||||
|
import io.github.wulkanowy.data.db.entities.SchoolAnnouncement
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import io.github.wulkanowy.data.db.entities.StudentInfo
|
||||||
|
import io.github.wulkanowy.data.db.entities.Subject
|
||||||
|
import io.github.wulkanowy.data.db.entities.Teacher
|
||||||
|
import io.github.wulkanowy.data.db.entities.Timetable
|
||||||
|
import io.github.wulkanowy.data.db.entities.TimetableAdditional
|
||||||
|
import io.github.wulkanowy.data.db.entities.TimetableHeader
|
||||||
import io.github.wulkanowy.data.db.migrations.*
|
import io.github.wulkanowy.data.db.migrations.*
|
||||||
import io.github.wulkanowy.utils.AppInfo
|
import io.github.wulkanowy.utils.AppInfo
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
@ -30,7 +92,7 @@ import javax.inject.Singleton
|
||||||
Subject::class,
|
Subject::class,
|
||||||
LuckyNumber::class,
|
LuckyNumber::class,
|
||||||
CompletedLesson::class,
|
CompletedLesson::class,
|
||||||
Mailbox::class,
|
ReportingUnit::class,
|
||||||
Recipient::class,
|
Recipient::class,
|
||||||
MobileDevice::class,
|
MobileDevice::class,
|
||||||
Teacher::class,
|
Teacher::class,
|
||||||
|
@ -46,8 +108,6 @@ import javax.inject.Singleton
|
||||||
autoMigrations = [
|
autoMigrations = [
|
||||||
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 = 51, to = 52),
|
|
||||||
],
|
],
|
||||||
version = AppDatabase.VERSION_SCHEMA,
|
version = AppDatabase.VERSION_SCHEMA,
|
||||||
exportSchema = true
|
exportSchema = true
|
||||||
|
@ -56,7 +116,7 @@ import javax.inject.Singleton
|
||||||
abstract class AppDatabase : RoomDatabase() {
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val VERSION_SCHEMA = 54
|
const val VERSION_SCHEMA = 47
|
||||||
|
|
||||||
fun getMigrations(sharedPrefProvider: SharedPrefProvider, appInfo: AppInfo) = arrayOf(
|
fun getMigrations(sharedPrefProvider: SharedPrefProvider, appInfo: AppInfo) = arrayOf(
|
||||||
Migration2(),
|
Migration2(),
|
||||||
|
@ -103,11 +163,6 @@ abstract class AppDatabase : RoomDatabase() {
|
||||||
Migration43(),
|
Migration43(),
|
||||||
Migration44(),
|
Migration44(),
|
||||||
Migration46(),
|
Migration46(),
|
||||||
Migration49(),
|
|
||||||
Migration50(),
|
|
||||||
Migration51(),
|
|
||||||
Migration53(),
|
|
||||||
Migration54(),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
fun newInstance(
|
fun newInstance(
|
||||||
|
@ -158,7 +213,7 @@ abstract class AppDatabase : RoomDatabase() {
|
||||||
|
|
||||||
abstract val completedLessonsDao: CompletedLessonsDao
|
abstract val completedLessonsDao: CompletedLessonsDao
|
||||||
|
|
||||||
abstract val mailboxDao: MailboxDao
|
abstract val reportingUnitDao: ReportingUnitDao
|
||||||
|
|
||||||
abstract val recipientDao: RecipientDao
|
abstract val recipientDao: RecipientDao
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
package io.github.wulkanowy.data.db
|
package io.github.wulkanowy.data.db
|
||||||
|
|
||||||
import androidx.room.TypeConverter
|
import androidx.room.TypeConverter
|
||||||
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
|
||||||
import kotlinx.serialization.decodeFromString
|
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.*
|
|
||||||
import java.util.*
|
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.Month
|
import java.time.Month
|
||||||
|
@ -61,11 +58,4 @@ class Converters {
|
||||||
emptyList() // handle errors from old gson Pair serialized data
|
emptyList() // handle errors from old gson Pair serialized data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TypeConverter
|
|
||||||
fun destinationToString(destination: Destination) = json.encodeToString(destination)
|
|
||||||
|
|
||||||
@TypeConverter
|
|
||||||
fun stringToDestination(destination: String): Destination = json.decodeFromString(destination)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,11 @@ package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
import androidx.room.Delete
|
import androidx.room.Delete
|
||||||
import androidx.room.Insert
|
import androidx.room.Insert
|
||||||
import androidx.room.OnConflictStrategy
|
|
||||||
import androidx.room.Update
|
import androidx.room.Update
|
||||||
|
|
||||||
interface BaseDao<T> {
|
interface BaseDao<T> {
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert
|
||||||
suspend fun insertAll(items: List<T>): List<Long>
|
suspend fun insertAll(items: List<T>): List<Long>
|
||||||
|
|
||||||
@Update
|
@Update
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.dao
|
|
||||||
|
|
||||||
import androidx.room.Dao
|
|
||||||
import androidx.room.Query
|
|
||||||
import io.github.wulkanowy.data.db.entities.Mailbox
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
@Dao
|
|
||||||
interface MailboxDao : BaseDao<Mailbox> {
|
|
||||||
|
|
||||||
@Query("SELECT * FROM Mailboxes WHERE email = :email")
|
|
||||||
suspend fun loadAll(email: String): 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>>
|
|
||||||
}
|
|
|
@ -11,12 +11,9 @@ import kotlinx.coroutines.flow.Flow
|
||||||
interface MessagesDao : BaseDao<Message> {
|
interface MessagesDao : BaseDao<Message> {
|
||||||
|
|
||||||
@Transaction
|
@Transaction
|
||||||
@Query("SELECT * FROM Messages WHERE message_global_key = :messageGlobalKey")
|
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND message_id = :messageId")
|
||||||
fun loadMessageWithAttachment(messageGlobalKey: String): Flow<MessageWithAttachment?>
|
fun loadMessageWithAttachment(studentId: Int, messageId: Int): Flow<MessageWithAttachment?>
|
||||||
|
|
||||||
@Query("SELECT * FROM Messages WHERE mailbox_key = :mailboxKey AND folder_id = :folder ORDER BY date DESC")
|
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND folder_id = :folder ORDER BY date DESC")
|
||||||
fun loadAll(mailboxKey: String, folder: Int): Flow<List<Message>>
|
fun loadAll(studentId: Int, 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>>
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,6 @@ import kotlinx.coroutines.flow.Flow
|
||||||
@Dao
|
@Dao
|
||||||
interface MobileDeviceDao : BaseDao<MobileDevice> {
|
interface MobileDeviceDao : BaseDao<MobileDevice> {
|
||||||
|
|
||||||
@Query("SELECT * FROM MobileDevices WHERE user_login_id = :userLoginId ORDER BY date DESC")
|
@Query("SELECT * FROM MobileDevices WHERE student_id = :userLoginId ORDER BY date DESC")
|
||||||
fun loadAll(userLoginId: Int): Flow<List<MobileDevice>>
|
fun loadAll(userLoginId: Int): Flow<List<MobileDevice>>
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ 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.MailboxType
|
|
||||||
import io.github.wulkanowy.data.db.entities.Recipient
|
import io.github.wulkanowy.data.db.entities.Recipient
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@ -10,6 +9,6 @@ import javax.inject.Singleton
|
||||||
@Dao
|
@Dao
|
||||||
interface RecipientDao : BaseDao<Recipient> {
|
interface RecipientDao : BaseDao<Recipient> {
|
||||||
|
|
||||||
@Query("SELECT * FROM Recipients WHERE type = :type AND studentMailboxGlobalKey = :studentMailboxGlobalKey")
|
@Query("SELECT * FROM Recipients WHERE student_id = :studentId AND unit_id = :unitId AND role = :role")
|
||||||
suspend fun loadAll(type: MailboxType, studentMailboxGlobalKey: String): List<Recipient>
|
suspend fun loadAll(studentId: Int, unitId: Int, role: Int): List<Recipient>
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Query
|
||||||
|
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Dao
|
||||||
|
interface ReportingUnitDao : BaseDao<ReportingUnit> {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM ReportingUnits WHERE student_id = :studentId")
|
||||||
|
suspend fun load(studentId: Int): List<ReportingUnit>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM ReportingUnits WHERE student_id = :studentId AND real_id = :unitId")
|
||||||
|
suspend fun loadOne(studentId: Int, unitId: Int): ReportingUnit?
|
||||||
|
}
|
|
@ -10,6 +10,6 @@ import javax.inject.Singleton
|
||||||
@Singleton
|
@Singleton
|
||||||
interface SchoolAnnouncementDao : BaseDao<SchoolAnnouncement> {
|
interface SchoolAnnouncementDao : BaseDao<SchoolAnnouncement> {
|
||||||
|
|
||||||
@Query("SELECT * FROM SchoolAnnouncements WHERE user_login_id = :userLoginId ORDER BY date DESC")
|
@Query("SELECT * FROM SchoolAnnouncements WHERE student_id = :studentId ORDER BY date DESC")
|
||||||
fun loadAll(userLoginId: Int): Flow<List<SchoolAnnouncement>>
|
fun loadAll(studentId: Int): Flow<List<SchoolAnnouncement>>
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,10 +33,6 @@ abstract class StudentDao {
|
||||||
@Query("SELECT * FROM Students")
|
@Query("SELECT * FROM Students")
|
||||||
abstract suspend fun loadStudentsWithSemesters(): List<StudentWithSemesters>
|
abstract suspend fun loadStudentsWithSemesters(): List<StudentWithSemesters>
|
||||||
|
|
||||||
@Transaction
|
|
||||||
@Query("SELECT * FROM Students WHERE id = :id")
|
|
||||||
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>
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,5 @@ data class GradeSemesterStatistics(
|
||||||
var id: Long = 0
|
var id: Long = 0
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
var classAverage: String = ""
|
var average: String = ""
|
||||||
|
|
||||||
@Transient
|
|
||||||
var studentAverage: String = ""
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.entities
|
|
||||||
|
|
||||||
import android.os.Parcelable
|
|
||||||
import androidx.room.Entity
|
|
||||||
import androidx.room.PrimaryKey
|
|
||||||
import kotlinx.parcelize.Parcelize
|
|
||||||
|
|
||||||
@Parcelize
|
|
||||||
@Entity(tableName = "Mailboxes")
|
|
||||||
data class Mailbox(
|
|
||||||
|
|
||||||
@PrimaryKey
|
|
||||||
val globalKey: String,
|
|
||||||
|
|
||||||
val email: String,
|
|
||||||
val symbol: String,
|
|
||||||
val schoolId: String,
|
|
||||||
|
|
||||||
val fullName: String,
|
|
||||||
val userName: String,
|
|
||||||
val studentName: String,
|
|
||||||
val schoolNameShort: String,
|
|
||||||
val type: MailboxType,
|
|
||||||
) : java.io.Serializable, Parcelable
|
|
||||||
|
|
||||||
enum class MailboxType {
|
|
||||||
STUDENT,
|
|
||||||
PARENT,
|
|
||||||
GUARDIAN,
|
|
||||||
EMPLOYEE,
|
|
||||||
UNKNOWN,
|
|
||||||
}
|
|
|
@ -9,19 +9,23 @@ import java.time.Instant
|
||||||
@Entity(tableName = "Messages")
|
@Entity(tableName = "Messages")
|
||||||
data class Message(
|
data class Message(
|
||||||
|
|
||||||
@ColumnInfo(name = "email")
|
@ColumnInfo(name = "student_id")
|
||||||
val email: String,
|
val studentId: Long,
|
||||||
|
|
||||||
@ColumnInfo(name = "message_global_key")
|
@ColumnInfo(name = "real_id")
|
||||||
val messageGlobalKey: String,
|
val realId: Int,
|
||||||
|
|
||||||
@ColumnInfo(name = "mailbox_key")
|
|
||||||
val mailboxKey: String,
|
|
||||||
|
|
||||||
@ColumnInfo(name = "message_id")
|
@ColumnInfo(name = "message_id")
|
||||||
val messageId: Int,
|
val messageId: Int,
|
||||||
|
|
||||||
val correspondents: String,
|
@ColumnInfo(name = "sender_name")
|
||||||
|
val sender: String,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "sender_id")
|
||||||
|
val senderId: Int,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "recipient_name")
|
||||||
|
val recipient: String,
|
||||||
|
|
||||||
val subject: String,
|
val subject: String,
|
||||||
|
|
||||||
|
@ -32,11 +36,7 @@ data class Message(
|
||||||
|
|
||||||
var unread: Boolean,
|
var unread: Boolean,
|
||||||
|
|
||||||
@ColumnInfo(name = "read_by")
|
val removed: Boolean,
|
||||||
val readBy: Int?,
|
|
||||||
|
|
||||||
@ColumnInfo(name = "unread_by")
|
|
||||||
val unreadBy: Int?,
|
|
||||||
|
|
||||||
@ColumnInfo(name = "has_attachments")
|
@ColumnInfo(name = "has_attachments")
|
||||||
val hasAttachments: Boolean
|
val hasAttachments: Boolean
|
||||||
|
@ -48,7 +48,11 @@ data class Message(
|
||||||
@ColumnInfo(name = "is_notified")
|
@ColumnInfo(name = "is_notified")
|
||||||
var isNotified: Boolean = true
|
var isNotified: Boolean = true
|
||||||
|
|
||||||
|
@ColumnInfo(name = "unread_by")
|
||||||
|
var unreadBy: Int = 0
|
||||||
|
|
||||||
|
@ColumnInfo(name = "read_by")
|
||||||
|
var readBy: Int = 0
|
||||||
|
|
||||||
var content: String = ""
|
var content: String = ""
|
||||||
var sender: String? = null
|
|
||||||
var recipients: String? = null
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,11 @@ data class MessageAttachment(
|
||||||
@ColumnInfo(name = "real_id")
|
@ColumnInfo(name = "real_id")
|
||||||
val realId: Int,
|
val realId: Int,
|
||||||
|
|
||||||
@ColumnInfo(name = "message_global_key")
|
@ColumnInfo(name = "message_id")
|
||||||
val messageGlobalKey: String,
|
val messageId: Int,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "one_drive_id")
|
||||||
|
val oneDriveId: String,
|
||||||
|
|
||||||
@ColumnInfo(name = "url")
|
@ColumnInfo(name = "url")
|
||||||
val url: String,
|
val url: String,
|
||||||
|
|
|
@ -7,6 +7,6 @@ data class MessageWithAttachment(
|
||||||
@Embedded
|
@Embedded
|
||||||
val message: Message,
|
val message: Message,
|
||||||
|
|
||||||
@Relation(parentColumn = "message_global_key", entityColumn = "message_global_key")
|
@Relation(parentColumn = "message_id", entityColumn = "message_id")
|
||||||
val attachments: List<MessageAttachment>
|
val attachments: List<MessageAttachment>
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,7 +9,7 @@ import java.time.Instant
|
||||||
@Entity(tableName = "MobileDevices")
|
@Entity(tableName = "MobileDevices")
|
||||||
data class MobileDevice(
|
data class MobileDevice(
|
||||||
|
|
||||||
@ColumnInfo(name = "user_login_id")
|
@ColumnInfo(name = "student_id")
|
||||||
val userLoginId: Int,
|
val userLoginId: Int,
|
||||||
|
|
||||||
@ColumnInfo(name = "device_id")
|
@ColumnInfo(name = "device_id")
|
||||||
|
|
|
@ -4,7 +4,6 @@ import androidx.room.ColumnInfo
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import io.github.wulkanowy.services.sync.notifications.NotificationType
|
import io.github.wulkanowy.services.sync.notifications.NotificationType
|
||||||
import io.github.wulkanowy.ui.modules.Destination
|
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
@Entity(tableName = "Notifications")
|
@Entity(tableName = "Notifications")
|
||||||
|
@ -19,9 +18,6 @@ data class Notification(
|
||||||
|
|
||||||
val type: NotificationType,
|
val type: NotificationType,
|
||||||
|
|
||||||
@ColumnInfo(defaultValue = "{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}")
|
|
||||||
val destination: Destination,
|
|
||||||
|
|
||||||
val date: Instant,
|
val date: Instant,
|
||||||
|
|
||||||
val data: String? = null
|
val data: String? = null
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.github.wulkanowy.data.db.entities
|
package io.github.wulkanowy.data.db.entities
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
@ -7,16 +8,32 @@ import java.io.Serializable
|
||||||
@kotlinx.serialization.Serializable
|
@kotlinx.serialization.Serializable
|
||||||
@Entity(tableName = "Recipients")
|
@Entity(tableName = "Recipients")
|
||||||
data class Recipient(
|
data class Recipient(
|
||||||
val mailboxGlobalKey: String,
|
|
||||||
val studentMailboxGlobalKey: String,
|
@ColumnInfo(name = "student_id")
|
||||||
val fullName: String,
|
val studentId: Int,
|
||||||
val userName: String,
|
|
||||||
val schoolShortName: String,
|
@ColumnInfo(name = "real_id")
|
||||||
val type: MailboxType,
|
val realId: String,
|
||||||
|
|
||||||
|
val name: String,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "real_name")
|
||||||
|
val realName: String,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "login_id")
|
||||||
|
val loginId: Int,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "unit_id")
|
||||||
|
val unitId: Int,
|
||||||
|
|
||||||
|
val role: Int,
|
||||||
|
|
||||||
|
val hash: String
|
||||||
|
|
||||||
) : Serializable {
|
) : Serializable {
|
||||||
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
var id: Long = 0
|
var id: Long = 0
|
||||||
|
|
||||||
override fun toString() = userName
|
override fun toString() = name
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
package io.github.wulkanowy.data.db.entities
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
@Entity(tableName = "ReportingUnits")
|
||||||
|
data class ReportingUnit(
|
||||||
|
|
||||||
|
@ColumnInfo(name = "student_id")
|
||||||
|
val studentId: Int,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "real_id")
|
||||||
|
val unitId: Int,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "short")
|
||||||
|
val shortName: String,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "sender_id")
|
||||||
|
val senderId: Int,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "sender_name")
|
||||||
|
val senderName: String,
|
||||||
|
|
||||||
|
val roles: List<Int>
|
||||||
|
|
||||||
|
) : Serializable {
|
||||||
|
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
var id: Long = 0
|
||||||
|
}
|
|
@ -9,8 +9,8 @@ import java.time.LocalDate
|
||||||
@Entity(tableName = "SchoolAnnouncements")
|
@Entity(tableName = "SchoolAnnouncements")
|
||||||
data class SchoolAnnouncement(
|
data class SchoolAnnouncement(
|
||||||
|
|
||||||
@ColumnInfo(name = "user_login_id")
|
@ColumnInfo(name = "student_id")
|
||||||
val userLoginId: Int,
|
val studentId: Int,
|
||||||
|
|
||||||
val date: LocalDate,
|
val date: LocalDate,
|
||||||
|
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.migrations
|
|
||||||
|
|
||||||
import androidx.room.migration.Migration
|
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
|
||||||
|
|
||||||
class Migration49 : Migration(48, 49) {
|
|
||||||
|
|
||||||
override fun migrate(database: SupportSQLiteDatabase) {
|
|
||||||
database.execSQL("DROP TABLE IF EXISTS SchoolAnnouncements")
|
|
||||||
|
|
||||||
database.execSQL(
|
|
||||||
"""
|
|
||||||
CREATE TABLE IF NOT EXISTS `SchoolAnnouncements` (
|
|
||||||
`user_login_id` INTEGER NOT NULL,
|
|
||||||
`date` INTEGER NOT NULL,
|
|
||||||
`subject` TEXT NOT NULL,
|
|
||||||
`content` TEXT NOT NULL,
|
|
||||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
||||||
`is_notified` INTEGER NOT NULL)
|
|
||||||
""".trimIndent()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.migrations
|
|
||||||
|
|
||||||
import androidx.room.migration.Migration
|
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
|
||||||
|
|
||||||
class Migration50 : Migration(49, 50) {
|
|
||||||
|
|
||||||
override fun migrate(database: SupportSQLiteDatabase) {
|
|
||||||
database.execSQL("DROP TABLE IF EXISTS MobileDevices")
|
|
||||||
database.execSQL(
|
|
||||||
"""
|
|
||||||
CREATE TABLE IF NOT EXISTS `MobileDevices` (
|
|
||||||
`user_login_id` INTEGER NOT NULL,
|
|
||||||
`device_id` INTEGER NOT NULL,
|
|
||||||
`name` TEXT NOT NULL,
|
|
||||||
`date` INTEGER NOT NULL,
|
|
||||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)
|
|
||||||
""".trimIndent()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,88 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.migrations
|
|
||||||
|
|
||||||
import androidx.room.migration.Migration
|
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
|
||||||
|
|
||||||
class Migration51 : Migration(50, 51) {
|
|
||||||
|
|
||||||
override fun migrate(database: SupportSQLiteDatabase) {
|
|
||||||
createMailboxTable(database)
|
|
||||||
recreateMessagesTable(database)
|
|
||||||
recreateMessageAttachmentsTable(database)
|
|
||||||
recreateRecipientsTable(database)
|
|
||||||
deleteReportingUnitTable(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,
|
|
||||||
`fullName` TEXT NOT NULL,
|
|
||||||
`userName` TEXT NOT NULL,
|
|
||||||
`userLoginId` INTEGER 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` (
|
|
||||||
`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,
|
|
||||||
`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()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun recreateMessageAttachmentsTable(database: SupportSQLiteDatabase) {
|
|
||||||
database.execSQL("DROP TABLE IF EXISTS MessageAttachments")
|
|
||||||
database.execSQL(
|
|
||||||
"""
|
|
||||||
CREATE TABLE IF NOT EXISTS `MessageAttachments` (
|
|
||||||
`real_id` INTEGER NOT NULL,
|
|
||||||
`message_global_key` TEXT NOT NULL,
|
|
||||||
`url` TEXT NOT NULL,
|
|
||||||
`filename` TEXT NOT NULL,
|
|
||||||
PRIMARY KEY(`real_id`)
|
|
||||||
)""".trimIndent()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun recreateRecipientsTable(database: SupportSQLiteDatabase) {
|
|
||||||
database.execSQL("DROP TABLE IF EXISTS Recipients")
|
|
||||||
database.execSQL(
|
|
||||||
"""
|
|
||||||
CREATE TABLE IF NOT EXISTS `Recipients` (
|
|
||||||
`mailboxGlobalKey` TEXT NOT NULL,
|
|
||||||
`studentMailboxGlobalKey` TEXT NOT NULL,
|
|
||||||
`fullName` TEXT NOT NULL,
|
|
||||||
`userName` TEXT NOT NULL,
|
|
||||||
`schoolShortName` TEXT NOT NULL,
|
|
||||||
`type` TEXT NOT NULL,
|
|
||||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL
|
|
||||||
)""".trimIndent()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun deleteReportingUnitTable(database: SupportSQLiteDatabase) {
|
|
||||||
database.execSQL("DROP TABLE IF EXISTS ReportingUnits")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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'")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,8 +2,7 @@ package io.github.wulkanowy.data.enums
|
||||||
|
|
||||||
enum class GradeSortingMode(val value: String) {
|
enum class GradeSortingMode(val value: String) {
|
||||||
ALPHABETIC("alphabetic"),
|
ALPHABETIC("alphabetic"),
|
||||||
DATE("date"),
|
DATE("date");
|
||||||
AVERAGE("average");
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun getByValue(value: String) = values().find { it.value == value } ?: ALPHABETIC
|
fun getByValue(value: String) = values().find { it.value == value } ?: ALPHABETIC
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -6,7 +6,7 @@ import io.github.wulkanowy.sdk.pojo.DirectorInformation as SdkDirectorInformatio
|
||||||
|
|
||||||
fun List<SdkDirectorInformation>.mapToEntities(student: Student) = map {
|
fun List<SdkDirectorInformation>.mapToEntities(student: Student) = map {
|
||||||
SchoolAnnouncement(
|
SchoolAnnouncement(
|
||||||
userLoginId = student.userLoginId,
|
studentId = student.userLoginId,
|
||||||
date = it.date,
|
date = it.date,
|
||||||
subject = it.subject,
|
subject = it.subject,
|
||||||
content = it.content,
|
content = it.content,
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
package io.github.wulkanowy.data.mappers
|
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.Mailbox
|
|
||||||
import io.github.wulkanowy.data.db.entities.MailboxType
|
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
|
||||||
import io.github.wulkanowy.sdk.pojo.Mailbox as SdkMailbox
|
|
||||||
|
|
||||||
fun List<SdkMailbox>.mapToEntities(student: Student) = map {
|
|
||||||
Mailbox(
|
|
||||||
globalKey = it.globalKey,
|
|
||||||
fullName = it.fullName,
|
|
||||||
userName = it.userName,
|
|
||||||
studentName = it.studentName,
|
|
||||||
schoolNameShort = it.schoolNameShort,
|
|
||||||
type = MailboxType.valueOf(it.type.name),
|
|
||||||
email = student.email,
|
|
||||||
symbol = student.symbol,
|
|
||||||
schoolId = student.schoolSymbol,
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,46 +1,40 @@
|
||||||
package io.github.wulkanowy.data.mappers
|
package io.github.wulkanowy.data.mappers
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.*
|
import io.github.wulkanowy.data.db.entities.Message
|
||||||
import io.github.wulkanowy.sdk.pojo.MailboxType
|
import io.github.wulkanowy.data.db.entities.MessageAttachment
|
||||||
import timber.log.Timber
|
import io.github.wulkanowy.data.db.entities.Recipient
|
||||||
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import java.time.Instant
|
||||||
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(student: Student) = map {
|
||||||
student: Student,
|
|
||||||
mailbox: Mailbox?,
|
|
||||||
allMailboxes: List<Mailbox>
|
|
||||||
): List<Message> = map {
|
|
||||||
Message(
|
Message(
|
||||||
messageGlobalKey = it.globalKey,
|
studentId = student.id,
|
||||||
mailboxKey = mailbox?.globalKey ?: allMailboxes.find { box ->
|
realId = it.id ?: 0,
|
||||||
box.fullName == it.mailbox
|
messageId = it.messageId ?: 0,
|
||||||
}?.globalKey.let { mailboxKey ->
|
sender = it.sender?.name.orEmpty(),
|
||||||
if (mailboxKey == null) {
|
senderId = it.sender?.loginId ?: 0,
|
||||||
Timber.e("Can't find ${it.mailbox} in $allMailboxes")
|
recipient = it.recipients.singleOrNull()?.name ?: "Wielu adresatów",
|
||||||
"unknown"
|
|
||||||
} else mailboxKey
|
|
||||||
},
|
|
||||||
email = student.email,
|
|
||||||
messageId = it.id,
|
|
||||||
correspondents = it.correspondents,
|
|
||||||
subject = it.subject.trim(),
|
subject = it.subject.trim(),
|
||||||
date = it.dateZoned.toInstant(),
|
date = it.dateZoned?.toInstant() ?: Instant.now(),
|
||||||
folderId = it.folderId,
|
folderId = it.folderId,
|
||||||
unread = it.unread,
|
unread = it.unread ?: false,
|
||||||
unreadBy = it.unreadBy,
|
removed = it.removed,
|
||||||
readBy = it.readBy,
|
hasAttachments = it.hasAttachments
|
||||||
hasAttachments = it.hasAttachments,
|
|
||||||
).apply {
|
).apply {
|
||||||
content = it.content.orEmpty()
|
content = it.content.orEmpty()
|
||||||
|
unreadBy = it.unreadBy ?: 0
|
||||||
|
readBy = it.readBy ?: 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun List<SdkMessageAttachment>.mapToEntities(messageGlobalKey: String) = map {
|
fun List<SdkMessageAttachment>.mapToEntities() = map {
|
||||||
MessageAttachment(
|
MessageAttachment(
|
||||||
messageGlobalKey = messageGlobalKey,
|
realId = it.id,
|
||||||
realId = it.url.hashCode(),
|
messageId = it.messageId,
|
||||||
|
oneDriveId = it.oneDriveId,
|
||||||
url = it.url,
|
url = it.url,
|
||||||
filename = it.filename
|
filename = it.filename
|
||||||
)
|
)
|
||||||
|
@ -48,11 +42,12 @@ fun List<SdkMessageAttachment>.mapToEntities(messageGlobalKey: String) = map {
|
||||||
|
|
||||||
fun List<Recipient>.mapFromEntities() = map {
|
fun List<Recipient>.mapFromEntities() = map {
|
||||||
SdkRecipient(
|
SdkRecipient(
|
||||||
fullName = it.fullName,
|
id = it.realId,
|
||||||
userName = it.userName,
|
name = it.realName,
|
||||||
studentName = it.userName,
|
loginId = it.loginId,
|
||||||
mailboxGlobalKey = it.mailboxGlobalKey,
|
reportingUnitId = it.unitId,
|
||||||
schoolNameShort = it.schoolShortName,
|
role = it.role,
|
||||||
type = MailboxType.valueOf(it.type.name),
|
hash = it.hash,
|
||||||
|
shortName = it.name
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
package io.github.wulkanowy.data.mappers
|
package io.github.wulkanowy.data.mappers
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.MobileDevice
|
import io.github.wulkanowy.data.db.entities.MobileDevice
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.pojos.MobileDeviceToken
|
import io.github.wulkanowy.data.pojos.MobileDeviceToken
|
||||||
import io.github.wulkanowy.sdk.pojo.Device as SdkDevice
|
import io.github.wulkanowy.sdk.pojo.Device as SdkDevice
|
||||||
import io.github.wulkanowy.sdk.pojo.Token as SdkToken
|
import io.github.wulkanowy.sdk.pojo.Token as SdkToken
|
||||||
|
|
||||||
fun List<SdkDevice>.mapToEntities(student: Student) = map {
|
fun List<SdkDevice>.mapToEntities(semester: Semester) = map {
|
||||||
MobileDevice(
|
MobileDevice(
|
||||||
userLoginId = student.userLoginId,
|
userLoginId = semester.studentId,
|
||||||
date = it.createDateZoned.toInstant(),
|
date = it.createDateZoned.toInstant(),
|
||||||
deviceId = it.id,
|
deviceId = it.id,
|
||||||
name = it.name
|
name = it.name
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
package io.github.wulkanowy.data.mappers
|
package io.github.wulkanowy.data.mappers
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.MailboxType
|
|
||||||
import io.github.wulkanowy.data.db.entities.Recipient
|
import io.github.wulkanowy.data.db.entities.Recipient
|
||||||
import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient
|
import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient
|
||||||
|
|
||||||
fun List<SdkRecipient>.mapToEntities(studentMailboxGlobalKey: String) = map {
|
fun List<SdkRecipient>.mapToEntities(userLoginId: Int) = map {
|
||||||
Recipient(
|
Recipient(
|
||||||
mailboxGlobalKey = it.mailboxGlobalKey,
|
studentId = userLoginId,
|
||||||
fullName = it.fullName,
|
realId = it.id,
|
||||||
userName = it.userName,
|
realName = it.name,
|
||||||
studentMailboxGlobalKey = studentMailboxGlobalKey,
|
name = it.shortName,
|
||||||
schoolShortName = it.schoolNameShort,
|
hash = it.hash,
|
||||||
type = MailboxType.valueOf(it.type.name),
|
loginId = it.loginId,
|
||||||
|
role = it.role,
|
||||||
|
unitId = it.reportingUnitId ?: 0
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,87 +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 io.github.wulkanowy.sdk.Sdk
|
|
||||||
import io.github.wulkanowy.sdk.mapper.mapSemesters
|
|
||||||
import java.time.Instant
|
|
||||||
import io.github.wulkanowy.sdk.scrapper.register.RegisterStudent as SdkRegisterStudent
|
|
||||||
import io.github.wulkanowy.sdk.scrapper.register.RegisterUser as SdkRegisterUser
|
|
||||||
|
|
||||||
fun SdkRegisterUser.mapToPojo(password: String) = RegisterUser(
|
|
||||||
email = email,
|
|
||||||
login = login,
|
|
||||||
password = password,
|
|
||||||
baseUrl = baseUrl,
|
|
||||||
loginType = loginType,
|
|
||||||
symbols = symbols.map { registerSymbol ->
|
|
||||||
RegisterSymbol(
|
|
||||||
symbol = registerSymbol.symbol,
|
|
||||||
error = registerSymbol.error,
|
|
||||||
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
|
|
||||||
.mapSemesters()
|
|
||||||
.mapToEntities(registerSubject.studentId),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
fun RegisterStudent.mapToStudentWithSemesters(
|
|
||||||
user: RegisterUser,
|
|
||||||
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,
|
|
||||||
schoolName = unit.schoolName,
|
|
||||||
schoolShortName = unit.schoolShortName,
|
|
||||||
schoolSymbol = unit.schoolId,
|
|
||||||
studentName = "$studentName $studentSurname",
|
|
||||||
loginMode = Sdk.Mode.SCRAPPER.name,
|
|
||||||
scrapperBaseUrl = user.baseUrl,
|
|
||||||
mobileBaseUrl = "",
|
|
||||||
certificateKey = "",
|
|
||||||
privateKey = "",
|
|
||||||
password = user.password,
|
|
||||||
isCurrent = false,
|
|
||||||
registrationDate = Instant.now(),
|
|
||||||
).apply {
|
|
||||||
avatarColor = colors.random()
|
|
||||||
},
|
|
||||||
)
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
package io.github.wulkanowy.data.mappers
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||||
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import io.github.wulkanowy.sdk.pojo.ReportingUnit as SdkReportingUnit
|
||||||
|
|
||||||
|
fun List<SdkReportingUnit>.mapToEntities(student: Student) = map {
|
||||||
|
ReportingUnit(
|
||||||
|
studentId = student.id.toInt(),
|
||||||
|
unitId = it.id,
|
||||||
|
roles = it.roles,
|
||||||
|
senderId = it.senderId,
|
||||||
|
senderName = it.senderName,
|
||||||
|
shortName = it.short
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
package io.github.wulkanowy.data.pojos
|
package io.github.wulkanowy.data.pojos
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
import io.github.wulkanowy.services.sync.notifications.NotificationType
|
import io.github.wulkanowy.services.sync.notifications.NotificationType
|
||||||
import io.github.wulkanowy.ui.modules.Destination
|
|
||||||
|
|
||||||
data class NotificationData(
|
data class NotificationData(
|
||||||
val destination: Destination,
|
val intentToStart: Intent,
|
||||||
val title: String,
|
val title: String,
|
||||||
val content: String
|
val content: String
|
||||||
)
|
)
|
||||||
|
@ -13,7 +13,7 @@ data class GroupNotificationData(
|
||||||
val notificationDataList: List<NotificationData>,
|
val notificationDataList: List<NotificationData>,
|
||||||
val title: String,
|
val title: String,
|
||||||
val content: String,
|
val content: String,
|
||||||
val destination: Destination,
|
val intentToStart: Intent,
|
||||||
val type: NotificationType
|
val type: NotificationType
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
package io.github.wulkanowy.data.pojos
|
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
|
||||||
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 baseUrl: String,
|
|
||||||
val loginType: Scrapper.LoginType,
|
|
||||||
val symbols: List<RegisterSymbol>,
|
|
||||||
) : java.io.Serializable
|
|
||||||
|
|
||||||
data class RegisterSymbol(
|
|
||||||
val symbol: String,
|
|
||||||
val error: Throwable?,
|
|
||||||
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
|
|
|
@ -3,8 +3,8 @@ package io.github.wulkanowy.data.repositories
|
||||||
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.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.networkBoundResource
|
|
||||||
import io.github.wulkanowy.utils.AppInfo
|
import io.github.wulkanowy.utils.AppInfo
|
||||||
|
import io.github.wulkanowy.utils.networkBoundResource
|
||||||
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
|
||||||
|
@ -19,7 +19,6 @@ class AdminMessageRepository @Inject constructor(
|
||||||
|
|
||||||
suspend fun getAdminMessages(student: Student) = networkBoundResource(
|
suspend fun getAdminMessages(student: Student) = networkBoundResource(
|
||||||
mutex = saveFetchResultMutex,
|
mutex = saveFetchResultMutex,
|
||||||
isResultEmpty = { it == null },
|
|
||||||
query = { adminMessageDao.loadAll() },
|
query = { adminMessageDao.loadAll() },
|
||||||
fetch = { adminMessageService.getAdminMessages() },
|
fetch = { adminMessageService.getAdminMessages() },
|
||||||
shouldFetch = { true },
|
shouldFetch = { true },
|
||||||
|
|
|
@ -1,19 +1,15 @@
|
||||||
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
|
||||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
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 +19,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,
|
||||||
) {
|
) {
|
||||||
|
@ -41,7 +36,6 @@ class AttendanceRepository @Inject constructor(
|
||||||
notify: Boolean = false,
|
notify: Boolean = false,
|
||||||
) = networkBoundResource(
|
) = networkBoundResource(
|
||||||
mutex = saveFetchResultMutex,
|
mutex = saveFetchResultMutex,
|
||||||
isResultEmpty = { it.isEmpty() },
|
|
||||||
shouldFetch = {
|
shouldFetch = {
|
||||||
val isExpired = refreshHelper.shouldBeRefreshed(
|
val isExpired = refreshHelper.shouldBeRefreshed(
|
||||||
key = getRefreshKey(cacheKey, semester, start, end)
|
key = getRefreshKey(cacheKey, semester, start, end)
|
||||||
|
@ -52,15 +46,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, semester.semesterId)
|
.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)
|
||||||
|
|
|
@ -4,12 +4,8 @@ import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao
|
||||||
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.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.data.networkBoundResource
|
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.getRefreshKey
|
|
||||||
import io.github.wulkanowy.utils.init
|
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
|
||||||
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
|
||||||
|
@ -32,7 +28,6 @@ class AttendanceSummaryRepository @Inject constructor(
|
||||||
forceRefresh: Boolean,
|
forceRefresh: Boolean,
|
||||||
) = networkBoundResource(
|
) = networkBoundResource(
|
||||||
mutex = saveFetchResultMutex,
|
mutex = saveFetchResultMutex,
|
||||||
isResultEmpty = { it.isEmpty() },
|
|
||||||
shouldFetch = {
|
shouldFetch = {
|
||||||
val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, semester))
|
val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, semester))
|
||||||
it.isEmpty() || forceRefresh || isExpired
|
it.isEmpty() || forceRefresh || isExpired
|
||||||
|
|
|
@ -4,7 +4,6 @@ import io.github.wulkanowy.data.db.dao.CompletedLessonsDao
|
||||||
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.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.data.networkBoundResource
|
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.*
|
import io.github.wulkanowy.utils.*
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
|
@ -31,7 +30,6 @@ class CompletedLessonsRepository @Inject constructor(
|
||||||
forceRefresh: Boolean,
|
forceRefresh: Boolean,
|
||||||
) = networkBoundResource(
|
) = networkBoundResource(
|
||||||
mutex = saveFetchResultMutex,
|
mutex = saveFetchResultMutex,
|
||||||
isResultEmpty = { it.isEmpty() },
|
|
||||||
shouldFetch = {
|
shouldFetch = {
|
||||||
val isExpired = refreshHelper.shouldBeRefreshed(
|
val isExpired = refreshHelper.shouldBeRefreshed(
|
||||||
key = getRefreshKey(cacheKey, semester, start, end)
|
key = getRefreshKey(cacheKey, semester, start, end)
|
||||||
|
|
|
@ -5,12 +5,8 @@ import io.github.wulkanowy.data.db.entities.Conference
|
||||||
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.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.data.networkBoundResource
|
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.getRefreshKey
|
|
||||||
import io.github.wulkanowy.utils.init
|
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
@ -36,7 +32,6 @@ class ConferenceRepository @Inject constructor(
|
||||||
startDate: Instant = Instant.EPOCH,
|
startDate: Instant = Instant.EPOCH,
|
||||||
) = networkBoundResource(
|
) = networkBoundResource(
|
||||||
mutex = saveFetchResultMutex,
|
mutex = saveFetchResultMutex,
|
||||||
isResultEmpty = { it.isEmpty() },
|
|
||||||
shouldFetch = {
|
shouldFetch = {
|
||||||
val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, semester))
|
val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, semester))
|
||||||
it.isEmpty() || forceRefresh || isExpired
|
it.isEmpty() || forceRefresh || isExpired
|
||||||
|
|
|
@ -5,7 +5,6 @@ import io.github.wulkanowy.data.db.entities.Exam
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.data.networkBoundResource
|
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.*
|
import io.github.wulkanowy.utils.*
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
@ -34,7 +33,6 @@ class ExamRepository @Inject constructor(
|
||||||
notify: Boolean = false,
|
notify: Boolean = false,
|
||||||
) = networkBoundResource(
|
) = networkBoundResource(
|
||||||
mutex = saveFetchResultMutex,
|
mutex = saveFetchResultMutex,
|
||||||
isResultEmpty = { it.isEmpty() },
|
|
||||||
shouldFetch = {
|
shouldFetch = {
|
||||||
val isExpired = refreshHelper.shouldBeRefreshed(
|
val isExpired = refreshHelper.shouldBeRefreshed(
|
||||||
key = getRefreshKey(cacheKey, semester, start, end)
|
key = getRefreshKey(cacheKey, semester, start, end)
|
||||||
|
|
|
@ -7,7 +7,6 @@ import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.data.networkBoundResource
|
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.*
|
import io.github.wulkanowy.utils.*
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
@ -37,10 +36,6 @@ class GradeRepository @Inject constructor(
|
||||||
notify: Boolean = false,
|
notify: Boolean = false,
|
||||||
) = networkBoundResource(
|
) = networkBoundResource(
|
||||||
mutex = saveFetchResultMutex,
|
mutex = saveFetchResultMutex,
|
||||||
isResultEmpty = {
|
|
||||||
//When details is empty and summary is not, app will not use summary cache - edge case
|
|
||||||
it.first.isEmpty()
|
|
||||||
},
|
|
||||||
shouldFetch = { (details, summaries) ->
|
shouldFetch = { (details, summaries) ->
|
||||||
val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, semester))
|
val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, semester))
|
||||||
details.isEmpty() || summaries.isEmpty() || forceRefresh || isExpired
|
details.isEmpty() || summaries.isEmpty() || forceRefresh || isExpired
|
||||||
|
|
|
@ -11,12 +11,8 @@ import io.github.wulkanowy.data.mappers.mapPartialToStatisticItems
|
||||||
import io.github.wulkanowy.data.mappers.mapPointsToStatisticsItems
|
import io.github.wulkanowy.data.mappers.mapPointsToStatisticsItems
|
||||||
import io.github.wulkanowy.data.mappers.mapSemesterToStatisticItems
|
import io.github.wulkanowy.data.mappers.mapSemesterToStatisticItems
|
||||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.data.networkBoundResource
|
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.getRefreshKey
|
|
||||||
import io.github.wulkanowy.utils.init
|
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -46,7 +42,6 @@ class GradeStatisticsRepository @Inject constructor(
|
||||||
forceRefresh: Boolean,
|
forceRefresh: Boolean,
|
||||||
) = networkBoundResource(
|
) = networkBoundResource(
|
||||||
mutex = partialMutex,
|
mutex = partialMutex,
|
||||||
isResultEmpty = { it.isEmpty() },
|
|
||||||
shouldFetch = {
|
shouldFetch = {
|
||||||
val isExpired = refreshHelper.shouldBeRefreshed(
|
val isExpired = refreshHelper.shouldBeRefreshed(
|
||||||
key = getRefreshKey(partialCacheKey, semester)
|
key = getRefreshKey(partialCacheKey, semester)
|
||||||
|
@ -68,16 +63,20 @@ class GradeStatisticsRepository @Inject constructor(
|
||||||
mapResult = { items ->
|
mapResult = { items ->
|
||||||
when (subjectName) {
|
when (subjectName) {
|
||||||
"Wszystkie" -> {
|
"Wszystkie" -> {
|
||||||
val summaryItem = GradePartialStatistics(
|
val numerator = items.map {
|
||||||
|
it.classAverage.replace(",", ".").toDoubleOrNull() ?: .0
|
||||||
|
}.filterNot { it == .0 }
|
||||||
|
(items.reversed() + GradePartialStatistics(
|
||||||
studentId = semester.studentId,
|
studentId = semester.studentId,
|
||||||
semesterId = semester.semesterId,
|
semesterId = semester.semesterId,
|
||||||
subject = subjectName,
|
subject = subjectName,
|
||||||
classAverage = items.map { it.classAverage }.getSummaryAverage(),
|
classAverage = if (numerator.isEmpty()) "" else numerator.average().let {
|
||||||
studentAverage = items.map { it.studentAverage }.getSummaryAverage(),
|
"%.2f".format(Locale.FRANCE, it)
|
||||||
|
},
|
||||||
|
studentAverage = "",
|
||||||
classAmounts = items.map { it.classAmounts }.sumGradeAmounts(),
|
classAmounts = items.map { it.classAmounts }.sumGradeAmounts(),
|
||||||
studentAmounts = items.map { it.studentAmounts }.sumGradeAmounts()
|
studentAmounts = items.map { it.studentAmounts }.sumGradeAmounts()
|
||||||
)
|
)).reversed()
|
||||||
listOf(summaryItem) + items
|
|
||||||
}
|
}
|
||||||
else -> items.filter { it.subject == subjectName }
|
else -> items.filter { it.subject == subjectName }
|
||||||
}.mapPartialToStatisticItems()
|
}.mapPartialToStatisticItems()
|
||||||
|
@ -91,7 +90,6 @@ class GradeStatisticsRepository @Inject constructor(
|
||||||
forceRefresh: Boolean,
|
forceRefresh: Boolean,
|
||||||
) = networkBoundResource(
|
) = networkBoundResource(
|
||||||
mutex = semesterMutex,
|
mutex = semesterMutex,
|
||||||
isResultEmpty = { it.isEmpty() },
|
|
||||||
shouldFetch = {
|
shouldFetch = {
|
||||||
val isExpired = refreshHelper.shouldBeRefreshed(
|
val isExpired = refreshHelper.shouldBeRefreshed(
|
||||||
key = getRefreshKey(semesterCacheKey, semester)
|
key = getRefreshKey(semesterCacheKey, semester)
|
||||||
|
@ -114,29 +112,29 @@ class GradeStatisticsRepository @Inject constructor(
|
||||||
val itemsWithAverage = items.map { item ->
|
val itemsWithAverage = items.map { item ->
|
||||||
item.copy().apply {
|
item.copy().apply {
|
||||||
val denominator = item.amounts.sum()
|
val denominator = item.amounts.sum()
|
||||||
classAverage = if (denominator == 0) "" else {
|
average = if (denominator == 0) "" else {
|
||||||
(item.amounts.mapIndexed { gradeValue, amount ->
|
(item.amounts.mapIndexed { gradeValue, amount ->
|
||||||
(gradeValue + 1) * amount
|
(gradeValue + 1) * amount
|
||||||
}.sum().toDouble() / denominator).asAverageString()
|
}.sum().toDouble() / denominator).let {
|
||||||
|
"%.2f".format(Locale.FRANCE, it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
when (subjectName) {
|
when (subjectName) {
|
||||||
"Wszystkie" -> {
|
"Wszystkie" -> (itemsWithAverage.reversed() + GradeSemesterStatistics(
|
||||||
val summaryItem = GradeSemesterStatistics(
|
studentId = semester.studentId,
|
||||||
studentId = semester.studentId,
|
semesterId = semester.semesterId,
|
||||||
semesterId = semester.semesterId,
|
subject = subjectName,
|
||||||
subject = subjectName,
|
amounts = itemsWithAverage.map { it.amounts }.sumGradeAmounts(),
|
||||||
amounts = itemsWithAverage.map { it.amounts }.sumGradeAmounts(),
|
studentGrade = 0
|
||||||
studentGrade = 0,
|
).apply {
|
||||||
).apply {
|
average = itemsWithAverage.mapNotNull {
|
||||||
classAverage = itemsWithAverage.map { it.classAverage }.getSummaryAverage()
|
it.average.replace(",", ".").toDoubleOrNull()
|
||||||
studentAverage = items
|
}.average().let {
|
||||||
.mapNotNull { summary -> summary.studentGrade.takeIf { it != 0 } }
|
"%.2f".format(Locale.FRANCE, it)
|
||||||
.average().asAverageString()
|
|
||||||
}
|
}
|
||||||
listOf(summaryItem) + itemsWithAverage
|
}).reversed()
|
||||||
}
|
|
||||||
else -> itemsWithAverage.filter { it.subject == subjectName }
|
else -> itemsWithAverage.filter { it.subject == subjectName }
|
||||||
}.mapSemesterToStatisticItems()
|
}.mapSemesterToStatisticItems()
|
||||||
}
|
}
|
||||||
|
@ -149,7 +147,6 @@ class GradeStatisticsRepository @Inject constructor(
|
||||||
forceRefresh: Boolean,
|
forceRefresh: Boolean,
|
||||||
) = networkBoundResource(
|
) = networkBoundResource(
|
||||||
mutex = pointsMutex,
|
mutex = pointsMutex,
|
||||||
isResultEmpty = { it.isEmpty() },
|
|
||||||
shouldFetch = {
|
shouldFetch = {
|
||||||
val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(pointsCacheKey, semester))
|
val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(pointsCacheKey, semester))
|
||||||
it.isEmpty() || forceRefresh || isExpired
|
it.isEmpty() || forceRefresh || isExpired
|
||||||
|
@ -174,19 +171,6 @@ class GradeStatisticsRepository @Inject constructor(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun List<String>.getSummaryAverage(): String {
|
|
||||||
val averages = mapNotNull {
|
|
||||||
it.replace(",", ".").toDoubleOrNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
return averages.average()
|
|
||||||
.asAverageString()
|
|
||||||
.takeIf { averages.isNotEmpty() }
|
|
||||||
.orEmpty()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Double.asAverageString(): String = "%.2f".format(Locale.FRANCE, this)
|
|
||||||
|
|
||||||
private fun List<List<Int>>.sumGradeAmounts(): List<Int> {
|
private fun List<List<Int>>.sumGradeAmounts(): List<Int> {
|
||||||
val result = mutableListOf(0, 0, 0, 0, 0, 0)
|
val result = mutableListOf(0, 0, 0, 0, 0, 0)
|
||||||
forEach {
|
forEach {
|
||||||
|
|
|
@ -5,7 +5,6 @@ import io.github.wulkanowy.data.db.entities.Homework
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.data.networkBoundResource
|
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.*
|
import io.github.wulkanowy.utils.*
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
|
@ -33,7 +32,6 @@ class HomeworkRepository @Inject constructor(
|
||||||
notify: Boolean = false,
|
notify: Boolean = false,
|
||||||
) = networkBoundResource(
|
) = networkBoundResource(
|
||||||
mutex = saveFetchResultMutex,
|
mutex = saveFetchResultMutex,
|
||||||
isResultEmpty = { it.isEmpty() },
|
|
||||||
shouldFetch = {
|
shouldFetch = {
|
||||||
val isExpired = refreshHelper.shouldBeRefreshed(
|
val isExpired = refreshHelper.shouldBeRefreshed(
|
||||||
key = getRefreshKey(cacheKey, semester, start, end)
|
key = getRefreshKey(cacheKey, semester, start, end)
|
||||||
|
|
|
@ -4,9 +4,9 @@ import io.github.wulkanowy.data.db.dao.LuckyNumberDao
|
||||||
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.mappers.mapToEntity
|
import io.github.wulkanowy.data.mappers.mapToEntity
|
||||||
import io.github.wulkanowy.data.networkBoundResource
|
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.init
|
import io.github.wulkanowy.utils.init
|
||||||
|
import io.github.wulkanowy.utils.networkBoundResource
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
|
@ -29,7 +29,6 @@ class LuckyNumberRepository @Inject constructor(
|
||||||
notify: Boolean = false,
|
notify: Boolean = false,
|
||||||
) = networkBoundResource(
|
) = networkBoundResource(
|
||||||
mutex = saveFetchResultMutex,
|
mutex = saveFetchResultMutex,
|
||||||
isResultEmpty = { it == null },
|
|
||||||
shouldFetch = { it == null || forceRefresh },
|
shouldFetch = { it == null || forceRefresh },
|
||||||
query = { luckyNumberDb.load(student.studentId, now()) },
|
query = { luckyNumberDb.load(student.studentId, now()) },
|
||||||
fetch = {
|
fetch = {
|
||||||
|
|
|
@ -3,32 +3,35 @@ package io.github.wulkanowy.data.repositories
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
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.*
|
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.*
|
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.Semester
|
||||||
|
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.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.pojos.MessageDraft
|
import io.github.wulkanowy.data.pojos.MessageDraft
|
||||||
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.sdk.pojo.SentMessage
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||||
import io.github.wulkanowy.utils.getRefreshKey
|
import io.github.wulkanowy.utils.getRefreshKey
|
||||||
import io.github.wulkanowy.utils.init
|
import io.github.wulkanowy.utils.init
|
||||||
|
import io.github.wulkanowy.utils.networkBoundResource
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
import io.github.wulkanowy.utils.uniqueSubtract
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.first
|
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import kotlinx.serialization.decodeFromString
|
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
|
||||||
|
import java.time.LocalDateTime.now
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@ -41,93 +44,98 @@ 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?,
|
semester: Semester,
|
||||||
folder: MessageFolder,
|
folder: MessageFolder,
|
||||||
forceRefresh: Boolean,
|
forceRefresh: Boolean,
|
||||||
notify: Boolean = false,
|
notify: Boolean = false,
|
||||||
): Flow<Resource<List<Message>>> = networkBoundResource(
|
): Flow<Resource<List<Message>>> = networkBoundResource(
|
||||||
mutex = saveFetchResultMutex,
|
mutex = saveFetchResultMutex,
|
||||||
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(student.id.toInt(), 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.valueOf(folder.name), now().minusMonths(3), now())
|
||||||
folder = Folder.valueOf(folder.name),
|
.mapToEntities(student)
|
||||||
mailboxKey = mailbox?.globalKey,
|
|
||||||
).mapToEntities(student, mailbox, mailboxDao.loadAll(student.email))
|
|
||||||
},
|
},
|
||||||
saveFetchResult = { old, new ->
|
saveFetchResult = { old, new ->
|
||||||
messagesDb.deleteAll(old uniqueSubtract new)
|
messagesDb.deleteAll(old uniqueSubtract new)
|
||||||
messagesDb.insertAll((new uniqueSubtract old).onEach {
|
messagesDb.insertAll((new uniqueSubtract old).onEach {
|
||||||
it.isNotified = !notify
|
it.isNotified = !notify
|
||||||
})
|
})
|
||||||
|
messagesDb.updateAll(getMessagesWithReadByChange(old, new, !notify))
|
||||||
|
|
||||||
refreshHelper.updateLastRefreshTimestamp(
|
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, student, folder))
|
||||||
getRefreshKey(messagesCacheKey, mailbox, folder)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private fun getMessagesWithReadByChange(
|
||||||
|
old: List<Message>,
|
||||||
|
new: List<Message>,
|
||||||
|
setNotified: Boolean
|
||||||
|
): List<Message> {
|
||||||
|
val oldMeta = old.map { Triple(it, it.readBy, it.unreadBy) }
|
||||||
|
val newMeta = new.map { Triple(it, it.readBy, it.unreadBy) }
|
||||||
|
|
||||||
|
val updatedItems = newMeta uniqueSubtract oldMeta
|
||||||
|
|
||||||
|
return updatedItems.map {
|
||||||
|
val oldItem = old.find { item -> item.messageId == it.first.messageId }
|
||||||
|
it.first.apply {
|
||||||
|
id = oldItem?.id ?: 0
|
||||||
|
isNotified = oldItem?.isNotified ?: setNotified
|
||||||
|
content = oldItem?.content.orEmpty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun getMessage(
|
fun getMessage(
|
||||||
student: Student,
|
student: Student,
|
||||||
message: Message,
|
message: Message,
|
||||||
markAsRead: Boolean = false,
|
markAsRead: Boolean = false,
|
||||||
): Flow<Resource<MessageWithAttachment?>> = networkBoundResource(
|
): Flow<Resource<MessageWithAttachment?>> = networkBoundResource(
|
||||||
isResultEmpty = { it?.message?.content.isNullOrBlank() },
|
|
||||||
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.isEmpty()}")
|
||||||
it.message.unread || it.message.content.isBlank()
|
it.message.unread || it.message.content.isEmpty()
|
||||||
},
|
|
||||||
query = {
|
|
||||||
messagesDb.loadMessageWithAttachment(message.messageGlobalKey)
|
|
||||||
},
|
},
|
||||||
|
query = { messagesDb.loadMessageWithAttachment(student.id.toInt(), message.messageId) },
|
||||||
fetch = {
|
fetch = {
|
||||||
sdk.init(student).getMessageDetails(it!!.message.messageGlobalKey, markAsRead)
|
sdk.init(student).getMessageDetails(
|
||||||
|
messageId = it!!.message.messageId,
|
||||||
|
folderId = message.folderId,
|
||||||
|
read = markAsRead,
|
||||||
|
id = message.realId
|
||||||
|
).let { details ->
|
||||||
|
details.content to details.attachments.mapToEntities()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
saveFetchResult = { old, new ->
|
saveFetchResult = { old, (downloadedMessage, attachments) ->
|
||||||
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 = old.message.id
|
||||||
id = message.id
|
unread = !markAsRead
|
||||||
unread = !markAsRead
|
content = content.ifBlank { downloadedMessage }
|
||||||
sender = new.sender
|
}))
|
||||||
recipients = new.recipients.singleOrNull() ?: "Wielu adresatów"
|
messageAttachmentDao.insertAttachments(attachments)
|
||||||
content = content.ifBlank { new.content }
|
|
||||||
})
|
|
||||||
)
|
|
||||||
messageAttachmentDao.insertAttachments(
|
|
||||||
items = new.attachments.mapToEntities(message.messageGlobalKey),
|
|
||||||
)
|
|
||||||
|
|
||||||
Timber.d("Message ${message.messageId} with blank content: ${old.message.content.isBlank()}, marked as read")
|
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(student: Student): Flow<List<Message>> {
|
||||||
return if (mailbox == null) {
|
return messagesDb.loadAll(student.id.toInt(), 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>) {
|
||||||
|
@ -139,88 +147,31 @@ class MessageRepository @Inject constructor(
|
||||||
subject: String,
|
subject: String,
|
||||||
content: String,
|
content: String,
|
||||||
recipients: List<Recipient>,
|
recipients: List<Recipient>,
|
||||||
mailboxId: String,
|
): SentMessage = sdk.init(student).sendMessage(
|
||||||
) {
|
subject = subject,
|
||||||
sdk.init(student).sendMessage(
|
content = content,
|
||||||
subject = subject,
|
recipients = recipients.mapFromEntities()
|
||||||
content = content,
|
|
||||||
recipients = recipients.mapFromEntities(),
|
|
||||||
mailboxId = mailboxId,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun deleteMessages(student: Student, mailbox: Mailbox?, messages: List<Message>) {
|
|
||||||
val firstMessage = messages.first()
|
|
||||||
sdk.init(student).deleteMessages(
|
|
||||||
messages = messages.map { it.messageGlobalKey },
|
|
||||||
removeForever = firstMessage.folderId == TRASHED.id,
|
|
||||||
)
|
|
||||||
|
|
||||||
if (firstMessage.folderId != TRASHED.id) {
|
|
||||||
val deletedMessages = messages.map {
|
|
||||||
it.copy(folderId = TRASHED.id)
|
|
||||||
.apply {
|
|
||||||
id = it.id
|
|
||||||
content = it.content
|
|
||||||
sender = it.sender
|
|
||||||
recipients = it.recipients
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
messagesDb.updateAll(deletedMessages)
|
|
||||||
} else messagesDb.deleteAll(messages)
|
|
||||||
|
|
||||||
getMessages(
|
|
||||||
student = student,
|
|
||||||
mailbox = mailbox,
|
|
||||||
folder = TRASHED,
|
|
||||||
forceRefresh = true,
|
|
||||||
).first()
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun deleteMessage(student: Student, mailbox: Mailbox?, message: 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? {
|
suspend fun deleteMessage(student: Student, message: Message) {
|
||||||
val mailbox = getMailboxByStudentUseCase(student)
|
val isDeleted = sdk.init(student).deleteMessages(
|
||||||
|
messages = listOf(message.messageId), message.folderId
|
||||||
|
)
|
||||||
|
|
||||||
return if (mailbox == null) {
|
if (message.folderId != MessageFolder.TRASHED.id && isDeleted) {
|
||||||
getMailboxes(student, forceRefresh = true)
|
val deletedMessage = message.copy(folderId = MessageFolder.TRASHED.id).apply {
|
||||||
.onResourceError { throw it }
|
id = message.id
|
||||||
.onResourceSuccess { Timber.i("Found ${it.size} new mailboxes") }
|
content = message.content
|
||||||
.waitForResult()
|
}
|
||||||
|
messagesDb.updateAll(listOf(deletedMessage))
|
||||||
getMailboxByStudentUseCase(student)
|
} else messagesDb.deleteAll(listOf(message))
|
||||||
} 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_send_draft))
|
||||||
?.let { json.decodeFromString(it) }
|
?.let { json.decodeFromString(it) }
|
||||||
set(value) = sharedPrefProvider.putString(
|
set(value) = sharedPrefProvider.putString(
|
||||||
context.getString(R.string.pref_key_message_draft),
|
context.getString(R.string.pref_key_message_send_draft),
|
||||||
value?.let { json.encodeToString(it) }
|
value?.let { json.encodeToString(it) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,9 @@ 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.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.data.mappers.mapToMobileDeviceToken
|
import io.github.wulkanowy.data.mappers.mapToMobileDeviceToken
|
||||||
import io.github.wulkanowy.data.networkBoundResource
|
|
||||||
import io.github.wulkanowy.data.pojos.MobileDeviceToken
|
import io.github.wulkanowy.data.pojos.MobileDeviceToken
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.getRefreshKey
|
|
||||||
import io.github.wulkanowy.utils.init
|
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
|
||||||
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
|
||||||
|
@ -34,17 +30,16 @@ class MobileDeviceRepository @Inject constructor(
|
||||||
forceRefresh: Boolean,
|
forceRefresh: Boolean,
|
||||||
) = networkBoundResource(
|
) = networkBoundResource(
|
||||||
mutex = saveFetchResultMutex,
|
mutex = saveFetchResultMutex,
|
||||||
isResultEmpty = { it.isEmpty() },
|
|
||||||
shouldFetch = {
|
shouldFetch = {
|
||||||
val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, student))
|
val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, student))
|
||||||
it.isEmpty() || forceRefresh || isExpired
|
it.isEmpty() || forceRefresh || isExpired
|
||||||
},
|
},
|
||||||
query = { mobileDb.loadAll(student.userLoginId) },
|
query = { mobileDb.loadAll(student.userLoginId.takeIf { it != 0 } ?: student.studentId) },
|
||||||
fetch = {
|
fetch = {
|
||||||
sdk.init(student)
|
sdk.init(student)
|
||||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.getRegisteredDevices()
|
.getRegisteredDevices()
|
||||||
.mapToEntities(student)
|
.mapToEntities(semester)
|
||||||
},
|
},
|
||||||
saveFetchResult = { old, new ->
|
saveFetchResult = { old, new ->
|
||||||
mobileDb.deleteAll(old uniqueSubtract new)
|
mobileDb.deleteAll(old uniqueSubtract new)
|
||||||
|
|
|
@ -5,7 +5,6 @@ import io.github.wulkanowy.data.db.entities.Note
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.data.networkBoundResource
|
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.*
|
import io.github.wulkanowy.utils.*
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
@ -31,7 +30,6 @@ class NoteRepository @Inject constructor(
|
||||||
notify: Boolean = false,
|
notify: Boolean = false,
|
||||||
) = networkBoundResource(
|
) = networkBoundResource(
|
||||||
mutex = saveFetchResultMutex,
|
mutex = saveFetchResultMutex,
|
||||||
isResultEmpty = { it.isEmpty() },
|
|
||||||
shouldFetch = {
|
shouldFetch = {
|
||||||
val isExpired = refreshHelper.shouldBeRefreshed(
|
val isExpired = refreshHelper.shouldBeRefreshed(
|
||||||
getRefreshKey(cacheKey, semester)
|
getRefreshKey(cacheKey, semester)
|
||||||
|
|
|
@ -10,16 +10,17 @@ 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 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.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,
|
||||||
|
@ -221,31 +222,19 @@ class PreferencesRepository @Inject constructor(
|
||||||
get() = selectedDashboardTilesPreference.asFlow()
|
get() = selectedDashboardTilesPreference.asFlow()
|
||||||
.map { set ->
|
.map { set ->
|
||||||
set.map { DashboardItem.Tile.valueOf(it) }
|
set.map { DashboardItem.Tile.valueOf(it) }
|
||||||
.plus(
|
.plus(DashboardItem.Tile.ACCOUNT)
|
||||||
listOfNotNull(
|
.plus(DashboardItem.Tile.ADMIN_MESSAGE)
|
||||||
DashboardItem.Tile.ACCOUNT,
|
|
||||||
DashboardItem.Tile.ADMIN_MESSAGE,
|
|
||||||
DashboardItem.Tile.ADS.takeIf { isAdsEnabled }
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.toSet()
|
.toSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
var selectedDashboardTiles: Set<DashboardItem.Tile>
|
var selectedDashboardTiles: Set<DashboardItem.Tile>
|
||||||
get() = selectedDashboardTilesPreference.get()
|
get() = selectedDashboardTilesPreference.get()
|
||||||
.map { DashboardItem.Tile.valueOf(it) }
|
.map { DashboardItem.Tile.valueOf(it) }
|
||||||
.plus(
|
.plus(DashboardItem.Tile.ACCOUNT)
|
||||||
listOfNotNull(
|
.plus(DashboardItem.Tile.ADMIN_MESSAGE)
|
||||||
DashboardItem.Tile.ACCOUNT,
|
|
||||||
DashboardItem.Tile.ADMIN_MESSAGE,
|
|
||||||
DashboardItem.Tile.ADS.takeIf { isAdsEnabled }
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.toSet()
|
.toSet()
|
||||||
set(value) {
|
set(value) {
|
||||||
val filteredValue = value.filterNot {
|
val filteredValue = value.filterNot { it == DashboardItem.Tile.ACCOUNT }
|
||||||
it == DashboardItem.Tile.ACCOUNT || it == DashboardItem.Tile.ADMIN_MESSAGE
|
|
||||||
}
|
|
||||||
.map { it.name }
|
.map { it.name }
|
||||||
.toSet()
|
.toSet()
|
||||||
|
|
||||||
|
@ -282,48 +271,7 @@ class PreferencesRepository @Inject constructor(
|
||||||
|
|
||||||
var isAppReviewDone: Boolean
|
var isAppReviewDone: Boolean
|
||||||
get() = sharedPref.getBoolean(PREF_KEY_IN_APP_REVIEW_DONE, false)
|
get() = sharedPref.getBoolean(PREF_KEY_IN_APP_REVIEW_DONE, false)
|
||||||
set(value) = sharedPref.edit { putBoolean(PREF_KEY_IN_APP_REVIEW_DONE, value) }
|
set(value) = sharedPref.edit().putBoolean(PREF_KEY_IN_APP_REVIEW_DONE, value).apply()
|
||||||
|
|
||||||
var isAppSupportShown: Boolean
|
|
||||||
get() = sharedPref.getBoolean(PREF_KEY_APP_SUPPORT_SHOWN, false)
|
|
||||||
set(value) = sharedPref.edit { putBoolean(PREF_KEY_APP_SUPPORT_SHOWN, value) }
|
|
||||||
|
|
||||||
var isAgreeToProcessData: Boolean
|
|
||||||
get() = getBoolean(
|
|
||||||
R.string.pref_key_ads_consent_data_processing,
|
|
||||||
R.bool.pref_default_ads_consent_data_processing
|
|
||||||
)
|
|
||||||
set(value) = sharedPref.edit {
|
|
||||||
putBoolean(context.getString(R.string.pref_key_ads_consent_data_processing), value)
|
|
||||||
}
|
|
||||||
|
|
||||||
var isPersonalizedAdsEnabled: Boolean
|
|
||||||
get() = sharedPref.getBoolean(PREF_KEY_PERSONALIZED_ADS_ENABLED, false)
|
|
||||||
set(value) = sharedPref.edit { putBoolean(PREF_KEY_PERSONALIZED_ADS_ENABLED, value) }
|
|
||||||
|
|
||||||
val isAdsEnabledFlow = flowSharedPref.getBoolean(
|
|
||||||
context.getString(R.string.pref_key_ads_enabled),
|
|
||||||
context.resources.getBoolean(R.bool.pref_default_ads_enabled)
|
|
||||||
).asFlow()
|
|
||||||
|
|
||||||
var isAdsEnabled: Boolean
|
|
||||||
get() = getBoolean(
|
|
||||||
R.string.pref_key_ads_enabled,
|
|
||||||
R.bool.pref_default_ads_enabled
|
|
||||||
)
|
|
||||||
set(value) = sharedPref.edit {
|
|
||||||
putBoolean(context.getString(R.string.pref_key_ads_enabled), 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)
|
||||||
|
|
||||||
|
@ -340,14 +288,19 @@ 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_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_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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
package io.github.wulkanowy.data.repositories
|
package io.github.wulkanowy.data.repositories
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.dao.RecipientDao
|
import io.github.wulkanowy.data.db.dao.RecipientDao
|
||||||
import io.github.wulkanowy.data.db.entities.*
|
import io.github.wulkanowy.data.db.entities.Message
|
||||||
|
import io.github.wulkanowy.data.db.entities.Recipient
|
||||||
|
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||||
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||||
|
@ -20,10 +23,9 @@ class RecipientRepository @Inject constructor(
|
||||||
|
|
||||||
private val cacheKey = "recipient"
|
private val cacheKey = "recipient"
|
||||||
|
|
||||||
suspend fun refreshRecipients(student: Student, mailbox: Mailbox, type: MailboxType) {
|
suspend fun refreshRecipients(student: Student, unit: ReportingUnit, role: Int) {
|
||||||
val new = sdk.init(student).getRecipients(mailbox.globalKey)
|
val new = sdk.init(student).getRecipients(unit.unitId, role).mapToEntities(unit.studentId)
|
||||||
.mapToEntities(mailbox.globalKey)
|
val old = recipientDb.loadAll(unit.studentId, unit.unitId, role)
|
||||||
val old = recipientDb.loadAll(type, mailbox.globalKey)
|
|
||||||
|
|
||||||
recipientDb.deleteAll(old uniqueSubtract new)
|
recipientDb.deleteAll(old uniqueSubtract new)
|
||||||
recipientDb.insertAll(new uniqueSubtract old)
|
recipientDb.insertAll(new uniqueSubtract old)
|
||||||
|
@ -31,33 +33,18 @@ class RecipientRepository @Inject constructor(
|
||||||
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, student))
|
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, student))
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getRecipients(
|
suspend fun getRecipients(student: Student, unit: ReportingUnit, role: Int): List<Recipient> {
|
||||||
student: Student,
|
val cached = recipientDb.loadAll(unit.studentId, unit.unitId, role)
|
||||||
mailbox: Mailbox?,
|
|
||||||
type: MailboxType,
|
|
||||||
): List<Recipient> {
|
|
||||||
mailbox ?: return emptyList()
|
|
||||||
|
|
||||||
val cached = recipientDb.loadAll(type, mailbox.globalKey)
|
|
||||||
|
|
||||||
val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, student))
|
val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, student))
|
||||||
return if (cached.isEmpty() || isExpired) {
|
return if (cached.isEmpty() || isExpired) {
|
||||||
refreshRecipients(student, mailbox, type)
|
refreshRecipients(student, unit, role)
|
||||||
recipientDb.loadAll(type, mailbox.globalKey)
|
recipientDb.loadAll(unit.studentId, unit.unitId, role)
|
||||||
} else cached
|
} else cached
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getMessageSender(
|
suspend fun getMessageRecipients(student: Student, message: Message): List<Recipient> {
|
||||||
student: Student,
|
return sdk.init(student).getMessageRecipients(message.messageId, message.senderId)
|
||||||
mailbox: Mailbox?,
|
.mapToEntities(student.studentId)
|
||||||
message: Message,
|
|
||||||
): List<Recipient> {
|
|
||||||
mailbox ?: return emptyList()
|
|
||||||
|
|
||||||
return sdk.init(student)
|
|
||||||
.getMessageReplayDetails(message.messageGlobalKey)
|
|
||||||
.sender
|
|
||||||
.let(::listOf)
|
|
||||||
.mapToEntities(mailbox.globalKey)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
package io.github.wulkanowy.data.repositories
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.db.dao.ReportingUnitDao
|
||||||
|
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||||
|
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.init
|
||||||
|
import io.github.wulkanowy.utils.uniqueSubtract
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class ReportingUnitRepository @Inject constructor(
|
||||||
|
private val reportingUnitDb: ReportingUnitDao,
|
||||||
|
private val sdk: Sdk
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun refreshReportingUnits(student: Student) {
|
||||||
|
val new = sdk.init(student).getReportingUnits().mapToEntities(student)
|
||||||
|
val old = reportingUnitDb.load(student.id.toInt())
|
||||||
|
|
||||||
|
reportingUnitDb.deleteAll(old.uniqueSubtract(new))
|
||||||
|
reportingUnitDb.insertAll(new.uniqueSubtract(old))
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getReportingUnits(student: Student): List<ReportingUnit> {
|
||||||
|
return reportingUnitDb.load(student.id.toInt()).ifEmpty {
|
||||||
|
refreshReportingUnits(student)
|
||||||
|
|
||||||
|
reportingUnitDb.load(student.id.toInt())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getReportingUnit(student: Student, unitId: Int): ReportingUnit? {
|
||||||
|
return reportingUnitDb.loadOne(student.id.toInt(), unitId) ?: run {
|
||||||
|
refreshReportingUnits(student)
|
||||||
|
|
||||||
|
return reportingUnitDb.loadOne(student.id.toInt(), unitId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,11 +4,11 @@ import io.github.wulkanowy.data.db.dao.SchoolAnnouncementDao
|
||||||
import io.github.wulkanowy.data.db.entities.SchoolAnnouncement
|
import io.github.wulkanowy.data.db.entities.SchoolAnnouncement
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.data.networkBoundResource
|
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||||
import io.github.wulkanowy.utils.getRefreshKey
|
import io.github.wulkanowy.utils.getRefreshKey
|
||||||
import io.github.wulkanowy.utils.init
|
import io.github.wulkanowy.utils.init
|
||||||
|
import io.github.wulkanowy.utils.networkBoundResource
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
import io.github.wulkanowy.utils.uniqueSubtract
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
|
@ -28,17 +28,15 @@ class SchoolAnnouncementRepository @Inject constructor(
|
||||||
|
|
||||||
fun getSchoolAnnouncements(
|
fun getSchoolAnnouncements(
|
||||||
student: Student,
|
student: Student,
|
||||||
forceRefresh: Boolean,
|
forceRefresh: Boolean, notify: Boolean = false
|
||||||
notify: Boolean = false
|
|
||||||
) = networkBoundResource(
|
) = networkBoundResource(
|
||||||
mutex = saveFetchResultMutex,
|
mutex = saveFetchResultMutex,
|
||||||
isResultEmpty = { it.isEmpty() },
|
|
||||||
shouldFetch = {
|
shouldFetch = {
|
||||||
val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, student))
|
val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, student))
|
||||||
it.isEmpty() || forceRefresh || isExpired
|
it.isEmpty() || forceRefresh || isExpired
|
||||||
},
|
},
|
||||||
query = {
|
query = {
|
||||||
schoolAnnouncementDb.loadAll(student.userLoginId)
|
schoolAnnouncementDb.loadAll(student.studentId)
|
||||||
},
|
},
|
||||||
fetch = {
|
fetch = {
|
||||||
sdk.init(student)
|
sdk.init(student)
|
||||||
|
@ -57,7 +55,7 @@ class SchoolAnnouncementRepository @Inject constructor(
|
||||||
)
|
)
|
||||||
|
|
||||||
fun getSchoolAnnouncementFromDatabase(student: Student): Flow<List<SchoolAnnouncement>> {
|
fun getSchoolAnnouncementFromDatabase(student: Student): Flow<List<SchoolAnnouncement>> {
|
||||||
return schoolAnnouncementDb.loadAll(student.userLoginId)
|
return schoolAnnouncementDb.loadAll(student.studentId)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updateSchoolAnnouncement(schoolAnnouncement: List<SchoolAnnouncement>) =
|
suspend fun updateSchoolAnnouncement(schoolAnnouncement: List<SchoolAnnouncement>) =
|
||||||
|
|
|
@ -4,11 +4,11 @@ import io.github.wulkanowy.data.db.dao.SchoolDao
|
||||||
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.mappers.mapToEntity
|
import io.github.wulkanowy.data.mappers.mapToEntity
|
||||||
import io.github.wulkanowy.data.networkBoundResource
|
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||||
import io.github.wulkanowy.utils.getRefreshKey
|
import io.github.wulkanowy.utils.getRefreshKey
|
||||||
import io.github.wulkanowy.utils.init
|
import io.github.wulkanowy.utils.init
|
||||||
|
import io.github.wulkanowy.utils.networkBoundResource
|
||||||
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
|
||||||
|
@ -30,7 +30,6 @@ class SchoolRepository @Inject constructor(
|
||||||
forceRefresh: Boolean,
|
forceRefresh: Boolean,
|
||||||
) = networkBoundResource(
|
) = networkBoundResource(
|
||||||
mutex = saveFetchResultMutex,
|
mutex = saveFetchResultMutex,
|
||||||
isResultEmpty = { it == null },
|
|
||||||
shouldFetch = {
|
shouldFetch = {
|
||||||
val isExpired = refreshHelper.shouldBeRefreshed(
|
val isExpired = refreshHelper.shouldBeRefreshed(
|
||||||
key = getRefreshKey(cacheKey, student)
|
key = getRefreshKey(cacheKey, student)
|
||||||
|
|
|
@ -4,9 +4,9 @@ import io.github.wulkanowy.data.db.dao.StudentInfoDao
|
||||||
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.mappers.mapToEntity
|
import io.github.wulkanowy.data.mappers.mapToEntity
|
||||||
import io.github.wulkanowy.data.networkBoundResource
|
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.init
|
import io.github.wulkanowy.utils.init
|
||||||
|
import io.github.wulkanowy.utils.networkBoundResource
|
||||||
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
|
||||||
|
@ -25,7 +25,6 @@ class StudentInfoRepository @Inject constructor(
|
||||||
forceRefresh: Boolean,
|
forceRefresh: Boolean,
|
||||||
) = networkBoundResource(
|
) = networkBoundResource(
|
||||||
mutex = saveFetchResultMutex,
|
mutex = saveFetchResultMutex,
|
||||||
isResultEmpty = { it == null },
|
|
||||||
shouldFetch = { it == null || forceRefresh },
|
shouldFetch = { it == null || forceRefresh },
|
||||||
query = { studentInfoDao.loadStudentInfo(student.studentId) },
|
query = { studentInfoDao.loadStudentInfo(student.studentId) },
|
||||||
fetch = {
|
fetch = {
|
||||||
|
|
|
@ -11,8 +11,6 @@ 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.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.data.mappers.mapToPojo
|
|
||||||
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.AppInfo
|
||||||
import io.github.wulkanowy.utils.DispatchersProvider
|
import io.github.wulkanowy.utils.DispatchersProvider
|
||||||
|
@ -54,14 +52,6 @@ class StudentRepository @Inject constructor(
|
||||||
sdk.getStudentsFromScrapper(email, password, scrapperBaseUrl, symbol)
|
sdk.getStudentsFromScrapper(email, password, scrapperBaseUrl, symbol)
|
||||||
.mapToEntities(password, appInfo.defaultColorsForAvatar)
|
.mapToEntities(password, appInfo.defaultColorsForAvatar)
|
||||||
|
|
||||||
suspend fun getUserSubjectsFromScrapper(
|
|
||||||
email: String,
|
|
||||||
password: String,
|
|
||||||
scrapperBaseUrl: String,
|
|
||||||
symbol: String
|
|
||||||
): RegisterUser = sdk.getUserSubjectsFromScrapper(email, password, scrapperBaseUrl, symbol)
|
|
||||||
.mapToPojo(password)
|
|
||||||
|
|
||||||
suspend fun getStudentsHybrid(
|
suspend fun getStudentsHybrid(
|
||||||
email: String,
|
email: String,
|
||||||
password: String,
|
password: String,
|
||||||
|
@ -83,15 +73,6 @@ class StudentRepository @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getSavedStudentById(id: Long, decryptPass: Boolean = true) =
|
|
||||||
studentDb.loadStudentWithSemestersById(id)?.apply {
|
|
||||||
if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) {
|
|
||||||
student.password = withContext(dispatchers.io) {
|
|
||||||
decrypt(student.password)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,8 @@ import io.github.wulkanowy.data.db.dao.SubjectDao
|
||||||
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.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.data.networkBoundResource
|
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.getRefreshKey
|
|
||||||
import io.github.wulkanowy.utils.init
|
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
|
||||||
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
|
||||||
|
@ -31,7 +27,6 @@ class SubjectRepository @Inject constructor(
|
||||||
forceRefresh: Boolean = false,
|
forceRefresh: Boolean = false,
|
||||||
) = networkBoundResource(
|
) = networkBoundResource(
|
||||||
mutex = saveFetchResultMutex,
|
mutex = saveFetchResultMutex,
|
||||||
isResultEmpty = { it.isEmpty() },
|
|
||||||
shouldFetch = {
|
shouldFetch = {
|
||||||
val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, semester))
|
val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, semester))
|
||||||
it.isEmpty() || forceRefresh || isExpired
|
it.isEmpty() || forceRefresh || isExpired
|
||||||
|
|
|
@ -4,12 +4,8 @@ import io.github.wulkanowy.data.db.dao.TeacherDao
|
||||||
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.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.data.networkBoundResource
|
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.getRefreshKey
|
|
||||||
import io.github.wulkanowy.utils.init
|
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
|
||||||
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
|
||||||
|
@ -31,7 +27,6 @@ class TeacherRepository @Inject constructor(
|
||||||
forceRefresh: Boolean,
|
forceRefresh: Boolean,
|
||||||
) = networkBoundResource(
|
) = networkBoundResource(
|
||||||
mutex = saveFetchResultMutex,
|
mutex = saveFetchResultMutex,
|
||||||
isResultEmpty = { it.isEmpty() },
|
|
||||||
shouldFetch = {
|
shouldFetch = {
|
||||||
val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, semester))
|
val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, semester))
|
||||||
it.isEmpty() || forceRefresh || isExpired
|
it.isEmpty() || forceRefresh || isExpired
|
||||||
|
|
|
@ -5,7 +5,6 @@ import io.github.wulkanowy.data.db.dao.TimetableDao
|
||||||
import io.github.wulkanowy.data.db.dao.TimetableHeaderDao
|
import io.github.wulkanowy.data.db.dao.TimetableHeaderDao
|
||||||
import io.github.wulkanowy.data.db.entities.*
|
import io.github.wulkanowy.data.db.entities.*
|
||||||
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.pojos.TimetableFull
|
import io.github.wulkanowy.data.pojos.TimetableFull
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper
|
import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper
|
||||||
|
@ -31,10 +30,6 @@ class TimetableRepository @Inject constructor(
|
||||||
|
|
||||||
private val cacheKey = "timetable"
|
private val cacheKey = "timetable"
|
||||||
|
|
||||||
enum class TimetableType {
|
|
||||||
NORMAL, ADDITIONAL
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getTimetable(
|
fun getTimetable(
|
||||||
student: Student,
|
student: Student,
|
||||||
semester: Semester,
|
semester: Semester,
|
||||||
|
@ -42,16 +37,9 @@ class TimetableRepository @Inject constructor(
|
||||||
end: LocalDate,
|
end: LocalDate,
|
||||||
forceRefresh: Boolean,
|
forceRefresh: Boolean,
|
||||||
refreshAdditional: Boolean = false,
|
refreshAdditional: Boolean = false,
|
||||||
notify: Boolean = false,
|
notify: Boolean = false
|
||||||
timetableType: TimetableType = TimetableType.NORMAL
|
|
||||||
) = networkBoundResource(
|
) = networkBoundResource(
|
||||||
mutex = saveFetchResultMutex,
|
mutex = saveFetchResultMutex,
|
||||||
isResultEmpty = {
|
|
||||||
when (timetableType) {
|
|
||||||
TimetableType.NORMAL -> it.lessons.isEmpty()
|
|
||||||
TimetableType.ADDITIONAL -> it.additional.isEmpty()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
shouldFetch = { (timetable, additional, headers) ->
|
shouldFetch = { (timetable, additional, headers) ->
|
||||||
val refreshKey = getRefreshKey(cacheKey, semester, start, end)
|
val refreshKey = getRefreshKey(cacheKey, semester, start, end)
|
||||||
val isExpired = refreshHelper.shouldBeRefreshed(refreshKey)
|
val isExpired = refreshHelper.shouldBeRefreshed(refreshKey)
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
package io.github.wulkanowy.data.serializers
|
|
||||||
|
|
||||||
import kotlinx.serialization.ExperimentalSerializationApi
|
|
||||||
import kotlinx.serialization.KSerializer
|
|
||||||
import kotlinx.serialization.descriptors.PrimitiveKind
|
|
||||||
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
|
|
||||||
import kotlinx.serialization.descriptors.nullable
|
|
||||||
import kotlinx.serialization.encoding.Decoder
|
|
||||||
import kotlinx.serialization.encoding.Encoder
|
|
||||||
import java.time.LocalDate
|
|
||||||
|
|
||||||
@OptIn(ExperimentalSerializationApi::class)
|
|
||||||
object LocalDateSerializer : KSerializer<LocalDate?> {
|
|
||||||
|
|
||||||
override val descriptor = PrimitiveSerialDescriptor("LocalDate", PrimitiveKind.LONG).nullable
|
|
||||||
|
|
||||||
override fun serialize(encoder: Encoder, value: LocalDate?) {
|
|
||||||
if (value == null) {
|
|
||||||
encoder.encodeNull()
|
|
||||||
} else {
|
|
||||||
encoder.encodeNotNullMark()
|
|
||||||
encoder.encodeLong(value.toEpochDay())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun deserialize(decoder: Decoder): LocalDate? =
|
|
||||||
if (decoder.decodeNotNullMark()) {
|
|
||||||
LocalDate.ofEpochDay(decoder.decodeLong())
|
|
||||||
} else {
|
|
||||||
decoder.decodeNull()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -10,18 +10,19 @@ import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.onResourceError
|
import io.github.wulkanowy.data.Status
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||||
import io.github.wulkanowy.data.resourceFlow
|
|
||||||
import io.github.wulkanowy.services.sync.channels.UpcomingLessonsChannel.Companion.CHANNEL_ID
|
import io.github.wulkanowy.services.sync.channels.UpcomingLessonsChannel.Companion.CHANNEL_ID
|
||||||
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.ui.modules.splash.SplashActivity
|
||||||
import io.github.wulkanowy.utils.PendingIntentCompat
|
import io.github.wulkanowy.utils.PendingIntentCompat
|
||||||
|
import io.github.wulkanowy.utils.flowWithResource
|
||||||
import io.github.wulkanowy.utils.getCompatColor
|
import io.github.wulkanowy.utils.getCompatColor
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -58,7 +59,7 @@ class TimetableNotificationReceiver : BroadcastReceiver() {
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
Timber.d("Receiving intent... ${intent.toUri(0)}")
|
Timber.d("Receiving intent... ${intent.toUri(0)}")
|
||||||
|
|
||||||
resourceFlow {
|
flowWithResource {
|
||||||
val showStudentName = !studentRepository.isOneUniqueStudent()
|
val showStudentName = !studentRepository.isOneUniqueStudent()
|
||||||
val student = studentRepository.getCurrentStudent(false)
|
val student = studentRepository.getCurrentStudent(false)
|
||||||
val studentId = intent.getIntExtra(STUDENT_ID, 0)
|
val studentId = intent.getIntExtra(STUDENT_ID, 0)
|
||||||
|
@ -68,9 +69,9 @@ class TimetableNotificationReceiver : BroadcastReceiver() {
|
||||||
} else {
|
} else {
|
||||||
Timber.d("Notification studentId($studentId) differs from current(${student.studentId})")
|
Timber.d("Notification studentId($studentId) differs from current(${student.studentId})")
|
||||||
}
|
}
|
||||||
}
|
}.onEach {
|
||||||
.onResourceError { Timber.e(it) }
|
if (it.status == Status.ERROR) Timber.e(it.error!!)
|
||||||
.launchIn(GlobalScope)
|
}.launchIn(GlobalScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun prepareNotification(context: Context, intent: Intent, showStudentName: Boolean) {
|
private fun prepareNotification(context: Context, intent: Intent, showStudentName: Boolean) {
|
||||||
|
|
|
@ -15,41 +15,76 @@ import javax.inject.Singleton
|
||||||
@Singleton
|
@Singleton
|
||||||
class ShortcutsHelper @Inject constructor(@ApplicationContext private val context: Context) {
|
class ShortcutsHelper @Inject constructor(@ApplicationContext private val context: Context) {
|
||||||
|
|
||||||
fun initializeShortcuts() {
|
private val destinations = mapOf(
|
||||||
|
"grade" to Destination.Grade,
|
||||||
|
"attendance" to Destination.Attendance,
|
||||||
|
"exam" to Destination.Exam,
|
||||||
|
"timetable" to Destination.Timetable()
|
||||||
|
)
|
||||||
|
|
||||||
|
init {
|
||||||
|
initializeShortcuts()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDestination(intent: Intent) =
|
||||||
|
destinations[intent.getStringExtra(EXTRA_SHORTCUT_DESTINATION_ID)]
|
||||||
|
|
||||||
|
private fun initializeShortcuts() {
|
||||||
val shortcutsInfo = listOf(
|
val shortcutsInfo = listOf(
|
||||||
ShortcutInfoCompat.Builder(context, "grade_shortcut")
|
ShortcutInfoCompat.Builder(context, "grade_shortcut")
|
||||||
.setShortLabel(context.getString(R.string.grade_title))
|
.setShortLabel(context.getString(R.string.grade_title))
|
||||||
.setLongLabel(context.getString(R.string.grade_title))
|
.setLongLabel(context.getString(R.string.grade_title))
|
||||||
.setIcon(IconCompat.createWithResource(context, R.drawable.ic_shortcut_grade))
|
.setIcon(IconCompat.createWithResource(context, R.drawable.ic_shortcut_grade))
|
||||||
.setIntent(SplashActivity.getStartIntent(context, Destination.Grade)
|
.setIntent(SplashActivity.getStartIntent(context)
|
||||||
.apply { action = Intent.ACTION_VIEW })
|
.apply {
|
||||||
|
action = Intent.ACTION_VIEW
|
||||||
|
putExtra(EXTRA_SHORTCUT_DESTINATION_ID, "grade")
|
||||||
|
}
|
||||||
|
)
|
||||||
.build(),
|
.build(),
|
||||||
|
|
||||||
ShortcutInfoCompat.Builder(context, "attendance_shortcut")
|
ShortcutInfoCompat.Builder(context, "attendance_shortcut")
|
||||||
.setShortLabel(context.getString(R.string.attendance_title))
|
.setShortLabel(context.getString(R.string.attendance_title))
|
||||||
.setLongLabel(context.getString(R.string.attendance_title))
|
.setLongLabel(context.getString(R.string.attendance_title))
|
||||||
.setIcon(IconCompat.createWithResource(context, R.drawable.ic_shortcut_attendance))
|
.setIcon(IconCompat.createWithResource(context, R.drawable.ic_shortcut_attendance))
|
||||||
.setIntent(SplashActivity.getStartIntent(context, Destination.Attendance)
|
.setIntent(SplashActivity.getStartIntent(context)
|
||||||
.apply { action = Intent.ACTION_VIEW })
|
.apply {
|
||||||
|
action = Intent.ACTION_VIEW
|
||||||
|
putExtra(EXTRA_SHORTCUT_DESTINATION_ID, "attendance")
|
||||||
|
}
|
||||||
|
)
|
||||||
.build(),
|
.build(),
|
||||||
|
|
||||||
ShortcutInfoCompat.Builder(context, "exam_shortcut")
|
ShortcutInfoCompat.Builder(context, "exam_shortcut")
|
||||||
.setShortLabel(context.getString(R.string.exam_title))
|
.setShortLabel(context.getString(R.string.exam_title))
|
||||||
.setLongLabel(context.getString(R.string.exam_title))
|
.setLongLabel(context.getString(R.string.exam_title))
|
||||||
.setIcon(IconCompat.createWithResource(context, R.drawable.ic_shortcut_exam))
|
.setIcon(IconCompat.createWithResource(context, R.drawable.ic_shortcut_exam))
|
||||||
.setIntent(SplashActivity.getStartIntent(context, Destination.Exam)
|
.setIntent(SplashActivity.getStartIntent(context)
|
||||||
.apply { action = Intent.ACTION_VIEW })
|
.apply {
|
||||||
|
action = Intent.ACTION_VIEW
|
||||||
|
putExtra(EXTRA_SHORTCUT_DESTINATION_ID, "exam")
|
||||||
|
}
|
||||||
|
)
|
||||||
.build(),
|
.build(),
|
||||||
|
|
||||||
ShortcutInfoCompat.Builder(context, "timetable_shortcut")
|
ShortcutInfoCompat.Builder(context, "timetable_shortcut")
|
||||||
.setShortLabel(context.getString(R.string.timetable_title))
|
.setShortLabel(context.getString(R.string.timetable_title))
|
||||||
.setLongLabel(context.getString(R.string.timetable_title))
|
.setLongLabel(context.getString(R.string.timetable_title))
|
||||||
.setIcon(IconCompat.createWithResource(context, R.drawable.ic_shortcut_timetable))
|
.setIcon(IconCompat.createWithResource(context, R.drawable.ic_shortcut_timetable))
|
||||||
.setIntent(SplashActivity.getStartIntent(context, Destination.Timetable())
|
.setIntent(SplashActivity.getStartIntent(context)
|
||||||
.apply { action = Intent.ACTION_VIEW })
|
.apply {
|
||||||
|
action = Intent.ACTION_VIEW
|
||||||
|
putExtra(EXTRA_SHORTCUT_DESTINATION_ID, "timetable")
|
||||||
|
}
|
||||||
|
)
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
|
|
||||||
shortcutsInfo.forEach { ShortcutManagerCompat.pushDynamicShortcut(context, it) }
|
shortcutsInfo.forEach { ShortcutManagerCompat.pushDynamicShortcut(context, it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
|
||||||
|
private const val EXTRA_SHORTCUT_DESTINATION_ID = "shortcut_destination_id"
|
||||||
|
}
|
||||||
}
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue