Compare commits
666 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e03aae2d56 | ||
![]() |
9c60ce688b | ||
![]() |
fdce2cf477 | ||
![]() |
650cbd5a10 | ||
![]() |
b160367744 | ||
![]() |
6c115fb915 | ||
![]() |
7a408899df | ||
![]() |
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 | ||
![]() |
db6c84775b | ||
![]() |
72d8b4aa84 | ||
![]() |
170b7c4379 | ||
![]() |
79e9e1a780 | ||
![]() |
98dcc62bb7 | ||
![]() |
ea0fb00bde | ||
![]() |
4aa6b0b995 | ||
![]() |
57d11e825b | ||
![]() |
2f43b6e552 | ||
![]() |
765f8a2d1f | ||
![]() |
04c727a0c8 | ||
![]() |
55518cb044 | ||
![]() |
cebd1aa75d | ||
![]() |
4a38a0be70 | ||
![]() |
b4b9d91ea6 | ||
![]() |
a6a2bcff3b | ||
![]() |
2979d8b62a | ||
![]() |
aba2068a84 | ||
![]() |
076948a680 | ||
![]() |
1cfabe43a5 | ||
![]() |
02b87c8c6a | ||
![]() |
eb94e06d54 | ||
![]() |
d3b3939d26 | ||
![]() |
9c5d2fbf84 | ||
![]() |
428e40d7fe | ||
![]() |
9c819835ca | ||
![]() |
626169de11 | ||
![]() |
72ef5f428e | ||
![]() |
4ae3f7b016 | ||
![]() |
7c94837af0 | ||
![]() |
2a91346155 | ||
![]() |
ec6d18968f | ||
![]() |
b61e63249c | ||
![]() |
d73aa605f9 | ||
![]() |
14f4808434 | ||
![]() |
2bc6d7ad0d | ||
![]() |
888052cd9c | ||
![]() |
bdc2281fdc | ||
![]() |
d01edc2312 | ||
![]() |
484a3aa731 | ||
![]() |
51be23470f | ||
![]() |
19495ffce9 | ||
![]() |
bd766d33db | ||
![]() |
ff8b3f8837 | ||
![]() |
e678e6d7f9 | ||
![]() |
f6f3447f1d | ||
![]() |
e1c1f305c4 | ||
![]() |
c8c9001277 | ||
![]() |
3422951e47 | ||
![]() |
3278c11cce | ||
![]() |
e00dea51f1 | ||
![]() |
5bf411039d | ||
![]() |
62ca394c9a | ||
![]() |
255b89bbb3 | ||
![]() |
f7987f4b29 | ||
![]() |
0b583439dd | ||
![]() |
ca481dc6f5 | ||
![]() |
f6a92a4cc3 | ||
![]() |
55a6219a42 | ||
![]() |
ad653f10df | ||
![]() |
7a780486f6 | ||
![]() |
c01b0eff9d | ||
![]() |
3a4614e2b7 | ||
![]() |
44ee8859b1 | ||
![]() |
3dd7878ae5 | ||
![]() |
0305a005ab | ||
![]() |
2229f0e3e9 | ||
![]() |
d9aab7afa2 | ||
![]() |
0558f30646 | ||
![]() |
238f257c6c | ||
![]() |
40372e7cea | ||
![]() |
b65a060fca | ||
![]() |
c1ed748188 | ||
![]() |
b911521ccc | ||
![]() |
b046679542 | ||
![]() |
3decc95a20 | ||
![]() |
c301198006 | ||
![]() |
190a5f2067 | ||
![]() |
27e1a07eec | ||
![]() |
64feae9f1c | ||
![]() |
085158721e | ||
![]() |
44888b048d | ||
![]() |
b9a12e46bf | ||
![]() |
2fe5e62e72 | ||
![]() |
6305e1a908 | ||
![]() |
6bf7a2e26c | ||
![]() |
34487175d8 | ||
![]() |
f02db914bf | ||
![]() |
18e0a59e2b | ||
![]() |
e4371af284 | ||
![]() |
44d5f69de1 | ||
![]() |
d13e0adb00 | ||
![]() |
e60e573ac0 | ||
![]() |
91dbc9e3d7 | ||
![]() |
8ccbea2c21 | ||
![]() |
211cb5e4f2 | ||
![]() |
b60c59216d | ||
![]() |
d20f3180cf | ||
![]() |
17761af9d6 | ||
![]() |
067817bace | ||
![]() |
51800d91b2 | ||
![]() |
3640c4f249 | ||
![]() |
05aa38b591 | ||
![]() |
983dcd8656 | ||
![]() |
59cf4fb222 | ||
![]() |
d6ebcc97e3 | ||
![]() |
047579c394 | ||
![]() |
a90fd4b776 | ||
![]() |
03d3a5db11 | ||
![]() |
bf5e61490d | ||
![]() |
d87fa589a8 | ||
![]() |
1fff1c2b14 | ||
![]() |
58d66b6e70 | ||
![]() |
202d13d509 | ||
![]() |
db808de06c | ||
![]() |
d8dae09f39 | ||
![]() |
32640e0796 | ||
![]() |
4e80441167 | ||
![]() |
075cfb20b1 | ||
![]() |
56e4e9be5e | ||
![]() |
53c798ebdb | ||
![]() |
022a4d1ea2 | ||
![]() |
dfa25d8445 | ||
![]() |
b2efe0d981 | ||
![]() |
2a7f846d3f | ||
![]() |
da5817d08a | ||
![]() |
cacf2f651a | ||
![]() |
605c816a32 | ||
![]() |
1587be2fa8 | ||
![]() |
00b23ca20c | ||
![]() |
34db20ab0c | ||
![]() |
0d271d925a | ||
![]() |
b7da43a52a | ||
![]() |
44af5d59fb | ||
![]() |
bc776993a9 | ||
![]() |
9a19ce9ca4 | ||
![]() |
6855296de4 | ||
![]() |
b695c7f600 | ||
![]() |
3a1a383383 | ||
![]() |
97810d02ab | ||
![]() |
30b337a364 | ||
![]() |
8f6c847562 | ||
![]() |
e5d54c95f3 | ||
![]() |
eb5ad81ec1 | ||
![]() |
3aa9f0ca2f | ||
![]() |
8e587358aa | ||
![]() |
4492f4a864 | ||
![]() |
b453225941 | ||
![]() |
13ccfda009 | ||
![]() |
95ffb0a687 | ||
![]() |
f131edf857 | ||
![]() |
bd2d26418a | ||
![]() |
aeb3b2a030 | ||
![]() |
7bc5219d81 | ||
![]() |
6cb4ea4b0f | ||
![]() |
0bdd33ef4a | ||
![]() |
792de4cd3d | ||
![]() |
3071e19584 | ||
![]() |
f2130998ec | ||
![]() |
8a5ca8c91f | ||
![]() |
fada13e2d3 | ||
![]() |
6e19eb943d | ||
![]() |
c70fe3430c |
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
|
|
@ -1,3 +1,12 @@
|
||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Utwórz raport błędu, aby pomóc nam ulepszyć Wulkanowego
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Co powinno się dziać
|
## Co powinno się dziać
|
||||||
|
|
||||||
|
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Zaproponuj nowy pomysł dla Wulkanowego
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
** Czy Twoja prośba o funkcję jest związana z problemem? Proszę opisz.**
|
||||||
|
Jasny i zwięzły opis problemu. Np. Zawsze jestem sfrustrowany, gdy [...]
|
||||||
|
|
||||||
|
** Opisz żądane rozwiązanie **
|
||||||
|
Jasny i zwięzły opis tego, co chcesz, aby się wydarzyło.
|
||||||
|
|
||||||
|
** Opisz alternatywy, które rozważałeś **
|
||||||
|
Jasny i zwięzły opis wszelkich rozważanych alternatywnych rozwiązań lub funkcji.
|
||||||
|
|
||||||
|
** Dodatkowy kontekst **
|
||||||
|
Dodaj inny kontekst lub zrzuty ekranu dotyczące żądania funkcji tutaj.
|
12
.github/dependabot.yml
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: gradle
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: weekly
|
||||||
|
open-pull-requests-limit: 10
|
||||||
|
target-branch: develop
|
||||||
|
ignore:
|
||||||
|
- dependency-name: io.github.wulkanowy:sdk
|
||||||
|
reviewers:
|
||||||
|
- Faierbel
|
48
.github/workflows/deploy-store.yml
vendored
|
@ -1,4 +1,4 @@
|
||||||
name: Deploy to app stores
|
name: Deploy release
|
||||||
|
|
||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
|
@ -7,16 +7,17 @@ on:
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
deploy-google-play:
|
deploy-google-play:
|
||||||
name: Deploy to google play
|
name: Google Play
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
environment: google-play
|
environment: google-play
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-java@v1
|
- uses: actions/setup-java@v2
|
||||||
with:
|
with:
|
||||||
|
distribution: 'zulu'
|
||||||
java-version: 11
|
java-version: 11
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.gradle/caches
|
~/.gradle/caches
|
||||||
|
@ -28,27 +29,31 @@ jobs:
|
||||||
SERVICES_ENCRYPT_KEY: ${{ secrets.SERVICES_ENCRYPT_KEY }}
|
SERVICES_ENCRYPT_KEY: ${{ secrets.SERVICES_ENCRYPT_KEY }}
|
||||||
run: |
|
run: |
|
||||||
gpg --yes --batch --passphrase=$SERVICES_ENCRYPT_KEY ./app/src/release/google-services.json.gpg
|
gpg --yes --batch --passphrase=$SERVICES_ENCRYPT_KEY ./app/src/release/google-services.json.gpg
|
||||||
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/key.p12.gpg
|
|
||||||
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/upload-key.jks.gpg
|
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/upload-key.jks.gpg
|
||||||
- name: Upload apk to google play
|
- name: Upload apk to google play
|
||||||
env:
|
env:
|
||||||
|
PLAY_STORE_PASSWORD: ${{ secrets.PLAY_STORE_PASSWORD }}
|
||||||
PLAY_KEY_ALIAS: ${{ secrets.PLAY_KEY_ALIAS }}
|
PLAY_KEY_ALIAS: ${{ secrets.PLAY_KEY_ALIAS }}
|
||||||
PLAY_KEY_PASSWORD: ${{ secrets.PLAY_KEY_PASSWORD }}
|
PLAY_KEY_PASSWORD: ${{ secrets.PLAY_KEY_PASSWORD }}
|
||||||
PLAY_SERVICE_ACCOUNT_EMAIL: ${{ secrets.PLAY_SERVICE_ACCOUNT_EMAIL }}
|
ANDROID_PUBLISHER_CREDENTIALS: ${{ secrets.ANDROID_PUBLISHER_CREDENTIALS }}
|
||||||
PLAY_STORE_PASSWORD: ${{ secrets.PLAY_STORE_PASSWORD }}
|
ADMOB_PROJECT_ID: ${{ secrets.ADMOB_PROJECT_ID }}
|
||||||
run: ./gradlew publishPlayRelease -PenableFirebase --stacktrace;
|
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:
|
deploy-app-gallery:
|
||||||
name: Deploy to AppGallery
|
name: AppGallery
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
environment: app-gallery
|
environment: app-gallery
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-java@v1
|
- uses: actions/setup-java@v2
|
||||||
with:
|
with:
|
||||||
|
distribution: 'zulu'
|
||||||
java-version: 11
|
java-version: 11
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.gradle/caches
|
~/.gradle/caches
|
||||||
|
@ -60,16 +65,15 @@ jobs:
|
||||||
SERVICES_ENCRYPT_KEY: ${{ secrets.SERVICES_ENCRYPT_KEY }}
|
SERVICES_ENCRYPT_KEY: ${{ secrets.SERVICES_ENCRYPT_KEY }}
|
||||||
run: |
|
run: |
|
||||||
gpg --yes --batch --passphrase=$SERVICES_ENCRYPT_KEY ./app/src/release/agconnect-services.json.gpg
|
gpg --yes --batch --passphrase=$SERVICES_ENCRYPT_KEY ./app/src/release/agconnect-services.json.gpg
|
||||||
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/key.p12.gpg
|
|
||||||
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/upload-key.jks.gpg
|
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/upload-key.jks.gpg
|
||||||
- name: Build HMS version
|
- name: Prepare credentials
|
||||||
env:
|
env:
|
||||||
|
AGC_CREDENTIALS: ${{ secrets.AGC_CREDENTIALS }}
|
||||||
|
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_ALIAS: ${{ secrets.PLAY_KEY_ALIAS }}
|
||||||
PLAY_KEY_PASSWORD: ${{ secrets.PLAY_KEY_PASSWORD }}
|
PLAY_KEY_PASSWORD: ${{ secrets.PLAY_KEY_PASSWORD }}
|
||||||
PLAY_STORE_PASSWORD: ${{ secrets.PLAY_STORE_PASSWORD }}
|
SET_BUILD_TIMESTAMP: ${{ secrets.SET_BUILD_TIMESTAMP }}
|
||||||
run: ./gradlew assembleHmsRelease --stacktrace
|
run: ./gradlew bundleHmsRelease --stacktrace && ./gradlew publishHuaweiAppGalleryHmsRelease --stacktrace
|
||||||
- name: Upload APK to AppGallery
|
|
||||||
env:
|
|
||||||
AGC_CLIENT_ID: ${{ secrets.AGC_CLIENT_ID }}
|
|
||||||
AGC_CLIENT_SECRET: ${{ secrets.AGC_CLIENT_SECRET }}
|
|
||||||
run: ./gradlew publishHuaweiAppGalleryHmsRelease --stacktrace;
|
|
||||||
|
|
20
.github/workflows/deploy-test.yml
vendored
|
@ -1,4 +1,4 @@
|
||||||
name: Deploy to app tests
|
name: Deploy DEV
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
@ -18,11 +18,12 @@ jobs:
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
environment: app-center
|
environment: app-center
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-java@v1
|
- uses: actions/setup-java@v2
|
||||||
with:
|
with:
|
||||||
|
distribution: 'zulu'
|
||||||
java-version: 11
|
java-version: 11
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.gradle/caches
|
~/.gradle/caches
|
||||||
|
@ -66,7 +67,7 @@ jobs:
|
||||||
BITRISE_KEY_PASSWORD: ${{ secrets.BITRISE_KEY_PASSWORD }}
|
BITRISE_KEY_PASSWORD: ${{ secrets.BITRISE_KEY_PASSWORD }}
|
||||||
run: ./gradlew assembleFdroidDebug --stacktrace
|
run: ./gradlew assembleFdroidDebug --stacktrace
|
||||||
- name: Upload apk to github artifacts
|
- name: Upload apk to github artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: wulkanowyDEV-${{ env.RUN_NUMBER }}.apk
|
name: wulkanowyDEV-${{ env.RUN_NUMBER }}.apk
|
||||||
path: app/build/outputs/apk/fdroid/debug/app-fdroid-debug.apk
|
path: app/build/outputs/apk/fdroid/debug/app-fdroid-debug.apk
|
||||||
|
@ -87,11 +88,12 @@ jobs:
|
||||||
environment: app-distribution
|
environment: app-distribution
|
||||||
if: github.event_name != 'pull_request_target'
|
if: github.event_name != 'pull_request_target'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-java@v1
|
- uses: actions/setup-java@v2
|
||||||
with:
|
with:
|
||||||
|
distribution: 'zulu'
|
||||||
java-version: 11
|
java-version: 11
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.gradle/caches
|
~/.gradle/caches
|
||||||
|
@ -131,7 +133,7 @@ jobs:
|
||||||
BITRISE_KEY_PASSWORD: ${{ secrets.BITRISE_KEY_PASSWORD }}
|
BITRISE_KEY_PASSWORD: ${{ secrets.BITRISE_KEY_PASSWORD }}
|
||||||
run: ./gradlew assemblePlayDebug -PenableFirebase --stacktrace
|
run: ./gradlew assemblePlayDebug -PenableFirebase --stacktrace
|
||||||
- name: Upload apk to github artifacts
|
- name: Upload apk to github artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: wulkanowyDEV-${{ env.RUN_NUMBER }}-dev.apk
|
name: wulkanowyDEV-${{ env.RUN_NUMBER }}-dev.apk
|
||||||
path: app/build/outputs/apk/play/debug/app-play-debug.apk
|
path: app/build/outputs/apk/play/debug/app-play-debug.apk
|
||||||
|
|
70
.github/workflows/test.yml
vendored
|
@ -8,18 +8,20 @@ on:
|
||||||
branches: [ master, develop ]
|
branches: [ master, develop ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
unit-tests:
|
|
||||||
name: Unit tests
|
tests-fdroid:
|
||||||
|
name: F-Droid
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
steps:
|
steps:
|
||||||
- uses: fkirc/skip-duplicate-actions@master
|
- uses: fkirc/skip-duplicate-actions@master
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- uses: gradle/wrapper-validation-action@v1
|
- uses: gradle/wrapper-validation-action@v1
|
||||||
- uses: actions/setup-java@v1
|
- uses: actions/setup-java@v2
|
||||||
with:
|
with:
|
||||||
|
distribution: 'zulu'
|
||||||
java-version: 11
|
java-version: 11
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.gradle/caches
|
~/.gradle/caches
|
||||||
|
@ -27,8 +29,60 @@ jobs:
|
||||||
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}
|
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}
|
||||||
- name: Unit tests
|
- name: Unit tests
|
||||||
run: |
|
run: |
|
||||||
./gradlew --build-cache -Pcoverage testFdroidDebugUnitTest --stacktrace
|
./gradlew testFdroidDebugUnitTest --stacktrace
|
||||||
./gradlew --build-cache -Pcoverage jacocoTestReport --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:
|
with:
|
||||||
flags: unit
|
flags: unit
|
||||||
|
|
2
.gitignore
vendored
|
@ -117,3 +117,5 @@ Thumbs.db
|
||||||
|
|
||||||
|
|
||||||
app/src/release/agconnect-services.json
|
app/src/release/agconnect-services.json
|
||||||
|
app/src/release/agconnect-credentials.json
|
||||||
|
.idea/deploymentTargetDropDown.xml
|
||||||
|
|
24
.idea/codeStyles/Project.xml
generated
|
@ -2,23 +2,6 @@
|
||||||
<code_scheme name="Project" version="173">
|
<code_scheme name="Project" version="173">
|
||||||
<option name="LINE_SEPARATOR" value=" " />
|
<option name="LINE_SEPARATOR" value=" " />
|
||||||
<JetCodeStyleSettings>
|
<JetCodeStyleSettings>
|
||||||
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
|
||||||
<value>
|
|
||||||
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
|
|
||||||
</value>
|
|
||||||
</option>
|
|
||||||
<option name="PACKAGES_IMPORT_LAYOUT">
|
|
||||||
<value>
|
|
||||||
<package name="" alias="false" withSubpackages="true" />
|
|
||||||
<package name="java" alias="false" withSubpackages="true" />
|
|
||||||
<package name="javax" alias="false" withSubpackages="true" />
|
|
||||||
<package name="kotlin" alias="false" withSubpackages="true" />
|
|
||||||
<package name="" alias="true" withSubpackages="true" />
|
|
||||||
</value>
|
|
||||||
</option>
|
|
||||||
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
|
|
||||||
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
|
|
||||||
<option name="WRAP_ELVIS_EXPRESSIONS" value="0" />
|
|
||||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||||
</JetCodeStyleSettings>
|
</JetCodeStyleSettings>
|
||||||
<codeStyleSettings language="XML">
|
<codeStyleSettings language="XML">
|
||||||
|
@ -135,13 +118,6 @@
|
||||||
</codeStyleSettings>
|
</codeStyleSettings>
|
||||||
<codeStyleSettings language="kotlin">
|
<codeStyleSettings language="kotlin">
|
||||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||||
<option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1" />
|
|
||||||
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
|
|
||||||
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="0" />
|
|
||||||
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
|
|
||||||
<indentOptions>
|
|
||||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
|
||||||
</indentOptions>
|
|
||||||
</codeStyleSettings>
|
</codeStyleSettings>
|
||||||
</code_scheme>
|
</code_scheme>
|
||||||
</component>
|
</component>
|
2
LICENSE
|
@ -186,7 +186,7 @@
|
||||||
same "printed page" as the copyright notice for easier
|
same "printed page" as the copyright notice for easier
|
||||||
identification within third-party archives.
|
identification within third-party archives.
|
||||||
|
|
||||||
Copyright 2019 Wulkanowy
|
Copyright 2022 Wulkanowy
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
|
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
|
||||||
|
* volitelné reklamy na podporu projektu
|
||||||
|
|
||||||
|
## 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
|
@ -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
|
||||||
|
* abgeschlossene Unterrichtsstunden
|
||||||
|
* 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
|
||||||
|
* optionale Werbungen, die es uns ermöglichen das Projekt zu unterstützen
|
||||||
|
|
||||||
|
## 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,12 +1,13 @@
|
||||||
[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
|
# Wulkanowy
|
||||||
|
|
||||||
[](https://github.com/wulkanowy/wulkanowy/actions)
|
[](https://github.com/wulkanowy/wulkanowy/actions)
|
||||||
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
||||||
[](https://discord.gg/vccAQBr)
|
[](https://discord.gg/vccAQBr)
|
||||||
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
||||||
[](https://github.com/wulkanowy/wulkanowy/releases)
|
[](https://github.com/wulkanowy/wulkanowy/releases)
|
||||||
|
[](https://translate.wulkanowy.net.pl)
|
||||||
|
|
||||||
Unofficial android VULCAN UONET+ register client for both students and their parents
|
Unofficial android VULCAN UONET+ register client for both students and their parents
|
||||||
|
|
||||||
|
@ -33,7 +34,7 @@ Unofficial android VULCAN UONET+ register client for both students and their par
|
||||||
* support for multiple accounts with the ability to rename students
|
* support for multiple accounts with the ability to rename students
|
||||||
* dark and black (AMOLED) theme
|
* dark and black (AMOLED) theme
|
||||||
* offline mode
|
* offline mode
|
||||||
* no ads
|
* optional ads which allow to support the project
|
||||||
|
|
||||||
## Download
|
## Download
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
[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
|
# Wulkanowy
|
||||||
|
|
||||||
[](https://github.com/wulkanowy/wulkanowy/actions)
|
[](https://github.com/wulkanowy/wulkanowy/actions)
|
||||||
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
||||||
[](https://discord.gg/vccAQBr)
|
[](https://discord.gg/vccAQBr)
|
||||||
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
||||||
[](https://github.com/wulkanowy/wulkanowy/releases)
|
[](https://github.com/wulkanowy/wulkanowy/releases)
|
||||||
|
[](https://translate.wulkanowy.net.pl)
|
||||||
|
|
||||||
Nieoficjalny klient dziennika VULCAN UONET+ dla ucznia i rodzica
|
Nieoficjalny klient dziennika VULCAN UONET+ dla ucznia i rodzica
|
||||||
|
|
||||||
|
@ -33,7 +34,7 @@ Nieoficjalny klient dziennika VULCAN UONET+ dla ucznia i rodzica
|
||||||
* obsługa wielu kont wraz z możliwością zmiany nazwy ucznia
|
* obsługa wielu kont wraz z możliwością zmiany nazwy ucznia
|
||||||
* ciemny i czarny (AMOLED) motyw
|
* ciemny i czarny (AMOLED) motyw
|
||||||
* tryb offline
|
* tryb offline
|
||||||
* brak reklam
|
* opcjonalne reklamy umożliwiające wsparcie projektu
|
||||||
|
|
||||||
## Pobierz
|
## Pobierz
|
||||||
|
|
||||||
|
|
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
|
||||||
|
* voliteľné reklamy na podporu projektu
|
||||||
|
|
||||||
|
## 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)
|
206
app/build.gradle
|
@ -1,37 +1,37 @@
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
|
apply plugin: 'kotlinx-serialization'
|
||||||
|
apply plugin: 'kotlin-parcelize'
|
||||||
apply plugin: 'kotlin-kapt'
|
apply plugin: 'kotlin-kapt'
|
||||||
apply plugin: 'dagger.hilt.android.plugin'
|
apply plugin: 'dagger.hilt.android.plugin'
|
||||||
|
apply plugin: 'com.google.gms.google-services'
|
||||||
apply plugin: 'com.google.firebase.crashlytics'
|
apply plugin: 'com.google.firebase.crashlytics'
|
||||||
apply plugin: 'com.github.triplet.play'
|
apply plugin: 'com.github.triplet.play'
|
||||||
apply plugin: 'ru.cian.huawei-publish'
|
apply plugin: 'ru.cian.huawei-publish'
|
||||||
apply plugin: 'com.mikepenz.aboutlibraries.plugin'
|
apply plugin: 'com.mikepenz.aboutlibraries.plugin'
|
||||||
apply plugin: 'com.google.gms.google-services'
|
|
||||||
apply plugin: 'com.huawei.agconnect'
|
apply plugin: 'com.huawei.agconnect'
|
||||||
apply from: 'jacoco.gradle'
|
apply from: 'jacoco.gradle'
|
||||||
apply from: 'sonarqube.gradle'
|
apply from: 'sonarqube.gradle'
|
||||||
apply from: 'hooks.gradle'
|
apply from: 'hooks.gradle'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 30
|
namespace 'io.github.wulkanowy'
|
||||||
buildToolsVersion '30.0.3'
|
compileSdkVersion 32
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "io.github.wulkanowy"
|
applicationId "io.github.wulkanowy"
|
||||||
testApplicationId "io.github.tests.wulkanowy"
|
testApplicationId "io.github.tests.wulkanowy"
|
||||||
minSdkVersion 17
|
minSdkVersion 21
|
||||||
targetSdkVersion 30
|
targetSdkVersion 32
|
||||||
versionCode 91
|
versionCode 116
|
||||||
versionName "1.1.5"
|
versionName "1.8.1"
|
||||||
multiDexEnabled true
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables.useSupportLibrary = true
|
|
||||||
|
|
||||||
resValue "string", "app_name", "Wulkanowy"
|
resValue "string", "app_name", "Wulkanowy"
|
||||||
buildConfigField "long", "BUILD_TIMESTAMP", String.valueOf(System.currentTimeMillis())
|
|
||||||
|
|
||||||
manifestPlaceholders = [
|
manifestPlaceholders = [
|
||||||
firebase_enabled: project.hasProperty("enableFirebase")
|
firebase_enabled: project.hasProperty("enableFirebase"),
|
||||||
|
admob_project_id: ""
|
||||||
]
|
]
|
||||||
javaCompileOptions {
|
javaCompileOptions {
|
||||||
annotationProcessorOptions {
|
annotationProcessorOptions {
|
||||||
|
@ -41,6 +41,15 @@ android {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildConfigField "String", "SINGLE_SUPPORT_AD_ID", "null"
|
||||||
|
buildConfigField "String", "DASHBOARD_TILE_AD_ID", "null"
|
||||||
|
|
||||||
|
if (System.env.SET_BUILD_TIMESTAMP) {
|
||||||
|
buildConfigField "long", "BUILD_TIMESTAMP", String.valueOf(System.currentTimeMillis())
|
||||||
|
} else {
|
||||||
|
buildConfigField "long", "BUILD_TIMESTAMP", "1486235849000"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
|
@ -63,13 +72,16 @@ android {
|
||||||
shrinkResources true
|
shrinkResources true
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
signingConfig signingConfigs.release
|
signingConfig signingConfigs.release
|
||||||
|
buildConfigField "String", "MESSAGES_BASE_URL", "\"https://messages.wulkanowy.net.pl\""
|
||||||
}
|
}
|
||||||
debug {
|
debug {
|
||||||
resValue "string", "app_name", "Wulkanowy DEV " + defaultConfig.versionCode
|
minifyEnabled false
|
||||||
|
shrinkResources false
|
||||||
|
resValue "string", "app_name", "Wulkanowy DEV"
|
||||||
applicationIdSuffix ".dev"
|
applicationIdSuffix ".dev"
|
||||||
versionNameSuffix "-dev"
|
versionNameSuffix "-dev"
|
||||||
testCoverageEnabled = project.hasProperty('coverage')
|
|
||||||
ext.enableCrashlytics = project.hasProperty("enableFirebase")
|
ext.enableCrashlytics = project.hasProperty("enableFirebase")
|
||||||
|
buildConfigField "String", "MESSAGES_BASE_URL", "\"https://messages.wulkanowy.net.pl\""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,54 +90,62 @@ android {
|
||||||
productFlavors {
|
productFlavors {
|
||||||
hms {
|
hms {
|
||||||
dimension "platform"
|
dimension "platform"
|
||||||
minSdkVersion 19
|
manifestPlaceholders = [install_channel: "AppGallery"]
|
||||||
manifestPlaceholders = [
|
|
||||||
install_channel: "AppGallery"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
play {
|
play {
|
||||||
dimension "platform"
|
dimension "platform"
|
||||||
manifestPlaceholders = [
|
manifestPlaceholders = [
|
||||||
install_channel: "Google Play"
|
install_channel : "Google Play",
|
||||||
|
admob_project_id: System.getenv("ADMOB_PROJECT_ID") ?: "ca-app-pub-3940256099942544~3347511713"
|
||||||
]
|
]
|
||||||
|
buildConfigField "String", "SINGLE_SUPPORT_AD_ID", "\"${System.getenv("SINGLE_SUPPORT_AD_ID") ?: "ca-app-pub-3940256099942544/5354046379"}\""
|
||||||
|
buildConfigField "String", "DASHBOARD_TILE_AD_ID", "\"${System.getenv("DASHBOARD_TILE_AD_ID") ?: "ca-app-pub-3940256099942544/6300978111"}\""
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fdroid {
|
fdroid {
|
||||||
dimension "platform"
|
dimension "platform"
|
||||||
manifestPlaceholders = [
|
manifestPlaceholders = [install_channel: "F-Droid"]
|
||||||
install_channel: "F-Droid"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
playConfigs {
|
||||||
|
play { enabled.set(true) }
|
||||||
|
}
|
||||||
|
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
viewBinding = true
|
viewBinding true
|
||||||
}
|
}
|
||||||
|
|
||||||
lintOptions {
|
bundle {
|
||||||
disable 'HardwareIds'
|
language {
|
||||||
|
enableSplit = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
testOptions.unitTests {
|
testOptions.unitTests {
|
||||||
includeAndroidResources = true
|
includeAndroidResources = true
|
||||||
|
// workaround HMS test errors https://github.com/robolectric/robolectric/issues/2750
|
||||||
|
all { jvmArgs '-noverify' }
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
coreLibraryDesugaringEnabled true
|
coreLibraryDesugaringEnabled true
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
sourceCompatibility JavaVersion.VERSION_11
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
targetCompatibility JavaVersion.VERSION_11
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
useIR = true
|
jvmTarget = "11"
|
||||||
jvmTarget = "1.8"
|
freeCompilerArgs += ["-opt-in=kotlin.RequiresOptIn", "-Xjvm-default=all"]
|
||||||
freeCompilerArgs += ["-Xopt-in=kotlin.RequiresOptIn", "-Xjvm-default=all"]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
packagingOptions {
|
packagingOptions {
|
||||||
exclude 'META-INF/library_release.kotlin_module'
|
resources {
|
||||||
exclude 'META-INF/library-core_release.kotlin_module'
|
excludes += ['META-INF/library_release.kotlin_module',
|
||||||
|
'META-INF/library-core_release.kotlin_module']
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aboutLibraries {
|
aboutLibraries {
|
||||||
|
@ -133,65 +153,68 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kapt {
|
||||||
|
correctErrorTypes true
|
||||||
|
}
|
||||||
|
|
||||||
play {
|
play {
|
||||||
serviceAccountEmail = System.getenv("PLAY_SERVICE_ACCOUNT_EMAIL") ?: "jan@fakelog.cf"
|
|
||||||
serviceAccountCredentials = file('key.p12')
|
|
||||||
defaultToAppBundles = false
|
defaultToAppBundles = false
|
||||||
track = 'production'
|
track = 'production'
|
||||||
updatePriority = 1
|
releaseStatus = com.github.triplet.gradle.androidpublisher.ReleaseStatus.IN_PROGRESS
|
||||||
|
userFraction = 0.10d
|
||||||
|
updatePriority = 4
|
||||||
|
enabled.set(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
huaweiPublish {
|
huaweiPublish {
|
||||||
instances {
|
instances {
|
||||||
hmsRelease {
|
hmsRelease {
|
||||||
clientId = System.getenv("AGC_CLIENT_ID")
|
credentialsPath = "$rootDir/app/src/release/agconnect-credentials.json"
|
||||||
clientSecret = System.getenv("AGC_CLIENT_SECRET")
|
buildFormat = "aab"
|
||||||
buildFormat = "apk"
|
|
||||||
deployType = "draft"
|
deployType = "draft"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
work_manager = "2.5.0"
|
work_manager = "2.7.1"
|
||||||
work_hilt = "1.0.0-beta01"
|
android_hilt = "1.0.0"
|
||||||
room = "2.3.0-rc01"
|
room = "2.4.3"
|
||||||
chucker = "3.4.0"
|
chucker = "3.5.2"
|
||||||
mockk = "1.11.0"
|
mockk = "1.13.2"
|
||||||
moshi = "1.11.0"
|
coroutines = "1.6.4"
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "io.github.wulkanowy:sdk:1.1.5"
|
implementation "io.github.wulkanowy:sdk:1.8.1"
|
||||||
|
|
||||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.8'
|
||||||
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1"
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3'
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines"
|
||||||
|
|
||||||
implementation "androidx.core:core-ktx:1.3.2"
|
implementation "androidx.core:core-ktx:1.8.0"
|
||||||
implementation "androidx.activity:activity-ktx:1.2.2"
|
implementation 'androidx.core:core-splashscreen:1.0.0'
|
||||||
implementation "androidx.appcompat:appcompat:1.2.0"
|
implementation "androidx.activity:activity-ktx:1.5.1"
|
||||||
implementation "androidx.appcompat:appcompat-resources:1.2.0"
|
implementation "androidx.appcompat:appcompat:1.5.1"
|
||||||
implementation "androidx.fragment:fragment-ktx:1.3.2"
|
implementation "androidx.fragment:fragment-ktx:1.5.4"
|
||||||
implementation "androidx.annotation:annotation:1.2.0"
|
implementation "androidx.annotation:annotation:1.5.0"
|
||||||
implementation "androidx.multidex:multidex:2.0.1"
|
|
||||||
|
|
||||||
implementation "androidx.preference:preference-ktx:1.1.1"
|
implementation "androidx.preference:preference-ktx:1.2.0"
|
||||||
implementation "androidx.recyclerview:recyclerview:1.1.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.swiperefreshlayout:swiperefreshlayout:1.1.0"
|
||||||
implementation "androidx.constraintlayout:constraintlayout:2.0.4"
|
implementation "androidx.constraintlayout:constraintlayout:2.1.4"
|
||||||
implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"
|
implementation "androidx.coordinatorlayout:coordinatorlayout:1.2.0"
|
||||||
implementation "com.google.android.material:material:1.3.0"
|
implementation "com.google.android.material:material:1.7.0"
|
||||||
implementation "com.github.wulkanowy:material-chips-input:2.2.0"
|
implementation "com.github.wulkanowy:material-chips-input:2.3.1"
|
||||||
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
|
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
|
||||||
implementation 'com.mikhaellopez:circularimageview:4.2.0'
|
implementation 'com.github.lopspower:CircularImageView:4.3.0'
|
||||||
|
|
||||||
implementation "androidx.work:work-runtime-ktx:$work_manager"
|
implementation "androidx.work:work-runtime-ktx:$work_manager"
|
||||||
playImplementation "androidx.work:work-gcm:$work_manager"
|
playImplementation "androidx.work:work-gcm:$work_manager"
|
||||||
|
|
||||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1"
|
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.5.1"
|
||||||
|
|
||||||
implementation "androidx.room:room-runtime:$room"
|
implementation "androidx.room:room-runtime:$room"
|
||||||
implementation "androidx.room:room-ktx:$room"
|
implementation "androidx.room:room-ktx:$room"
|
||||||
|
@ -199,55 +222,58 @@ dependencies {
|
||||||
|
|
||||||
implementation "com.google.dagger:hilt-android:$hilt_version"
|
implementation "com.google.dagger:hilt-android:$hilt_version"
|
||||||
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
|
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
|
||||||
implementation "androidx.hilt:hilt-work:$work_hilt"
|
kapt "androidx.hilt:hilt-compiler:$android_hilt"
|
||||||
kapt "androidx.hilt:hilt-compiler:$work_hilt"
|
implementation "androidx.hilt:hilt-work:$android_hilt"
|
||||||
|
|
||||||
implementation "com.aurelhubert:ahbottomnavigation:2.3.4"
|
implementation 'com.github.ncapdevi:FragNav:3.3.0'
|
||||||
implementation "com.ncapdevi:frag-nav:3.3.0"
|
|
||||||
implementation "com.github.YarikSOffice:lingver:1.3.0"
|
implementation "com.github.YarikSOffice:lingver:1.3.0"
|
||||||
|
|
||||||
implementation "com.squareup.moshi:moshi:$moshi"
|
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||||
implementation "com.squareup.moshi:moshi-adapters:$moshi"
|
implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0"
|
||||||
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi"
|
implementation "com.squareup.okhttp3:logging-interceptor:4.10.0"
|
||||||
implementation "com.jakewharton.timber:timber:4.7.1"
|
|
||||||
implementation "at.favre.lib:slf4j-timber:1.0.1"
|
|
||||||
implementation "fr.bipi.treessence:treessence:0.3.2"
|
|
||||||
implementation "com.mikepenz:aboutlibraries-core:$about_libraries"
|
|
||||||
implementation 'com.wdullaer:materialdatetimepicker:4.2.3'
|
|
||||||
implementation "io.coil-kt:coil:1.1.1"
|
|
||||||
implementation "io.github.wulkanowy:AppKillerManager:3.0.0"
|
|
||||||
implementation 'me.xdrop:fuzzywuzzy:1.3.1'
|
|
||||||
|
|
||||||
playImplementation platform('com.google.firebase:firebase-bom:26.7.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.5'
|
||||||
|
implementation "com.mikepenz:aboutlibraries-core:$about_libraries"
|
||||||
|
implementation "io.coil-kt:coil:2.2.2"
|
||||||
|
implementation "io.github.wulkanowy:AppKillerManager:3.0.0"
|
||||||
|
implementation 'me.xdrop:fuzzywuzzy:1.4.0'
|
||||||
|
implementation 'com.fredporciuncula:flow-preferences:1.8.0'
|
||||||
|
|
||||||
|
playImplementation platform('com.google.firebase:firebase-bom:31.0.3')
|
||||||
playImplementation 'com.google.firebase:firebase-analytics-ktx'
|
playImplementation 'com.google.firebase:firebase-analytics-ktx'
|
||||||
playImplementation 'com.google.firebase:firebase-messaging:'
|
playImplementation 'com.google.firebase:firebase-messaging:'
|
||||||
playImplementation 'com.google.firebase:firebase-crashlytics:'
|
playImplementation 'com.google.firebase:firebase-crashlytics:'
|
||||||
|
playImplementation 'com.google.android.play:core:1.10.3'
|
||||||
playImplementation 'com.google.android.play:core-ktx:1.8.1'
|
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:5.2.0.301'
|
hmsImplementation 'com.huawei.hms:hianalytics:6.8.0.300'
|
||||||
hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.5.1.200'
|
hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.7.3.300'
|
||||||
|
|
||||||
releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker"
|
releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker"
|
||||||
|
|
||||||
debugImplementation "com.github.ChuckerTeam.Chucker:library:$chucker"
|
debugImplementation "com.github.ChuckerTeam.Chucker:library:$chucker"
|
||||||
debugImplementation "com.amitshekhar.android:debug-db:1.0.6"
|
debugImplementation 'com.github.amitshekhariitbhu.Android-Debug-Database:debug-db:1.0.6'
|
||||||
|
debugImplementation 'com.github.haroldadmin:WhatTheStack:1.0.0-alpha04'
|
||||||
|
|
||||||
testImplementation "junit:junit:4.13.2"
|
testImplementation "junit:junit:4.13.2"
|
||||||
testImplementation "io.mockk:mockk:$mockk"
|
testImplementation "io.mockk:mockk:$mockk"
|
||||||
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.2'
|
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines"
|
||||||
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||||
|
|
||||||
testImplementation 'org.robolectric:robolectric:4.5.1'
|
testImplementation 'org.robolectric:robolectric:4.9'
|
||||||
testImplementation "androidx.test:runner:1.3.0"
|
testImplementation "androidx.test:runner:1.5.1"
|
||||||
testImplementation "androidx.test.ext:junit:1.1.2"
|
testImplementation "androidx.test.ext:junit:1.1.4"
|
||||||
testImplementation "androidx.test:core:1.3.0"
|
testImplementation "androidx.test:core:1.5.0"
|
||||||
testImplementation "androidx.room:room-testing:$room"
|
testImplementation "androidx.room:room-testing:$room"
|
||||||
testImplementation "com.google.dagger:hilt-android-testing:$hilt_version"
|
testImplementation "com.google.dagger:hilt-android-testing:$hilt_version"
|
||||||
kaptTest "com.google.dagger:hilt-android-compiler:$hilt_version"
|
kaptTest "com.google.dagger:hilt-android-compiler:$hilt_version"
|
||||||
|
|
||||||
androidTestImplementation "androidx.test:core:1.3.0"
|
androidTestImplementation "androidx.test:core:1.4.0"
|
||||||
androidTestImplementation "androidx.test:runner:1.3.0"
|
androidTestImplementation "androidx.test:runner:1.4.0"
|
||||||
androidTestImplementation "androidx.test.ext:junit:1.1.2"
|
androidTestImplementation "androidx.test.ext:junit:1.1.3"
|
||||||
androidTestImplementation "io.mockk:mockk-android:$mockk"
|
androidTestImplementation "io.mockk:mockk-android:$mockk"
|
||||||
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
apply plugin: "jacoco"
|
apply plugin: "jacoco"
|
||||||
|
|
||||||
jacoco {
|
jacoco {
|
||||||
toolVersion "0.8.5"
|
toolVersion "0.8.7"
|
||||||
reportsDir = file("$buildDir/reports")
|
reportsDirectory.set(file("$buildDir/reports"))
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(Test) {
|
tasks.withType(Test) {
|
||||||
|
@ -16,8 +16,8 @@ task jacocoTestReport(type: JacocoReport) {
|
||||||
description = "Generate Jacoco coverage reports"
|
description = "Generate Jacoco coverage reports"
|
||||||
|
|
||||||
reports {
|
reports {
|
||||||
xml.enabled = true
|
xml.required.set(true)
|
||||||
html.enabled = true
|
html.required.set(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
def excludes = ['**/R.class',
|
def excludes = ['**/R.class',
|
||||||
|
|
BIN
app/key.p12.gpg
2160
app/schemas/io.github.wulkanowy.data.db.AppDatabase/36.json
Normal file
2204
app/schemas/io.github.wulkanowy.data.db.AppDatabase/37.json
Normal file
2248
app/schemas/io.github.wulkanowy.data.db.AppDatabase/38.json
Normal file
2260
app/schemas/io.github.wulkanowy.data.db.AppDatabase/39.json
Normal file
2316
app/schemas/io.github.wulkanowy.data.db.AppDatabase/40.json
Normal file
2322
app/schemas/io.github.wulkanowy.data.db.AppDatabase/41.json
Normal file
2396
app/schemas/io.github.wulkanowy.data.db.AppDatabase/42.json
Normal file
2408
app/schemas/io.github.wulkanowy.data.db.AppDatabase/43.json
Normal file
2414
app/schemas/io.github.wulkanowy.data.db.AppDatabase/44.json
Normal file
2430
app/schemas/io.github.wulkanowy.data.db.AppDatabase/45.json
Normal file
2430
app/schemas/io.github.wulkanowy.data.db.AppDatabase/46.json
Normal file
2438
app/schemas/io.github.wulkanowy.data.db.AppDatabase/47.json
Normal file
2445
app/schemas/io.github.wulkanowy.data.db.AppDatabase/48.json
Normal file
2445
app/schemas/io.github.wulkanowy.data.db.AppDatabase/49.json
Normal file
2445
app/schemas/io.github.wulkanowy.data.db.AppDatabase/50.json
Normal file
2409
app/schemas/io.github.wulkanowy.data.db.AppDatabase/51.json
Normal file
2421
app/schemas/io.github.wulkanowy.data.db.AppDatabase/52.json
Normal file
2439
app/schemas/io.github.wulkanowy.data.db.AppDatabase/53.json
Normal file
|
@ -1,33 +1,92 @@
|
||||||
{
|
{
|
||||||
"agcgw":{
|
"agcgw": {
|
||||||
"backurl":"connect-dre.dbankcloud.cn",
|
"backurl": "connect-dre.hispace.hicloud.com",
|
||||||
"url":"connect-dre.hispace.hicloud.com"
|
"url": "connect-dre.dbankcloud.cn",
|
||||||
|
"websocketbackurl": "connect-ws-dre.hispace.dbankcloud.com",
|
||||||
|
"websocketurl": "connect-ws-dre.hispace.dbankcloud.cn"
|
||||||
},
|
},
|
||||||
"client":{
|
"agcgw_all": {
|
||||||
"cp_id":"890048000024105546",
|
"CN": "connect-drcn.dbankcloud.cn",
|
||||||
"product_id":"",
|
"CN_back": "connect-drcn.hispace.hicloud.com",
|
||||||
"client_id":"",
|
"DE": "connect-dre.dbankcloud.cn",
|
||||||
"client_secret":"",
|
"DE_back": "connect-dre.hispace.hicloud.com",
|
||||||
"app_id":"101440411",
|
"RU": "connect-drru.hispace.dbankcloud.ru",
|
||||||
"package_name":"io.github.wulkanowy.dev",
|
"RU_back": "connect-drru.hispace.dbankcloud.cn",
|
||||||
"api_key":""
|
"SG": "connect-dra.dbankcloud.cn",
|
||||||
|
"SG_back": "connect-dra.hispace.hicloud.com"
|
||||||
},
|
},
|
||||||
"service":{
|
"websocketgw_all": {
|
||||||
"analytics":{
|
"CN": "connect-ws-drcn.hispace.dbankcloud.cn",
|
||||||
"collector_url":"datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn",
|
"CN_back": "connect-ws-drcn.hispace.dbankcloud.com",
|
||||||
"resource_id":"p1",
|
"DE": "connect-ws-dre.hispace.dbankcloud.cn",
|
||||||
"channel_id":""
|
"DE_back": "connect-ws-dre.hispace.dbankcloud.com",
|
||||||
|
"RU": "connect-ws-drru.hispace.dbankcloud.ru",
|
||||||
|
"RU_back": "connect-ws-drru.hispace.dbankcloud.cn",
|
||||||
|
"SG": "connect-ws-dra.hispace.dbankcloud.cn",
|
||||||
|
"SG_back": "connect-ws-dra.hispace.dbankcloud.com"
|
||||||
|
},
|
||||||
|
"client": {
|
||||||
|
"cp_id": "890048000024105546",
|
||||||
|
"product_id": "736430079244736562",
|
||||||
|
"client_id": "514530959291319360",
|
||||||
|
"client_secret": "C42522DBF17D3D4BBE9D9C1783A54484B7E6844B388B7A67502D36A633A4186B",
|
||||||
|
"project_id": "736430079244736562",
|
||||||
|
"app_id": "106552551",
|
||||||
|
"api_key": "CgB6e3x9BUNiq+r8ebCHNojjjYsMT4pJSjjNDOkm9owtBb6rVI6LjnASoZBRxbjjhObcrV5gANo99fI/eKZDTbWS",
|
||||||
|
"package_name": "io.github.wulkanowy.dev"
|
||||||
|
},
|
||||||
|
"oauth_client": {
|
||||||
|
"client_id": "106552551",
|
||||||
|
"client_type": 1
|
||||||
|
},
|
||||||
|
"app_info": {
|
||||||
|
"app_id": "106552551",
|
||||||
|
"package_name": "io.github.wulkanowy.dev"
|
||||||
|
},
|
||||||
|
"service": {
|
||||||
|
"analytics": {
|
||||||
|
"collector_url": "datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn",
|
||||||
|
"collector_url_ru": "datacollector-drru.dt.dbankcloud.ru,datacollector-drru.dt.hicloud.com",
|
||||||
|
"collector_url_sg": "datacollector-dra.dt.hicloud.com,datacollector-dra.dt.dbankcloud.cn",
|
||||||
|
"collector_url_de": "datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn",
|
||||||
|
"collector_url_cn": "datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn",
|
||||||
|
"resource_id": "p1",
|
||||||
|
"channel_id": ""
|
||||||
},
|
},
|
||||||
"search":{
|
"search":{
|
||||||
"url":"https://search-dre.cloud.huawei.com"
|
"url":"https://search-dre.cloud.huawei.com"
|
||||||
},
|
},
|
||||||
"cloudstorage":{
|
"cloudstorage": {
|
||||||
"storage_url":"https://ops-dre.agcstorage.link"
|
"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":{
|
"ml": {
|
||||||
"mlservice_url":"ml-api-dre.ai.dbankcloud.com,ml-api-dre.ai.dbankcloud.cn"
|
"mlservice_url": "ml-api-dre.ai.dbankcloud.com,ml-api-dre.ai.dbankcloud.cn"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"region":"DE",
|
"region": "DE",
|
||||||
"configuration_version":"1.0"
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 478 B |
Before Width: | Height: | Size: 652 B |
Before Width: | Height: | Size: 384 B |
Before Width: | Height: | Size: 460 B |
Before Width: | Height: | Size: 426 B |
Before Width: | Height: | Size: 355 B |
Before Width: | Height: | Size: 451 B |
Before Width: | Height: | Size: 297 B |
Before Width: | Height: | Size: 339 B |
Before Width: | Height: | Size: 335 B |
Before Width: | Height: | Size: 588 B |
Before Width: | Height: | Size: 897 B |
Before Width: | Height: | Size: 508 B |
Before Width: | Height: | Size: 586 B |
Before Width: | Height: | Size: 519 B |
Before Width: | Height: | Size: 781 B |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 692 B |
Before Width: | Height: | Size: 805 B |
Before Width: | Height: | Size: 700 B |
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")
|
@Suppress("UNUSED_PARAMETER")
|
||||||
class AnalyticsHelper @Inject constructor() {
|
class AnalyticsHelper @Inject constructor() {
|
||||||
|
|
||||||
fun logEvent(name: String, vararg params: Pair<String, Any?>) {
|
fun logEvent(name: String, vararg params: Pair<String, Any?>) = Unit
|
||||||
// do nothing
|
fun setCurrentScreen(activity: Activity, name: String?) = Unit
|
||||||
}
|
fun popCurrentScreen(name: String?) = Unit
|
||||||
|
|
||||||
fun setCurrentScreen(activity: Activity, name: String?) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
fun popCurrentScreen(name: String?) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package io.github.wulkanowy.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
|
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
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun showInAppReview(activity: MainActivity) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
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.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import com.huawei.agconnect.crash.AGConnectCrash
|
||||||
import com.huawei.hms.analytics.HiAnalytics
|
import com.huawei.hms.analytics.HiAnalytics
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
|
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class AnalyticsHelper @Inject constructor(
|
class AnalyticsHelper @Inject constructor(
|
||||||
@ApplicationContext private val context: Context
|
@ApplicationContext private val context: Context,
|
||||||
|
preferencesRepository: PreferencesRepository,
|
||||||
|
appInfo: AppInfo,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val analytics by lazy { HiAnalytics.getInstance(context) }
|
private val analytics by lazy { HiAnalytics.getInstance(context) }
|
||||||
|
|
||||||
|
private val connectCrash by lazy { AGConnectCrash.getInstance() }
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (!appInfo.isDebug) {
|
||||||
|
connectCrash.setUserId(preferencesRepository.installationId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun logEvent(name: String, vararg params: Pair<String, Any?>) {
|
fun logEvent(name: String, vararg params: Pair<String, Any?>) {
|
||||||
Bundle().apply {
|
Bundle().apply {
|
||||||
params.forEach {
|
params.forEach { (key, value) ->
|
||||||
if (it.second == null) return@forEach
|
if (value == null) return@forEach
|
||||||
when (it.second) {
|
when (value) {
|
||||||
is String, is String? -> putString(it.first, it.second as String)
|
is String -> putString(key, value)
|
||||||
is Int, is Int? -> putInt(it.first, it.second as Int)
|
is Int -> putInt(key, value)
|
||||||
is Boolean, is Boolean? -> putBoolean(it.first, it.second as Boolean)
|
is Boolean -> putBoolean(key, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
analytics.onEvent(name, this)
|
analytics.onEvent(name, this)
|
||||||
|
|
|
@ -3,11 +3,7 @@ package io.github.wulkanowy.utils
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.huawei.agconnect.crash.AGConnectCrash
|
import com.huawei.agconnect.crash.AGConnectCrash
|
||||||
import fr.bipi.tressence.base.FormatterPriorityTree
|
import fr.bipi.tressence.base.FormatterPriorityTree
|
||||||
import io.github.wulkanowy.sdk.exception.FeatureNotAvailableException
|
import fr.bipi.tressence.common.StackTraceRecorder
|
||||||
import io.github.wulkanowy.sdk.scrapper.exception.FeatureDisabledException
|
|
||||||
import java.io.InterruptedIOException
|
|
||||||
import java.net.SocketTimeoutException
|
|
||||||
import java.net.UnknownHostException
|
|
||||||
|
|
||||||
class CrashLogTree : FormatterPriorityTree(Log.VERBOSE) {
|
class CrashLogTree : FormatterPriorityTree(Log.VERBOSE) {
|
||||||
|
|
||||||
|
@ -20,34 +16,17 @@ class CrashLogTree : FormatterPriorityTree(Log.VERBOSE) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CrashLogExceptionTree : FormatterPriorityTree(Log.ERROR) {
|
class CrashLogExceptionTree : FormatterPriorityTree(Log.ERROR, ExceptionFilter) {
|
||||||
|
|
||||||
private val connectCrash by lazy { AGConnectCrash.getInstance() }
|
private val connectCrash by lazy { AGConnectCrash.getInstance() }
|
||||||
|
|
||||||
override fun skipLog(priority: Int, tag: String?, message: String, t: Throwable?): Boolean {
|
|
||||||
return when (t) {
|
|
||||||
is FeatureDisabledException,
|
|
||||||
is FeatureNotAvailableException,
|
|
||||||
is UnknownHostException,
|
|
||||||
is SocketTimeoutException,
|
|
||||||
is InterruptedIOException -> true
|
|
||||||
else -> super.skipLog(priority, tag, message, t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
|
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
|
||||||
if (skipLog(priority, tag, message, t)) return
|
if (skipLog(priority, tag, message, t)) return
|
||||||
|
|
||||||
// Disabled due to a bug in the Huawei library
|
|
||||||
|
|
||||||
/*connectCrash.setCustomKey("priority", priority)
|
|
||||||
connectCrash.setCustomKey("tag", tag.orEmpty())
|
|
||||||
connectCrash.setCustomKey("message", message)
|
|
||||||
|
|
||||||
if (t != null) {
|
if (t != null) {
|
||||||
connectCrash.recordException(t)
|
connectCrash.recordException(t)
|
||||||
} else {
|
} else {
|
||||||
connectCrash.recordException(StackTraceRecorder(format(priority, tag, message)))
|
connectCrash.recordException(StackTraceRecorder(format(priority, tag, message)))
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package io.github.wulkanowy.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
|
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Suppress("UNUSED_PARAMETER", "unused")
|
||||||
|
class InAppReviewHelper @Inject constructor(
|
||||||
|
@ApplicationContext private val context: Context
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun showInAppReview(activity: MainActivity) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +1,14 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="io.github.wulkanowy"
|
|
||||||
android:installLocation="internalOnly">
|
android:installLocation="internalOnly">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
|
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
|
||||||
|
|
||||||
<queries>
|
<queries>
|
||||||
<intent>
|
<intent>
|
||||||
|
@ -37,13 +38,14 @@
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
|
android:networkSecurityConfig="@xml/network_security_config"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="false"
|
android:supportsRtl="false"
|
||||||
android:theme="@style/WulkanowyTheme"
|
android:theme="@style/WulkanowyTheme"
|
||||||
android:usesCleartextTraffic="true"
|
|
||||||
tools:ignore="GoogleAppIndexingWarning,UnusedAttribute">
|
tools:ignore="GoogleAppIndexingWarning,UnusedAttribute">
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.modules.splash.SplashActivity"
|
android:name=".ui.modules.splash.SplashActivity"
|
||||||
|
android:exported="true"
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
android:theme="@style/WulkanowyTheme.SplashScreen"
|
android:theme="@style/WulkanowyTheme.SplashScreen"
|
||||||
tools:ignore="LockedOrientationActivity">
|
tools:ignore="LockedOrientationActivity">
|
||||||
|
@ -73,6 +75,7 @@
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.modules.timetablewidget.TimetableWidgetConfigureActivity"
|
android:name=".ui.modules.timetablewidget.TimetableWidgetConfigureActivity"
|
||||||
android:excludeFromRecents="true"
|
android:excludeFromRecents="true"
|
||||||
|
android:exported="true"
|
||||||
android:noHistory="true"
|
android:noHistory="true"
|
||||||
android:theme="@style/WulkanowyTheme.WidgetAccountSwitcher">
|
android:theme="@style/WulkanowyTheme.WidgetAccountSwitcher">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
@ -82,6 +85,7 @@
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.modules.luckynumberwidget.LuckyNumberWidgetConfigureActivity"
|
android:name=".ui.modules.luckynumberwidget.LuckyNumberWidgetConfigureActivity"
|
||||||
android:excludeFromRecents="true"
|
android:excludeFromRecents="true"
|
||||||
|
android:exported="true"
|
||||||
android:noHistory="true"
|
android:noHistory="true"
|
||||||
android:theme="@style/WulkanowyTheme.WidgetAccountSwitcher">
|
android:theme="@style/WulkanowyTheme.WidgetAccountSwitcher">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
@ -92,6 +96,22 @@
|
||||||
<service
|
<service
|
||||||
android:name=".services.widgets.TimetableWidgetService"
|
android:name=".services.widgets.TimetableWidgetService"
|
||||||
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
||||||
|
<service
|
||||||
|
android:name=".services.piggyback.VulcanNotificationListenerService"
|
||||||
|
android:exported="true"
|
||||||
|
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.service.notification.NotificationListenerService" />
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
<service
|
||||||
|
android:name=".services.messaging.AppMessagingService"
|
||||||
|
android:exported="false"
|
||||||
|
tools:ignore="MissingClass">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".ui.modules.timetablewidget.TimetableWidgetProvider"
|
android:name=".ui.modules.timetablewidget.TimetableWidgetProvider"
|
||||||
|
@ -106,6 +126,7 @@
|
||||||
</receiver>
|
</receiver>
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".ui.modules.luckynumberwidget.LuckyNumberWidgetProvider"
|
android:name=".ui.modules.luckynumberwidget.LuckyNumberWidgetProvider"
|
||||||
|
android:exported="true"
|
||||||
android:label="@string/lucky_number_title">
|
android:label="@string/lucky_number_title">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
|
@ -118,11 +139,9 @@
|
||||||
<receiver android:name=".services.alarm.TimetableNotificationReceiver" />
|
<receiver android:name=".services.alarm.TimetableNotificationReceiver" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="androidx.work.impl.WorkManagerInitializer"
|
android:name="androidx.startup.InitializationProvider"
|
||||||
android:authorities="${applicationId}.workmanager-init"
|
android:authorities="${applicationId}.androidx-startup"
|
||||||
android:exported="false"
|
|
||||||
tools:node="remove" />
|
tools:node="remove" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="androidx.core.content.FileProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
android:authorities="${applicationId}.fileprovider"
|
android:authorities="${applicationId}.fileprovider"
|
||||||
|
@ -133,44 +152,44 @@
|
||||||
android:resource="@xml/provider_paths" />
|
android:resource="@xml/provider_paths" />
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
<meta-data
|
|
||||||
android:name="install_channel"
|
|
||||||
android:value="${install_channel}" />
|
|
||||||
|
|
||||||
<!-- workaround for https://github.com/firebase/firebase-android-sdk/issues/473 enabled:false -->
|
<!-- workaround for https://github.com/firebase/firebase-android-sdk/issues/473 enabled:false -->
|
||||||
<!-- https://firebase.googleblog.com/2017/03/take-control-of-your-firebase-init-on.html -->
|
<!-- https://firebase.googleblog.com/2017/03/take-control-of-your-firebase-init-on.html -->
|
||||||
<provider
|
<provider
|
||||||
android:name="com.google.firebase.provider.FirebaseInitProvider"
|
android:name="com.google.firebase.provider.FirebaseInitProvider"
|
||||||
android:authorities="${applicationId}.firebaseinitprovider"
|
android:authorities="${applicationId}.firebaseinitprovider"
|
||||||
android:enabled="${firebase_enabled}"
|
android:enabled="${firebase_enabled}"
|
||||||
android:exported="false" />
|
android:exported="false"
|
||||||
|
tools:ignore="MissingClass" />
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="install_channel"
|
||||||
|
android:value="${install_channel}" />
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="firebase_analytics_collection_enabled"
|
android:name="firebase_analytics_collection_enabled"
|
||||||
android:value="${firebase_enabled}" />
|
android:value="${firebase_enabled}" />
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="google_analytics_adid_collection_enabled"
|
android:name="google_analytics_adid_collection_enabled"
|
||||||
android:value="${firebase_enabled}" />
|
android:value="${firebase_enabled}" />
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="firebase_crashlytics_collection_enabled"
|
android:name="firebase_crashlytics_collection_enabled"
|
||||||
android:value="${firebase_enabled}" />
|
android:value="${firebase_enabled}" />
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="firebase_messaging_auto_init_enabled"
|
android:name="firebase_messaging_auto_init_enabled"
|
||||||
android:value="${firebase_enabled}" />
|
android:value="${firebase_enabled}" />
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="firebase_inapp_messaging_auto_data_collection_enabled"
|
android:name="firebase_inapp_messaging_auto_data_collection_enabled"
|
||||||
android:value="${firebase_enabled}" />
|
android:value="${firebase_enabled}" />
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="com.google.firebase.messaging.default_notification_icon"
|
android:name="com.google.firebase.messaging.default_notification_icon"
|
||||||
android:resource="@drawable/ic_stat_push" />
|
android:resource="@drawable/ic_stat_all" />
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="com.google.firebase.messaging.default_notification_channel_id"
|
android:name="com.google.firebase.messaging.default_notification_channel_id"
|
||||||
android:value="push_channel" />
|
android:value="push_channel" />
|
||||||
|
<meta-data
|
||||||
|
android:name="com.google.android.gms.ads.APPLICATION_ID"
|
||||||
|
android:value="${admob_project_id}" />
|
||||||
|
<meta-data
|
||||||
|
android:name="com.google.android.gms.ads.DELAY_APP_MEASUREMENT_INIT"
|
||||||
|
android:value="true" />
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
"githubUsername": "Luncenok"
|
"githubUsername": "Luncenok"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"displayName": "MRmlik12",
|
"displayName": "Daniel Olczyk",
|
||||||
"githubUsername": "MRmlik12"
|
"githubUsername": "MRmlik12"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -46,5 +46,9 @@
|
||||||
{
|
{
|
||||||
"displayName": "Kamil Studziński",
|
"displayName": "Kamil Studziński",
|
||||||
"githubUsername": "studzinskik"
|
"githubUsername": "studzinskik"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"displayName": "Tomasz F.",
|
||||||
|
"githubUsername": "Pengwius"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,27 +1,15 @@
|
||||||
package io.github.wulkanowy
|
package io.github.wulkanowy
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.Context
|
import android.util.Log.*
|
||||||
import android.util.Log.DEBUG
|
|
||||||
import android.util.Log.INFO
|
|
||||||
import android.util.Log.VERBOSE
|
|
||||||
import android.webkit.WebView
|
|
||||||
import androidx.fragment.app.FragmentManager
|
|
||||||
import androidx.hilt.work.HiltWorkerFactory
|
import androidx.hilt.work.HiltWorkerFactory
|
||||||
import androidx.multidex.MultiDex
|
|
||||||
import androidx.work.Configuration
|
import androidx.work.Configuration
|
||||||
import com.yariksoffice.lingver.Lingver
|
import com.yariksoffice.lingver.Lingver
|
||||||
import dagger.hilt.android.HiltAndroidApp
|
import dagger.hilt.android.HiltAndroidApp
|
||||||
import fr.bipi.tressence.file.FileLoggerTree
|
import fr.bipi.tressence.file.FileLoggerTree
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||||
import io.github.wulkanowy.ui.base.ThemeManager
|
import io.github.wulkanowy.ui.base.ThemeManager
|
||||||
import io.github.wulkanowy.utils.ActivityLifecycleLogger
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.AnalyticsHelper
|
|
||||||
import io.github.wulkanowy.utils.AppInfo
|
|
||||||
import io.github.wulkanowy.utils.CrashLogExceptionTree
|
|
||||||
import io.github.wulkanowy.utils.CrashLogTree
|
|
||||||
import io.github.wulkanowy.utils.DebugLogTree
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -43,19 +31,15 @@ class WulkanowyApp : Application(), Configuration.Provider {
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var analyticsHelper: AnalyticsHelper
|
lateinit var analyticsHelper: AnalyticsHelper
|
||||||
|
|
||||||
override fun attachBaseContext(base: Context?) {
|
@Inject
|
||||||
super.attachBaseContext(base)
|
lateinit var adsHelper: AdsHelper
|
||||||
MultiDex.install(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("UnsafeOptInUsageWarning")
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
FragmentManager.enableNewStateManager(false)
|
|
||||||
initializeAppLanguage()
|
initializeAppLanguage()
|
||||||
themeManager.applyDefaultTheme()
|
themeManager.applyDefaultTheme()
|
||||||
|
adsHelper.initialize()
|
||||||
initLogging()
|
initLogging()
|
||||||
fixWebViewLocale()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initLogging() {
|
private fun initLogging() {
|
||||||
|
@ -87,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: Exception) {
|
|
||||||
//Ignore exceptions
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getWorkManagerConfiguration() = Configuration.Builder()
|
override fun getWorkManagerConfiguration() = Configuration.Builder()
|
||||||
.setWorkerFactory(workerFactory)
|
.setWorkerFactory(workerFactory)
|
||||||
.setMinimumLoggingLevel(if (appInfo.isDebug) VERBOSE else INFO)
|
.setMinimumLoggingLevel(if (appInfo.isDebug) VERBOSE else INFO)
|
||||||
|
|
|
@ -2,45 +2,48 @@ package io.github.wulkanowy.data
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.content.res.AssetManager
|
|
||||||
import android.content.res.Resources
|
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.chuckerteam.chucker.api.ChuckerCollector
|
import com.chuckerteam.chucker.api.ChuckerCollector
|
||||||
import com.chuckerteam.chucker.api.ChuckerInterceptor
|
import com.chuckerteam.chucker.api.ChuckerInterceptor
|
||||||
import com.chuckerteam.chucker.api.RetentionManager
|
import com.chuckerteam.chucker.api.RetentionManager
|
||||||
|
import com.fredporciuncula.flow.preferences.FlowSharedPreferences
|
||||||
|
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import dagger.hilt.components.SingletonComponent
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
import io.github.wulkanowy.data.api.AdminMessageService
|
||||||
import io.github.wulkanowy.data.db.AppDatabase
|
import io.github.wulkanowy.data.db.AppDatabase
|
||||||
import io.github.wulkanowy.data.db.SharedPrefProvider
|
import io.github.wulkanowy.data.db.SharedPrefProvider
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.AppInfo
|
import io.github.wulkanowy.utils.AppInfo
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.logging.HttpLoggingInterceptor
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import retrofit2.create
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@InstallIn(SingletonComponent::class)
|
@InstallIn(SingletonComponent::class)
|
||||||
internal class RepositoryModule {
|
internal class DataModule {
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideSdk(chuckerCollector: ChuckerCollector, @ApplicationContext context: Context): Sdk {
|
fun provideSdk(chuckerInterceptor: ChuckerInterceptor) =
|
||||||
return Sdk().apply {
|
Sdk().apply {
|
||||||
androidVersion = android.os.Build.VERSION.RELEASE
|
androidVersion = android.os.Build.VERSION.RELEASE
|
||||||
buildTag = android.os.Build.MODEL
|
buildTag = android.os.Build.MODEL
|
||||||
setSimpleHttpLogger { Timber.d(it) }
|
setSimpleHttpLogger { Timber.d(it) }
|
||||||
|
|
||||||
// for debug only
|
// for debug only
|
||||||
addInterceptor(
|
addInterceptor(chuckerInterceptor, network = true)
|
||||||
ChuckerInterceptor.Builder(context)
|
|
||||||
.collector(chuckerCollector)
|
|
||||||
.alwaysReadResponseBody(true)
|
|
||||||
.build(), network = true
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
|
@ -48,13 +51,50 @@ internal class RepositoryModule {
|
||||||
fun provideChuckerCollector(
|
fun provideChuckerCollector(
|
||||||
@ApplicationContext context: Context,
|
@ApplicationContext context: Context,
|
||||||
prefRepository: PreferencesRepository
|
prefRepository: PreferencesRepository
|
||||||
): ChuckerCollector {
|
) = ChuckerCollector(
|
||||||
return ChuckerCollector(
|
|
||||||
context = context,
|
context = context,
|
||||||
showNotification = prefRepository.isDebugNotificationEnable,
|
showNotification = prefRepository.isDebugNotificationEnable,
|
||||||
retentionPeriod = RetentionManager.Period.ONE_HOUR
|
retentionPeriod = RetentionManager.Period.ONE_HOUR
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
fun provideChuckerInterceptor(
|
||||||
|
@ApplicationContext context: Context,
|
||||||
|
chuckerCollector: ChuckerCollector
|
||||||
|
) = ChuckerInterceptor.Builder(context)
|
||||||
|
.collector(chuckerCollector)
|
||||||
|
.alwaysReadResponseBody(true)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
fun provideOkHttpClient(chuckerInterceptor: ChuckerInterceptor): OkHttpClient =
|
||||||
|
OkHttpClient.Builder()
|
||||||
|
.addNetworkInterceptor(chuckerInterceptor)
|
||||||
|
.addInterceptor(HttpLoggingInterceptor().apply {
|
||||||
|
level = HttpLoggingInterceptor.Level.BASIC
|
||||||
|
})
|
||||||
|
.connectTimeout(30, TimeUnit.SECONDS)
|
||||||
|
.readTimeout(30, TimeUnit.SECONDS)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
fun provideRetrofit(
|
||||||
|
okHttpClient: OkHttpClient,
|
||||||
|
json: Json,
|
||||||
|
appInfo: AppInfo
|
||||||
|
): Retrofit = Retrofit.Builder()
|
||||||
|
.baseUrl(appInfo.messagesBaseUrl)
|
||||||
|
.client(okHttpClient)
|
||||||
|
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
|
||||||
|
.build()
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
fun provideAdminMessageService(retrofit: Retrofit): AdminMessageService = retrofit.create()
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
|
@ -64,19 +104,22 @@ internal class RepositoryModule {
|
||||||
appInfo: AppInfo
|
appInfo: AppInfo
|
||||||
) = AppDatabase.newInstance(context, sharedPrefProvider, appInfo)
|
) = AppDatabase.newInstance(context, sharedPrefProvider, appInfo)
|
||||||
|
|
||||||
@Singleton
|
|
||||||
@Provides
|
|
||||||
fun provideResources(@ApplicationContext context: Context): Resources = context.resources
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
@Provides
|
|
||||||
fun provideAssets(@ApplicationContext context: Context): AssetManager = context.assets
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideSharedPref(@ApplicationContext context: Context): SharedPreferences =
|
fun provideSharedPref(@ApplicationContext context: Context): SharedPreferences =
|
||||||
PreferenceManager.getDefaultSharedPreferences(context)
|
PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
fun provideFlowSharedPref(sharedPreferences: SharedPreferences) =
|
||||||
|
FlowSharedPreferences(sharedPreferences)
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
fun provideJson() = Json {
|
||||||
|
ignoreUnknownKeys = true
|
||||||
|
}
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideStudentDao(database: AppDatabase) = database.studentDao
|
fun provideStudentDao(database: AppDatabase) = database.studentDao
|
||||||
|
@ -152,7 +195,7 @@ internal class RepositoryModule {
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideReportingUnitDao(database: AppDatabase) = database.reportingUnitDao
|
fun provideMailboxesDao(database: AppDatabase) = database.mailboxDao
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
|
@ -181,4 +224,20 @@ internal class RepositoryModule {
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideStudentInfoDao(database: AppDatabase) = database.studentInfoDao
|
fun provideStudentInfoDao(database: AppDatabase) = database.studentInfoDao
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
fun provideTimetableHeaderDao(database: AppDatabase) = database.timetableHeaderDao
|
||||||
|
|
||||||
|
@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
|
package io.github.wulkanowy.data
|
||||||
|
|
||||||
data class Resource<T>(val status: Status, val data: T?, val error: Throwable?) {
|
import kotlinx.coroutines.flow.*
|
||||||
companion object {
|
import kotlinx.coroutines.sync.Mutex
|
||||||
fun <T> success(data: T?): Resource<T> {
|
import kotlinx.coroutines.sync.withLock
|
||||||
return Resource(Status.SUCCESS, data, null)
|
import timber.log.Timber
|
||||||
|
|
||||||
|
sealed class Resource<T> {
|
||||||
|
|
||||||
|
open class Loading<T> : Resource<T>()
|
||||||
|
|
||||||
|
data class Intermediate<T>(val data: T) : Loading<T>()
|
||||||
|
|
||||||
|
data class Success<T>(val data: T) : Resource<T>()
|
||||||
|
|
||||||
|
data class Error<T>(val error: Throwable) : Resource<T>()
|
||||||
|
}
|
||||||
|
|
||||||
|
val <T> Resource<T>.dataOrNull: T?
|
||||||
|
get() = when (this) {
|
||||||
|
is Resource.Success -> this.data
|
||||||
|
is Resource.Intermediate -> this.data
|
||||||
|
is Resource.Loading -> null
|
||||||
|
is Resource.Error -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> error(error: Throwable?, data: T? = null): Resource<T> {
|
val <T> Resource<T>.errorOrNull: Throwable?
|
||||||
return Resource(Status.ERROR, data, error)
|
get() = when (this) {
|
||||||
|
is Resource.Error -> this.error
|
||||||
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> loading(data: T? = null): Resource<T> {
|
fun <T> resourceFlow(block: suspend () -> T) = flow {
|
||||||
return Resource(Status.LOADING, data, null)
|
emit(Resource.Loading())
|
||||||
|
emit(Resource.Success(block()))
|
||||||
|
}.catch { emit(Resource.Error(it)) }
|
||||||
|
|
||||||
|
fun <T> flatResourceFlow(block: suspend () -> Flow<Resource<T>>) = flow {
|
||||||
|
emit(Resource.Loading())
|
||||||
|
emitAll(block().filter { it is Resource.Intermediate || it !is Resource.Loading })
|
||||||
|
}.catch { emit(Resource.Error(it)) }
|
||||||
|
|
||||||
|
fun <T, U> Resource<T>.mapData(block: (T) -> U) = when (this) {
|
||||||
|
is Resource.Success -> Resource.Success(block(this.data))
|
||||||
|
is Resource.Intermediate -> Resource.Intermediate(block(this.data))
|
||||||
|
is Resource.Loading -> Resource.Loading()
|
||||||
|
is Resource.Error -> Resource.Error(this.error)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> Flow<Resource<T>>.logResourceStatus(name: String, showData: Boolean = false) = onEach {
|
||||||
|
val description = when (it) {
|
||||||
|
is Resource.Intermediate -> "intermediate data received" + if (showData) " (data: `${it.data}`)" else ""
|
||||||
|
is Resource.Loading -> "started"
|
||||||
|
is Resource.Success -> "success" + if (showData) " (data: `${it.data}`)" else ""
|
||||||
|
is Resource.Error -> "exception occurred: ${it.error}"
|
||||||
}
|
}
|
||||||
|
Timber.i("$name: $description")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T, U> Flow<Resource<T>>.mapResourceData(block: (T) -> U) = map {
|
||||||
|
it.mapData(block)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> Flow<Resource<T>>.onResourceData(block: suspend (T) -> Unit) = onEach {
|
||||||
|
when (it) {
|
||||||
|
is Resource.Success -> block(it.data)
|
||||||
|
is Resource.Intermediate -> block(it.data)
|
||||||
|
is Resource.Error,
|
||||||
|
is Resource.Loading -> Unit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class Status {
|
fun <T> Flow<Resource<T>>.onResourceLoading(block: suspend () -> Unit) = onEach {
|
||||||
LOADING,
|
if (it is Resource.Loading) {
|
||||||
SUCCESS,
|
block()
|
||||||
ERROR
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,97 +1,11 @@
|
||||||
package io.github.wulkanowy.data.db
|
package io.github.wulkanowy.data.db
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.room.Database
|
import androidx.room.*
|
||||||
import androidx.room.Room
|
|
||||||
import androidx.room.RoomDatabase
|
|
||||||
import androidx.room.RoomDatabase.JournalMode.TRUNCATE
|
import androidx.room.RoomDatabase.JournalMode.TRUNCATE
|
||||||
import androidx.room.TypeConverters
|
import io.github.wulkanowy.data.db.dao.*
|
||||||
import io.github.wulkanowy.data.db.dao.AttendanceDao
|
import io.github.wulkanowy.data.db.entities.*
|
||||||
import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao
|
import io.github.wulkanowy.data.db.migrations.*
|
||||||
import io.github.wulkanowy.data.db.dao.CompletedLessonsDao
|
|
||||||
import io.github.wulkanowy.data.db.dao.ConferenceDao
|
|
||||||
import io.github.wulkanowy.data.db.dao.ExamDao
|
|
||||||
import io.github.wulkanowy.data.db.dao.GradeDao
|
|
||||||
import io.github.wulkanowy.data.db.dao.GradePartialStatisticsDao
|
|
||||||
import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao
|
|
||||||
import io.github.wulkanowy.data.db.dao.GradeSemesterStatisticsDao
|
|
||||||
import io.github.wulkanowy.data.db.dao.GradeSummaryDao
|
|
||||||
import io.github.wulkanowy.data.db.dao.HomeworkDao
|
|
||||||
import io.github.wulkanowy.data.db.dao.LuckyNumberDao
|
|
||||||
import io.github.wulkanowy.data.db.dao.MessageAttachmentDao
|
|
||||||
import io.github.wulkanowy.data.db.dao.MessagesDao
|
|
||||||
import io.github.wulkanowy.data.db.dao.MobileDeviceDao
|
|
||||||
import io.github.wulkanowy.data.db.dao.NoteDao
|
|
||||||
import io.github.wulkanowy.data.db.dao.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.entities.Attendance
|
|
||||||
import io.github.wulkanowy.data.db.entities.AttendanceSummary
|
|
||||||
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
|
||||||
import io.github.wulkanowy.data.db.entities.Conference
|
|
||||||
import io.github.wulkanowy.data.db.entities.Exam
|
|
||||||
import io.github.wulkanowy.data.db.entities.Grade
|
|
||||||
import io.github.wulkanowy.data.db.entities.GradePartialStatistics
|
|
||||||
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
|
||||||
import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics
|
|
||||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
|
||||||
import io.github.wulkanowy.data.db.entities.Homework
|
|
||||||
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
|
||||||
import io.github.wulkanowy.data.db.entities.Message
|
|
||||||
import io.github.wulkanowy.data.db.entities.MessageAttachment
|
|
||||||
import io.github.wulkanowy.data.db.entities.MobileDevice
|
|
||||||
import io.github.wulkanowy.data.db.entities.Note
|
|
||||||
import io.github.wulkanowy.data.db.entities.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.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.Migration4
|
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration5
|
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration6
|
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration7
|
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration8
|
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration9
|
|
||||||
import io.github.wulkanowy.utils.AppInfo
|
import io.github.wulkanowy.utils.AppInfo
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@ -116,7 +30,7 @@ import javax.inject.Singleton
|
||||||
Subject::class,
|
Subject::class,
|
||||||
LuckyNumber::class,
|
LuckyNumber::class,
|
||||||
CompletedLesson::class,
|
CompletedLesson::class,
|
||||||
ReportingUnit::class,
|
Mailbox::class,
|
||||||
Recipient::class,
|
Recipient::class,
|
||||||
MobileDevice::class,
|
MobileDevice::class,
|
||||||
Teacher::class,
|
Teacher::class,
|
||||||
|
@ -124,6 +38,16 @@ import javax.inject.Singleton
|
||||||
Conference::class,
|
Conference::class,
|
||||||
TimetableAdditional::class,
|
TimetableAdditional::class,
|
||||||
StudentInfo::class,
|
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,
|
version = AppDatabase.VERSION_SCHEMA,
|
||||||
exportSchema = true
|
exportSchema = true
|
||||||
|
@ -132,7 +56,7 @@ import javax.inject.Singleton
|
||||||
abstract class AppDatabase : RoomDatabase() {
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val VERSION_SCHEMA = 35
|
const val VERSION_SCHEMA = 53
|
||||||
|
|
||||||
fun getMigrations(sharedPrefProvider: SharedPrefProvider, appInfo: AppInfo) = arrayOf(
|
fun getMigrations(sharedPrefProvider: SharedPrefProvider, appInfo: AppInfo) = arrayOf(
|
||||||
Migration2(),
|
Migration2(),
|
||||||
|
@ -168,7 +92,21 @@ abstract class AppDatabase : RoomDatabase() {
|
||||||
Migration32(),
|
Migration32(),
|
||||||
Migration33(),
|
Migration33(),
|
||||||
Migration34(),
|
Migration34(),
|
||||||
Migration35(appInfo)
|
Migration35(appInfo),
|
||||||
|
Migration36(),
|
||||||
|
Migration37(),
|
||||||
|
Migration38(),
|
||||||
|
Migration39(),
|
||||||
|
Migration40(),
|
||||||
|
Migration41(sharedPrefProvider),
|
||||||
|
Migration42(),
|
||||||
|
Migration43(),
|
||||||
|
Migration44(),
|
||||||
|
Migration46(),
|
||||||
|
Migration49(),
|
||||||
|
Migration50(),
|
||||||
|
Migration51(),
|
||||||
|
Migration53(),
|
||||||
)
|
)
|
||||||
|
|
||||||
fun newInstance(
|
fun newInstance(
|
||||||
|
@ -219,7 +157,7 @@ abstract class AppDatabase : RoomDatabase() {
|
||||||
|
|
||||||
abstract val completedLessonsDao: CompletedLessonsDao
|
abstract val completedLessonsDao: CompletedLessonsDao
|
||||||
|
|
||||||
abstract val reportingUnitDao: ReportingUnitDao
|
abstract val mailboxDao: MailboxDao
|
||||||
|
|
||||||
abstract val recipientDao: RecipientDao
|
abstract val recipientDao: RecipientDao
|
||||||
|
|
||||||
|
@ -234,4 +172,12 @@ abstract class AppDatabase : RoomDatabase() {
|
||||||
abstract val timetableAdditionalDao: TimetableAdditionalDao
|
abstract val timetableAdditionalDao: TimetableAdditionalDao
|
||||||
|
|
||||||
abstract val studentInfoDao: StudentInfoDao
|
abstract val studentInfoDao: StudentInfoDao
|
||||||
|
|
||||||
|
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
|
package io.github.wulkanowy.data.db
|
||||||
|
|
||||||
import androidx.room.TypeConverter
|
import androidx.room.TypeConverter
|
||||||
import com.squareup.moshi.Moshi
|
import io.github.wulkanowy.ui.modules.Destination
|
||||||
import com.squareup.moshi.Types
|
import io.github.wulkanowy.utils.toTimestamp
|
||||||
import io.github.wulkanowy.data.db.adapters.PairAdapterFactory
|
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.Instant
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalDateTime
|
|
||||||
import java.time.Month
|
import java.time.Month
|
||||||
import java.time.ZoneOffset
|
import java.time.ZoneOffset
|
||||||
import java.util.Date
|
import java.util.*
|
||||||
|
|
||||||
class Converters {
|
class Converters {
|
||||||
|
|
||||||
private val moshi by lazy { Moshi.Builder().add(PairAdapterFactory).build() }
|
private val json = Json
|
||||||
|
|
||||||
private val integerListAdapter by lazy {
|
|
||||||
moshi.adapter<List<Int>>(Types.newParameterizedType(List::class.java, Integer::class.java))
|
|
||||||
}
|
|
||||||
|
|
||||||
private val stringListPairAdapter by lazy {
|
|
||||||
moshi.adapter<List<Pair<String, String>>>(Types.newParameterizedType(List::class.java, Pair::class.java, String::class.java, String::class.java))
|
|
||||||
}
|
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun timestampToDate(value: Long?): LocalDate? = value?.run {
|
fun timestampToLocalDate(value: Long?): LocalDate? =
|
||||||
Date(value).toInstant().atZone(ZoneOffset.UTC).toLocalDate()
|
value?.let(::Date)?.toInstant()?.atZone(ZoneOffset.UTC)?.toLocalDate()
|
||||||
}
|
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun dateToTimestamp(date: LocalDate?): Long? {
|
fun dateToTimestamp(date: LocalDate?): Long? = date?.toTimestamp()
|
||||||
return date?.atStartOfDay()?.toInstant(ZoneOffset.UTC)?.toEpochMilli()
|
|
||||||
}
|
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun timestampToTime(value: Long?): LocalDateTime? = value?.let {
|
fun instantToTimestamp(instant: Instant?): Long? = instant?.toEpochMilli()
|
||||||
LocalDateTime.ofInstant(Instant.ofEpochMilli(value), ZoneOffset.UTC)
|
|
||||||
}
|
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun timeToTimestamp(date: LocalDateTime?): Long? {
|
fun timestampToInstant(timestamp: Long?): Instant? = timestamp?.let(Instant::ofEpochMilli)
|
||||||
return date?.atZone(ZoneOffset.UTC)?.toInstant()?.toEpochMilli()
|
|
||||||
}
|
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun monthToInt(month: Month?) = month?.value
|
fun monthToInt(month: Month?) = month?.value
|
||||||
|
@ -51,21 +40,32 @@ class Converters {
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun intListToJson(list: List<Int>): String {
|
fun intListToJson(list: List<Int>): String {
|
||||||
return integerListAdapter.toJson(list)
|
return json.encodeToString(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun jsonToIntList(value: String): List<Int> {
|
fun jsonToIntList(value: String): List<Int> {
|
||||||
return integerListAdapter.fromJson(value).orEmpty()
|
return json.decodeFromString(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun stringPairListToJson(list: List<Pair<String, String>>): String {
|
fun stringPairListToJson(list: List<Pair<String, String>>): String {
|
||||||
return stringListPairAdapter.toJson(list)
|
return json.encodeToString(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun jsonToStringPairList(value: String): List<Pair<String, String>> {
|
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)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,18 @@ class SharedPrefProvider @Inject constructor(
|
||||||
|
|
||||||
fun getLong(key: String, defaultValue: Long) = sharedPref.getLong(key, defaultValue)
|
fun getLong(key: String, defaultValue: Long) = sharedPref.getLong(key, defaultValue)
|
||||||
|
|
||||||
fun getString(key: String, defaultValue: String): String = sharedPref.getString(key, defaultValue) ?: defaultValue
|
fun getString(key: String) = sharedPref.getString(key, null)
|
||||||
|
|
||||||
fun putString(key: String, value: String, sync: Boolean = false) {
|
fun getString(key: String, defaultValue: String): String =
|
||||||
|
sharedPref.getString(key, defaultValue) ?: 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 putString(key: String, value: String?, sync: Boolean = false) {
|
||||||
sharedPref.edit(sync) { putString(key, value) }
|
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
|
@Dao
|
||||||
interface AttendanceDao : BaseDao<Attendance> {
|
interface AttendanceDao : BaseDao<Attendance> {
|
||||||
|
|
||||||
@Query("SELECT * FROM Attendance WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
@Query("SELECT * FROM Attendance WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :start AND date <= :end")
|
||||||
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow<List<Attendance>>
|
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.Delete
|
||||||
import androidx.room.Insert
|
import androidx.room.Insert
|
||||||
|
import androidx.room.OnConflictStrategy
|
||||||
import androidx.room.Update
|
import androidx.room.Update
|
||||||
|
|
||||||
interface BaseDao<T> {
|
interface BaseDao<T> {
|
||||||
|
|
||||||
@Insert
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
suspend fun insertAll(items: List<T>): List<Long>
|
suspend fun insertAll(items: List<T>): List<Long>
|
||||||
|
|
||||||
@Update
|
@Update
|
||||||
|
|
|
@ -4,12 +4,13 @@ import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.Conference
|
import io.github.wulkanowy.data.db.entities.Conference
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import java.time.Instant
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
@Singleton
|
@Singleton
|
||||||
interface ConferenceDao : BaseDao<Conference> {
|
interface ConferenceDao : BaseDao<Conference> {
|
||||||
|
|
||||||
@Query("SELECT * FROM Conferences WHERE diary_id = :diaryId AND student_id = :studentId")
|
@Query("SELECT * FROM Conferences WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :startDate")
|
||||||
fun loadAll(diaryId: Int, studentId: Int): 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> {
|
interface MessagesDao : BaseDao<Message> {
|
||||||
|
|
||||||
@Transaction
|
@Transaction
|
||||||
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND message_id = :messageId")
|
@Query("SELECT * FROM Messages WHERE message_global_key = :messageGlobalKey")
|
||||||
fun loadMessageWithAttachment(studentId: Int, messageId: Int): Flow<MessageWithAttachment?>
|
fun loadMessageWithAttachment(messageGlobalKey: String): Flow<MessageWithAttachment?>
|
||||||
|
|
||||||
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND folder_id = :folder ORDER BY date DESC")
|
@Query("SELECT * FROM Messages WHERE mailbox_key = :mailboxKey AND folder_id = :folder ORDER BY date DESC")
|
||||||
fun loadAll(studentId: Int, folder: Int): Flow<List<Message>>
|
fun loadAll(mailboxKey: String, folder: Int): Flow<List<Message>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM Messages WHERE email = :email AND folder_id = :folder ORDER BY date DESC")
|
||||||
|
fun loadAll(folder: Int, email: String): Flow<List<Message>>
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,6 @@ import kotlinx.coroutines.flow.Flow
|
||||||
@Dao
|
@Dao
|
||||||
interface MobileDeviceDao : BaseDao<MobileDevice> {
|
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>>
|
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.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
|
import io.github.wulkanowy.data.db.entities.MailboxType
|
||||||
import io.github.wulkanowy.data.db.entities.Recipient
|
import io.github.wulkanowy.data.db.entities.Recipient
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@ -9,6 +10,6 @@ import javax.inject.Singleton
|
||||||
@Dao
|
@Dao
|
||||||
interface RecipientDao : BaseDao<Recipient> {
|
interface RecipientDao : BaseDao<Recipient> {
|
||||||
|
|
||||||
@Query("SELECT * FROM Recipients WHERE student_id = :studentId AND unit_id = :unitId AND role = :role")
|
@Query("SELECT * FROM Recipients WHERE type = :type AND studentMailboxGlobalKey = :studentMailboxGlobalKey")
|
||||||
suspend fun loadAll(studentId: Int, unitId: Int, role: Int): List<Recipient>
|
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?
|
|
||||||
}
|
|
|
@ -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.SchoolAnnouncement
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
@Singleton
|
||||||
|
interface SchoolAnnouncementDao : BaseDao<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
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.*
|
||||||
import androidx.room.Delete
|
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.OnConflictStrategy.ABORT
|
import androidx.room.OnConflictStrategy.ABORT
|
||||||
import androidx.room.Query
|
|
||||||
import androidx.room.Transaction
|
|
||||||
import androidx.room.Update
|
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.db.entities.StudentNickAndAvatar
|
import io.github.wulkanowy.data.db.entities.StudentNickAndAvatar
|
||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||||
|
@ -14,33 +9,43 @@ import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Dao
|
@Dao
|
||||||
interface StudentDao {
|
abstract class StudentDao {
|
||||||
|
|
||||||
@Insert(onConflict = ABORT)
|
@Insert(onConflict = ABORT)
|
||||||
suspend fun insertAll(student: List<Student>): List<Long>
|
abstract suspend fun insertAll(student: List<Student>): List<Long>
|
||||||
|
|
||||||
@Delete
|
@Delete
|
||||||
suspend fun delete(student: Student)
|
abstract suspend fun delete(student: Student)
|
||||||
|
|
||||||
@Update(entity = Student::class)
|
@Update(entity = Student::class)
|
||||||
suspend fun update(studentNickAndAvatar: StudentNickAndAvatar)
|
abstract suspend fun update(studentNickAndAvatar: StudentNickAndAvatar)
|
||||||
|
|
||||||
@Query("SELECT * FROM Students WHERE is_current = 1")
|
@Query("SELECT * FROM Students WHERE is_current = 1")
|
||||||
suspend fun loadCurrent(): Student?
|
abstract suspend fun loadCurrent(): Student?
|
||||||
|
|
||||||
@Query("SELECT * FROM Students WHERE id = :id")
|
@Query("SELECT * FROM Students WHERE id = :id")
|
||||||
suspend fun loadById(id: Long): Student?
|
abstract suspend fun loadById(id: Long): Student?
|
||||||
|
|
||||||
@Query("SELECT * FROM Students")
|
@Query("SELECT * FROM Students")
|
||||||
suspend fun loadAll(): List<Student>
|
abstract suspend fun loadAll(): List<Student>
|
||||||
|
|
||||||
@Transaction
|
@Transaction
|
||||||
@Query("SELECT * FROM Students")
|
@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")
|
@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")
|
@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 io.github.wulkanowy.data.db.entities.TimetableAdditional
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
|
import java.util.UUID
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
|
@ -12,5 +13,13 @@ import javax.inject.Singleton
|
||||||
interface TimetableAdditionalDao : BaseDao<TimetableAdditional> {
|
interface TimetableAdditionalDao : BaseDao<TimetableAdditional> {
|
||||||
|
|
||||||
@Query("SELECT * FROM TimetableAdditional WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
@Query("SELECT * FROM TimetableAdditional WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
||||||
fun loadAll(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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,4 +13,7 @@ interface TimetableDao : BaseDao<Timetable> {
|
||||||
|
|
||||||
@Query("SELECT * FROM Timetable WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
@Query("SELECT * FROM Timetable WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
||||||
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow<List<Timetable>>
|
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow<List<Timetable>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM Timetable WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
||||||
|
fun load(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): List<Timetable>
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Query
|
||||||
|
import io.github.wulkanowy.data.db.entities.TimetableHeader
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import java.time.LocalDate
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
@Singleton
|
||||||
|
interface TimetableHeaderDao : BaseDao<TimetableHeader> {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM TimetableHeaders 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<TimetableHeader>>
|
||||||
|
}
|
|
@ -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)
|
@PrimaryKey(autoGenerate = true)
|
||||||
var id: Long = 0
|
var id: Long = 0
|
||||||
|
|
||||||
|
@ColumnInfo(name = "is_notified")
|
||||||
|
var isNotified: Boolean = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import androidx.room.ColumnInfo
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.time.LocalDateTime
|
import java.time.Instant
|
||||||
|
|
||||||
@Entity(tableName = "Conferences")
|
@Entity(tableName = "Conferences")
|
||||||
data class Conference(
|
data class Conference(
|
||||||
|
@ -27,9 +27,12 @@ data class Conference(
|
||||||
@ColumnInfo(name = "conference_id")
|
@ColumnInfo(name = "conference_id")
|
||||||
val conferenceId: Int,
|
val conferenceId: Int,
|
||||||
|
|
||||||
val date: LocalDateTime
|
val date: Instant,
|
||||||
) : Serializable {
|
) : Serializable {
|
||||||
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
var id: Long = 0
|
var id: Long = 0
|
||||||
|
|
||||||
|
@ColumnInfo(name = "is_notified")
|
||||||
|
var isNotified: Boolean = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,4 +36,7 @@ data class Exam(
|
||||||
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
var id: Long = 0
|
var id: Long = 0
|
||||||
|
|
||||||
|
@ColumnInfo(name = "is_notified")
|
||||||
|
var isNotified: Boolean = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,5 +24,8 @@ data class GradeSemesterStatistics(
|
||||||
var id: Long = 0
|
var id: Long = 0
|
||||||
|
|
||||||
@Transient
|
@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.ColumnInfo
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import java.time.LocalDateTime
|
import java.time.Instant
|
||||||
|
|
||||||
@Entity(tableName = "GradesSummary")
|
@Entity(tableName = "GradesSummary")
|
||||||
data class GradeSummary(
|
data class GradeSummary(
|
||||||
|
@ -45,8 +45,8 @@ data class GradeSummary(
|
||||||
var isFinalGradeNotified: Boolean = true
|
var isFinalGradeNotified: Boolean = true
|
||||||
|
|
||||||
@ColumnInfo(name = "predicted_grade_last_change")
|
@ColumnInfo(name = "predicted_grade_last_change")
|
||||||
var predictedGradeLastChange: LocalDateTime = LocalDateTime.now()
|
var predictedGradeLastChange: Instant = Instant.now()
|
||||||
|
|
||||||
@ColumnInfo(name = "final_grade_last_change")
|
@ColumnInfo(name = "final_grade_last_change")
|
||||||
var finalGradeLastChange: LocalDateTime = LocalDateTime.now()
|
var finalGradeLastChange: Instant = Instant.now()
|
||||||
}
|
}
|
||||||
|
|