forked from github/wulkanowy-mirror
Compare commits
496 Commits
Author | SHA1 | Date | |
---|---|---|---|
4bce35f810 | |||
2d83218f61 | |||
d3e276d6fc | |||
51a1097bb4 | |||
db4f172fb8 | |||
4d49e956b8 | |||
b8296ac02f | |||
d6385e8cdd | |||
885319a885 | |||
fded5007c1 | |||
66ff14f719 | |||
1257dc63d3 | |||
50b6d380b6 | |||
62b7d42a73 | |||
21fe209246 | |||
02cd4e4e06 | |||
86fe2b61cb | |||
4113bd9b53 | |||
d924902dac | |||
b269360ecb | |||
ffd5addadb | |||
c5e2b18695 | |||
515a3973b7 | |||
7bee10d5ce | |||
22a4f509dc | |||
3925a6261b | |||
49b383fbe5 | |||
4a484dc2ce | |||
a14c4b489b | |||
e91cd18804 | |||
4c24363599 | |||
e20c232f8f | |||
1f11eea9b5 | |||
42f9a00e8c | |||
ad487e680c | |||
3f431022a5 | |||
cd037f0ce0 | |||
37f7f21a03 | |||
c653039590 | |||
95a90a7a79 | |||
4dc80595ac | |||
8114a2376e | |||
a523850216 | |||
354f51dd70 | |||
b271c12ebc | |||
8ca41b5ba3 | |||
edbe45332a | |||
1bbd249275 | |||
5148ff291b | |||
a1dc00af42 | |||
f1db993fee | |||
4f0519552e | |||
3625c5c518 | |||
afbfb9761f | |||
a5c636853a | |||
d5d45ed1ba | |||
d3f869c6c2 | |||
46c29c438e | |||
73a7255d3a | |||
c7af85e0e1 | |||
afc16e3d17 | |||
59f6f5c212 | |||
86f8763e69 | |||
157becb017 | |||
83ca9a7060 | |||
1033be4503 | |||
e67066f3ae | |||
bc22808b0e | |||
e05abb3539 | |||
6153c7b97d | |||
e574e5e2ec | |||
e6571a1dfc | |||
d566de0282 | |||
558db061f5 | |||
190f40ede8 | |||
4b795d6ef5 | |||
d139bd5b14 | |||
bf34cb0c1e | |||
eed091aad2 | |||
535206056d | |||
f2cb3b4f9e | |||
54372e0a55 | |||
5c17c38d1d | |||
f68a8e4215 | |||
70c2cb7dbf | |||
7f6fd60821 | |||
62c04fb205 | |||
10c36f19bf | |||
37d756b8fe | |||
de1bc4809f | |||
3d6ec93cde | |||
c293c76398 | |||
09e07a1713 | |||
71f1a55437 | |||
d9e22af5ef | |||
bc0689a30d | |||
9d47127921 | |||
08a3bd77bd | |||
9fe1151a04 | |||
793952cb44 | |||
d64a21b50c | |||
274f9dde07 | |||
5a884a4c56 | |||
c55fd98179 | |||
ffc0cd840b | |||
96067946d0 | |||
9339e7d916 | |||
b4117aa62e | |||
dc3a941e24 | |||
b67ecbba4b | |||
1175740ba2 | |||
378ed0100f | |||
cf87339ac4 | |||
c23a90f104 | |||
d337be0f40 | |||
cf7c6f78ea | |||
efa68f5044 | |||
b9be85d99c | |||
dfc4553fc6 | |||
08c9539abe | |||
fd18583df2 | |||
7c4f1c7b22 | |||
bdb6c962ea | |||
f1c217b087 | |||
4b6277abf5 | |||
344e0d55ff | |||
89a6a98bbf | |||
fcc7dc0913 | |||
1b74bffc06 | |||
0f11f14c3e | |||
e70fe6f097 | |||
b70649f136 | |||
7b13684137 | |||
c4689fcbb3 | |||
d8f644c5b4 | |||
c808bf2e61 | |||
0fb55bd6c6 | |||
c5dfea788c | |||
120e5c9171 | |||
a97039a727 | |||
e9ba65f8f6 | |||
a264abf814 | |||
0a2eb07844 | |||
bfab265ccf | |||
cd59166efb | |||
06ed5f6079 | |||
6b70583573 | |||
c3cbaa6ac2 | |||
f61d820d6f | |||
03ad5527f8 | |||
cce736410b | |||
8c515bd03f | |||
8dcb3ed45d | |||
4f3f24ac10 | |||
d074e5c9b3 | |||
d2d1d1dba7 | |||
891e241d1a | |||
5c4a3d578b | |||
fcf0adfd80 | |||
c42a47ac48 | |||
fa48b033af | |||
808927a58a | |||
dc717c9fb5 | |||
a2804d813a | |||
847ab6149a | |||
dc74d2877b | |||
6534176685 | |||
9542b9f231 | |||
dbba61a99f | |||
c2496a15b8 | |||
facf84d9a8 | |||
459c8330f9 | |||
0c8e2632a2 | |||
b17e9deca0 | |||
c296e72c30 | |||
637125e1fc | |||
445bfda801 | |||
ebde42328a | |||
a0bf14b576 | |||
2e7caabde3 | |||
bb052fd4c9 | |||
28ef8c6761 | |||
15e8e096ed | |||
6007de017f | |||
775b5122ef | |||
fed00122d7 | |||
426bee882c | |||
d37de197fc | |||
447ece3696 | |||
a73f39e59c | |||
f912aac140 | |||
3caabd3e0e | |||
88576271e2 | |||
b088551005 | |||
130e11a629 | |||
d5e0ae7b37 | |||
e6f56a74a4 | |||
1bc59cfa7f | |||
41bae262a5 | |||
ae65228805 | |||
391ee6e621 | |||
0a87df3d82 | |||
cb4ae21903 | |||
679cf2554d | |||
d473d53879 | |||
6531061b48 | |||
3347e8fba8 | |||
84067126a1 | |||
da9bebe923 | |||
b371fd6709 | |||
884d443c5b | |||
df58aa78ae | |||
2131e892ad | |||
63380d3e12 | |||
c572a91b38 | |||
20dde6e896 | |||
042b66ca5c | |||
8d8990761a | |||
a07741b5c5 | |||
f851a4d2c5 | |||
c8d069c787 | |||
5ce30a3000 | |||
26e0f43fa0 | |||
08c1bedca1 | |||
15537586c4 | |||
a04ba4ae10 | |||
57ea6379ab | |||
c3abe50ed4 | |||
f48caf9f70 | |||
9a413c14c3 | |||
8915c5dd8e | |||
e7561d4794 | |||
820b99dbc7 | |||
aff0fb3a60 | |||
d3bf5c3e0a | |||
dec2703cc7 | |||
edd1c9442e | |||
18568c86be | |||
84d0ba525f | |||
6290663f02 | |||
be046a1ddd | |||
96ee4bd9e5 | |||
923af85d18 | |||
ce36e86bb2 | |||
a4f455b38f | |||
01b8bd9d4a | |||
cfcc051ce4 | |||
0b0993be9a | |||
d07b0dbc98 | |||
daa7b54dab | |||
de9fcb9af9 | |||
40e0934504 | |||
009ec433be | |||
e1d82d70ee | |||
7a9ba04ff4 | |||
513b4b7d3e | |||
ce4157933f | |||
5d1085a64a | |||
a00f2dcbda | |||
b52a6f7f61 | |||
5146e44574 | |||
90e1cea679 | |||
c9b506ae10 | |||
14ebdad7b2 | |||
210308695b | |||
d5cc2263f5 | |||
47e3f2dc58 | |||
6dc16b288d | |||
daf97be9ad | |||
2bb2190410 | |||
aff1a7030d | |||
8877322357 | |||
bc672e94f8 | |||
a03bcf8e62 | |||
20673c4ead | |||
5321d00ee9 | |||
e6b2acabd5 | |||
bfd7f688ab | |||
ba02531aa4 | |||
210c3a0e28 | |||
68f0ecc45c | |||
0965d03f1a | |||
496641f594 | |||
684c258e2d | |||
5e96917508 | |||
17096ad11b | |||
bd883c9f38 | |||
6520f8a0d7 | |||
2eee50ad81 | |||
8560fd7e81 | |||
f718147ae9 | |||
cd12c4c891 | |||
65f114ce05 | |||
497083be97 | |||
e26860ea5a | |||
094df212b4 | |||
cc22985dc5 | |||
ad9a2711c4 | |||
daf44c531c | |||
4e12eb1552 | |||
c846cc999f | |||
47d430292c | |||
5e1ff2243f | |||
a35bef58f2 | |||
0005d84974 | |||
19558cb871 | |||
45e884127f | |||
c87085a226 | |||
79b970256f | |||
70f038f15f | |||
9cabd7ef08 | |||
d89e4ccfdf | |||
1bcc4d199e | |||
2e85e88c5d | |||
6ab67fe25b | |||
8563277a89 | |||
e458cc90b0 | |||
651e3a21b9 | |||
f6b969cfb1 | |||
d2aa940d46 | |||
ab435a72ea | |||
a56f4b8745 | |||
d003b0897c | |||
581bb2de77 | |||
495e385228 | |||
10ba36ba44 | |||
eae396424f | |||
a7891bb266 | |||
6e82409dbc | |||
984db18be3 | |||
c99bc96c08 | |||
3e7030abc2 | |||
6dad3b299b | |||
5e997f5a3e | |||
601d573283 | |||
6ae6ca7fbb | |||
c3d38afc3d | |||
4e19964249 | |||
a6c0efcb81 | |||
fcc71c0d5f | |||
a59d10b6c1 | |||
a48e4eb4ee | |||
2a3668bb18 | |||
804d0d9113 | |||
88b893e6c0 | |||
2874a7495e | |||
40d8f7a93d | |||
84cd51205f | |||
bac1832f27 | |||
8bf1e22407 | |||
e9f43f925c | |||
aa632edf5c | |||
57315d75c6 | |||
4552bc85b0 | |||
6b7795118c | |||
1960782d8e | |||
8836be3766 | |||
8697993149 | |||
b88c7eb4e4 | |||
9066bce0d5 | |||
f15b90782a | |||
0642bf7d73 | |||
981d6d559c | |||
39327ff3ea | |||
b098ac029b | |||
7e0e2fbb67 | |||
8a181c747c | |||
68fdb167c2 | |||
17563d1a4b | |||
370881104e | |||
62b1b18326 | |||
214e43bd4b | |||
358e0850ad | |||
c183428107 | |||
6de937703a | |||
10cb2b70f1 | |||
9230db3f99 | |||
66e58ab74e | |||
99b7af64c0 | |||
4295dd6246 | |||
fb2d92c749 | |||
07b1969a35 | |||
886403bf1e | |||
e8b21c1429 | |||
007d62e61d | |||
f88d44f0ec | |||
4401df6203 | |||
e6f23ab35b | |||
eea20ced57 | |||
b7134221cb | |||
8be605629a | |||
1a3d580116 | |||
a62ed54d07 | |||
36a570eeb0 | |||
8ed8b5a33c | |||
26c749c219 | |||
1d910f8d66 | |||
de11644e9b | |||
621db49fbf | |||
b593795844 | |||
0f800b61f6 | |||
94fd303f8e | |||
09a134d442 | |||
58ea2c530e | |||
84e4167dbd | |||
54e9ea6478 | |||
4c8d9c8f7f | |||
e7550f7a43 | |||
ac86737050 | |||
e3122127c0 | |||
d6918077bf | |||
9d0366d010 | |||
3d0cd11ba4 | |||
64dbbd54b4 | |||
539be586ce | |||
a240fd5d5f | |||
4e69cfe23c | |||
2ab0a57a41 | |||
ebf9e741c2 | |||
e8075e30e4 | |||
1839d7cb8f | |||
2d84b0775a | |||
426379ec17 | |||
8315759c83 | |||
04393e60bb | |||
031a17ea50 | |||
60501fcd72 | |||
8e607d48f7 | |||
e02d93f979 | |||
76514e2d72 | |||
689012131f | |||
6cdcf92782 | |||
9c8bcbfdd3 | |||
0b83a66b85 | |||
9711cc868c | |||
f8cb7599e6 | |||
7636618e23 | |||
5bc54c12f1 | |||
e10e530dee | |||
d69118b085 | |||
dc90549b9d | |||
b552dbc904 | |||
a6a1678b47 | |||
7a46ef5f19 | |||
f9e0f7b390 | |||
9211baf7ec | |||
de6131f4f5 | |||
2cb11e443c | |||
a43ffcdef4 | |||
6615e68430 | |||
36daa7ccc1 | |||
6e5481f345 | |||
ba1c14ca0e | |||
c69bb2ef71 | |||
9cb4754132 | |||
5ba8289c87 | |||
258782c648 | |||
c568bc1515 | |||
da668f93cf | |||
037dbd792f | |||
7ec7afed87 | |||
bea50e6db5 | |||
6a00e75816 | |||
957adaf6ee | |||
827fb33eeb | |||
19c96ee83f | |||
5a7f52c773 | |||
dddeff802f | |||
91f6310892 | |||
0389642543 | |||
8528e0beff | |||
e665a8f18b | |||
6d5acbad2c | |||
7217d0f753 | |||
16a5d88dfb | |||
646a46727f | |||
f5e9197f98 | |||
b47f26684b | |||
3a03b5f1c6 | |||
3d0dcead50 | |||
b64b41c11c | |||
77c5330f91 | |||
2b55ec02ff | |||
49ebae6e63 | |||
44a9db48a6 | |||
0008a72be1 | |||
a43acaaa07 | |||
e6c9abb4e5 | |||
3b9451184c | |||
45d1727dbe | |||
8d7b611c44 | |||
c3adb9b6d6 | |||
d87283eb31 | |||
d139c22782 | |||
e557021ad9 | |||
37af5de25c |
12
.editorconfig
Normal file
12
.editorconfig
Normal file
@ -0,0 +1,12 @@
|
||||
[*]
|
||||
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 to app stores
|
||||
name: Deploy release
|
||||
|
||||
on:
|
||||
release:
|
||||
@ -7,16 +7,17 @@ on:
|
||||
jobs:
|
||||
|
||||
deploy-google-play:
|
||||
name: Deploy to google play
|
||||
name: Google Play
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
environment: google-play
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-java@v1
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 11
|
||||
- uses: actions/cache@v2
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
@ -28,27 +29,31 @@ jobs:
|
||||
SERVICES_ENCRYPT_KEY: ${{ secrets.SERVICES_ENCRYPT_KEY }}
|
||||
run: |
|
||||
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
|
||||
- name: Upload apk to google play
|
||||
env:
|
||||
PLAY_STORE_PASSWORD: ${{ secrets.PLAY_STORE_PASSWORD }}
|
||||
PLAY_KEY_ALIAS: ${{ secrets.PLAY_KEY_ALIAS }}
|
||||
PLAY_KEY_PASSWORD: ${{ secrets.PLAY_KEY_PASSWORD }}
|
||||
PLAY_SERVICE_ACCOUNT_EMAIL: ${{ secrets.PLAY_SERVICE_ACCOUNT_EMAIL }}
|
||||
PLAY_STORE_PASSWORD: ${{ secrets.PLAY_STORE_PASSWORD }}
|
||||
run: ./gradlew publishPlayRelease -PenableFirebase --stacktrace;
|
||||
ANDROID_PUBLISHER_CREDENTIALS: ${{ secrets.ANDROID_PUBLISHER_CREDENTIALS }}
|
||||
ADMOB_PROJECT_ID: ${{ secrets.ADMOB_PROJECT_ID }}
|
||||
SINGLE_SUPPORT_AD_ID: ${{ secrets.SINGLE_SUPPORT_AD_ID }}
|
||||
DASHBOARD_TILE_AD_ID: ${{ secrets.DASHBOARD_TILE_AD_ID }}
|
||||
SET_BUILD_TIMESTAMP: ${{ secrets.SET_BUILD_TIMESTAMP }}
|
||||
run: ./gradlew publishPlayReleaseApps -PenableFirebase --stacktrace;
|
||||
|
||||
deploy-app-gallery:
|
||||
name: Deploy to AppGallery
|
||||
name: AppGallery
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
environment: app-gallery
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-java@v1
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 11
|
||||
- uses: actions/cache@v2
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
@ -60,7 +65,6 @@ jobs:
|
||||
SERVICES_ENCRYPT_KEY: ${{ secrets.SERVICES_ENCRYPT_KEY }}
|
||||
run: |
|
||||
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
|
||||
- name: Prepare credentials
|
||||
env:
|
||||
@ -68,7 +72,8 @@ jobs:
|
||||
run: echo $AGC_CREDENTIALS > ./app/src/release/agconnect-credentials.json
|
||||
- name: Build and publish HMS version
|
||||
env:
|
||||
PLAY_STORE_PASSWORD: ${{ secrets.PLAY_STORE_PASSWORD }}
|
||||
PLAY_KEY_ALIAS: ${{ secrets.PLAY_KEY_ALIAS }}
|
||||
PLAY_KEY_PASSWORD: ${{ secrets.PLAY_KEY_PASSWORD }}
|
||||
PLAY_STORE_PASSWORD: ${{ secrets.PLAY_STORE_PASSWORD }}
|
||||
run: ./gradlew assembleHmsRelease --stacktrace && ./gradlew publishHuaweiAppGalleryHmsRelease --stacktrace
|
||||
SET_BUILD_TIMESTAMP: ${{ secrets.SET_BUILD_TIMESTAMP }}
|
||||
run: ./gradlew bundleHmsRelease --stacktrace && ./gradlew publishHuaweiAppGalleryHmsRelease --stacktrace
|
||||
|
20
.github/workflows/deploy-test.yml
vendored
20
.github/workflows/deploy-test.yml
vendored
@ -1,4 +1,4 @@
|
||||
name: Deploy to app tests
|
||||
name: Deploy DEV
|
||||
|
||||
on:
|
||||
push:
|
||||
@ -18,11 +18,12 @@ jobs:
|
||||
timeout-minutes: 10
|
||||
environment: app-center
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-java@v1
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 11
|
||||
- uses: actions/cache@v2
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
@ -66,7 +67,7 @@ jobs:
|
||||
BITRISE_KEY_PASSWORD: ${{ secrets.BITRISE_KEY_PASSWORD }}
|
||||
run: ./gradlew assembleFdroidDebug --stacktrace
|
||||
- name: Upload apk to github artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: wulkanowyDEV-${{ env.RUN_NUMBER }}.apk
|
||||
path: app/build/outputs/apk/fdroid/debug/app-fdroid-debug.apk
|
||||
@ -87,11 +88,12 @@ jobs:
|
||||
environment: app-distribution
|
||||
if: github.event_name != 'pull_request_target'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-java@v1
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 11
|
||||
- uses: actions/cache@v2
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
@ -131,7 +133,7 @@ jobs:
|
||||
BITRISE_KEY_PASSWORD: ${{ secrets.BITRISE_KEY_PASSWORD }}
|
||||
run: ./gradlew assemblePlayDebug -PenableFirebase --stacktrace
|
||||
- name: Upload apk to github artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: wulkanowyDEV-${{ env.RUN_NUMBER }}-dev.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,18 +8,20 @@ on:
|
||||
branches: [ master, develop ]
|
||||
|
||||
jobs:
|
||||
unit-tests:
|
||||
name: Unit tests
|
||||
|
||||
tests-fdroid:
|
||||
name: F-Droid
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: fkirc/skip-duplicate-actions@master
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
- uses: actions/setup-java@v1
|
||||
- uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 11
|
||||
- uses: actions/cache@v2
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
@ -29,6 +31,58 @@ jobs:
|
||||
run: |
|
||||
./gradlew testFdroidDebugUnitTest --stacktrace
|
||||
./gradlew jacocoTestReport --stacktrace
|
||||
- uses: codecov/codecov-action@v1
|
||||
- uses: codecov/codecov-action@v3
|
||||
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:
|
||||
flags: unit
|
||||
|
15
.idea/codeStyles/Project.xml
generated
15
.idea/codeStyles/Project.xml
generated
@ -2,14 +2,6 @@
|
||||
<code_scheme name="Project" version="173">
|
||||
<option name="LINE_SEPARATOR" value=" " />
|
||||
<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" />
|
||||
</JetCodeStyleSettings>
|
||||
<codeStyleSettings language="XML">
|
||||
@ -126,13 +118,6 @@
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="kotlin">
|
||||
<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>
|
||||
</code_scheme>
|
||||
</component>
|
2
LICENSE
2
LICENSE
@ -186,7 +186,7 @@
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2019 Wulkanowy
|
||||
Copyright 2022 Wulkanowy
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
73
README.cs.md
Normal file
73
README.cs.md
Normal file
@ -0,0 +1,73 @@
|
||||
Česká verze / [Deutsche Version](README.de.md) / [English version](README.en.md) / [Polska wersja](README.md) / [Slovenská verzia](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)
|
||||
[](https://translate.wulkanowy.net.pl)
|
||||
|
||||
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 pomocí
|
||||
|
||||
|
||||
* [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)
|
73
README.de.md
Normal file
73
README.de.md
Normal file
@ -0,0 +1,73 @@
|
||||
[Česká verze](README.cs.md) / Deutsche Version / [English version](README.en.md) / [Polska wersja](README.md) / [Slovenská verzia](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)
|
||||
[](https://translate.wulkanowy.net.pl)
|
||||
|
||||
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,4 +1,4 @@
|
||||
[Polska wersja README](README.md)
|
||||
[Česká verze](README.cs.md) / [Deutsche Version](README.de.md) / English version / [Polska wersja](README.md) / [Slovenská verzia](README.sk.md)
|
||||
|
||||
# Wulkanowy
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
[](https://discord.gg/vccAQBr)
|
||||
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
||||
[](https://github.com/wulkanowy/wulkanowy/releases)
|
||||
[](https://translate.wulkanowy.net.pl)
|
||||
|
||||
Unofficial android VULCAN UONET+ register client for both students and their parents
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
[English version of README](README.en.md)
|
||||
[Česká verze](README.cs.md) / [Deutsche Version](README.de.md) / [English version](README.en.md) / Polska wersja / [Slovenská verzia](README.sk.md)
|
||||
|
||||
# Wulkanowy
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
[](https://discord.gg/vccAQBr)
|
||||
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
||||
[](https://github.com/wulkanowy/wulkanowy/releases)
|
||||
[](https://translate.wulkanowy.net.pl)
|
||||
|
||||
Nieoficjalny klient dziennika VULCAN UONET+ dla ucznia i rodzica
|
||||
|
||||
|
73
README.sk.md
Normal file
73
README.sk.md
Normal file
@ -0,0 +1,73 @@
|
||||
[Česká verze](README.cs.md) / [Deutsche Version](README.de.md) / [English version](README.en.md) / [Polska wersja](README.md) / Slovenská verzia
|
||||
|
||||
# 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)
|
||||
[](https://translate.wulkanowy.net.pl)
|
||||
|
||||
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 pomocou
|
||||
|
||||
|
||||
* [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)
|
158
app/build.gradle
158
app/build.gradle
@ -1,5 +1,6 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlinx-serialization'
|
||||
apply plugin: 'kotlin-parcelize'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
apply plugin: 'dagger.hilt.android.plugin'
|
||||
@ -14,32 +15,41 @@ apply from: 'sonarqube.gradle'
|
||||
apply from: 'hooks.gradle'
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
namespace 'io.github.wulkanowy'
|
||||
compileSdkVersion 32
|
||||
|
||||
defaultConfig {
|
||||
applicationId "io.github.wulkanowy"
|
||||
testApplicationId "io.github.tests.wulkanowy"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 30
|
||||
versionCode 93
|
||||
versionName "1.2.0"
|
||||
targetSdkVersion 32
|
||||
versionCode 115
|
||||
versionName "1.8.0"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
|
||||
resValue "string", "app_name", "Wulkanowy"
|
||||
buildConfigField "long", "BUILD_TIMESTAMP", String.valueOf(System.currentTimeMillis())
|
||||
|
||||
manifestPlaceholders = [
|
||||
firebase_enabled: project.hasProperty("enableFirebase")
|
||||
firebase_enabled: project.hasProperty("enableFirebase"),
|
||||
admob_project_id: ""
|
||||
]
|
||||
javaCompileOptions {
|
||||
annotationProcessorOptions {
|
||||
arguments += [
|
||||
"room.schemaLocation": "$projectDir/schemas".toString(),
|
||||
"room.incremental" : "true"
|
||||
"room.schemaLocation": "$projectDir/schemas".toString(),
|
||||
"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 {
|
||||
@ -62,12 +72,16 @@ android {
|
||||
shrinkResources true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
signingConfig signingConfigs.release
|
||||
buildConfigField "String", "MESSAGES_BASE_URL", "\"https://messages.wulkanowy.net.pl\""
|
||||
}
|
||||
debug {
|
||||
resValue "string", "app_name", "Wulkanowy DEV " + defaultConfig.versionCode
|
||||
minifyEnabled false
|
||||
shrinkResources false
|
||||
resValue "string", "app_name", "Wulkanowy DEV"
|
||||
applicationIdSuffix ".dev"
|
||||
versionNameSuffix "-dev"
|
||||
ext.enableCrashlytics = project.hasProperty("enableFirebase")
|
||||
buildConfigField "String", "MESSAGES_BASE_URL", "\"https://messages.wulkanowy.net.pl\""
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,32 +90,44 @@ android {
|
||||
productFlavors {
|
||||
hms {
|
||||
dimension "platform"
|
||||
manifestPlaceholders = [
|
||||
install_channel: "AppGallery"
|
||||
]
|
||||
manifestPlaceholders = [install_channel: "AppGallery"]
|
||||
}
|
||||
|
||||
play {
|
||||
dimension "platform"
|
||||
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 {
|
||||
dimension "platform"
|
||||
manifestPlaceholders = [
|
||||
install_channel: "F-Droid"
|
||||
]
|
||||
manifestPlaceholders = [install_channel: "F-Droid"]
|
||||
}
|
||||
}
|
||||
|
||||
playConfigs {
|
||||
play { enabled.set(true) }
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
}
|
||||
|
||||
bundle {
|
||||
language {
|
||||
enableSplit = false
|
||||
}
|
||||
}
|
||||
|
||||
testOptions.unitTests {
|
||||
includeAndroidResources = true
|
||||
// workaround HMS test errors https://github.com/robolectric/robolectric/issues/2750
|
||||
all { jvmArgs '-noverify' }
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
@ -112,12 +138,14 @@ android {
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "11"
|
||||
freeCompilerArgs += ["-Xopt-in=kotlin.RequiresOptIn", "-Xjvm-default=all"]
|
||||
freeCompilerArgs += ["-opt-in=kotlin.RequiresOptIn", "-Xjvm-default=all"]
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
exclude 'META-INF/library_release.kotlin_module'
|
||||
exclude 'META-INF/library-core_release.kotlin_module'
|
||||
resources {
|
||||
excludes += ['META-INF/library_release.kotlin_module',
|
||||
'META-INF/library-core_release.kotlin_module']
|
||||
}
|
||||
}
|
||||
|
||||
aboutLibraries {
|
||||
@ -130,61 +158,63 @@ kapt {
|
||||
}
|
||||
|
||||
play {
|
||||
serviceAccountEmail = System.getenv("PLAY_SERVICE_ACCOUNT_EMAIL") ?: "jan@fakelog.cf"
|
||||
serviceAccountCredentials = file('key.p12')
|
||||
defaultToAppBundles = false
|
||||
track = 'beta'
|
||||
updatePriority = 3
|
||||
track = 'production'
|
||||
releaseStatus = com.github.triplet.gradle.androidpublisher.ReleaseStatus.IN_PROGRESS
|
||||
userFraction = 0.25d
|
||||
updatePriority = 4
|
||||
enabled.set(false)
|
||||
}
|
||||
|
||||
huaweiPublish {
|
||||
instances {
|
||||
hmsRelease {
|
||||
credentialsPath = "$rootDir/app/src/release/agconnect-credentials.json"
|
||||
buildFormat = "apk"
|
||||
buildFormat = "aab"
|
||||
deployType = "draft"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ext {
|
||||
work_manager = "2.5.0"
|
||||
work_manager = "2.7.1"
|
||||
android_hilt = "1.0.0"
|
||||
room = "2.3.0"
|
||||
room = "2.4.3"
|
||||
chucker = "3.5.2"
|
||||
mockk = "1.12.0"
|
||||
moshi = "1.12.0"
|
||||
mockk = "1.13.2"
|
||||
coroutines = "1.6.4"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "io.github.wulkanowy:sdk:1.2.0"
|
||||
implementation "io.github.wulkanowy:sdk:1.8.0"
|
||||
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.8'
|
||||
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.1"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines"
|
||||
|
||||
implementation "androidx.core:core-ktx:1.6.0"
|
||||
implementation "androidx.activity:activity-ktx:1.3.1"
|
||||
implementation "androidx.appcompat:appcompat:1.3.1"
|
||||
implementation "androidx.appcompat:appcompat-resources:1.3.1"
|
||||
implementation "androidx.fragment:fragment-ktx:1.3.6"
|
||||
implementation "androidx.annotation:annotation:1.2.0"
|
||||
implementation "androidx.core:core-ktx:1.8.0"
|
||||
implementation 'androidx.core:core-splashscreen:1.0.0'
|
||||
implementation "androidx.activity:activity-ktx:1.5.1"
|
||||
implementation "androidx.appcompat:appcompat:1.5.1"
|
||||
implementation "androidx.fragment:fragment-ktx:1.5.4"
|
||||
implementation "androidx.annotation:annotation:1.5.0"
|
||||
|
||||
implementation "androidx.preference:preference-ktx:1.1.1"
|
||||
implementation "androidx.preference:preference-ktx:1.2.0"
|
||||
implementation "androidx.recyclerview:recyclerview:1.2.1"
|
||||
implementation "androidx.viewpager:viewpager:1.0.0"
|
||||
implementation "androidx.viewpager2:viewpager2:1.1.0-beta01"
|
||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
|
||||
implementation "androidx.constraintlayout:constraintlayout:2.1.0"
|
||||
implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"
|
||||
implementation "com.google.android.material:material:1.4.0"
|
||||
implementation "com.github.wulkanowy:material-chips-input:2.2.0"
|
||||
implementation "androidx.constraintlayout:constraintlayout:2.1.4"
|
||||
implementation "androidx.coordinatorlayout:coordinatorlayout:1.2.0"
|
||||
implementation "com.google.android.material:material:1.7.0"
|
||||
implementation "com.github.wulkanowy:material-chips-input:2.3.1"
|
||||
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
|
||||
implementation 'com.github.lopspower:CircularImageView:4.2.0'
|
||||
implementation 'com.github.lopspower:CircularImageView:4.3.0'
|
||||
|
||||
implementation "androidx.work:work-runtime-ktx:$work_manager"
|
||||
playImplementation "androidx.work:work-gcm:$work_manager"
|
||||
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1"
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.5.1"
|
||||
|
||||
implementation "androidx.room:room-runtime:$room"
|
||||
implementation "androidx.room:room-ktx:$room"
|
||||
@ -198,43 +228,45 @@ dependencies {
|
||||
implementation 'com.github.ncapdevi:FragNav:3.3.0'
|
||||
implementation "com.github.YarikSOffice:lingver:1.3.0"
|
||||
|
||||
implementation "com.squareup.moshi:moshi:$moshi"
|
||||
implementation "com.squareup.moshi:moshi-adapters:$moshi"
|
||||
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi"
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||
implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0"
|
||||
implementation "com.squareup.okhttp3:logging-interceptor:4.10.0"
|
||||
|
||||
implementation "com.jakewharton.timber:timber:5.0.1"
|
||||
implementation "at.favre.lib:slf4j-timber:1.0.1"
|
||||
implementation 'com.github.bastienpaulfr:Treessence:1.0.4'
|
||||
implementation 'com.github.bastienpaulfr:Treessence:1.0.5'
|
||||
implementation "com.mikepenz:aboutlibraries-core:$about_libraries"
|
||||
implementation "io.coil-kt:coil:1.3.2"
|
||||
implementation "io.coil-kt:coil:2.2.2"
|
||||
implementation "io.github.wulkanowy:AppKillerManager:3.0.0"
|
||||
implementation 'me.xdrop:fuzzywuzzy:1.3.1'
|
||||
implementation 'com.fredporciuncula:flow-preferences:1.5.0'
|
||||
implementation 'me.xdrop:fuzzywuzzy:1.4.0'
|
||||
implementation 'com.fredporciuncula:flow-preferences:1.8.0'
|
||||
|
||||
playImplementation platform('com.google.firebase:firebase-bom:28.4.0')
|
||||
playImplementation platform('com.google.firebase:firebase-bom:31.0.3')
|
||||
playImplementation 'com.google.firebase:firebase-analytics-ktx'
|
||||
playImplementation 'com.google.firebase:firebase-messaging:'
|
||||
playImplementation 'com.google.firebase:firebase-crashlytics:'
|
||||
playImplementation 'com.google.android.play:core:1.10.0'
|
||||
playImplementation 'com.google.android.play:core:1.10.3'
|
||||
playImplementation 'com.google.android.play:core-ktx:1.8.1'
|
||||
playImplementation 'com.google.android.gms:play-services-ads:21.3.0'
|
||||
|
||||
hmsImplementation 'com.huawei.hms:hianalytics:6.1.1.300'
|
||||
hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.6.0.300'
|
||||
hmsImplementation 'com.huawei.hms:hianalytics:6.8.0.300'
|
||||
hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.7.3.300'
|
||||
|
||||
releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker"
|
||||
|
||||
debugImplementation "com.github.ChuckerTeam.Chucker:library:$chucker"
|
||||
debugImplementation 'com.github.amitshekhariitbhu.Android-Debug-Database:debug-db:v1.0.6'
|
||||
debugImplementation 'com.github.amitshekhariitbhu.Android-Debug-Database:debug-db:1.0.6'
|
||||
debugImplementation 'com.github.haroldadmin:WhatTheStack:1.0.0-alpha04'
|
||||
|
||||
testImplementation "junit:junit:4.13.2"
|
||||
testImplementation "io.mockk:mockk:$mockk"
|
||||
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.5.1'
|
||||
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines"
|
||||
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||
|
||||
testImplementation 'org.robolectric:robolectric:4.6.1'
|
||||
testImplementation "androidx.test:runner:1.4.0"
|
||||
testImplementation "androidx.test.ext:junit:1.1.3"
|
||||
testImplementation "androidx.test:core:1.4.0"
|
||||
testImplementation 'org.robolectric:robolectric:4.9'
|
||||
testImplementation "androidx.test:runner:1.5.1"
|
||||
testImplementation "androidx.test.ext:junit:1.1.4"
|
||||
testImplementation "androidx.test:core:1.5.0"
|
||||
testImplementation "androidx.room:room-testing:$room"
|
||||
testImplementation "com.google.dagger:hilt-android-testing:$hilt_version"
|
||||
kaptTest "com.google.dagger:hilt-android-compiler:$hilt_version"
|
||||
|
BIN
app/key.p12.gpg
BIN
app/key.p12.gpg
Binary file not shown.
2316
app/schemas/io.github.wulkanowy.data.db.AppDatabase/40.json
Normal file
2316
app/schemas/io.github.wulkanowy.data.db.AppDatabase/40.json
Normal file
File diff suppressed because it is too large
Load Diff
2322
app/schemas/io.github.wulkanowy.data.db.AppDatabase/41.json
Normal file
2322
app/schemas/io.github.wulkanowy.data.db.AppDatabase/41.json
Normal file
File diff suppressed because it is too large
Load Diff
2396
app/schemas/io.github.wulkanowy.data.db.AppDatabase/42.json
Normal file
2396
app/schemas/io.github.wulkanowy.data.db.AppDatabase/42.json
Normal file
File diff suppressed because it is too large
Load Diff
2408
app/schemas/io.github.wulkanowy.data.db.AppDatabase/43.json
Normal file
2408
app/schemas/io.github.wulkanowy.data.db.AppDatabase/43.json
Normal file
File diff suppressed because it is too large
Load Diff
2414
app/schemas/io.github.wulkanowy.data.db.AppDatabase/44.json
Normal file
2414
app/schemas/io.github.wulkanowy.data.db.AppDatabase/44.json
Normal file
File diff suppressed because it is too large
Load Diff
2430
app/schemas/io.github.wulkanowy.data.db.AppDatabase/45.json
Normal file
2430
app/schemas/io.github.wulkanowy.data.db.AppDatabase/45.json
Normal file
File diff suppressed because it is too large
Load Diff
2430
app/schemas/io.github.wulkanowy.data.db.AppDatabase/46.json
Normal file
2430
app/schemas/io.github.wulkanowy.data.db.AppDatabase/46.json
Normal file
File diff suppressed because it is too large
Load Diff
2438
app/schemas/io.github.wulkanowy.data.db.AppDatabase/47.json
Normal file
2438
app/schemas/io.github.wulkanowy.data.db.AppDatabase/47.json
Normal file
File diff suppressed because it is too large
Load Diff
2445
app/schemas/io.github.wulkanowy.data.db.AppDatabase/48.json
Normal file
2445
app/schemas/io.github.wulkanowy.data.db.AppDatabase/48.json
Normal file
File diff suppressed because it is too large
Load Diff
2445
app/schemas/io.github.wulkanowy.data.db.AppDatabase/49.json
Normal file
2445
app/schemas/io.github.wulkanowy.data.db.AppDatabase/49.json
Normal file
File diff suppressed because it is too large
Load Diff
2445
app/schemas/io.github.wulkanowy.data.db.AppDatabase/50.json
Normal file
2445
app/schemas/io.github.wulkanowy.data.db.AppDatabase/50.json
Normal file
File diff suppressed because it is too large
Load Diff
2409
app/schemas/io.github.wulkanowy.data.db.AppDatabase/51.json
Normal file
2409
app/schemas/io.github.wulkanowy.data.db.AppDatabase/51.json
Normal file
File diff suppressed because it is too large
Load Diff
2421
app/schemas/io.github.wulkanowy.data.db.AppDatabase/52.json
Normal file
2421
app/schemas/io.github.wulkanowy.data.db.AppDatabase/52.json
Normal file
File diff suppressed because it is too large
Load Diff
2439
app/schemas/io.github.wulkanowy.data.db.AppDatabase/53.json
Normal file
2439
app/schemas/io.github.wulkanowy.data.db.AppDatabase/53.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,33 +1,92 @@
|
||||
{
|
||||
"agcgw":{
|
||||
"backurl":"connect-dre.dbankcloud.cn",
|
||||
"url":"connect-dre.hispace.hicloud.com"
|
||||
},
|
||||
"client":{
|
||||
"cp_id":"890048000024105546",
|
||||
"product_id":"",
|
||||
"client_id":"",
|
||||
"client_secret":"",
|
||||
"app_id":"101440411",
|
||||
"package_name":"io.github.wulkanowy.dev",
|
||||
"api_key":""
|
||||
},
|
||||
"service":{
|
||||
"analytics":{
|
||||
"collector_url":"datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn",
|
||||
"resource_id":"p1",
|
||||
"channel_id":""
|
||||
},
|
||||
"agcgw": {
|
||||
"backurl": "connect-dre.hispace.hicloud.com",
|
||||
"url": "connect-dre.dbankcloud.cn",
|
||||
"websocketbackurl": "connect-ws-dre.hispace.dbankcloud.com",
|
||||
"websocketurl": "connect-ws-dre.hispace.dbankcloud.cn"
|
||||
},
|
||||
"agcgw_all": {
|
||||
"CN": "connect-drcn.dbankcloud.cn",
|
||||
"CN_back": "connect-drcn.hispace.hicloud.com",
|
||||
"DE": "connect-dre.dbankcloud.cn",
|
||||
"DE_back": "connect-dre.hispace.hicloud.com",
|
||||
"RU": "connect-drru.hispace.dbankcloud.ru",
|
||||
"RU_back": "connect-drru.hispace.dbankcloud.cn",
|
||||
"SG": "connect-dra.dbankcloud.cn",
|
||||
"SG_back": "connect-dra.hispace.hicloud.com"
|
||||
},
|
||||
"websocketgw_all": {
|
||||
"CN": "connect-ws-drcn.hispace.dbankcloud.cn",
|
||||
"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":{
|
||||
"url":"https://search-dre.cloud.huawei.com"
|
||||
},
|
||||
"cloudstorage":{
|
||||
"storage_url":"https://ops-dre.agcstorage.link"
|
||||
},
|
||||
"ml":{
|
||||
"mlservice_url":"ml-api-dre.ai.dbankcloud.com,ml-api-dre.ai.dbankcloud.cn"
|
||||
}
|
||||
},
|
||||
"region":"DE",
|
||||
"configuration_version":"1.0"
|
||||
"cloudstorage": {
|
||||
"storage_url_sg_back": "https://agc-storage-dra.cloud.huawei.asia",
|
||||
"storage_url_ru_back": "https://agc-storage-drru.cloud.huawei.ru",
|
||||
"storage_url_ru": "https://agc-storage-drru.cloud.huawei.ru",
|
||||
"storage_url_de_back": "https://agc-storage-dre.cloud.huawei.eu",
|
||||
"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",
|
||||
"storage_url_cn_back": "https://agc-storage-drcn.cloud.huawei.com.cn",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
28
app/src/fdroid/java/io/github/wulkanowy/utils/AdsHelper.kt
Normal file
28
app/src/fdroid/java/io/github/wulkanowy/utils/AdsHelper.kt
Normal file
@ -0,0 +1,28 @@
|
||||
package io.github.wulkanowy.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("unused")
|
||||
class AdsHelper @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val preferencesRepository: PreferencesRepository
|
||||
) {
|
||||
|
||||
fun initialize() {
|
||||
preferencesRepository.isAdsEnabled = false
|
||||
preferencesRepository.isAgreeToProcessData = false
|
||||
preferencesRepository.selectedDashboardTiles -= DashboardItem.Tile.ADS
|
||||
}
|
||||
|
||||
@Suppress("RedundantSuspendModifier", "UNUSED_PARAMETER")
|
||||
suspend fun getDashboardTileAdBanner(width: Int): AdBanner {
|
||||
throw IllegalStateException("Can't get ad banner (F-droid)")
|
||||
}
|
||||
}
|
||||
|
||||
data class AdBanner(val view: View)
|
@ -8,15 +8,7 @@ import javax.inject.Singleton
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
class AnalyticsHelper @Inject constructor() {
|
||||
|
||||
fun logEvent(name: String, vararg params: Pair<String, Any?>) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
fun setCurrentScreen(activity: Activity, name: String?) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
fun popCurrentScreen(name: String?) {
|
||||
// do nothing
|
||||
}
|
||||
fun logEvent(name: String, vararg params: Pair<String, Any?>) = Unit
|
||||
fun setCurrentScreen(activity: Activity, name: String?) = Unit
|
||||
fun popCurrentScreen(name: String?) = Unit
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import javax.inject.Singleton
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("UNUSED_PARAMETER", "unused")
|
||||
@Singleton
|
||||
class InAppReviewHelper @Inject constructor(
|
||||
@ApplicationContext private val context: Context
|
||||
|
28
app/src/hms/java/io/github/wulkanowy/utils/AdsHelper.kt
Normal file
28
app/src/hms/java/io/github/wulkanowy/utils/AdsHelper.kt
Normal file
@ -0,0 +1,28 @@
|
||||
package io.github.wulkanowy.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("unused")
|
||||
class AdsHelper @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val preferencesRepository: PreferencesRepository
|
||||
) {
|
||||
|
||||
fun initialize() {
|
||||
preferencesRepository.isAdsEnabled = false
|
||||
preferencesRepository.isAgreeToProcessData = false
|
||||
preferencesRepository.selectedDashboardTiles -= DashboardItem.Tile.ADS
|
||||
}
|
||||
|
||||
@Suppress("RedundantSuspendModifier", "UNUSED_PARAMETER")
|
||||
suspend fun getDashboardTileAdBanner(width: Int): AdBanner {
|
||||
throw IllegalStateException("Can't get ad banner (HMS)")
|
||||
}
|
||||
}
|
||||
|
||||
data class AdBanner(val view: View)
|
@ -3,26 +3,38 @@ package io.github.wulkanowy.utils
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import com.huawei.agconnect.crash.AGConnectCrash
|
||||
import com.huawei.hms.analytics.HiAnalytics
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class AnalyticsHelper @Inject constructor(
|
||||
@ApplicationContext private val context: Context
|
||||
@ApplicationContext private val context: Context,
|
||||
preferencesRepository: PreferencesRepository,
|
||||
appInfo: AppInfo,
|
||||
) {
|
||||
|
||||
private val analytics by lazy { HiAnalytics.getInstance(context) }
|
||||
|
||||
private val connectCrash by lazy { AGConnectCrash.getInstance() }
|
||||
|
||||
init {
|
||||
if (!appInfo.isDebug) {
|
||||
connectCrash.setUserId(preferencesRepository.installationId)
|
||||
}
|
||||
}
|
||||
|
||||
fun logEvent(name: String, vararg params: Pair<String, Any?>) {
|
||||
Bundle().apply {
|
||||
params.forEach {
|
||||
if (it.second == null) return@forEach
|
||||
when (it.second) {
|
||||
is String, is String? -> putString(it.first, it.second as String)
|
||||
is Int, is Int? -> putInt(it.first, it.second as Int)
|
||||
is Boolean, is Boolean? -> putBoolean(it.first, it.second as Boolean)
|
||||
params.forEach { (key, value) ->
|
||||
if (value == null) return@forEach
|
||||
when (value) {
|
||||
is String -> putString(key, value)
|
||||
is Int -> putInt(key, value)
|
||||
is Boolean -> putBoolean(key, value)
|
||||
}
|
||||
}
|
||||
analytics.onEvent(name, this)
|
||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.utils
|
||||
import android.util.Log
|
||||
import com.huawei.agconnect.crash.AGConnectCrash
|
||||
import fr.bipi.tressence.base.FormatterPriorityTree
|
||||
import fr.bipi.tressence.common.StackTraceRecorder
|
||||
|
||||
class CrashLogTree : FormatterPriorityTree(Log.VERBOSE) {
|
||||
|
||||
@ -22,16 +23,10 @@ class CrashLogExceptionTree : FormatterPriorityTree(Log.ERROR, ExceptionFilter)
|
||||
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
|
||||
if (skipLog(priority, tag, message, t)) return
|
||||
|
||||
// Disabled due to a bug in the Huawei library
|
||||
|
||||
/*connectCrash.setCustomKey("priority", priority)
|
||||
connectCrash.setCustomKey("tag", tag.orEmpty())
|
||||
connectCrash.setCustomKey("message", message)
|
||||
|
||||
if (t != null) {
|
||||
connectCrash.recordException(t)
|
||||
} else {
|
||||
connectCrash.recordException(StackTraceRecorder(format(priority, tag, message)))
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@Suppress("UNUSED_PARAMETER", "unused")
|
||||
class InAppReviewHelper @Inject constructor(
|
||||
@ApplicationContext private val context: Context
|
||||
) {
|
||||
@ -14,4 +15,4 @@ class InAppReviewHelper @Inject constructor(
|
||||
fun showInAppReview(activity: MainActivity) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="io.github.wulkanowy"
|
||||
android:installLocation="internalOnly">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
@ -9,6 +8,7 @@
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
|
||||
|
||||
<queries>
|
||||
<intent>
|
||||
@ -38,13 +38,14 @@
|
||||
android:allowBackup="false"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="false"
|
||||
android:theme="@style/WulkanowyTheme"
|
||||
android:usesCleartextTraffic="true"
|
||||
tools:ignore="GoogleAppIndexingWarning,UnusedAttribute">
|
||||
<activity
|
||||
android:name=".ui.modules.splash.SplashActivity"
|
||||
android:exported="true"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/WulkanowyTheme.SplashScreen"
|
||||
tools:ignore="LockedOrientationActivity">
|
||||
@ -74,6 +75,7 @@
|
||||
<activity
|
||||
android:name=".ui.modules.timetablewidget.TimetableWidgetConfigureActivity"
|
||||
android:excludeFromRecents="true"
|
||||
android:exported="true"
|
||||
android:noHistory="true"
|
||||
android:theme="@style/WulkanowyTheme.WidgetAccountSwitcher">
|
||||
<intent-filter>
|
||||
@ -83,6 +85,7 @@
|
||||
<activity
|
||||
android:name=".ui.modules.luckynumberwidget.LuckyNumberWidgetConfigureActivity"
|
||||
android:excludeFromRecents="true"
|
||||
android:exported="true"
|
||||
android:noHistory="true"
|
||||
android:theme="@style/WulkanowyTheme.WidgetAccountSwitcher">
|
||||
<intent-filter>
|
||||
@ -93,6 +96,22 @@
|
||||
<service
|
||||
android:name=".services.widgets.TimetableWidgetService"
|
||||
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
|
||||
android:name=".ui.modules.timetablewidget.TimetableWidgetProvider"
|
||||
@ -107,6 +126,7 @@
|
||||
</receiver>
|
||||
<receiver
|
||||
android:name=".ui.modules.luckynumberwidget.LuckyNumberWidgetProvider"
|
||||
android:exported="true"
|
||||
android:label="@string/lucky_number_title">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
@ -119,11 +139,9 @@
|
||||
<receiver android:name=".services.alarm.TimetableNotificationReceiver" />
|
||||
|
||||
<provider
|
||||
android:name="androidx.work.impl.WorkManagerInitializer"
|
||||
android:authorities="${applicationId}.workmanager-init"
|
||||
android:exported="false"
|
||||
android:name="androidx.startup.InitializationProvider"
|
||||
android:authorities="${applicationId}.androidx-startup"
|
||||
tools:node="remove" />
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.fileprovider"
|
||||
@ -134,44 +152,44 @@
|
||||
android:resource="@xml/provider_paths" />
|
||||
</provider>
|
||||
|
||||
<meta-data
|
||||
android:name="install_channel"
|
||||
android:value="${install_channel}" />
|
||||
|
||||
<!-- 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 -->
|
||||
<provider
|
||||
android:name="com.google.firebase.provider.FirebaseInitProvider"
|
||||
android:authorities="${applicationId}.firebaseinitprovider"
|
||||
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
|
||||
android:name="firebase_analytics_collection_enabled"
|
||||
android:value="${firebase_enabled}" />
|
||||
|
||||
<meta-data
|
||||
android:name="google_analytics_adid_collection_enabled"
|
||||
android:value="${firebase_enabled}" />
|
||||
|
||||
<meta-data
|
||||
android:name="firebase_crashlytics_collection_enabled"
|
||||
android:value="${firebase_enabled}" />
|
||||
|
||||
<meta-data
|
||||
android:name="firebase_messaging_auto_init_enabled"
|
||||
android:value="${firebase_enabled}" />
|
||||
|
||||
<meta-data
|
||||
android:name="firebase_inapp_messaging_auto_data_collection_enabled"
|
||||
android:value="${firebase_enabled}" />
|
||||
|
||||
<meta-data
|
||||
android:name="com.google.firebase.messaging.default_notification_icon"
|
||||
android:resource="@drawable/ic_stat_all" />
|
||||
|
||||
<meta-data
|
||||
android:name="com.google.firebase.messaging.default_notification_channel_id"
|
||||
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>
|
||||
</manifest>
|
||||
|
@ -1,12 +1,7 @@
|
||||
package io.github.wulkanowy
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
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 android.util.Log.*
|
||||
import androidx.hilt.work.HiltWorkerFactory
|
||||
import androidx.work.Configuration
|
||||
import com.yariksoffice.lingver.Lingver
|
||||
@ -14,12 +9,7 @@ import dagger.hilt.android.HiltAndroidApp
|
||||
import fr.bipi.tressence.file.FileLoggerTree
|
||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import io.github.wulkanowy.ui.base.ThemeManager
|
||||
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 io.github.wulkanowy.utils.*
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -41,14 +31,15 @@ class WulkanowyApp : Application(), Configuration.Provider {
|
||||
@Inject
|
||||
lateinit var analyticsHelper: AnalyticsHelper
|
||||
|
||||
@SuppressLint("UnsafeOptInUsageWarning")
|
||||
@Inject
|
||||
lateinit var adsHelper: AdsHelper
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
FragmentManager.enableNewStateManager(false)
|
||||
initializeAppLanguage()
|
||||
themeManager.applyDefaultTheme()
|
||||
adsHelper.initialize()
|
||||
initLogging()
|
||||
fixWebViewLocale()
|
||||
}
|
||||
|
||||
private fun initLogging() {
|
||||
@ -80,15 +71,6 @@ 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()
|
||||
.setWorkerFactory(workerFactory)
|
||||
.setMinimumLoggingLevel(if (appInfo.isDebug) VERBOSE else INFO)
|
||||
|
@ -2,62 +2,99 @@ package io.github.wulkanowy.data
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.content.res.AssetManager
|
||||
import android.content.res.Resources
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.chuckerteam.chucker.api.ChuckerCollector
|
||||
import com.chuckerteam.chucker.api.ChuckerInterceptor
|
||||
import com.chuckerteam.chucker.api.RetentionManager
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.fredporciuncula.flow.preferences.FlowSharedPreferences
|
||||
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
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.SharedPrefProvider
|
||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
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 java.util.concurrent.TimeUnit
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal class RepositoryModule {
|
||||
internal class DataModule {
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideSdk(chuckerCollector: ChuckerCollector, @ApplicationContext context: Context): Sdk {
|
||||
return Sdk().apply {
|
||||
fun provideSdk(chuckerInterceptor: ChuckerInterceptor) =
|
||||
Sdk().apply {
|
||||
androidVersion = android.os.Build.VERSION.RELEASE
|
||||
buildTag = android.os.Build.MODEL
|
||||
setSimpleHttpLogger { Timber.d(it) }
|
||||
|
||||
// for debug only
|
||||
addInterceptor(
|
||||
ChuckerInterceptor.Builder(context)
|
||||
.collector(chuckerCollector)
|
||||
.alwaysReadResponseBody(true)
|
||||
.build(), network = true
|
||||
)
|
||||
addInterceptor(chuckerInterceptor, network = true)
|
||||
}
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideChuckerCollector(
|
||||
@ApplicationContext context: Context,
|
||||
prefRepository: PreferencesRepository
|
||||
): ChuckerCollector {
|
||||
return ChuckerCollector(
|
||||
context = context,
|
||||
showNotification = prefRepository.isDebugNotificationEnable,
|
||||
retentionPeriod = RetentionManager.Period.ONE_HOUR
|
||||
)
|
||||
}
|
||||
) = ChuckerCollector(
|
||||
context = context,
|
||||
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
|
||||
@Provides
|
||||
@ -67,20 +104,11 @@ internal class RepositoryModule {
|
||||
appInfo: 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
|
||||
@Provides
|
||||
fun provideSharedPref(@ApplicationContext context: Context): SharedPreferences =
|
||||
PreferenceManager.getDefaultSharedPreferences(context)
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideFlowSharedPref(sharedPreferences: SharedPreferences) =
|
||||
@ -88,7 +116,9 @@ internal class RepositoryModule {
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideMoshi() = Moshi.Builder().build()
|
||||
fun provideJson() = Json {
|
||||
ignoreUnknownKeys = true
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
@ -165,7 +195,7 @@ internal class RepositoryModule {
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideReportingUnitDao(database: AppDatabase) = database.reportingUnitDao
|
||||
fun provideMailboxesDao(database: AppDatabase) = database.mailboxDao
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
@ -202,4 +232,12 @@ internal class RepositoryModule {
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideSchoolAnnouncementDao(database: AppDatabase) = database.schoolAnnouncementDao
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideNotificationDao(database: AppDatabase) = database.notificationDao
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideAdminMessageDao(database: AppDatabase) = database.adminMessagesDao
|
||||
}
|
@ -1,23 +1,173 @@
|
||||
package io.github.wulkanowy.data
|
||||
|
||||
data class Resource<T>(val status: Status, val data: T?, val error: Throwable?) {
|
||||
companion object {
|
||||
fun <T> success(data: T?): Resource<T> {
|
||||
return Resource(Status.SUCCESS, data, null)
|
||||
}
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import timber.log.Timber
|
||||
|
||||
fun <T> error(error: Throwable?, data: T? = null): Resource<T> {
|
||||
return Resource(Status.ERROR, data, error)
|
||||
}
|
||||
sealed class Resource<T> {
|
||||
|
||||
fun <T> loading(data: T? = null): Resource<T> {
|
||||
return Resource(Status.LOADING, data, null)
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
enum class Status {
|
||||
LOADING,
|
||||
SUCCESS,
|
||||
ERROR
|
||||
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 {
|
||||
val newData = fetch(data)
|
||||
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)) }
|
||||
})
|
||||
}
|
||||
|
||||
@JvmName("networkBoundResourceWithMap")
|
||||
inline fun <ResultType, RequestType, T> networkBoundResource(
|
||||
mutex: Mutex = Mutex(),
|
||||
showSavedOnLoading: Boolean = true,
|
||||
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)) }
|
||||
})
|
||||
}
|
||||
|
@ -0,0 +1,12 @@
|
||||
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,105 +1,11 @@
|
||||
package io.github.wulkanowy.data.db
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.room.*
|
||||
import androidx.room.RoomDatabase.JournalMode.TRUNCATE
|
||||
import androidx.room.TypeConverters
|
||||
import io.github.wulkanowy.data.db.dao.AttendanceDao
|
||||
import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao
|
||||
import io.github.wulkanowy.data.db.dao.CompletedLessonsDao
|
||||
import io.github.wulkanowy.data.db.dao.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.data.db.dao.*
|
||||
import io.github.wulkanowy.data.db.entities.*
|
||||
import io.github.wulkanowy.data.db.migrations.*
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import javax.inject.Singleton
|
||||
|
||||
@ -124,7 +30,7 @@ import javax.inject.Singleton
|
||||
Subject::class,
|
||||
LuckyNumber::class,
|
||||
CompletedLesson::class,
|
||||
ReportingUnit::class,
|
||||
Mailbox::class,
|
||||
Recipient::class,
|
||||
MobileDevice::class,
|
||||
Teacher::class,
|
||||
@ -134,6 +40,14 @@ import javax.inject.Singleton
|
||||
StudentInfo::class,
|
||||
TimetableHeader::class,
|
||||
SchoolAnnouncement::class,
|
||||
Notification::class,
|
||||
AdminMessage::class
|
||||
],
|
||||
autoMigrations = [
|
||||
AutoMigration(from = 44, to = 45),
|
||||
AutoMigration(from = 46, to = 47),
|
||||
AutoMigration(from = 47, to = 48),
|
||||
AutoMigration(from = 51, to = 52),
|
||||
],
|
||||
version = AppDatabase.VERSION_SCHEMA,
|
||||
exportSchema = true
|
||||
@ -142,7 +56,7 @@ import javax.inject.Singleton
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
companion object {
|
||||
const val VERSION_SCHEMA = 39
|
||||
const val VERSION_SCHEMA = 53
|
||||
|
||||
fun getMigrations(sharedPrefProvider: SharedPrefProvider, appInfo: AppInfo) = arrayOf(
|
||||
Migration2(),
|
||||
@ -183,6 +97,16 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
Migration37(),
|
||||
Migration38(),
|
||||
Migration39(),
|
||||
Migration40(),
|
||||
Migration41(sharedPrefProvider),
|
||||
Migration42(),
|
||||
Migration43(),
|
||||
Migration44(),
|
||||
Migration46(),
|
||||
Migration49(),
|
||||
Migration50(),
|
||||
Migration51(),
|
||||
Migration53(),
|
||||
)
|
||||
|
||||
fun newInstance(
|
||||
@ -233,7 +157,7 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
abstract val completedLessonsDao: CompletedLessonsDao
|
||||
|
||||
abstract val reportingUnitDao: ReportingUnitDao
|
||||
abstract val mailboxDao: MailboxDao
|
||||
|
||||
abstract val recipientDao: RecipientDao
|
||||
|
||||
@ -252,4 +176,8 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
abstract val timetableHeaderDao: TimetableHeaderDao
|
||||
|
||||
abstract val schoolAnnouncementDao: SchoolAnnouncementDao
|
||||
|
||||
abstract val notificationDao: NotificationDao
|
||||
|
||||
abstract val adminMessagesDao: AdminMessageDao
|
||||
}
|
||||
|
@ -1,47 +1,36 @@
|
||||
package io.github.wulkanowy.data.db
|
||||
|
||||
import androidx.room.TypeConverter
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.Types
|
||||
import io.github.wulkanowy.data.db.adapters.PairAdapterFactory
|
||||
import io.github.wulkanowy.ui.modules.Destination
|
||||
import io.github.wulkanowy.utils.toTimestamp
|
||||
import kotlinx.serialization.SerializationException
|
||||
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.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
import java.time.Month
|
||||
import java.time.ZoneOffset
|
||||
import java.util.Date
|
||||
import java.util.*
|
||||
|
||||
class Converters {
|
||||
|
||||
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))
|
||||
}
|
||||
private val json = Json
|
||||
|
||||
@TypeConverter
|
||||
fun timestampToDate(value: Long?): LocalDate? = value?.run {
|
||||
Date(value).toInstant().atZone(ZoneOffset.UTC).toLocalDate()
|
||||
}
|
||||
fun timestampToLocalDate(value: Long?): LocalDate? =
|
||||
value?.let(::Date)?.toInstant()?.atZone(ZoneOffset.UTC)?.toLocalDate()
|
||||
|
||||
@TypeConverter
|
||||
fun dateToTimestamp(date: LocalDate?): Long? {
|
||||
return date?.atStartOfDay()?.toInstant(ZoneOffset.UTC)?.toEpochMilli()
|
||||
}
|
||||
fun dateToTimestamp(date: LocalDate?): Long? = date?.toTimestamp()
|
||||
|
||||
@TypeConverter
|
||||
fun timestampToTime(value: Long?): LocalDateTime? = value?.let {
|
||||
LocalDateTime.ofInstant(Instant.ofEpochMilli(value), ZoneOffset.UTC)
|
||||
}
|
||||
fun instantToTimestamp(instant: Instant?): Long? = instant?.toEpochMilli()
|
||||
|
||||
@TypeConverter
|
||||
fun timeToTimestamp(date: LocalDateTime?): Long? {
|
||||
return date?.atZone(ZoneOffset.UTC)?.toInstant()?.toEpochMilli()
|
||||
}
|
||||
fun timestampToInstant(timestamp: Long?): Instant? = timestamp?.let(Instant::ofEpochMilli)
|
||||
|
||||
@TypeConverter
|
||||
fun monthToInt(month: Month?) = month?.value
|
||||
@ -51,21 +40,32 @@ class Converters {
|
||||
|
||||
@TypeConverter
|
||||
fun intListToJson(list: List<Int>): String {
|
||||
return integerListAdapter.toJson(list)
|
||||
return json.encodeToString(list)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun jsonToIntList(value: String): List<Int> {
|
||||
return integerListAdapter.fromJson(value).orEmpty()
|
||||
return json.decodeFromString(value)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun stringPairListToJson(list: List<Pair<String, String>>): String {
|
||||
return stringListPairAdapter.toJson(list)
|
||||
return json.encodeToString(list)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun jsonToStringPairList(value: String): List<Pair<String, String>> {
|
||||
return stringListPairAdapter.fromJson(value).orEmpty()
|
||||
return try {
|
||||
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,11 +22,14 @@ class SharedPrefProvider @Inject constructor(
|
||||
|
||||
fun getString(key: String) = sharedPref.getString(key, null)
|
||||
|
||||
fun getString(key: String, defaultValue: String): String = sharedPref.getString(key, defaultValue) ?: defaultValue
|
||||
fun getString(key: String, defaultValue: String): String =
|
||||
sharedPref.getString(key, defaultValue) ?: defaultValue
|
||||
|
||||
fun getBoolean(key: String, defaultValue: Boolean): Boolean = sharedPref.getBoolean(key, defaultValue)
|
||||
fun getBoolean(key: String, defaultValue: Boolean): Boolean =
|
||||
sharedPref.getBoolean(key, defaultValue)
|
||||
|
||||
fun putBoolean(key: String, value: Boolean, sync: Boolean = false) = sharedPref.edit(sync) { putBoolean(key, value) }
|
||||
fun putBoolean(key: String, value: Boolean, sync: Boolean = false) =
|
||||
sharedPref.edit(sync) { putBoolean(key, value) }
|
||||
|
||||
fun putString(key: String, value: String?, sync: Boolean = false) {
|
||||
sharedPref.edit(sync) { putString(key, value) }
|
||||
|
@ -1,68 +0,0 @@
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
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,6 +11,11 @@ import javax.inject.Singleton
|
||||
@Dao
|
||||
interface AttendanceDao : BaseDao<Attendance> {
|
||||
|
||||
@Query("SELECT * FROM Attendance WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
||||
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow<List<Attendance>>
|
||||
@Query("SELECT * FROM Attendance WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :start AND date <= :end")
|
||||
fun loadAll(
|
||||
diaryId: Int,
|
||||
studentId: Int,
|
||||
start: LocalDate,
|
||||
end: LocalDate
|
||||
): Flow<List<Attendance>>
|
||||
}
|
||||
|
@ -2,11 +2,12 @@ package io.github.wulkanowy.data.db.dao
|
||||
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Update
|
||||
|
||||
interface BaseDao<T> {
|
||||
|
||||
@Insert
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insertAll(items: List<T>): List<Long>
|
||||
|
||||
@Update
|
||||
|
@ -4,7 +4,7 @@ import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.Conference
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import java.time.LocalDateTime
|
||||
import java.time.Instant
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Dao
|
||||
@ -12,5 +12,5 @@ import javax.inject.Singleton
|
||||
interface ConferenceDao : BaseDao<Conference> {
|
||||
|
||||
@Query("SELECT * FROM Conferences WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :startDate")
|
||||
fun loadAll(diaryId: Int, studentId: Int, startDate: LocalDateTime): Flow<List<Conference>>
|
||||
fun loadAll(diaryId: Int, studentId: Int, startDate: Instant): Flow<List<Conference>>
|
||||
}
|
||||
|
@ -0,0 +1,18 @@
|
||||
package io.github.wulkanowy.data.db.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.Mailbox
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@Dao
|
||||
interface MailboxDao : BaseDao<Mailbox> {
|
||||
|
||||
@Query("SELECT * FROM Mailboxes WHERE email = :email")
|
||||
suspend fun loadAll(email: String): List<Mailbox>
|
||||
|
||||
@Query("SELECT * FROM Mailboxes WHERE email = :email AND symbol = :symbol AND schoolId = :schoolId")
|
||||
fun loadAll(email: String, symbol: String, schoolId: String): Flow<List<Mailbox>>
|
||||
}
|
@ -11,9 +11,12 @@ import kotlinx.coroutines.flow.Flow
|
||||
interface MessagesDao : BaseDao<Message> {
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND message_id = :messageId")
|
||||
fun loadMessageWithAttachment(studentId: Int, messageId: Int): Flow<MessageWithAttachment?>
|
||||
@Query("SELECT * FROM Messages WHERE message_global_key = :messageGlobalKey")
|
||||
fun loadMessageWithAttachment(messageGlobalKey: String): Flow<MessageWithAttachment?>
|
||||
|
||||
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND folder_id = :folder ORDER BY date DESC")
|
||||
fun loadAll(studentId: Int, folder: Int): Flow<List<Message>>
|
||||
@Query("SELECT * FROM Messages WHERE mailbox_key = :mailboxKey AND folder_id = :folder ORDER BY date DESC")
|
||||
fun loadAll(mailboxKey: String, folder: Int): Flow<List<Message>>
|
||||
|
||||
@Query("SELECT * FROM Messages WHERE email = :email AND folder_id = :folder ORDER BY date DESC")
|
||||
fun loadAll(folder: Int, email: String): Flow<List<Message>>
|
||||
}
|
||||
|
@ -8,6 +8,6 @@ import kotlinx.coroutines.flow.Flow
|
||||
@Dao
|
||||
interface MobileDeviceDao : BaseDao<MobileDevice> {
|
||||
|
||||
@Query("SELECT * FROM MobileDevices WHERE student_id = :userLoginId ORDER BY date DESC")
|
||||
@Query("SELECT * FROM MobileDevices WHERE user_login_id = :userLoginId ORDER BY date DESC")
|
||||
fun loadAll(userLoginId: Int): Flow<List<MobileDevice>>
|
||||
}
|
||||
|
@ -0,0 +1,15 @@
|
||||
package io.github.wulkanowy.data.db.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.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,6 +2,7 @@ package io.github.wulkanowy.data.db.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.MailboxType
|
||||
import io.github.wulkanowy.data.db.entities.Recipient
|
||||
import javax.inject.Singleton
|
||||
|
||||
@ -9,6 +10,6 @@ import javax.inject.Singleton
|
||||
@Dao
|
||||
interface RecipientDao : BaseDao<Recipient> {
|
||||
|
||||
@Query("SELECT * FROM Recipients WHERE student_id = :studentId AND unit_id = :unitId AND role = :role")
|
||||
suspend fun loadAll(studentId: Int, unitId: Int, role: Int): List<Recipient>
|
||||
@Query("SELECT * FROM Recipients WHERE type = :type AND studentMailboxGlobalKey = :studentMailboxGlobalKey")
|
||||
suspend fun loadAll(type: MailboxType, studentMailboxGlobalKey: String): List<Recipient>
|
||||
}
|
||||
|
@ -1,17 +0,0 @@
|
||||
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
|
||||
interface SchoolAnnouncementDao : BaseDao<SchoolAnnouncement> {
|
||||
|
||||
@Query("SELECT * FROM SchoolAnnouncements WHERE student_id = :studentId")
|
||||
fun loadAll(studentId: Int): Flow<List<SchoolAnnouncement>>
|
||||
@Query("SELECT * FROM SchoolAnnouncements WHERE user_login_id = :userLoginId ORDER BY date DESC")
|
||||
fun loadAll(userLoginId: Int): Flow<List<SchoolAnnouncement>>
|
||||
}
|
||||
|
@ -1,12 +1,7 @@
|
||||
package io.github.wulkanowy.data.db.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.*
|
||||
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.StudentNickAndAvatar
|
||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||
@ -14,33 +9,43 @@ import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@Dao
|
||||
interface StudentDao {
|
||||
abstract class StudentDao {
|
||||
|
||||
@Insert(onConflict = ABORT)
|
||||
suspend fun insertAll(student: List<Student>): List<Long>
|
||||
abstract suspend fun insertAll(student: List<Student>): List<Long>
|
||||
|
||||
@Delete
|
||||
suspend fun delete(student: Student)
|
||||
abstract suspend fun delete(student: Student)
|
||||
|
||||
@Update(entity = Student::class)
|
||||
suspend fun update(studentNickAndAvatar: StudentNickAndAvatar)
|
||||
abstract suspend fun update(studentNickAndAvatar: StudentNickAndAvatar)
|
||||
|
||||
@Query("SELECT * FROM Students WHERE is_current = 1")
|
||||
suspend fun loadCurrent(): Student?
|
||||
abstract suspend fun loadCurrent(): Student?
|
||||
|
||||
@Query("SELECT * FROM Students WHERE id = :id")
|
||||
suspend fun loadById(id: Long): Student?
|
||||
abstract suspend fun loadById(id: Long): Student?
|
||||
|
||||
@Query("SELECT * FROM Students")
|
||||
suspend fun loadAll(): List<Student>
|
||||
abstract suspend fun loadAll(): List<Student>
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM Students")
|
||||
suspend fun loadStudentsWithSemesters(): List<StudentWithSemesters>
|
||||
abstract suspend fun loadStudentsWithSemesters(): List<StudentWithSemesters>
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM Students WHERE id = :id")
|
||||
abstract suspend fun loadStudentWithSemestersById(id: Long): StudentWithSemesters?
|
||||
|
||||
@Query("UPDATE Students SET is_current = 1 WHERE id = :id")
|
||||
suspend fun updateCurrent(id: Long)
|
||||
abstract suspend fun updateCurrent(id: Long)
|
||||
|
||||
@Query("UPDATE Students SET is_current = 0")
|
||||
suspend fun resetCurrent()
|
||||
abstract suspend fun resetCurrent()
|
||||
|
||||
@Transaction
|
||||
open suspend fun switchCurrent(id: Long) {
|
||||
resetCurrent()
|
||||
updateCurrent(id)
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import androidx.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.TimetableAdditional
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import java.time.LocalDate
|
||||
import java.util.UUID
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Dao
|
||||
@ -12,5 +13,13 @@ import javax.inject.Singleton
|
||||
interface TimetableAdditionalDao : BaseDao<TimetableAdditional> {
|
||||
|
||||
@Query("SELECT * FROM TimetableAdditional WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
||||
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow<List<TimetableAdditional>>
|
||||
fun loadAll(
|
||||
diaryId: Int,
|
||||
studentId: Int,
|
||||
from: LocalDate,
|
||||
end: LocalDate
|
||||
): Flow<List<TimetableAdditional>>
|
||||
|
||||
@Query("DELETE FROM TimetableAdditional WHERE repeat_id = :repeatId")
|
||||
suspend fun deleteAllByRepeatId(repeatId: UUID)
|
||||
}
|
||||
|
@ -0,0 +1,40 @@
|
||||
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,4 +47,7 @@ data class Attendance(
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
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.PrimaryKey
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDateTime
|
||||
import java.time.Instant
|
||||
|
||||
@Entity(tableName = "Conferences")
|
||||
data class Conference(
|
||||
@ -27,7 +27,7 @@ data class Conference(
|
||||
@ColumnInfo(name = "conference_id")
|
||||
val conferenceId: Int,
|
||||
|
||||
val date: LocalDateTime
|
||||
val date: Instant,
|
||||
) : Serializable {
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
|
@ -24,5 +24,8 @@ data class GradeSemesterStatistics(
|
||||
var id: Long = 0
|
||||
|
||||
@Transient
|
||||
var average: String = ""
|
||||
var classAverage: String = ""
|
||||
|
||||
@Transient
|
||||
var studentAverage: String = ""
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package io.github.wulkanowy.data.db.entities
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import java.time.LocalDateTime
|
||||
import java.time.Instant
|
||||
|
||||
@Entity(tableName = "GradesSummary")
|
||||
data class GradeSummary(
|
||||
@ -45,8 +45,8 @@ data class GradeSummary(
|
||||
var isFinalGradeNotified: Boolean = true
|
||||
|
||||
@ColumnInfo(name = "predicted_grade_last_change")
|
||||
var predictedGradeLastChange: LocalDateTime = LocalDateTime.now()
|
||||
var predictedGradeLastChange: Instant = Instant.now()
|
||||
|
||||
@ColumnInfo(name = "final_grade_last_change")
|
||||
var finalGradeLastChange: LocalDateTime = LocalDateTime.now()
|
||||
var finalGradeLastChange: Instant = Instant.now()
|
||||
}
|
||||
|
@ -40,4 +40,7 @@ data class Homework(
|
||||
|
||||
@ColumnInfo(name = "is_notified")
|
||||
var isNotified: Boolean = true
|
||||
|
||||
@ColumnInfo(name = "is_added_by_user")
|
||||
var isAddedByUser: Boolean = false
|
||||
}
|
||||
|
@ -0,0 +1,32 @@
|
||||
package io.github.wulkanowy.data.db.entities
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
@Entity(tableName = "Mailboxes")
|
||||
data class Mailbox(
|
||||
|
||||
@PrimaryKey
|
||||
val globalKey: String,
|
||||
|
||||
val email: String,
|
||||
val symbol: String,
|
||||
val schoolId: String,
|
||||
|
||||
val fullName: String,
|
||||
val userName: String,
|
||||
val studentName: String,
|
||||
val schoolNameShort: String,
|
||||
val type: MailboxType,
|
||||
) : java.io.Serializable, Parcelable
|
||||
|
||||
enum class MailboxType {
|
||||
STUDENT,
|
||||
PARENT,
|
||||
GUARDIAN,
|
||||
EMPLOYEE,
|
||||
UNKNOWN,
|
||||
}
|
@ -4,39 +4,39 @@ import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDateTime
|
||||
import java.time.Instant
|
||||
|
||||
@Entity(tableName = "Messages")
|
||||
data class Message(
|
||||
|
||||
@ColumnInfo(name = "student_id")
|
||||
val studentId: Long,
|
||||
@ColumnInfo(name = "email")
|
||||
val email: String,
|
||||
|
||||
@ColumnInfo(name = "real_id")
|
||||
val realId: Int,
|
||||
@ColumnInfo(name = "message_global_key")
|
||||
val messageGlobalKey: String,
|
||||
|
||||
@ColumnInfo(name = "mailbox_key")
|
||||
val mailboxKey: String,
|
||||
|
||||
@ColumnInfo(name = "message_id")
|
||||
val messageId: Int,
|
||||
|
||||
@ColumnInfo(name = "sender_name")
|
||||
val sender: String,
|
||||
|
||||
@ColumnInfo(name = "sender_id")
|
||||
val senderId: Int,
|
||||
|
||||
@ColumnInfo(name = "recipient_name")
|
||||
val recipient: String,
|
||||
val correspondents: String,
|
||||
|
||||
val subject: String,
|
||||
|
||||
val date: LocalDateTime,
|
||||
val date: Instant,
|
||||
|
||||
@ColumnInfo(name = "folder_id")
|
||||
val folderId: Int,
|
||||
|
||||
var unread: Boolean,
|
||||
|
||||
val removed: Boolean,
|
||||
@ColumnInfo(name = "read_by")
|
||||
val readBy: Int?,
|
||||
|
||||
@ColumnInfo(name = "unread_by")
|
||||
val unreadBy: Int?,
|
||||
|
||||
@ColumnInfo(name = "has_attachments")
|
||||
val hasAttachments: Boolean
|
||||
@ -48,11 +48,7 @@ data class Message(
|
||||
@ColumnInfo(name = "is_notified")
|
||||
var isNotified: Boolean = true
|
||||
|
||||
@ColumnInfo(name = "unread_by")
|
||||
var unreadBy: Int = 0
|
||||
|
||||
@ColumnInfo(name = "read_by")
|
||||
var readBy: Int = 0
|
||||
|
||||
var content: String = ""
|
||||
var sender: String? = null
|
||||
var recipients: String? = null
|
||||
}
|
||||
|
@ -12,11 +12,8 @@ data class MessageAttachment(
|
||||
@ColumnInfo(name = "real_id")
|
||||
val realId: Int,
|
||||
|
||||
@ColumnInfo(name = "message_id")
|
||||
val messageId: Int,
|
||||
|
||||
@ColumnInfo(name = "one_drive_id")
|
||||
val oneDriveId: String,
|
||||
@ColumnInfo(name = "message_global_key")
|
||||
val messageGlobalKey: String,
|
||||
|
||||
@ColumnInfo(name = "url")
|
||||
val url: String,
|
||||
|
@ -7,6 +7,6 @@ data class MessageWithAttachment(
|
||||
@Embedded
|
||||
val message: Message,
|
||||
|
||||
@Relation(parentColumn = "message_id", entityColumn = "message_id")
|
||||
@Relation(parentColumn = "message_global_key", entityColumn = "message_global_key")
|
||||
val attachments: List<MessageAttachment>
|
||||
)
|
||||
|
@ -4,12 +4,12 @@ import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDateTime
|
||||
import java.time.Instant
|
||||
|
||||
@Entity(tableName = "MobileDevices")
|
||||
data class MobileDevice(
|
||||
|
||||
@ColumnInfo(name = "student_id")
|
||||
@ColumnInfo(name = "user_login_id")
|
||||
val userLoginId: Int,
|
||||
|
||||
@ColumnInfo(name = "device_id")
|
||||
@ -17,7 +17,7 @@ data class MobileDevice(
|
||||
|
||||
val name: String,
|
||||
|
||||
val date: LocalDateTime
|
||||
val date: Instant,
|
||||
) : Serializable {
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
|
@ -0,0 +1,31 @@
|
||||
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,40 +1,22 @@
|
||||
package io.github.wulkanowy.data.db.entities
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import com.squareup.moshi.JsonClass
|
||||
import java.io.Serializable
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
@kotlinx.serialization.Serializable
|
||||
@Entity(tableName = "Recipients")
|
||||
data class Recipient(
|
||||
|
||||
@ColumnInfo(name = "student_id")
|
||||
val studentId: Int,
|
||||
|
||||
@ColumnInfo(name = "real_id")
|
||||
val realId: String,
|
||||
|
||||
val name: String,
|
||||
|
||||
@ColumnInfo(name = "real_name")
|
||||
val realName: String,
|
||||
|
||||
@ColumnInfo(name = "login_id")
|
||||
val loginId: Int,
|
||||
|
||||
@ColumnInfo(name = "unit_id")
|
||||
val unitId: Int,
|
||||
|
||||
val role: Int,
|
||||
|
||||
val hash: String
|
||||
|
||||
val mailboxGlobalKey: String,
|
||||
val studentMailboxGlobalKey: String,
|
||||
val fullName: String,
|
||||
val userName: String,
|
||||
val schoolShortName: String,
|
||||
val type: MailboxType,
|
||||
) : Serializable {
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
var id: Long = 0
|
||||
|
||||
override fun toString() = name
|
||||
override fun toString() = userName
|
||||
}
|
||||
|
@ -1,32 +0,0 @@
|
||||
package io.github.wulkanowy.data.db.entities
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import java.io.Serializable
|
||||
|
||||
@Entity(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")
|
||||
data class SchoolAnnouncement(
|
||||
|
||||
@ColumnInfo(name = "student_id")
|
||||
val studentId: Int,
|
||||
@ColumnInfo(name = "user_login_id")
|
||||
val userLoginId: Int,
|
||||
|
||||
val date: LocalDate,
|
||||
|
||||
|
@ -7,7 +7,12 @@ import androidx.room.PrimaryKey
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDate
|
||||
|
||||
@Entity(tableName = "Semesters", indices = [Index(value = ["student_id", "diary_id", "semester_id"], unique = true)])
|
||||
@Entity(
|
||||
tableName = "Semesters", indices = [Index(
|
||||
value = ["student_id", "diary_id", "kindergarten_diary_id", "semester_id"],
|
||||
unique = true
|
||||
)]
|
||||
)
|
||||
data class Semester(
|
||||
|
||||
@ColumnInfo(name = "student_id")
|
||||
@ -16,6 +21,9 @@ data class Semester(
|
||||
@ColumnInfo(name = "diary_id")
|
||||
val diaryId: Int,
|
||||
|
||||
@ColumnInfo(name = "kindergarten_diary_id", defaultValue = "0")
|
||||
val kindergartenDiaryId: Int,
|
||||
|
||||
@ColumnInfo(name = "diary_name")
|
||||
val diaryName: String,
|
||||
|
||||
@ -37,12 +45,11 @@ data class Semester(
|
||||
|
||||
@ColumnInfo(name = "unit_id")
|
||||
val unitId: Int
|
||||
): Serializable {
|
||||
) : Serializable {
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
var id: Long = 0
|
||||
|
||||
|
||||
@ColumnInfo(name = "is_current")
|
||||
var current: Boolean = false
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import androidx.room.Entity
|
||||
import androidx.room.Index
|
||||
import androidx.room.PrimaryKey
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDateTime
|
||||
import java.time.Instant
|
||||
|
||||
@Entity(
|
||||
tableName = "Students",
|
||||
@ -74,7 +74,7 @@ data class Student(
|
||||
val isCurrent: Boolean,
|
||||
|
||||
@ColumnInfo(name = "registration_date")
|
||||
val registrationDate: LocalDateTime
|
||||
val registrationDate: Instant,
|
||||
) : Serializable {
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
|
@ -4,8 +4,8 @@ import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import java.io.Serializable
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
|
||||
@Entity(tableName = "Timetable")
|
||||
data class Timetable(
|
||||
@ -18,9 +18,9 @@ data class Timetable(
|
||||
|
||||
val number: Int,
|
||||
|
||||
val start: LocalDateTime,
|
||||
val start: Instant,
|
||||
|
||||
val end: LocalDateTime,
|
||||
val end: Instant,
|
||||
|
||||
val date: LocalDate,
|
||||
|
||||
@ -50,4 +50,7 @@ data class Timetable(
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
var id: Long = 0
|
||||
|
||||
@ColumnInfo(name = "is_notified")
|
||||
var isNotified: Boolean = true
|
||||
}
|
||||
|
@ -4,8 +4,9 @@ import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import java.io.Serializable
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
import java.util.*
|
||||
|
||||
@Entity(tableName = "TimetableAdditional")
|
||||
data class TimetableAdditional(
|
||||
@ -16,9 +17,9 @@ data class TimetableAdditional(
|
||||
@ColumnInfo(name = "diary_id")
|
||||
val diaryId: Int,
|
||||
|
||||
val start: LocalDateTime,
|
||||
val start: Instant,
|
||||
|
||||
val end: LocalDateTime,
|
||||
val end: Instant,
|
||||
|
||||
val date: LocalDate,
|
||||
|
||||
@ -27,4 +28,10 @@ data class TimetableAdditional(
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
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,12 +43,14 @@ class Migration12 : Migration(11, 12) {
|
||||
|
||||
private fun getStudentsIds(database: SupportSQLiteDatabase): List<Int> {
|
||||
val students = mutableListOf<Int>()
|
||||
val studentsCursor = database.query("SELECT student_id FROM Students")
|
||||
if (studentsCursor.moveToFirst()) {
|
||||
do {
|
||||
students.add(studentsCursor.getInt(0))
|
||||
} while (studentsCursor.moveToNext())
|
||||
database.query("SELECT student_id FROM Students").use {
|
||||
if (it.moveToFirst()) {
|
||||
do {
|
||||
students.add(it.getInt(0))
|
||||
} while (it.moveToNext())
|
||||
}
|
||||
}
|
||||
|
||||
return students
|
||||
}
|
||||
|
||||
|
@ -25,12 +25,14 @@ class Migration13 : Migration(12, 13) {
|
||||
|
||||
private fun getStudentsIds(database: SupportSQLiteDatabase): MutableList<Pair<Int, String>> {
|
||||
val students = mutableListOf<Pair<Int, String>>()
|
||||
val studentsCursor = database.query("SELECT id, school_name FROM Students")
|
||||
if (studentsCursor.moveToFirst()) {
|
||||
do {
|
||||
students.add(studentsCursor.getInt(0) to studentsCursor.getString(1))
|
||||
} while (studentsCursor.moveToNext())
|
||||
database.query("SELECT id, school_name FROM Students").use {
|
||||
if (it.moveToFirst()) {
|
||||
do {
|
||||
students.add(it.getInt(0) to it.getString(1))
|
||||
} while (it.moveToNext())
|
||||
}
|
||||
}
|
||||
|
||||
return students
|
||||
}
|
||||
|
||||
@ -42,12 +44,14 @@ class Migration13 : Migration(12, 13) {
|
||||
|
||||
private fun getStudentsAndClassIds(database: SupportSQLiteDatabase): List<Pair<Int, Int>> {
|
||||
val students = mutableListOf<Pair<Int, Int>>()
|
||||
val studentsCursor = database.query("SELECT student_id, class_id FROM Students")
|
||||
if (studentsCursor.moveToFirst()) {
|
||||
do {
|
||||
students.add(studentsCursor.getInt(0) to studentsCursor.getInt(1))
|
||||
} while (studentsCursor.moveToNext())
|
||||
database.query("SELECT student_id, class_id FROM Students").use {
|
||||
if (it.moveToFirst()) {
|
||||
do {
|
||||
students.add(it.getInt(0) to it.getInt(1))
|
||||
} while (it.moveToNext())
|
||||
}
|
||||
}
|
||||
|
||||
return students
|
||||
}
|
||||
|
||||
|
@ -22,24 +22,28 @@ class Migration27 : Migration(26, 27) {
|
||||
|
||||
private fun getStudentsIdsAndNames(database: SupportSQLiteDatabase): MutableList<Triple<Long, Int, String>> {
|
||||
val students = mutableListOf<Triple<Long, Int, String>>()
|
||||
val studentsCursor = database.query("SELECT id, user_login_id, student_name FROM Students")
|
||||
if (studentsCursor.moveToFirst()) {
|
||||
do {
|
||||
students.add(Triple(studentsCursor.getLong(0), studentsCursor.getInt(1), studentsCursor.getString(2)))
|
||||
} while (studentsCursor.moveToNext())
|
||||
database.query("SELECT id, user_login_id, student_name FROM Students").use {
|
||||
if (it.moveToFirst()) {
|
||||
do {
|
||||
students.add(Triple(it.getLong(0), it.getInt(1), it.getString(2)))
|
||||
} while (it.moveToNext())
|
||||
}
|
||||
}
|
||||
|
||||
return students
|
||||
}
|
||||
|
||||
private fun getReportingUnits(database: SupportSQLiteDatabase): MutableList<Pair<Int, String>> {
|
||||
val units = mutableListOf<Pair<Int, String>>()
|
||||
val unitsCursor = database.query("SELECT sender_id, sender_name FROM ReportingUnits")
|
||||
if (unitsCursor.moveToFirst()) {
|
||||
do {
|
||||
units.add(unitsCursor.getInt(0) to unitsCursor.getString(1))
|
||||
} while (unitsCursor.moveToNext())
|
||||
database.query("SELECT sender_id, sender_name FROM ReportingUnits").use {
|
||||
if (it.moveToFirst()) {
|
||||
do {
|
||||
units.add(it.getInt(0) to it.getString(1))
|
||||
} while (it.moveToNext())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return units
|
||||
}
|
||||
}
|
||||
|
@ -10,15 +10,17 @@ class Migration35(private val appInfo: AppInfo) : Migration(34, 35) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Students ADD COLUMN `avatar_color` INTEGER NOT NULL DEFAULT 0")
|
||||
|
||||
val studentsCursor = database.query("SELECT * FROM Students")
|
||||
|
||||
while (studentsCursor.moveToNext()) {
|
||||
val studentId = studentsCursor.getLongOrNull(0)
|
||||
database.execSQL(
|
||||
"""UPDATE Students
|
||||
SET avatar_color = ${appInfo.defaultColorsForAvatar.random()}
|
||||
WHERE id = $studentId"""
|
||||
)
|
||||
database.query("SELECT * FROM Students").use {
|
||||
while (it.moveToNext()) {
|
||||
val studentId = it.getLongOrNull(0)
|
||||
database.execSQL(
|
||||
"""
|
||||
UPDATE Students
|
||||
SET avatar_color = ${appInfo.defaultColorsForAvatar.random()}
|
||||
WHERE id = $studentId
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
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
|
||||
)
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
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")
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
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`))"""
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
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")
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
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")
|
||||
}
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
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()
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
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()
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
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()
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
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")
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package io.github.wulkanowy.data.db.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration53 : Migration(52, 53) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
createMailboxTable(database)
|
||||
recreateMessagesTable(database)
|
||||
}
|
||||
|
||||
private fun createMailboxTable(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE IF EXISTS Mailboxes")
|
||||
database.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS `Mailboxes` (
|
||||
`globalKey` TEXT NOT NULL,
|
||||
`email` TEXT NOT NULL,
|
||||
`symbol` TEXT NOT NULL,
|
||||
`schoolId` TEXT NOT NULL,
|
||||
`fullName` TEXT NOT NULL,
|
||||
`userName` TEXT NOT NULL,
|
||||
`studentName` TEXT NOT NULL,
|
||||
`schoolNameShort` TEXT NOT NULL,
|
||||
`type` TEXT NOT NULL,
|
||||
PRIMARY KEY(`globalKey`)
|
||||
)""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
private fun recreateMessagesTable(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE IF EXISTS Messages")
|
||||
database.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS `Messages` (
|
||||
`email` TEXT NOT NULL,
|
||||
`message_global_key` TEXT NOT NULL,
|
||||
`mailbox_key` TEXT NOT NULL,
|
||||
`message_id` INTEGER NOT NULL,
|
||||
`correspondents` TEXT NOT NULL,
|
||||
`subject` TEXT NOT NULL,
|
||||
`date` INTEGER NOT NULL,
|
||||
`folder_id` INTEGER NOT NULL,
|
||||
`unread` INTEGER NOT NULL,
|
||||
`read_by` INTEGER,
|
||||
`unread_by` INTEGER,
|
||||
`has_attachments` INTEGER NOT NULL,
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
`is_notified` INTEGER NOT NULL,
|
||||
`content` TEXT NOT NULL,
|
||||
`sender` TEXT,
|
||||
`recipients` TEXT
|
||||
)""".trimIndent()
|
||||
)
|
||||
}
|
||||
}
|
12
app/src/main/java/io/github/wulkanowy/data/enums/AppTheme.kt
Normal file
12
app/src/main/java/io/github/wulkanowy/data/enums/AppTheme.kt
Normal file
@ -0,0 +1,12 @@
|
||||
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
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
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
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
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
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
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
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
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,
|
||||
agenda = it.agenda,
|
||||
conferenceId = it.id,
|
||||
date = it.date,
|
||||
date = it.dateZoned.toInstant(),
|
||||
presentOnConference = it.presentOnConference,
|
||||
subject = it.subject,
|
||||
title = it.title
|
||||
|
@ -6,7 +6,7 @@ import io.github.wulkanowy.sdk.pojo.DirectorInformation as SdkDirectorInformatio
|
||||
|
||||
fun List<SdkDirectorInformation>.mapToEntities(student: Student) = map {
|
||||
SchoolAnnouncement(
|
||||
studentId = student.studentId,
|
||||
userLoginId = student.userLoginId,
|
||||
date = it.date,
|
||||
subject = it.subject,
|
||||
content = it.content,
|
||||
|
@ -0,0 +1,20 @@
|
||||
package io.github.wulkanowy.data.mappers
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Mailbox
|
||||
import io.github.wulkanowy.data.db.entities.MailboxType
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.sdk.pojo.Mailbox as SdkMailbox
|
||||
|
||||
fun List<SdkMailbox>.mapToEntities(student: Student) = map {
|
||||
Mailbox(
|
||||
globalKey = it.globalKey,
|
||||
fullName = it.fullName,
|
||||
userName = it.userName,
|
||||
studentName = it.studentName,
|
||||
schoolNameShort = it.schoolNameShort,
|
||||
type = MailboxType.valueOf(it.type.name),
|
||||
email = student.email,
|
||||
symbol = student.symbol,
|
||||
schoolId = student.schoolSymbol,
|
||||
)
|
||||
}
|
@ -1,40 +1,36 @@
|
||||
package io.github.wulkanowy.data.mappers
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Message
|
||||
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.data.db.entities.*
|
||||
import io.github.wulkanowy.sdk.pojo.MailboxType
|
||||
import io.github.wulkanowy.sdk.pojo.Message as SdkMessage
|
||||
import io.github.wulkanowy.sdk.pojo.MessageAttachment as SdkMessageAttachment
|
||||
import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient
|
||||
|
||||
fun List<SdkMessage>.mapToEntities(student: Student) = map {
|
||||
fun List<SdkMessage>.mapToEntities(student: Student, mailbox: Mailbox?, allMailboxes: List<Mailbox>) = map {
|
||||
Message(
|
||||
studentId = student.id,
|
||||
realId = it.id ?: 0,
|
||||
messageId = it.messageId ?: 0,
|
||||
sender = it.sender?.name.orEmpty(),
|
||||
senderId = it.sender?.loginId ?: 0,
|
||||
recipient = it.recipients.singleOrNull()?.name ?: "Wielu adresatów",
|
||||
messageGlobalKey = it.globalKey,
|
||||
mailboxKey = mailbox?.globalKey ?: allMailboxes.find { box ->
|
||||
box.fullName == it.mailbox
|
||||
}?.globalKey!!,
|
||||
email = student.email,
|
||||
messageId = it.id,
|
||||
correspondents = it.correspondents,
|
||||
subject = it.subject.trim(),
|
||||
date = it.date ?: LocalDateTime.now(),
|
||||
date = it.dateZoned.toInstant(),
|
||||
folderId = it.folderId,
|
||||
unread = it.unread ?: false,
|
||||
removed = it.removed,
|
||||
hasAttachments = it.hasAttachments
|
||||
unread = it.unread,
|
||||
unreadBy = it.unreadBy,
|
||||
readBy = it.readBy,
|
||||
hasAttachments = it.hasAttachments,
|
||||
).apply {
|
||||
content = it.content.orEmpty()
|
||||
unreadBy = it.unreadBy ?: 0
|
||||
readBy = it.readBy ?: 0
|
||||
}
|
||||
}
|
||||
|
||||
fun List<SdkMessageAttachment>.mapToEntities() = map {
|
||||
fun List<SdkMessageAttachment>.mapToEntities(messageGlobalKey: String) = map {
|
||||
MessageAttachment(
|
||||
realId = it.id,
|
||||
messageId = it.messageId,
|
||||
oneDriveId = it.oneDriveId,
|
||||
messageGlobalKey = messageGlobalKey,
|
||||
realId = it.url.hashCode(),
|
||||
url = it.url,
|
||||
filename = it.filename
|
||||
)
|
||||
@ -42,12 +38,11 @@ fun List<SdkMessageAttachment>.mapToEntities() = map {
|
||||
|
||||
fun List<Recipient>.mapFromEntities() = map {
|
||||
SdkRecipient(
|
||||
id = it.realId,
|
||||
name = it.realName,
|
||||
loginId = it.loginId,
|
||||
reportingUnitId = it.unitId,
|
||||
role = it.role,
|
||||
hash = it.hash,
|
||||
shortName = it.name
|
||||
fullName = it.fullName,
|
||||
userName = it.userName,
|
||||
studentName = it.userName,
|
||||
mailboxGlobalKey = it.mailboxGlobalKey,
|
||||
schoolNameShort = it.schoolShortName,
|
||||
type = MailboxType.valueOf(it.type.name),
|
||||
)
|
||||
}
|
||||
|
@ -1,15 +1,15 @@
|
||||
package io.github.wulkanowy.data.mappers
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.MobileDevice
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.pojos.MobileDeviceToken
|
||||
import io.github.wulkanowy.sdk.pojo.Token as SdkToken
|
||||
import io.github.wulkanowy.sdk.pojo.Device as SdkDevice
|
||||
import io.github.wulkanowy.sdk.pojo.Token as SdkToken
|
||||
|
||||
fun List<SdkDevice>.mapToEntities(semester: Semester) = map {
|
||||
fun List<SdkDevice>.mapToEntities(student: Student) = map {
|
||||
MobileDevice(
|
||||
userLoginId = semester.studentId,
|
||||
date = it.createDate,
|
||||
userLoginId = student.userLoginId,
|
||||
date = it.createDateZoned.toInstant(),
|
||||
deviceId = it.id,
|
||||
name = it.name
|
||||
)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user