Compare commits
No commits in common. "1.7.2" and "1.2.0" have entirely different histories.
524 changed files with 8453 additions and 44356 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
|
|
37
.github/workflows/deploy-store.yml
vendored
37
.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
|
||||||
|
@ -29,31 +28,27 @@ jobs:
|
||||||
SERVICES_ENCRYPT_KEY: ${{ secrets.SERVICES_ENCRYPT_KEY }}
|
SERVICES_ENCRYPT_KEY: ${{ secrets.SERVICES_ENCRYPT_KEY }}
|
||||||
run: |
|
run: |
|
||||||
gpg --yes --batch --passphrase=$SERVICES_ENCRYPT_KEY ./app/src/release/google-services.json.gpg
|
gpg --yes --batch --passphrase=$SERVICES_ENCRYPT_KEY ./app/src/release/google-services.json.gpg
|
||||||
|
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/key.p12.gpg
|
||||||
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/upload-key.jks.gpg
|
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/upload-key.jks.gpg
|
||||||
- name: Upload apk to google play
|
- name: Upload apk to google play
|
||||||
env:
|
env:
|
||||||
PLAY_STORE_PASSWORD: ${{ secrets.PLAY_STORE_PASSWORD }}
|
|
||||||
PLAY_KEY_ALIAS: ${{ secrets.PLAY_KEY_ALIAS }}
|
PLAY_KEY_ALIAS: ${{ secrets.PLAY_KEY_ALIAS }}
|
||||||
PLAY_KEY_PASSWORD: ${{ secrets.PLAY_KEY_PASSWORD }}
|
PLAY_KEY_PASSWORD: ${{ secrets.PLAY_KEY_PASSWORD }}
|
||||||
ANDROID_PUBLISHER_CREDENTIALS: ${{ secrets.ANDROID_PUBLISHER_CREDENTIALS }}
|
PLAY_SERVICE_ACCOUNT_EMAIL: ${{ secrets.PLAY_SERVICE_ACCOUNT_EMAIL }}
|
||||||
ADMOB_PROJECT_ID: ${{ secrets.ADMOB_PROJECT_ID }}
|
PLAY_STORE_PASSWORD: ${{ secrets.PLAY_STORE_PASSWORD }}
|
||||||
SINGLE_SUPPORT_AD_ID: ${{ secrets.SINGLE_SUPPORT_AD_ID }}
|
run: ./gradlew publishPlayRelease -PenableFirebase --stacktrace;
|
||||||
DASHBOARD_TILE_AD_ID: ${{ secrets.DASHBOARD_TILE_AD_ID }}
|
|
||||||
SET_BUILD_TIMESTAMP: ${{ secrets.SET_BUILD_TIMESTAMP }}
|
|
||||||
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
|
||||||
|
@ -65,6 +60,7 @@ jobs:
|
||||||
SERVICES_ENCRYPT_KEY: ${{ secrets.SERVICES_ENCRYPT_KEY }}
|
SERVICES_ENCRYPT_KEY: ${{ secrets.SERVICES_ENCRYPT_KEY }}
|
||||||
run: |
|
run: |
|
||||||
gpg --yes --batch --passphrase=$SERVICES_ENCRYPT_KEY ./app/src/release/agconnect-services.json.gpg
|
gpg --yes --batch --passphrase=$SERVICES_ENCRYPT_KEY ./app/src/release/agconnect-services.json.gpg
|
||||||
|
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/key.p12.gpg
|
||||||
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/upload-key.jks.gpg
|
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/upload-key.jks.gpg
|
||||||
- name: Prepare credentials
|
- name: Prepare credentials
|
||||||
env:
|
env:
|
||||||
|
@ -72,8 +68,7 @@ jobs:
|
||||||
run: echo $AGC_CREDENTIALS > ./app/src/release/agconnect-credentials.json
|
run: echo $AGC_CREDENTIALS > ./app/src/release/agconnect-credentials.json
|
||||||
- name: Build and publish HMS version
|
- name: Build and publish HMS version
|
||||||
env:
|
env:
|
||||||
PLAY_STORE_PASSWORD: ${{ secrets.PLAY_STORE_PASSWORD }}
|
|
||||||
PLAY_KEY_ALIAS: ${{ secrets.PLAY_KEY_ALIAS }}
|
PLAY_KEY_ALIAS: ${{ secrets.PLAY_KEY_ALIAS }}
|
||||||
PLAY_KEY_PASSWORD: ${{ secrets.PLAY_KEY_PASSWORD }}
|
PLAY_KEY_PASSWORD: ${{ secrets.PLAY_KEY_PASSWORD }}
|
||||||
SET_BUILD_TIMESTAMP: ${{ secrets.SET_BUILD_TIMESTAMP }}
|
PLAY_STORE_PASSWORD: ${{ secrets.PLAY_STORE_PASSWORD }}
|
||||||
run: ./gradlew bundleHmsRelease --stacktrace && ./gradlew publishHuaweiAppGalleryHmsRelease --stacktrace
|
run: ./gradlew assembleHmsRelease --stacktrace && ./gradlew publishHuaweiAppGalleryHmsRelease --stacktrace
|
||||||
|
|
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
|
||||||
|
|
66
.github/workflows/test.yml
vendored
66
.github/workflows/test.yml
vendored
|
@ -8,20 +8,18 @@ on:
|
||||||
branches: [ master, develop ]
|
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
|
||||||
|
@ -31,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
|
||||||
|
|
15
.idea/codeStyles/Project.xml
generated
15
.idea/codeStyles/Project.xml
generated
|
@ -2,6 +2,14 @@
|
||||||
<code_scheme name="Project" version="173">
|
<code_scheme name="Project" version="173">
|
||||||
<option name="LINE_SEPARATOR" value=" " />
|
<option name="LINE_SEPARATOR" value=" " />
|
||||||
<JetCodeStyleSettings>
|
<JetCodeStyleSettings>
|
||||||
|
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
||||||
|
<value>
|
||||||
|
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
|
||||||
|
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
|
||||||
|
<option name="WRAP_ELVIS_EXPRESSIONS" value="0" />
|
||||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||||
</JetCodeStyleSettings>
|
</JetCodeStyleSettings>
|
||||||
<codeStyleSettings language="XML">
|
<codeStyleSettings language="XML">
|
||||||
|
@ -118,6 +126,13 @@
|
||||||
</codeStyleSettings>
|
</codeStyleSettings>
|
||||||
<codeStyleSettings language="kotlin">
|
<codeStyleSettings language="kotlin">
|
||||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||||
|
<option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1" />
|
||||||
|
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
|
||||||
|
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="0" />
|
||||||
|
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
|
||||||
|
<indentOptions>
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||||
|
</indentOptions>
|
||||||
</codeStyleSettings>
|
</codeStyleSettings>
|
||||||
</code_scheme>
|
</code_scheme>
|
||||||
</component>
|
</component>
|
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 2022 Wulkanowy
|
Copyright 2019 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.
|
||||||
|
|
78
README.cs.md
78
README.cs.md
|
@ -1,78 +0,0 @@
|
||||||
[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
|
|
||||||
|
|
||||||
[](https://github.com/wulkanowy/wulkanowy/actions)
|
|
||||||
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
|
||||||
[](https://discord.gg/vccAQBr)
|
|
||||||
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
|
||||||
[](https://github.com/wulkanowy/wulkanowy/releases)
|
|
||||||
|
|
||||||
Neoficiální klient deníku VULCAN UONET+ pro žáka a rodiče
|
|
||||||
|
|
||||||
## Funkce
|
|
||||||
|
|
||||||
* přihlášení pomocí emailu a hesla
|
|
||||||
* funkce z webové stránky deníku:
|
|
||||||
* známky
|
|
||||||
* statistiky známek
|
|
||||||
* frekvence
|
|
||||||
* procento frekvence
|
|
||||||
* zkoušky
|
|
||||||
* plán lekce
|
|
||||||
* dokončené lekce
|
|
||||||
* zprávy
|
|
||||||
* domácí úkoly
|
|
||||||
* poznámky
|
|
||||||
* šťastné číslo
|
|
||||||
* další lekce
|
|
||||||
* školní setkání
|
|
||||||
* informace o žáku a škole
|
|
||||||
* výpočet průměru nezávisle na preferencích školy
|
|
||||||
* upozornění, např. o nových známkách
|
|
||||||
* podpora více účtů s možností přejmenování žáků
|
|
||||||
* tmavý a černý (AMOLED) motiv
|
|
||||||
* offline režim
|
|
||||||
* žádné reklamy
|
|
||||||
|
|
||||||
## Stáhnout
|
|
||||||
|
|
||||||
Aktuální verzi si můžete stáhnout z Google Play, F-Droid nebo Huawei AppGallery
|
|
||||||
|
|
||||||
[<img src="https://play.google.com/intl/cs-CZ/badges/images/generic/cs_badge_web_generic.png"
|
|
||||||
alt="Nyní na Google Play"
|
|
||||||
height="80">](https://play.google.com/store/apps/details?id=io.github.wulkanowy)
|
|
||||||
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
|
|
||||||
alt="Stáhnout s F-Droid"
|
|
||||||
height="80">](https://f-droid.org/packages/io.github.wulkanowy/)
|
|
||||||
[<img src="https://i.imgur.com/baTGiDP.png"
|
|
||||||
alt="Objevuj v AppGallery"
|
|
||||||
height="80">](https://appgallery.cloud.huawei.com/ag/n/app/C101440411?channelId=Badge&id=1b3f7fbb700849a9be0dba6b520b2282&s=EB1D3BF9ED9D1564D869B7B94B18016D3CABFCA5AEFB8E29F675FA04E0DC131D&detailType=0&v=)
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
* [Wulkanowy SDK](https://github.com/wulkanowy/sdk)
|
|
||||||
* [Kotlin Coroutines](https://kotlinlang.org/docs/reference/coroutines-overview.html)
|
|
||||||
* [Hilt](https://dagger.dev/hilt/)
|
|
||||||
* [Room](https://developer.android.com/topic/libraries/architecture/room)
|
|
||||||
* [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager)
|
|
||||||
|
|
||||||
## Spolupráce
|
|
||||||
|
|
||||||
Přispějte do projektu vytvořením PR nebo odesláním issue na GitHub.
|
|
||||||
|
|
||||||
Pro zájemce o překlad aplikace do různých jazyků poskytujeme Crowdin:
|
|
||||||
https://crowdin.com/project/wulkanowy2
|
|
||||||
|
|
||||||
## Licence
|
|
||||||
|
|
||||||
Tento projekt je licencován pod licencí Apache License 2.0 - podrobnosti v souboru [LICENSE](LICENSE)
|
|
74
README.de.md
74
README.de.md
|
@ -1,74 +0,0 @@
|
||||||
[Polska wersja README](README.md)
|
|
||||||
|
|
||||||
[English version of README](README.en.md)
|
|
||||||
|
|
||||||
# Wulkanowy
|
|
||||||
|
|
||||||
[](https://github.com/wulkanowy/wulkanowy/actions)
|
|
||||||
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
|
||||||
[](https://discord.gg/vccAQBr)
|
|
||||||
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
|
||||||
[](https://github.com/wulkanowy/wulkanowy/releases)
|
|
||||||
|
|
||||||
Inoffizieller Android VULCAN UONET+ Registrierungsclient für Schüler und ihre Eltern
|
|
||||||
|
|
||||||
## Merkmale
|
|
||||||
|
|
||||||
* Einloggen mit E-Mail und Passwort
|
|
||||||
* Funktionen von der Registerwebsite:
|
|
||||||
* Noten
|
|
||||||
* Notenstatistik
|
|
||||||
* Anwesenheit
|
|
||||||
* Prozentsatz der Anwesenheit
|
|
||||||
* Prüfungen
|
|
||||||
* Stundenplan
|
|
||||||
* Unterricht abgeschlossen
|
|
||||||
* Nachrichten
|
|
||||||
* Hausaufgaben
|
|
||||||
* Anmerkungen
|
|
||||||
* Glückszahl
|
|
||||||
* Zusätzliche Lektionen
|
|
||||||
* Schulkonferenzen
|
|
||||||
* Schüler- und Schulinformationen
|
|
||||||
* Berechnung des Durchschnitts unabhängig von den Präferenzen der Schule
|
|
||||||
* Benachrichtigungen, z. B. über eine neue Note
|
|
||||||
* Unterstützung für mehrere Konten mit der Möglichkeit, den Namen des Schülers zu ändern
|
|
||||||
* dunkles und schwarzes (AMOLED) Thema
|
|
||||||
* Offline-Modus
|
|
||||||
* keine Werbung
|
|
||||||
|
|
||||||
## Herunterladen
|
|
||||||
|
|
||||||
Die aktuelle Version können Sie von der Google Play, F-Droid oder Huawei AppGallery store herunterladen
|
|
||||||
|
|
||||||
[<img src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png"
|
|
||||||
alt="Get it on Google Play"
|
|
||||||
height="80">](https://play.google.com/store/apps/details?id=io.github.wulkanowy)
|
|
||||||
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
|
|
||||||
alt="Get it on F-Droid"
|
|
||||||
height="80">](https://f-droid.org/packages/io.github.wulkanowy/)
|
|
||||||
[<img src="appgallery_badge.png"
|
|
||||||
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=)
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
## Gebaut mit
|
|
||||||
|
|
||||||
|
|
||||||
* [Wulkanowy SDK](https://github.com/wulkanowy/sdk)
|
|
||||||
* [Kotlin Coroutines](https://kotlinlang.org/docs/reference/coroutines-overview.html)
|
|
||||||
* [Hilt](https://dagger.dev/hilt/)
|
|
||||||
* [Room](https://developer.android.com/topic/libraries/architecture/room)
|
|
||||||
* [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager)
|
|
||||||
|
|
||||||
## Beitragen
|
|
||||||
|
|
||||||
Bitte tragen Sie zum Projekt bei, indem Sie entweder eine PR erstellen oder ein Issue auf GitHub einreichen.
|
|
||||||
|
|
||||||
Für Personen, die daran interessiert sind, die Anwendung in verschiedene Sprachen zu übersetzen, bieten wir Crowdin
|
|
||||||
https://crowdin.com/project/wulkanowy2
|
|
||||||
|
|
||||||
## Lizenz
|
|
||||||
|
|
||||||
Dieses Projekt ist unter der Apache License 2.0 lizenziert - siehe die [LIZENZ](LICENSE) Datei für Details
|
|
|
@ -1,11 +1,5 @@
|
||||||
[Polska wersja README](README.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)
|
||||||
|
|
|
@ -1,11 +1,5 @@
|
||||||
[English version of README](README.en.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)
|
||||||
|
|
78
README.sk.md
78
README.sk.md
|
@ -1,78 +0,0 @@
|
||||||
[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
|
|
||||||
|
|
||||||
[](https://github.com/wulkanowy/wulkanowy/actions)
|
|
||||||
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
|
||||||
[](https://discord.gg/vccAQBr)
|
|
||||||
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
|
||||||
[](https://github.com/wulkanowy/wulkanowy/releases)
|
|
||||||
|
|
||||||
Neoficiálny klient denníka VULCAN UONET+ pre žiaka a rodičov
|
|
||||||
|
|
||||||
## Funkcie
|
|
||||||
|
|
||||||
* prihlásenie pomocou emailu a hesla
|
|
||||||
* funkcie z webovej stránky denníka:
|
|
||||||
* známky
|
|
||||||
* štatistiky známok
|
|
||||||
* frekvencia
|
|
||||||
* percento frekvencie
|
|
||||||
* skúšky
|
|
||||||
* plán lekcie
|
|
||||||
* dokončené lekcie
|
|
||||||
* správy
|
|
||||||
* domáce úlohy
|
|
||||||
* poznámky
|
|
||||||
* šťastné číslo
|
|
||||||
* ďalšie lekcie
|
|
||||||
* školské stretnutie
|
|
||||||
* informácie o žiakovi a škole
|
|
||||||
* výpočet priemeru nezávisle od preferencií školy
|
|
||||||
* upozornenia, napr. o nových známkach
|
|
||||||
* podpora viacerých účtov s možnosťou premenovania žiakov
|
|
||||||
* tmavý a čierny (AMOLED) motív
|
|
||||||
* offline režim
|
|
||||||
* žiadne reklamy
|
|
||||||
|
|
||||||
## Stiahnuť
|
|
||||||
|
|
||||||
Aktuálnu verziu si môžete stiahnuť z Google Play, F-Droid alebo Huawei AppGallery
|
|
||||||
|
|
||||||
[<img src="https://play.google.com/intl/sk/badges/images/generic/sk_badge_web_generic.png"
|
|
||||||
alt="Nyní na Google Play"
|
|
||||||
height="80">](https://play.google.com/store/apps/details?id=io.github.wulkanowy)
|
|
||||||
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
|
|
||||||
alt="Stiahnuť s F-Droid"
|
|
||||||
height="80">](https://f-droid.org/packages/io.github.wulkanowy/)
|
|
||||||
[<img src="https://i.imgur.com/sX8UyAw.png"
|
|
||||||
alt="Objavíte v AppGallery"
|
|
||||||
height="80">](https://appgallery.cloud.huawei.com/ag/n/app/C101440411?channelId=Badge&id=1b3f7fbb700849a9be0dba6b520b2282&s=EB1D3BF9ED9D1564D869B7B94B18016D3CABFCA5AEFB8E29F675FA04E0DC131D&detailType=0&v=)
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
* [Wulkanowy SDK](https://github.com/wulkanowy/sdk)
|
|
||||||
* [Kotlin Coroutines](https://kotlinlang.org/docs/reference/coroutines-overview.html)
|
|
||||||
* [Hilt](https://dagger.dev/hilt/)
|
|
||||||
* [Room](https://developer.android.com/topic/libraries/architecture/room)
|
|
||||||
* [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager)
|
|
||||||
|
|
||||||
## Spolupráca
|
|
||||||
|
|
||||||
Prispejte do projektu vytvorením PR alebo odoslaním issue na GitHub.
|
|
||||||
|
|
||||||
Pre záujemcov o preklad aplikácie do rôznych jazykov poskytujeme Crowdin:
|
|
||||||
https://crowdin.com/project/wulkanowy2
|
|
||||||
|
|
||||||
## Licencia
|
|
||||||
|
|
||||||
Tento projekt je licencovaný pod licenciou Apache License 2.0 - podrobnosti v súbore [LICENSE](LICENSE)
|
|
150
app/build.gradle
150
app/build.gradle
|
@ -1,6 +1,5 @@
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
apply plugin: 'kotlinx-serialization'
|
|
||||||
apply plugin: 'kotlin-parcelize'
|
apply plugin: 'kotlin-parcelize'
|
||||||
apply plugin: 'kotlin-kapt'
|
apply plugin: 'kotlin-kapt'
|
||||||
apply plugin: 'dagger.hilt.android.plugin'
|
apply plugin: 'dagger.hilt.android.plugin'
|
||||||
|
@ -15,41 +14,32 @@ apply from: 'sonarqube.gradle'
|
||||||
apply from: 'hooks.gradle'
|
apply from: 'hooks.gradle'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace 'io.github.wulkanowy'
|
compileSdkVersion 30
|
||||||
compileSdkVersion 32
|
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "io.github.wulkanowy"
|
applicationId "io.github.wulkanowy"
|
||||||
testApplicationId "io.github.tests.wulkanowy"
|
testApplicationId "io.github.tests.wulkanowy"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 32
|
targetSdkVersion 30
|
||||||
versionCode 111
|
versionCode 93
|
||||||
versionName "1.7.2"
|
versionName "1.2.0"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
vectorDrawables.useSupportLibrary = true
|
||||||
|
|
||||||
resValue "string", "app_name", "Wulkanowy"
|
resValue "string", "app_name", "Wulkanowy"
|
||||||
|
buildConfigField "long", "BUILD_TIMESTAMP", String.valueOf(System.currentTimeMillis())
|
||||||
|
|
||||||
manifestPlaceholders = [
|
manifestPlaceholders = [
|
||||||
firebase_enabled: project.hasProperty("enableFirebase"),
|
firebase_enabled: project.hasProperty("enableFirebase")
|
||||||
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", "DASHBOARD_TILE_AD_ID", "null"
|
|
||||||
|
|
||||||
if (System.env.SET_BUILD_TIMESTAMP) {
|
|
||||||
buildConfigField "long", "BUILD_TIMESTAMP", String.valueOf(System.currentTimeMillis())
|
|
||||||
} else {
|
|
||||||
buildConfigField "long", "BUILD_TIMESTAMP", "1486235849000"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
|
@ -72,16 +62,12 @@ android {
|
||||||
shrinkResources true
|
shrinkResources true
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
signingConfig signingConfigs.release
|
signingConfig signingConfigs.release
|
||||||
buildConfigField "String", "MESSAGES_BASE_URL", "\"https://messages.wulkanowy.net.pl\""
|
|
||||||
}
|
}
|
||||||
debug {
|
debug {
|
||||||
minifyEnabled false
|
resValue "string", "app_name", "Wulkanowy DEV " + defaultConfig.versionCode
|
||||||
shrinkResources false
|
|
||||||
resValue "string", "app_name", "Wulkanowy DEV"
|
|
||||||
applicationIdSuffix ".dev"
|
applicationIdSuffix ".dev"
|
||||||
versionNameSuffix "-dev"
|
versionNameSuffix "-dev"
|
||||||
ext.enableCrashlytics = project.hasProperty("enableFirebase")
|
ext.enableCrashlytics = project.hasProperty("enableFirebase")
|
||||||
buildConfigField "String", "MESSAGES_BASE_URL", "\"https://messages.wulkanowy.net.pl\""
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,44 +76,32 @@ android {
|
||||||
productFlavors {
|
productFlavors {
|
||||||
hms {
|
hms {
|
||||||
dimension "platform"
|
dimension "platform"
|
||||||
manifestPlaceholders = [install_channel: "AppGallery"]
|
manifestPlaceholders = [
|
||||||
|
install_channel: "AppGallery"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
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"
|
|
||||||
]
|
]
|
||||||
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 {
|
||||||
dimension "platform"
|
dimension "platform"
|
||||||
manifestPlaceholders = [install_channel: "F-Droid"]
|
manifestPlaceholders = [
|
||||||
|
install_channel: "F-Droid"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
playConfigs {
|
|
||||||
play { enabled.set(true) }
|
|
||||||
}
|
|
||||||
|
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
viewBinding true
|
viewBinding true
|
||||||
}
|
}
|
||||||
|
|
||||||
bundle {
|
|
||||||
language {
|
|
||||||
enableSplit = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 +112,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 {
|
||||||
|
@ -158,63 +130,61 @@ kapt {
|
||||||
}
|
}
|
||||||
|
|
||||||
play {
|
play {
|
||||||
|
serviceAccountEmail = System.getenv("PLAY_SERVICE_ACCOUNT_EMAIL") ?: "jan@fakelog.cf"
|
||||||
|
serviceAccountCredentials = file('key.p12')
|
||||||
defaultToAppBundles = false
|
defaultToAppBundles = false
|
||||||
track = 'production'
|
track = 'beta'
|
||||||
releaseStatus = com.github.triplet.gradle.androidpublisher.ReleaseStatus.IN_PROGRESS
|
updatePriority = 3
|
||||||
userFraction = 0.05d
|
|
||||||
updatePriority = 5
|
|
||||||
enabled.set(false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
huaweiPublish {
|
huaweiPublish {
|
||||||
instances {
|
instances {
|
||||||
hmsRelease {
|
hmsRelease {
|
||||||
credentialsPath = "$rootDir/app/src/release/agconnect-credentials.json"
|
credentialsPath = "$rootDir/app/src/release/agconnect-credentials.json"
|
||||||
buildFormat = "aab"
|
buildFormat = "apk"
|
||||||
deployType = "draft"
|
deployType = "draft"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
work_manager = "2.7.1"
|
work_manager = "2.5.0"
|
||||||
android_hilt = "1.0.0"
|
android_hilt = "1.0.0"
|
||||||
room = "2.4.3"
|
room = "2.3.0"
|
||||||
chucker = "3.5.2"
|
chucker = "3.5.2"
|
||||||
mockk = "1.12.7"
|
mockk = "1.12.0"
|
||||||
coroutines = "1.6.4"
|
moshi = "1.12.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "io.github.wulkanowy:sdk:1.7.2"
|
implementation "io.github.wulkanowy:sdk:1.2.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.0"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.1"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines"
|
|
||||||
|
|
||||||
implementation "androidx.core:core-ktx:1.8.0"
|
implementation "androidx.core:core-ktx:1.6.0"
|
||||||
implementation 'androidx.core:core-splashscreen:1.0.0'
|
implementation "androidx.activity:activity-ktx:1.3.1"
|
||||||
implementation "androidx.activity:activity-ktx:1.5.1"
|
implementation "androidx.appcompat:appcompat:1.3.1"
|
||||||
implementation "androidx.appcompat:appcompat:1.5.0"
|
implementation "androidx.appcompat:appcompat-resources:1.3.1"
|
||||||
implementation "androidx.fragment:fragment-ktx:1.5.2"
|
implementation "androidx.fragment:fragment-ktx:1.3.6"
|
||||||
implementation "androidx.annotation:annotation:1.4.0"
|
implementation "androidx.annotation:annotation:1.2.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.viewpager:viewpager:1.0.0"
|
||||||
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.0"
|
||||||
implementation "androidx.coordinatorlayout:coordinatorlayout:1.2.0"
|
implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"
|
||||||
implementation "com.google.android.material:material:1.6.1"
|
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.2.0"
|
||||||
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
|
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
|
||||||
implementation 'com.github.lopspower:CircularImageView:4.2.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.3.1"
|
||||||
|
|
||||||
implementation "androidx.room:room-runtime:$room"
|
implementation "androidx.room:room-runtime:$room"
|
||||||
implementation "androidx.room:room-ktx:$room"
|
implementation "androidx.room:room-ktx:$room"
|
||||||
|
@ -228,42 +198,40 @@ dependencies {
|
||||||
implementation 'com.github.ncapdevi:FragNav:3.3.0'
|
implementation 'com.github.ncapdevi:FragNav:3.3.0'
|
||||||
implementation "com.github.YarikSOffice:lingver:1.3.0"
|
implementation "com.github.YarikSOffice:lingver:1.3.0"
|
||||||
|
|
||||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
implementation "com.squareup.moshi:moshi:$moshi"
|
||||||
implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0"
|
implementation "com.squareup.moshi:moshi-adapters:$moshi"
|
||||||
implementation "com.squareup.okhttp3:logging-interceptor:4.10.0"
|
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi"
|
||||||
|
|
||||||
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.4'
|
||||||
implementation "com.mikepenz:aboutlibraries-core:$about_libraries"
|
implementation "com.mikepenz:aboutlibraries-core:$about_libraries"
|
||||||
implementation "io.coil-kt:coil:2.2.0"
|
implementation "io.coil-kt:coil:1.3.2"
|
||||||
implementation "io.github.wulkanowy:AppKillerManager:3.0.0"
|
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.5.0'
|
||||||
|
|
||||||
playImplementation platform('com.google.firebase:firebase-bom:30.3.2')
|
playImplementation platform('com.google.firebase:firebase-bom:28.4.0')
|
||||||
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.0'
|
||||||
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.1.0'
|
|
||||||
|
|
||||||
hmsImplementation 'com.huawei.hms:hianalytics:6.7.0.300'
|
hmsImplementation 'com.huawei.hms:hianalytics:6.1.1.300'
|
||||||
hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.7.1.300'
|
hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.6.0.300'
|
||||||
|
|
||||||
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:v1.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:1.5.1'
|
||||||
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||||
|
|
||||||
testImplementation 'org.robolectric:robolectric:4.8.2'
|
testImplementation 'org.robolectric:robolectric:4.6.1'
|
||||||
testImplementation "androidx.test:runner:1.4.0"
|
testImplementation "androidx.test:runner:1.4.0"
|
||||||
testImplementation "androidx.test.ext:junit:1.1.3"
|
testImplementation "androidx.test.ext:junit:1.1.3"
|
||||||
testImplementation "androidx.test:core:1.4.0"
|
testImplementation "androidx.test:core:1.4.0"
|
||||||
|
|
BIN
app/key.p12.gpg
Normal file
BIN
app/key.p12.gpg
Normal file
Binary file not shown.
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
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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
|
|
@ -6,7 +6,6 @@ import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER", "unused")
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class InAppReviewHelper @Inject constructor(
|
class InAppReviewHelper @Inject constructor(
|
||||||
@ApplicationContext private val context: Context
|
@ApplicationContext private val context: Context
|
||||||
|
|
|
@ -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)
|
|
|
@ -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
|
||||||
) {
|
) {
|
||||||
|
@ -15,4 +14,4 @@ class InAppReviewHelper @Inject constructor(
|
||||||
fun showInAppReview(activity: MainActivity) {
|
fun showInAppReview(activity: MainActivity) {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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,7 +9,6 @@
|
||||||
<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"/>
|
|
||||||
|
|
||||||
<queries>
|
<queries>
|
||||||
<intent>
|
<intent>
|
||||||
|
@ -38,14 +38,13 @@
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
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:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="false"
|
android:supportsRtl="false"
|
||||||
android:theme="@style/WulkanowyTheme"
|
android:theme="@style/WulkanowyTheme"
|
||||||
|
android:usesCleartextTraffic="true"
|
||||||
tools:ignore="GoogleAppIndexingWarning,UnusedAttribute">
|
tools:ignore="GoogleAppIndexingWarning,UnusedAttribute">
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.modules.splash.SplashActivity"
|
android:name=".ui.modules.splash.SplashActivity"
|
||||||
android:exported="true"
|
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
android:theme="@style/WulkanowyTheme.SplashScreen"
|
android:theme="@style/WulkanowyTheme.SplashScreen"
|
||||||
tools:ignore="LockedOrientationActivity">
|
tools:ignore="LockedOrientationActivity">
|
||||||
|
@ -75,7 +74,6 @@
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.modules.timetablewidget.TimetableWidgetConfigureActivity"
|
android:name=".ui.modules.timetablewidget.TimetableWidgetConfigureActivity"
|
||||||
android:excludeFromRecents="true"
|
android:excludeFromRecents="true"
|
||||||
android:exported="true"
|
|
||||||
android:noHistory="true"
|
android:noHistory="true"
|
||||||
android:theme="@style/WulkanowyTheme.WidgetAccountSwitcher">
|
android:theme="@style/WulkanowyTheme.WidgetAccountSwitcher">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
@ -85,7 +83,6 @@
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.modules.luckynumberwidget.LuckyNumberWidgetConfigureActivity"
|
android:name=".ui.modules.luckynumberwidget.LuckyNumberWidgetConfigureActivity"
|
||||||
android:excludeFromRecents="true"
|
android:excludeFromRecents="true"
|
||||||
android:exported="true"
|
|
||||||
android:noHistory="true"
|
android:noHistory="true"
|
||||||
android:theme="@style/WulkanowyTheme.WidgetAccountSwitcher">
|
android:theme="@style/WulkanowyTheme.WidgetAccountSwitcher">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
@ -96,22 +93,6 @@
|
||||||
<service
|
<service
|
||||||
android:name=".services.widgets.TimetableWidgetService"
|
android:name=".services.widgets.TimetableWidgetService"
|
||||||
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
||||||
<service
|
|
||||||
android:name=".services.piggyback.VulcanNotificationListenerService"
|
|
||||||
android:exported="true"
|
|
||||||
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.service.notification.NotificationListenerService" />
|
|
||||||
</intent-filter>
|
|
||||||
</service>
|
|
||||||
<service
|
|
||||||
android:name=".services.messaging.AppMessagingService"
|
|
||||||
android:exported="false"
|
|
||||||
tools:ignore="MissingClass">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
|
||||||
</intent-filter>
|
|
||||||
</service>
|
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".ui.modules.timetablewidget.TimetableWidgetProvider"
|
android:name=".ui.modules.timetablewidget.TimetableWidgetProvider"
|
||||||
|
@ -126,7 +107,6 @@
|
||||||
</receiver>
|
</receiver>
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".ui.modules.luckynumberwidget.LuckyNumberWidgetProvider"
|
android:name=".ui.modules.luckynumberwidget.LuckyNumberWidgetProvider"
|
||||||
android:exported="true"
|
|
||||||
android:label="@string/lucky_number_title">
|
android:label="@string/lucky_number_title">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
|
@ -139,9 +119,11 @@
|
||||||
<receiver android:name=".services.alarm.TimetableNotificationReceiver" />
|
<receiver android:name=".services.alarm.TimetableNotificationReceiver" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="androidx.startup.InitializationProvider"
|
android:name="androidx.work.impl.WorkManagerInitializer"
|
||||||
android:authorities="${applicationId}.androidx-startup"
|
android:authorities="${applicationId}.workmanager-init"
|
||||||
|
android:exported="false"
|
||||||
tools:node="remove" />
|
tools:node="remove" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="androidx.core.content.FileProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
android:authorities="${applicationId}.fileprovider"
|
android:authorities="${applicationId}.fileprovider"
|
||||||
|
@ -152,44 +134,44 @@
|
||||||
android:resource="@xml/provider_paths" />
|
android:resource="@xml/provider_paths" />
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="install_channel"
|
||||||
|
android:value="${install_channel}" />
|
||||||
|
|
||||||
<!-- workaround for https://github.com/firebase/firebase-android-sdk/issues/473 enabled:false -->
|
<!-- workaround for https://github.com/firebase/firebase-android-sdk/issues/473 enabled:false -->
|
||||||
<!-- https://firebase.googleblog.com/2017/03/take-control-of-your-firebase-init-on.html -->
|
<!-- https://firebase.googleblog.com/2017/03/take-control-of-your-firebase-init-on.html -->
|
||||||
<provider
|
<provider
|
||||||
android:name="com.google.firebase.provider.FirebaseInitProvider"
|
android:name="com.google.firebase.provider.FirebaseInitProvider"
|
||||||
android:authorities="${applicationId}.firebaseinitprovider"
|
android:authorities="${applicationId}.firebaseinitprovider"
|
||||||
android:enabled="${firebase_enabled}"
|
android:enabled="${firebase_enabled}"
|
||||||
android:exported="false"
|
android:exported="false" />
|
||||||
tools:ignore="MissingClass" />
|
|
||||||
|
|
||||||
<meta-data
|
|
||||||
android:name="install_channel"
|
|
||||||
android:value="${install_channel}" />
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="firebase_analytics_collection_enabled"
|
android:name="firebase_analytics_collection_enabled"
|
||||||
android:value="${firebase_enabled}" />
|
android:value="${firebase_enabled}" />
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="google_analytics_adid_collection_enabled"
|
android:name="google_analytics_adid_collection_enabled"
|
||||||
android:value="${firebase_enabled}" />
|
android:value="${firebase_enabled}" />
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="firebase_crashlytics_collection_enabled"
|
android:name="firebase_crashlytics_collection_enabled"
|
||||||
android:value="${firebase_enabled}" />
|
android:value="${firebase_enabled}" />
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="firebase_messaging_auto_init_enabled"
|
android:name="firebase_messaging_auto_init_enabled"
|
||||||
android:value="${firebase_enabled}" />
|
android:value="${firebase_enabled}" />
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="firebase_inapp_messaging_auto_data_collection_enabled"
|
android:name="firebase_inapp_messaging_auto_data_collection_enabled"
|
||||||
android:value="${firebase_enabled}" />
|
android:value="${firebase_enabled}" />
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="com.google.firebase.messaging.default_notification_icon"
|
android:name="com.google.firebase.messaging.default_notification_icon"
|
||||||
android:resource="@drawable/ic_stat_all" />
|
android:resource="@drawable/ic_stat_all" />
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="com.google.firebase.messaging.default_notification_channel_id"
|
android:name="com.google.firebase.messaging.default_notification_channel_id"
|
||||||
android:value="push_channel" />
|
android:value="push_channel" />
|
||||||
<meta-data
|
|
||||||
android:name="com.google.android.gms.ads.APPLICATION_ID"
|
|
||||||
android:value="${admob_project_id}" />
|
|
||||||
<meta-data
|
|
||||||
android:name="com.google.android.gms.ads.DELAY_APP_MEASUREMENT_INIT"
|
|
||||||
android:value="true" />
|
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
package io.github.wulkanowy
|
package io.github.wulkanowy
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.util.Log.*
|
import android.util.Log.DEBUG
|
||||||
|
import android.util.Log.INFO
|
||||||
|
import android.util.Log.VERBOSE
|
||||||
|
import android.webkit.WebView
|
||||||
|
import androidx.fragment.app.FragmentManager
|
||||||
import androidx.hilt.work.HiltWorkerFactory
|
import androidx.hilt.work.HiltWorkerFactory
|
||||||
import androidx.work.Configuration
|
import androidx.work.Configuration
|
||||||
import com.yariksoffice.lingver.Lingver
|
import com.yariksoffice.lingver.Lingver
|
||||||
|
@ -9,7 +14,12 @@ import dagger.hilt.android.HiltAndroidApp
|
||||||
import fr.bipi.tressence.file.FileLoggerTree
|
import fr.bipi.tressence.file.FileLoggerTree
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||||
import io.github.wulkanowy.ui.base.ThemeManager
|
import io.github.wulkanowy.ui.base.ThemeManager
|
||||||
import io.github.wulkanowy.utils.*
|
import io.github.wulkanowy.utils.ActivityLifecycleLogger
|
||||||
|
import io.github.wulkanowy.utils.AnalyticsHelper
|
||||||
|
import io.github.wulkanowy.utils.AppInfo
|
||||||
|
import io.github.wulkanowy.utils.CrashLogExceptionTree
|
||||||
|
import io.github.wulkanowy.utils.CrashLogTree
|
||||||
|
import io.github.wulkanowy.utils.DebugLogTree
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -31,15 +41,14 @@ class WulkanowyApp : Application(), Configuration.Provider {
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var analyticsHelper: AnalyticsHelper
|
lateinit var analyticsHelper: AnalyticsHelper
|
||||||
|
|
||||||
@Inject
|
@SuppressLint("UnsafeOptInUsageWarning")
|
||||||
lateinit var adsHelper: AdsHelper
|
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
FragmentManager.enableNewStateManager(false)
|
||||||
initializeAppLanguage()
|
initializeAppLanguage()
|
||||||
themeManager.applyDefaultTheme()
|
themeManager.applyDefaultTheme()
|
||||||
adsHelper.initialize()
|
|
||||||
initLogging()
|
initLogging()
|
||||||
|
fixWebViewLocale()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initLogging() {
|
private fun initLogging() {
|
||||||
|
@ -71,6 +80,15 @@ class WulkanowyApp : Application(), Configuration.Provider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun fixWebViewLocale() {
|
||||||
|
//https://stackoverflow.com/questions/40398528/android-webview-language-changes-abruptly-on-android-7-0-and-above
|
||||||
|
try {
|
||||||
|
WebView(this).destroy()
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
//Ignore exceptions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun getWorkManagerConfiguration() = Configuration.Builder()
|
override fun getWorkManagerConfiguration() = Configuration.Builder()
|
||||||
.setWorkerFactory(workerFactory)
|
.setWorkerFactory(workerFactory)
|
||||||
.setMinimumLoggingLevel(if (appInfo.isDebug) VERBOSE else INFO)
|
.setMinimumLoggingLevel(if (appInfo.isDebug) VERBOSE else INFO)
|
||||||
|
|
|
@ -2,99 +2,62 @@ package io.github.wulkanowy.data
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
|
import android.content.res.AssetManager
|
||||||
|
import android.content.res.Resources
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.chuckerteam.chucker.api.ChuckerCollector
|
import com.chuckerteam.chucker.api.ChuckerCollector
|
||||||
import com.chuckerteam.chucker.api.ChuckerInterceptor
|
import com.chuckerteam.chucker.api.ChuckerInterceptor
|
||||||
import com.chuckerteam.chucker.api.RetentionManager
|
import com.chuckerteam.chucker.api.RetentionManager
|
||||||
|
import com.squareup.moshi.Moshi
|
||||||
import com.fredporciuncula.flow.preferences.FlowSharedPreferences
|
import com.fredporciuncula.flow.preferences.FlowSharedPreferences
|
||||||
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
|
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import dagger.hilt.components.SingletonComponent
|
import dagger.hilt.components.SingletonComponent
|
||||||
import io.github.wulkanowy.data.api.AdminMessageService
|
|
||||||
import io.github.wulkanowy.data.db.AppDatabase
|
import io.github.wulkanowy.data.db.AppDatabase
|
||||||
import io.github.wulkanowy.data.db.SharedPrefProvider
|
import io.github.wulkanowy.data.db.SharedPrefProvider
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.AppInfo
|
import io.github.wulkanowy.utils.AppInfo
|
||||||
import kotlinx.serialization.ExperimentalSerializationApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.serialization.json.Json
|
|
||||||
import okhttp3.MediaType.Companion.toMediaType
|
|
||||||
import okhttp3.OkHttpClient
|
|
||||||
import okhttp3.logging.HttpLoggingInterceptor
|
|
||||||
import retrofit2.Retrofit
|
|
||||||
import retrofit2.create
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@InstallIn(SingletonComponent::class)
|
@InstallIn(SingletonComponent::class)
|
||||||
internal class DataModule {
|
internal class RepositoryModule {
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideSdk(chuckerInterceptor: ChuckerInterceptor) =
|
fun provideSdk(chuckerCollector: ChuckerCollector, @ApplicationContext context: Context): Sdk {
|
||||||
Sdk().apply {
|
return Sdk().apply {
|
||||||
androidVersion = android.os.Build.VERSION.RELEASE
|
androidVersion = android.os.Build.VERSION.RELEASE
|
||||||
buildTag = android.os.Build.MODEL
|
buildTag = android.os.Build.MODEL
|
||||||
setSimpleHttpLogger { Timber.d(it) }
|
setSimpleHttpLogger { Timber.d(it) }
|
||||||
|
|
||||||
// for debug only
|
// for debug only
|
||||||
addInterceptor(chuckerInterceptor, network = true)
|
addInterceptor(
|
||||||
|
ChuckerInterceptor.Builder(context)
|
||||||
|
.collector(chuckerCollector)
|
||||||
|
.alwaysReadResponseBody(true)
|
||||||
|
.build(), network = true
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideChuckerCollector(
|
fun provideChuckerCollector(
|
||||||
@ApplicationContext context: Context,
|
@ApplicationContext context: Context,
|
||||||
prefRepository: PreferencesRepository
|
prefRepository: PreferencesRepository
|
||||||
) = ChuckerCollector(
|
): ChuckerCollector {
|
||||||
context = context,
|
return ChuckerCollector(
|
||||||
showNotification = prefRepository.isDebugNotificationEnable,
|
context = context,
|
||||||
retentionPeriod = RetentionManager.Period.ONE_HOUR
|
showNotification = prefRepository.isDebugNotificationEnable,
|
||||||
)
|
retentionPeriod = RetentionManager.Period.ONE_HOUR
|
||||||
|
)
|
||||||
@Singleton
|
}
|
||||||
@Provides
|
|
||||||
fun provideChuckerInterceptor(
|
|
||||||
@ApplicationContext context: Context,
|
|
||||||
chuckerCollector: ChuckerCollector
|
|
||||||
) = ChuckerInterceptor.Builder(context)
|
|
||||||
.collector(chuckerCollector)
|
|
||||||
.alwaysReadResponseBody(true)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
@Provides
|
|
||||||
fun provideOkHttpClient(chuckerInterceptor: ChuckerInterceptor): OkHttpClient =
|
|
||||||
OkHttpClient.Builder()
|
|
||||||
.addNetworkInterceptor(chuckerInterceptor)
|
|
||||||
.addInterceptor(HttpLoggingInterceptor().apply {
|
|
||||||
level = HttpLoggingInterceptor.Level.BASIC
|
|
||||||
})
|
|
||||||
.connectTimeout(30, TimeUnit.SECONDS)
|
|
||||||
.readTimeout(30, TimeUnit.SECONDS)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
@OptIn(ExperimentalSerializationApi::class)
|
|
||||||
@Singleton
|
|
||||||
@Provides
|
|
||||||
fun provideRetrofit(
|
|
||||||
okHttpClient: OkHttpClient,
|
|
||||||
json: Json,
|
|
||||||
appInfo: AppInfo
|
|
||||||
): Retrofit = Retrofit.Builder()
|
|
||||||
.baseUrl(appInfo.messagesBaseUrl)
|
|
||||||
.client(okHttpClient)
|
|
||||||
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
|
|
||||||
.build()
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
@Provides
|
|
||||||
fun provideAdminMessageService(retrofit: Retrofit): AdminMessageService = retrofit.create()
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
|
@ -104,11 +67,20 @@ internal class DataModule {
|
||||||
appInfo: AppInfo
|
appInfo: AppInfo
|
||||||
) = AppDatabase.newInstance(context, sharedPrefProvider, appInfo)
|
) = AppDatabase.newInstance(context, sharedPrefProvider, appInfo)
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
fun provideResources(@ApplicationContext context: Context): Resources = context.resources
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
fun provideAssets(@ApplicationContext context: Context): AssetManager = context.assets
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
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) =
|
||||||
|
@ -116,9 +88,7 @@ internal class DataModule {
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideJson() = Json {
|
fun provideMoshi() = Moshi.Builder().build()
|
||||||
ignoreUnknownKeys = true
|
|
||||||
}
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
|
@ -195,7 +165,7 @@ internal class DataModule {
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideMailboxesDao(database: AppDatabase) = database.mailboxDao
|
fun provideReportingUnitDao(database: AppDatabase) = database.reportingUnitDao
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
|
@ -232,12 +202,4 @@ internal class DataModule {
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideSchoolAnnouncementDao(database: AppDatabase) = database.schoolAnnouncementDao
|
fun provideSchoolAnnouncementDao(database: AppDatabase) = database.schoolAnnouncementDao
|
||||||
|
|
||||||
@Singleton
|
|
||||||
@Provides
|
|
||||||
fun provideNotificationDao(database: AppDatabase) = database.notificationDao
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
@Provides
|
|
||||||
fun provideAdminMessageDao(database: AppDatabase) = database.adminMessagesDao
|
|
||||||
}
|
}
|
|
@ -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.Loading -> "started"
|
|
||||||
is Resource.Intermediate -> "intermediate data received" + if (showData) " (data: `${it.data}`)" else ""
|
|
||||||
is Resource.Success -> "success" + if (showData) " (data: `${it.data}`)" else ""
|
|
||||||
is Resource.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,12 +0,0 @@
|
||||||
package io.github.wulkanowy.data.api
|
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.AdminMessage
|
|
||||||
import retrofit2.http.GET
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
interface AdminMessageService {
|
|
||||||
|
|
||||||
@GET("/v1.json")
|
|
||||||
suspend fun getAdminMessages(): List<AdminMessage>
|
|
||||||
}
|
|
|
@ -1,11 +1,105 @@
|
||||||
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.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.AttendanceDao
|
||||||
import io.github.wulkanowy.data.db.migrations.*
|
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.SchoolAnnouncementDao
|
||||||
|
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.RecipientDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.ReportingUnitDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.SchoolDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.SemesterDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.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.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.SchoolAnnouncement
|
||||||
|
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.Recipient
|
||||||
|
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||||
|
import io.github.wulkanowy.data.db.entities.School
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.github.wulkanowy.data.db.entities.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.Migration10
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration11
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration12
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration13
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration14
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration15
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration16
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration17
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration18
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration19
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration2
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration20
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration21
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration22
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration23
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration24
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration25
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration26
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration27
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration28
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration29
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration3
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration30
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration31
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration32
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration33
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration34
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration35
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration36
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration37
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration38
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration39
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration4
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration5
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration6
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration7
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration8
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration9
|
||||||
import io.github.wulkanowy.utils.AppInfo
|
import io.github.wulkanowy.utils.AppInfo
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@ -30,7 +124,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,
|
||||||
|
@ -40,13 +134,6 @@ import javax.inject.Singleton
|
||||||
StudentInfo::class,
|
StudentInfo::class,
|
||||||
TimetableHeader::class,
|
TimetableHeader::class,
|
||||||
SchoolAnnouncement::class,
|
SchoolAnnouncement::class,
|
||||||
Notification::class,
|
|
||||||
AdminMessage::class
|
|
||||||
],
|
|
||||||
autoMigrations = [
|
|
||||||
AutoMigration(from = 44, to = 45),
|
|
||||||
AutoMigration(from = 46, to = 47),
|
|
||||||
AutoMigration(from = 47, to = 48),
|
|
||||||
],
|
],
|
||||||
version = AppDatabase.VERSION_SCHEMA,
|
version = AppDatabase.VERSION_SCHEMA,
|
||||||
exportSchema = true
|
exportSchema = true
|
||||||
|
@ -55,7 +142,7 @@ import javax.inject.Singleton
|
||||||
abstract class AppDatabase : RoomDatabase() {
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val VERSION_SCHEMA = 51
|
const val VERSION_SCHEMA = 39
|
||||||
|
|
||||||
fun getMigrations(sharedPrefProvider: SharedPrefProvider, appInfo: AppInfo) = arrayOf(
|
fun getMigrations(sharedPrefProvider: SharedPrefProvider, appInfo: AppInfo) = arrayOf(
|
||||||
Migration2(),
|
Migration2(),
|
||||||
|
@ -96,15 +183,6 @@ abstract class AppDatabase : RoomDatabase() {
|
||||||
Migration37(),
|
Migration37(),
|
||||||
Migration38(),
|
Migration38(),
|
||||||
Migration39(),
|
Migration39(),
|
||||||
Migration40(),
|
|
||||||
Migration41(sharedPrefProvider),
|
|
||||||
Migration42(),
|
|
||||||
Migration43(),
|
|
||||||
Migration44(),
|
|
||||||
Migration46(),
|
|
||||||
Migration49(),
|
|
||||||
Migration50(),
|
|
||||||
Migration51(),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
fun newInstance(
|
fun newInstance(
|
||||||
|
@ -155,7 +233,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
|
||||||
|
|
||||||
|
@ -174,8 +252,4 @@ abstract class AppDatabase : RoomDatabase() {
|
||||||
abstract val timetableHeaderDao: TimetableHeaderDao
|
abstract val timetableHeaderDao: TimetableHeaderDao
|
||||||
|
|
||||||
abstract val schoolAnnouncementDao: SchoolAnnouncementDao
|
abstract val schoolAnnouncementDao: SchoolAnnouncementDao
|
||||||
|
|
||||||
abstract val notificationDao: NotificationDao
|
|
||||||
|
|
||||||
abstract val adminMessagesDao: AdminMessageDao
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,36 +1,47 @@
|
||||||
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 com.squareup.moshi.Moshi
|
||||||
import io.github.wulkanowy.utils.toTimestamp
|
import com.squareup.moshi.Types
|
||||||
import kotlinx.serialization.SerializationException
|
import io.github.wulkanowy.data.db.adapters.PairAdapterFactory
|
||||||
import kotlinx.serialization.decodeFromString
|
|
||||||
import kotlinx.serialization.encodeToString
|
|
||||||
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.LocalDateTime
|
||||||
import java.time.Month
|
import java.time.Month
|
||||||
import java.time.ZoneOffset
|
import java.time.ZoneOffset
|
||||||
import java.util.*
|
import java.util.Date
|
||||||
|
|
||||||
class Converters {
|
class Converters {
|
||||||
|
|
||||||
private val json = Json
|
private val moshi by lazy { Moshi.Builder().add(PairAdapterFactory).build() }
|
||||||
|
|
||||||
|
private val integerListAdapter by lazy {
|
||||||
|
moshi.adapter<List<Int>>(Types.newParameterizedType(List::class.java, Integer::class.java))
|
||||||
|
}
|
||||||
|
|
||||||
|
private val stringListPairAdapter by lazy {
|
||||||
|
moshi.adapter<List<Pair<String, String>>>(Types.newParameterizedType(List::class.java, Pair::class.java, String::class.java, String::class.java))
|
||||||
|
}
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun timestampToLocalDate(value: Long?): LocalDate? =
|
fun timestampToDate(value: Long?): LocalDate? = value?.run {
|
||||||
value?.let(::Date)?.toInstant()?.atZone(ZoneOffset.UTC)?.toLocalDate()
|
Date(value).toInstant().atZone(ZoneOffset.UTC).toLocalDate()
|
||||||
|
}
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun dateToTimestamp(date: LocalDate?): Long? = date?.toTimestamp()
|
fun dateToTimestamp(date: LocalDate?): Long? {
|
||||||
|
return date?.atStartOfDay()?.toInstant(ZoneOffset.UTC)?.toEpochMilli()
|
||||||
|
}
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun instantToTimestamp(instant: Instant?): Long? = instant?.toEpochMilli()
|
fun timestampToTime(value: Long?): LocalDateTime? = value?.let {
|
||||||
|
LocalDateTime.ofInstant(Instant.ofEpochMilli(value), ZoneOffset.UTC)
|
||||||
|
}
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun timestampToInstant(timestamp: Long?): Instant? = timestamp?.let(Instant::ofEpochMilli)
|
fun timeToTimestamp(date: LocalDateTime?): Long? {
|
||||||
|
return date?.atZone(ZoneOffset.UTC)?.toInstant()?.toEpochMilli()
|
||||||
|
}
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun monthToInt(month: Month?) = month?.value
|
fun monthToInt(month: Month?) = month?.value
|
||||||
|
@ -40,32 +51,21 @@ class Converters {
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun intListToJson(list: List<Int>): String {
|
fun intListToJson(list: List<Int>): String {
|
||||||
return json.encodeToString(list)
|
return integerListAdapter.toJson(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun jsonToIntList(value: String): List<Int> {
|
fun jsonToIntList(value: String): List<Int> {
|
||||||
return json.decodeFromString(value)
|
return integerListAdapter.fromJson(value).orEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun stringPairListToJson(list: List<Pair<String, String>>): String {
|
fun stringPairListToJson(list: List<Pair<String, String>>): String {
|
||||||
return json.encodeToString(list)
|
return stringListPairAdapter.toJson(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun jsonToStringPairList(value: String): List<Pair<String, String>> {
|
fun jsonToStringPairList(value: String): List<Pair<String, String>> {
|
||||||
return try {
|
return stringListPairAdapter.fromJson(value).orEmpty()
|
||||||
json.decodeFromString(value)
|
|
||||||
} catch (e: SerializationException) {
|
|
||||||
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)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,14 +22,11 @@ class SharedPrefProvider @Inject constructor(
|
||||||
|
|
||||||
fun getString(key: String) = sharedPref.getString(key, null)
|
fun getString(key: String) = sharedPref.getString(key, null)
|
||||||
|
|
||||||
fun getString(key: String, defaultValue: String): String =
|
fun getString(key: String, defaultValue: String): String = sharedPref.getString(key, defaultValue) ?: defaultValue
|
||||||
sharedPref.getString(key, defaultValue) ?: defaultValue
|
|
||||||
|
|
||||||
fun getBoolean(key: String, defaultValue: Boolean): Boolean =
|
fun getBoolean(key: String, defaultValue: Boolean): Boolean = sharedPref.getBoolean(key, defaultValue)
|
||||||
sharedPref.getBoolean(key, defaultValue)
|
|
||||||
|
|
||||||
fun putBoolean(key: String, value: Boolean, sync: Boolean = false) =
|
fun putBoolean(key: String, value: Boolean, sync: Boolean = false) = sharedPref.edit(sync) { putBoolean(key, value) }
|
||||||
sharedPref.edit(sync) { putBoolean(key, value) }
|
|
||||||
|
|
||||||
fun putString(key: String, value: String?, sync: Boolean = false) {
|
fun putString(key: String, value: String?, sync: Boolean = false) {
|
||||||
sharedPref.edit(sync) { putString(key, value) }
|
sharedPref.edit(sync) { putString(key, value) }
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
package io.github.wulkanowy.data.db.adapters
|
||||||
|
|
||||||
|
import com.squareup.moshi.JsonAdapter
|
||||||
|
import com.squareup.moshi.JsonReader
|
||||||
|
import com.squareup.moshi.JsonWriter
|
||||||
|
import com.squareup.moshi.Moshi
|
||||||
|
import com.squareup.moshi.Types
|
||||||
|
import java.lang.reflect.ParameterizedType
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
|
||||||
|
object PairAdapterFactory : JsonAdapter.Factory {
|
||||||
|
|
||||||
|
override fun create(type: Type, annotations: MutableSet<out Annotation>, moshi: Moshi): JsonAdapter<*>? {
|
||||||
|
if (type !is ParameterizedType || List::class.java != type.rawType) return null
|
||||||
|
if (type.actualTypeArguments[0] != Pair::class.java) return null
|
||||||
|
|
||||||
|
val listType = Types.newParameterizedType(List::class.java, Map::class.java, String::class.java)
|
||||||
|
val listAdapter = moshi.adapter<List<Map<String, String>>>(listType)
|
||||||
|
|
||||||
|
val mapType = Types.newParameterizedType(MutableMap::class.java, String::class.java, String::class.java)
|
||||||
|
val mapAdapter = moshi.adapter<Map<String, String>>(mapType)
|
||||||
|
|
||||||
|
return PairAdapter(listAdapter, mapAdapter)
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PairAdapter(
|
||||||
|
private val listAdapter: JsonAdapter<List<Map<String, String>>>,
|
||||||
|
private val mapAdapter: JsonAdapter<Map<String, String>>,
|
||||||
|
) : JsonAdapter<List<Pair<String, String>>>() {
|
||||||
|
|
||||||
|
override fun toJson(writer: JsonWriter, value: List<Pair<String, String>>?) {
|
||||||
|
writer.beginArray()
|
||||||
|
value?.forEach {
|
||||||
|
writer.beginObject()
|
||||||
|
writer.name("first").value(it.first)
|
||||||
|
writer.name("second").value(it.second)
|
||||||
|
writer.endObject()
|
||||||
|
}
|
||||||
|
writer.endArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fromJson(reader: JsonReader): List<Pair<String, String>>? {
|
||||||
|
return if (reader.peek() == JsonReader.Token.BEGIN_OBJECT) deserializeMoshiMap(reader)
|
||||||
|
else deserializeGsonPair(reader)
|
||||||
|
}
|
||||||
|
|
||||||
|
// for compatibility with 0.21.0
|
||||||
|
private fun deserializeMoshiMap(reader: JsonReader): List<Pair<String, String>>? {
|
||||||
|
val map = mapAdapter.fromJson(reader) ?: return null
|
||||||
|
|
||||||
|
return map.entries.map {
|
||||||
|
it.key to it.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeGsonPair(reader: JsonReader): List<Pair<String, String>>? {
|
||||||
|
val list = listAdapter.fromJson(reader) ?: return null
|
||||||
|
|
||||||
|
return list.map {
|
||||||
|
require(it.size == 2) {
|
||||||
|
"pair with more or less than two elements: $list"
|
||||||
|
}
|
||||||
|
|
||||||
|
it["first"].orEmpty() to it["second"].orEmpty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,25 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.dao
|
|
||||||
|
|
||||||
import androidx.room.Dao
|
|
||||||
import androidx.room.Query
|
|
||||||
import androidx.room.Transaction
|
|
||||||
import io.github.wulkanowy.data.db.entities.AdminMessage
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
@Dao
|
|
||||||
abstract class AdminMessageDao : BaseDao<AdminMessage> {
|
|
||||||
|
|
||||||
@Query("SELECT * FROM AdminMessages")
|
|
||||||
abstract fun loadAll(): Flow<List<AdminMessage>>
|
|
||||||
|
|
||||||
@Transaction
|
|
||||||
open suspend fun removeOldAndSaveNew(
|
|
||||||
oldMessages: List<AdminMessage>,
|
|
||||||
newMessages: List<AdminMessage>
|
|
||||||
) {
|
|
||||||
deleteAll(oldMessages)
|
|
||||||
insertAll(newMessages)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -11,11 +11,6 @@ import javax.inject.Singleton
|
||||||
@Dao
|
@Dao
|
||||||
interface AttendanceDao : BaseDao<Attendance> {
|
interface AttendanceDao : BaseDao<Attendance> {
|
||||||
|
|
||||||
@Query("SELECT * FROM Attendance WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :start AND date <= :end")
|
@Query("SELECT * FROM Attendance WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
||||||
fun loadAll(
|
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow<List<Attendance>>
|
||||||
diaryId: Int,
|
|
||||||
studentId: Int,
|
|
||||||
start: LocalDate,
|
|
||||||
end: LocalDate
|
|
||||||
): Flow<List<Attendance>>
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -4,7 +4,7 @@ import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.Conference
|
import io.github.wulkanowy.data.db.entities.Conference
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import java.time.Instant
|
import java.time.LocalDateTime
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
|
@ -12,5 +12,5 @@ import javax.inject.Singleton
|
||||||
interface ConferenceDao : BaseDao<Conference> {
|
interface ConferenceDao : BaseDao<Conference> {
|
||||||
|
|
||||||
@Query("SELECT * FROM Conferences WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :startDate")
|
@Query("SELECT * FROM Conferences WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :startDate")
|
||||||
fun loadAll(diaryId: Int, studentId: Int, startDate: Instant): Flow<List<Conference>>
|
fun loadAll(diaryId: Int, studentId: Int, startDate: LocalDateTime): Flow<List<Conference>>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +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 javax.inject.Singleton
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
@Dao
|
|
||||||
interface MailboxDao : BaseDao<Mailbox> {
|
|
||||||
|
|
||||||
@Query("SELECT * FROM Mailboxes WHERE userLoginId = :userLoginId ")
|
|
||||||
suspend fun loadAll(userLoginId: Int): List<Mailbox>
|
|
||||||
}
|
|
|
@ -11,9 +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>>
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.dao
|
|
||||||
|
|
||||||
import androidx.room.Dao
|
|
||||||
import androidx.room.Query
|
|
||||||
import io.github.wulkanowy.data.db.entities.Notification
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
@Dao
|
|
||||||
interface NotificationDao : BaseDao<Notification> {
|
|
||||||
|
|
||||||
@Query("SELECT * FROM Notifications WHERE student_id = :studentId OR student_id = -1")
|
|
||||||
fun loadAll(studentId: Long): Flow<List<Notification>>
|
|
||||||
}
|
|
|
@ -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")
|
||||||
fun loadAll(userLoginId: Int): Flow<List<SchoolAnnouncement>>
|
fun loadAll(studentId: Int): Flow<List<SchoolAnnouncement>>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
package io.github.wulkanowy.data.db.dao
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
import androidx.room.*
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Delete
|
||||||
|
import androidx.room.Insert
|
||||||
import androidx.room.OnConflictStrategy.ABORT
|
import androidx.room.OnConflictStrategy.ABORT
|
||||||
|
import androidx.room.Query
|
||||||
|
import androidx.room.Transaction
|
||||||
|
import androidx.room.Update
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.db.entities.StudentNickAndAvatar
|
import io.github.wulkanowy.data.db.entities.StudentNickAndAvatar
|
||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||||
|
@ -9,43 +14,33 @@ import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Dao
|
@Dao
|
||||||
abstract class StudentDao {
|
interface StudentDao {
|
||||||
|
|
||||||
@Insert(onConflict = ABORT)
|
@Insert(onConflict = ABORT)
|
||||||
abstract suspend fun insertAll(student: List<Student>): List<Long>
|
suspend fun insertAll(student: List<Student>): List<Long>
|
||||||
|
|
||||||
@Delete
|
@Delete
|
||||||
abstract suspend fun delete(student: Student)
|
suspend fun delete(student: Student)
|
||||||
|
|
||||||
@Update(entity = Student::class)
|
@Update(entity = Student::class)
|
||||||
abstract suspend fun update(studentNickAndAvatar: StudentNickAndAvatar)
|
suspend fun update(studentNickAndAvatar: StudentNickAndAvatar)
|
||||||
|
|
||||||
@Query("SELECT * FROM Students WHERE is_current = 1")
|
@Query("SELECT * FROM Students WHERE is_current = 1")
|
||||||
abstract suspend fun loadCurrent(): Student?
|
suspend fun loadCurrent(): Student?
|
||||||
|
|
||||||
@Query("SELECT * FROM Students WHERE id = :id")
|
@Query("SELECT * FROM Students WHERE id = :id")
|
||||||
abstract suspend fun loadById(id: Long): Student?
|
suspend fun loadById(id: Long): Student?
|
||||||
|
|
||||||
@Query("SELECT * FROM Students")
|
@Query("SELECT * FROM Students")
|
||||||
abstract suspend fun loadAll(): List<Student>
|
suspend fun loadAll(): List<Student>
|
||||||
|
|
||||||
@Transaction
|
@Transaction
|
||||||
@Query("SELECT * FROM Students")
|
@Query("SELECT * FROM Students")
|
||||||
abstract suspend fun loadStudentsWithSemesters(): List<StudentWithSemesters>
|
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)
|
suspend fun updateCurrent(id: Long)
|
||||||
|
|
||||||
@Query("UPDATE Students SET is_current = 0")
|
@Query("UPDATE Students SET is_current = 0")
|
||||||
abstract suspend fun resetCurrent()
|
suspend fun resetCurrent()
|
||||||
|
|
||||||
@Transaction
|
|
||||||
open suspend fun switchCurrent(id: Long) {
|
|
||||||
resetCurrent()
|
|
||||||
updateCurrent(id)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.TimetableAdditional
|
import io.github.wulkanowy.data.db.entities.TimetableAdditional
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.util.UUID
|
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
|
@ -13,13 +12,5 @@ import javax.inject.Singleton
|
||||||
interface TimetableAdditionalDao : BaseDao<TimetableAdditional> {
|
interface TimetableAdditionalDao : BaseDao<TimetableAdditional> {
|
||||||
|
|
||||||
@Query("SELECT * FROM TimetableAdditional WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
@Query("SELECT * FROM TimetableAdditional WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
||||||
fun loadAll(
|
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow<List<TimetableAdditional>>
|
||||||
diaryId: Int,
|
|
||||||
studentId: Int,
|
|
||||||
from: LocalDate,
|
|
||||||
end: LocalDate
|
|
||||||
): Flow<List<TimetableAdditional>>
|
|
||||||
|
|
||||||
@Query("DELETE FROM TimetableAdditional WHERE repeat_id = :repeatId")
|
|
||||||
suspend fun deleteAllByRepeatId(repeatId: UUID)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.entities
|
|
||||||
|
|
||||||
import androidx.room.ColumnInfo
|
|
||||||
import androidx.room.Entity
|
|
||||||
import androidx.room.PrimaryKey
|
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
@Entity(tableName = "AdminMessages")
|
|
||||||
data class AdminMessage(
|
|
||||||
|
|
||||||
@PrimaryKey
|
|
||||||
val id: Int,
|
|
||||||
|
|
||||||
val title: String,
|
|
||||||
|
|
||||||
val content: String,
|
|
||||||
|
|
||||||
@ColumnInfo(name = "version_name")
|
|
||||||
val versionMin: Int? = null,
|
|
||||||
|
|
||||||
@ColumnInfo(name = "version_max")
|
|
||||||
val versionMax: Int? = null,
|
|
||||||
|
|
||||||
@ColumnInfo(name = "target_register_host")
|
|
||||||
val targetRegisterHost: String? = null,
|
|
||||||
|
|
||||||
@ColumnInfo(name = "target_flavor")
|
|
||||||
val targetFlavor: String? = null,
|
|
||||||
|
|
||||||
@ColumnInfo(name = "destination_url")
|
|
||||||
val destinationUrl: String? = null,
|
|
||||||
|
|
||||||
val priority: String,
|
|
||||||
|
|
||||||
val type: String,
|
|
||||||
|
|
||||||
@ColumnInfo(name = "is_dismissible")
|
|
||||||
val isDismissible: Boolean = false
|
|
||||||
)
|
|
|
@ -47,7 +47,4 @@ data class Attendance(
|
||||||
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
var id: Long = 0
|
var id: Long = 0
|
||||||
|
|
||||||
@ColumnInfo(name = "is_notified")
|
|
||||||
var isNotified: Boolean = true
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ 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
|
||||||
import java.time.Instant
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
@Entity(tableName = "Conferences")
|
@Entity(tableName = "Conferences")
|
||||||
data class Conference(
|
data class Conference(
|
||||||
|
@ -27,7 +27,7 @@ data class Conference(
|
||||||
@ColumnInfo(name = "conference_id")
|
@ColumnInfo(name = "conference_id")
|
||||||
val conferenceId: Int,
|
val conferenceId: Int,
|
||||||
|
|
||||||
val date: Instant,
|
val date: LocalDateTime
|
||||||
) : Serializable {
|
) : Serializable {
|
||||||
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
|
|
@ -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 = ""
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package io.github.wulkanowy.data.db.entities
|
||||||
import androidx.room.ColumnInfo
|
import androidx.room.ColumnInfo
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import java.time.Instant
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
@Entity(tableName = "GradesSummary")
|
@Entity(tableName = "GradesSummary")
|
||||||
data class GradeSummary(
|
data class GradeSummary(
|
||||||
|
@ -45,8 +45,8 @@ data class GradeSummary(
|
||||||
var isFinalGradeNotified: Boolean = true
|
var isFinalGradeNotified: Boolean = true
|
||||||
|
|
||||||
@ColumnInfo(name = "predicted_grade_last_change")
|
@ColumnInfo(name = "predicted_grade_last_change")
|
||||||
var predictedGradeLastChange: Instant = Instant.now()
|
var predictedGradeLastChange: LocalDateTime = LocalDateTime.now()
|
||||||
|
|
||||||
@ColumnInfo(name = "final_grade_last_change")
|
@ColumnInfo(name = "final_grade_last_change")
|
||||||
var finalGradeLastChange: Instant = Instant.now()
|
var finalGradeLastChange: LocalDateTime = LocalDateTime.now()
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,4 @@ data class Homework(
|
||||||
|
|
||||||
@ColumnInfo(name = "is_notified")
|
@ColumnInfo(name = "is_notified")
|
||||||
var isNotified: Boolean = true
|
var isNotified: Boolean = true
|
||||||
|
|
||||||
@ColumnInfo(name = "is_added_by_user")
|
|
||||||
var isAddedByUser: Boolean = false
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.entities
|
|
||||||
|
|
||||||
import androidx.room.Entity
|
|
||||||
import androidx.room.PrimaryKey
|
|
||||||
|
|
||||||
@Entity(tableName = "Mailboxes")
|
|
||||||
data class Mailbox(
|
|
||||||
|
|
||||||
@PrimaryKey
|
|
||||||
val globalKey: String,
|
|
||||||
val fullName: String,
|
|
||||||
val userName: String,
|
|
||||||
val userLoginId: Int,
|
|
||||||
val studentName: String,
|
|
||||||
val schoolNameShort: String,
|
|
||||||
val type: MailboxType,
|
|
||||||
)
|
|
||||||
|
|
||||||
enum class MailboxType {
|
|
||||||
STUDENT,
|
|
||||||
PARENT,
|
|
||||||
GUARDIAN,
|
|
||||||
EMPLOYEE,
|
|
||||||
UNKNOWN,
|
|
||||||
}
|
|
|
@ -4,31 +4,40 @@ 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
|
||||||
import java.time.Instant
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
@Entity(tableName = "Messages")
|
@Entity(tableName = "Messages")
|
||||||
data class Message(
|
data class Message(
|
||||||
|
|
||||||
@ColumnInfo(name = "message_global_key")
|
@ColumnInfo(name = "student_id")
|
||||||
val messageGlobalKey: String,
|
val studentId: Long,
|
||||||
|
|
||||||
@ColumnInfo(name = "mailbox_key")
|
@ColumnInfo(name = "real_id")
|
||||||
val mailboxKey: String,
|
val realId: Int,
|
||||||
|
|
||||||
@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,
|
||||||
|
|
||||||
val date: Instant,
|
val date: LocalDateTime,
|
||||||
|
|
||||||
@ColumnInfo(name = "folder_id")
|
@ColumnInfo(name = "folder_id")
|
||||||
val folderId: Int,
|
val folderId: Int,
|
||||||
|
|
||||||
var unread: Boolean,
|
var unread: Boolean,
|
||||||
|
|
||||||
|
val removed: Boolean,
|
||||||
|
|
||||||
@ColumnInfo(name = "has_attachments")
|
@ColumnInfo(name = "has_attachments")
|
||||||
val hasAttachments: Boolean
|
val hasAttachments: Boolean
|
||||||
) : Serializable {
|
) : Serializable {
|
||||||
|
@ -39,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>
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,12 +4,12 @@ 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
|
||||||
import java.time.Instant
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
@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")
|
||||||
|
@ -17,7 +17,7 @@ data class MobileDevice(
|
||||||
|
|
||||||
val name: String,
|
val name: String,
|
||||||
|
|
||||||
val date: Instant,
|
val date: LocalDateTime
|
||||||
) : Serializable {
|
) : Serializable {
|
||||||
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.entities
|
|
||||||
|
|
||||||
import androidx.room.ColumnInfo
|
|
||||||
import androidx.room.Entity
|
|
||||||
import androidx.room.PrimaryKey
|
|
||||||
import io.github.wulkanowy.services.sync.notifications.NotificationType
|
|
||||||
import io.github.wulkanowy.ui.modules.Destination
|
|
||||||
import java.time.Instant
|
|
||||||
|
|
||||||
@Entity(tableName = "Notifications")
|
|
||||||
data class Notification(
|
|
||||||
|
|
||||||
@ColumnInfo(name = "student_id")
|
|
||||||
val studentId: Long,
|
|
||||||
|
|
||||||
val title: String,
|
|
||||||
|
|
||||||
val content: String,
|
|
||||||
|
|
||||||
val type: NotificationType,
|
|
||||||
|
|
||||||
@ColumnInfo(defaultValue = "{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}")
|
|
||||||
val destination: Destination,
|
|
||||||
|
|
||||||
val date: Instant,
|
|
||||||
|
|
||||||
val data: String? = null
|
|
||||||
) {
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
|
||||||
var id: Long = 0
|
|
||||||
}
|
|
|
@ -1,22 +1,40 @@
|
||||||
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 com.squareup.moshi.JsonClass
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
@kotlinx.serialization.Serializable
|
@JsonClass(generateAdapter = true)
|
||||||
@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,
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,7 @@ import androidx.room.PrimaryKey
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
|
|
||||||
@Entity(
|
@Entity(tableName = "Semesters", indices = [Index(value = ["student_id", "diary_id", "semester_id"], unique = true)])
|
||||||
tableName = "Semesters", indices = [Index(
|
|
||||||
value = ["student_id", "diary_id", "kindergarten_diary_id", "semester_id"],
|
|
||||||
unique = true
|
|
||||||
)]
|
|
||||||
)
|
|
||||||
data class Semester(
|
data class Semester(
|
||||||
|
|
||||||
@ColumnInfo(name = "student_id")
|
@ColumnInfo(name = "student_id")
|
||||||
|
@ -21,9 +16,6 @@ data class Semester(
|
||||||
@ColumnInfo(name = "diary_id")
|
@ColumnInfo(name = "diary_id")
|
||||||
val diaryId: Int,
|
val diaryId: Int,
|
||||||
|
|
||||||
@ColumnInfo(name = "kindergarten_diary_id", defaultValue = "0")
|
|
||||||
val kindergartenDiaryId: Int,
|
|
||||||
|
|
||||||
@ColumnInfo(name = "diary_name")
|
@ColumnInfo(name = "diary_name")
|
||||||
val diaryName: String,
|
val diaryName: String,
|
||||||
|
|
||||||
|
@ -45,11 +37,12 @@ data class Semester(
|
||||||
|
|
||||||
@ColumnInfo(name = "unit_id")
|
@ColumnInfo(name = "unit_id")
|
||||||
val unitId: Int
|
val unitId: Int
|
||||||
) : Serializable {
|
): Serializable {
|
||||||
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
var id: Long = 0
|
var id: Long = 0
|
||||||
|
|
||||||
|
|
||||||
@ColumnInfo(name = "is_current")
|
@ColumnInfo(name = "is_current")
|
||||||
var current: Boolean = false
|
var current: Boolean = false
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import androidx.room.Entity
|
||||||
import androidx.room.Index
|
import androidx.room.Index
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.time.Instant
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
@Entity(
|
@Entity(
|
||||||
tableName = "Students",
|
tableName = "Students",
|
||||||
|
@ -74,7 +74,7 @@ data class Student(
|
||||||
val isCurrent: Boolean,
|
val isCurrent: Boolean,
|
||||||
|
|
||||||
@ColumnInfo(name = "registration_date")
|
@ColumnInfo(name = "registration_date")
|
||||||
val registrationDate: Instant,
|
val registrationDate: LocalDateTime
|
||||||
) : Serializable {
|
) : Serializable {
|
||||||
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
|
|
@ -4,8 +4,8 @@ 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
|
||||||
import java.time.Instant
|
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
@Entity(tableName = "Timetable")
|
@Entity(tableName = "Timetable")
|
||||||
data class Timetable(
|
data class Timetable(
|
||||||
|
@ -18,9 +18,9 @@ data class Timetable(
|
||||||
|
|
||||||
val number: Int,
|
val number: Int,
|
||||||
|
|
||||||
val start: Instant,
|
val start: LocalDateTime,
|
||||||
|
|
||||||
val end: Instant,
|
val end: LocalDateTime,
|
||||||
|
|
||||||
val date: LocalDate,
|
val date: LocalDate,
|
||||||
|
|
||||||
|
@ -50,7 +50,4 @@ data class Timetable(
|
||||||
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
var id: Long = 0
|
var id: Long = 0
|
||||||
|
|
||||||
@ColumnInfo(name = "is_notified")
|
|
||||||
var isNotified: Boolean = true
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,8 @@ 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
|
||||||
import java.time.Instant
|
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.util.*
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
@Entity(tableName = "TimetableAdditional")
|
@Entity(tableName = "TimetableAdditional")
|
||||||
data class TimetableAdditional(
|
data class TimetableAdditional(
|
||||||
|
@ -17,9 +16,9 @@ data class TimetableAdditional(
|
||||||
@ColumnInfo(name = "diary_id")
|
@ColumnInfo(name = "diary_id")
|
||||||
val diaryId: Int,
|
val diaryId: Int,
|
||||||
|
|
||||||
val start: Instant,
|
val start: LocalDateTime,
|
||||||
|
|
||||||
val end: Instant,
|
val end: LocalDateTime,
|
||||||
|
|
||||||
val date: LocalDate,
|
val date: LocalDate,
|
||||||
|
|
||||||
|
@ -28,10 +27,4 @@ data class TimetableAdditional(
|
||||||
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
var id: Long = 0
|
var id: Long = 0
|
||||||
|
|
||||||
@ColumnInfo(name = "repeat_id", defaultValue = "NULL")
|
|
||||||
var repeatId: UUID? = null
|
|
||||||
|
|
||||||
@ColumnInfo(name = "is_added_by_user", defaultValue = "0")
|
|
||||||
var isAddedByUser: Boolean = false
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,14 +43,12 @@ class Migration12 : Migration(11, 12) {
|
||||||
|
|
||||||
private fun getStudentsIds(database: SupportSQLiteDatabase): List<Int> {
|
private fun getStudentsIds(database: SupportSQLiteDatabase): List<Int> {
|
||||||
val students = mutableListOf<Int>()
|
val students = mutableListOf<Int>()
|
||||||
database.query("SELECT student_id FROM Students").use {
|
val studentsCursor = database.query("SELECT student_id FROM Students")
|
||||||
if (it.moveToFirst()) {
|
if (studentsCursor.moveToFirst()) {
|
||||||
do {
|
do {
|
||||||
students.add(it.getInt(0))
|
students.add(studentsCursor.getInt(0))
|
||||||
} while (it.moveToNext())
|
} while (studentsCursor.moveToNext())
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return students
|
return students
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,14 +25,12 @@ class Migration13 : Migration(12, 13) {
|
||||||
|
|
||||||
private fun getStudentsIds(database: SupportSQLiteDatabase): MutableList<Pair<Int, String>> {
|
private fun getStudentsIds(database: SupportSQLiteDatabase): MutableList<Pair<Int, String>> {
|
||||||
val students = mutableListOf<Pair<Int, String>>()
|
val students = mutableListOf<Pair<Int, String>>()
|
||||||
database.query("SELECT id, school_name FROM Students").use {
|
val studentsCursor = database.query("SELECT id, school_name FROM Students")
|
||||||
if (it.moveToFirst()) {
|
if (studentsCursor.moveToFirst()) {
|
||||||
do {
|
do {
|
||||||
students.add(it.getInt(0) to it.getString(1))
|
students.add(studentsCursor.getInt(0) to studentsCursor.getString(1))
|
||||||
} while (it.moveToNext())
|
} while (studentsCursor.moveToNext())
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return students
|
return students
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,14 +42,12 @@ class Migration13 : Migration(12, 13) {
|
||||||
|
|
||||||
private fun getStudentsAndClassIds(database: SupportSQLiteDatabase): List<Pair<Int, Int>> {
|
private fun getStudentsAndClassIds(database: SupportSQLiteDatabase): List<Pair<Int, Int>> {
|
||||||
val students = mutableListOf<Pair<Int, Int>>()
|
val students = mutableListOf<Pair<Int, Int>>()
|
||||||
database.query("SELECT student_id, class_id FROM Students").use {
|
val studentsCursor = database.query("SELECT student_id, class_id FROM Students")
|
||||||
if (it.moveToFirst()) {
|
if (studentsCursor.moveToFirst()) {
|
||||||
do {
|
do {
|
||||||
students.add(it.getInt(0) to it.getInt(1))
|
students.add(studentsCursor.getInt(0) to studentsCursor.getInt(1))
|
||||||
} while (it.moveToNext())
|
} while (studentsCursor.moveToNext())
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return students
|
return students
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,28 +22,24 @@ class Migration27 : Migration(26, 27) {
|
||||||
|
|
||||||
private fun getStudentsIdsAndNames(database: SupportSQLiteDatabase): MutableList<Triple<Long, Int, String>> {
|
private fun getStudentsIdsAndNames(database: SupportSQLiteDatabase): MutableList<Triple<Long, Int, String>> {
|
||||||
val students = mutableListOf<Triple<Long, Int, String>>()
|
val students = mutableListOf<Triple<Long, Int, String>>()
|
||||||
database.query("SELECT id, user_login_id, student_name FROM Students").use {
|
val studentsCursor = database.query("SELECT id, user_login_id, student_name FROM Students")
|
||||||
if (it.moveToFirst()) {
|
if (studentsCursor.moveToFirst()) {
|
||||||
do {
|
do {
|
||||||
students.add(Triple(it.getLong(0), it.getInt(1), it.getString(2)))
|
students.add(Triple(studentsCursor.getLong(0), studentsCursor.getInt(1), studentsCursor.getString(2)))
|
||||||
} while (it.moveToNext())
|
} while (studentsCursor.moveToNext())
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return students
|
return students
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getReportingUnits(database: SupportSQLiteDatabase): MutableList<Pair<Int, String>> {
|
private fun getReportingUnits(database: SupportSQLiteDatabase): MutableList<Pair<Int, String>> {
|
||||||
val units = mutableListOf<Pair<Int, String>>()
|
val units = mutableListOf<Pair<Int, String>>()
|
||||||
database.query("SELECT sender_id, sender_name FROM ReportingUnits").use {
|
val unitsCursor = database.query("SELECT sender_id, sender_name FROM ReportingUnits")
|
||||||
if (it.moveToFirst()) {
|
if (unitsCursor.moveToFirst()) {
|
||||||
do {
|
do {
|
||||||
units.add(it.getInt(0) to it.getString(1))
|
units.add(unitsCursor.getInt(0) to unitsCursor.getString(1))
|
||||||
} while (it.moveToNext())
|
} while (unitsCursor.moveToNext())
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return units
|
return units
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,17 +10,15 @@ class Migration35(private val appInfo: AppInfo) : Migration(34, 35) {
|
||||||
override fun migrate(database: SupportSQLiteDatabase) {
|
override fun migrate(database: SupportSQLiteDatabase) {
|
||||||
database.execSQL("ALTER TABLE Students ADD COLUMN `avatar_color` INTEGER NOT NULL DEFAULT 0")
|
database.execSQL("ALTER TABLE Students ADD COLUMN `avatar_color` INTEGER NOT NULL DEFAULT 0")
|
||||||
|
|
||||||
database.query("SELECT * FROM Students").use {
|
val studentsCursor = database.query("SELECT * FROM Students")
|
||||||
while (it.moveToNext()) {
|
|
||||||
val studentId = it.getLongOrNull(0)
|
while (studentsCursor.moveToNext()) {
|
||||||
database.execSQL(
|
val studentId = studentsCursor.getLongOrNull(0)
|
||||||
"""
|
database.execSQL(
|
||||||
UPDATE Students
|
"""UPDATE Students
|
||||||
SET avatar_color = ${appInfo.defaultColorsForAvatar.random()}
|
SET avatar_color = ${appInfo.defaultColorsForAvatar.random()}
|
||||||
WHERE id = $studentId
|
WHERE id = $studentId"""
|
||||||
"""
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.migrations
|
|
||||||
|
|
||||||
import androidx.room.migration.Migration
|
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
|
||||||
|
|
||||||
class Migration40 : Migration(39, 40) {
|
|
||||||
|
|
||||||
override fun migrate(database: SupportSQLiteDatabase) {
|
|
||||||
database.execSQL(
|
|
||||||
"""
|
|
||||||
CREATE TABLE IF NOT EXISTS `Notifications` (
|
|
||||||
`student_id` INTEGER NOT NULL,
|
|
||||||
`title` TEXT NOT NULL,
|
|
||||||
`content` TEXT NOT NULL,
|
|
||||||
`type` TEXT NOT NULL,
|
|
||||||
`date` INTEGER NOT NULL,
|
|
||||||
`data` TEXT,
|
|
||||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL
|
|
||||||
)
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.migrations
|
|
||||||
|
|
||||||
import androidx.room.migration.Migration
|
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
|
||||||
import io.github.wulkanowy.data.db.SharedPrefProvider
|
|
||||||
import io.github.wulkanowy.data.enums.GradeExpandMode
|
|
||||||
|
|
||||||
class Migration41(private val sharedPrefProvider: SharedPrefProvider) : Migration(40, 41) {
|
|
||||||
|
|
||||||
override fun migrate(database: SupportSQLiteDatabase) {
|
|
||||||
migrateSharedPreferences()
|
|
||||||
database.execSQL("ALTER TABLE Homework ADD COLUMN is_added_by_user INTEGER NOT NULL DEFAULT 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun migrateSharedPreferences() {
|
|
||||||
if (sharedPrefProvider.getBoolean("pref_key_expand_grade", false)) {
|
|
||||||
sharedPrefProvider.putString("pref_key_expand_grade_mode", GradeExpandMode.ALWAYS_EXPANDED.value)
|
|
||||||
}
|
|
||||||
sharedPrefProvider.delete("pref_key_expand_grade")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.migrations
|
|
||||||
|
|
||||||
import androidx.room.migration.Migration
|
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
|
||||||
|
|
||||||
class Migration42 : Migration(41, 42) {
|
|
||||||
|
|
||||||
override fun migrate(database: SupportSQLiteDatabase) {
|
|
||||||
database.execSQL(
|
|
||||||
"""CREATE TABLE IF NOT EXISTS `AdminMessages` (
|
|
||||||
`id` INTEGER NOT NULL,
|
|
||||||
`title` TEXT NOT NULL,
|
|
||||||
`content` TEXT NOT NULL,
|
|
||||||
`version_name` INTEGER,
|
|
||||||
`version_max` INTEGER,
|
|
||||||
`target_register_host` TEXT,
|
|
||||||
`target_flavor` TEXT,
|
|
||||||
`destination_url` TEXT,
|
|
||||||
`priority` TEXT NOT NULL,
|
|
||||||
`type` TEXT NOT NULL,
|
|
||||||
PRIMARY KEY(`id`))"""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.migrations
|
|
||||||
|
|
||||||
import androidx.room.migration.Migration
|
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
|
||||||
|
|
||||||
class Migration43 : Migration(42, 43) {
|
|
||||||
|
|
||||||
override fun migrate(database: SupportSQLiteDatabase) {
|
|
||||||
database.execSQL("ALTER TABLE Timetable ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1")
|
|
||||||
database.execSQL("ALTER TABLE Attendance ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.migrations
|
|
||||||
|
|
||||||
import androidx.room.migration.Migration
|
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
|
||||||
|
|
||||||
class Migration44 : Migration(43, 44) {
|
|
||||||
|
|
||||||
override fun migrate(database: SupportSQLiteDatabase) {
|
|
||||||
database.execSQL("ALTER TABLE AdminMessages ADD COLUMN is_dismissible INTEGER NOT NULL DEFAULT 0")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,102 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.migrations
|
|
||||||
|
|
||||||
import androidx.room.migration.Migration
|
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
|
||||||
import java.time.Instant
|
|
||||||
import java.time.ZoneId
|
|
||||||
import java.time.ZoneOffset
|
|
||||||
|
|
||||||
class Migration46 : Migration(45, 46) {
|
|
||||||
|
|
||||||
override fun migrate(database: SupportSQLiteDatabase) {
|
|
||||||
migrateConferences(database)
|
|
||||||
migrateMessages(database)
|
|
||||||
migrateMobileDevices(database)
|
|
||||||
migrateNotifications(database)
|
|
||||||
migrateTimetable(database)
|
|
||||||
migrateTimetableAdditional(database)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun migrateConferences(database: SupportSQLiteDatabase) {
|
|
||||||
database.query("SELECT * FROM Conferences").use {
|
|
||||||
while (it.moveToNext()) {
|
|
||||||
val id = it.getLong(it.getColumnIndexOrThrow("id"))
|
|
||||||
val timestampLocal = it.getLong(it.getColumnIndexOrThrow("date"))
|
|
||||||
val timestampUtc = timestampLocal.timestampLocalToUTC()
|
|
||||||
|
|
||||||
database.execSQL("UPDATE Conferences SET date = $timestampUtc WHERE id = $id")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun migrateMessages(database: SupportSQLiteDatabase) {
|
|
||||||
database.query("SELECT * FROM Messages").use {
|
|
||||||
while (it.moveToNext()) {
|
|
||||||
val id = it.getLong(it.getColumnIndexOrThrow("id"))
|
|
||||||
val timestampLocal = it.getLong(it.getColumnIndexOrThrow("date"))
|
|
||||||
val timestampUtc = timestampLocal.timestampLocalToUTC()
|
|
||||||
|
|
||||||
database.execSQL("UPDATE Messages SET date = $timestampUtc WHERE id = $id")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun migrateMobileDevices(database: SupportSQLiteDatabase) {
|
|
||||||
database.query("SELECT * FROM MobileDevices").use {
|
|
||||||
while (it.moveToNext()) {
|
|
||||||
val id = it.getLong(it.getColumnIndexOrThrow("id"))
|
|
||||||
val timestampLocal = it.getLong(it.getColumnIndexOrThrow("date"))
|
|
||||||
val timestampUtc = timestampLocal.timestampLocalToUTC()
|
|
||||||
|
|
||||||
database.execSQL("UPDATE MobileDevices SET date = $timestampUtc WHERE id = $id")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun migrateNotifications(database: SupportSQLiteDatabase) {
|
|
||||||
database.query("SELECT * FROM Notifications").use {
|
|
||||||
while (it.moveToNext()) {
|
|
||||||
val id = it.getLong(it.getColumnIndexOrThrow("id"))
|
|
||||||
val timestampLocal = it.getLong(it.getColumnIndexOrThrow("date"))
|
|
||||||
val timestampUtc = timestampLocal.timestampLocalToUTC()
|
|
||||||
|
|
||||||
database.execSQL("UPDATE Notifications SET date = $timestampUtc WHERE id = $id")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun migrateTimetable(database: SupportSQLiteDatabase) {
|
|
||||||
database.query("SELECT * FROM Timetable").use {
|
|
||||||
while (it.moveToNext()) {
|
|
||||||
val id = it.getLong(it.getColumnIndexOrThrow("id"))
|
|
||||||
val timestampLocalStart = it.getLong(it.getColumnIndexOrThrow("start"))
|
|
||||||
val timestampLocalEnd = it.getLong(it.getColumnIndexOrThrow("end"))
|
|
||||||
val timestampUtcStart = timestampLocalStart.timestampLocalToUTC()
|
|
||||||
val timestampUtcEnd = timestampLocalEnd.timestampLocalToUTC()
|
|
||||||
|
|
||||||
database.execSQL("UPDATE Timetable SET start = $timestampUtcStart, end = $timestampUtcEnd WHERE id = $id")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun migrateTimetableAdditional(database: SupportSQLiteDatabase) {
|
|
||||||
database.query("SELECT * FROM TimetableAdditional").use {
|
|
||||||
while (it.moveToNext()) {
|
|
||||||
val id = it.getLong(it.getColumnIndexOrThrow("id"))
|
|
||||||
val timestampLocalStart = it.getLong(it.getColumnIndexOrThrow("start"))
|
|
||||||
val timestampLocalEnd = it.getLong(it.getColumnIndexOrThrow("end"))
|
|
||||||
val timestampUtcStart = timestampLocalStart.timestampLocalToUTC()
|
|
||||||
val timestampUtcEnd = timestampLocalEnd.timestampLocalToUTC()
|
|
||||||
|
|
||||||
database.execSQL("UPDATE TimetableAdditional SET start = $timestampUtcStart, end = $timestampUtcEnd WHERE id = $id")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Long.timestampLocalToUTC(): Long = Instant.ofEpochMilli(this)
|
|
||||||
.atZone(ZoneOffset.UTC)
|
|
||||||
.withZoneSameLocal(ZoneId.of("Europe/Warsaw"))
|
|
||||||
.withZoneSameInstant(ZoneId.systemDefault())
|
|
||||||
.toInstant()
|
|
||||||
.toEpochMilli()
|
|
||||||
}
|
|
|
@ -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,12 +0,0 @@
|
||||||
package io.github.wulkanowy.data.enums
|
|
||||||
|
|
||||||
enum class AppTheme(val value: String) {
|
|
||||||
SYSTEM("system"),
|
|
||||||
LIGHT("light"),
|
|
||||||
DARK("dark"),
|
|
||||||
BLACK("black");
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun getByValue(value: String) = values().find { it.value == value } ?: LIGHT
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
package io.github.wulkanowy.data.enums
|
|
||||||
|
|
||||||
import java.io.Serializable
|
|
||||||
|
|
||||||
enum class GradeColorTheme(val value: String) : Serializable {
|
|
||||||
VULCAN("vulcan"),
|
|
||||||
MATERIAL("material"),
|
|
||||||
GRADE_COLOR("grade_color");
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun getByValue(value: String) = values().find { it.value == value } ?: VULCAN
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
package io.github.wulkanowy.data.enums
|
|
||||||
|
|
||||||
enum class GradeExpandMode(val value: String) {
|
|
||||||
ONE("one"),
|
|
||||||
UNLIMITED("any"),
|
|
||||||
ALWAYS_EXPANDED("always");
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun getByValue(value: String) = values().find { it.value == value } ?: ONE
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
package io.github.wulkanowy.data.enums
|
|
||||||
|
|
||||||
enum class GradeSortingMode(val value: String) {
|
|
||||||
ALPHABETIC("alphabetic"),
|
|
||||||
DATE("date"),
|
|
||||||
AVERAGE("average");
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun getByValue(value: String) = values().find { it.value == value } ?: ALPHABETIC
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
package io.github.wulkanowy.data.enums
|
|
||||||
|
|
||||||
enum class TimetableMode(val value: String) {
|
|
||||||
WHOLE_PLAN("yes"),
|
|
||||||
ONLY_CURRENT_GROUP("no"),
|
|
||||||
SMALL_OTHER_GROUP("small");
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun getByValue(value: String) = values().find { it.value == value } ?: ONLY_CURRENT_GROUP
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -10,7 +10,7 @@ fun List<SdkConference>.mapToEntities(semester: Semester) = map {
|
||||||
diaryId = semester.diaryId,
|
diaryId = semester.diaryId,
|
||||||
agenda = it.agenda,
|
agenda = it.agenda,
|
||||||
conferenceId = it.id,
|
conferenceId = it.id,
|
||||||
date = it.dateZoned.toInstant(),
|
date = it.date,
|
||||||
presentOnConference = it.presentOnConference,
|
presentOnConference = it.presentOnConference,
|
||||||
subject = it.subject,
|
subject = it.subject,
|
||||||
title = it.title
|
title = it.title
|
||||||
|
|
|
@ -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.studentId,
|
||||||
date = it.date,
|
date = it.date,
|
||||||
subject = it.subject,
|
subject = it.subject,
|
||||||
content = it.content,
|
content = it.content,
|
||||||
|
|
|
@ -1,18 +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,
|
|
||||||
userLoginId = student.userLoginId,
|
|
||||||
studentName = it.studentName,
|
|
||||||
schoolNameShort = it.schoolNameShort,
|
|
||||||
type = MailboxType.valueOf(it.type.name),
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,31 +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 io.github.wulkanowy.data.db.entities.Recipient
|
||||||
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import java.time.LocalDateTime
|
||||||
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(mailbox: Mailbox) = map {
|
fun List<SdkMessage>.mapToEntities(student: Student) = map {
|
||||||
Message(
|
Message(
|
||||||
messageGlobalKey = it.globalKey,
|
studentId = student.id,
|
||||||
mailboxKey = mailbox.globalKey,
|
realId = it.id ?: 0,
|
||||||
messageId = it.id,
|
messageId = it.messageId ?: 0,
|
||||||
correspondents = it.correspondents,
|
sender = it.sender?.name.orEmpty(),
|
||||||
|
senderId = it.sender?.loginId ?: 0,
|
||||||
|
recipient = it.recipients.singleOrNull()?.name ?: "Wielu adresatów",
|
||||||
subject = it.subject.trim(),
|
subject = it.subject.trim(),
|
||||||
date = it.dateZoned.toInstant(),
|
date = it.date ?: LocalDateTime.now(),
|
||||||
folderId = it.folderId,
|
folderId = it.folderId,
|
||||||
unread = it.unread,
|
unread = it.unread ?: false,
|
||||||
|
removed = it.removed,
|
||||||
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
|
||||||
)
|
)
|
||||||
|
@ -33,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,15 +1,15 @@
|
||||||
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.Token as SdkToken
|
import io.github.wulkanowy.sdk.pojo.Token as SdkToken
|
||||||
|
import io.github.wulkanowy.sdk.pojo.Device as SdkDevice
|
||||||
|
|
||||||
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.createDate,
|
||||||
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
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
)
|
||||||
|
}
|
|
@ -7,7 +7,6 @@ fun List<SdkSemester>.mapToEntities(studentId: Int) = map {
|
||||||
Semester(
|
Semester(
|
||||||
studentId = studentId,
|
studentId = studentId,
|
||||||
diaryId = it.diaryId,
|
diaryId = it.diaryId,
|
||||||
kindergartenDiaryId = it.kindergartenDiaryId,
|
|
||||||
diaryName = it.diaryName,
|
diaryName = it.diaryName,
|
||||||
schoolYear = it.schoolYear,
|
schoolYear = it.schoolYear,
|
||||||
semesterId = it.semesterId,
|
semesterId = it.semesterId,
|
||||||
|
|
|
@ -2,7 +2,7 @@ package io.github.wulkanowy.data.mappers
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||||
import java.time.Instant
|
import java.time.LocalDateTime
|
||||||
import io.github.wulkanowy.sdk.pojo.Student as SdkStudent
|
import io.github.wulkanowy.sdk.pojo.Student as SdkStudent
|
||||||
|
|
||||||
fun List<SdkStudent>.mapToEntities(password: String = "", colors: List<Long>) = map {
|
fun List<SdkStudent>.mapToEntities(password: String = "", colors: List<Long>) = map {
|
||||||
|
@ -24,7 +24,7 @@ fun List<SdkStudent>.mapToEntities(password: String = "", colors: List<Long>) =
|
||||||
scrapperBaseUrl = it.scrapperBaseUrl,
|
scrapperBaseUrl = it.scrapperBaseUrl,
|
||||||
loginType = it.loginType.name,
|
loginType = it.loginType.name,
|
||||||
isCurrent = false,
|
isCurrent = false,
|
||||||
registrationDate = Instant.now(),
|
registrationDate = LocalDateTime.now(),
|
||||||
mobileBaseUrl = it.mobileBaseUrl,
|
mobileBaseUrl = it.mobileBaseUrl,
|
||||||
privateKey = it.privateKey,
|
privateKey = it.privateKey,
|
||||||
certificateKey = it.certificateKey,
|
certificateKey = it.certificateKey,
|
||||||
|
|
|
@ -21,8 +21,8 @@ fun List<SdkTimetable>.mapToEntities(semester: Semester) = map {
|
||||||
studentId = semester.studentId,
|
studentId = semester.studentId,
|
||||||
diaryId = semester.diaryId,
|
diaryId = semester.diaryId,
|
||||||
number = it.number,
|
number = it.number,
|
||||||
start = it.startZoned.toInstant(),
|
start = it.start,
|
||||||
end = it.endZoned.toInstant(),
|
end = it.end,
|
||||||
date = it.date,
|
date = it.date,
|
||||||
subject = it.subject,
|
subject = it.subject,
|
||||||
subjectOld = it.subjectOld,
|
subjectOld = it.subjectOld,
|
||||||
|
@ -45,8 +45,8 @@ fun List<SdkTimetableAdditional>.mapToEntities(semester: Semester) = map {
|
||||||
diaryId = semester.diaryId,
|
diaryId = semester.diaryId,
|
||||||
subject = it.subject,
|
subject = it.subject,
|
||||||
date = it.date,
|
date = it.date,
|
||||||
start = it.startZoned.toInstant(),
|
start = it.start,
|
||||||
end = it.endZoned.toInstant(),
|
end = it.end
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.github.wulkanowy.data.pojos
|
package io.github.wulkanowy.data.pojos
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
||||||
@Serializable
|
@JsonClass(generateAdapter = true)
|
||||||
class Contributor(
|
class Contributor(
|
||||||
val displayName: String,
|
val displayName: String,
|
||||||
val githubUsername: String
|
val githubUsername: String
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue