mirror of
https://github.com/PranshulGG/WeatherMaster.git
synced 2026-10-19 01:31:17 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
206a8ab23a | ||
|
|
042f675ac8 | ||
|
|
cfff16c57d | ||
|
|
5f698cab75 | ||
|
|
9be4c7eab7 | ||
|
|
b196ed6799 | ||
|
|
3654d8d630 | ||
|
|
0297ba99bc | ||
|
|
d30f9b8a66 | ||
|
|
dfa6d89aba | ||
|
|
1e1b8b2cab | ||
|
|
f271d32ed9 | ||
|
|
cde9f5c55b | ||
|
|
86dbe0f029 | ||
|
|
027ab2b18d | ||
|
|
402843a93a | ||
|
|
7f21132013 | ||
|
|
f91d9792ce | ||
|
|
f330a33202 | ||
|
|
996549b3bc | ||
|
|
68656c02a1 | ||
|
|
260cd86527 | ||
|
|
7f83896f4a | ||
|
|
aef3869891 | ||
|
|
22d51ee63a | ||
|
|
b08ea96207 | ||
|
|
26c535aab3 | ||
|
|
1d3c64ee79 | ||
|
|
6bfd46a438 | ||
|
|
12ff63f518 | ||
|
|
ce386c7036 | ||
|
|
04fa01f093 | ||
|
|
f02f68da81 | ||
|
|
cf2d9a8557 | ||
|
|
1c6096108f | ||
|
|
0f37309dd2 | ||
|
|
32b1d3d94f | ||
|
|
501955817c | ||
|
|
97de9412a9 | ||
|
|
c8cd37c9bc | ||
|
|
ba6f293017 | ||
|
|
548127fa2f | ||
|
|
387f945311 | ||
|
|
17203bdf7a | ||
|
|
36be536aff | ||
|
|
3f91b16feb | ||
|
|
3b0370b48c | ||
|
|
ee64dedab2 | ||
|
|
a2cd0500f9 | ||
|
|
dfedb104a9 | ||
|
|
33c54ecbfb | ||
|
|
893ac8beaa | ||
|
|
abc4c30151 | ||
|
|
f651e34a25 | ||
|
|
65b2020412 | ||
|
|
c700b649b9 | ||
|
|
43f069d904 | ||
|
|
6552b9721e | ||
|
|
ed9400d2b7 | ||
|
|
63f029be75 | ||
|
|
8045d6340a | ||
|
|
c3edf51fb8 | ||
|
|
38b0586556 | ||
|
|
4fa749ebb5 | ||
|
|
43bf77fe1f | ||
|
|
15c011b621 | ||
|
|
74f81d2886 | ||
|
|
1a8705cac1 | ||
|
|
899fff4974 | ||
|
|
d20283bf28 | ||
|
|
f4f0abbff9 | ||
|
|
adedb4631d | ||
|
|
9c4708c24a | ||
|
|
ca31292a60 | ||
|
|
89c22e23a0 | ||
|
|
cf4cd505f8 | ||
|
|
3d8d2f1450 | ||
|
|
8cd7bd07a1 | ||
|
|
4cc69b43c3 | ||
|
|
4f1ec0a295 | ||
|
|
19ff66cdec | ||
|
|
64c253b39f | ||
|
|
ed3409ac22 | ||
|
|
6f1bbdf30e | ||
|
|
ae85de71f3 | ||
|
|
66f5fb0241 | ||
|
|
08e741823d | ||
|
|
66cb039232 | ||
|
|
7a2a101a2e | ||
|
|
efca511021 | ||
|
|
56908af4ef | ||
|
|
4d0da91355 | ||
|
|
ffc6ffa5e8 | ||
|
|
4e781a44af | ||
|
|
8bda1ce3e3 | ||
|
|
adbcffead4 | ||
|
|
5111d9d9f0 | ||
|
|
0c625daa33 | ||
|
|
b14e644fcc | ||
|
|
73bc232e91 | ||
|
|
81eb54bad7 | ||
|
|
815137eb02 | ||
|
|
e578bae8a1 | ||
|
|
53e8d8f1ef | ||
|
|
9a69c4cce6 | ||
|
|
136f4f37a0 | ||
|
|
10509d8427 | ||
|
|
910787b056 | ||
|
|
7cc4e643a4 | ||
|
|
cf0ca64199 | ||
|
|
fac5fe2c59 | ||
|
|
e7e94d0390 | ||
|
|
78ae8da2a8 | ||
|
|
469acf95c3 | ||
|
|
8b7564d0fb | ||
|
|
9627cefdd1 | ||
|
|
5ac3c511cd | ||
|
|
9a51fec33b | ||
|
|
fcc52ecb5e | ||
|
|
e7097f081b | ||
|
|
94951173d0 | ||
|
|
ae06a0a827 | ||
|
|
b9a0cb7d54 | ||
|
|
c20f581c41 | ||
|
|
48314baa0a | ||
|
|
06ffe45167 | ||
|
|
9d74fbbeef | ||
|
|
7819fa5323 | ||
|
|
ad3531ad33 | ||
|
|
0736a4e9e8 | ||
|
|
5953f8ffd5 | ||
|
|
0d14513648 | ||
|
|
83fb2f2911 | ||
|
|
a09ec9e735 | ||
|
|
bbfafbfdb9 | ||
|
|
25c5426b4e | ||
|
|
cebac4681d | ||
|
|
9304fd4eea | ||
|
|
4299d0e9b4 | ||
|
|
a12eb90d14 | ||
|
|
b3a4dc4bc2 | ||
|
|
8cd290105f | ||
|
|
56251ad992 | ||
|
|
abcb1b460f | ||
|
|
acd8cfd24f | ||
|
|
145809a62c | ||
|
|
4e05961df8 | ||
|
|
ee41bb0380 | ||
|
|
bc3e17d8b6 | ||
|
|
17ef87f3dd | ||
|
|
02ebad26ed | ||
|
|
40c48a3330 | ||
|
|
a550ccee77 | ||
|
|
c52d61126d | ||
|
|
e782c84659 | ||
|
|
f309a6a1f7 | ||
|
|
d191b84956 | ||
|
|
e011dd92ea | ||
|
|
7ddeb9c271 | ||
|
|
7d5396626d | ||
|
|
6a874ff3d2 | ||
|
|
0e2deed274 | ||
|
|
f75e1b484e | ||
|
|
ca13f75055 | ||
|
|
0cdeb42136 | ||
|
|
7ecce86eba | ||
|
|
9a02b5d149 | ||
|
|
02f55cc56c | ||
|
|
2c512574c0 | ||
|
|
4bdcdf1107 | ||
|
|
32191bda80 | ||
|
|
1b0021275d | ||
|
|
7a2c83517a | ||
|
|
8bff40ccb4 | ||
|
|
cbdc5a902a | ||
|
|
bd6fbf9bef | ||
|
|
c31c60cbdc | ||
|
|
547c05114e | ||
|
|
58e1b54ac2 | ||
|
|
c5803f299a | ||
|
|
998b7aae7f | ||
|
|
c7612b0a8f | ||
|
|
6c0a6434af | ||
|
|
32b3e81842 | ||
|
|
e9a2cadab3 | ||
|
|
3c55d45baa | ||
|
|
e0795688a7 | ||
|
|
534dba0971 | ||
|
|
22a01314b3 | ||
|
|
05db53929b | ||
|
|
9e0a0c7d3e | ||
|
|
042caed47b | ||
|
|
03672e9d52 | ||
|
|
60b521c725 | ||
|
|
eaa296464d | ||
|
|
be27ae93c4 | ||
|
|
653a6c672a | ||
|
|
5cf9a52766 | ||
|
|
ab37bfa083 | ||
|
|
f18d874cc2 | ||
|
|
b353a4c6cd | ||
|
|
50c16ded25 | ||
|
|
07da76f76a | ||
|
|
06b498f841 | ||
|
|
3c61ddc037 | ||
|
|
197b6177e4 | ||
|
|
488034eb9c | ||
|
|
aa6cd371bf | ||
|
|
c5fb65408b | ||
|
|
fd83a163f5 | ||
|
|
2606361bba | ||
|
|
c19e30f0db | ||
|
|
cff2be99e4 | ||
|
|
783fe3c305 | ||
|
|
8d1cb83dbb | ||
|
|
fb90527fbf | ||
|
|
62055559dc | ||
|
|
aa98be6c13 | ||
|
|
231c992b4f | ||
|
|
e9977e2f71 | ||
|
|
8c2c4314ed | ||
|
|
956163fe9f | ||
|
|
d2c89da024 | ||
|
|
b6ef35f80a | ||
|
|
7fe2201a63 | ||
|
|
37ff2c6234 | ||
|
|
8e0aa56ad8 | ||
|
|
2fd30077fa | ||
|
|
9716bcdbd9 | ||
|
|
f3e6143b7e | ||
|
|
991f74a9f6 | ||
|
|
644a83dd28 | ||
|
|
2992fe5afb | ||
|
|
8d1f7434df | ||
|
|
f27563de27 | ||
|
|
bf13576b05 | ||
|
|
c47325885b | ||
|
|
387d022871 | ||
|
|
f78a580bf8 | ||
|
|
9fb5ce964d | ||
|
|
d26882e137 | ||
|
|
8dd8ad1504 | ||
|
|
af230b8970 | ||
|
|
8863b82317 | ||
|
|
f3132a772e | ||
|
|
aab31a2809 | ||
|
|
75562186b9 | ||
|
|
191fe86e1e | ||
|
|
8c2296b602 | ||
|
|
3eb4c4c1f7 | ||
|
|
92495ed55a | ||
|
|
ae5129778e | ||
|
|
33a8dccd36 | ||
|
|
0475f86e46 | ||
|
|
2c114f83e5 | ||
|
|
44286fd1ef | ||
|
|
79f7b42a3a | ||
|
|
6ff7528b5e | ||
|
|
a09e044ab9 | ||
|
|
4990819f49 | ||
|
|
0634439209 | ||
|
|
a1ecf07ed1 | ||
|
|
38579071f4 | ||
|
|
cb095feeec | ||
|
|
32ac4f4ca2 | ||
|
|
177ade280f | ||
|
|
30d8fb8bfb | ||
|
|
a615652a74 | ||
|
|
29054b7ebd | ||
|
|
5d73b6758c | ||
|
|
2cd5146b3b | ||
|
|
936565c5a6 | ||
|
|
f7a2b00286 | ||
|
|
e63a7fef42 | ||
|
|
ca05f102ae | ||
|
|
9a652e32ab | ||
|
|
075aae0e8c | ||
|
|
eea42ff074 | ||
|
|
d8731ae768 | ||
|
|
5c67123290 | ||
|
|
f0dc836631 | ||
|
|
e8db1e45c1 | ||
|
|
2721359394 | ||
|
|
3836e22c5a | ||
|
|
db378e8efb | ||
|
|
81702b7a17 | ||
|
|
a8e844dec3 | ||
|
|
cfd606baa5 | ||
|
|
cf8e9a52df | ||
|
|
d2e65ef50a | ||
|
|
99f332d661 | ||
|
|
9330d02457 | ||
|
|
fd42c54005 | ||
|
|
7c39e9d402 | ||
|
|
e274bf8ee5 | ||
|
|
e3377907f4 | ||
|
|
a834a13420 | ||
|
|
8434131c45 | ||
|
|
42efce2adc | ||
|
|
2dac97769b | ||
|
|
26b6a45b6a | ||
|
|
f16b713e81 | ||
|
|
4ae3a46cee | ||
|
|
10e7dde828 | ||
|
|
70deefc2dd | ||
|
|
e4fea1dcca | ||
|
|
4fe834091c | ||
|
|
b127b237e5 | ||
|
|
5a62a9c598 | ||
|
|
6820379008 | ||
|
|
c06e36e206 | ||
|
|
5611229508 | ||
|
|
25a32308b1 | ||
|
|
c086382c5e | ||
|
|
fa901ff60a | ||
|
|
097af8d0bb | ||
|
|
d3eeaa5e21 | ||
|
|
07ee9a04d5 | ||
|
|
ae21b74622 | ||
|
|
c057edc390 | ||
|
|
790937dc43 | ||
|
|
7dff6feef6 | ||
|
|
e19290a517 | ||
|
|
976d243e82 | ||
|
|
37b955cc38 | ||
|
|
d516ba79d8 | ||
|
|
835fa61eaa | ||
|
|
512530491f | ||
|
|
8a0b5fd04d | ||
|
|
b37e772882 | ||
|
|
deff68c6c3 | ||
|
|
8f303a8c55 | ||
|
|
3186c11d6b | ||
|
|
894f32cd14 | ||
|
|
df4e116564 | ||
|
|
e11459b9c9 | ||
|
|
bba8768952 | ||
|
|
d88c3e0cc2 | ||
|
|
8ca8ef7b96 | ||
|
|
ee3db85233 | ||
|
|
4a39f5c02c | ||
|
|
ef8cdb03d2 | ||
|
|
723eb741b4 | ||
|
|
466566433f | ||
|
|
d3e6a0273f | ||
|
|
af14e4e440 | ||
|
|
feed0d847d | ||
|
|
b2e61968e1 | ||
|
|
b357572473 | ||
|
|
145bea15ec | ||
|
|
be301782cc | ||
|
|
bb9d723a24 | ||
|
|
af2f127d78 | ||
|
|
effa4f4a48 | ||
|
|
0d6bc73fdb | ||
|
|
ed437164af | ||
|
|
aff6849557 | ||
|
|
5dbbd73152 | ||
|
|
9aa6884356 | ||
|
|
b9a123626a | ||
|
|
2e35367ae9 | ||
|
|
14cf35624c | ||
|
|
b22f3f3b3b | ||
|
|
90ea14b88d | ||
|
|
df54f032c5 | ||
|
|
e325d2bd8e | ||
|
|
350358c11f | ||
|
|
da083bd25d | ||
|
|
c6337a7d05 | ||
|
|
d782552a7c | ||
|
|
c576b53666 | ||
|
|
6bcd03b14e | ||
|
|
8e6bb9d2c3 | ||
|
|
cc5ee455ee | ||
|
|
c30149b84e | ||
|
|
8f030ef45d | ||
|
|
868d022f62 | ||
|
|
9208364396 | ||
|
|
421077a893 | ||
|
|
26055e2ed0 | ||
|
|
8f8c38c31c | ||
|
|
c103a20d67 | ||
|
|
440fe23cb1 | ||
|
|
54cd8731a4 | ||
|
|
60a2451c04 | ||
|
|
b77dd5cfef | ||
|
|
6a0d12ca99 | ||
|
|
50069d5bbf | ||
|
|
cffa79e1a9 | ||
|
|
4f25c0984e | ||
|
|
f13804eee4 | ||
|
|
a8454b5f0f | ||
|
|
501ab35af7 | ||
|
|
aba3ee8eca | ||
|
|
d76abb1f06 | ||
|
|
241ab03dd2 | ||
|
|
41a2a9abe3 | ||
|
|
f1e8707aa1 | ||
|
|
9327b90e9f | ||
|
|
e2c43cd774 | ||
|
|
21d7466d24 | ||
|
|
40a41432ea | ||
|
|
bc23098401 | ||
|
|
26b90e2721 | ||
|
|
dbf162d92f | ||
|
|
d99a79d925 | ||
|
|
610b2f29e6 | ||
|
|
e0fa0374d3 | ||
|
|
0f63154f84 | ||
|
|
7a799cb24a | ||
|
|
178300a547 | ||
|
|
9baec3bb63 | ||
|
|
d417f6b4f1 | ||
|
|
ff60bb41f1 | ||
|
|
f41bd691e9 | ||
|
|
78450b78a2 | ||
|
|
3bff4f99b8 | ||
|
|
2ba49de23f | ||
|
|
ce14573fa0 | ||
|
|
535ad8feb6 | ||
|
|
0f6b0950ea | ||
|
|
0fe4afe5c5 | ||
|
|
a3f8ab735f | ||
|
|
aee884b7cd | ||
|
|
ee5df57a43 | ||
|
|
b0289561ab | ||
|
|
041fdfd605 | ||
|
|
4419fef116 | ||
|
|
788354ecea | ||
|
|
3b55de9785 | ||
|
|
6b7285f0f4 | ||
|
|
d493b6f83d | ||
|
|
875ab0138a | ||
|
|
2bd0ae075d | ||
|
|
92db6f7f3c | ||
|
|
36406fd803 | ||
|
|
22a69af5d5 | ||
|
|
140f880973 | ||
|
|
df427f4dbc | ||
|
|
6f0da01b1b | ||
|
|
28849dce75 | ||
|
|
110fb5cb10 | ||
|
|
1531eeb2f2 | ||
|
|
437fada842 | ||
|
|
89516df777 | ||
|
|
e5e1dd653a | ||
|
|
a6efd55267 | ||
|
|
a6d3d150c7 | ||
|
|
f628a22b45 | ||
|
|
d73020699a | ||
|
|
eb9d91f955 | ||
|
|
2df11581d5 | ||
|
|
08a0753376 | ||
|
|
d1590f435f | ||
|
|
1fa82c1623 | ||
|
|
c653127a5f | ||
|
|
ee49326a65 | ||
|
|
78c46369cc | ||
|
|
c34b6a3fed | ||
|
|
057b171dc5 | ||
|
|
0a26f51cc1 | ||
|
|
505b23bac4 | ||
|
|
2693fef706 | ||
|
|
95bd4d51be | ||
|
|
f16820d63a | ||
|
|
d44f2f6650 | ||
|
|
131c0d422d | ||
|
|
ee30d3c32c | ||
|
|
6d953c1be5 | ||
|
|
6c892dfc7c | ||
|
|
a78fdf7794 | ||
|
|
cf4f20d4e1 | ||
|
|
eba12e7764 | ||
|
|
08a376b368 | ||
|
|
1a5aa6e8bb | ||
|
|
94992e2964 | ||
|
|
55dfa49092 | ||
|
|
d00bdc6fd2 | ||
|
|
3a0303c7a8 | ||
|
|
cd59a1acbb | ||
|
|
908b9ad1f1 | ||
|
|
b904ccfda3 | ||
|
|
1fc1fdbfb3 | ||
|
|
af41a68451 | ||
|
|
e3fe505f5b | ||
|
|
9f9539ce6f | ||
|
|
8d33745d06 | ||
|
|
99a9918676 | ||
|
|
e5f01faf6a | ||
|
|
f21c18c058 | ||
|
|
7ab944e769 | ||
|
|
90a80b1e61 | ||
|
|
43aeb6d59e | ||
|
|
ccf0135932 | ||
|
|
c859e43f3e | ||
|
|
a450ec0895 | ||
|
|
1bee5cf6c6 | ||
|
|
6c364f6d10 | ||
|
|
4c0139c0aa | ||
|
|
f3efc3f73a | ||
|
|
1bebbac4ae | ||
|
|
1d39ddd941 | ||
|
|
7303979d93 | ||
|
|
0dda08ec21 | ||
|
|
84b56ac53f | ||
|
|
46d099927e | ||
|
|
442fc8fd4e | ||
|
|
af80866766 | ||
|
|
6f8b45ca18 | ||
|
|
47a5b0b1b7 | ||
|
|
0d70296959 | ||
|
|
8b52d13b3e | ||
|
|
28bf02a6fa | ||
|
|
dd8f1f0685 | ||
|
|
7c4b4027f3 | ||
|
|
80bcbf43f0 | ||
|
|
70fe1a8459 | ||
|
|
7d2b97173a | ||
|
|
2f5cf31a36 | ||
|
|
0fb5d6386e | ||
|
|
3316760752 | ||
|
|
4f78b59e4d | ||
|
|
6c29dc1fc8 | ||
|
|
6b57d3c557 | ||
|
|
b0a9b03ebd | ||
|
|
2a848ce478 | ||
|
|
61a94e1e90 | ||
|
|
b910f85bc9 | ||
|
|
ed56bd48e2 | ||
|
|
380c8fceb6 | ||
|
|
245ec8cafc | ||
|
|
130ae9437e | ||
|
|
023195386a | ||
|
|
e33cf1e4b7 | ||
|
|
fafcca97ff | ||
|
|
83b34568c8 | ||
|
|
4bfab73ff7 | ||
|
|
6fe4c4587a | ||
|
|
dee4780980 | ||
|
|
a179446126 | ||
|
|
bf5468ea04 | ||
|
|
747527c23c | ||
|
|
4b47a9bcf4 | ||
|
|
291984de32 | ||
|
|
b54b17872d | ||
|
|
2bb8549a93 | ||
|
|
f3ae6d5563 | ||
|
|
4479c43182 | ||
|
|
2dac241237 | ||
|
|
e9fb0ab462 | ||
|
|
fa651168f6 | ||
|
|
d59b4b7a4b | ||
|
|
d852fbbeea | ||
|
|
d7a062edd8 | ||
|
|
90f331b824 | ||
|
|
dd84612797 | ||
|
|
61ce0712a5 | ||
|
|
312df078c6 | ||
|
|
4977ff7a70 | ||
|
|
0fd4423d9e | ||
|
|
ba1108a681 | ||
|
|
eb9e6bae8c | ||
|
|
4b363fc70c | ||
|
|
b589268359 | ||
|
|
56f6167059 | ||
|
|
822647ad9d | ||
|
|
a483367254 | ||
|
|
fb9a8418bb | ||
|
|
996c4d0da7 | ||
|
|
556d0c17a3 | ||
|
|
77a3c2b447 | ||
|
|
8ea3391834 | ||
|
|
7763842e3f | ||
|
|
2681b5f79c | ||
|
|
8b63311f27 | ||
|
|
a9ccd31878 | ||
|
|
ec379303df | ||
|
|
197d7f289e | ||
|
|
d6ffaa6296 | ||
|
|
a712aa5cf3 | ||
|
|
67aecfb801 | ||
|
|
c906608949 | ||
|
|
0250de39da | ||
|
|
f8eaf46410 | ||
|
|
de0edc1a5a | ||
|
|
b0978fcc59 | ||
|
|
494baa735e | ||
|
|
9b45954b3e | ||
|
|
d643ac0824 | ||
|
|
8735ae3c91 | ||
|
|
9a8b7dc039 | ||
|
|
eb08b049b6 | ||
|
|
adf707b05e | ||
|
|
c63300147d | ||
|
|
30ed7e5ecc | ||
|
|
8d76519371 | ||
|
|
8224eee33e | ||
|
|
2fcf6d505f | ||
|
|
c8303d1c30 | ||
|
|
9eb21ed44d | ||
|
|
fd4487e8ef | ||
|
|
d6dd1cef95 | ||
|
|
708b50d8dd | ||
|
|
75d1b310cd | ||
|
|
39c7195910 | ||
|
|
101a58c302 | ||
|
|
4f1ca5e81e | ||
|
|
57bc9940eb | ||
|
|
c3b3948a84 | ||
|
|
fa0259251c | ||
|
|
b1e00eb18b | ||
|
|
47597f5eda | ||
|
|
3dcfff12b8 | ||
|
|
caf008ff4b | ||
|
|
b2786768e5 | ||
|
|
a00c0dedeb | ||
|
|
08bd6aeb58 | ||
|
|
d95b1e7238 | ||
|
|
0c1a483dd8 | ||
|
|
564b469af2 | ||
|
|
c774f38b75 | ||
|
|
5d592d37f4 | ||
|
|
e6da014ec8 | ||
|
|
f328401991 | ||
|
|
a3efc52b6c | ||
|
|
da4b9429ba | ||
|
|
2aa8918eca | ||
|
|
4e7587cac5 | ||
|
|
b8133ea7ab | ||
|
|
5753ff235d | ||
|
|
b94021f6b4 | ||
|
|
65bdc3597a | ||
|
|
d5e8c1153a | ||
|
|
5063572e8e | ||
|
|
0e33eb45b4 | ||
|
|
c3c10c32df | ||
|
|
a6308fe77e | ||
|
|
580b0fafbc | ||
|
|
d8cc015f1e | ||
|
|
22c46cdfe2 | ||
|
|
6da01ba665 | ||
|
|
1c66ab3ea5 | ||
|
|
a6073fea32 | ||
|
|
85728b1125 | ||
|
|
24a6f127cd | ||
|
|
9a8155dd6a | ||
|
|
476bd06bd3 | ||
|
|
f1d1671b24 | ||
|
|
a472202580 | ||
|
|
a05427d32c | ||
|
|
c15119949b | ||
|
|
d939a097c9 | ||
|
|
c3388f152e | ||
|
|
f749eb43ce | ||
|
|
ecac8de460 | ||
|
|
41bd1ebcf3 | ||
|
|
965cfc17da | ||
|
|
39d597df20 | ||
|
|
d05660faa2 | ||
|
|
f86217bc7b | ||
|
|
1229bc792f | ||
|
|
e4355b9b93 | ||
|
|
282d3ba501 | ||
|
|
8b2f80ddc8 | ||
|
|
26dee72ce7 | ||
|
|
4abbcabf12 | ||
|
|
d2b0314c63 | ||
|
|
9dc685fbf8 | ||
|
|
64885f5b6d | ||
|
|
f2eb7d2f70 | ||
|
|
53812e94ce | ||
|
|
b4e7c67e62 | ||
|
|
99bd0ba8aa | ||
|
|
ba692433e3 | ||
|
|
78c36087ab | ||
|
|
1c1dad0e5d | ||
|
|
71607b1313 | ||
|
|
971e2c42d8 | ||
|
|
1644a212df | ||
|
|
3c372d3109 | ||
|
|
8fd490d781 | ||
|
|
f3b71b4845 | ||
|
|
b9519e22b7 | ||
|
|
6f16ae6d10 | ||
|
|
122bf1f4f0 | ||
|
|
dc9fca7d59 | ||
|
|
0d8bc25b4e | ||
|
|
f965e2c2cc | ||
|
|
a97213e99b | ||
|
|
f5a68f2881 | ||
|
|
d0dc74c34b | ||
|
|
5b4991983f | ||
|
|
737beffb50 | ||
|
|
d60eddc4c5 | ||
|
|
bdfc1350f7 | ||
|
|
59a10e71e3 | ||
|
|
9d3cdc5df9 | ||
|
|
9a3aab06f6 | ||
|
|
a69233a026 | ||
|
|
2f66a4a0fd | ||
|
|
a7d1b8d959 | ||
|
|
5b85adc07d | ||
|
|
f8bf501fb3 | ||
|
|
c7660b6d62 | ||
|
|
20ebd7b17e | ||
|
|
e4d3339694 | ||
|
|
2ed989b619 | ||
|
|
a4857fc516 | ||
|
|
700c64bbfa | ||
|
|
9c3e5dbb97 | ||
|
|
f5db93222f | ||
|
|
dd7b5f2bc2 | ||
|
|
0a31a25250 | ||
|
|
c6c68c8202 | ||
|
|
a252e9ac2e | ||
|
|
eb4b6eff0d | ||
|
|
33d44e540b | ||
|
|
cf124b8fe8 | ||
|
|
ffd0e121f5 | ||
|
|
634ba26bbd | ||
|
|
41b681f571 | ||
|
|
d6e576d45c | ||
|
|
11b2755c09 | ||
|
|
a7b77cc985 | ||
|
|
79f61bee20 | ||
|
|
7b1098d936 | ||
|
|
5da6ab4690 | ||
|
|
74dd449600 | ||
|
|
6af2cbb3cb | ||
|
|
987168b1e4 | ||
|
|
8ac8300f29 | ||
|
|
8cd993e3d5 | ||
|
|
9c901ef2cd | ||
|
|
b30c4e7418 | ||
|
|
149dabd82c | ||
|
|
88f97b8980 | ||
|
|
06626f72f0 | ||
|
|
2dc819e94c | ||
|
|
72c4ffbbf0 | ||
|
|
e983fcea6e | ||
|
|
799dc84edb | ||
|
|
3e8ee4d05e | ||
|
|
b229b37e93 | ||
|
|
aa69f912d6 | ||
|
|
b2d7b10470 | ||
|
|
b288db34f4 | ||
|
|
a08f76c261 | ||
|
|
204c10c1d0 | ||
|
|
3c0d720441 | ||
|
|
69daeab654 | ||
|
|
8cb340127a | ||
|
|
1754f87005 | ||
|
|
7ae657049d | ||
|
|
7f3dc42fbb | ||
|
|
4c3f453e02 | ||
|
|
b05419b6a7 | ||
|
|
933c194fce | ||
|
|
74dc479417 | ||
|
|
8dd4807e34 | ||
|
|
336ae18f11 | ||
|
|
f6d084382e | ||
|
|
47fa36dbe5 | ||
|
|
635f1fa239 | ||
|
|
c051980c9f | ||
|
|
e15c44a98a | ||
|
|
12f8d2bb40 | ||
|
|
eeb4e0b81e | ||
|
|
30415e3bf3 | ||
|
|
b0ea149de3 | ||
|
|
761528e7fd | ||
|
|
9b83b2f48b | ||
|
|
ca5819bffe | ||
|
|
b4d322a62e | ||
|
|
24fcc6b80c | ||
|
|
3a33ae0e4d | ||
|
|
a33890777a | ||
|
|
8a204a7630 | ||
|
|
e3404a0740 | ||
|
|
fb04e7d55c | ||
|
|
021e3159f0 | ||
|
|
987251e1eb | ||
|
|
de85bd83f8 | ||
|
|
ac757c0ff6 | ||
|
|
92a701947e | ||
|
|
49af5f20ad | ||
|
|
93a023a3ee | ||
|
|
6131b8de09 | ||
|
|
d712175d7f | ||
|
|
aa43bdd420 | ||
|
|
07bc22d669 | ||
|
|
99d0f0aa6e | ||
|
|
49c4977fbf | ||
|
|
34578f67a4 | ||
|
|
3cdebbfec1 | ||
|
|
6e1166d0c3 | ||
|
|
ab647903d5 | ||
|
|
eddd7607d9 | ||
|
|
975d44eecc | ||
|
|
2554c234b8 | ||
|
|
6886eb193e | ||
|
|
ca0b887444 | ||
|
|
b956d53cb6 | ||
|
|
2179d265b1 | ||
|
|
117f441329 | ||
|
|
5958c621fd | ||
|
|
40e32687f9 | ||
|
|
c64b79e63a | ||
|
|
1f805b96a0 | ||
|
|
d38b18eab0 | ||
|
|
3dfa6fe17d | ||
|
|
f16b9b57bc | ||
|
|
576695095f | ||
|
|
691ff5939c | ||
|
|
46a7cef502 | ||
|
|
ff8e76d004 | ||
|
|
c3a394470b | ||
|
|
9be2dcb168 | ||
|
|
c7d8077c65 | ||
|
|
808967c66a | ||
|
|
a179ab884d | ||
|
|
6d5bcb79a9 | ||
|
|
122d2be099 | ||
|
|
9255fdb0d0 | ||
|
|
55d534bd8e | ||
|
|
15145ab7cc | ||
|
|
d708ed1290 | ||
|
|
2126be8a0a | ||
|
|
7f3bb87551 | ||
|
|
ca1328418e | ||
|
|
5ca4d5a52d | ||
|
|
18ff6e1357 | ||
|
|
0233af3c71 | ||
|
|
31cdeab3b9 | ||
|
|
95da6977cd | ||
|
|
fd13b4a4b5 | ||
|
|
411ac69118 | ||
|
|
d2242187fc | ||
|
|
48b5e1b92f | ||
|
|
7f76a2ec6a | ||
|
|
1e7b23b0a0 | ||
|
|
c57cf08395 | ||
|
|
987c02cf4a | ||
|
|
6cac8835ab | ||
|
|
92ff8f2e64 | ||
|
|
05e683582d | ||
|
|
d94496193e | ||
|
|
b972f5ca6c | ||
|
|
14b6e0559e | ||
|
|
8a83032278 | ||
|
|
232e1494b8 | ||
|
|
4e698f21e9 | ||
|
|
a156da9ac9 | ||
|
|
671b057d7c | ||
|
|
fc4cfba8b3 | ||
|
|
cac518ffbb | ||
|
|
b35e1eb202 | ||
|
|
d5a2b30ce2 | ||
|
|
2ecd3352b5 | ||
|
|
02512d938c | ||
|
|
a96556bfc1 | ||
|
|
4b90d96442 | ||
|
|
423e3f911a | ||
|
|
edb29fc177 | ||
|
|
4eaad73181 | ||
|
|
07d78bb283 | ||
|
|
eb2b47e19d | ||
|
|
01db325285 | ||
|
|
4db9829762 | ||
|
|
b9144d8778 | ||
|
|
687b5c04af | ||
|
|
a995278311 | ||
|
|
ada9b23b33 | ||
|
|
c62bbbdfda | ||
|
|
263de7cb92 | ||
|
|
c47e8becbe | ||
|
|
1766273e07 | ||
|
|
c9fea5a682 | ||
|
|
0d0ae42785 | ||
|
|
a29281cd3e | ||
|
|
0cf6937a96 | ||
|
|
be93c85d84 | ||
|
|
8c33c06705 | ||
|
|
43a7000dd4 | ||
|
|
a55f29403a | ||
|
|
149e98a4cd | ||
|
|
4c63584965 | ||
|
|
278bed5583 | ||
|
|
504c6d7cbc | ||
|
|
da46882a00 | ||
|
|
9aef395cd7 | ||
|
|
5bd56547f4 | ||
|
|
0f500a2413 | ||
|
|
7fe34d5b3f | ||
|
|
38227c2c10 | ||
|
|
462ea6667a | ||
|
|
6d03757260 | ||
|
|
c2455851be | ||
|
|
84f952a05e | ||
|
|
416e3b11e5 | ||
|
|
ead98a797a | ||
|
|
1deb842442 | ||
|
|
dc246bae8d | ||
|
|
e8b435f16c | ||
|
|
afc91ad4d3 | ||
|
|
480715a9ae | ||
|
|
c90ba47abb | ||
|
|
94d087b50b | ||
|
|
7831a8cb4f | ||
|
|
c596930652 | ||
|
|
06d8940c21 | ||
|
|
a43471f364 | ||
|
|
6bc5369b1f | ||
|
|
bc763e1ce0 | ||
|
|
97411bd233 | ||
|
|
3f9ca5a196 | ||
|
|
e8cc19431c | ||
|
|
66b11641b9 | ||
|
|
bbcdfd6e4b | ||
|
|
6cfcf4a922 | ||
|
|
6a1b5e188f | ||
|
|
fe903ca96a | ||
|
|
ca27a85bf9 | ||
|
|
9ee3618e81 | ||
|
|
bebe346e42 | ||
|
|
43f09dd806 | ||
|
|
df8c79261b | ||
|
|
a13a9a3644 | ||
|
|
549cd9e297 | ||
|
|
f24f10e14a | ||
|
|
29400f412c | ||
|
|
e03a719560 | ||
|
|
26eeab05d3 | ||
|
|
c97012b47f | ||
|
|
cc00107c23 | ||
|
|
c33e586290 | ||
|
|
3e71d01a44 | ||
|
|
bc2d800cac | ||
|
|
ffa4549121 | ||
|
|
e6a6dbf820 | ||
|
|
517c074074 | ||
|
|
404ac6ba0b | ||
|
|
82326f0bed | ||
|
|
64eb2cac31 | ||
|
|
98bb99d164 | ||
|
|
477f327ad1 | ||
|
|
36f532d171 | ||
|
|
318605edc6 | ||
|
|
92ea801617 | ||
|
|
cc3e4810ab | ||
|
|
a959cd93c4 | ||
|
|
da373ba486 | ||
|
|
78d783621b | ||
|
|
8980ece8df | ||
|
|
a70551086e | ||
|
|
462c497d2e | ||
|
|
45efc578b7 | ||
|
|
2bb718b1e0 | ||
|
|
11b686dd32 | ||
|
|
768eb83ce4 | ||
|
|
b061e4bf76 | ||
|
|
1a20a3056b | ||
|
|
122836514c | ||
|
|
2ee19a73be | ||
|
|
87cfc62522 | ||
|
|
0e9da04449 | ||
|
|
691b9f72a3 | ||
|
|
1703aeeb0f | ||
|
|
05203c989e | ||
|
|
0bc2cc706d | ||
|
|
e02523bfe9 | ||
|
|
c4899a4b0e | ||
|
|
adf58defef | ||
|
|
d69935beb5 | ||
|
|
e61c8602ab | ||
|
|
8a3c59ee3e | ||
|
|
d64fde385b | ||
|
|
479499c438 | ||
|
|
9ece78fa76 | ||
|
|
baab941181 | ||
|
|
51e04f82d9 | ||
|
|
92e58fd3a2 | ||
|
|
af0b5ce5b0 | ||
|
|
ae22fef9e8 | ||
|
|
64313a2619 | ||
|
|
bb3d218e5c | ||
|
|
6011cb57e6 | ||
|
|
703b6241a5 | ||
|
|
4483fca7f0 | ||
|
|
4e4235df66 | ||
|
|
08f72f283b | ||
|
|
5ae561681a | ||
|
|
c5b6222c41 | ||
|
|
b3d46603c9 | ||
|
|
457aa1ed42 | ||
|
|
15c5353e70 | ||
|
|
b9373e8610 | ||
|
|
97fd260333 | ||
|
|
3839dd6446 | ||
|
|
32c1a8cdcf | ||
|
|
3c2507a4a4 | ||
|
|
c64745d883 | ||
|
|
e595a178cd | ||
|
|
4d04f61356 | ||
|
|
0cf8b9cb14 | ||
|
|
ca987ea01a | ||
|
|
ce94ca03a9 | ||
|
|
f4cec63a20 | ||
|
|
ff7498fff5 | ||
|
|
ffe5365f7b | ||
|
|
baca28f67d | ||
|
|
bf153b9b5d | ||
|
|
27de0caae2 | ||
|
|
d6b536145f | ||
|
|
d90e2f46bb | ||
|
|
b8b22aaf0f | ||
|
|
3877bf8fe9 | ||
|
|
c9985050e7 | ||
|
|
66e9c8210f | ||
|
|
354ce2c927 | ||
|
|
4410e0914b | ||
|
|
c0b3cbb1e6 | ||
|
|
ce2a10cc05 | ||
|
|
bd7bf5aaa7 | ||
|
|
3296ded4d4 | ||
|
|
62b0481fd0 | ||
|
|
142395f6f4 | ||
|
|
022e74a67f | ||
|
|
8c1087e17e | ||
|
|
1ad71b45ae | ||
|
|
97d1d37c2c | ||
|
|
4b627aa43b | ||
|
|
e4318a3b41 | ||
|
|
4ffaaa32df | ||
|
|
11f29a88aa | ||
|
|
1166b749e2 | ||
|
|
686bd471c8 | ||
|
|
0d8c6f8419 | ||
|
|
da2d719bcb | ||
|
|
34f8eed802 | ||
|
|
000ba4beb4 | ||
|
|
ec7ad6c9dc | ||
|
|
81ede0378d | ||
|
|
5109e37581 | ||
|
|
0fd6ed57b1 | ||
|
|
6301edd296 | ||
|
|
a26545ecee | ||
|
|
bad24cbbee | ||
|
|
549b78cae9 | ||
|
|
9ce8df05f1 | ||
|
|
d92e481ffb | ||
|
|
a66bf67cc6 | ||
|
|
9d82060e81 | ||
|
|
9d7fd99833 | ||
|
|
87f59b4641 | ||
|
|
f29a788455 | ||
|
|
b546f639db | ||
|
|
57a4ff70ec | ||
|
|
2afd7d3070 | ||
|
|
aa0f619657 | ||
|
|
64c3e96567 | ||
|
|
a90fe0c672 | ||
|
|
fcb3d10186 | ||
|
|
f6e05ce542 | ||
|
|
19e02c4c29 | ||
|
|
c7c88ce9f4 | ||
|
|
5de0f00718 | ||
|
|
d75b12344f | ||
|
|
ca48c0c09e | ||
|
|
ae1d4fc7bd | ||
|
|
06e11a70f8 | ||
|
|
38cf3fc198 | ||
|
|
5bb6206303 | ||
|
|
1ed86e03e3 | ||
|
|
85301241cc | ||
|
|
5f6c014b7e | ||
|
|
03f848db04 | ||
|
|
68ca3803d4 | ||
|
|
6b81cfb922 | ||
|
|
c3e0c2ee7c | ||
|
|
6247cf2916 | ||
|
|
b845518e41 | ||
|
|
d8eaf32a0e | ||
|
|
746aa01593 | ||
|
|
7b44cca756 | ||
|
|
44a5e23be2 | ||
|
|
3277d1b9df | ||
|
|
9867b4e5ba | ||
|
|
9fd9c035ed | ||
|
|
f1264e723f | ||
|
|
af25ffd493 | ||
|
|
d7a12c999e | ||
|
|
11ea26a6e1 | ||
|
|
74d5a3592a | ||
|
|
0e80f21b44 | ||
|
|
c0500e56fa | ||
|
|
7c23fc8b23 | ||
|
|
9dd8eea5c7 | ||
|
|
3ba07102b8 | ||
|
|
343c3d4bc2 | ||
|
|
1e150e287b | ||
|
|
7b437779eb | ||
|
|
db7debcd8e | ||
|
|
c860a1481f | ||
|
|
676edae685 | ||
|
|
2341832053 | ||
|
|
ec59b6766c | ||
|
|
d54a57194e | ||
|
|
bf007a6523 | ||
|
|
a85c840fe2 | ||
|
|
969848f498 | ||
|
|
67fc3b346d | ||
|
|
afc2b06f6b | ||
|
|
0ac7fe7c47 | ||
|
|
1a41cd5a47 | ||
|
|
56c6cef6b8 | ||
|
|
5da8a878f5 | ||
|
|
cfbdf03d96 | ||
|
|
e95b3b8b7c | ||
|
|
f85017f43f | ||
|
|
e7a388f16b | ||
|
|
8bea7d3c6d | ||
|
|
e0eeeb6eb2 | ||
|
|
b4a136bb54 | ||
|
|
518bad5042 | ||
|
|
3dbbfeee8a | ||
|
|
0cbf5da7c4 | ||
|
|
fbd5eb87f5 | ||
|
|
4a878ed801 | ||
|
|
cde66f9394 | ||
|
|
dfaa25f17b | ||
|
|
90c2737e10 | ||
|
|
6dd2f0665a | ||
|
|
aa4ea06aff | ||
|
|
0d5626a150 | ||
|
|
30c4848db5 | ||
|
|
f2f39087b3 | ||
|
|
d94db12e0e | ||
|
|
9f097a350b | ||
|
|
ea1ed70e69 | ||
|
|
fda0a76218 | ||
|
|
4bd9cbb44a | ||
|
|
4c57b6e129 | ||
|
|
57571c6bad | ||
|
|
47848a5fa2 | ||
|
|
794ccfca76 | ||
|
|
8670db4227 | ||
|
|
88f7bdc881 | ||
|
|
2e56c74ac4 | ||
|
|
47f94f39e9 | ||
|
|
073312a234 | ||
|
|
1c41b2ae59 | ||
|
|
2c741f5c44 | ||
|
|
a51e9c0ca8 | ||
|
|
6841eb6b2e | ||
|
|
4c0ba7fcdb | ||
|
|
0a163fd87b | ||
|
|
cb173476f2 | ||
|
|
b5a03ea640 | ||
|
|
d467db7714 | ||
|
|
8d40cfcc94 | ||
|
|
792f9370b2 | ||
|
|
e8e08235c2 | ||
|
|
ad0a96f290 | ||
|
|
a767a5fbeb | ||
|
|
499c8989f8 | ||
|
|
8e31cfaeda | ||
|
|
355a5f9bf0 | ||
|
|
c6dfcabf23 | ||
|
|
ba0e41f1c8 | ||
|
|
8a5faa6b06 | ||
|
|
400295659e | ||
|
|
2c42390128 | ||
|
|
5decbf0144 | ||
|
|
83520f5802 | ||
|
|
e3e1efbdd1 | ||
|
|
dc896faba3 | ||
|
|
e20a4fabb1 | ||
|
|
898bfc6eba | ||
|
|
92ce0a5706 | ||
|
|
61d290a4c9 | ||
|
|
0dc84f3d18 | ||
|
|
ff9c25172f | ||
|
|
61aabaecbd | ||
|
|
3849b3251e | ||
|
|
366c584259 | ||
|
|
00a47d069d | ||
|
|
770d5ba0e5 | ||
|
|
80414f110a | ||
|
|
18e2d01d94 | ||
|
|
7113945a81 | ||
|
|
d12bb7d151 | ||
|
|
8f71864224 | ||
|
|
a09f650d00 | ||
|
|
fe7a374952 | ||
|
|
79ed86b0d5 | ||
|
|
140f54aebf | ||
|
|
2a6a6b8d87 | ||
|
|
3827307a32 | ||
|
|
0a26842590 | ||
|
|
728cd13c19 | ||
|
|
9248dd7e6d | ||
|
|
9a954574e9 | ||
|
|
32dbc9b340 | ||
|
|
5abefe75c5 | ||
|
|
1da76b134c | ||
|
|
34fdf58285 | ||
|
|
9bb7714bbd | ||
|
|
0f75770d17 | ||
|
|
55c8fb3f22 | ||
|
|
7caaa66363 | ||
|
|
3a05449f4a | ||
|
|
9922678abb | ||
|
|
25ca4e67c7 | ||
|
|
3bf3a5b225 | ||
|
|
f03eaab4cf | ||
|
|
430dc185fb | ||
|
|
3a588465d2 | ||
|
|
1584bca762 | ||
|
|
12017b11c3 | ||
|
|
a69abf866a | ||
|
|
4edcf7b3ae | ||
|
|
3dcdeb197f | ||
|
|
55927d15ae | ||
|
|
3c5719f774 | ||
|
|
bdc30e16e3 | ||
|
|
26ae9fdcd0 | ||
|
|
91dbab2309 | ||
|
|
802ce27bba | ||
|
|
09d88b1d19 | ||
|
|
124f9f24fb | ||
|
|
03cf055f52 | ||
|
|
912187a9b2 | ||
|
|
a302d51d70 | ||
|
|
632a614894 | ||
|
|
a5a7d75b8d | ||
|
|
24915b42b1 | ||
|
|
bbb084cf73 | ||
|
|
32f2587a50 | ||
|
|
610088c8b5 | ||
|
|
da5f903c74 | ||
|
|
ce3bf468d4 | ||
|
|
1158709791 | ||
|
|
a36ca02589 | ||
|
|
23402a272c | ||
|
|
abfca933cd | ||
|
|
45ad8a2011 | ||
|
|
64f55c9da0 | ||
|
|
d1b62cbb31 | ||
|
|
f6a62bbeec | ||
|
|
3cbf80620b | ||
|
|
34177b4cf7 | ||
|
|
aeac03327f | ||
|
|
06e4df257c | ||
|
|
f9646ef13d | ||
|
|
bd9b4f5664 | ||
|
|
f29fcba543 | ||
|
|
8a35f6f949 | ||
|
|
3744b6133f | ||
|
|
744f9e335a | ||
|
|
88919d873a | ||
|
|
79c96602fa | ||
|
|
abf4741a7f | ||
|
|
442c4267fd | ||
|
|
1613431e95 | ||
|
|
f8a889a8ed | ||
|
|
5929359a1b | ||
|
|
7e59078be1 | ||
|
|
f2feb8fa6f | ||
|
|
c43862329a | ||
|
|
1ecdac5096 | ||
|
|
c9f983ca84 | ||
|
|
f80c9585fa | ||
|
|
62df55f029 | ||
|
|
39c16784eb | ||
|
|
efc6b72f3e | ||
|
|
a8ad1c098d | ||
|
|
9a510c1b8b | ||
|
|
40f3d482fa | ||
|
|
e2c4319698 | ||
|
|
c8d414cbca | ||
|
|
76a7320831 | ||
|
|
fa74d3ded9 | ||
|
|
07e43b8af2 | ||
|
|
6b6375de69 | ||
|
|
bc68cca8cb | ||
|
|
5637c6da45 | ||
|
|
3f2ba808d5 | ||
|
|
4707619b9f | ||
|
|
e7dfde895f | ||
|
|
a51335db29 | ||
|
|
84a4a1e551 | ||
|
|
75a57bb369 | ||
|
|
8be288e838 | ||
|
|
8278e2d0ab | ||
|
|
fafc78e2c0 | ||
|
|
1e73ace403 | ||
|
|
c9e1657855 | ||
|
|
4b70a2e717 | ||
|
|
c5fd01f5b3 | ||
|
|
430bd7d94a | ||
|
|
b0278c0fc1 | ||
|
|
82dbed4a08 | ||
|
|
17ff5e9985 | ||
|
|
770c4c09ac | ||
|
|
4c842b52e5 | ||
|
|
073925719e | ||
|
|
39c2197b40 | ||
|
|
e19032848e | ||
|
|
16fa2366f0 | ||
|
|
8d28ed98c1 | ||
|
|
5155b2f748 | ||
|
|
7ab05ff903 | ||
|
|
fb966ac1fc | ||
|
|
52ae155b73 | ||
|
|
5282aa8b4a | ||
|
|
97ea5abc17 | ||
|
|
74f1f9ca39 | ||
|
|
2272157b60 | ||
|
|
a78eec66bd | ||
|
|
4bc33951e4 | ||
|
|
b5a7677db0 | ||
|
|
e21956ee13 | ||
|
|
0421684d8b | ||
|
|
1e50046c0f | ||
|
|
df79648fbc | ||
|
|
4e7b8a3422 | ||
|
|
5aa163f919 | ||
|
|
3ca2d4e372 | ||
|
|
0f49cff675 | ||
|
|
b58d1396bc | ||
|
|
d91e108603 | ||
|
|
62755e80d0 | ||
|
|
d0e1638960 | ||
|
|
38779270c6 | ||
|
|
3267ad4fc6 | ||
|
|
5aafd36fb6 | ||
|
|
2cd03623da | ||
|
|
0537795ef0 | ||
|
|
8f76ec6a64 | ||
|
|
95dde6101d | ||
|
|
e06d990a30 | ||
|
|
d4aff5cbc4 | ||
|
|
08b8d07c83 | ||
|
|
5b30275470 | ||
|
|
3104cbd6f2 | ||
|
|
daf794fc1c | ||
|
|
07730aed97 | ||
|
|
0445ac0359 | ||
|
|
59ac2eec33 | ||
|
|
c595e82820 | ||
|
|
2c5ee6c64e | ||
|
|
c194237425 | ||
|
|
a963a44674 | ||
|
|
8bcb4ce8f6 | ||
|
|
36ed8fca55 | ||
|
|
c5681f1aec | ||
|
|
c12f3b6cbd | ||
|
|
5cb9a11b21 | ||
|
|
bba8005dd1 | ||
|
|
6c3504a1db | ||
|
|
64d92c8e5b | ||
|
|
064f44e47c | ||
|
|
83c647706a | ||
|
|
8732a73018 | ||
|
|
70873b0170 | ||
|
|
6fbeb3063b | ||
|
|
2462c0c8cc | ||
|
|
546eb7ef1f | ||
|
|
58221d8a4b | ||
|
|
32d320a352 | ||
|
|
6dbfb7269e | ||
|
|
b5dea96fc0 | ||
|
|
c057923404 | ||
|
|
69017417e7 | ||
|
|
dec36d4189 | ||
|
|
bd183a9f62 | ||
|
|
fcaee23975 | ||
|
|
bd794e821a | ||
|
|
4a91234729 | ||
|
|
90aac42048 | ||
|
|
4aa1ba02ad | ||
|
|
d22a83b867 | ||
|
|
7fbc3013d9 | ||
|
|
d56c472911 | ||
|
|
f52879d45b | ||
|
|
320f332da6 | ||
|
|
1881fb15d2 | ||
|
|
c00ea27aae | ||
|
|
1db31d20d9 | ||
|
|
08a1f11408 | ||
|
|
cc71c65b72 | ||
|
|
b6624c1e4f | ||
|
|
bff0c7465d | ||
|
|
2d575b8167 | ||
|
|
6c6600d02c | ||
|
|
6af7d57ad3 | ||
|
|
f27d92cd79 | ||
|
|
4a686a6862 | ||
|
|
a146adf69a | ||
|
|
4adbafa9e0 | ||
|
|
f17dc42601 | ||
|
|
05d0749c77 | ||
|
|
f8bcf885a8 | ||
|
|
da6715d958 | ||
|
|
5c3d5dab77 | ||
|
|
df96aa2481 | ||
|
|
fcbb52f26b | ||
|
|
81461f7c25 | ||
|
|
9f0c63eff1 | ||
|
|
5d3906df42 | ||
|
|
9b6e1a2613 | ||
|
|
b6381be715 | ||
|
|
ff8af9bd73 | ||
|
|
5cd825e052 | ||
|
|
fef587a6e5 | ||
|
|
e018ed21c1 | ||
|
|
7a55055a90 | ||
|
|
981838b48f | ||
|
|
1f350ce7ba | ||
|
|
3290e68c63 | ||
|
|
4f79efb80c | ||
|
|
81b3caef4a | ||
|
|
c2739dee85 | ||
|
|
f36498c5c2 | ||
|
|
74984c3791 | ||
|
|
2501a21cf4 | ||
|
|
88f01a2f16 | ||
|
|
4063a8ddcf | ||
|
|
9d8ec47bb4 | ||
|
|
a20cd212b2 | ||
|
|
01d3e8e9f9 | ||
|
|
8dd6766d93 | ||
|
|
d798f7bf52 | ||
|
|
5690d69b34 | ||
|
|
477c62d18a | ||
|
|
b99ac0dce8 | ||
|
|
90326e46c1 | ||
|
|
0d457b99cc | ||
|
|
a3d15f71a8 | ||
|
|
57d621b407 | ||
|
|
8997b835f7 | ||
|
|
0680be9d77 | ||
|
|
a6d49f5411 | ||
|
|
c39908fda0 | ||
|
|
e372bde373 | ||
|
|
432b427a7c | ||
|
|
75443257ec | ||
|
|
5f7e3c1fa3 | ||
|
|
b88560f9f9 | ||
|
|
eea67e74b4 | ||
|
|
d592ad923b | ||
|
|
e3790b77fa | ||
|
|
508c45601f | ||
|
|
d350773571 | ||
|
|
78a2e68928 | ||
|
|
5c507b92f7 | ||
|
|
ad748cd240 | ||
|
|
87ff70d480 | ||
|
|
5afc421dc2 | ||
|
|
a941595b46 | ||
|
|
c2757ea4b5 | ||
|
|
6e13c8b0ef | ||
|
|
08d8cdbdac | ||
|
|
2b9fcd7878 | ||
|
|
e6ebf905a6 | ||
|
|
1504884429 | ||
|
|
aea71b1c8a | ||
|
|
59735f1b53 | ||
|
|
2c7ee93a92 | ||
|
|
e883cb1b22 | ||
|
|
d83f4f4a34 | ||
|
|
7d8b97e67e | ||
|
|
ae148bafeb | ||
|
|
cb49613ff7 | ||
|
|
3f16878da1 | ||
|
|
e88f357d47 | ||
|
|
4cc790ed98 | ||
|
|
24e55b15f1 | ||
|
|
151daf1226 | ||
|
|
aaa1585bbb | ||
|
|
2824bd33eb | ||
|
|
7ce1b3c31a | ||
|
|
5b8a93bfd9 | ||
|
|
777c059f62 | ||
|
|
f4332f12b3 | ||
|
|
bb8f9143da | ||
|
|
23efc87258 | ||
|
|
b2d48c1c59 | ||
|
|
7c08f8e7e0 | ||
|
|
90a4e4ffa0 | ||
|
|
2a4759c321 | ||
|
|
b4bd3bca72 | ||
|
|
960eaa907a | ||
|
|
8c63eb4839 | ||
|
|
7e7ec4f483 | ||
|
|
fac1037862 | ||
|
|
d6d939f629 | ||
|
|
2f4a9c6070 | ||
|
|
ef58d661fc | ||
|
|
ea10e14735 | ||
|
|
bf0ceca34d | ||
|
|
bccf0092b3 | ||
|
|
c2b424f347 | ||
|
|
06b7c6648d | ||
|
|
687ec11956 | ||
|
|
c429f8ff3e | ||
|
|
c2064256ff | ||
|
|
efab4d940c | ||
|
|
235eac4569 | ||
|
|
843c02d58c | ||
|
|
80b32aae29 | ||
|
|
505c7c53b4 | ||
|
|
8bd8fb70a3 | ||
|
|
859c2da0f0 | ||
|
|
8c881a6058 | ||
|
|
74b083b503 | ||
|
|
e39be278ea | ||
|
|
a902a33085 | ||
|
|
9a004c28f9 | ||
|
|
61257cddff | ||
|
|
da00862941 | ||
|
|
7d33b699d4 | ||
|
|
19d32f8477 | ||
|
|
57d4e036fd | ||
|
|
75cbf896e7 | ||
|
|
f24ab12576 | ||
|
|
698955e5d2 | ||
|
|
7aa1e42383 | ||
|
|
364d381376 | ||
|
|
84118a8a7c | ||
|
|
0c57f8c9a6 | ||
|
|
72a4e0b658 | ||
|
|
de8448634e | ||
|
|
e4c64b8bb9 | ||
|
|
6376435df2 | ||
|
|
90ea267a0e | ||
|
|
5c2329ab67 | ||
|
|
03ef9582f2 | ||
|
|
1a3b717cf1 | ||
|
|
121efe7bc7 | ||
|
|
24f33783cd | ||
|
|
774b88db4e | ||
|
|
9767ee9343 | ||
|
|
3365d59fba | ||
|
|
10d5623c55 | ||
|
|
6637c9e938 | ||
|
|
f1cb4b3991 | ||
|
|
1a06a41283 | ||
|
|
3a3d836a9b | ||
|
|
6d188d02f9 | ||
|
|
92708eeb3a | ||
|
|
3af3013a93 | ||
|
|
7f9cdd5be2 | ||
|
|
1d0eaa8789 | ||
|
|
9ebe44feaa | ||
|
|
03223ec459 | ||
|
|
026b038b00 | ||
|
|
b90642aa8b | ||
|
|
49887b88ad | ||
|
|
7c0ca9e39b | ||
|
|
d6213f553d | ||
|
|
6c698403f8 | ||
|
|
8a842cc7f6 | ||
|
|
0bd04a4425 | ||
|
|
ad6bddc33a | ||
|
|
71f1563880 | ||
|
|
ec378c8e13 | ||
|
|
ab296ccf5e | ||
|
|
3be0cbdfe9 | ||
|
|
0a2c17fec2 | ||
|
|
5242f11af5 | ||
|
|
2146247e61 | ||
|
|
5c8f4d8e17 | ||
|
|
919549f877 | ||
|
|
b1207f2d9f | ||
|
|
0b2b752f06 | ||
|
|
846e95b0c2 | ||
|
|
43feee4576 | ||
|
|
57c33df481 | ||
|
|
9fbdce5b69 | ||
|
|
064a3d7b8d | ||
|
|
af0dc61e51 | ||
|
|
09502364c7 | ||
|
|
e9e2894e20 | ||
|
|
a947c9456f | ||
|
|
6ba4dce473 | ||
|
|
675fa1f7dc | ||
|
|
deab4f3c11 | ||
|
|
979b93e1cb | ||
|
|
34c51476f7 | ||
|
|
4b9bead9cf | ||
|
|
c15331980b | ||
|
|
b849e63db5 | ||
|
|
e7f1c5fad8 | ||
|
|
22a91455a7 | ||
|
|
e9cb5e7c37 | ||
|
|
ed03fc0d3c | ||
|
|
339276e8cb | ||
|
|
83b9eb3ebe | ||
|
|
35b4686b42 | ||
|
|
4715bc502f | ||
|
|
f1d1e0a2a8 | ||
|
|
7303a25190 | ||
|
|
65c3069d44 | ||
|
|
7587ff082d | ||
|
|
c998379da8 | ||
|
|
fe807595fb | ||
|
|
575861c11c | ||
|
|
ef44a199ef | ||
|
|
7b5a7cc12b | ||
|
|
be29e89175 | ||
|
|
b4f9d3e925 | ||
|
|
9dcb2847e7 | ||
|
|
dc6aeb232f | ||
|
|
207cd584ce | ||
|
|
44f190efc2 | ||
|
|
3207118bd9 | ||
|
|
07a39f1b01 | ||
|
|
15987d40ad | ||
|
|
000d01d53d | ||
|
|
4ce97d2926 | ||
|
|
85e9c335fa | ||
|
|
2e2513d785 | ||
|
|
feb70e9fb7 | ||
|
|
bbeda9892e | ||
|
|
caf2edb9a5 | ||
|
|
5307930e35 | ||
|
|
98908b39d6 | ||
|
|
82604383a0 | ||
|
|
0c6ab67de5 | ||
|
|
39f5576871 | ||
|
|
9c99ae0dc0 | ||
|
|
956febe1e4 | ||
|
|
0c428ab47a | ||
|
|
cb77efa483 | ||
|
|
65fbd34d09 | ||
|
|
5eb14cf3dc | ||
|
|
327df68aa4 | ||
|
|
527d23772d | ||
|
|
e6a04c53a7 | ||
|
|
2d3e3dd5dd | ||
|
|
6e8d0eb1bd | ||
|
|
fd812834aa | ||
|
|
4395b2c6a6 | ||
|
|
289fcf2162 | ||
|
|
e37f31996f | ||
|
|
2f3db7a43f | ||
|
|
6a53ad0b08 | ||
|
|
ca505ae9eb | ||
|
|
25b9ccb847 | ||
|
|
2df12b3089 | ||
|
|
d6d70900d2 | ||
|
|
5af3405efa | ||
|
|
b235220a3a | ||
|
|
5f8e3925a5 | ||
|
|
6494789a13 | ||
|
|
65d09aa3fe | ||
|
|
9acae1ce64 | ||
|
|
89fe3adfd8 | ||
|
|
86736acf25 | ||
|
|
62606fa1d2 | ||
|
|
7a121bdd5e | ||
|
|
c1569bd6ff | ||
|
|
41e48d7c9a | ||
|
|
f4829a2e52 | ||
|
|
2121c073d0 | ||
|
|
15f59e043e | ||
|
|
48ec4cc375 | ||
|
|
54a0036cc9 | ||
|
|
d82bfbd05f | ||
|
|
f5f3b9bf8f | ||
|
|
606f020cab | ||
|
|
1357acbd58 | ||
|
|
c0b43ebd1e | ||
|
|
745f27fd13 | ||
|
|
a626c8310c | ||
|
|
996cf38ec4 | ||
|
|
71af7d453e | ||
|
|
41e6fb2189 | ||
|
|
7fe05243a8 | ||
|
|
4c7654381e | ||
|
|
536e0262f6 | ||
|
|
e1cdfb9049 | ||
|
|
ff2017586c | ||
|
|
b3f71e5f33 | ||
|
|
2109efc811 | ||
|
|
4116e057fa | ||
|
|
3b9c42dfc2 | ||
|
|
6b2e484cb4 | ||
|
|
ffb9e671f1 | ||
|
|
606cb45c80 | ||
|
|
a467c8e8e7 | ||
|
|
5d6b628f99 | ||
|
|
0131347f7a | ||
|
|
622ab3063d | ||
|
|
9d839d74a3 | ||
|
|
ceb737b44b | ||
|
|
e2ada7c46a | ||
|
|
597b658b08 | ||
|
|
142de313f0 | ||
|
|
4bee08e9b8 | ||
|
|
6a0e177182 | ||
|
|
951c98f603 | ||
|
|
564db75da6 | ||
|
|
5a3d645542 | ||
|
|
8e79aefbc7 | ||
|
|
3ba91eaefc | ||
|
|
82110f17a1 | ||
|
|
081c6f8836 | ||
|
|
12e95bdb3b | ||
|
|
3b95e40aa3 | ||
|
|
a52a757f47 | ||
|
|
ebc4452e61 | ||
|
|
641994a5c3 | ||
|
|
cd7ba2d878 | ||
|
|
4497bf0aef | ||
|
|
6cddc43b33 | ||
|
|
9e191c7a5d | ||
|
|
0e8a3a9d34 | ||
|
|
8497d0f535 | ||
|
|
796af5925a | ||
|
|
a223cba972 | ||
|
|
01ddc283b4 | ||
|
|
a3b9fbf5b9 | ||
|
|
2a4e93c6c3 | ||
|
|
0f61c7dc98 | ||
|
|
5e27fe3ecc | ||
|
|
b26b205635 | ||
|
|
9326e2ddd1 | ||
|
|
644b99e5de | ||
|
|
3ac8e3cc34 | ||
|
|
c8edfd93e3 | ||
|
|
6208bea136 | ||
|
|
cae533c6e9 | ||
|
|
a6aff4c2e5 | ||
|
|
2368157d8a | ||
|
|
f8104a9501 | ||
|
|
20faf7c5d3 | ||
|
|
50b8b2f84f | ||
|
|
a3259f778a | ||
|
|
ea4a24eea9 | ||
|
|
16a966a9e8 | ||
|
|
50475e4f16 | ||
|
|
bda6f8d2d9 | ||
|
|
46bf026a8d | ||
|
|
3a3cddd8be | ||
|
|
e6c2b75434 | ||
|
|
c6f8b55725 | ||
|
|
58d5eecad4 | ||
|
|
52db57481b | ||
|
|
7e817863f4 | ||
|
|
2bbb2c8537 | ||
|
|
0cac9b692b | ||
|
|
733e6a8ab8 | ||
|
|
f0958e0ead | ||
|
|
2a318c0266 | ||
|
|
ed4d9eb150 | ||
|
|
cde5f618e9 | ||
|
|
82d70145d8 | ||
|
|
e553d2562a | ||
|
|
01ff4cec25 | ||
|
|
9dff05f6e5 | ||
|
|
ee909f858f | ||
|
|
cd3a883c3b | ||
|
|
2acb4f9742 | ||
|
|
f5d8cf23e9 | ||
|
|
56425e7e94 | ||
|
|
ee95d7f4c2 | ||
|
|
c916a82f3e | ||
|
|
074249a74e | ||
|
|
5aec9a9d2b | ||
|
|
1920c8b23d | ||
|
|
50d47bbc4b | ||
|
|
46aad61b1b | ||
|
|
a7550f0a67 | ||
|
|
084f614519 | ||
|
|
eb31413345 | ||
|
|
723fc352a8 | ||
|
|
6e9e7c46e9 | ||
|
|
82cc93c772 | ||
|
|
e77815b3fd | ||
|
|
8f4cd91157 | ||
|
|
740caaa7c9 | ||
|
|
5dcb915da6 | ||
|
|
6f9e2739d1 | ||
|
|
e74d372a6f | ||
|
|
2245a6d952 | ||
|
|
913d25a7d3 | ||
|
|
36e27f378f | ||
|
|
faefff91f5 | ||
|
|
e80935e9d2 | ||
|
|
4fa0673b8e | ||
|
|
2623963eb8 | ||
|
|
09bb78b884 | ||
|
|
1e5497b6cc | ||
|
|
d7c37109ef | ||
|
|
ee34637cd6 | ||
|
|
74ba3a3b69 | ||
|
|
e233f51641 | ||
|
|
3b0cc96335 | ||
|
|
ab8906b51a | ||
|
|
f720ef1d33 | ||
|
|
805167b703 | ||
|
|
11f033d026 | ||
|
|
353189d018 | ||
|
|
060c474268 | ||
|
|
eb493e1001 | ||
|
|
f73101a69e | ||
|
|
96735101ab | ||
|
|
127f86bcd9 | ||
|
|
d3f45f2de2 | ||
|
|
d7eb691168 | ||
|
|
bb71636ed3 | ||
|
|
f98a890728 | ||
|
|
f2ac00b6da | ||
|
|
3ce0ca1adf | ||
|
|
68d1960014 | ||
|
|
28407cbec3 | ||
|
|
4bda0631da | ||
|
|
da05bf3d37 | ||
|
|
bd3719d833 | ||
|
|
cb02462cc2 | ||
|
|
c81e4a87db | ||
|
|
68bc23ecfb | ||
|
|
6baa451b13 | ||
|
|
03d085aade | ||
|
|
38d07fe2df | ||
|
|
b86c012bcb | ||
|
|
536dc57357 | ||
|
|
d5d409314c | ||
|
|
1fe7f7fb16 | ||
|
|
51f8f7f0a5 | ||
|
|
3633056517 | ||
|
|
6d0d3be00e | ||
|
|
6644427470 | ||
|
|
cd2de7f75c | ||
|
|
675eb41f1b | ||
|
|
521cddeed0 | ||
|
|
0b06dc5816 | ||
|
|
f356fbfb72 | ||
|
|
a6dcd6bbd3 | ||
|
|
6dae31fe00 | ||
|
|
95f1ba152e | ||
|
|
a2481dd06b | ||
|
|
2026b7ef7d | ||
|
|
4b13ed3ca3 | ||
|
|
21bd675681 | ||
|
|
155f49707f | ||
|
|
9198a86d11 | ||
|
|
a17a29cc7c | ||
|
|
4e330845f7 | ||
|
|
c3c73d96f6 | ||
|
|
8048e631ae | ||
|
|
da0ba5bd3f | ||
|
|
f79b496852 | ||
|
|
ddd7b50da5 | ||
|
|
6346a55e5b | ||
|
|
b1df66c011 | ||
|
|
251c38ede0 | ||
|
|
29e221da19 | ||
|
|
f173d5ed3c | ||
|
|
db80684e32 | ||
|
|
095ac63cee | ||
|
|
84d4d21d5e | ||
|
|
9378dc577f | ||
|
|
d0f113e30e | ||
|
|
673fbc1a5a | ||
|
|
157c16b32c | ||
|
|
3bc416bfa0 | ||
|
|
72d965898f | ||
|
|
e2b3f88d28 | ||
|
|
9eba8f09fc | ||
|
|
cac973a3af | ||
|
|
3d403ca096 | ||
|
|
8b3a846d29 | ||
|
|
b179ca0dc9 | ||
|
|
d043e1c87e | ||
|
|
6989340ef1 | ||
|
|
bbce3ba5ae | ||
|
|
8efc7a96af | ||
|
|
c37c780eb2 | ||
|
|
795d5bcef3 | ||
|
|
c11318f163 | ||
|
|
10b98fa78f | ||
|
|
fdbd28e84d | ||
|
|
38d13e54b6 | ||
|
|
cee4ddf86d | ||
|
|
4460b663c4 | ||
|
|
a097b4f2fd | ||
|
|
c560a3b958 | ||
|
|
f701fd56b5 | ||
|
|
c9244e2efd | ||
|
|
e056d71632 | ||
|
|
d45ee763dd | ||
|
|
1afcdc503e | ||
|
|
ed9c2bcf3a | ||
|
|
7e576900ea | ||
|
|
98d2883d26 | ||
|
|
bc710505f5 | ||
|
|
ba81fb4f85 | ||
|
|
067bca4af1 | ||
|
|
900713ca3d | ||
|
|
7c7d6d99c2 | ||
|
|
4ca4dc9b96 | ||
|
|
e3ce217a70 | ||
|
|
b9a32b1640 | ||
|
|
3962d45c8f | ||
|
|
875d6e7b80 | ||
|
|
c34f113de3 | ||
|
|
6089afc23e | ||
|
|
bb3822718d | ||
|
|
a9af38eb38 | ||
|
|
574a167b07 | ||
|
|
c8d9bf058f | ||
|
|
842db00f21 | ||
|
|
33cf77ba27 | ||
|
|
020fe12043 | ||
|
|
67037e82a6 | ||
|
|
d04fab22cc | ||
|
|
abced8efdd | ||
|
|
c6945cf380 | ||
|
|
e40d1a7f89 | ||
|
|
ae81dda885 | ||
|
|
81a2e142b0 | ||
|
|
a3ba8a1dab | ||
|
|
e06b2dcbda | ||
|
|
9086d09201 | ||
|
|
26870df47d | ||
|
|
b119a39c71 | ||
|
|
7a47a8f6b7 | ||
|
|
e80edc1e6a | ||
|
|
a869c48a68 | ||
|
|
3e44617612 | ||
|
|
c80da8aec5 | ||
|
|
aa92444824 | ||
|
|
fc42fef72e | ||
|
|
799c99e0ab | ||
|
|
edcf0be6dc | ||
|
|
8cdfe8766b | ||
|
|
e356fdeff0 | ||
|
|
23a120f873 | ||
|
|
2b6381cdd5 | ||
|
|
0069db761b | ||
|
|
1691aeebb5 | ||
|
|
ee110d7037 | ||
|
|
45016c578f | ||
|
|
ec1ed2d8cc | ||
|
|
79ce021fe4 | ||
|
|
9512f781eb | ||
|
|
247c3de3bb | ||
|
|
9a151c9072 | ||
|
|
5cbffde74b | ||
|
|
5cc45eca52 | ||
|
|
bc57486911 | ||
|
|
7986a5d531 | ||
|
|
7866d78c85 | ||
|
|
b57693a125 | ||
|
|
e0383fcaf5 | ||
|
|
be7cf6219d | ||
|
|
eb9f8445a4 | ||
|
|
c571ecd56a | ||
|
|
ae42bc0b25 | ||
|
|
a065a59b56 | ||
|
|
9a0489e007 | ||
|
|
d63b32cd01 | ||
|
|
419ff8eff3 | ||
|
|
444b51c40b | ||
|
|
08db096cdf | ||
|
|
13747a633b | ||
|
|
eb6b4b3640 | ||
|
|
93637dab4a | ||
|
|
b537539156 | ||
|
|
29db2465d9 | ||
|
|
e0d19e471d | ||
|
|
f02de5c042 | ||
|
|
46bccf3b24 | ||
|
|
fe6cf88a7e | ||
|
|
7fedac7aba | ||
|
|
b386b75182 | ||
|
|
4a069f0f91 | ||
|
|
2074122fb4 | ||
|
|
327ea2ff77 | ||
|
|
f78376eec3 | ||
|
|
fffa99063e | ||
|
|
3e9af6bfae | ||
|
|
c613db6fbd | ||
|
|
379d0cafd2 | ||
|
|
7dcd7d9a0e | ||
|
|
73c05c434e | ||
|
|
6d16c4b2cd | ||
|
|
3fe9825b7b | ||
|
|
3490af955d | ||
|
|
1721eb3153 | ||
|
|
f5d3399937 | ||
|
|
b3fcf452a8 | ||
|
|
138d9c064c | ||
|
|
e8339c69b6 | ||
|
|
2a17909935 | ||
|
|
b133d25311 | ||
|
|
c531e65c44 | ||
|
|
9731d8960f | ||
|
|
59f0366933 | ||
|
|
8edf1f28fc | ||
|
|
4474b6a5eb | ||
|
|
78f2226b7a | ||
|
|
9db951c67d | ||
|
|
ac23e28fe4 | ||
|
|
e37b8470f5 | ||
|
|
eeaf41b468 | ||
|
|
2fc1fc579b | ||
|
|
1963ee205c | ||
|
|
5c4902b7dd | ||
|
|
2f8b14b535 | ||
|
|
4f5b8d5bb6 | ||
|
|
432156e747 | ||
|
|
dd94c0d9ba | ||
|
|
4a14a10666 | ||
|
|
d122733b4c | ||
|
|
a0bf49861c | ||
|
|
48dee56c7e | ||
|
|
4cb78607fd | ||
|
|
f4f0183097 | ||
|
|
e85a0073f6 | ||
|
|
741d014897 | ||
|
|
f6420ffa2f | ||
|
|
f0c914b4b0 | ||
|
|
459ab7e8af | ||
|
|
96add1f35a | ||
|
|
7b49d9d904 | ||
|
|
7b917b6c78 | ||
|
|
255dfce685 | ||
|
|
8a2f9ab297 | ||
|
|
1c1fe1af11 | ||
|
|
2cbf37b8e0 | ||
|
|
b4b5118124 | ||
|
|
85538040a8 | ||
|
|
5eb58e7bca | ||
|
|
c490881747 | ||
|
|
ba1656d3d5 | ||
|
|
eb9e92b55a | ||
|
|
b18c3f8bea | ||
|
|
2395382c95 | ||
|
|
c1b17ed0d2 | ||
|
|
1c091f78eb | ||
|
|
f3b4a57c40 | ||
|
|
de35f8f78e | ||
|
|
ecab4f1df0 | ||
|
|
3c2f341315 | ||
|
|
8adff8837c | ||
|
|
4ab3154a2d | ||
|
|
fe0aa8edad | ||
|
|
fbdf56fe49 | ||
|
|
60caaf8fac | ||
|
|
37dfde7536 | ||
|
|
d6ced47723 | ||
|
|
d0e9fde71b | ||
|
|
a5c2fdd7c0 | ||
|
|
3bea61386b | ||
|
|
a923b86f72 | ||
|
|
30ed3b5e35 | ||
|
|
11646d9f4e | ||
|
|
d99d43efba | ||
|
|
38a452e82b | ||
|
|
f6b5b72ca5 | ||
|
|
e5fd2f41be | ||
|
|
87513050b8 | ||
|
|
d3d972aab6 | ||
|
|
669c724882 | ||
|
|
166233e5af | ||
|
|
b3be33c62d | ||
|
|
7015226c68 | ||
|
|
c0aa385ae5 | ||
|
|
7b568638a2 | ||
|
|
1b77ee373a | ||
|
|
ca1f0ab450 | ||
|
|
79d0bb9f71 | ||
|
|
f445ebbaeb | ||
|
|
ba4dcf17f6 | ||
|
|
d3ee7eb17e | ||
|
|
caf56fbdac | ||
|
|
4794678485 | ||
|
|
95ceb73719 | ||
|
|
2e58403ca7 | ||
|
|
adb7452bf4 | ||
|
|
230cc7bb94 | ||
|
|
5d08ac6bb3 | ||
|
|
71c155b7ac | ||
|
|
5974427d48 | ||
|
|
c364a7df72 | ||
|
|
934179fd3e | ||
|
|
b7a0962447 | ||
|
|
e9b3efc019 | ||
|
|
543409c3c6 | ||
|
|
07b3d904c3 | ||
|
|
74d435ed79 | ||
|
|
2359c88aff | ||
|
|
c41e965145 | ||
|
|
f37d8429e2 | ||
|
|
080972a26a | ||
|
|
934409e344 | ||
|
|
796fcee1eb | ||
|
|
846f6761e7 | ||
|
|
ffffbe4c1f | ||
|
|
88938b3e18 | ||
|
|
9cd437bf1f | ||
|
|
41567202ad | ||
|
|
aa6fa26ad0 | ||
|
|
61e12c71f2 | ||
|
|
b12d5b9fb2 | ||
|
|
c6347bfdee | ||
|
|
a436416faa | ||
|
|
115bd879d2 | ||
|
|
2dd3e7c5d9 | ||
|
|
6deb7d9986 | ||
|
|
74f1c0d3fa | ||
|
|
f968500ebc | ||
|
|
c12d059ce9 | ||
|
|
4e5243aab8 | ||
|
|
90ba2fe0a3 | ||
|
|
51717a1eb4 | ||
|
|
1544843fcf | ||
|
|
f76c66a144 | ||
|
|
7a5fc52d68 | ||
|
|
6ad7e9bb7f | ||
|
|
c5dd8296ed | ||
|
|
27fdb9a885 | ||
|
|
294c3b89fb | ||
|
|
d7c4645bc9 | ||
|
|
ec3aae5600 | ||
|
|
84d3d92f53 | ||
|
|
8cc9cf179b | ||
|
|
55adcb3acb | ||
|
|
736a599bae | ||
|
|
92437ca5bd | ||
|
|
230911f770 | ||
|
|
b67d7e8fdc | ||
|
|
d6e645c0e0 | ||
|
|
1de646fcc5 | ||
|
|
038ad8883c | ||
|
|
f499dadb69 | ||
|
|
5e561cd301 | ||
|
|
135d047af5 | ||
|
|
0abc1f383c | ||
|
|
86a8700f17 | ||
|
|
fcb5abbcf1 | ||
|
|
a3765cbd73 | ||
|
|
f543509d71 | ||
|
|
37c9bd6992 | ||
|
|
72083112e5 | ||
|
|
a351afb468 | ||
|
|
b4decf5381 | ||
|
|
641bbe726c | ||
|
|
a7d889f8fc | ||
|
|
9e2dc088d0 | ||
|
|
8ac28e036d | ||
|
|
a0dbcb9a21 | ||
|
|
4478f7c98a | ||
|
|
fdfaa74e17 | ||
|
|
d74480e98b | ||
|
|
0396ffadc5 | ||
|
|
d019c182eb | ||
|
|
664419b770 | ||
|
|
9d65d9c8b4 | ||
|
|
f22948eafb | ||
|
|
4341c4047c | ||
|
|
db3509b176 | ||
|
|
44b18200f7 | ||
|
|
0f26e1d4f2 | ||
|
|
f9b6b04b3f | ||
|
|
1e66cdc33d | ||
|
|
3a73fbaad2 | ||
|
|
79c7c8b662 | ||
|
|
60d53cf343 | ||
|
|
94d4dce5ca | ||
|
|
b8f5bd0e0f | ||
|
|
22ed28096d | ||
|
|
7752d0b81c | ||
|
|
86b24d974d | ||
|
|
f06de99291 | ||
|
|
010a1068a5 | ||
|
|
3748e095c5 | ||
|
|
d1ea9720e3 | ||
|
|
518c876e82 | ||
|
|
8b3c7d2817 | ||
|
|
32cf4618d4 | ||
|
|
6fc1819038 | ||
|
|
55fb9ac560 | ||
|
|
a4c993cc00 | ||
|
|
5bfd5945a3 | ||
|
|
0da69bd223 | ||
|
|
9344d0692c | ||
|
|
eb20b9358c | ||
|
|
96526f46d8 | ||
|
|
fe6fa0e9e0 | ||
|
|
1ad6034e66 | ||
|
|
7e789e9e01 | ||
|
|
81583ad05a | ||
|
|
d6475b22ac | ||
|
|
a8ff948b81 | ||
|
|
535fe3ec85 | ||
|
|
64289be950 | ||
|
|
a14679feee | ||
|
|
d79be76936 | ||
|
|
1ec3d6da4f | ||
|
|
b67acc3885 | ||
|
|
2f17041843 | ||
|
|
11fc7f138a | ||
|
|
90d2826e21 | ||
|
|
b9e40ba294 | ||
|
|
da713a28cb | ||
|
|
b868ff00fc | ||
|
|
2450673826 | ||
|
|
71ec19b395 | ||
|
|
82b215a8e9 | ||
|
|
434ab7800d | ||
|
|
19c7676a4e | ||
|
|
739361255d | ||
|
|
0462d8a79e | ||
|
|
31482a7df3 | ||
|
|
0e89f1c4b0 | ||
|
|
da689a6ca3 | ||
|
|
2017697bfb | ||
|
|
91abf80631 | ||
|
|
050e4a73d9 | ||
|
|
00fa6e25fc | ||
|
|
1c534f1d10 | ||
|
|
a6c512ccbf | ||
|
|
4aa316ead2 | ||
|
|
0fdb62ee64 | ||
|
|
cc026da135 | ||
|
|
103390e9e1 | ||
|
|
5b34db7ce8 | ||
|
|
46dd248030 | ||
|
|
92eb2b0b36 | ||
|
|
66f77f65ae | ||
|
|
2c58544eff | ||
|
|
360b7372d8 | ||
|
|
cd91bd3705 | ||
|
|
b2fa8ede42 | ||
|
|
f5459ff752 | ||
|
|
577baa24b4 | ||
|
|
e7df1c9b4a | ||
|
|
148e1347ba | ||
|
|
63aa564086 | ||
|
|
399b5123ec | ||
|
|
92a3f1cc50 | ||
|
|
2338079041 | ||
|
|
21b180728c | ||
|
|
8dab6126d4 | ||
|
|
cc1e06c2a3 | ||
|
|
c0f2135021 | ||
|
|
b43912b7c5 | ||
|
|
b42b582e6e | ||
|
|
62dfd30f1b | ||
|
|
332d7249ac | ||
|
|
1a15aaa965 | ||
|
|
0de7a150bd | ||
|
|
d002f4cbab | ||
|
|
63a13c57f4 | ||
|
|
6ea0bf64b9 | ||
|
|
8351dbf827 | ||
|
|
23932371fb | ||
|
|
16864ed688 | ||
|
|
39571861cd | ||
|
|
693a596a7e | ||
|
|
eca77b3659 | ||
|
|
bb217ee8dc | ||
|
|
bd2c12d6bb | ||
|
|
60b37c58e6 | ||
|
|
f6f4e21c0e | ||
|
|
b0c046ad7b | ||
|
|
76fc4544af | ||
|
|
72415c8520 | ||
|
|
ef2676bde1 | ||
|
|
7524a9308e | ||
|
|
880b80d779 | ||
|
|
52045c9dff | ||
|
|
96ac827746 | ||
|
|
47aea1ad3f | ||
|
|
a41396a335 | ||
|
|
383cb07273 | ||
|
|
662a22ce33 | ||
|
|
b008ea54bd | ||
|
|
79d3151020 | ||
|
|
60aa1c35c3 | ||
|
|
5264874bd9 | ||
|
|
0dd03cf6ec | ||
|
|
4162f0353b | ||
|
|
319948e25c | ||
|
|
be4fce9c77 | ||
|
|
b151de735a | ||
|
|
67e3de0b39 | ||
|
|
2cab9da603 | ||
|
|
7e46a5df7b | ||
|
|
1b0cef1b36 | ||
|
|
d50206280c | ||
|
|
27937ad90f | ||
|
|
b02d11369d | ||
|
|
e18cd087ea | ||
|
|
de25bb0028 |
No files matched your search
@@ -0,0 +1,4 @@
|
||||
# These are supported funding model platforms
|
||||
github: [PranshulGG]
|
||||
ko_fi: pranshulgg
|
||||
liberapay: PranshulGG
|
||||
@@ -0,0 +1,51 @@
|
||||
name: Bug Report
|
||||
description: Report a bug
|
||||
labels: [ "bug" ]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please fill out the sections below to help everyone identify and fix the bug
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Describe your issue
|
||||
placeholder: When I click here this happens
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: steps
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
placeholder: |
|
||||
1. Go to page X
|
||||
2. Click here
|
||||
3. Click there
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: What was the expected result?
|
||||
placeholder: I expected this to happen
|
||||
- type: input
|
||||
id: source_used
|
||||
attributes:
|
||||
label: Which weather source are you using?
|
||||
placeholder: Example "Open Meteo"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: screenshots
|
||||
attributes:
|
||||
label: Put here any screenshots or videos (optional)
|
||||
- type: checkboxes
|
||||
id: acknowledgementsCheck
|
||||
attributes:
|
||||
label: Acknowledgements
|
||||
description: Your issue will be closed if you don’t read this carefully.
|
||||
options:
|
||||
- label: I have reviewed the existing issues to confirm that this is a unique report and not related to any currently open or closed tickets.
|
||||
required: true
|
||||
- label: I understand that this app is provided as-is, without any guarantees, and I might not receive a response to my request. Sometimes you might not get the response you want.
|
||||
required: true
|
||||
@@ -0,0 +1,51 @@
|
||||
name: Feature Request
|
||||
description: Suggest an idea to improve this project
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please provide detailed information to help us understand your idea and its potential impact.
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Problem Statement
|
||||
placeholder: Describe the problem or limitation you're facing that the new feature would solve.
|
||||
description: Clearly explain the challenge or issue you're encountering to help us understand the context.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: Proposed Solution
|
||||
placeholder: Explain how you think the feature should work and address the problem.
|
||||
description: Describe the solution in detail, including any specific behaviors or functionality it should have.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: Alternatives Considered
|
||||
placeholder: Describe any alternative solutions or features you've considered.
|
||||
description: If there are other ways to solve the issue, please share them here.
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional Context
|
||||
placeholder: Provide any extra details, links, or examples that might help clarify your request.
|
||||
description: This field is optional but highly encouraged if you have additional information.
|
||||
- type: checkboxes
|
||||
id: acknowledgementsCheck
|
||||
attributes:
|
||||
label: Acknowledgements
|
||||
description: Please confirm the following before submitting your feature request
|
||||
options:
|
||||
- label: I have searched the existing issues and discussions to ensure this feature has not already been requested.
|
||||
required: true
|
||||
- label: I understand that submitting a request does not guarantee it will be implemented.
|
||||
required: true
|
||||
- label: I have provided all necessary information to clearly explain my request.
|
||||
required: true
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for suggesting an improvement! Your feedback is valuable, and we will review it as soon as possible.
|
||||
@@ -0,0 +1,30 @@
|
||||
name: New source
|
||||
description: Suggest an new source
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please fill out the sections below
|
||||
- type: textarea
|
||||
id: api_link
|
||||
attributes:
|
||||
label: Link to publicly available API or Docs
|
||||
placeholder: Link here
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: details
|
||||
attributes:
|
||||
label: Additional details/context about this source
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: acknowledgementsCheck
|
||||
attributes:
|
||||
label: Acknowledgements
|
||||
description: Your issue will be closed if you don’t read this carefully.
|
||||
options:
|
||||
- label: I have reviewed the existing issues to confirm that this is a unique report and not related to any currently open or closed tickets.
|
||||
required: true
|
||||
- label: I understand that this app is provided as-is, without any guarantees, and I might not receive a response to my request. Sometimes you might not get the response you want.
|
||||
required: true
|
||||
@@ -16,6 +16,8 @@ jobs:
|
||||
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
|
||||
GEO_NAMES_USERNAME: ${{ secrets.GEO_NAMES_USERNAME }}
|
||||
MF_KEY: ${{ secrets.MF_KEY }}
|
||||
ACCU_KEY: ${{ secrets.ACCU_KEY }}
|
||||
WEATHERAPI_KEY: ${{ secrets.WEATHERAPI_KEY }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -25,13 +27,15 @@ jobs:
|
||||
run: chmod +x gradlew
|
||||
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: "21.0.7"
|
||||
|
||||
- name: Setup Android SDK
|
||||
uses: android-actions/setup-android@v3
|
||||
with:
|
||||
packages: 'platform-tools'
|
||||
|
||||
- name: Decode keystore
|
||||
run: |
|
||||
@@ -48,6 +52,10 @@ jobs:
|
||||
./gradlew \
|
||||
--no-daemon \
|
||||
--no-build-cache \
|
||||
-PGEO_NAMES_USERNAME="${{ secrets.GEO_NAMES_USERNAME }}" \
|
||||
-PMF_KEY="${{ secrets.MF_KEY }}" \
|
||||
-PACCU_KEY="${{ secrets.ACCU_KEY }}" \
|
||||
-PWEATHERAPI_KEY="${{ secrets.WEATHERAPI_KEY }}" \
|
||||
clean assembleRelease
|
||||
|
||||
- name: Upload APK
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
# Contributing to WeatherMaster
|
||||
|
||||
Thanks for contributing to WeatherMaster :P Before opening a PR, please read
|
||||
through the guidelines below. They are intended to keep the codebase
|
||||
consistent and make contributions easier to review and maintain
|
||||
|
||||
## Before Contributing
|
||||
|
||||
Before starting work on a contribution, please open an issue first and
|
||||
describe what you would like to change.
|
||||
|
||||
For small changes like typo fixe or other
|
||||
obvious minor fixes, opening an issue is optional
|
||||
|
||||
## General stuff
|
||||
|
||||
- Keep changes focused and avoid unrelated refactors.
|
||||
- Follow the existing architecture and patterns used in the project.
|
||||
- Prefer reusing existing abstractions over introducing new ones.
|
||||
- Don't introduce a new pattern or framework for a single feature.
|
||||
- Keep platform-independent logic independent of UI code where
|
||||
possible
|
||||
- Avoid unnecessary changes to existing behavior.
|
||||
|
||||
## Adding a New Weather Source
|
||||
|
||||
The goal is that adding a new source should primarily require changes to the
|
||||
source itself, rather than adding special cases throughout the codebase
|
||||
|
||||
When implementing a new source:
|
||||
|
||||
- Use the existing source abstractions and interfaces.
|
||||
- Do not add source-specific UI.
|
||||
- Do not add source-specific logic to existing UI components.
|
||||
- If the source requires information that the existing architecture cannot
|
||||
represent, discuss the change before implementing a
|
||||
source-specific workaround
|
||||
|
||||
## AI-Assisted Contributions
|
||||
|
||||
AI tools are allowed, but contributors are expected to understand and take
|
||||
ownership of the code they submit
|
||||
|
||||
Please disclose AI usage in your PR description, including what the AI was
|
||||
used for
|
||||
|
||||
PRs that appear to be largely or entirely AI-generated without meaningful
|
||||
review, understanding, or contribution from the author will be closed
|
||||
|
||||
## Attributions
|
||||
|
||||
Add your attribution above the feature you implemented. Attribution should only be added for feature
|
||||
implementations
|
||||
|
||||
For example:
|
||||
|
||||
```kt
|
||||
/**
|
||||
* Initial YOUR_FEATURE integration implemented by https://github.com/YOUR_GITHUB
|
||||
*/
|
||||
```
|
||||
|
||||
_Thanks :P_
|
||||
|
||||
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
# Privacy Policy
|
||||
|
||||
WeatherMaster is an open-source application.
|
||||
|
||||
We respect your privacy. The application itself does **not**:
|
||||
|
||||
- Collect, store, or share personal information.
|
||||
- Track your IP address, usage data, or device identifiers.
|
||||
- Send personal data to us directly.
|
||||
|
||||
---
|
||||
|
||||
## Third-Party Services & APIs
|
||||
|
||||
WeatherMaster relies on external weather and geolocation services to provide forecasts and
|
||||
location-based functionality.
|
||||
|
||||
These third-party services may process certain technical information, including:
|
||||
|
||||
- IP address
|
||||
- Approximate or precise location data
|
||||
- Device or network-related information required for API requests
|
||||
|
||||
This data processing is handled by the respective service providers under their own privacy
|
||||
policies. WeatherMaster itself does not control or store this data.
|
||||
|
||||
---
|
||||
|
||||
## Location Permission
|
||||
|
||||
The app may request access to your device's location to display local weather information.
|
||||
|
||||
- Granting location permission is optional.
|
||||
- Your precise location is used locally within the app to fetch weather data from external APIs.
|
||||
- WeatherMaster does not store your precise location.
|
||||
|
||||
---
|
||||
|
||||
## Children
|
||||
|
||||
This application is not directed toward children under the age of 13 and does not knowingly collect
|
||||
personal information.
|
||||
|
||||
---
|
||||
|
||||
## Changes
|
||||
|
||||
This Privacy Policy may be updated from time to time. Continued use of the app after changes become
|
||||
effective constitutes acceptance of the revised policy.
|
||||
|
||||
---
|
||||
|
||||
## Contact
|
||||
|
||||
If you have any questions about privacy, please contact:
|
||||
|
||||
**Email:** <pranshul.devmain@gmail.com>
|
||||
@@ -31,8 +31,10 @@
|
||||
</div>
|
||||
|
||||
<div align="center">
|
||||
<a href="https://github.com/PranshulGG/WeatherMaster/releases"><img alt="GitHub" src="https://user-images.githubusercontent.com/69304392/148696068-0cfea65d-b18f-4685-82b5-329a330b1c0d.png" height="80"/></a>
|
||||
<a href="https://apt.izzysoft.de/fdroid/index/apk/com.pranshulgg.weather_master_app"><img alt="GitHub" src="preview/download_Btn.png" height="80"/></a></div>
|
||||
<a href="https://github.com/PranshulGG/WeatherMaster/releases"><img alt="GitHub" src="preview/get_on_github_btn.png" height="80"/></a>
|
||||
<a href="https://apt.izzysoft.de/fdroid/index/apk/com.pranshulgg.weather_master_app"><img alt="GitHub" src="preview/get_on_izzy_btn.png" height="80"/></a>
|
||||
<a href="https://play.google.com/store/apps/details?id=com.pranshulgg.weather_master"><img alt="GitHub" src="preview/get_on_googleplay_btn.png" height="80"/></a></div>
|
||||
|
||||
<br>
|
||||
|
||||

|
||||
@@ -44,28 +46,87 @@
|
||||
<img src="preview/preview_2.png" width="250">
|
||||
<img src="preview/preview_3.png" width="250">
|
||||
<img src="preview/preview_4.png" width="250">
|
||||
<img src="preview/preview_5.png" width="250">
|
||||
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
# 🌐 Translate the app on [Crowdin](https://crowdin.com/project/weathermaster)
|
||||
|
||||
- **Feel free to open an issue if you want to request a language**
|
||||
|
||||
<a href="https://crowdin.com/project/weathermaster"><img src="https://badges.crowdin.net/weathermaster/localized.svg" width="200"> </a>
|
||||
|
||||
# 🌦️ Supported weather sources
|
||||
|
||||
- **Open Meteo**
|
||||
- **Met Norway**
|
||||
- **National Weather Service (NWS)**
|
||||
- **NWS**
|
||||
- **SMHI**
|
||||
- **DWD**
|
||||
- **Meteo-France**
|
||||
- **FMI**
|
||||
- **ECCC**
|
||||
- **BMKG**
|
||||
- **China**
|
||||
- **AccuWeather**
|
||||
- **Meteo AM**
|
||||
- **IPMA**
|
||||
- **WeatherApi.com**
|
||||
- **Gismeteo**
|
||||
- **Met Office** _(requires your own API key — sign up [here](https://www.metoffice.gov.uk/))_
|
||||
- **AEMET** _(requires your own API key — sign
|
||||
up [here](https://opendata.aemet.es/centrodedescargas/altaUsuario))_
|
||||
- **IMD**
|
||||
- **WMO Severe Weather Information Centre**
|
||||
- **FOSS Public Alert Server**
|
||||
- **CWA**
|
||||
- **Pirate Weather**
|
||||
- **JMA**
|
||||
- **IMET**
|
||||
- **OpenWeather**
|
||||
- _**And more to be added**_
|
||||
|
||||
Some sources need a free API key from the provider before you can select them — add yours from a
|
||||
location's weather source picker, or from **Settings → Weather Sources → API key config**.
|
||||
|
||||
# 🌐 Translate the app on [Crowdin](https://crowdin.com/project/weathermaster)
|
||||
|
||||
_**Feel free to open an issue if you want to request a language**_
|
||||
|
||||
<a href="https://crowdin.com/project/weathermaster" style="background-color: red"></a>
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
[](https://crowdin.com/project/weathermaster)
|
||||
|
||||
# ✉️ Contact
|
||||
|
||||
For any questions or feedback, feel free to open an issue on GitHub or contact
|
||||
|
||||
+51
-8
@@ -3,7 +3,7 @@ import java.util.Properties
|
||||
plugins {
|
||||
alias(libs.plugins.android.application)
|
||||
alias(libs.plugins.kotlin.compose)
|
||||
id("com.google.devtools.ksp") version "2.3.4"
|
||||
id("com.google.devtools.ksp") version "2.3.6"
|
||||
id("com.google.dagger.hilt.android")
|
||||
id("androidx.room")
|
||||
kotlin("plugin.serialization") version "2.3.21"
|
||||
@@ -22,10 +22,18 @@ val geoNamesUserNameKey =
|
||||
|
||||
val mfKey = providers.gradleProperty("MF_KEY").orNull ?: System.getenv("MF_KEY")
|
||||
?: ""
|
||||
|
||||
val accuKey = providers.gradleProperty("ACCU_KEY").orNull ?: System.getenv("ACCU_KEY")
|
||||
?: ""
|
||||
val weatherapiKey =
|
||||
providers.gradleProperty("WEATHERAPI_KEY").orNull ?: System.getenv("WEATHERAPI_KEY")
|
||||
?: ""
|
||||
val keystoreFile = file("../keystore/release.jks")
|
||||
val hasKeystore = keystoreFile.exists()
|
||||
|
||||
val versionNameString = "3.11.0"
|
||||
|
||||
val playStore = false
|
||||
|
||||
android {
|
||||
namespace = "com.pranshulgg.weather_master_app"
|
||||
compileSdk {
|
||||
@@ -34,11 +42,15 @@ android {
|
||||
android.buildFeatures.buildConfig = true
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.pranshulgg.weather_master_app"
|
||||
minSdk = 24
|
||||
applicationId = if (playStore) {
|
||||
"com.pranshulgg.weather_master"
|
||||
} else {
|
||||
"com.pranshulgg.weather_master_app"
|
||||
}
|
||||
minSdk = 26
|
||||
targetSdk = 36
|
||||
versionCode = 51
|
||||
versionName = "3.3.0"
|
||||
versionCode = 68
|
||||
versionName = versionNameString
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
@@ -53,6 +65,30 @@ android {
|
||||
"MF_KEY",
|
||||
"\"$mfKey\""
|
||||
)
|
||||
|
||||
buildConfigField(
|
||||
"String",
|
||||
"ACCU_KEY",
|
||||
"\"$accuKey\""
|
||||
)
|
||||
|
||||
buildConfigField(
|
||||
"String",
|
||||
"WEATHERAPI_KEY",
|
||||
"\"$weatherapiKey\""
|
||||
)
|
||||
|
||||
buildConfigField(
|
||||
"String",
|
||||
"APP_VERSION",
|
||||
"\"v${versionNameString}\""
|
||||
)
|
||||
|
||||
buildConfigField(
|
||||
"boolean",
|
||||
"IS_PLAYSTORE_BUILD",
|
||||
playStore.toString()
|
||||
)
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
@@ -83,7 +119,7 @@ android {
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
isCoreLibraryDesugaringEnabled = true
|
||||
// isCoreLibraryDesugaringEnabled = true
|
||||
}
|
||||
buildFeatures {
|
||||
compose = true
|
||||
@@ -130,8 +166,14 @@ dependencies {
|
||||
implementation(libs.common.suncalc)
|
||||
implementation(libs.androidx.appcompat)
|
||||
|
||||
coreLibraryDesugaring(libs.desugar.jdk.libs)
|
||||
implementation(libs.jts.core)
|
||||
implementation(libs.jts.io.common)
|
||||
|
||||
implementation(libs.jackson.module.kotlin)
|
||||
|
||||
// coreLibraryDesugaring(libs.desugar.jdk.libs) // Not sure but it causes timezone crashes on some devices
|
||||
implementation(libs.androidx.hilt.navigation.compose)
|
||||
implementation(libs.converter.jaxb)
|
||||
ksp(libs.room.compiler)
|
||||
implementation(libs.hilt.android)
|
||||
ksp(libs.hilt.android.compiler)
|
||||
@@ -143,6 +185,7 @@ dependencies {
|
||||
|
||||
implementation(libs.androidx.work.runtime)
|
||||
implementation(libs.hilt.work)
|
||||
ksp(libs.hilt.metadata.jvm)
|
||||
|
||||
implementation(libs.androidx.glance)
|
||||
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
{
|
||||
"version": 3,
|
||||
"artifactType": {
|
||||
"type": "APK",
|
||||
"kind": "Directory"
|
||||
},
|
||||
"applicationId": "com.pranshulgg.weather_master_app",
|
||||
"variantName": "release",
|
||||
"elements": [
|
||||
{
|
||||
"type": "SINGLE",
|
||||
"filters": [],
|
||||
"attributes": [],
|
||||
"versionCode": 50,
|
||||
"versionName": "3.2.0",
|
||||
"outputFile": "app-release.apk"
|
||||
}
|
||||
],
|
||||
"elementType": "File",
|
||||
"baselineProfiles": [
|
||||
{
|
||||
"minApi": 28,
|
||||
"maxApi": 30,
|
||||
"baselineProfiles": [
|
||||
"baselineProfiles/1/app-release.dm"
|
||||
]
|
||||
},
|
||||
{
|
||||
"minApi": 31,
|
||||
"maxApi": 2147483647,
|
||||
"baselineProfiles": [
|
||||
"baselineProfiles/0/app-release.dm"
|
||||
]
|
||||
}
|
||||
],
|
||||
"minSdkVersionForDexing": 24
|
||||
}
|
||||
+747
@@ -0,0 +1,747 @@
|
||||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 43,
|
||||
"identityHash": "3498b6cf93a31e50cf1bef443490315f",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "weather_locations",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `country` TEXT NOT NULL, `lat` REAL NOT NULL, `lon` REAL NOT NULL, `timezone` TEXT NOT NULL, `source` TEXT NOT NULL, `state` TEXT, `isFavorite` INTEGER NOT NULL, `isPinned` INTEGER NOT NULL, `countryCode` TEXT, `isDefault` INTEGER NOT NULL, `isDeviceLocation` INTEGER NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "country",
|
||||
"columnName": "country",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lat",
|
||||
"columnName": "lat",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lon",
|
||||
"columnName": "lon",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "timezone",
|
||||
"columnName": "timezone",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "source",
|
||||
"columnName": "source",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "state",
|
||||
"columnName": "state",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "isFavorite",
|
||||
"columnName": "isFavorite",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isPinned",
|
||||
"columnName": "isPinned",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "countryCode",
|
||||
"columnName": "countryCode",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "isDefault",
|
||||
"columnName": "isDefault",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isDeviceLocation",
|
||||
"columnName": "isDeviceLocation",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "weather_current",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `temperature` REAL, `humidity` REAL NOT NULL, `windSpeed` REAL, `windDirection` TEXT, `pressureMsl` REAL, `visibility` INTEGER, `cloudCover` REAL, `uvIndex` REAL, `weatherCondition` TEXT NOT NULL, `feelsLike` REAL, `time` INTEGER NOT NULL, `dewPoint` REAL, `utcOffsetSeconds` INTEGER, `lastUpdatedInMilli` INTEGER NOT NULL, PRIMARY KEY(`locationId`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperature",
|
||||
"columnName": "temperature",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "humidity",
|
||||
"columnName": "humidity",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "windSpeed",
|
||||
"columnName": "windSpeed",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windDirection",
|
||||
"columnName": "windDirection",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureMsl",
|
||||
"columnName": "pressureMsl",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "cloudCover",
|
||||
"columnName": "cloudCover",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "uvIndex",
|
||||
"columnName": "uvIndex",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "weatherCondition",
|
||||
"columnName": "weatherCondition",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "feelsLike",
|
||||
"columnName": "feelsLike",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dewPoint",
|
||||
"columnName": "dewPoint",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "utcOffsetSeconds",
|
||||
"columnName": "utcOffsetSeconds",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdatedInMilli",
|
||||
"columnName": "lastUpdatedInMilli",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_weather_current_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_weather_current_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "weather_hourly",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `temperature` REAL, `windSpeed` REAL, `windDirection` TEXT, `rain` REAL NOT NULL, `snowfall` REAL, `uvIndex` REAL, `weatherCondition` TEXT NOT NULL, `pressureMsl` REAL, `visibility` INTEGER, `humidity` REAL, `dewPoint` REAL, `time` INTEGER NOT NULL, `precipitationProbability` INTEGER, PRIMARY KEY(`locationId`, `time`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperature",
|
||||
"columnName": "temperature",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windSpeed",
|
||||
"columnName": "windSpeed",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windDirection",
|
||||
"columnName": "windDirection",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "rain",
|
||||
"columnName": "rain",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "snowfall",
|
||||
"columnName": "snowfall",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "uvIndex",
|
||||
"columnName": "uvIndex",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "weatherCondition",
|
||||
"columnName": "weatherCondition",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureMsl",
|
||||
"columnName": "pressureMsl",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "humidity",
|
||||
"columnName": "humidity",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "dewPoint",
|
||||
"columnName": "dewPoint",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "precipitationProbability",
|
||||
"columnName": "precipitationProbability",
|
||||
"affinity": "INTEGER"
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId",
|
||||
"time"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_weather_hourly_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_weather_hourly_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "weather_daily",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `temperatureMin` REAL, `temperatureMax` REAL, `windSpeed` REAL, `windDirection` TEXT, `rainSum` REAL NOT NULL, `snowfallSum` REAL, `uvIndexMax` REAL, `weatherCondition` TEXT NOT NULL, `time` INTEGER NOT NULL, `precipitationProbabilityMax` INTEGER, `sunrise` INTEGER NOT NULL, `sunset` INTEGER NOT NULL, `moonrise` INTEGER NOT NULL, `moonset` INTEGER NOT NULL, `moonPhase` TEXT NOT NULL, `dawn` INTEGER NOT NULL, `dusk` INTEGER NOT NULL, PRIMARY KEY(`locationId`, `time`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperatureMin",
|
||||
"columnName": "temperatureMin",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperatureMax",
|
||||
"columnName": "temperatureMax",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windSpeed",
|
||||
"columnName": "windSpeed",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windDirection",
|
||||
"columnName": "windDirection",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "rainSum",
|
||||
"columnName": "rainSum",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "snowfallSum",
|
||||
"columnName": "snowfallSum",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "uvIndexMax",
|
||||
"columnName": "uvIndexMax",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "weatherCondition",
|
||||
"columnName": "weatherCondition",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "precipitationProbabilityMax",
|
||||
"columnName": "precipitationProbabilityMax",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "sunrise",
|
||||
"columnName": "sunrise",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "sunset",
|
||||
"columnName": "sunset",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "moonrise",
|
||||
"columnName": "moonrise",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "moonset",
|
||||
"columnName": "moonset",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "moonPhase",
|
||||
"columnName": "moonPhase",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dawn",
|
||||
"columnName": "dawn",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dusk",
|
||||
"columnName": "dusk",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId",
|
||||
"time"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_weather_daily_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_weather_daily_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "weather_units",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `tempUnit` TEXT NOT NULL, `windUnit` TEXT NOT NULL, `distanceUnit` TEXT NOT NULL, `pressureUnit` TEXT NOT NULL, `precipitationUnit` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "tempUnit",
|
||||
"columnName": "tempUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "windUnit",
|
||||
"columnName": "windUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "distanceUnit",
|
||||
"columnName": "distanceUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureUnit",
|
||||
"columnName": "pressureUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "precipitationUnit",
|
||||
"columnName": "precipitationUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "weather_blocks",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `isDaily` INTEGER NOT NULL, `type` TEXT NOT NULL, `isHidden` INTEGER NOT NULL, `position` INTEGER NOT NULL)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isDaily",
|
||||
"columnName": "isDaily",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "type",
|
||||
"columnName": "type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isHidden",
|
||||
"columnName": "isHidden",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "position",
|
||||
"columnName": "position",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": true,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "air_quality_current",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `usAqi` INTEGER, `pm10` REAL, `pm25` REAL, `carbonMonoxide` REAL, `nitrogenDioxide` REAL, `sulphurDioxide` REAL, `ozone` REAL, `lastUpdatedInMilli` INTEGER NOT NULL, PRIMARY KEY(`locationId`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "usAqi",
|
||||
"columnName": "usAqi",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pm10",
|
||||
"columnName": "pm10",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pm25",
|
||||
"columnName": "pm25",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "carbonMonoxide",
|
||||
"columnName": "carbonMonoxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "nitrogenDioxide",
|
||||
"columnName": "nitrogenDioxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "sulphurDioxide",
|
||||
"columnName": "sulphurDioxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "ozone",
|
||||
"columnName": "ozone",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdatedInMilli",
|
||||
"columnName": "lastUpdatedInMilli",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_air_quality_current_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_air_quality_current_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "nws_location_gridpoints",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `officeId` TEXT NOT NULL, `gridX` INTEGER NOT NULL, `gridY` INTEGER NOT NULL, `stationIdentifier` TEXT NOT NULL, `lastUpdatedMilli` INTEGER NOT NULL, PRIMARY KEY(`locationId`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "officeId",
|
||||
"columnName": "officeId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "gridX",
|
||||
"columnName": "gridX",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "gridY",
|
||||
"columnName": "gridY",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "stationIdentifier",
|
||||
"columnName": "stationIdentifier",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdatedMilli",
|
||||
"columnName": "lastUpdatedMilli",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_nws_location_gridpoints_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_nws_location_gridpoints_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "github",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `currentTag` TEXT NOT NULL, `lastFetchedTag` TEXT NOT NULL, `lastFetchedTime` INTEGER NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "currentTag",
|
||||
"columnName": "currentTag",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastFetchedTag",
|
||||
"columnName": "lastFetchedTag",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastFetchedTime",
|
||||
"columnName": "lastFetchedTime",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '3498b6cf93a31e50cf1bef443490315f')"
|
||||
]
|
||||
}
|
||||
}
|
||||
+767
@@ -0,0 +1,767 @@
|
||||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 44,
|
||||
"identityHash": "80da71ec25bcf07ba0d22811005aa37f",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "weather_locations",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `country` TEXT NOT NULL, `lat` REAL NOT NULL, `lon` REAL NOT NULL, `timezone` TEXT NOT NULL, `source` TEXT NOT NULL, `state` TEXT, `isFavorite` INTEGER NOT NULL, `isPinned` INTEGER NOT NULL, `countryCode` TEXT, `isDefault` INTEGER NOT NULL, `isDeviceLocation` INTEGER NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "country",
|
||||
"columnName": "country",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lat",
|
||||
"columnName": "lat",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lon",
|
||||
"columnName": "lon",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "timezone",
|
||||
"columnName": "timezone",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "source",
|
||||
"columnName": "source",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "state",
|
||||
"columnName": "state",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "isFavorite",
|
||||
"columnName": "isFavorite",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isPinned",
|
||||
"columnName": "isPinned",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "countryCode",
|
||||
"columnName": "countryCode",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "isDefault",
|
||||
"columnName": "isDefault",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isDeviceLocation",
|
||||
"columnName": "isDeviceLocation",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "weather_current",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `temperature` REAL, `humidity` REAL NOT NULL, `windSpeed` REAL, `windDirection` TEXT, `pressureMsl` REAL, `visibility` INTEGER, `cloudCover` REAL, `uvIndex` REAL, `weatherCondition` TEXT NOT NULL, `feelsLike` REAL, `time` INTEGER NOT NULL, `dewPoint` REAL, `utcOffsetSeconds` INTEGER, `lastUpdatedInMilli` INTEGER NOT NULL, PRIMARY KEY(`locationId`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperature",
|
||||
"columnName": "temperature",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "humidity",
|
||||
"columnName": "humidity",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "windSpeed",
|
||||
"columnName": "windSpeed",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windDirection",
|
||||
"columnName": "windDirection",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureMsl",
|
||||
"columnName": "pressureMsl",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "cloudCover",
|
||||
"columnName": "cloudCover",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "uvIndex",
|
||||
"columnName": "uvIndex",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "weatherCondition",
|
||||
"columnName": "weatherCondition",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "feelsLike",
|
||||
"columnName": "feelsLike",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dewPoint",
|
||||
"columnName": "dewPoint",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "utcOffsetSeconds",
|
||||
"columnName": "utcOffsetSeconds",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdatedInMilli",
|
||||
"columnName": "lastUpdatedInMilli",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_weather_current_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_weather_current_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "weather_hourly",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `temperature` REAL, `windSpeed` REAL, `windDirection` TEXT, `rain` REAL NOT NULL, `snowfall` REAL, `uvIndex` REAL, `weatherCondition` TEXT NOT NULL, `pressureMsl` REAL, `visibility` INTEGER, `humidity` REAL, `dewPoint` REAL, `time` INTEGER NOT NULL, `precipitationProbability` INTEGER, PRIMARY KEY(`locationId`, `time`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperature",
|
||||
"columnName": "temperature",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windSpeed",
|
||||
"columnName": "windSpeed",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windDirection",
|
||||
"columnName": "windDirection",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "rain",
|
||||
"columnName": "rain",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "snowfall",
|
||||
"columnName": "snowfall",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "uvIndex",
|
||||
"columnName": "uvIndex",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "weatherCondition",
|
||||
"columnName": "weatherCondition",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureMsl",
|
||||
"columnName": "pressureMsl",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "humidity",
|
||||
"columnName": "humidity",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "dewPoint",
|
||||
"columnName": "dewPoint",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "precipitationProbability",
|
||||
"columnName": "precipitationProbability",
|
||||
"affinity": "INTEGER"
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId",
|
||||
"time"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_weather_hourly_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_weather_hourly_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "weather_daily",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `temperatureMin` REAL, `temperatureMax` REAL, `windSpeed` REAL, `windDirection` TEXT, `rainSum` REAL NOT NULL, `snowfallSum` REAL, `uvIndexMax` REAL, `weatherCondition` TEXT NOT NULL, `time` INTEGER NOT NULL, `precipitationProbabilityMax` INTEGER, `pressureMsl` REAL, `visibility` INTEGER, `humidity` REAL, `dewPoint` REAL, `sunrise` INTEGER NOT NULL, `sunset` INTEGER NOT NULL, `moonrise` INTEGER NOT NULL, `moonset` INTEGER NOT NULL, `moonPhase` TEXT NOT NULL, `dawn` INTEGER NOT NULL, `dusk` INTEGER NOT NULL, PRIMARY KEY(`locationId`, `time`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperatureMin",
|
||||
"columnName": "temperatureMin",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperatureMax",
|
||||
"columnName": "temperatureMax",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windSpeed",
|
||||
"columnName": "windSpeed",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windDirection",
|
||||
"columnName": "windDirection",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "rainSum",
|
||||
"columnName": "rainSum",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "snowfallSum",
|
||||
"columnName": "snowfallSum",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "uvIndexMax",
|
||||
"columnName": "uvIndexMax",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "weatherCondition",
|
||||
"columnName": "weatherCondition",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "precipitationProbabilityMax",
|
||||
"columnName": "precipitationProbabilityMax",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureMsl",
|
||||
"columnName": "pressureMsl",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "humidity",
|
||||
"columnName": "humidity",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "dewPoint",
|
||||
"columnName": "dewPoint",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "sunrise",
|
||||
"columnName": "sunrise",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "sunset",
|
||||
"columnName": "sunset",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "moonrise",
|
||||
"columnName": "moonrise",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "moonset",
|
||||
"columnName": "moonset",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "moonPhase",
|
||||
"columnName": "moonPhase",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dawn",
|
||||
"columnName": "dawn",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dusk",
|
||||
"columnName": "dusk",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId",
|
||||
"time"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_weather_daily_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_weather_daily_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "weather_units",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `tempUnit` TEXT NOT NULL, `windUnit` TEXT NOT NULL, `distanceUnit` TEXT NOT NULL, `pressureUnit` TEXT NOT NULL, `precipitationUnit` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "tempUnit",
|
||||
"columnName": "tempUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "windUnit",
|
||||
"columnName": "windUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "distanceUnit",
|
||||
"columnName": "distanceUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureUnit",
|
||||
"columnName": "pressureUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "precipitationUnit",
|
||||
"columnName": "precipitationUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "weather_blocks",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `isDaily` INTEGER NOT NULL, `type` TEXT NOT NULL, `isHidden` INTEGER NOT NULL, `position` INTEGER NOT NULL)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isDaily",
|
||||
"columnName": "isDaily",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "type",
|
||||
"columnName": "type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isHidden",
|
||||
"columnName": "isHidden",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "position",
|
||||
"columnName": "position",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": true,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "air_quality_current",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `usAqi` INTEGER, `pm10` REAL, `pm25` REAL, `carbonMonoxide` REAL, `nitrogenDioxide` REAL, `sulphurDioxide` REAL, `ozone` REAL, `lastUpdatedInMilli` INTEGER NOT NULL, PRIMARY KEY(`locationId`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "usAqi",
|
||||
"columnName": "usAqi",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pm10",
|
||||
"columnName": "pm10",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pm25",
|
||||
"columnName": "pm25",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "carbonMonoxide",
|
||||
"columnName": "carbonMonoxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "nitrogenDioxide",
|
||||
"columnName": "nitrogenDioxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "sulphurDioxide",
|
||||
"columnName": "sulphurDioxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "ozone",
|
||||
"columnName": "ozone",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdatedInMilli",
|
||||
"columnName": "lastUpdatedInMilli",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_air_quality_current_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_air_quality_current_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "nws_location_gridpoints",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `officeId` TEXT NOT NULL, `gridX` INTEGER NOT NULL, `gridY` INTEGER NOT NULL, `stationIdentifier` TEXT NOT NULL, `lastUpdatedMilli` INTEGER NOT NULL, PRIMARY KEY(`locationId`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "officeId",
|
||||
"columnName": "officeId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "gridX",
|
||||
"columnName": "gridX",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "gridY",
|
||||
"columnName": "gridY",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "stationIdentifier",
|
||||
"columnName": "stationIdentifier",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdatedMilli",
|
||||
"columnName": "lastUpdatedMilli",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_nws_location_gridpoints_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_nws_location_gridpoints_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "github",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `currentTag` TEXT NOT NULL, `lastFetchedTag` TEXT NOT NULL, `lastFetchedTime` INTEGER NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "currentTag",
|
||||
"columnName": "currentTag",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastFetchedTag",
|
||||
"columnName": "lastFetchedTag",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastFetchedTime",
|
||||
"columnName": "lastFetchedTime",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '80da71ec25bcf07ba0d22811005aa37f')"
|
||||
]
|
||||
}
|
||||
}
|
||||
+851
@@ -0,0 +1,851 @@
|
||||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 45,
|
||||
"identityHash": "b2ca5c75db987a1d27628fc45eac72bf",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "weather_locations",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `country` TEXT NOT NULL, `lat` REAL NOT NULL, `lon` REAL NOT NULL, `timezone` TEXT NOT NULL, `source` TEXT NOT NULL, `state` TEXT, `isFavorite` INTEGER NOT NULL, `isPinned` INTEGER NOT NULL, `countryCode` TEXT, `isDefault` INTEGER NOT NULL, `isDeviceLocation` INTEGER NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "country",
|
||||
"columnName": "country",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lat",
|
||||
"columnName": "lat",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lon",
|
||||
"columnName": "lon",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "timezone",
|
||||
"columnName": "timezone",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "source",
|
||||
"columnName": "source",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "state",
|
||||
"columnName": "state",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "isFavorite",
|
||||
"columnName": "isFavorite",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isPinned",
|
||||
"columnName": "isPinned",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "countryCode",
|
||||
"columnName": "countryCode",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "isDefault",
|
||||
"columnName": "isDefault",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isDeviceLocation",
|
||||
"columnName": "isDeviceLocation",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "weather_current",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `temperature` REAL, `humidity` REAL NOT NULL, `windSpeed` REAL, `windDirection` TEXT, `pressureMsl` REAL, `visibility` INTEGER, `cloudCover` REAL, `uvIndex` REAL, `weatherCondition` TEXT NOT NULL, `feelsLike` REAL, `time` INTEGER NOT NULL, `dewPoint` REAL, `utcOffsetSeconds` INTEGER, `lastUpdatedInMilli` INTEGER NOT NULL, PRIMARY KEY(`locationId`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperature",
|
||||
"columnName": "temperature",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "humidity",
|
||||
"columnName": "humidity",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "windSpeed",
|
||||
"columnName": "windSpeed",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windDirection",
|
||||
"columnName": "windDirection",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureMsl",
|
||||
"columnName": "pressureMsl",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "cloudCover",
|
||||
"columnName": "cloudCover",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "uvIndex",
|
||||
"columnName": "uvIndex",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "weatherCondition",
|
||||
"columnName": "weatherCondition",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "feelsLike",
|
||||
"columnName": "feelsLike",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dewPoint",
|
||||
"columnName": "dewPoint",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "utcOffsetSeconds",
|
||||
"columnName": "utcOffsetSeconds",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdatedInMilli",
|
||||
"columnName": "lastUpdatedInMilli",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_weather_current_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_weather_current_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "weather_hourly",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `temperature` REAL, `windSpeed` REAL, `windDirection` TEXT, `rain` REAL NOT NULL, `snowfall` REAL, `uvIndex` REAL, `weatherCondition` TEXT NOT NULL, `pressureMsl` REAL, `visibility` INTEGER, `humidity` REAL, `dewPoint` REAL, `time` INTEGER NOT NULL, `precipitationProbability` INTEGER, PRIMARY KEY(`locationId`, `time`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperature",
|
||||
"columnName": "temperature",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windSpeed",
|
||||
"columnName": "windSpeed",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windDirection",
|
||||
"columnName": "windDirection",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "rain",
|
||||
"columnName": "rain",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "snowfall",
|
||||
"columnName": "snowfall",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "uvIndex",
|
||||
"columnName": "uvIndex",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "weatherCondition",
|
||||
"columnName": "weatherCondition",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureMsl",
|
||||
"columnName": "pressureMsl",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "humidity",
|
||||
"columnName": "humidity",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "dewPoint",
|
||||
"columnName": "dewPoint",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "precipitationProbability",
|
||||
"columnName": "precipitationProbability",
|
||||
"affinity": "INTEGER"
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId",
|
||||
"time"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_weather_hourly_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_weather_hourly_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "weather_daily",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `temperatureMin` REAL, `temperatureMax` REAL, `windSpeed` REAL, `windDirection` TEXT, `rainSum` REAL NOT NULL, `snowfallSum` REAL, `uvIndexMax` REAL, `weatherCondition` TEXT NOT NULL, `time` INTEGER NOT NULL, `precipitationProbabilityMax` INTEGER, `pressureMsl` REAL, `visibility` INTEGER, `humidity` REAL, `dewPoint` REAL, `sunrise` INTEGER NOT NULL, `sunset` INTEGER NOT NULL, `moonrise` INTEGER NOT NULL, `moonset` INTEGER NOT NULL, `moonPhase` TEXT NOT NULL, `dawn` INTEGER NOT NULL, `dusk` INTEGER NOT NULL, PRIMARY KEY(`locationId`, `time`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperatureMin",
|
||||
"columnName": "temperatureMin",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperatureMax",
|
||||
"columnName": "temperatureMax",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windSpeed",
|
||||
"columnName": "windSpeed",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windDirection",
|
||||
"columnName": "windDirection",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "rainSum",
|
||||
"columnName": "rainSum",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "snowfallSum",
|
||||
"columnName": "snowfallSum",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "uvIndexMax",
|
||||
"columnName": "uvIndexMax",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "weatherCondition",
|
||||
"columnName": "weatherCondition",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "precipitationProbabilityMax",
|
||||
"columnName": "precipitationProbabilityMax",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureMsl",
|
||||
"columnName": "pressureMsl",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "humidity",
|
||||
"columnName": "humidity",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "dewPoint",
|
||||
"columnName": "dewPoint",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "sunrise",
|
||||
"columnName": "sunrise",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "sunset",
|
||||
"columnName": "sunset",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "moonrise",
|
||||
"columnName": "moonrise",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "moonset",
|
||||
"columnName": "moonset",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "moonPhase",
|
||||
"columnName": "moonPhase",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dawn",
|
||||
"columnName": "dawn",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dusk",
|
||||
"columnName": "dusk",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId",
|
||||
"time"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_weather_daily_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_weather_daily_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "weather_units",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `tempUnit` TEXT NOT NULL, `windUnit` TEXT NOT NULL, `distanceUnit` TEXT NOT NULL, `pressureUnit` TEXT NOT NULL, `precipitationUnit` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "tempUnit",
|
||||
"columnName": "tempUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "windUnit",
|
||||
"columnName": "windUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "distanceUnit",
|
||||
"columnName": "distanceUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureUnit",
|
||||
"columnName": "pressureUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "precipitationUnit",
|
||||
"columnName": "precipitationUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "weather_blocks",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `isDaily` INTEGER NOT NULL, `type` TEXT NOT NULL, `isHidden` INTEGER NOT NULL, `position` INTEGER NOT NULL)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isDaily",
|
||||
"columnName": "isDaily",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "type",
|
||||
"columnName": "type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isHidden",
|
||||
"columnName": "isHidden",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "position",
|
||||
"columnName": "position",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": true,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "air_quality_current",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `usAqi` INTEGER, `pm10` REAL, `pm25` REAL, `carbonMonoxide` REAL, `nitrogenDioxide` REAL, `sulphurDioxide` REAL, `ozone` REAL, `lastUpdatedInMilli` INTEGER NOT NULL, PRIMARY KEY(`locationId`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "usAqi",
|
||||
"columnName": "usAqi",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pm10",
|
||||
"columnName": "pm10",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pm25",
|
||||
"columnName": "pm25",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "carbonMonoxide",
|
||||
"columnName": "carbonMonoxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "nitrogenDioxide",
|
||||
"columnName": "nitrogenDioxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "sulphurDioxide",
|
||||
"columnName": "sulphurDioxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "ozone",
|
||||
"columnName": "ozone",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdatedInMilli",
|
||||
"columnName": "lastUpdatedInMilli",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_air_quality_current_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_air_quality_current_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "nws_location_gridpoints",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `officeId` TEXT NOT NULL, `gridX` INTEGER NOT NULL, `gridY` INTEGER NOT NULL, `stationIdentifier` TEXT NOT NULL, `lastUpdatedMilli` INTEGER NOT NULL, PRIMARY KEY(`locationId`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "officeId",
|
||||
"columnName": "officeId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "gridX",
|
||||
"columnName": "gridX",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "gridY",
|
||||
"columnName": "gridY",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "stationIdentifier",
|
||||
"columnName": "stationIdentifier",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdatedMilli",
|
||||
"columnName": "lastUpdatedMilli",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_nws_location_gridpoints_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_nws_location_gridpoints_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "github",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `currentTag` TEXT NOT NULL, `lastFetchedTag` TEXT NOT NULL, `lastFetchedTime` INTEGER NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "currentTag",
|
||||
"columnName": "currentTag",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastFetchedTag",
|
||||
"columnName": "lastFetchedTag",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastFetchedTime",
|
||||
"columnName": "lastFetchedTime",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "air_quality_hourly",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `locationId` TEXT NOT NULL, `pm10` REAL, `pm25` REAL, `carbonMonoxide` REAL, `nitrogenDioxide` REAL, `sulphurDioxide` REAL, `ozone` REAL, `time` INTEGER NOT NULL, FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pm10",
|
||||
"columnName": "pm10",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pm25",
|
||||
"columnName": "pm25",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "carbonMonoxide",
|
||||
"columnName": "carbonMonoxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "nitrogenDioxide",
|
||||
"columnName": "nitrogenDioxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "sulphurDioxide",
|
||||
"columnName": "sulphurDioxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "ozone",
|
||||
"columnName": "ozone",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": true,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_air_quality_hourly_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_air_quality_hourly_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'b2ca5c75db987a1d27628fc45eac72bf')"
|
||||
]
|
||||
}
|
||||
}
|
||||
+863
@@ -0,0 +1,863 @@
|
||||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 46,
|
||||
"identityHash": "fd66b7531bfe72f6bcac04b8fe26dc9e",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "weather_locations",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `country` TEXT NOT NULL, `lat` REAL NOT NULL, `lon` REAL NOT NULL, `timezone` TEXT NOT NULL, `source` TEXT NOT NULL, `state` TEXT, `isFavorite` INTEGER NOT NULL, `isPinned` INTEGER NOT NULL, `countryCode` TEXT, `isDefault` INTEGER NOT NULL, `isDeviceLocation` INTEGER NOT NULL, `alertSource` TEXT NOT NULL, `airQualitySource` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "country",
|
||||
"columnName": "country",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lat",
|
||||
"columnName": "lat",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lon",
|
||||
"columnName": "lon",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "timezone",
|
||||
"columnName": "timezone",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "source",
|
||||
"columnName": "source",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "state",
|
||||
"columnName": "state",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "isFavorite",
|
||||
"columnName": "isFavorite",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isPinned",
|
||||
"columnName": "isPinned",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "countryCode",
|
||||
"columnName": "countryCode",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "isDefault",
|
||||
"columnName": "isDefault",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isDeviceLocation",
|
||||
"columnName": "isDeviceLocation",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "alertSource",
|
||||
"columnName": "alertSource",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "airQualitySource",
|
||||
"columnName": "airQualitySource",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "weather_current",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `temperature` REAL, `humidity` REAL NOT NULL, `windSpeed` REAL, `windDirection` TEXT, `pressureMsl` REAL, `visibility` INTEGER, `cloudCover` REAL, `uvIndex` REAL, `weatherCondition` TEXT NOT NULL, `feelsLike` REAL, `time` INTEGER NOT NULL, `dewPoint` REAL, `utcOffsetSeconds` INTEGER, `lastUpdatedInMilli` INTEGER NOT NULL, PRIMARY KEY(`locationId`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperature",
|
||||
"columnName": "temperature",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "humidity",
|
||||
"columnName": "humidity",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "windSpeed",
|
||||
"columnName": "windSpeed",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windDirection",
|
||||
"columnName": "windDirection",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureMsl",
|
||||
"columnName": "pressureMsl",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "cloudCover",
|
||||
"columnName": "cloudCover",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "uvIndex",
|
||||
"columnName": "uvIndex",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "weatherCondition",
|
||||
"columnName": "weatherCondition",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "feelsLike",
|
||||
"columnName": "feelsLike",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dewPoint",
|
||||
"columnName": "dewPoint",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "utcOffsetSeconds",
|
||||
"columnName": "utcOffsetSeconds",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdatedInMilli",
|
||||
"columnName": "lastUpdatedInMilli",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_weather_current_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_weather_current_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "weather_hourly",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `temperature` REAL, `windSpeed` REAL, `windDirection` TEXT, `rain` REAL NOT NULL, `snowfall` REAL, `uvIndex` REAL, `weatherCondition` TEXT NOT NULL, `pressureMsl` REAL, `visibility` INTEGER, `humidity` REAL, `dewPoint` REAL, `time` INTEGER NOT NULL, `precipitationProbability` INTEGER, PRIMARY KEY(`locationId`, `time`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperature",
|
||||
"columnName": "temperature",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windSpeed",
|
||||
"columnName": "windSpeed",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windDirection",
|
||||
"columnName": "windDirection",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "rain",
|
||||
"columnName": "rain",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "snowfall",
|
||||
"columnName": "snowfall",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "uvIndex",
|
||||
"columnName": "uvIndex",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "weatherCondition",
|
||||
"columnName": "weatherCondition",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureMsl",
|
||||
"columnName": "pressureMsl",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "humidity",
|
||||
"columnName": "humidity",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "dewPoint",
|
||||
"columnName": "dewPoint",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "precipitationProbability",
|
||||
"columnName": "precipitationProbability",
|
||||
"affinity": "INTEGER"
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId",
|
||||
"time"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_weather_hourly_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_weather_hourly_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "weather_daily",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `temperatureMin` REAL, `temperatureMax` REAL, `windSpeed` REAL, `windDirection` TEXT, `rainSum` REAL NOT NULL, `snowfallSum` REAL, `uvIndexMax` REAL, `weatherCondition` TEXT NOT NULL, `time` INTEGER NOT NULL, `precipitationProbabilityMax` INTEGER, `pressureMsl` REAL, `visibility` INTEGER, `humidity` REAL, `dewPoint` REAL, `sunrise` INTEGER NOT NULL, `sunset` INTEGER NOT NULL, `moonrise` INTEGER NOT NULL, `moonset` INTEGER NOT NULL, `moonPhase` TEXT NOT NULL, `dawn` INTEGER NOT NULL, `dusk` INTEGER NOT NULL, PRIMARY KEY(`locationId`, `time`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperatureMin",
|
||||
"columnName": "temperatureMin",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperatureMax",
|
||||
"columnName": "temperatureMax",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windSpeed",
|
||||
"columnName": "windSpeed",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windDirection",
|
||||
"columnName": "windDirection",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "rainSum",
|
||||
"columnName": "rainSum",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "snowfallSum",
|
||||
"columnName": "snowfallSum",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "uvIndexMax",
|
||||
"columnName": "uvIndexMax",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "weatherCondition",
|
||||
"columnName": "weatherCondition",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "precipitationProbabilityMax",
|
||||
"columnName": "precipitationProbabilityMax",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureMsl",
|
||||
"columnName": "pressureMsl",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "humidity",
|
||||
"columnName": "humidity",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "dewPoint",
|
||||
"columnName": "dewPoint",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "sunrise",
|
||||
"columnName": "sunrise",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "sunset",
|
||||
"columnName": "sunset",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "moonrise",
|
||||
"columnName": "moonrise",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "moonset",
|
||||
"columnName": "moonset",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "moonPhase",
|
||||
"columnName": "moonPhase",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dawn",
|
||||
"columnName": "dawn",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dusk",
|
||||
"columnName": "dusk",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId",
|
||||
"time"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_weather_daily_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_weather_daily_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "weather_units",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `tempUnit` TEXT NOT NULL, `windUnit` TEXT NOT NULL, `distanceUnit` TEXT NOT NULL, `pressureUnit` TEXT NOT NULL, `precipitationUnit` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "tempUnit",
|
||||
"columnName": "tempUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "windUnit",
|
||||
"columnName": "windUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "distanceUnit",
|
||||
"columnName": "distanceUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureUnit",
|
||||
"columnName": "pressureUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "precipitationUnit",
|
||||
"columnName": "precipitationUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "weather_blocks",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `isDaily` INTEGER NOT NULL, `type` TEXT NOT NULL, `isHidden` INTEGER NOT NULL, `position` INTEGER NOT NULL)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isDaily",
|
||||
"columnName": "isDaily",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "type",
|
||||
"columnName": "type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isHidden",
|
||||
"columnName": "isHidden",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "position",
|
||||
"columnName": "position",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": true,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "air_quality_current",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `usAqi` INTEGER, `pm10` REAL, `pm25` REAL, `carbonMonoxide` REAL, `nitrogenDioxide` REAL, `sulphurDioxide` REAL, `ozone` REAL, `lastUpdatedInMilli` INTEGER NOT NULL, PRIMARY KEY(`locationId`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "usAqi",
|
||||
"columnName": "usAqi",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pm10",
|
||||
"columnName": "pm10",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pm25",
|
||||
"columnName": "pm25",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "carbonMonoxide",
|
||||
"columnName": "carbonMonoxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "nitrogenDioxide",
|
||||
"columnName": "nitrogenDioxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "sulphurDioxide",
|
||||
"columnName": "sulphurDioxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "ozone",
|
||||
"columnName": "ozone",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdatedInMilli",
|
||||
"columnName": "lastUpdatedInMilli",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_air_quality_current_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_air_quality_current_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "nws_location_gridpoints",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `officeId` TEXT NOT NULL, `gridX` INTEGER NOT NULL, `gridY` INTEGER NOT NULL, `stationIdentifier` TEXT NOT NULL, `lastUpdatedMilli` INTEGER NOT NULL, PRIMARY KEY(`locationId`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "officeId",
|
||||
"columnName": "officeId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "gridX",
|
||||
"columnName": "gridX",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "gridY",
|
||||
"columnName": "gridY",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "stationIdentifier",
|
||||
"columnName": "stationIdentifier",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdatedMilli",
|
||||
"columnName": "lastUpdatedMilli",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_nws_location_gridpoints_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_nws_location_gridpoints_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "github",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `currentTag` TEXT NOT NULL, `lastFetchedTag` TEXT NOT NULL, `lastFetchedTime` INTEGER NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "currentTag",
|
||||
"columnName": "currentTag",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastFetchedTag",
|
||||
"columnName": "lastFetchedTag",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastFetchedTime",
|
||||
"columnName": "lastFetchedTime",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "air_quality_hourly",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `locationId` TEXT NOT NULL, `pm10` REAL, `pm25` REAL, `carbonMonoxide` REAL, `nitrogenDioxide` REAL, `sulphurDioxide` REAL, `ozone` REAL, `time` INTEGER NOT NULL, FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pm10",
|
||||
"columnName": "pm10",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pm25",
|
||||
"columnName": "pm25",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "carbonMonoxide",
|
||||
"columnName": "carbonMonoxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "nitrogenDioxide",
|
||||
"columnName": "nitrogenDioxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "sulphurDioxide",
|
||||
"columnName": "sulphurDioxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "ozone",
|
||||
"columnName": "ozone",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": true,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_air_quality_hourly_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_air_quality_hourly_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'fd66b7531bfe72f6bcac04b8fe26dc9e')"
|
||||
]
|
||||
}
|
||||
}
|
||||
+863
@@ -0,0 +1,863 @@
|
||||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 47,
|
||||
"identityHash": "fd66b7531bfe72f6bcac04b8fe26dc9e",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "weather_locations",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `country` TEXT NOT NULL, `lat` REAL NOT NULL, `lon` REAL NOT NULL, `timezone` TEXT NOT NULL, `source` TEXT NOT NULL, `state` TEXT, `isFavorite` INTEGER NOT NULL, `isPinned` INTEGER NOT NULL, `countryCode` TEXT, `isDefault` INTEGER NOT NULL, `isDeviceLocation` INTEGER NOT NULL, `alertSource` TEXT NOT NULL, `airQualitySource` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "country",
|
||||
"columnName": "country",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lat",
|
||||
"columnName": "lat",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lon",
|
||||
"columnName": "lon",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "timezone",
|
||||
"columnName": "timezone",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "source",
|
||||
"columnName": "source",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "state",
|
||||
"columnName": "state",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "isFavorite",
|
||||
"columnName": "isFavorite",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isPinned",
|
||||
"columnName": "isPinned",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "countryCode",
|
||||
"columnName": "countryCode",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "isDefault",
|
||||
"columnName": "isDefault",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isDeviceLocation",
|
||||
"columnName": "isDeviceLocation",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "alertSource",
|
||||
"columnName": "alertSource",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "airQualitySource",
|
||||
"columnName": "airQualitySource",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "weather_current",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `temperature` REAL, `humidity` REAL NOT NULL, `windSpeed` REAL, `windDirection` TEXT, `pressureMsl` REAL, `visibility` INTEGER, `cloudCover` REAL, `uvIndex` REAL, `weatherCondition` TEXT NOT NULL, `feelsLike` REAL, `time` INTEGER NOT NULL, `dewPoint` REAL, `utcOffsetSeconds` INTEGER, `lastUpdatedInMilli` INTEGER NOT NULL, PRIMARY KEY(`locationId`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperature",
|
||||
"columnName": "temperature",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "humidity",
|
||||
"columnName": "humidity",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "windSpeed",
|
||||
"columnName": "windSpeed",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windDirection",
|
||||
"columnName": "windDirection",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureMsl",
|
||||
"columnName": "pressureMsl",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "cloudCover",
|
||||
"columnName": "cloudCover",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "uvIndex",
|
||||
"columnName": "uvIndex",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "weatherCondition",
|
||||
"columnName": "weatherCondition",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "feelsLike",
|
||||
"columnName": "feelsLike",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dewPoint",
|
||||
"columnName": "dewPoint",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "utcOffsetSeconds",
|
||||
"columnName": "utcOffsetSeconds",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdatedInMilli",
|
||||
"columnName": "lastUpdatedInMilli",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_weather_current_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_weather_current_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "weather_hourly",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `temperature` REAL, `windSpeed` REAL, `windDirection` TEXT, `rain` REAL NOT NULL, `snowfall` REAL, `uvIndex` REAL, `weatherCondition` TEXT NOT NULL, `pressureMsl` REAL, `visibility` INTEGER, `humidity` REAL, `dewPoint` REAL, `time` INTEGER NOT NULL, `precipitationProbability` INTEGER, PRIMARY KEY(`locationId`, `time`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperature",
|
||||
"columnName": "temperature",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windSpeed",
|
||||
"columnName": "windSpeed",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windDirection",
|
||||
"columnName": "windDirection",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "rain",
|
||||
"columnName": "rain",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "snowfall",
|
||||
"columnName": "snowfall",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "uvIndex",
|
||||
"columnName": "uvIndex",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "weatherCondition",
|
||||
"columnName": "weatherCondition",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureMsl",
|
||||
"columnName": "pressureMsl",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "humidity",
|
||||
"columnName": "humidity",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "dewPoint",
|
||||
"columnName": "dewPoint",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "precipitationProbability",
|
||||
"columnName": "precipitationProbability",
|
||||
"affinity": "INTEGER"
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId",
|
||||
"time"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_weather_hourly_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_weather_hourly_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "weather_daily",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `temperatureMin` REAL, `temperatureMax` REAL, `windSpeed` REAL, `windDirection` TEXT, `rainSum` REAL NOT NULL, `snowfallSum` REAL, `uvIndexMax` REAL, `weatherCondition` TEXT NOT NULL, `time` INTEGER NOT NULL, `precipitationProbabilityMax` INTEGER, `pressureMsl` REAL, `visibility` INTEGER, `humidity` REAL, `dewPoint` REAL, `sunrise` INTEGER NOT NULL, `sunset` INTEGER NOT NULL, `moonrise` INTEGER NOT NULL, `moonset` INTEGER NOT NULL, `moonPhase` TEXT NOT NULL, `dawn` INTEGER NOT NULL, `dusk` INTEGER NOT NULL, PRIMARY KEY(`locationId`, `time`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperatureMin",
|
||||
"columnName": "temperatureMin",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperatureMax",
|
||||
"columnName": "temperatureMax",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windSpeed",
|
||||
"columnName": "windSpeed",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windDirection",
|
||||
"columnName": "windDirection",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "rainSum",
|
||||
"columnName": "rainSum",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "snowfallSum",
|
||||
"columnName": "snowfallSum",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "uvIndexMax",
|
||||
"columnName": "uvIndexMax",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "weatherCondition",
|
||||
"columnName": "weatherCondition",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "precipitationProbabilityMax",
|
||||
"columnName": "precipitationProbabilityMax",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureMsl",
|
||||
"columnName": "pressureMsl",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "humidity",
|
||||
"columnName": "humidity",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "dewPoint",
|
||||
"columnName": "dewPoint",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "sunrise",
|
||||
"columnName": "sunrise",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "sunset",
|
||||
"columnName": "sunset",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "moonrise",
|
||||
"columnName": "moonrise",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "moonset",
|
||||
"columnName": "moonset",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "moonPhase",
|
||||
"columnName": "moonPhase",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dawn",
|
||||
"columnName": "dawn",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dusk",
|
||||
"columnName": "dusk",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId",
|
||||
"time"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_weather_daily_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_weather_daily_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "weather_units",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `tempUnit` TEXT NOT NULL, `windUnit` TEXT NOT NULL, `distanceUnit` TEXT NOT NULL, `pressureUnit` TEXT NOT NULL, `precipitationUnit` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "tempUnit",
|
||||
"columnName": "tempUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "windUnit",
|
||||
"columnName": "windUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "distanceUnit",
|
||||
"columnName": "distanceUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureUnit",
|
||||
"columnName": "pressureUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "precipitationUnit",
|
||||
"columnName": "precipitationUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "weather_blocks",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `isDaily` INTEGER NOT NULL, `type` TEXT NOT NULL, `isHidden` INTEGER NOT NULL, `position` INTEGER NOT NULL)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isDaily",
|
||||
"columnName": "isDaily",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "type",
|
||||
"columnName": "type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isHidden",
|
||||
"columnName": "isHidden",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "position",
|
||||
"columnName": "position",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": true,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "air_quality_current",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `usAqi` INTEGER, `pm10` REAL, `pm25` REAL, `carbonMonoxide` REAL, `nitrogenDioxide` REAL, `sulphurDioxide` REAL, `ozone` REAL, `lastUpdatedInMilli` INTEGER NOT NULL, PRIMARY KEY(`locationId`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "usAqi",
|
||||
"columnName": "usAqi",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pm10",
|
||||
"columnName": "pm10",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pm25",
|
||||
"columnName": "pm25",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "carbonMonoxide",
|
||||
"columnName": "carbonMonoxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "nitrogenDioxide",
|
||||
"columnName": "nitrogenDioxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "sulphurDioxide",
|
||||
"columnName": "sulphurDioxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "ozone",
|
||||
"columnName": "ozone",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdatedInMilli",
|
||||
"columnName": "lastUpdatedInMilli",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_air_quality_current_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_air_quality_current_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "nws_location_gridpoints",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `officeId` TEXT NOT NULL, `gridX` INTEGER NOT NULL, `gridY` INTEGER NOT NULL, `stationIdentifier` TEXT NOT NULL, `lastUpdatedMilli` INTEGER NOT NULL, PRIMARY KEY(`locationId`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "officeId",
|
||||
"columnName": "officeId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "gridX",
|
||||
"columnName": "gridX",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "gridY",
|
||||
"columnName": "gridY",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "stationIdentifier",
|
||||
"columnName": "stationIdentifier",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdatedMilli",
|
||||
"columnName": "lastUpdatedMilli",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_nws_location_gridpoints_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_nws_location_gridpoints_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "github",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `currentTag` TEXT NOT NULL, `lastFetchedTag` TEXT NOT NULL, `lastFetchedTime` INTEGER NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "currentTag",
|
||||
"columnName": "currentTag",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastFetchedTag",
|
||||
"columnName": "lastFetchedTag",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastFetchedTime",
|
||||
"columnName": "lastFetchedTime",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "air_quality_hourly",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `locationId` TEXT NOT NULL, `pm10` REAL, `pm25` REAL, `carbonMonoxide` REAL, `nitrogenDioxide` REAL, `sulphurDioxide` REAL, `ozone` REAL, `time` INTEGER NOT NULL, FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pm10",
|
||||
"columnName": "pm10",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pm25",
|
||||
"columnName": "pm25",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "carbonMonoxide",
|
||||
"columnName": "carbonMonoxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "nitrogenDioxide",
|
||||
"columnName": "nitrogenDioxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "sulphurDioxide",
|
||||
"columnName": "sulphurDioxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "ozone",
|
||||
"columnName": "ozone",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": true,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_air_quality_hourly_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_air_quality_hourly_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'fd66b7531bfe72f6bcac04b8fe26dc9e')"
|
||||
]
|
||||
}
|
||||
}
|
||||
+868
@@ -0,0 +1,868 @@
|
||||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 48,
|
||||
"identityHash": "5ca7c9b34ef5941f3d7515379d9646f9",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "weather_locations",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `country` TEXT NOT NULL, `lat` REAL NOT NULL, `lon` REAL NOT NULL, `timezone` TEXT NOT NULL, `source` TEXT NOT NULL, `state` TEXT, `isFavorite` INTEGER NOT NULL, `isPinned` INTEGER NOT NULL, `countryCode` TEXT, `isDefault` INTEGER NOT NULL, `isDeviceLocation` INTEGER NOT NULL, `alertSource` TEXT NOT NULL, `airQualitySource` TEXT NOT NULL, `customName` TEXT, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "country",
|
||||
"columnName": "country",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lat",
|
||||
"columnName": "lat",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lon",
|
||||
"columnName": "lon",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "timezone",
|
||||
"columnName": "timezone",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "source",
|
||||
"columnName": "source",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "state",
|
||||
"columnName": "state",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "isFavorite",
|
||||
"columnName": "isFavorite",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isPinned",
|
||||
"columnName": "isPinned",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "countryCode",
|
||||
"columnName": "countryCode",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "isDefault",
|
||||
"columnName": "isDefault",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isDeviceLocation",
|
||||
"columnName": "isDeviceLocation",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "alertSource",
|
||||
"columnName": "alertSource",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "airQualitySource",
|
||||
"columnName": "airQualitySource",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "customName",
|
||||
"columnName": "customName",
|
||||
"affinity": "TEXT"
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "weather_current",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `temperature` REAL, `humidity` REAL NOT NULL, `windSpeed` REAL, `windDirection` TEXT, `pressureMsl` REAL, `visibility` INTEGER, `cloudCover` REAL, `uvIndex` REAL, `weatherCondition` TEXT NOT NULL, `feelsLike` REAL, `time` INTEGER NOT NULL, `dewPoint` REAL, `utcOffsetSeconds` INTEGER, `lastUpdatedInMilli` INTEGER NOT NULL, PRIMARY KEY(`locationId`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperature",
|
||||
"columnName": "temperature",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "humidity",
|
||||
"columnName": "humidity",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "windSpeed",
|
||||
"columnName": "windSpeed",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windDirection",
|
||||
"columnName": "windDirection",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureMsl",
|
||||
"columnName": "pressureMsl",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "cloudCover",
|
||||
"columnName": "cloudCover",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "uvIndex",
|
||||
"columnName": "uvIndex",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "weatherCondition",
|
||||
"columnName": "weatherCondition",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "feelsLike",
|
||||
"columnName": "feelsLike",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dewPoint",
|
||||
"columnName": "dewPoint",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "utcOffsetSeconds",
|
||||
"columnName": "utcOffsetSeconds",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdatedInMilli",
|
||||
"columnName": "lastUpdatedInMilli",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_weather_current_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_weather_current_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "weather_hourly",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `temperature` REAL, `windSpeed` REAL, `windDirection` TEXT, `rain` REAL NOT NULL, `snowfall` REAL, `uvIndex` REAL, `weatherCondition` TEXT NOT NULL, `pressureMsl` REAL, `visibility` INTEGER, `humidity` REAL, `dewPoint` REAL, `time` INTEGER NOT NULL, `precipitationProbability` INTEGER, PRIMARY KEY(`locationId`, `time`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperature",
|
||||
"columnName": "temperature",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windSpeed",
|
||||
"columnName": "windSpeed",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windDirection",
|
||||
"columnName": "windDirection",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "rain",
|
||||
"columnName": "rain",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "snowfall",
|
||||
"columnName": "snowfall",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "uvIndex",
|
||||
"columnName": "uvIndex",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "weatherCondition",
|
||||
"columnName": "weatherCondition",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureMsl",
|
||||
"columnName": "pressureMsl",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "humidity",
|
||||
"columnName": "humidity",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "dewPoint",
|
||||
"columnName": "dewPoint",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "precipitationProbability",
|
||||
"columnName": "precipitationProbability",
|
||||
"affinity": "INTEGER"
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId",
|
||||
"time"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_weather_hourly_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_weather_hourly_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "weather_daily",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `temperatureMin` REAL, `temperatureMax` REAL, `windSpeed` REAL, `windDirection` TEXT, `rainSum` REAL NOT NULL, `snowfallSum` REAL, `uvIndexMax` REAL, `weatherCondition` TEXT NOT NULL, `time` INTEGER NOT NULL, `precipitationProbabilityMax` INTEGER, `pressureMsl` REAL, `visibility` INTEGER, `humidity` REAL, `dewPoint` REAL, `sunrise` INTEGER NOT NULL, `sunset` INTEGER NOT NULL, `moonrise` INTEGER NOT NULL, `moonset` INTEGER NOT NULL, `moonPhase` TEXT NOT NULL, `dawn` INTEGER NOT NULL, `dusk` INTEGER NOT NULL, PRIMARY KEY(`locationId`, `time`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperatureMin",
|
||||
"columnName": "temperatureMin",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperatureMax",
|
||||
"columnName": "temperatureMax",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windSpeed",
|
||||
"columnName": "windSpeed",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windDirection",
|
||||
"columnName": "windDirection",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "rainSum",
|
||||
"columnName": "rainSum",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "snowfallSum",
|
||||
"columnName": "snowfallSum",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "uvIndexMax",
|
||||
"columnName": "uvIndexMax",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "weatherCondition",
|
||||
"columnName": "weatherCondition",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "precipitationProbabilityMax",
|
||||
"columnName": "precipitationProbabilityMax",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureMsl",
|
||||
"columnName": "pressureMsl",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "humidity",
|
||||
"columnName": "humidity",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "dewPoint",
|
||||
"columnName": "dewPoint",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "sunrise",
|
||||
"columnName": "sunrise",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "sunset",
|
||||
"columnName": "sunset",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "moonrise",
|
||||
"columnName": "moonrise",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "moonset",
|
||||
"columnName": "moonset",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "moonPhase",
|
||||
"columnName": "moonPhase",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dawn",
|
||||
"columnName": "dawn",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dusk",
|
||||
"columnName": "dusk",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId",
|
||||
"time"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_weather_daily_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_weather_daily_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "weather_units",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `tempUnit` TEXT NOT NULL, `windUnit` TEXT NOT NULL, `distanceUnit` TEXT NOT NULL, `pressureUnit` TEXT NOT NULL, `precipitationUnit` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "tempUnit",
|
||||
"columnName": "tempUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "windUnit",
|
||||
"columnName": "windUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "distanceUnit",
|
||||
"columnName": "distanceUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureUnit",
|
||||
"columnName": "pressureUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "precipitationUnit",
|
||||
"columnName": "precipitationUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "weather_blocks",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `isDaily` INTEGER NOT NULL, `type` TEXT NOT NULL, `isHidden` INTEGER NOT NULL, `position` INTEGER NOT NULL)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isDaily",
|
||||
"columnName": "isDaily",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "type",
|
||||
"columnName": "type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isHidden",
|
||||
"columnName": "isHidden",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "position",
|
||||
"columnName": "position",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": true,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "air_quality_current",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `usAqi` INTEGER, `pm10` REAL, `pm25` REAL, `carbonMonoxide` REAL, `nitrogenDioxide` REAL, `sulphurDioxide` REAL, `ozone` REAL, `lastUpdatedInMilli` INTEGER NOT NULL, PRIMARY KEY(`locationId`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "usAqi",
|
||||
"columnName": "usAqi",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pm10",
|
||||
"columnName": "pm10",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pm25",
|
||||
"columnName": "pm25",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "carbonMonoxide",
|
||||
"columnName": "carbonMonoxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "nitrogenDioxide",
|
||||
"columnName": "nitrogenDioxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "sulphurDioxide",
|
||||
"columnName": "sulphurDioxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "ozone",
|
||||
"columnName": "ozone",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdatedInMilli",
|
||||
"columnName": "lastUpdatedInMilli",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_air_quality_current_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_air_quality_current_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "nws_location_gridpoints",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `officeId` TEXT NOT NULL, `gridX` INTEGER NOT NULL, `gridY` INTEGER NOT NULL, `stationIdentifier` TEXT NOT NULL, `lastUpdatedMilli` INTEGER NOT NULL, PRIMARY KEY(`locationId`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "officeId",
|
||||
"columnName": "officeId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "gridX",
|
||||
"columnName": "gridX",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "gridY",
|
||||
"columnName": "gridY",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "stationIdentifier",
|
||||
"columnName": "stationIdentifier",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdatedMilli",
|
||||
"columnName": "lastUpdatedMilli",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_nws_location_gridpoints_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_nws_location_gridpoints_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "github",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `currentTag` TEXT NOT NULL, `lastFetchedTag` TEXT NOT NULL, `lastFetchedTime` INTEGER NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "currentTag",
|
||||
"columnName": "currentTag",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastFetchedTag",
|
||||
"columnName": "lastFetchedTag",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastFetchedTime",
|
||||
"columnName": "lastFetchedTime",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "air_quality_hourly",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `locationId` TEXT NOT NULL, `pm10` REAL, `pm25` REAL, `carbonMonoxide` REAL, `nitrogenDioxide` REAL, `sulphurDioxide` REAL, `ozone` REAL, `time` INTEGER NOT NULL, FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pm10",
|
||||
"columnName": "pm10",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pm25",
|
||||
"columnName": "pm25",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "carbonMonoxide",
|
||||
"columnName": "carbonMonoxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "nitrogenDioxide",
|
||||
"columnName": "nitrogenDioxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "sulphurDioxide",
|
||||
"columnName": "sulphurDioxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "ozone",
|
||||
"columnName": "ozone",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": true,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_air_quality_hourly_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_air_quality_hourly_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '5ca7c9b34ef5941f3d7515379d9646f9')"
|
||||
]
|
||||
}
|
||||
}
|
||||
+916
@@ -0,0 +1,916 @@
|
||||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 49,
|
||||
"identityHash": "41f3af0cd4a758a20290098071993b9c",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "weather_locations",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `country` TEXT NOT NULL, `lat` REAL NOT NULL, `lon` REAL NOT NULL, `timezone` TEXT NOT NULL, `source` TEXT NOT NULL, `state` TEXT, `isFavorite` INTEGER NOT NULL, `isPinned` INTEGER NOT NULL, `countryCode` TEXT, `isDefault` INTEGER NOT NULL, `isDeviceLocation` INTEGER NOT NULL, `alertSource` TEXT NOT NULL, `airQualitySource` TEXT NOT NULL, `customName` TEXT, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "country",
|
||||
"columnName": "country",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lat",
|
||||
"columnName": "lat",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lon",
|
||||
"columnName": "lon",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "timezone",
|
||||
"columnName": "timezone",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "source",
|
||||
"columnName": "source",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "state",
|
||||
"columnName": "state",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "isFavorite",
|
||||
"columnName": "isFavorite",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isPinned",
|
||||
"columnName": "isPinned",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "countryCode",
|
||||
"columnName": "countryCode",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "isDefault",
|
||||
"columnName": "isDefault",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isDeviceLocation",
|
||||
"columnName": "isDeviceLocation",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "alertSource",
|
||||
"columnName": "alertSource",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "airQualitySource",
|
||||
"columnName": "airQualitySource",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "customName",
|
||||
"columnName": "customName",
|
||||
"affinity": "TEXT"
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "weather_current",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `temperature` REAL, `humidity` REAL NOT NULL, `windSpeed` REAL, `windDirection` TEXT, `pressureMsl` REAL, `visibility` INTEGER, `cloudCover` REAL, `uvIndex` REAL, `weatherCondition` TEXT NOT NULL, `feelsLike` REAL, `time` INTEGER NOT NULL, `dewPoint` REAL, `utcOffsetSeconds` INTEGER, `lastUpdatedInMilli` INTEGER NOT NULL, PRIMARY KEY(`locationId`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperature",
|
||||
"columnName": "temperature",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "humidity",
|
||||
"columnName": "humidity",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "windSpeed",
|
||||
"columnName": "windSpeed",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windDirection",
|
||||
"columnName": "windDirection",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureMsl",
|
||||
"columnName": "pressureMsl",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "cloudCover",
|
||||
"columnName": "cloudCover",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "uvIndex",
|
||||
"columnName": "uvIndex",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "weatherCondition",
|
||||
"columnName": "weatherCondition",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "feelsLike",
|
||||
"columnName": "feelsLike",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dewPoint",
|
||||
"columnName": "dewPoint",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "utcOffsetSeconds",
|
||||
"columnName": "utcOffsetSeconds",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdatedInMilli",
|
||||
"columnName": "lastUpdatedInMilli",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_weather_current_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_weather_current_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "weather_hourly",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `temperature` REAL, `windSpeed` REAL, `windDirection` TEXT, `rain` REAL NOT NULL, `snowfall` REAL, `uvIndex` REAL, `weatherCondition` TEXT NOT NULL, `pressureMsl` REAL, `visibility` INTEGER, `humidity` REAL, `dewPoint` REAL, `time` INTEGER NOT NULL, `precipitationProbability` INTEGER, PRIMARY KEY(`locationId`, `time`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperature",
|
||||
"columnName": "temperature",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windSpeed",
|
||||
"columnName": "windSpeed",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windDirection",
|
||||
"columnName": "windDirection",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "rain",
|
||||
"columnName": "rain",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "snowfall",
|
||||
"columnName": "snowfall",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "uvIndex",
|
||||
"columnName": "uvIndex",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "weatherCondition",
|
||||
"columnName": "weatherCondition",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureMsl",
|
||||
"columnName": "pressureMsl",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "humidity",
|
||||
"columnName": "humidity",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "dewPoint",
|
||||
"columnName": "dewPoint",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "precipitationProbability",
|
||||
"columnName": "precipitationProbability",
|
||||
"affinity": "INTEGER"
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId",
|
||||
"time"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_weather_hourly_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_weather_hourly_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "weather_daily",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `temperatureMin` REAL, `temperatureMax` REAL, `windSpeed` REAL, `windDirection` TEXT, `rainSum` REAL NOT NULL, `snowfallSum` REAL, `uvIndexMax` REAL, `weatherCondition` TEXT NOT NULL, `time` INTEGER NOT NULL, `precipitationProbabilityMax` INTEGER, `pressureMsl` REAL, `visibility` INTEGER, `humidity` REAL, `dewPoint` REAL, `sunrise` INTEGER NOT NULL, `sunset` INTEGER NOT NULL, `moonrise` INTEGER NOT NULL, `moonset` INTEGER NOT NULL, `moonPhase` TEXT NOT NULL, `dawn` INTEGER NOT NULL, `dusk` INTEGER NOT NULL, PRIMARY KEY(`locationId`, `time`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperatureMin",
|
||||
"columnName": "temperatureMin",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperatureMax",
|
||||
"columnName": "temperatureMax",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windSpeed",
|
||||
"columnName": "windSpeed",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "windDirection",
|
||||
"columnName": "windDirection",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "rainSum",
|
||||
"columnName": "rainSum",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "snowfallSum",
|
||||
"columnName": "snowfallSum",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "uvIndexMax",
|
||||
"columnName": "uvIndexMax",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "weatherCondition",
|
||||
"columnName": "weatherCondition",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "precipitationProbabilityMax",
|
||||
"columnName": "precipitationProbabilityMax",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureMsl",
|
||||
"columnName": "pressureMsl",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "humidity",
|
||||
"columnName": "humidity",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "dewPoint",
|
||||
"columnName": "dewPoint",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "sunrise",
|
||||
"columnName": "sunrise",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "sunset",
|
||||
"columnName": "sunset",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "moonrise",
|
||||
"columnName": "moonrise",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "moonset",
|
||||
"columnName": "moonset",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "moonPhase",
|
||||
"columnName": "moonPhase",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dawn",
|
||||
"columnName": "dawn",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dusk",
|
||||
"columnName": "dusk",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId",
|
||||
"time"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_weather_daily_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_weather_daily_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "weather_units",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `tempUnit` TEXT NOT NULL, `windUnit` TEXT NOT NULL, `distanceUnit` TEXT NOT NULL, `pressureUnit` TEXT NOT NULL, `precipitationUnit` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "tempUnit",
|
||||
"columnName": "tempUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "windUnit",
|
||||
"columnName": "windUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "distanceUnit",
|
||||
"columnName": "distanceUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressureUnit",
|
||||
"columnName": "pressureUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "precipitationUnit",
|
||||
"columnName": "precipitationUnit",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "weather_blocks",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `isDaily` INTEGER NOT NULL, `type` TEXT NOT NULL, `isHidden` INTEGER NOT NULL, `position` INTEGER NOT NULL)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isDaily",
|
||||
"columnName": "isDaily",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "type",
|
||||
"columnName": "type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isHidden",
|
||||
"columnName": "isHidden",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "position",
|
||||
"columnName": "position",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": true,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "air_quality_current",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `usAqi` INTEGER, `pm10` REAL, `pm25` REAL, `carbonMonoxide` REAL, `nitrogenDioxide` REAL, `sulphurDioxide` REAL, `ozone` REAL, `lastUpdatedInMilli` INTEGER NOT NULL, PRIMARY KEY(`locationId`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "usAqi",
|
||||
"columnName": "usAqi",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pm10",
|
||||
"columnName": "pm10",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pm25",
|
||||
"columnName": "pm25",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "carbonMonoxide",
|
||||
"columnName": "carbonMonoxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "nitrogenDioxide",
|
||||
"columnName": "nitrogenDioxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "sulphurDioxide",
|
||||
"columnName": "sulphurDioxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "ozone",
|
||||
"columnName": "ozone",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdatedInMilli",
|
||||
"columnName": "lastUpdatedInMilli",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_air_quality_current_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_air_quality_current_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "nws_location_gridpoints",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `officeId` TEXT NOT NULL, `gridX` INTEGER NOT NULL, `gridY` INTEGER NOT NULL, `stationIdentifier` TEXT NOT NULL, `lastUpdatedMilli` INTEGER NOT NULL, PRIMARY KEY(`locationId`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "officeId",
|
||||
"columnName": "officeId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "gridX",
|
||||
"columnName": "gridX",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "gridY",
|
||||
"columnName": "gridY",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "stationIdentifier",
|
||||
"columnName": "stationIdentifier",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdatedMilli",
|
||||
"columnName": "lastUpdatedMilli",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_nws_location_gridpoints_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_nws_location_gridpoints_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "github",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `currentTag` TEXT NOT NULL, `lastFetchedTag` TEXT NOT NULL, `lastFetchedTime` INTEGER NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "currentTag",
|
||||
"columnName": "currentTag",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastFetchedTag",
|
||||
"columnName": "lastFetchedTag",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastFetchedTime",
|
||||
"columnName": "lastFetchedTime",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "air_quality_hourly",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `locationId` TEXT NOT NULL, `pm10` REAL, `pm25` REAL, `carbonMonoxide` REAL, `nitrogenDioxide` REAL, `sulphurDioxide` REAL, `ozone` REAL, `time` INTEGER NOT NULL, FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pm10",
|
||||
"columnName": "pm10",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pm25",
|
||||
"columnName": "pm25",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "carbonMonoxide",
|
||||
"columnName": "carbonMonoxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "nitrogenDioxide",
|
||||
"columnName": "nitrogenDioxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "sulphurDioxide",
|
||||
"columnName": "sulphurDioxide",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "ozone",
|
||||
"columnName": "ozone",
|
||||
"affinity": "REAL"
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": true,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_air_quality_hourly_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_air_quality_hourly_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "accu_locations",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` TEXT NOT NULL, `cityKey` TEXT NOT NULL, PRIMARY KEY(`locationId`), FOREIGN KEY(`locationId`) REFERENCES `weather_locations`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "locationId",
|
||||
"columnName": "locationId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "cityKey",
|
||||
"columnName": "cityKey",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_accu_locations_locationId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"locationId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_accu_locations_locationId` ON `${TABLE_NAME}` (`locationId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "weather_locations",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"locationId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '41f3af0cd4a758a20290098071993b9c')"
|
||||
]
|
||||
}
|
||||
}
|
||||
+1004
File diff suppressed because it is too large.
Load diff
+1002
File diff suppressed because it is too large.
Load diff
+1002
File diff suppressed because it is too large.
Load diff
+1009
File diff suppressed because it is too large.
Load diff
+1014
File diff suppressed because it is too large.
Load diff
+1048
File diff suppressed because it is too large.
Load diff
+1048
File diff suppressed because it is too large.
Load diff
+1048
File diff suppressed because it is too large.
Load diff
+1047
File diff suppressed because it is too large.
Load diff
+1041
File diff suppressed because it is too large.
Load diff
+1035
File diff suppressed because it is too large.
Load diff
@@ -6,9 +6,9 @@
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
||||
|
||||
<application
|
||||
android:name=".WeatherMasterApplication"
|
||||
@@ -31,7 +31,13 @@
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".widgets.config.WidgetConfigActivity"
|
||||
android:theme="@style/Theme.WeatherMaster"
|
||||
android:exported="true" />
|
||||
|
||||
<service
|
||||
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
|
||||
@@ -54,10 +60,14 @@
|
||||
tools:node="remove" />
|
||||
</provider>
|
||||
|
||||
<receiver
|
||||
android:name=".feature.notifications.scheduled.ScheduledNotification"
|
||||
android:enabled="true" />
|
||||
|
||||
<!--WIDGETS-->
|
||||
<receiver
|
||||
android:name=".widgets.weather.WeatherWidgetReceiver"
|
||||
android:label="Weather"
|
||||
android:label="Weather 1"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
@@ -71,7 +81,7 @@
|
||||
|
||||
<receiver
|
||||
android:name=".widgets.pill.WidgetPillReceiver"
|
||||
android:label="Weather"
|
||||
android:label="Pill"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
@@ -85,7 +95,7 @@
|
||||
|
||||
<receiver
|
||||
android:name=".widgets.summary.SummaryWidgetReceiver"
|
||||
android:label="Summary"
|
||||
android:label="Day Summary"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
@@ -96,6 +106,125 @@
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/summary_widget_info" />
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name=".widgets.weatherhorizontal.WeatherHorizontalWidgetReceiver"
|
||||
android:label="Weather 2"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/weather_widget_horizontal_info" />
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name=".widgets.glance.GlanceWidgetReceiver"
|
||||
android:label="Glance"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/glance_widget_info" />
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name=".widgets.weather3.Weather3WidgetReceiver"
|
||||
android:label="Weather 3"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/weather3_widget_info" />
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name=".widgets.weather4.Weather4WidgerReceiver"
|
||||
android:label="Weather 4"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/weather4_widget_info" />
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name=".widgets.hourly.WidgetHourlyReceiver"
|
||||
android:label="Hourly"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/hourly_widget_info" />
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name=".widgets.uvindex.UvIndexWidgetReceiver"
|
||||
android:label="UV index"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/uv_index_widget_info" />
|
||||
</receiver>
|
||||
|
||||
|
||||
<receiver
|
||||
android:name=".widgets.weather5.Weather5WidgetReceiver"
|
||||
android:label="Weather 5"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/weather5_widget_info" />
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name=".widgets.froggy.FroggyWidgetReceiver"
|
||||
android:label="Froggy"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/froggy_widget_info" />
|
||||
</receiver>
|
||||
|
||||
</application>
|
||||
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="nodomain.freeyourgadget.gadgetbridge.ACTION_GENERIC_WEATHER" />
|
||||
</intent>
|
||||
</queries>
|
||||
</manifest>
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"featurecla":"Admin-0 country","scalerank":1,"labelrank":2,"sovereignt":"China","sov_a3":"CH1","adm0_dif":1,"level":2,"type":"Country","tlc":"1","admin":"China","adm0_a3":"CHN","geou_dif":0,"geounit":"China","gu_a3":"CHN","su_dif":0,"subunit":"China","su_a3":"CHN","brk_diff":0,"name":"China","name_long":"China","brk_a3":"CHN","brk_name":"China","brk_group":null,"abbrev":"China","postal":"CN","formal_en":"People's Republic of China","formal_fr":null,"name_ciawf":"China","note_adm0":null,"note_brk":null,"name_sort":"China","name_alt":null,"mapcolor7":4,"mapcolor8":4,"mapcolor9":4,"mapcolor13":3,"pop_est":1397715000,"pop_rank":18,"pop_year":2019,"gdp_md":14342903,"gdp_year":2019,"economy":"3. Emerging region: BRIC","income_grp":"3. Upper middle income","fips_10":"CH","iso_a2":"CN","iso_a2_eh":"CN","iso_a3":"CHN","iso_a3_eh":"CHN","iso_n3":"156","iso_n3_eh":"156","un_a3":"156","wb_a2":"CN","wb_a3":"CHN","woe_id":23424781,"woe_id_eh":23424781,"woe_note":"Exact WOE match as country","adm0_iso":"CHN","adm0_diff":null,"adm0_tlc":"CHN","adm0_a3_us":"CHN","adm0_a3_fr":"CHN","adm0_a3_ru":"CHN","adm0_a3_es":"CHN","adm0_a3_cn":"CHN","adm0_a3_tw":"TWN","adm0_a3_in":"CHN","adm0_a3_np":"CHN","adm0_a3_pk":"CHN","adm0_a3_de":"CHN","adm0_a3_gb":"CHN","adm0_a3_br":"CHN","adm0_a3_il":"CHN","adm0_a3_ps":"CHN","adm0_a3_sa":"CHN","adm0_a3_eg":"CHN","adm0_a3_ma":"CHN","adm0_a3_pt":"CHN","adm0_a3_ar":"CHN","adm0_a3_jp":"CHN","adm0_a3_ko":"CHN","adm0_a3_vn":"CHN","adm0_a3_tr":"CHN","adm0_a3_id":"CHN","adm0_a3_pl":"CHN","adm0_a3_gr":"CHN","adm0_a3_it":"CHN","adm0_a3_nl":"CHN","adm0_a3_se":"CHN","adm0_a3_bd":"CHN","adm0_a3_ua":"CHN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Eastern Asia","region_wb":"East Asia & Pacific","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1,"min_zoom":0,"min_label":1.7,"max_label":5.7,"label_x":106.337289,"label_y":32.498178,"ne_id":1159320471,"wikidataid":"Q148","name_ar":"الصين","name_bn":"গণচীন","name_de":"Volksrepublik China","name_en":"People's Republic of China","name_es":"China","name_fa":"جمهوری خلق چین","name_fr":"République populaire de Chine","name_el":"Λαϊκή Δημοκρατία της Κίνας","name_he":"הרפובליקה העממית של סין","name_hi":"चीनी जनवादी गणराज्य","name_hu":"Kína","name_id":"Republik Rakyat Tiongkok","name_it":"Cina","name_ja":"中華人民共和国","name_ko":"중화인민공화국","name_nl":"Volksrepubliek China","name_pl":"Chińska Republika Ludowa","name_pt":"China","name_ru":"Китайская Народная Республика","name_sv":"Kina","name_tr":"Çin Halk Cumhuriyeti","name_uk":"Китайська Народна Республіка","name_ur":"عوامی جمہوریہ چین","name_vi":"Trung Quốc","name_zh":"中华人民共和国","name_zht":"中華人民共和國","fclass_iso":"Admin-0 country","tlc_diff":null,"fclass_tlc":"Admin-0 country","fclass_us":null,"fclass_fr":null,"fclass_ru":null,"fclass_es":null,"fclass_cn":null,"fclass_tw":"Unrecognized","fclass_in":null,"fclass_np":null,"fclass_pk":null,"fclass_de":null,"fclass_gb":null,"fclass_br":null,"fclass_il":null,"fclass_ps":null,"fclass_sa":null,"fclass_eg":null,"fclass_ma":null,"fclass_pt":null,"fclass_ar":null,"fclass_jp":null,"fclass_ko":null,"fclass_vn":null,"fclass_tr":null,"fclass_id":null,"fclass_pl":null,"fclass_gr":null,"fclass_it":null,"fclass_nl":null,"fclass_se":null,"fclass_bd":null,"fclass_ua":null,"filename":"CHN.geojson"},"geometry":{"type":"MultiPolygon","coordinates":[[[[109.47520958866365,18.197700913968575],[108.65520796105616,18.507681993071387],[108.62621748254044,19.367887885001906],[109.11905561730804,19.821038519769345],[110.21159874882281,20.101253973872033],[110.78655073450221,20.077534491450052],[111.01005130416458,19.69592987719072],[110.57064660038677,19.25587921800927],[110.33918786015147,18.678395087147592],[109.47520958866365,18.197700913968575]]],[[[80.2599902688853,42.34999929459906],[80.1801501809943,42.92006785742694],[80.86620649610126,43.18036204688101],[79.96610639844141,44.91751699480463],[81.9470707539181,45.31702749285312],[82.45892581576906,45.539649563166506],[83.18048383986047,47.33003123635086],[85.16429039911324,47.0009557155161],[85.72048383987067,47.452969468773105],[85.7682328633083,48.45575063739699],[86.59877648310336,48.549181626980626],[87.35997033076265,49.21498078062912],[87.75126427607671,49.297197984405486],[88.01383222855173,48.599462795600616],[88.85429772334676,48.069081732772965],[90.28082563676392,47.69354909930793],[90.97080936072501,46.88814606382293],[90.58576826371828,45.71971609148753],[90.9455395853343,45.28607330991028],[92.13389082231822,45.11507599545646],[93.4807336771413,44.975472113619965],[94.68892866412533,44.35233185482842],[95.30687544147153,44.24133087826547],[95.76245486855669,43.319449164394605],[96.Line truncated
|
||||
@@ -1,37 +1,74 @@
|
||||
package com.pranshulgg.weather_master_app
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.SystemBarStyle
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||
import androidx.work.ExistingWorkPolicy
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import com.pranshulgg.weather_master_app.core.prefs.AppPrefs
|
||||
import com.pranshulgg.weather_master_app.core.prefs.AppPrefs.initPrefs
|
||||
import com.pranshulgg.weather_master_app.core.prefs.helper.PreferencesHelper
|
||||
import com.pranshulgg.weather_master_app.core.ui.theme.isThemeDark
|
||||
import com.pranshulgg.weather_master_app.data.provider.devicelocation.GetDeviceLocation
|
||||
import com.pranshulgg.weather_master_app.data.store.InitializationStoreState
|
||||
import com.pranshulgg.weather_master_app.data.worker.WeatherWorker
|
||||
import com.pranshulgg.weather_master_app.feature.shared.WeatherViewModel
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import java.util.concurrent.TimeUnit
|
||||
import com.pranshulgg.weather_master_app.data.store.InitializationStore
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class MainActivity : AppCompatActivity() {
|
||||
private val viewModel: WeatherViewModel by viewModels()
|
||||
@Inject
|
||||
lateinit var initializationStore: InitializationStore
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
val splashScreen = installSplashScreen()
|
||||
val startTime = System.currentTimeMillis()
|
||||
|
||||
|
||||
splashScreen.setKeepOnScreenCondition {
|
||||
val initialized = viewModel.uiState.value.isInitialized
|
||||
val initialized = initializationStore.data.value.isInitialized
|
||||
val timedOut = System.currentTimeMillis() - startTime > 5000
|
||||
|
||||
!initialized && !timedOut
|
||||
}
|
||||
initPrefs(this)
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
val theme = PreferencesHelper.getString("app_theme") ?: "Dark"
|
||||
|
||||
val isDark = resolveThemeDark(
|
||||
theme,
|
||||
resources.configuration.uiMode and
|
||||
android.content.res.Configuration.UI_MODE_NIGHT_MASK ==
|
||||
android.content.res.Configuration.UI_MODE_NIGHT_YES
|
||||
)
|
||||
|
||||
enableEdgeToEdge(
|
||||
navigationBarStyle = if (isDark) {
|
||||
SystemBarStyle.dark(Color.TRANSPARENT)
|
||||
} else {
|
||||
SystemBarStyle.light(
|
||||
Color.TRANSPARENT, Color.TRANSPARENT
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
setContent {
|
||||
WeatherMasterApp()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
val locationHelper = GetDeviceLocation()
|
||||
@@ -40,6 +77,19 @@ class MainActivity : AppCompatActivity() {
|
||||
locationHelper.stopUpdates()
|
||||
}
|
||||
|
||||
|
||||
private fun resolveThemeDark(
|
||||
appTheme: String,
|
||||
systemDark: Boolean
|
||||
): Boolean {
|
||||
return when (appTheme) {
|
||||
"Dark" -> true
|
||||
"Light" -> false
|
||||
"System" -> systemDark
|
||||
else -> systemDark
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.pranshulgg.weather_master_app
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
import androidx.compose.material3.SnackbarDuration
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.material3.SnackbarResult
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -40,7 +39,7 @@ fun WeatherMasterApp() {
|
||||
),
|
||||
actionLabel = if (event.actionLabel != null) context.getString(event.actionLabel) else null,
|
||||
withDismissAction = event.actionLabel == null,
|
||||
duration = SnackbarDuration.Short
|
||||
duration = event.duration
|
||||
)
|
||||
|
||||
if (result == SnackbarResult.ActionPerformed) {
|
||||
@@ -71,4 +70,5 @@ fun WeatherMasterApp() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -3,18 +3,13 @@ package com.pranshulgg.weather_master_app
|
||||
import android.app.Application
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import androidx.hilt.work.HiltWorkerFactory
|
||||
import androidx.lifecycle.ProcessLifecycleOwner
|
||||
import dagger.hilt.android.HiltAndroidApp
|
||||
import androidx.work.Configuration
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import com.pranshulgg.weather_master_app.data.worker.AppVisibility
|
||||
import com.pranshulgg.weather_master_app.data.worker.WeatherWorker
|
||||
import com.pranshulgg.weather_master_app.data.worker.notification.WeatherNotificationConfig
|
||||
import java.util.concurrent.TimeUnit
|
||||
import com.pranshulgg.weather_master_app.data.worker.notification.BackgroundUpdateNotificationConfig
|
||||
import com.pranshulgg.weather_master_app.feature.notifications.NotificationChannels
|
||||
import dagger.hilt.android.HiltAndroidApp
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltAndroidApp
|
||||
@@ -40,17 +35,7 @@ class WeatherMasterApplication : Application(), Configuration.Provider {
|
||||
.lifecycle
|
||||
.addObserver(visibilityTracker)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
|
||||
val channel = NotificationChannel(
|
||||
WeatherNotificationConfig.CHANNEL_ID,
|
||||
"WeatherMaster Updates",
|
||||
NotificationManager.IMPORTANCE_HIGH
|
||||
)
|
||||
|
||||
val manager = getSystemService(NotificationManager::class.java)
|
||||
manager.createNotificationChannel(channel)
|
||||
}
|
||||
NotificationChannels.createAll(this)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,41 +1,46 @@
|
||||
package com.pranshulgg.weather_master_app.core.di
|
||||
|
||||
import android.content.Context
|
||||
import com.pranshulgg.weather_master_app.core.managers.ExternalManager
|
||||
import com.pranshulgg.weather_master_app.core.managers.LocationManager
|
||||
import com.pranshulgg.weather_master_app.core.managers.SourceManager
|
||||
import com.pranshulgg.weather_master_app.core.managers.WeatherBlocksManager
|
||||
import com.pranshulgg.weather_master_app.core.managers.WeatherManager
|
||||
import com.pranshulgg.weather_master_app.core.managers.WeatherUnitsManager
|
||||
import com.pranshulgg.weather_master_app.core.managers.requests.PendingRequests
|
||||
import com.pranshulgg.weather_master_app.core.network.github.GithubApi
|
||||
import com.pranshulgg.weather_master_app.core.network.github.GithubRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.address.nominatim.NominatimApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.address.nominatim.json.NominatimRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.airquality.openmeteo.OpenMeteoAqiApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.airquality.openmeteo.OpenMeteoAqiRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.search.geonames.GeoNamesSearchApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.search.geonames.GeoNamesSearchRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.search.geonames.timezone.GeoNamesTimezoneApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.search.geonames.GeoNamesTimezoneRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.search.openmeteo.OpenMeteoSearchApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.search.openmeteo.OpenMeteoSearchRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.metnorway.MetNorwayApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.metnorway.MetNorwayRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.nws.NwsApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.nws.NwsRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.openmeteo.OpenMeteoApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.openmeteo.OpenMeteoRepository
|
||||
import com.pranshulgg.weather_master_app.data.local.WeatherMasterDatabase
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.airquality.AirQualityDao
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.location.LocationsDao
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.alerts.AlertsDao
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.github.GithubDao
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.location.LocationKeysDao
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.weather.WeatherContextDao
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.weather.ApiKeysDao
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.weather.WeatherBlocksDao
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.weather.WeatherDao
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.weather.WeatherUnitsDao
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.weather.nws.NwsDao
|
||||
import com.pranshulgg.weather_master_app.data.repository.LocationsRepository
|
||||
import com.pranshulgg.weather_master_app.data.provider.devicelocation.ChinaOfflineGeocoder
|
||||
import com.pranshulgg.weather_master_app.data.repository.ApiKeysRepository
|
||||
import com.pranshulgg.weather_master_app.data.repository.WeatherContextRepository
|
||||
import com.pranshulgg.weather_master_app.data.repository.WeatherBlocksRepository
|
||||
import com.pranshulgg.weather_master_app.data.repository.WeatherDataReconcilerRepository
|
||||
import com.pranshulgg.weather_master_app.data.repository.WeatherUnitsRepository
|
||||
import com.pranshulgg.weather_master_app.data.repository.data.SourceDataRepository
|
||||
import com.pranshulgg.weather_master_app.data.store.InitializationStore
|
||||
import com.pranshulgg.weather_master_app.data.store.LocationStore
|
||||
import com.pranshulgg.weather_master_app.data.store.WeatherBlocksStore
|
||||
import com.pranshulgg.weather_master_app.data.store.WeatherStore
|
||||
import com.pranshulgg.weather_master_app.data.store.WeatherUnitsStore
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
import dagger.Lazy
|
||||
import javax.inject.Provider
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
@@ -51,12 +56,23 @@ object AppModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideLocationsRepository(
|
||||
dao: LocationsDao,
|
||||
fun provideWeatherContextRepository(
|
||||
dao: WeatherContextDao,
|
||||
airQualityDao: AirQualityDao,
|
||||
nominatimRepository: NominatimRepository,
|
||||
@ApplicationContext context: Context
|
||||
): LocationsRepository = LocationsRepository(dao, airQualityDao, context, nominatimRepository)
|
||||
@ApplicationContext context: Context,
|
||||
alertsDao: AlertsDao,
|
||||
sourceManager: SourceManager,
|
||||
chinaOfflineGeocoder: ChinaOfflineGeocoder
|
||||
): WeatherContextRepository = WeatherContextRepository(
|
||||
dao,
|
||||
airQualityDao,
|
||||
context,
|
||||
nominatimRepository,
|
||||
alertsDao,
|
||||
sourceManager,
|
||||
chinaOfflineGeocoder
|
||||
)
|
||||
|
||||
|
||||
@Provides
|
||||
@@ -71,22 +87,101 @@ object AppModule {
|
||||
): WeatherBlocksRepository =
|
||||
WeatherBlocksRepository(weatherBlocksDao)
|
||||
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideWeatherDataReconcilerRepository(
|
||||
nwsDao: NwsDao,
|
||||
locationsDao: LocationsDao
|
||||
): WeatherDataReconcilerRepository = WeatherDataReconcilerRepository(nwsDao, locationsDao)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideGithubRepository(
|
||||
api: GithubApi
|
||||
): GithubRepository = GithubRepository(api)
|
||||
api: GithubApi,
|
||||
dao: GithubDao
|
||||
): GithubRepository = GithubRepository(api, dao)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideNominatimRepository(api: NominatimApi): NominatimRepository =
|
||||
NominatimRepository(api)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideApiKeysRepository(dao: ApiKeysDao): ApiKeysRepository = ApiKeysRepository(dao)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideSourceManager(
|
||||
nwsDao: NwsDao,
|
||||
locationKeysDao: LocationKeysDao,
|
||||
airQualityDao: AirQualityDao,
|
||||
alertsDao: AlertsDao,
|
||||
weatherContextRepository: Provider<WeatherContextRepository>,
|
||||
pendingRequests: PendingRequests,
|
||||
locationStore: LocationStore
|
||||
): SourceManager {
|
||||
return SourceManager(
|
||||
nwsDao,
|
||||
locationKeysDao,
|
||||
airQualityDao,
|
||||
alertsDao,
|
||||
weatherContextRepository,
|
||||
pendingRequests,
|
||||
locationStore
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideLocationManager(
|
||||
weatherContextRepository: WeatherContextRepository,
|
||||
locationStore: LocationStore,
|
||||
initializationStore: InitializationStore,
|
||||
pendingRequests: PendingRequests
|
||||
): LocationManager {
|
||||
return LocationManager(
|
||||
weatherContextRepository,
|
||||
locationStore,
|
||||
initializationStore,
|
||||
pendingRequests
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideWeatherBlocksManager(
|
||||
weatherBlocksRepository: WeatherBlocksRepository,
|
||||
weatherBlocksStore: WeatherBlocksStore
|
||||
): WeatherBlocksManager {
|
||||
return WeatherBlocksManager(
|
||||
weatherBlocksRepository,
|
||||
weatherBlocksStore
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideWeatherManager(
|
||||
weatherContextRepository: WeatherContextRepository,
|
||||
sourceDataRepository: SourceDataRepository,
|
||||
weatherStore: WeatherStore,
|
||||
locationStore: LocationStore,
|
||||
initializationStore: InitializationStore,
|
||||
externalManager: ExternalManager
|
||||
): WeatherManager {
|
||||
return WeatherManager(
|
||||
weatherContextRepository,
|
||||
sourceDataRepository,
|
||||
weatherStore,
|
||||
locationStore,
|
||||
initializationStore,
|
||||
externalManager
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideWeatherUnitsManager(
|
||||
weatherUnitsStore: WeatherUnitsStore,
|
||||
weatherUnitsRepository: WeatherUnitsRepository
|
||||
): WeatherUnitsManager {
|
||||
return WeatherUnitsManager(
|
||||
weatherUnitsStore,
|
||||
weatherUnitsRepository
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.pranshulgg.weather_master_app.core.di.db
|
||||
|
||||
import com.pranshulgg.weather_master_app.data.local.WeatherMasterDatabase
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.weather.WeatherContextDao
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
@@ -11,8 +12,8 @@ import dagger.hilt.components.SingletonComponent
|
||||
@InstallIn(SingletonComponent::class)
|
||||
object DaoModule {
|
||||
@Provides
|
||||
fun provideLocationDao(db: WeatherMasterDatabase) =
|
||||
db.locationsDao()
|
||||
fun provideWeatherContextDao(db: WeatherMasterDatabase) =
|
||||
db.weatherContextDao()
|
||||
|
||||
@Provides
|
||||
fun provideWeatherDataDao(db: WeatherMasterDatabase) =
|
||||
@@ -31,4 +32,16 @@ object DaoModule {
|
||||
|
||||
@Provides
|
||||
fun provideNwsDao(db: WeatherMasterDatabase) = db.nwsDao()
|
||||
|
||||
@Provides
|
||||
fun provideGithubDao(db: WeatherMasterDatabase) = db.githubDao()
|
||||
|
||||
@Provides
|
||||
fun provideLocationKeysDao(db: WeatherMasterDatabase) = db.locationKeysDao()
|
||||
|
||||
@Provides
|
||||
fun provideAlertsDao(db: WeatherMasterDatabase) = db.alertsDao()
|
||||
|
||||
@Provides
|
||||
fun provideApiKeysDao(db: WeatherMasterDatabase) = db.apiKeysDao()
|
||||
}
|
||||
@@ -2,15 +2,42 @@ package com.pranshulgg.weather_master_app.core.di.network
|
||||
|
||||
import com.pranshulgg.weather_master_app.core.network.github.GithubApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.address.nominatim.NominatimApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.airquality.openmeteo.OpenMeteoAqiApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.airquality.moenv.MoenvApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.alerts.fpas.FpasApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.alerts.weatherapi.AlertsWeatherApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.alerts.wmosevereweather.WmoSevereWeatherApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.search.accu.AccuSearchApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.search.geonames.GeoNamesSearchApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.search.geonames.timezone.GeoNamesTimezoneApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.search.openmeteo.OpenMeteoSearchApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.accu.AccuApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.aemet.AemetApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.bmkg.BmkgApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.china.ChinaApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.cwa.CwaApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.jma.JmaApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.dwd.DwdApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.eccc.EcccApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.fmi.FmiApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.gismeteo.GismeteoApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.imd.ImdApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.inmet.IbgeApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.inmet.InmetAvisosApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.inmet.InmetForecastApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.inmet.InmetObservationApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.ipma.IpmaApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.kmi.KmiApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.meteoam.MeteoamApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.meteofrance.MeteoFranceApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.metnorway.MetNorwayApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.metoffice.MetOfficeApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.mgm.MgmApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.nws.NwsApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.openmeteo.OpenMeteoApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.openmeteo.airquality.OpenMeteoAqiApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.openweather.OpenWeatherApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.openweather.OpenWeatherOneCallApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.pirateweather.PirateWeatherApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.smhi.SmhiApi
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
@@ -69,4 +96,113 @@ object ApiModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideMeteoFranceApi(): MeteoFranceApi = MeteoFranceApi.create()
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideEcccApi(): EcccApi = EcccApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideFmiApi(): FmiApi = FmiApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideChinaApi(): ChinaApi = ChinaApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideBmkgApi(): BmkgApi = BmkgApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideAccuApi(): AccuApi = AccuApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideMeteoamApi(): MeteoamApi = MeteoamApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideAlertsWeatherApi(): AlertsWeatherApi = AlertsWeatherApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideIpmaApi(): IpmaApi = IpmaApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideAccuSearchApi(): AccuSearchApi = AccuSearchApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideWmoSevereWeatherAlertsApi(): WmoSevereWeatherApi = WmoSevereWeatherApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideFpasAlertsApi(): FpasApi = FpasApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideGismeteoApi(): GismeteoApi = GismeteoApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideMetOfficeApi(): MetOfficeApi = MetOfficeApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideAemetApi(): AemetApi = AemetApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideImdApi(): ImdApi = ImdApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providePirateWeatherApi(): PirateWeatherApi = PirateWeatherApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideCwaApi(): CwaApi = CwaApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideJmaApi(): JmaApi = JmaApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideInmetForecastApi(): InmetForecastApi = InmetForecastApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideInmetAvisosApi(): InmetAvisosApi = InmetAvisosApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideInmetObservationApi(): InmetObservationApi = InmetObservationApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideIbgeApi(): IbgeApi = IbgeApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideOpenWeatherApi(): OpenWeatherApi = OpenWeatherApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideOpenWeatherOneCallApi(): OpenWeatherOneCallApi = OpenWeatherOneCallApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideMgmApi(): MgmApi = MgmApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideKmiApi(): KmiApi = KmiApi.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideMoenvApi(): MoenvApi = MoenvApi.create()
|
||||
|
||||
}
|
||||
+8
@@ -1,5 +1,7 @@
|
||||
package com.pranshulgg.weather_master_app.core.di.search
|
||||
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.search.accu.AccuSearchApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.search.accu.AccuSearchRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.search.geonames.GeoNamesSearchApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.search.geonames.GeoNamesSearchRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.search.geonames.GeoNamesTimezoneRepository
|
||||
@@ -32,4 +34,10 @@ object SearchRepositoryModule {
|
||||
fun provideGeoNamesTimezoneRepository(api: GeoNamesTimezoneApi): GeoNamesTimezoneRepository =
|
||||
GeoNamesTimezoneRepository(api)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideAccuSearchRepository(
|
||||
api: AccuSearchApi
|
||||
): AccuSearchRepository = AccuSearchRepository(api)
|
||||
|
||||
}
|
||||
+262
-20
@@ -1,21 +1,64 @@
|
||||
package com.pranshulgg.weather_master_app.core.di.weather
|
||||
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.airquality.openmeteo.OpenMeteoAqiApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.airquality.openmeteo.OpenMeteoAqiRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.openmeteo.airquality.OpenMeteoAqiApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.accu.AccuApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.accu.AccuRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.aemet.AemetApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.aemet.AemetRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.bmkg.BmkgApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.bmkg.BmkgRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.china.ChinaApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.china.ChinaRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.cwa.CwaApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.cwa.CwaRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.dwd.DwdApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.dwd.DwdRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.eccc.EcccApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.eccc.EcccRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.fmi.FmiApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.fmi.FmiRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.gismeteo.GismeteoApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.gismeteo.GismeteoRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.meteofor.MeteoforRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.imd.ImdApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.imd.ImdRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.inmet.IbgeApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.inmet.InmetAvisosApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.inmet.InmetForecastApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.inmet.InmetObservationApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.inmet.InmetRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.jma.JmaApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.jma.JmaRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.ipma.IpmaApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.ipma.IpmaRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.kmi.KmiApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.kmi.KmiRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.meteoam.MeteoamApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.meteoam.MeteoamRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.meteofrance.MeteoFranceApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.meteofrance.MeteoFranceRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.metnorway.MetNorwayApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.metnorway.MetNorwayRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.metoffice.MetOfficeApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.metoffice.MetOfficeRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.mgm.MgmApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.mgm.MgmRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.nws.NwsApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.nws.NwsRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.openmeteo.OpenMeteoApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.openmeteo.OpenMeteoRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.openweather.OpenWeatherApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.openweather.OpenWeatherOneCallApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.openweather.OpenWeatherRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.pirateweather.PirateWeatherApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.pirateweather.PirateWeatherRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.smhi.SmhiApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.weather.smhi.SmhiRepository
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.airquality.AirQualityDao
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.location.LocationsDao
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.alerts.AlertsDao
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.location.LocationKeysDao
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.weather.WeatherContextDao
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.weather.ApiKeysDao
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.weather.WeatherDao
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.weather.nws.NwsDao
|
||||
import dagger.Module
|
||||
@@ -30,32 +73,28 @@ object WeatherRepositoryModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideOpenMeteoRepository(
|
||||
dao: LocationsDao,
|
||||
dao: WeatherContextDao,
|
||||
api: OpenMeteoApi,
|
||||
weatherDao: WeatherDao
|
||||
): OpenMeteoRepository = OpenMeteoRepository(dao, weatherDao, api)
|
||||
weatherDao: WeatherDao,
|
||||
airQualityDao: AirQualityDao,
|
||||
airQualityApi: OpenMeteoAqiApi
|
||||
): OpenMeteoRepository = OpenMeteoRepository(dao, weatherDao, api, airQualityApi, airQualityDao)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideOpenMeteoAqiRepository(
|
||||
api: OpenMeteoAqiApi,
|
||||
dao: AirQualityDao
|
||||
): OpenMeteoAqiRepository =
|
||||
OpenMeteoAqiRepository(api, dao)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideNwsRepository(
|
||||
api: NwsApi,
|
||||
dao: LocationsDao,
|
||||
dao: WeatherContextDao,
|
||||
weatherDao: WeatherDao,
|
||||
nwsDao: NwsDao
|
||||
): NwsRepository = NwsRepository(dao, weatherDao, nwsDao, api)
|
||||
nwsDao: NwsDao,
|
||||
alertsDao: AlertsDao
|
||||
): NwsRepository = NwsRepository(dao, weatherDao, nwsDao, api, alertsDao)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideMetNorwayRepository(
|
||||
dao: LocationsDao,
|
||||
dao: WeatherContextDao,
|
||||
api: MetNorwayApi,
|
||||
weatherDao: WeatherDao
|
||||
): MetNorwayRepository = MetNorwayRepository(dao, weatherDao, api)
|
||||
@@ -63,7 +102,7 @@ object WeatherRepositoryModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideSmhiRepository(
|
||||
dao: LocationsDao,
|
||||
dao: WeatherContextDao,
|
||||
api: SmhiApi,
|
||||
weatherDao: WeatherDao
|
||||
): SmhiRepository = SmhiRepository(dao, weatherDao, api)
|
||||
@@ -71,7 +110,7 @@ object WeatherRepositoryModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideDwdRepository(
|
||||
dao: LocationsDao,
|
||||
dao: WeatherContextDao,
|
||||
api: DwdApi,
|
||||
weatherDao: WeatherDao
|
||||
): DwdRepository = DwdRepository(dao, weatherDao, api)
|
||||
@@ -79,8 +118,211 @@ object WeatherRepositoryModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideMeteoFranceRepository(
|
||||
dao: LocationsDao,
|
||||
dao: WeatherContextDao,
|
||||
api: MeteoFranceApi,
|
||||
weatherDao: WeatherDao
|
||||
): MeteoFranceRepository = MeteoFranceRepository(dao, weatherDao, api)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideEcccRepository(
|
||||
dao: WeatherContextDao,
|
||||
api: EcccApi,
|
||||
weatherDao: WeatherDao
|
||||
): EcccRepository = EcccRepository(dao, weatherDao, api)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideFmiRepository(
|
||||
dao: WeatherContextDao,
|
||||
api: FmiApi,
|
||||
weatherDao: WeatherDao
|
||||
): FmiRepository = FmiRepository(dao, weatherDao, api)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideChinaRepository(
|
||||
dao: WeatherContextDao,
|
||||
api: ChinaApi,
|
||||
weatherDao: WeatherDao
|
||||
): ChinaRepository = ChinaRepository(dao, weatherDao, api)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideBmkgRepository(
|
||||
dao: WeatherContextDao,
|
||||
api: BmkgApi,
|
||||
weatherDao: WeatherDao
|
||||
): BmkgRepository = BmkgRepository(dao, weatherDao, api)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideAccuRepository(
|
||||
dao: WeatherContextDao,
|
||||
api: AccuApi,
|
||||
weatherDao: WeatherDao,
|
||||
locationKeysDao: LocationKeysDao,
|
||||
airQualityDao: AirQualityDao,
|
||||
alertsDao: AlertsDao,
|
||||
weatherContextDao: WeatherContextDao
|
||||
): AccuRepository = AccuRepository(
|
||||
dao,
|
||||
weatherDao,
|
||||
api,
|
||||
locationKeysDao,
|
||||
airQualityDao,
|
||||
weatherContextDao,
|
||||
alertsDao
|
||||
)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideMeteoamRepository(
|
||||
dao: WeatherContextDao,
|
||||
api: MeteoamApi,
|
||||
weatherDao: WeatherDao
|
||||
): MeteoamRepository = MeteoamRepository(dao, weatherDao, api)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideIpmaRepository(
|
||||
dao: WeatherContextDao,
|
||||
api: IpmaApi,
|
||||
weatherDao: WeatherDao,
|
||||
locationKeysDao: LocationKeysDao
|
||||
): IpmaRepository = IpmaRepository(dao, weatherDao, api, locationKeysDao)
|
||||
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideGismeteoRepository(
|
||||
dao: WeatherContextDao,
|
||||
api: GismeteoApi,
|
||||
weatherDao: WeatherDao,
|
||||
locationKeysDao: LocationKeysDao
|
||||
): GismeteoRepository = GismeteoRepository(dao, weatherDao, api, locationKeysDao)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideMeteoforRepository(
|
||||
dao: WeatherContextDao,
|
||||
api: GismeteoApi,
|
||||
weatherDao: WeatherDao,
|
||||
locationKeysDao: LocationKeysDao
|
||||
): MeteoforRepository = MeteoforRepository(dao, weatherDao, api, locationKeysDao)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideMetOfficeRepository(
|
||||
dao: WeatherContextDao,
|
||||
api: MetOfficeApi,
|
||||
weatherDao: WeatherDao,
|
||||
apiKeysDao: ApiKeysDao
|
||||
): MetOfficeRepository = MetOfficeRepository(dao, weatherDao, api, apiKeysDao)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideAemetRepository(
|
||||
dao: WeatherContextDao,
|
||||
api: AemetApi,
|
||||
weatherDao: WeatherDao,
|
||||
apiKeysDao: ApiKeysDao,
|
||||
locationKeysDao: LocationKeysDao
|
||||
): AemetRepository = AemetRepository(dao, weatherDao, api, apiKeysDao, locationKeysDao)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideImdRepository(
|
||||
dao: WeatherContextDao,
|
||||
weatherDao: WeatherDao,
|
||||
api: ImdApi
|
||||
): ImdRepository = ImdRepository(dao, weatherDao, api)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providePirateWeatherRepository(
|
||||
dao: WeatherContextDao,
|
||||
api: PirateWeatherApi,
|
||||
weatherDao: WeatherDao,
|
||||
apiKeysDao: ApiKeysDao,
|
||||
alertsDao: AlertsDao
|
||||
): PirateWeatherRepository =
|
||||
PirateWeatherRepository(dao, weatherDao, api, apiKeysDao, alertsDao)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideCwaRepository(
|
||||
dao: WeatherContextDao,
|
||||
api: CwaApi,
|
||||
weatherDao: WeatherDao,
|
||||
apiKeysDao: ApiKeysDao,
|
||||
locationKeysDao: LocationKeysDao
|
||||
): CwaRepository = CwaRepository(dao, weatherDao, api, apiKeysDao, locationKeysDao)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideJmaRepository(
|
||||
dao: WeatherContextDao,
|
||||
weatherDao: WeatherDao,
|
||||
api: JmaApi,
|
||||
locationKeysDao: LocationKeysDao,
|
||||
alertsDao: AlertsDao
|
||||
): JmaRepository = JmaRepository(dao, weatherDao, api, locationKeysDao, alertsDao)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideInmetRepository(
|
||||
dao: WeatherContextDao,
|
||||
weatherDao: WeatherDao,
|
||||
forecastApi: InmetForecastApi,
|
||||
observationApi: InmetObservationApi,
|
||||
ibgeApi: IbgeApi,
|
||||
avisosApi: InmetAvisosApi,
|
||||
locationKeysDao: LocationKeysDao,
|
||||
alertsDao: AlertsDao
|
||||
): InmetRepository = InmetRepository(
|
||||
dao,
|
||||
weatherDao,
|
||||
forecastApi,
|
||||
observationApi,
|
||||
ibgeApi,
|
||||
avisosApi,
|
||||
locationKeysDao,
|
||||
alertsDao
|
||||
)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideOpenWeatherRepository(
|
||||
dao: WeatherContextDao,
|
||||
weatherDao: WeatherDao,
|
||||
api: OpenWeatherApi,
|
||||
airQualityDao: AirQualityDao,
|
||||
apiKeysDao: ApiKeysDao,
|
||||
oneCallApi: OpenWeatherOneCallApi
|
||||
): OpenWeatherRepository =
|
||||
OpenWeatherRepository(dao, weatherDao, api, oneCallApi, airQualityDao, apiKeysDao)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideMgmRepository(
|
||||
dao: WeatherContextDao,
|
||||
weatherDao: WeatherDao,
|
||||
api: MgmApi,
|
||||
apiKeysDao: ApiKeysDao,
|
||||
locationKeysDao: LocationKeysDao,
|
||||
alertsDao: AlertsDao
|
||||
): MgmRepository = MgmRepository(dao, weatherDao, api, apiKeysDao, locationKeysDao, alertsDao)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideKmiRepository(
|
||||
dao: WeatherContextDao,
|
||||
weatherDao: WeatherDao,
|
||||
api: KmiApi,
|
||||
apiKeysDao: ApiKeysDao,
|
||||
locationKeysDao: LocationKeysDao,
|
||||
alertsDao: AlertsDao
|
||||
): KmiRepository = KmiRepository(dao, weatherDao, api, apiKeysDao, locationKeysDao, alertsDao)
|
||||
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package com.pranshulgg.weather_master_app.core.di.weather.airquality
|
||||
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.airquality.moenv.MoenvApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.airquality.moenv.MoenvRepository
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.airquality.AirQualityDao
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
object AirQualityRepositoryModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideMoenvRepository(
|
||||
api: MoenvApi,
|
||||
airQualityDao: AirQualityDao
|
||||
): MoenvRepository = MoenvRepository(api, airQualityDao)
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package com.pranshulgg.weather_master_app.core.di.weather.alerts
|
||||
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.alerts.fpas.FpasApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.alerts.fpas.FpasRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.alerts.weatherapi.AlertsWeatherApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.alerts.weatherapi.AlertsWeatherApiRepository
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.alerts.wmosevereweather.WmoSevereWeatherApi
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.alerts.wmosevereweather.WmoSevereWeatherRepository
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.alerts.AlertsDao
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.weather.WeatherContextDao
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
object AlertsRepositoryModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideWmoSevereWeatherAlertsRepository(
|
||||
api: WmoSevereWeatherApi,
|
||||
dao: AlertsDao,
|
||||
weatherContextDao: WeatherContextDao
|
||||
): WmoSevereWeatherRepository = WmoSevereWeatherRepository(api, dao, weatherContextDao)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideFpasAlertsRepository(
|
||||
api: FpasApi,
|
||||
dao: AlertsDao,
|
||||
weatherContextDao: WeatherContextDao
|
||||
): FpasRepository = FpasRepository(api, dao, weatherContextDao)
|
||||
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideWeatherApiAlertsRepository(
|
||||
api: AlertsWeatherApi,
|
||||
dao: AlertsDao,
|
||||
weatherContextDao: WeatherContextDao
|
||||
): AlertsWeatherApiRepository = AlertsWeatherApiRepository(api, dao, weatherContextDao)
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.pranshulgg.weather_master_app.core.managers
|
||||
|
||||
import android.content.Context
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.weather.Weather
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.weather.WeatherUnits
|
||||
import com.pranshulgg.weather_master_app.core.prefs.helper.PreferencesHelper
|
||||
import com.pranshulgg.weather_master_app.data.store.LocationStore
|
||||
import com.pranshulgg.weather_master_app.data.store.WeatherStore
|
||||
import com.pranshulgg.weather_master_app.data.store.WeatherUnitsStore
|
||||
import com.pranshulgg.weather_master_app.data.worker.WeatherBackgroundUpdateScheduler
|
||||
import com.pranshulgg.weather_master_app.feature.notifications.ongoing.OnGoingNotification
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
// UPDATES NOTIFICATION/WIDGETS
|
||||
// APP SIDE ONLY!!!
|
||||
@Singleton
|
||||
class ExternalManager @Inject constructor(
|
||||
private val weatherStore: WeatherStore,
|
||||
private val weatherUnitsStore: WeatherUnitsStore,
|
||||
@ApplicationContext val context: Context
|
||||
) {
|
||||
|
||||
|
||||
suspend fun refreshWidgets() {
|
||||
val weather = weatherStore.data.value.weather
|
||||
val units = weatherUnitsStore.data.value.units
|
||||
if (weather != null && weather.location.isDefault) {
|
||||
WeatherBackgroundUpdateScheduler.updateAllWidgets(
|
||||
context = context,
|
||||
data = weather,
|
||||
units = units
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun refreshNotifications() {
|
||||
val units = weatherUnitsStore.data.value.units
|
||||
val weather = weatherStore.data.value.weather
|
||||
|
||||
val isOnGoingNotificationEnabled = PreferencesHelper.getBool(
|
||||
"isOnGoingNotificationEnabled"
|
||||
) ?: false
|
||||
|
||||
if (weather != null && weather.location.isDefault && isOnGoingNotificationEnabled) {
|
||||
OnGoingNotification.update(
|
||||
context = context,
|
||||
weather = weather,
|
||||
units = units
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.pranshulgg.weather_master_app.core.managers
|
||||
|
||||
import android.util.Log
|
||||
import com.pranshulgg.weather_master_app.core.managers.requests.PendingRequests
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.location.Location
|
||||
import com.pranshulgg.weather_master_app.core.model.sources.Source
|
||||
import com.pranshulgg.weather_master_app.core.model.weather.openmeteo.OpenMeteoModel
|
||||
import com.pranshulgg.weather_master_app.data.repository.WeatherContextRepository
|
||||
import com.pranshulgg.weather_master_app.data.store.InitializationStore
|
||||
import com.pranshulgg.weather_master_app.data.store.LocationStore
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class LocationManager @Inject constructor(
|
||||
private val weatherContextRepository: WeatherContextRepository,
|
||||
private val locationStore: LocationStore,
|
||||
private val initializationStore: InitializationStore,
|
||||
private val pendingRequests: PendingRequests
|
||||
|
||||
) {
|
||||
|
||||
suspend fun initialize(scope: CoroutineScope) {
|
||||
if (!initializationStore.data.value.isInitialized && locationStore.data.value.activeLocation == null) {
|
||||
if (weatherContextRepository.isLocationsEmpty()) {
|
||||
initializationStore.setInitialized()
|
||||
}
|
||||
val default = weatherContextRepository
|
||||
.getDefaultLocation()
|
||||
.filterNotNull()
|
||||
.first()
|
||||
|
||||
setActive(default, skipLoading = false)
|
||||
}
|
||||
|
||||
weatherContextRepository.getLocations().distinctUntilChanged()
|
||||
.onEach { locations ->
|
||||
writeLocations(
|
||||
locations = locations,
|
||||
isLoading = locationStore.data.value.isActiveLocationLoading
|
||||
)
|
||||
}.launchIn(scope)
|
||||
}
|
||||
|
||||
private fun writeLocations(locations: List<Location>, isLoading: Boolean) {
|
||||
|
||||
val previous = locationStore.data.value.locations
|
||||
|
||||
if (previous.isNotEmpty()) {
|
||||
|
||||
val newLocation = locations.firstOrNull { new ->
|
||||
previous.none { it.id == new.id }
|
||||
}
|
||||
|
||||
newLocation?.let {
|
||||
if (!isLoading) {
|
||||
setActive(newLocation, skipLoading = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
locationStore.setLocations(locations = locations)
|
||||
}
|
||||
|
||||
suspend fun deleteLocation(id: String) {
|
||||
weatherContextRepository.deleteLocation(id)
|
||||
|
||||
if (locationStore.data.value.activeLocation?.id == id) {
|
||||
val defaultLocation = locationStore.data.value.locations
|
||||
.first { it.isDefault }
|
||||
|
||||
setActive(defaultLocation, skipLoading = false)
|
||||
}
|
||||
}
|
||||
|
||||
fun setActive(location: Location, skipLoading: Boolean) {
|
||||
if (!skipLoading) {
|
||||
setActiveLoading()
|
||||
}
|
||||
locationStore.setActiveLocation(location)
|
||||
pendingRequests.queueRequest(location)
|
||||
}
|
||||
|
||||
fun setActiveLoading() {
|
||||
locationStore.setLoading(true)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
package com.pranshulgg.weather_master_app.core.managers
|
||||
|
||||
import com.pranshulgg.weather_master_app.core.managers.requests.PendingRequests
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.location.Location
|
||||
import com.pranshulgg.weather_master_app.core.model.sources.Source
|
||||
import com.pranshulgg.weather_master_app.core.model.weather.openmeteo.OpenMeteoModel
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.airquality.AirQualityDao
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.alerts.AlertsDao
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.location.LocationKeysDao
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.weather.nws.NwsDao
|
||||
import com.pranshulgg.weather_master_app.data.repository.WeatherContextRepository
|
||||
import com.pranshulgg.weather_master_app.data.store.LocationStore
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Provider
|
||||
import javax.inject.Singleton
|
||||
|
||||
|
||||
@Singleton
|
||||
class SourceManager @Inject constructor(
|
||||
private val nwsDao: NwsDao,
|
||||
private val locationKeysDao: LocationKeysDao,
|
||||
private val airQualityDao: AirQualityDao,
|
||||
private val alertsDao: AlertsDao,
|
||||
private val weatherContextRepository: Provider<WeatherContextRepository>,
|
||||
private val pendingRequests: PendingRequests,
|
||||
private val locationStore: LocationStore
|
||||
) {
|
||||
|
||||
|
||||
suspend fun updateSources(
|
||||
location: Location,
|
||||
source: Source,
|
||||
airQualitySource: Source,
|
||||
alertSource: Source,
|
||||
openMeteoModel: OpenMeteoModel
|
||||
) {
|
||||
val updatedLocation = location.copy(
|
||||
source = source,
|
||||
airQualitySource = airQualitySource,
|
||||
alertSource = alertSource,
|
||||
openMeteoModel = openMeteoModel
|
||||
)
|
||||
|
||||
val weatherContextRepository = weatherContextRepository.get()
|
||||
|
||||
weatherContextRepository.updateSourceForLocation(location.id, source)
|
||||
weatherContextRepository.updateAirQualitySourceForLocation(location.id, airQualitySource)
|
||||
weatherContextRepository.updateAlertSourceForLocation(location.id, alertSource)
|
||||
weatherContextRepository.updateOpenMeteoModelForLocation(location.id, openMeteoModel)
|
||||
|
||||
val forceRefreshForWeather = location.source != source
|
||||
|| location.openMeteoModel != openMeteoModel
|
||||
val forceRefreshForAirQuality = location.airQualitySource != airQualitySource
|
||||
val forceRefreshForAlerts = location.alertSource != alertSource
|
||||
|
||||
reconcileSourceChange(
|
||||
previous = location,
|
||||
updated = updatedLocation
|
||||
)
|
||||
if (location != updatedLocation) {
|
||||
locationStore.setLoading(true)
|
||||
locationStore.setActiveLocation(updatedLocation)
|
||||
}
|
||||
pendingRequests.queueRequest(
|
||||
location = updatedLocation,
|
||||
isForceRefresh = forceRefreshForWeather,
|
||||
isForceRefreshForAirQuality = forceRefreshForAirQuality,
|
||||
isForceRefreshForAlerts = forceRefreshForAlerts
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes cached data that is no longer needed after a location's
|
||||
* weather, air quality, or alert source changes.
|
||||
*/
|
||||
suspend fun reconcileSourceChange(
|
||||
previous: Location,
|
||||
updated: Location
|
||||
) {
|
||||
val locationId = previous.id
|
||||
|
||||
if (previous.source != updated.source) {
|
||||
cleanWeatherData(
|
||||
locationId = locationId,
|
||||
previousSource = previous.source,
|
||||
airQualitySource = updated.airQualitySource,
|
||||
alertSource = updated.alertSource
|
||||
)
|
||||
}
|
||||
|
||||
if (previous.airQualitySource != updated.airQualitySource) {
|
||||
cleanAirQualityData(
|
||||
locationId = locationId,
|
||||
currentWeatherSource = updated.source,
|
||||
currentAlertSource = updated.alertSource
|
||||
)
|
||||
}
|
||||
|
||||
if (previous.alertSource != updated.alertSource) {
|
||||
cleanAlertsData(
|
||||
locationId = locationId,
|
||||
currentWeatherSource = updated.source,
|
||||
currentAirQualitySource = updated.airQualitySource
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes source-specific data that is no longer valid for the location.
|
||||
*/
|
||||
suspend fun cleanLocationExtras(locationId: String) {
|
||||
nwsDao.deleteGridPointsForLocation(locationId)
|
||||
locationKeysDao.deleteCityKeyForLocation(locationId)
|
||||
}
|
||||
|
||||
private suspend fun cleanWeatherData(
|
||||
locationId: String,
|
||||
previousSource: Source,
|
||||
airQualitySource: Source,
|
||||
alertSource: Source
|
||||
) {
|
||||
when (previousSource) {
|
||||
Source.NWS -> {
|
||||
nwsDao.deleteGridPointsForLocation(locationId)
|
||||
}
|
||||
|
||||
Source.ACCU_WEATHER -> {
|
||||
cleanAccuWeatherData(
|
||||
locationId = locationId,
|
||||
airQualitySource = airQualitySource,
|
||||
alertSource = alertSource
|
||||
)
|
||||
}
|
||||
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun cleanAccuWeatherData(
|
||||
locationId: String,
|
||||
airQualitySource: Source,
|
||||
alertSource: Source
|
||||
) {
|
||||
if (
|
||||
airQualitySource != Source.ACCU_WEATHER &&
|
||||
alertSource != Source.ACCU_WEATHER
|
||||
) {
|
||||
locationKeysDao.deleteCityKeyForLocation(locationId)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun cleanAirQualityData(
|
||||
locationId: String,
|
||||
currentWeatherSource: Source,
|
||||
currentAlertSource: Source
|
||||
) {
|
||||
airQualityDao.deleteCurrentAirQuality(locationId)
|
||||
airQualityDao.deleteHourlyAirQuality(locationId)
|
||||
|
||||
if (
|
||||
currentWeatherSource != Source.ACCU_WEATHER &&
|
||||
currentAlertSource != Source.ACCU_WEATHER
|
||||
) {
|
||||
locationKeysDao.deleteCityKeyForLocation(locationId)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun cleanAlertsData(
|
||||
locationId: String,
|
||||
currentWeatherSource: Source,
|
||||
currentAirQualitySource: Source
|
||||
) {
|
||||
alertsDao.deleteAlertsForLocation(locationId)
|
||||
|
||||
if (
|
||||
currentWeatherSource != Source.ACCU_WEATHER &&
|
||||
currentAirQualitySource != Source.ACCU_WEATHER
|
||||
) {
|
||||
locationKeysDao.deleteCityKeyForLocation(locationId)
|
||||
}
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package com.pranshulgg.weather_master_app.core.managers
|
||||
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.weather.WeatherBlock
|
||||
import com.pranshulgg.weather_master_app.data.repository.WeatherBlocksRepository
|
||||
import com.pranshulgg.weather_master_app.data.store.WeatherBlocksStore
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
|
||||
@Singleton
|
||||
class WeatherBlocksManager @Inject constructor(
|
||||
private val weatherBlocksRepository: WeatherBlocksRepository,
|
||||
private val weatherBlocksStore: WeatherBlocksStore
|
||||
) {
|
||||
|
||||
suspend fun initialize() {
|
||||
val blocks = weatherBlocksRepository.loadBlocks()
|
||||
val dailyBlocks = weatherBlocksRepository.loadBlocks(isDaily = true)
|
||||
|
||||
weatherBlocksStore.set(blocks)
|
||||
weatherBlocksStore.setForDaily(dailyBlocks)
|
||||
}
|
||||
|
||||
suspend fun saveBlocks(
|
||||
items: List<WeatherBlock>,
|
||||
isDaily: Boolean = false
|
||||
) {
|
||||
if (isDaily) {
|
||||
weatherBlocksStore.setForDaily(items)
|
||||
} else {
|
||||
weatherBlocksStore.set(items)
|
||||
}
|
||||
weatherBlocksRepository.saveBlocks(items.map {
|
||||
WeatherBlock(
|
||||
type = it.type,
|
||||
isHidden = false,
|
||||
position = it.position,
|
||||
isDaily = isDaily,
|
||||
id = it.id
|
||||
)
|
||||
}, isDaily)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
package com.pranshulgg.weather_master_app.core.managers
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.AppException
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.location.Location
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.toAppException
|
||||
import com.pranshulgg.weather_master_app.core.model.sources.isGlobal
|
||||
import com.pranshulgg.weather_master_app.core.model.sources.isSourceSupportedFor
|
||||
import com.pranshulgg.weather_master_app.core.model.weather.WeatherResult
|
||||
import com.pranshulgg.weather_master_app.core.model.weather.airquality.AirQualityResult
|
||||
import com.pranshulgg.weather_master_app.core.model.weather.alerts.AlertResult
|
||||
import com.pranshulgg.weather_master_app.data.repository.WeatherContextRepository
|
||||
import com.pranshulgg.weather_master_app.data.repository.data.SourceDataRepository
|
||||
import com.pranshulgg.weather_master_app.data.store.InitializationStore
|
||||
import com.pranshulgg.weather_master_app.data.store.LocationStore
|
||||
import com.pranshulgg.weather_master_app.data.store.WeatherStore
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.cancel
|
||||
import kotlinx.coroutines.flow.drop
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
@Singleton
|
||||
class WeatherManager @Inject constructor(
|
||||
private val weatherContextRepository: WeatherContextRepository,
|
||||
private val sourceDataRepository: SourceDataRepository,
|
||||
private val weatherStore: WeatherStore,
|
||||
private val locationStore: LocationStore,
|
||||
private val initializationStore: InitializationStore,
|
||||
private val externalManager: ExternalManager
|
||||
) {
|
||||
|
||||
private val scope = CoroutineScope(SupervisorJob())
|
||||
|
||||
private val _errors = MutableSharedFlow<AppException>(
|
||||
extraBufferCapacity = 1
|
||||
)
|
||||
|
||||
/**
|
||||
* Lets the UI know that the source for this location
|
||||
* isn't supported in the region
|
||||
*/
|
||||
var isUnsupportedSource by mutableStateOf(false)
|
||||
private set
|
||||
|
||||
val errors = _errors.asSharedFlow()
|
||||
|
||||
private var weatherJob: Job? = null
|
||||
|
||||
operator fun invoke(
|
||||
location: Location,
|
||||
isManualRefresh: Boolean = false,
|
||||
isForceRefresh: Boolean = false,
|
||||
isForceRefreshForAirQuality: Boolean = false,
|
||||
isForceRefreshForAlerts: Boolean = false,
|
||||
skipDeviceLocationCheck: Boolean = false
|
||||
) {
|
||||
|
||||
isUnsupportedSource = false
|
||||
val startTime = System.currentTimeMillis()
|
||||
weatherJob?.cancel()
|
||||
|
||||
weatherJob = scope.launch {
|
||||
try {
|
||||
var effectiveLocation = location
|
||||
var effectiveForceRefresh = isForceRefresh
|
||||
var effectiveForceRefreshForAirQuality = isForceRefreshForAirQuality
|
||||
var effectiveForceRefreshForAlerts = isForceRefreshForAlerts
|
||||
|
||||
if (location.isDeviceLocation && !skipDeviceLocationCheck) {
|
||||
val positionChanged = try {
|
||||
weatherContextRepository.updateDeviceLocationPosition()
|
||||
} catch (e: AppException.CurrentLocationUnavailable) {
|
||||
false
|
||||
}
|
||||
if (positionChanged) {
|
||||
effectiveLocation = weatherContextRepository.getLocationForId(location.id)
|
||||
effectiveForceRefresh = true
|
||||
effectiveForceRefreshForAirQuality = true
|
||||
effectiveForceRefreshForAlerts = true
|
||||
locationStore.setActiveLocation(effectiveLocation)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sourceDataRepository.getData(
|
||||
location = effectiveLocation,
|
||||
isManualRefresh = isManualRefresh,
|
||||
isForceRefresh = effectiveForceRefresh,
|
||||
isForceRefreshForAirQuality = effectiveForceRefreshForAirQuality,
|
||||
isForceRefreshForAlerts = effectiveForceRefreshForAlerts,
|
||||
onWeather = { result ->
|
||||
writeWeather(result, effectiveLocation)
|
||||
},
|
||||
onAlerts = { result ->
|
||||
writeAlerts(result)
|
||||
},
|
||||
onAirQuality = { result ->
|
||||
writeAirQuality(result)
|
||||
},
|
||||
)
|
||||
|
||||
val elapsed = System.currentTimeMillis() - startTime
|
||||
val minLoadingTime = 1000L
|
||||
|
||||
// Prevents loader flicker when responses return too quickly
|
||||
if (elapsed < minLoadingTime) {
|
||||
delay(duration = (minLoadingTime - elapsed).milliseconds)
|
||||
}
|
||||
} finally {
|
||||
externalManager.refreshWidgets()
|
||||
externalManager.refreshNotifications()
|
||||
locationStore.setLoading(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun writeWeather(
|
||||
result: WeatherResult,
|
||||
location: Location
|
||||
) {
|
||||
when (result) {
|
||||
|
||||
is WeatherResult.Success -> {
|
||||
weatherStore.setWeather(weather = result.weather)
|
||||
initializationStore.setInitialized()
|
||||
}
|
||||
|
||||
is WeatherResult.Error -> {
|
||||
weatherStore.setWeather(weather = result.weather)
|
||||
|
||||
isUnsupportedSource = !location.source.isGlobal()
|
||||
&& !location.source.isSourceSupportedFor(
|
||||
countryCode = location.countryCode?.uppercase()
|
||||
)
|
||||
_errors.tryEmit(result.exception.toAppException())
|
||||
}
|
||||
|
||||
is WeatherResult.RefreshNotAvailable -> {
|
||||
weatherStore.setWeather(result.weather)
|
||||
_errors.tryEmit(AppException.RefreshNotAvailable())
|
||||
}
|
||||
|
||||
is WeatherResult.NotSupported -> {}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private fun writeAirQuality(result: AirQualityResult?) {
|
||||
if (result == null) {
|
||||
weatherStore.setAirQuality(airQuality = null)
|
||||
return
|
||||
}
|
||||
when (result) {
|
||||
is AirQualityResult.Success -> {
|
||||
weatherStore.setAirQuality(airQuality = result.airQuality)
|
||||
}
|
||||
// Fail silently, we just won't show the Air quality in the UI if null
|
||||
is AirQualityResult.Error -> {
|
||||
weatherStore.setAirQuality(airQuality = result.airQuality)
|
||||
}
|
||||
|
||||
is AirQualityResult.NotSupported -> {
|
||||
weatherStore.setAirQuality(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun writeAlerts(result: AlertResult?) {
|
||||
if (result == null) {
|
||||
weatherStore.setAlerts(alerts = emptyList())
|
||||
return
|
||||
}
|
||||
when (result) {
|
||||
is AlertResult.Success -> {
|
||||
weatherStore.setAlerts(alerts = result.alerts)
|
||||
}
|
||||
// Fail silently, we just won't show the alerts in the UI if null
|
||||
is AlertResult.Error -> {
|
||||
weatherStore.setAlerts(alerts = result.alerts)
|
||||
}
|
||||
|
||||
is AlertResult.NotSupported -> {
|
||||
weatherStore.setAlerts(alerts = emptyList())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.pranshulgg.weather_master_app.core.managers
|
||||
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.weather.WeatherUnits
|
||||
import com.pranshulgg.weather_master_app.data.repository.WeatherUnitsRepository
|
||||
import com.pranshulgg.weather_master_app.data.store.WeatherUnitsStore
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
|
||||
@Singleton
|
||||
class WeatherUnitsManager @Inject constructor(
|
||||
private val weatherUnitsStore: WeatherUnitsStore,
|
||||
private val weatherUnitsRepository: WeatherUnitsRepository
|
||||
) {
|
||||
fun initialize(scope: CoroutineScope) {
|
||||
weatherUnitsRepository.getUnits().distinctUntilChanged().onEach {
|
||||
weatherUnitsStore.set(it)
|
||||
}.launchIn(scope)
|
||||
}
|
||||
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
package com.pranshulgg.weather_master_app.core.managers.requests
|
||||
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.pranshulgg.weather_master_app.core.managers.LocationManager
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.location.Location
|
||||
import com.pranshulgg.weather_master_app.core.model.sources.Source
|
||||
import com.pranshulgg.weather_master_app.data.store.LocationStore
|
||||
import com.pranshulgg.weather_master_app.data.store.WeatherStore
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlin.time.Duration.Companion.minutes
|
||||
|
||||
@Singleton
|
||||
class AutoRefreshes @Inject constructor(
|
||||
private val locationStore: LocationStore,
|
||||
private val weatherStore: WeatherStore,
|
||||
private val pendingRequests: PendingRequests,
|
||||
private val locationManager: LocationManager
|
||||
) {
|
||||
private var autoRefreshJob: Job? = null
|
||||
|
||||
private val scope = CoroutineScope(SupervisorJob())
|
||||
|
||||
|
||||
fun start() {
|
||||
|
||||
if (autoRefreshJob?.isActive == true) return
|
||||
|
||||
autoRefreshJob = scope.launch {
|
||||
while (isActive) {
|
||||
delay(45.minutes)
|
||||
if (locationStore.data.value.isActiveLocationLoading || weatherStore.data.value.weather == null) {
|
||||
continue
|
||||
}
|
||||
|
||||
locationStore.data.value.activeLocation?.let {
|
||||
locationManager.setActiveLoading()
|
||||
pendingRequests.queueRequest(location = it, skipDeviceLocationCheck = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
autoRefreshJob?.cancel()
|
||||
autoRefreshJob = null
|
||||
}
|
||||
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package com.pranshulgg.weather_master_app.core.managers.requests
|
||||
|
||||
import android.util.Log
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.location.Location
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
data class WeatherRefreshRequestState(
|
||||
val location: Location,
|
||||
val isManualRefresh: Boolean,
|
||||
val forceRefresh: Boolean,
|
||||
val forceRefreshForAirQuality: Boolean,
|
||||
val forceRefreshForAlerts: Boolean,
|
||||
val skipDeviceLocationCheck: Boolean = false
|
||||
)
|
||||
|
||||
@Singleton
|
||||
class PendingRequests @Inject constructor() {
|
||||
|
||||
private val _pendingRequest =
|
||||
MutableStateFlow<WeatherRefreshRequestState?>(null)
|
||||
|
||||
val pendingRequest = _pendingRequest.asStateFlow()
|
||||
|
||||
fun queueRequest(
|
||||
location: Location,
|
||||
isManualRefresh: Boolean = false,
|
||||
isForceRefresh: Boolean = false,
|
||||
isForceRefreshForAirQuality: Boolean = false,
|
||||
isForceRefreshForAlerts: Boolean = false,
|
||||
skipDeviceLocationCheck: Boolean = false
|
||||
) {
|
||||
|
||||
|
||||
_pendingRequest.tryEmit(
|
||||
WeatherRefreshRequestState(
|
||||
location = location,
|
||||
forceRefresh = isForceRefresh,
|
||||
forceRefreshForAirQuality = isForceRefreshForAirQuality,
|
||||
forceRefreshForAlerts = isForceRefreshForAlerts,
|
||||
isManualRefresh = isManualRefresh,
|
||||
skipDeviceLocationCheck = skipDeviceLocationCheck
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -28,7 +28,9 @@ enum class MoonPhase(val displayName: Int, val icon: Int) {
|
||||
R.string.moonphase_last_quarter,
|
||||
R.drawable.moonphase_third_quarter
|
||||
), // TODO: FIX NAMING
|
||||
WANING_CRESCENT(R.string.moonphase_waning_crescent, R.drawable.moonphase_waning_crescent)
|
||||
WANING_CRESCENT(R.string.moonphase_waning_crescent, R.drawable.moonphase_waning_crescent),
|
||||
|
||||
UNKNOWN(R.string.weather_no_data, R.drawable.weather_not_available)
|
||||
}
|
||||
|
||||
fun getMoonPhase(phase: Double): MoonPhase {
|
||||
|
||||
+68
-4
@@ -1,26 +1,70 @@
|
||||
package com.pranshulgg.weather_master_app.core.model.domain
|
||||
|
||||
import coil.network.HttpException
|
||||
import com.pranshulgg.weather_master_app.R
|
||||
import java.io.IOException
|
||||
import java.net.ConnectException
|
||||
import java.net.NoRouteToHostException
|
||||
import java.net.SocketException
|
||||
import java.net.SocketTimeoutException
|
||||
import java.net.UnknownHostException
|
||||
import javax.net.ssl.SSLHandshakeException
|
||||
import javax.net.ssl.SSLPeerUnverifiedException
|
||||
import kotlin.coroutines.cancellation.CancellationException
|
||||
import retrofit2.HttpException
|
||||
|
||||
sealed class AppException(message: String? = null) : Exception(message) {
|
||||
class Network : AppException()
|
||||
class CurrentLocationUnavailable : AppException()
|
||||
class BadRequest : AppException()
|
||||
class Unauthorized : AppException()
|
||||
class Forbidden : AppException()
|
||||
class NotFound : AppException()
|
||||
class RequestTimeout : AppException()
|
||||
class TooManyRequests : AppException()
|
||||
class Server : AppException()
|
||||
|
||||
class Unknown : AppException()
|
||||
|
||||
class NoApiKeyError : AppException()
|
||||
|
||||
// A key was provided but the provider rejected it (invalid, revoked, or expired) -
|
||||
// sources can't tell those apart from an HTTP 401 alone, so the message stays generic.
|
||||
class ApiKeyRejectedError : AppException()
|
||||
|
||||
class SecureConnection : AppException()
|
||||
|
||||
class EmptyResponseBody : AppException()
|
||||
|
||||
class BackupSchemaVersionUnsupported : AppException()
|
||||
class BackupFileCorrupted : AppException()
|
||||
class BackupFileIOError : AppException()
|
||||
class BackupMissingDefaultLocation : AppException()
|
||||
|
||||
class RefreshNotAvailable : AppException()
|
||||
|
||||
}
|
||||
|
||||
fun AppException.toMessageRes(): Int {
|
||||
return when (this) {
|
||||
is AppException.Network -> R.string.error_network
|
||||
is AppException.CurrentLocationUnavailable -> R.string.current_location_not_found
|
||||
is AppException.BadRequest -> R.string.error_bad_request
|
||||
is AppException.Unauthorized -> R.string.error_unauthorized
|
||||
is AppException.Forbidden -> R.string.error_forbidden
|
||||
is AppException.NotFound -> R.string.error_not_found
|
||||
is AppException.RequestTimeout -> R.string.error_request_timeout
|
||||
is AppException.TooManyRequests -> R.string.error_too_many_requests
|
||||
is AppException.Server -> R.string.error_server
|
||||
is AppException.Unknown -> R.string.error_generic
|
||||
is AppException.NoApiKeyError -> R.string.error_no_api_key
|
||||
is AppException.ApiKeyRejectedError -> R.string.error_api_key_rejected
|
||||
is AppException.SecureConnection -> R.string.error_secure_connection_failed
|
||||
is AppException.EmptyResponseBody -> R.string.error_empty_response_body
|
||||
is AppException.BackupSchemaVersionUnsupported -> R.string.error_backup_schema_unsupported
|
||||
is AppException.BackupFileCorrupted -> R.string.error_backup_file_corrupted
|
||||
is AppException.BackupFileIOError -> R.string.error_backup_file_io
|
||||
is AppException.BackupMissingDefaultLocation -> R.string.error_backup_missing_default_location
|
||||
is AppException.RefreshNotAvailable -> R.string.weather_refresh_delay_fixed
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,11 +72,31 @@ fun Throwable.toAppException(): AppException {
|
||||
if (this is CancellationException) throw this
|
||||
|
||||
return when (this) {
|
||||
is UnknownHostException,
|
||||
is SocketTimeoutException,
|
||||
is AppException -> this
|
||||
|
||||
is SSLHandshakeException -> AppException.SecureConnection()
|
||||
is SSLPeerUnverifiedException -> AppException.SecureConnection()
|
||||
|
||||
is UnknownHostException -> AppException.Network()
|
||||
is ConnectException -> AppException.Network()
|
||||
is NoRouteToHostException -> AppException.Network()
|
||||
is SocketException -> AppException.Network()
|
||||
|
||||
is SocketTimeoutException -> AppException.RequestTimeout()
|
||||
|
||||
is IOException -> AppException.Network()
|
||||
|
||||
is HttpException -> AppException.Server()
|
||||
is HttpException -> when (this.code()) {
|
||||
400 -> AppException.BadRequest()
|
||||
401 -> AppException.Unauthorized()
|
||||
403 -> AppException.Forbidden()
|
||||
404 -> AppException.NotFound()
|
||||
408 -> AppException.RequestTimeout()
|
||||
429 -> AppException.TooManyRequests()
|
||||
in 500..599 -> AppException.Server()
|
||||
else -> AppException.Unknown()
|
||||
}
|
||||
|
||||
|
||||
else -> AppException.Unknown()
|
||||
}
|
||||
|
||||
+62
-1
@@ -11,7 +11,8 @@ import kotlin.math.roundToInt
|
||||
* We only display air quality if it's available
|
||||
*/
|
||||
data class AirQuality(
|
||||
val current: AirQualityCurrent
|
||||
val current: AirQualityCurrent,
|
||||
val hourly: List<AirQualityHourly>
|
||||
) {
|
||||
companion object {
|
||||
|
||||
@@ -78,6 +79,29 @@ data class AirQuality(
|
||||
)
|
||||
}
|
||||
|
||||
fun getAqiFromValues(
|
||||
carbonMonoxideMicrogramsPerCubicMeter: Double?,
|
||||
pm25: Double?,
|
||||
nitrogenDioxide: Double?,
|
||||
ozone: Double?,
|
||||
pm10: Double?,
|
||||
sulphurDioxide: Double?
|
||||
): Int {
|
||||
|
||||
// Open-Meteo provides "carbon_monoxide" in MicrogramsPerCubicMeter so we convert to Milligrams
|
||||
val coInMilligramsPerCubicMeter = (carbonMonoxideMicrogramsPerCubicMeter!! / 1000)
|
||||
|
||||
|
||||
return maxOf(
|
||||
getAqi(pm25!!, pm25Thresholds),
|
||||
getAqi(nitrogenDioxide!!, no2Thresholds),
|
||||
getAqi(ozone!!, o3Thresholds),
|
||||
getAqi(pm10!!, pm10Thresholds),
|
||||
getAqi(coInMilligramsPerCubicMeter, coThresholds),
|
||||
getAqi(sulphurDioxide!!, so2Thresholds)
|
||||
)
|
||||
}
|
||||
|
||||
// For AQI bars
|
||||
fun getAqiBarValue(aqi: Int): Float {
|
||||
return (aqi / 250f).coerceIn(0f, 1f)
|
||||
@@ -105,11 +129,48 @@ data class AirQuality(
|
||||
|
||||
data class AirQualityCurrent(
|
||||
val usAqi: Int?,
|
||||
|
||||
/** µg/m³. */
|
||||
val pm10: Double?,
|
||||
|
||||
/** µg/m³. */
|
||||
val pm25: Double?,
|
||||
|
||||
/** µg/m³. */
|
||||
val carbonMonoxide: Double?,
|
||||
|
||||
/** µg/m³. */
|
||||
val nitrogenDioxide: Double?,
|
||||
|
||||
/** µg/m³. */
|
||||
val sulphurDioxide: Double?,
|
||||
|
||||
/** µg/m³. */
|
||||
val ozone: Double?,
|
||||
|
||||
/** Milliseconds */
|
||||
val lastUpdatedInMilli: Long
|
||||
)
|
||||
|
||||
data class AirQualityHourly(
|
||||
/** µg/m³. */
|
||||
val pm10: Double?,
|
||||
|
||||
/** µg/m³. */
|
||||
val pm25: Double?,
|
||||
|
||||
/** µg/m³. */
|
||||
val carbonMonoxide: Double?,
|
||||
|
||||
/** µg/m³. */
|
||||
val nitrogenDioxide: Double?,
|
||||
|
||||
/** µg/m³. */
|
||||
val sulphurDioxide: Double?,
|
||||
|
||||
/** µg/m³. */
|
||||
val ozone: Double?,
|
||||
|
||||
/** Seconds */
|
||||
val time: Long,
|
||||
)
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.pranshulgg.weather_master_app.core.model.domain.alerts
|
||||
|
||||
import com.pranshulgg.weather_master_app.core.model.weather.alerts.AlertSeverity
|
||||
|
||||
|
||||
data class Alert(
|
||||
val locationId: String,
|
||||
val event: String,
|
||||
val severity: AlertSeverity?,
|
||||
val effective: Long?,
|
||||
val expires: Long?,
|
||||
val description: String,
|
||||
val source: String?,
|
||||
val lastUpdatedInMilli: Long
|
||||
)
|
||||
+2
-1
@@ -2,5 +2,6 @@ package com.pranshulgg.weather_master_app.core.model.domain.location
|
||||
|
||||
data class Address(
|
||||
val city: String?,
|
||||
val country: String
|
||||
val country: String,
|
||||
val countryCode: String?
|
||||
)
|
||||
+9
-3
@@ -1,6 +1,7 @@
|
||||
package com.pranshulgg.weather_master_app.core.model.domain.location
|
||||
|
||||
import com.pranshulgg.weather_master_app.core.model.sources.WeatherSource
|
||||
import com.pranshulgg.weather_master_app.core.model.sources.Source
|
||||
import com.pranshulgg.weather_master_app.core.model.weather.openmeteo.OpenMeteoModel
|
||||
|
||||
data class Location(
|
||||
val id: String,
|
||||
@@ -11,9 +12,14 @@ data class Location(
|
||||
val timezone: String,
|
||||
val countryCode: String?,
|
||||
val state: String,
|
||||
val source: WeatherSource = WeatherSource.OPEN_METEO,
|
||||
val source: Source = Source.OPEN_METEO,
|
||||
val isFavorite: Boolean = false,
|
||||
val isPinned: Boolean = false,
|
||||
val isDefault: Boolean,
|
||||
val isDeviceLocation: Boolean = false
|
||||
val isDeviceLocation: Boolean = false,
|
||||
val alertSource: Source = Source.NONE,
|
||||
val airQualitySource: Source = Source.OPEN_METEO,
|
||||
val customName: String? = null,
|
||||
val openMeteoModel: OpenMeteoModel = OpenMeteoModel.BEST_MATCH,
|
||||
val alertsLastFetchedAt: Long? = null
|
||||
)
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package com.pranshulgg.weather_master_app.core.model.domain.location
|
||||
|
||||
data class LocationKey(
|
||||
val locationId: String,
|
||||
val cityKey: String
|
||||
)
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package com.pranshulgg.weather_master_app.core.model.domain.weather
|
||||
|
||||
import com.pranshulgg.weather_master_app.core.model.sources.Source
|
||||
import com.pranshulgg.weather_master_app.data.local.entity.weather.ApiKeyEntity
|
||||
|
||||
data class ApiKey(
|
||||
val id: Long,
|
||||
val source: Source,
|
||||
val apiKey: String? = null
|
||||
)
|
||||
+42
-9
@@ -14,7 +14,7 @@ data class Weather(
|
||||
|
||||
data class WeatherCurrent(
|
||||
val temperature: Double?, // NOTE: ALWAYS C
|
||||
val humidity: Double,
|
||||
val humidity: Double?,
|
||||
val windSpeed: Double?, // NOTE: ALWAYS KMH
|
||||
val windDirection: WindDirection?, // NOTE: ALWAYS DOMINANT
|
||||
val pressureMsl: Double?, // NOTE: ALWAYS HPA
|
||||
@@ -23,7 +23,6 @@ data class WeatherCurrent(
|
||||
val uvIndex: Double?,
|
||||
val weatherCondition: WeatherCondition,
|
||||
val feelsLike: Double?,
|
||||
val time: Long, // NOTE: ALWAYS MILLISECONDS
|
||||
val dewPoint: Double?,
|
||||
val utcOffsetSeconds: Long?,
|
||||
val lastUpdatedInMilli: Long
|
||||
@@ -52,6 +51,11 @@ data class WeatherCurrent(
|
||||
fun isUvIndexValid(): Boolean {
|
||||
return uvIndex != null
|
||||
}
|
||||
|
||||
fun isHumidityValid(): Boolean {
|
||||
return humidity != null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data class WeatherHourly(
|
||||
@@ -85,7 +89,7 @@ data class WeatherHourly(
|
||||
data class WeatherDaily(
|
||||
val temperatureMin: Double?, // NOTE: ALWAYS C
|
||||
val temperatureMax: Double?, // NOTE: ALWAYS C
|
||||
val windSpeed: Double?, // NOTE: ALWAYS KMH
|
||||
val windSpeed: Double?, // NOTE: ALWAYS KMH (Average)
|
||||
val windDirection: WindDirection?, // NOTE: ALWAYS DOMINANT
|
||||
val rainSum: Double, // NOTE: ALWAYS MM
|
||||
val snowfallSum: Double?, // NOTE: ALWAYS CM
|
||||
@@ -93,13 +97,17 @@ data class WeatherDaily(
|
||||
val weatherCondition: WeatherCondition,
|
||||
val time: Long, // NOTE: ALWAYS MILLISECONDS
|
||||
val precipitationProbabilityMax: Int?,
|
||||
val sunrise: Long, // NOTE: ALWAYS MILLISECONDS
|
||||
val sunset: Long, // NOTE: ALWAYS MILLISECONDS
|
||||
val moonrise: Long, // NOTE: ALWAYS MILLISECONDS
|
||||
val moonset: Long, // NOTE: ALWAYS MILLISECONDS
|
||||
val pressureMsl: Double?, // NOTE: ALWAYS HPA (Average)
|
||||
val visibility: Int?, // NOTE: ALWAYS METERS (Minimum)
|
||||
val humidity: Double?, // (Average)
|
||||
val dewPoint: Double?, // (Average)
|
||||
val sunrise: Long?, // NOTE: ALWAYS MILLISECONDS
|
||||
val sunset: Long?, // NOTE: ALWAYS MILLISECONDS
|
||||
val moonrise: Long?, // NOTE: ALWAYS MILLISECONDS
|
||||
val moonset: Long?, // NOTE: ALWAYS MILLISECONDS
|
||||
val moonPhase: MoonPhase,
|
||||
val dawn: Long,
|
||||
val dusk: Long
|
||||
val dawn: Long?,
|
||||
val dusk: Long?
|
||||
) {
|
||||
|
||||
fun isWindSpeedValid(): Boolean {
|
||||
@@ -117,4 +125,29 @@ data class WeatherDaily(
|
||||
fun isUvIndexMaxValid(): Boolean {
|
||||
return uvIndexMax != null
|
||||
}
|
||||
|
||||
fun isVisibilityValid(): Boolean {
|
||||
return visibility != null && visibility != -1
|
||||
}
|
||||
|
||||
fun isHumidityValid(): Boolean {
|
||||
return humidity != null && humidity != -1.0
|
||||
}
|
||||
|
||||
fun isDewPointValid(): Boolean {
|
||||
return dewPoint != null
|
||||
}
|
||||
|
||||
fun isPressureValid(): Boolean {
|
||||
return pressureMsl != null && pressureMsl != -1.0
|
||||
}
|
||||
|
||||
fun isMoonValid(): Boolean {
|
||||
return moonrise != null && moonset != null
|
||||
}
|
||||
|
||||
|
||||
fun isSunValid(): Boolean {
|
||||
return sunrise != null && sunset != null
|
||||
}
|
||||
}
|
||||
+22
@@ -142,7 +142,29 @@ data class WeatherBlock(
|
||||
isDaily = true,
|
||||
id = (999L..2000L).random()
|
||||
),
|
||||
WeatherBlock(
|
||||
type = WeatherBlockType.HUMIDITY_BLOCK,
|
||||
isHidden = false,
|
||||
position = 6,
|
||||
isDaily = true,
|
||||
id = (999L..2000L).random()
|
||||
),
|
||||
WeatherBlock(
|
||||
type = WeatherBlockType.PRESSURE_BLOCK,
|
||||
isHidden = false,
|
||||
position = 7,
|
||||
isDaily = true,
|
||||
id = (999L..2000L).random()
|
||||
),
|
||||
WeatherBlock(
|
||||
type = WeatherBlockType.VISIBILITY_BLOCK,
|
||||
isHidden = false,
|
||||
position = 8,
|
||||
isDaily = true,
|
||||
id = (999L..2000L).random()
|
||||
),
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -2,5 +2,6 @@ package com.pranshulgg.weather_master_app.core.model.sources
|
||||
|
||||
enum class SearchSource(val displayName: String) {
|
||||
OPEN_METEO("Open Meteo"),
|
||||
GEO_NAMES("GeoNames")
|
||||
GEO_NAMES("GeoNames"),
|
||||
ACCU_WEATHER("AccuWeather")
|
||||
}
|
||||
@@ -0,0 +1,333 @@
|
||||
package com.pranshulgg.weather_master_app.core.model.sources
|
||||
|
||||
import com.pranshulgg.weather_master_app.R
|
||||
|
||||
|
||||
// TODO: implement alerts / air quality for sources that support it
|
||||
enum class Source(
|
||||
val displayName: String,
|
||||
val hourlyAggregationLimitHours: Int = 24, // stupid and should be removed
|
||||
val displayLink: String,
|
||||
val fullName: String,
|
||||
val countryNameRes: Int? = null,
|
||||
val requiresUserApiKey: Boolean = false, // Source must not be selectable until the user has provided their API key
|
||||
val signupLink: String? = null, // Shown instead of displayLink on the API key entry screen, when set
|
||||
val apiKeyNote: String? = null, // Optional hint shown under the link on the API key entry screen
|
||||
val regionalButWorldwideSupport: Boolean = false,
|
||||
val capabilities: Set<Capability>,
|
||||
// val providesAlerts: Boolean = false,
|
||||
// val providesAirQuality: Boolean = false,
|
||||
) {
|
||||
OPEN_METEO(
|
||||
displayName = "Open Meteo",
|
||||
fullName = "Open Meteo",
|
||||
displayLink = "https://open-meteo.com/",
|
||||
capabilities = setOf(Capability.WEATHER, Capability.AIR_QUALITY)
|
||||
),
|
||||
NWS(
|
||||
displayName = "NWS",
|
||||
fullName = "National Weather Service",
|
||||
displayLink = "https://www.weather.gov/documentation/services-web-api",
|
||||
countryNameRes = R.string.country_usa,
|
||||
capabilities = setOf(Capability.WEATHER, Capability.ALERTS)
|
||||
),
|
||||
SMHI(
|
||||
displayName = "SMHI",
|
||||
fullName = "Swedish Meteorological and Hydrological Institute",
|
||||
displayLink = "https://opendata.smhi.se",
|
||||
countryNameRes = R.string.country_sweden,
|
||||
capabilities = setOf(Capability.WEATHER)
|
||||
),
|
||||
DWD(
|
||||
displayName = "DWD",
|
||||
fullName = "Bright Sky DWD",
|
||||
displayLink = "https://brightsky.dev",
|
||||
countryNameRes = R.string.country_germany,
|
||||
capabilities = setOf(Capability.WEATHER)
|
||||
),
|
||||
METEO_FRANCE(
|
||||
displayName = "Météo-France",
|
||||
fullName = "Météo-France",
|
||||
displayLink = "https://meteofrance.com/",
|
||||
regionalButWorldwideSupport = true,
|
||||
capabilities = setOf(Capability.WEATHER)
|
||||
),
|
||||
ECCC(
|
||||
displayName = "ECCC",
|
||||
fullName = "Environment and Climate Change Canada",
|
||||
displayLink = "https://app.weather.gc.ca/",
|
||||
countryNameRes = R.string.country_canada,
|
||||
capabilities = setOf(Capability.WEATHER)
|
||||
),
|
||||
FMI(
|
||||
displayName = "FMI",
|
||||
fullName = "Finnish Meteorological Institute",
|
||||
displayLink = "https://en.ilmatieteenlaitos.fi/",
|
||||
countryNameRes = R.string.country_finland,
|
||||
capabilities = setOf(Capability.WEATHER)
|
||||
),
|
||||
CHINA(
|
||||
displayName = "China",
|
||||
fullName = "China National Environmental Monitoring Centre",
|
||||
displayLink = "https://www.cnemc.cn/",
|
||||
capabilities = setOf(Capability.WEATHER)
|
||||
),
|
||||
BMKG(
|
||||
displayName = "BMKG",
|
||||
fullName = "Badan Meteorologi, Klimatologi, dan Geofisika",
|
||||
displayLink = "https://www.bmkg.go.id/",
|
||||
countryNameRes = R.string.country_indonesia,
|
||||
capabilities = setOf(Capability.WEATHER)
|
||||
),
|
||||
ACCU_WEATHER(
|
||||
displayName = "AccuWeather",
|
||||
fullName = "AccuWeather",
|
||||
displayLink = "https://www.accuweather.com/",
|
||||
capabilities = setOf(Capability.WEATHER, Capability.ALERTS, Capability.AIR_QUALITY)
|
||||
),
|
||||
METEO_AM(
|
||||
displayName = "Meteo AM",
|
||||
fullName = "Meteorologia Aeronautica Militare",
|
||||
displayLink = "https://www.meteoam.it/",
|
||||
countryNameRes = R.string.country_italy,
|
||||
capabilities = setOf(Capability.WEATHER)
|
||||
),
|
||||
IPMA(
|
||||
displayName = "IPMA",
|
||||
fullName = "Instituto Português do Mar e da Atmosfera",
|
||||
displayLink = "https://api.ipma.pt/",
|
||||
countryNameRes = R.string.country_portugal,
|
||||
capabilities = setOf(Capability.WEATHER)
|
||||
),
|
||||
GISMETEO(
|
||||
displayName = "Gismeteo",
|
||||
fullName = "Gismeteo",
|
||||
displayLink = "https://www.gismeteo.ru/",
|
||||
countryNameRes = R.string.country_russia,
|
||||
regionalButWorldwideSupport = true,
|
||||
capabilities = setOf(Capability.WEATHER)
|
||||
),
|
||||
METEOFOR(
|
||||
displayName = "Meteofor",
|
||||
fullName = "Meteofor",
|
||||
displayLink = "https://meteofor.com.ua/",
|
||||
countryNameRes = R.string.country_ukraine,
|
||||
capabilities = setOf(Capability.WEATHER)
|
||||
),
|
||||
MET_OFFICE(
|
||||
displayName = "Met Office",
|
||||
fullName = "Meteorological Office",
|
||||
displayLink = "https://www.metoffice.gov.uk/",
|
||||
countryNameRes = R.string.country_united_kingdom,
|
||||
requiresUserApiKey = true,
|
||||
signupLink = "https://datahub.metoffice.gov.uk/pricing/site-specific",
|
||||
apiKeyNote = "Subscribe to the \"Global Spot\" option",
|
||||
regionalButWorldwideSupport = true,
|
||||
capabilities = setOf(Capability.WEATHER)
|
||||
),
|
||||
PIRATE_WEATHER(
|
||||
displayName = "Pirate Weather",
|
||||
fullName = "Pirate Weather",
|
||||
displayLink = "https://pirateweather.net/",
|
||||
requiresUserApiKey = true,
|
||||
regionalButWorldwideSupport = false,
|
||||
capabilities = setOf(Capability.WEATHER, Capability.ALERTS)
|
||||
),
|
||||
IMD(
|
||||
displayName = "IMD",
|
||||
fullName = "India Meteorological Department",
|
||||
displayLink = "https://mausam.imd.gov.in/",
|
||||
countryNameRes = R.string.country_india,
|
||||
capabilities = setOf(Capability.WEATHER)
|
||||
),
|
||||
MET_NORWAY(
|
||||
displayName = "Met Norway",
|
||||
fullName = "Met Norway",
|
||||
displayLink = "https://api.met.no/",
|
||||
regionalButWorldwideSupport = true,
|
||||
capabilities = setOf(Capability.WEATHER)
|
||||
),
|
||||
AEMET(
|
||||
displayName = "AEMET",
|
||||
fullName = "Agencia Estatal de Meteorología",
|
||||
displayLink = "https://opendata.aemet.es/centrodedescargas/altaUsuario",
|
||||
countryNameRes = R.string.country_spain,
|
||||
requiresUserApiKey = true,
|
||||
capabilities = setOf(Capability.WEATHER)
|
||||
),
|
||||
|
||||
WEATHER_API(
|
||||
displayName = "Weather API",
|
||||
fullName = "Weather API",
|
||||
displayLink = "https://www.weatherapi.com/",
|
||||
capabilities = setOf(Capability.ALERTS)
|
||||
),
|
||||
WMO_SEVERE_WEATHER(
|
||||
displayName = "WMO Severe Weather",
|
||||
fullName = "WMO Severe Weather Information Centre",
|
||||
displayLink = "https://www.wmo.int/",
|
||||
capabilities = setOf(Capability.ALERTS)
|
||||
),
|
||||
FPAS(
|
||||
displayName = "FOSS Public Alert Server",
|
||||
fullName = "FOSS Public Alert Server",
|
||||
displayLink = "https://invent.kde.org/webapps/foss-public-alert-server",
|
||||
capabilities = setOf(Capability.ALERTS)
|
||||
),
|
||||
NONE(
|
||||
displayName = "None",
|
||||
fullName = "",
|
||||
displayLink = "",
|
||||
capabilities = setOf(Capability.ALERTS, Capability.AIR_QUALITY)
|
||||
),
|
||||
CWA(
|
||||
displayName = "CWA",
|
||||
fullName = "Central Weather Administration",
|
||||
displayLink = "https://opendata.cwa.gov.tw/",
|
||||
countryNameRes = R.string.country_taiwan,
|
||||
requiresUserApiKey = true,
|
||||
capabilities = setOf(Capability.WEATHER)
|
||||
),
|
||||
JMA(
|
||||
displayName = "JMA",
|
||||
fullName = "Japan Meteorological Agency",
|
||||
displayLink = "https://www.jma.go.jp/bosai/",
|
||||
countryNameRes = R.string.country_japan,
|
||||
capabilities = setOf(Capability.WEATHER, Capability.ALERTS)
|
||||
),
|
||||
INMET(
|
||||
displayName = "INMET",
|
||||
fullName = "Instituto Nacional de Meteorologia",
|
||||
displayLink = "https://portal.inmet.gov.br/",
|
||||
countryNameRes = R.string.country_brazil,
|
||||
capabilities = setOf(Capability.WEATHER, Capability.ALERTS)
|
||||
),
|
||||
|
||||
MGM(
|
||||
displayName = "MGM",
|
||||
fullName = "Meteoroloji Genel Müdürlüğü",
|
||||
displayLink = "https://www.mgm.gov.tr/",
|
||||
countryNameRes = R.string.country_turkey,
|
||||
capabilities = setOf(Capability.WEATHER, Capability.ALERTS)
|
||||
),
|
||||
KMI(
|
||||
displayName = "KMI",
|
||||
fullName = "Royal Meteorological Institute of Belgium",
|
||||
displayLink = "https://www.meteo.be/",
|
||||
countryNameRes = R.string.country_belgium,
|
||||
capabilities = setOf(Capability.WEATHER, Capability.ALERTS)
|
||||
),
|
||||
OPEN_WEATHER(
|
||||
displayName = "OpenWeather",
|
||||
fullName = "OpenWeather",
|
||||
apiKeyNote = "To use One Call 4.0, append '&one_call_4' to the end of your API key (e.g., your_api_key&one_call_4). This requires an active One Call 4.0 subscription",
|
||||
displayLink = "https://openweathermap.org/",
|
||||
capabilities = setOf(Capability.WEATHER, Capability.AIR_QUALITY),
|
||||
requiresUserApiKey = true
|
||||
),
|
||||
MOENV(
|
||||
displayName = "MOENV",
|
||||
fullName = "Ministry of Environment",
|
||||
displayLink = "https://data.moenv.gov.tw/en/dataset/detail/aqx_p_432",
|
||||
countryNameRes = R.string.country_taiwan,
|
||||
requiresUserApiKey = true,
|
||||
signupLink = "https://data.moenv.gov.tw/api_term",
|
||||
apiKeyNote = "Check \"Atmosphere\" under Follow dataset categories when signing up",
|
||||
capabilities = setOf(Capability.AIR_QUALITY)
|
||||
);
|
||||
|
||||
// Sources that provide snow/rain as precipitation
|
||||
fun providesSnowFall(): Boolean {
|
||||
return when (this) {
|
||||
MET_NORWAY -> false
|
||||
DWD -> false
|
||||
CHINA -> false
|
||||
BMKG -> false
|
||||
IMD -> false
|
||||
CWA -> false
|
||||
JMA -> false
|
||||
INMET -> false
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// WE MAP EVERY WEATHER SOURCE HERE, AS THEY GET ADDED
|
||||
|
||||
private val sourcesByCountry = buildMap {
|
||||
put("US", listOf(Source.NWS))
|
||||
put("SE", listOf(Source.SMHI))
|
||||
put("DE", listOf(Source.DWD))
|
||||
put("CA", listOf(Source.ECCC))
|
||||
put("FI", listOf(Source.FMI))
|
||||
put("CN", listOf(Source.CHINA))
|
||||
put("ID", listOf(Source.BMKG))
|
||||
listOf("IT", "VA").forEach { put(it, listOf(Source.METEO_AM)) }
|
||||
put("PT", listOf(Source.IPMA))
|
||||
put("RU", listOf(Source.GISMETEO))
|
||||
put("UA", listOf(Source.METEOFOR))
|
||||
listOf("GB", "UK").forEach { put(it, listOf(Source.MET_OFFICE)) }
|
||||
put("NO", listOf(Source.MET_NORWAY))
|
||||
put("FR", listOf(Source.METEO_FRANCE))
|
||||
put("ES", listOf(Source.AEMET))
|
||||
put("IN", listOf(Source.IMD))
|
||||
put("TW", listOf(Source.CWA, Source.MOENV))
|
||||
put("JP", listOf(Source.JMA))
|
||||
put("BR", listOf(Source.INMET))
|
||||
put("TR", listOf(Source.MGM))
|
||||
put("BE", listOf(Source.KMI))
|
||||
|
||||
}
|
||||
|
||||
fun getSourcesForCountry(countryCode: String?): List<Source> {
|
||||
return sourcesByCountry[countryCode] ?: emptyList()
|
||||
}
|
||||
|
||||
/**
|
||||
* Any source that has global coverage,
|
||||
* including regional sources with global data,
|
||||
* must be added here.
|
||||
*/
|
||||
private val sourcesGlobal = listOf(
|
||||
|
||||
// GLOBAL
|
||||
Source.OPEN_METEO,
|
||||
Source.ACCU_WEATHER,
|
||||
Source.PIRATE_WEATHER,
|
||||
Source.OPEN_WEATHER,
|
||||
|
||||
// REGIONAL WITH GLOBAL
|
||||
Source.GISMETEO,
|
||||
Source.MET_OFFICE,
|
||||
Source.MET_NORWAY,
|
||||
Source.METEO_FRANCE,
|
||||
|
||||
// ALERTS
|
||||
Source.WEATHER_API,
|
||||
Source.WMO_SEVERE_WEATHER,
|
||||
Source.FPAS,
|
||||
|
||||
// Yes, "NONE" is a global source :P
|
||||
Source.NONE
|
||||
)
|
||||
|
||||
fun getSourcesGlobal(): List<Source> {
|
||||
return sourcesGlobal
|
||||
}
|
||||
|
||||
fun Source.isSourceSupportedFor(countryCode: String?): Boolean {
|
||||
val source = sourcesByCountry[countryCode] ?: return false
|
||||
|
||||
return this in source
|
||||
}
|
||||
|
||||
fun Source.isGlobal(): Boolean {
|
||||
return this in sourcesGlobal
|
||||
}
|
||||
|
||||
enum class Capability {
|
||||
WEATHER,
|
||||
ALERTS,
|
||||
AIR_QUALITY
|
||||
}
|
||||
-69
@@ -1,69 +0,0 @@
|
||||
package com.pranshulgg.weather_master_app.core.model.sources
|
||||
|
||||
enum class WeatherSource(
|
||||
val displayName: String,
|
||||
val hourlyAggregationLimitHours: Int,
|
||||
val displayLink: String
|
||||
) {
|
||||
OPEN_METEO(
|
||||
displayName = "Open Meteo",
|
||||
hourlyAggregationLimitHours = 24,
|
||||
displayLink = "https://open-meteo.com/"
|
||||
),
|
||||
NWS(
|
||||
displayName = "National Weather Service",
|
||||
hourlyAggregationLimitHours = 24,
|
||||
displayLink = "https://www.weather.gov/documentation/services-web-api"
|
||||
),
|
||||
SMHI(
|
||||
displayName = "SMHI (Sweden)",
|
||||
hourlyAggregationLimitHours = 24,
|
||||
displayLink = "https://opendata.smhi.se"
|
||||
),
|
||||
DWD(
|
||||
displayName = "Bright Sky DWD (Germany)",
|
||||
hourlyAggregationLimitHours = 24,
|
||||
displayLink = "https://brightsky.dev"
|
||||
),
|
||||
METEO_FRANCE(
|
||||
displayName = "Météo-France",
|
||||
hourlyAggregationLimitHours = 24,
|
||||
displayLink = "https://meteofrance.com/"
|
||||
),
|
||||
MET_NORWAY(
|
||||
displayName = "Met Norway",
|
||||
hourlyAggregationLimitHours = 24,
|
||||
"https://api.met.no/"
|
||||
);
|
||||
|
||||
fun providesSnowFall(): Boolean {
|
||||
return when (this) {
|
||||
MET_NORWAY -> false
|
||||
DWD -> false
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// WE MAP EVERY WEATHER SOURCE HERE, AS THEY GET ADDED
|
||||
private val weatherSourcesByCountry = mapOf(
|
||||
"US" to listOf(WeatherSource.NWS),
|
||||
"SE" to listOf(WeatherSource.SMHI),
|
||||
"DE" to listOf(WeatherSource.DWD)
|
||||
)
|
||||
|
||||
fun getWeatherSourcesForCountry(countryCode: String?): List<WeatherSource> {
|
||||
return weatherSourcesByCountry[countryCode] ?: emptyList()
|
||||
}
|
||||
|
||||
|
||||
// GLOBAL SOURCES
|
||||
private val weatherSourcesGlobal = listOf(
|
||||
WeatherSource.OPEN_METEO, WeatherSource.MET_NORWAY,
|
||||
WeatherSource.METEO_FRANCE
|
||||
)
|
||||
|
||||
fun getWeatherSourcesGlobal(): List<WeatherSource> {
|
||||
return weatherSourcesGlobal
|
||||
}
|
||||
@@ -182,34 +182,56 @@ fun TemperatureUnit.toName(context: Context): String {
|
||||
|
||||
fun WindSpeedUnit.toName(context: Context, inShort: Boolean = false): String {
|
||||
return when (this) {
|
||||
MPS -> if (inShort) "m/s" else context.getString(R.string.unit_wind_mps)
|
||||
MPH -> if (inShort) "mi/h" else context.getString(R.string.unit_wind_mph)
|
||||
KPH -> if (inShort) "km/h" else context.getString(R.string.unit_wind_kph)
|
||||
KT -> if (inShort) "kt" else context.getString(R.string.unit_wind_kt)
|
||||
BFT -> if (inShort) "bft" else context.getString(R.string.unit_wind_bft)
|
||||
MPS -> if (inShort) context.getString(R.string.unit_wind_mps_short) else context.getString(R.string.unit_wind_mps)
|
||||
MPH -> if (inShort) context.getString(R.string.unit_wind_mph_short) else context.getString(R.string.unit_wind_mph)
|
||||
KPH -> if (inShort) context.getString(R.string.unit_wind_kph_short) else context.getString(R.string.unit_wind_kph)
|
||||
KT -> if (inShort) context.getString(R.string.unit_wind_kt_short) else context.getString(R.string.unit_wind_kt)
|
||||
BFT -> if (inShort) context.getString(R.string.unit_wind_bft_short) else context.getString(R.string.unit_wind_bft)
|
||||
}
|
||||
}
|
||||
|
||||
fun PressureUnit.toName(inShort: Boolean = false, context: Context): String {
|
||||
return when (this) {
|
||||
HPA -> if (inShort) "hPa" else context.getString(R.string.unit_pressure_hpa)
|
||||
INHG -> if (inShort) "inHG" else context.getString(R.string.unit_pressure_inhg)
|
||||
PressureUnit.MMHG -> if (inShort) "mmHG" else context.getString(R.string.unit_pressure_mmhg)
|
||||
HPA -> if (inShort) context.getString(R.string.unit_pressure_hpa_short) else context.getString(
|
||||
R.string.unit_pressure_hpa
|
||||
)
|
||||
|
||||
INHG -> if (inShort) context.getString(R.string.unit_pressure_inhg_short) else context.getString(
|
||||
R.string.unit_pressure_inhg
|
||||
)
|
||||
|
||||
PressureUnit.MMHG -> if (inShort) context.getString(R.string.unit_pressure_mmhg_short) else context.getString(
|
||||
R.string.unit_pressure_mmhg
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun DistanceUnit.toName(inShort: Boolean = false, context: Context): String {
|
||||
return when (this) {
|
||||
KM -> if (inShort) "km" else context.getString(R.string.unit_distance_km)
|
||||
MI -> if (inShort) "mi" else context.getString(R.string.unit_distance_mi)
|
||||
M -> if (inShort) "m" else context.getString(R.string.unit_distance_m)
|
||||
KM -> if (inShort) context.getString(R.string.unit_distance_km_short) else context.getString(
|
||||
R.string.unit_distance_km
|
||||
)
|
||||
|
||||
MI -> if (inShort) context.getString(R.string.unit_distance_mi_short) else context.getString(
|
||||
R.string.unit_distance_mi
|
||||
)
|
||||
|
||||
M -> if (inShort) context.getString(R.string.unit_distance_m_short) else context.getString(R.string.unit_distance_m)
|
||||
}
|
||||
}
|
||||
|
||||
fun PrecipitationUnit.toName(context: Context, inShort: Boolean = false): String {
|
||||
return when (this) {
|
||||
PrecipitationUnit.MM -> if (inShort) "mm" else context.getString(R.string.unit_precipitation_mm)
|
||||
PrecipitationUnit.INCH -> if (inShort) "in" else context.getString(R.string.unit_precipitation_inch)
|
||||
PrecipitationUnit.CM -> if (inShort) "cm" else context.getString(R.string.unit_precipitation_cm)
|
||||
PrecipitationUnit.MM -> if (inShort) context.getString(R.string.unit_precipitation_mm_short) else context.getString(
|
||||
R.string.unit_precipitation_mm
|
||||
)
|
||||
|
||||
PrecipitationUnit.INCH -> if (inShort) context.getString(R.string.unit_precipitation_inch_short) else context.getString(
|
||||
R.string.unit_precipitation_inch
|
||||
)
|
||||
|
||||
PrecipitationUnit.CM -> if (inShort) context.getString(R.string.unit_precipitation_cm_short) else context.getString(
|
||||
R.string.unit_precipitation_cm
|
||||
)
|
||||
}
|
||||
}
|
||||
+25
-7
@@ -5,7 +5,11 @@ import com.pranshulgg.weather_master_app.R
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.weather.WeatherDaily
|
||||
|
||||
|
||||
// TODO: ADD SLEET, HAIL, WINDY, BLIZZARD, TORNADO, HURRICANE
|
||||
// TODO: WINDY, BLIZZARD, TORNADO, HURRICANE
|
||||
/**
|
||||
* SLEET AND HAIL is supported but not mapped to many sources yet
|
||||
* TODO: FIX IT
|
||||
*/
|
||||
enum class WeatherCondition {
|
||||
CLEAR_SKY,
|
||||
OVERCAST,
|
||||
@@ -23,6 +27,10 @@ enum class WeatherCondition {
|
||||
|
||||
RAIN,
|
||||
|
||||
SLEET,
|
||||
HAIL,
|
||||
MIXED_PRECIPITATION,
|
||||
|
||||
NO_CONDITION_FOUND,
|
||||
|
||||
// USED FOR DAILY
|
||||
@@ -64,7 +72,7 @@ enum class WeatherCondition {
|
||||
// ------- MAP TO ICONS -------
|
||||
|
||||
fun WeatherCondition.toIcon(daily: WeatherDaily? = null, targetTimeMilli: Long): Int {
|
||||
val isDay = if (daily != null) {
|
||||
val isDay = if (daily != null && daily.sunrise != null && daily.sunset != null) {
|
||||
targetTimeMilli in daily.sunrise..daily.sunset
|
||||
} else {
|
||||
true
|
||||
@@ -78,7 +86,7 @@ fun WeatherCondition.toIcon(daily: WeatherDaily? = null, targetTimeMilli: Long):
|
||||
WeatherCondition.PARTLY_CLOUDY -> if (isDay) R.drawable.weather_partly_cloudy_day else R.drawable.weather_partly_cloudy_night
|
||||
|
||||
WeatherCondition.HEAVY_RAIN -> R.drawable.weather_heavy_rain
|
||||
WeatherCondition.LIGHT_RAIN -> if (isDay) R.drawable.weather_light_rain_day else R.drawable.weather_light_rain_night
|
||||
WeatherCondition.LIGHT_RAIN -> R.drawable.weather_light_rain
|
||||
|
||||
WeatherCondition.LIGHT_SNOW -> if (isDay) R.drawable.weather_light_snow_day else R.drawable.weather_light_snow_night
|
||||
WeatherCondition.SNOW -> R.drawable.weather_snow
|
||||
@@ -97,6 +105,10 @@ fun WeatherCondition.toIcon(daily: WeatherDaily? = null, targetTimeMilli: Long):
|
||||
|
||||
WeatherCondition.RAIN -> R.drawable.weather_rain
|
||||
|
||||
WeatherCondition.SLEET, WeatherCondition.HAIL -> R.drawable.weather_sleet_hail
|
||||
|
||||
WeatherCondition.MIXED_PRECIPITATION -> R.drawable.weather_mixed_precipitation
|
||||
|
||||
WeatherCondition.CLEAR_WITH_CLOUDY -> R.drawable.clear_with_cloudy
|
||||
WeatherCondition.CLEAR_WITH_RAIN -> R.drawable.clear_with_rain
|
||||
WeatherCondition.CLEAR_WITH_SNOW -> R.drawable.clear_with_snow
|
||||
@@ -169,6 +181,10 @@ fun WeatherCondition.toLabel(context: Context): String {
|
||||
|
||||
WeatherCondition.RAIN -> context.getString(R.string.weather_rain)
|
||||
|
||||
WeatherCondition.SLEET -> context.getString(R.string.weather_sleet)
|
||||
WeatherCondition.HAIL -> context.getString(R.string.weather_hail)
|
||||
WeatherCondition.MIXED_PRECIPITATION -> context.getString(R.string.weather_mixed_precipitation)
|
||||
|
||||
WeatherCondition.CLEAR_WITH_CLOUDY -> context.getString(R.string.weather_clear_with_cloudy)
|
||||
WeatherCondition.CLEAR_WITH_RAIN -> context.getString(R.string.weather_clear_with_rain)
|
||||
WeatherCondition.CLEAR_WITH_SNOW -> context.getString(R.string.weather_clear_with_snow)
|
||||
@@ -212,7 +228,7 @@ fun WeatherCondition.toLabel(context: Context): String {
|
||||
|
||||
fun WeatherCondition.toFroggy(daily: WeatherDaily? = null, targetTimeMilli: Long): Int {
|
||||
|
||||
val isDay = if (daily != null) {
|
||||
val isDay = if (daily != null && daily.sunrise != null && daily.sunset != null) {
|
||||
targetTimeMilli in daily.sunrise..daily.sunset
|
||||
} else {
|
||||
true
|
||||
@@ -225,7 +241,7 @@ fun WeatherCondition.toFroggy(daily: WeatherDaily? = null, targetTimeMilli: Long
|
||||
|
||||
WeatherCondition.PARTLY_CLOUDY -> R.drawable.froggy_partly_cloudy
|
||||
|
||||
WeatherCondition.HEAVY_RAIN -> R.drawable.froggy_rain
|
||||
WeatherCondition.HEAVY_RAIN, WeatherCondition.HAIL, WeatherCondition.SLEET -> R.drawable.froggy_rain
|
||||
WeatherCondition.LIGHT_RAIN -> R.drawable.froggy_light_rain
|
||||
|
||||
WeatherCondition.LIGHT_SNOW -> R.drawable.froggy_snow
|
||||
@@ -245,9 +261,11 @@ fun WeatherCondition.toFroggy(daily: WeatherDaily? = null, targetTimeMilli: Long
|
||||
|
||||
WeatherCondition.RAIN -> R.drawable.froggy_rain
|
||||
|
||||
WeatherCondition.NO_CONDITION_FOUND -> R.drawable.weather_not_available
|
||||
WeatherCondition.MIXED_PRECIPITATION -> R.drawable.froggy_mixed_precip
|
||||
|
||||
else -> R.drawable.weather_not_available
|
||||
WeatherCondition.NO_CONDITION_FOUND -> R.drawable.froggy_no_condition_found
|
||||
|
||||
else -> R.drawable.froggy_no_condition_found
|
||||
|
||||
}
|
||||
|
||||
|
||||
+27
-4
@@ -1,14 +1,37 @@
|
||||
package com.pranshulgg.weather_master_app.core.model.weather
|
||||
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.alerts.Alert
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.weather.Weather
|
||||
import com.pranshulgg.weather_master_app.data.repository.data.WeatherAdditionalData
|
||||
|
||||
sealed class WeatherResult {
|
||||
data class Success(val weather: Weather) : WeatherResult()
|
||||
data object RefreshNotAvailable : WeatherResult()
|
||||
sealed class WeatherResult(
|
||||
) {
|
||||
|
||||
data class Success(
|
||||
val weather: Weather, val alerts: List<Alert> = emptyList()
|
||||
) : WeatherResult()
|
||||
|
||||
data class RefreshNotAvailable(val weather: Weather) : WeatherResult()
|
||||
|
||||
data class Error(
|
||||
val exception: Exception,
|
||||
val weather: Weather?,
|
||||
val rawException: Exception? = null
|
||||
) : WeatherResult()
|
||||
|
||||
class NotSupported : WeatherResult()
|
||||
|
||||
data class Error(val exception: Exception, val cacheWeather: Weather? = null) : WeatherResult()
|
||||
}
|
||||
|
||||
data class WeatherDataPack(
|
||||
val weather: Weather,
|
||||
val additionalData: WeatherAdditionalData? = null
|
||||
)
|
||||
|
||||
data class FinishedWeatherResult(
|
||||
val weather: Weather
|
||||
)
|
||||
|
||||
enum class WeatherResultType {
|
||||
REFRESH_TOO_EARLY,
|
||||
SUCCESS,
|
||||
|
||||
+19
-2
@@ -1,14 +1,31 @@
|
||||
package com.pranshulgg.weather_master_app.core.model.weather.airquality
|
||||
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.airquality.AirQuality
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.alerts.Alert
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.location.Location
|
||||
import com.pranshulgg.weather_master_app.data.repository.data.AirQualityAdditionalData
|
||||
import com.pranshulgg.weather_master_app.data.repository.data.AlertsAdditionalData
|
||||
|
||||
|
||||
sealed class AirQualityResult {
|
||||
data class Success(val airquality: AirQuality) : AirQualityResult()
|
||||
data class Error(val exception: Exception, val cacheAirQuality: AirQuality? = null) :
|
||||
data class Success(val airQuality: AirQuality) : AirQualityResult()
|
||||
data class Error(val exception: Exception, val airQuality: AirQuality? = null) :
|
||||
AirQualityResult()
|
||||
|
||||
class NotSupported : AirQualityResult()
|
||||
}
|
||||
|
||||
data class FinishedAirQualityResult(
|
||||
val airQuality: AirQuality
|
||||
)
|
||||
|
||||
data class AirQualityDataPack(
|
||||
val airQuality: AirQuality?,
|
||||
val location: Location,
|
||||
val additionalData: AirQualityAdditionalData? = null,
|
||||
)
|
||||
|
||||
|
||||
enum class AirQualityResultType {
|
||||
RETURN_CACHE,
|
||||
ERROR
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ enum class Pollutant(
|
||||
companion object {
|
||||
|
||||
|
||||
private fun getLevelIndex(value: Double, thresholds: List<Int>): Int {
|
||||
fun getLevelIndex(value: Double, thresholds: List<Int>): Int {
|
||||
val index = thresholds.indexOfLast { value >= it }
|
||||
return if (index == -1) 0 else index
|
||||
}
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package com.pranshulgg.weather_master_app.core.model.weather.alerts
|
||||
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.alerts.Alert
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.location.Location
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.weather.Weather
|
||||
import com.pranshulgg.weather_master_app.data.repository.data.AlertsAdditionalData
|
||||
import com.pranshulgg.weather_master_app.data.repository.data.WeatherAdditionalData
|
||||
|
||||
|
||||
sealed class AlertResult {
|
||||
data class Success(val alerts: List<Alert>) : AlertResult()
|
||||
data class Error(val exception: Exception, val alerts: List<Alert> = emptyList()) :
|
||||
AlertResult()
|
||||
|
||||
class NotSupported : AlertResult()
|
||||
}
|
||||
|
||||
data class FinishedAlertsResult(
|
||||
val alerts: List<Alert>
|
||||
)
|
||||
|
||||
data class AlertsDataPack(
|
||||
val alerts: List<Alert>,
|
||||
val location: Location,
|
||||
val additionalData: AlertsAdditionalData? = null,
|
||||
)
|
||||
|
||||
|
||||
enum class AlertResultType {
|
||||
RETURN_CACHE,
|
||||
ERROR
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
package com.pranshulgg.weather_master_app.core.model.weather.alerts
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import com.pranshulgg.weather_master_app.R
|
||||
|
||||
enum class AlertSeverity(
|
||||
val label: Int,
|
||||
val color: Color,
|
||||
val contentColor: Color,
|
||||
val colorRes: Int
|
||||
) {
|
||||
CRITICAL(
|
||||
R.string.alert_severity_critical,
|
||||
Color(0xFFD32F2F),
|
||||
Color(0xFFFFEBEE),
|
||||
R.color.alert_CRITICAL
|
||||
),
|
||||
HIGH(
|
||||
R.string.alert_severity_high,
|
||||
Color(0xFFF57C00),
|
||||
Color(0xFFFFF4E0),
|
||||
R.color.alert_HIGH
|
||||
),
|
||||
MODERATE(
|
||||
R.string.alert_severity_medium,
|
||||
Color(0xFFFBC02D),
|
||||
Color(0xFF5C4300),
|
||||
R.color.alert_MODERATE
|
||||
),
|
||||
LOW(
|
||||
R.string.alert_severity_low,
|
||||
Color(0xFF388E3C),
|
||||
Color(0xFF0F3D0F),
|
||||
R.color.alert_LOW
|
||||
),
|
||||
UNKNOWN(
|
||||
R.string.alert_severity_unknown,
|
||||
Color(0xFF757575),
|
||||
Color(0xFFF3E5F5),
|
||||
R.color.alert_UNKNOWN
|
||||
)
|
||||
}
|
||||
+320
@@ -0,0 +1,320 @@
|
||||
package com.pranshulgg.weather_master_app.core.model.weather.openmeteo
|
||||
|
||||
import com.pranshulgg.weather_master_app.R
|
||||
|
||||
enum class OpenMeteoModelType {
|
||||
BEST_MATCH,
|
||||
NCEP,
|
||||
JMA,
|
||||
KMA,
|
||||
|
||||
DWD,
|
||||
|
||||
GEM,
|
||||
|
||||
METEO_FRANCE,
|
||||
ITALIA_METEO,
|
||||
|
||||
MET_NORWAY,
|
||||
KNMI,
|
||||
DMI,
|
||||
|
||||
UK_MET_OFFICE,
|
||||
METEOSWISS,
|
||||
GEOSPHERE,
|
||||
CHMI,
|
||||
|
||||
UNDEFINED
|
||||
}
|
||||
|
||||
enum class OpenMeteoModel(
|
||||
val displayName: String,
|
||||
val stringValue: Int? = null,
|
||||
val modelId: String,
|
||||
val modelType: OpenMeteoModelType = OpenMeteoModelType.UNDEFINED
|
||||
) {
|
||||
BEST_MATCH(
|
||||
"Best Match",
|
||||
R.string.open_meteo_model_best_match,
|
||||
"best_match",
|
||||
OpenMeteoModelType.BEST_MATCH
|
||||
),
|
||||
|
||||
ECMWF_IFS_HRES_9KM(
|
||||
"ECMWF IFS HRES 9km",
|
||||
modelId = "ecmwf_ifs"
|
||||
),
|
||||
ECMWF_IFS_025(
|
||||
"ECMWF IFS 0.25°",
|
||||
modelId = "ecmwf_ifs025"
|
||||
),
|
||||
ECMWF_AIFS_025_SINGLE(
|
||||
"ECMWF AIFS 0.25° Single",
|
||||
modelId = "ecmwf_aifs025_single"
|
||||
),
|
||||
CMA_GRAPES_GLOBAL(
|
||||
"CMA GRAPES Global",
|
||||
modelId = "cma_grapes_global"
|
||||
),
|
||||
BOM_ACCESS_GLOBAL(
|
||||
"BOM ACCESS Global",
|
||||
modelId = "bom_access_global"
|
||||
),
|
||||
|
||||
NCEP_GFS_SEAMLESS(
|
||||
"NCEP GFS Seamless",
|
||||
R.string.open_meteo_model_seamless,
|
||||
"ncep_gfs_seamless",
|
||||
OpenMeteoModelType.NCEP
|
||||
),
|
||||
NCEP_GFS_GLOBAL_011_025(
|
||||
"NCEP GFS Global 0.11°/0.25°",
|
||||
modelId = "ncep_gfs_global",
|
||||
modelType = OpenMeteoModelType.NCEP
|
||||
),
|
||||
NCEP_HRRR_US_CONUS(
|
||||
"NCEP HRRR U.S. Conus",
|
||||
modelId = "ncep_hrrr_conus",
|
||||
modelType = OpenMeteoModelType.NCEP
|
||||
),
|
||||
NCEP_NBM_US_CONUS(
|
||||
"NCEP NBM U.S. Conus",
|
||||
modelId = "ncep_nbm_conus",
|
||||
modelType = OpenMeteoModelType.NCEP
|
||||
),
|
||||
NCEP_NAM_US_CONUS(
|
||||
"NCEP NAM U.S. Conus",
|
||||
modelId = "ncep_nam_conus",
|
||||
modelType = OpenMeteoModelType.NCEP
|
||||
),
|
||||
NCEP_AIGFS_025(
|
||||
"NCEP AIGFS 0.25°",
|
||||
modelId = "ncep_aigfs025",
|
||||
modelType = OpenMeteoModelType.NCEP
|
||||
),
|
||||
NCEP_HGEFS_025_ENSEMBLE_MEAN(
|
||||
"NCEP HGEFS 0.25° Ensemble Mean",
|
||||
modelId = "ncep_hgefs025_ensemble_mean",
|
||||
modelType = OpenMeteoModelType.NCEP
|
||||
),
|
||||
|
||||
JMA_SEAMLESS(
|
||||
"JMA Seamless",
|
||||
R.string.open_meteo_model_seamless,
|
||||
"jma_seamless",
|
||||
modelType = OpenMeteoModelType.JMA
|
||||
),
|
||||
JMA_MSM(
|
||||
"JMA MSM",
|
||||
modelId = "jma_msm",
|
||||
modelType = OpenMeteoModelType.JMA
|
||||
),
|
||||
JMA_GSM(
|
||||
"JMA GSM",
|
||||
modelId = "jma_gsm",
|
||||
modelType = OpenMeteoModelType.JMA
|
||||
),
|
||||
|
||||
KMA_SEAMLESS(
|
||||
"KMA Seamless",
|
||||
R.string.open_meteo_model_seamless,
|
||||
"kma_seamless",
|
||||
modelType = OpenMeteoModelType.KMA
|
||||
),
|
||||
KMA_LDPS(
|
||||
"KMA LDPS",
|
||||
modelId = "kma_ldps",
|
||||
modelType = OpenMeteoModelType.KMA
|
||||
),
|
||||
KMA_GDPS(
|
||||
"KMA GDPS",
|
||||
modelId = "kma_gdps",
|
||||
modelType = OpenMeteoModelType.KMA
|
||||
),
|
||||
|
||||
DWD_ICON_SEAMLESS(
|
||||
"DWD ICON Seamless",
|
||||
R.string.open_meteo_model_seamless,
|
||||
"dwd_icon_seamless",
|
||||
modelType = OpenMeteoModelType.DWD
|
||||
),
|
||||
DWD_ICON_GLOBAL(
|
||||
"DWD ICON Global",
|
||||
modelId = "dwd_icon_global",
|
||||
modelType = OpenMeteoModelType.DWD
|
||||
),
|
||||
DWD_ICON_EU(
|
||||
"DWD ICON EU",
|
||||
modelId = "dwd_icon_eu",
|
||||
modelType = OpenMeteoModelType.DWD
|
||||
),
|
||||
DWD_ICON_D2(
|
||||
"DWD ICON D2",
|
||||
modelId = "dwd_icon_d2",
|
||||
modelType = OpenMeteoModelType.DWD
|
||||
),
|
||||
|
||||
GEM_SEAMLESS(
|
||||
"GEM Seamless",
|
||||
R.string.open_meteo_model_seamless,
|
||||
"cmc_gem_seamless",
|
||||
modelType = OpenMeteoModelType.GEM
|
||||
),
|
||||
GEM_GLOBAL(
|
||||
"GEM Global",
|
||||
modelId = "cmc_gem_gdps",
|
||||
modelType = OpenMeteoModelType.GEM
|
||||
),
|
||||
GEM_REGIONAL(
|
||||
"GEM Regional",
|
||||
modelId = "cmc_gem_rdps",
|
||||
modelType = OpenMeteoModelType.GEM
|
||||
),
|
||||
GEM_HRDPS_CONTINENTAL(
|
||||
"GEM HRDPS Continental",
|
||||
modelId = "cmc_gem_hrdps",
|
||||
modelType = OpenMeteoModelType.GEM
|
||||
),
|
||||
GEM_HRDPS_WEST(
|
||||
"GEM HRDPS West",
|
||||
modelId = "cmc_gem_hrdps_west",
|
||||
modelType = OpenMeteoModelType.GEM
|
||||
),
|
||||
|
||||
METEO_FRANCE_SEAMLESS(
|
||||
"Météo-France Seamless",
|
||||
R.string.open_meteo_model_seamless,
|
||||
"meteofrance_seamless",
|
||||
modelType = OpenMeteoModelType.METEO_FRANCE
|
||||
),
|
||||
METEO_FRANCE_ARPEGE_WORLD(
|
||||
"Météo-France ARPEGE World",
|
||||
modelId = "meteofrance_arpege_world",
|
||||
modelType = OpenMeteoModelType.METEO_FRANCE
|
||||
),
|
||||
METEO_FRANCE_ARPEGE_EUROPE(
|
||||
"Météo-France ARPEGE Europe",
|
||||
modelId = "meteofrance_arpege_europe",
|
||||
modelType = OpenMeteoModelType.METEO_FRANCE
|
||||
),
|
||||
METEO_FRANCE_AROME_FRANCE(
|
||||
"Météo-France AROME France",
|
||||
modelId = "meteofrance_arome_france",
|
||||
modelType = OpenMeteoModelType.METEO_FRANCE
|
||||
),
|
||||
METEO_FRANCE_AROME_FRANCE_HD(
|
||||
"Météo-France AROME France HD",
|
||||
modelId = "meteofrance_arome_france_hd",
|
||||
modelType = OpenMeteoModelType.METEO_FRANCE
|
||||
),
|
||||
|
||||
ITALIAMETEO_ARPAE_ICON_2I(
|
||||
"ItaliaMeteo ARPAE ICON 2I",
|
||||
modelId = "italia_meteo_arpae_icon_2i",
|
||||
modelType = OpenMeteoModelType.ITALIA_METEO
|
||||
),
|
||||
|
||||
MET_NORWAY_NORDIC_SEAMLESS_WITH_ECMWF(
|
||||
"MET Norway Nordic (with ECMWF) Seamless",
|
||||
R.string.open_meteo_model_seamless,
|
||||
"metno_seamless",
|
||||
modelType = OpenMeteoModelType.MET_NORWAY
|
||||
),
|
||||
MET_NORWAY_NORDIC(
|
||||
"MET Norway Nordic",
|
||||
modelId = "metno_nordic",
|
||||
modelType = OpenMeteoModelType.MET_NORWAY
|
||||
),
|
||||
|
||||
KNMI_SEAMLESS_WITH_ECMWF(
|
||||
"KNMI (with ECMWF) Seamless",
|
||||
R.string.open_meteo_model_seamless,
|
||||
"knmi_seamless",
|
||||
modelType = OpenMeteoModelType.KNMI
|
||||
),
|
||||
KNMI_HARMONIE_AROME_EUROPE(
|
||||
"KNMI Harmonie AROME Europe",
|
||||
modelId = "knmi_harmonie_arome_europe",
|
||||
modelType = OpenMeteoModelType.KNMI
|
||||
),
|
||||
KNMI_HARMONIE_AROME_NETHERLANDS(
|
||||
"KNMI Harmonie AROME Netherlands",
|
||||
modelId = "knmi_harmonie_arome_netherlands",
|
||||
modelType = OpenMeteoModelType.KNMI
|
||||
),
|
||||
|
||||
DMI_SEAMLESS_WITH_ECMWF(
|
||||
"DMI (with ECMWF) Seamless",
|
||||
R.string.open_meteo_model_seamless,
|
||||
"dmi_seamless",
|
||||
modelType = OpenMeteoModelType.DMI
|
||||
),
|
||||
DMI_HARMONIE_AROME_EUROPE(
|
||||
"DMI Harmonie AROME Europe",
|
||||
modelId = "dmi_harmonie_arome_europe",
|
||||
modelType = OpenMeteoModelType.DMI
|
||||
),
|
||||
|
||||
UK_MET_OFFICE_SEAMLESS(
|
||||
"UK Met Office Seamless",
|
||||
R.string.open_meteo_model_seamless,
|
||||
"ukmo_seamless",
|
||||
modelType = OpenMeteoModelType.UK_MET_OFFICE
|
||||
),
|
||||
UK_MET_OFFICE_GLOBAL_10KM(
|
||||
"UK Met Office Global 10km",
|
||||
modelId = "ukmo_global_deterministic_10km",
|
||||
modelType = OpenMeteoModelType.UK_MET_OFFICE
|
||||
),
|
||||
UK_MET_OFFICE_UK_2KM(
|
||||
"UK Met Office UK 2km",
|
||||
modelId = "ukmo_uk_deterministic_2km",
|
||||
modelType = OpenMeteoModelType.UK_MET_OFFICE
|
||||
),
|
||||
|
||||
METEOSWISS_ICON_SEAMLESS(
|
||||
"MeteoSwiss ICON Seamless",
|
||||
R.string.open_meteo_model_seamless,
|
||||
"meteoswiss_icon_seamless",
|
||||
modelType = OpenMeteoModelType.METEOSWISS
|
||||
),
|
||||
METEOSWISS_ICON_CH1(
|
||||
"MeteoSwiss ICON CH1",
|
||||
modelId = "meteoswiss_icon_ch1",
|
||||
modelType = OpenMeteoModelType.METEOSWISS
|
||||
),
|
||||
METEOSWISS_ICON_CH2(
|
||||
"MeteoSwiss ICON CH2",
|
||||
modelId = "meteoswiss_icon_ch2",
|
||||
modelType = OpenMeteoModelType.METEOSWISS
|
||||
),
|
||||
|
||||
GEOSPHERE_SEAMLESS_WITH_ECMWF(
|
||||
"GeoSphere (with ECMWF) Seamless",
|
||||
R.string.open_meteo_model_seamless,
|
||||
"geosphere_seamless",
|
||||
modelType = OpenMeteoModelType.GEOSPHERE
|
||||
),
|
||||
GEOSPHERE_AROME_AUSTRIA(
|
||||
"GeoSphere AROME Austria",
|
||||
modelId = "geosphere_arome_austria",
|
||||
modelType = OpenMeteoModelType.GEOSPHERE
|
||||
),
|
||||
|
||||
CHMI_ALADIN_SEAMLESS(
|
||||
"CHMI Aladin Seamless",
|
||||
R.string.open_meteo_model_seamless,
|
||||
"chmi_aladin_seamless",
|
||||
modelType = OpenMeteoModelType.CHMI
|
||||
),
|
||||
CHMI_ALADIN_CENTRAL_EUROPE_2KM(
|
||||
"CHMI Aladin Central Europe 2km",
|
||||
modelId = "chmi_aladin_central_europe_2km",
|
||||
modelType = OpenMeteoModelType.CHMI
|
||||
),
|
||||
CHMI_ALADIN_CZ_1KM(
|
||||
"CHMI Aladin CZ 1km",
|
||||
modelId = "chmi_aladin_cz_1km",
|
||||
modelType = OpenMeteoModelType.CHMI
|
||||
),
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.pranshulgg.weather_master_app.core.model.weather.uv
|
||||
import android.content.Context
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import com.pranshulgg.weather_master_app.R
|
||||
import com.pranshulgg.weather_master_app.core.model.weather.airquality.AirQualityLevel
|
||||
|
||||
enum class UvIndex {
|
||||
LOW,
|
||||
@@ -40,4 +41,14 @@ fun UvIndex.toColor(): Color {
|
||||
UvIndex.VERY_HIGH -> Color(0xFFF44336)
|
||||
UvIndex.EXTREME -> Color(0xFF9C27B0)
|
||||
}
|
||||
}
|
||||
|
||||
fun UvIndex.toTextColor(): Color {
|
||||
return when (this) {
|
||||
UvIndex.LOW -> Color(0xFF0F3D0F)
|
||||
UvIndex.MODERATE -> Color(0xFF5C4300)
|
||||
UvIndex.HIGH -> Color(0xFFFFF4E0)
|
||||
UvIndex.VERY_HIGH -> Color(0xFFFFEBEE)
|
||||
UvIndex.EXTREME -> Color(0xFFFFE4F1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.pranshulgg.weather_master_app.core.network.calls
|
||||
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.AppException
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.toAppException
|
||||
import retrofit2.HttpException
|
||||
import retrofit2.Response
|
||||
import java.io.IOException
|
||||
|
||||
|
||||
suspend fun <T> safeApiCall(
|
||||
call: suspend () -> Response<T>
|
||||
): Result<T> {
|
||||
return try {
|
||||
val response = call()
|
||||
|
||||
if (response.isSuccessful) {
|
||||
response.body()?.let(Result.Companion::success)
|
||||
?: Result.failure(
|
||||
AppException.EmptyResponseBody()
|
||||
)
|
||||
} else {
|
||||
Result.failure(
|
||||
resolveException(response)
|
||||
)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Result.failure(e.toAppException())
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveException(response: Response<*>): AppException {
|
||||
return when (response.code()) {
|
||||
400 -> AppException.BadRequest()
|
||||
401 -> AppException.Unauthorized()
|
||||
403 -> AppException.Forbidden()
|
||||
404 -> AppException.NotFound()
|
||||
408 -> AppException.RequestTimeout()
|
||||
429 -> AppException.TooManyRequests()
|
||||
in 500..599 -> AppException.Server()
|
||||
else -> AppException.Unknown()
|
||||
}
|
||||
}
|
||||
+22
-4
@@ -1,12 +1,28 @@
|
||||
package com.pranshulgg.weather_master_app.core.network.github
|
||||
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.github.GithubDao
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.net.UnknownHostException
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
class GithubRepository @Inject constructor(
|
||||
private val api: GithubApi
|
||||
private val api: GithubApi,
|
||||
private val dao: GithubDao
|
||||
) {
|
||||
suspend fun isNewVersionAvailable(currentTag: String): Boolean {
|
||||
suspend fun isNewVersionAvailable(currentTag: String): Boolean = withContext(Dispatchers.IO) {
|
||||
|
||||
val getSavedVersionInfo = dao.getGithubEntity()
|
||||
if (getSavedVersionInfo != null && getSavedVersionInfo.currentTag == currentTag) {
|
||||
|
||||
val ageMillis = System.currentTimeMillis() - getSavedVersionInfo.lastFetchedTime
|
||||
val maxAgeMillis = TimeUnit.HOURS.toMillis(2)
|
||||
|
||||
if (ageMillis < maxAgeMillis) {
|
||||
return@withContext getSavedVersionInfo.lastFetchedTag != currentTag
|
||||
}
|
||||
}
|
||||
try {
|
||||
|
||||
val response = api.fetchGithubRepos()
|
||||
@@ -14,11 +30,13 @@ class GithubRepository @Inject constructor(
|
||||
val body = response.body() ?: throw UnknownHostException()
|
||||
|
||||
val firstTag = body.firstOrNull { !it.prerelease }?.tagName
|
||||
?: return false
|
||||
?: return@withContext false
|
||||
|
||||
val isNewAvailable = firstTag != currentTag
|
||||
|
||||
return isNewAvailable
|
||||
dao.insertGithubEntity(currentTag, firstTag, System.currentTimeMillis())
|
||||
|
||||
return@withContext isNewAvailable
|
||||
|
||||
} catch (e: Exception) {
|
||||
throw e
|
||||
|
||||
+2
-5
@@ -19,20 +19,17 @@ interface NominatimApi {
|
||||
@Query("format") format: String = "jsonv2",
|
||||
@Query("lat") latitude: Double,
|
||||
@Query("lon") longitude: Double,
|
||||
@Query("layer") layer: String = "address"
|
||||
@Query("layer") layer: String = "address",
|
||||
@Query("accept-language") lang: String = "en"
|
||||
): Response<NominatimAddressJson>
|
||||
|
||||
companion object {
|
||||
const val BASE_URL = "https://nominatim.openstreetmap.org/"
|
||||
|
||||
fun create(): NominatimApi {
|
||||
val logging = HttpLoggingInterceptor().apply {
|
||||
level = HttpLoggingInterceptor.Level.BODY
|
||||
}
|
||||
|
||||
|
||||
val client = OkHttpClient.Builder()
|
||||
.addInterceptor(logging)
|
||||
.addInterceptor { chain ->
|
||||
val request = chain.request().newBuilder()
|
||||
.header(
|
||||
|
||||
+3
-1
@@ -19,5 +19,7 @@ data class NominatimAddressDataJson(
|
||||
val suburb: String?,
|
||||
|
||||
val state: String?,
|
||||
val country: String
|
||||
val country: String,
|
||||
|
||||
@SerializedName("country_code") val countryCode: String?
|
||||
)
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
# Air Quality
|
||||
|
||||
This folder is for airquality-specific API implementations
|
||||
|
||||
### Rules
|
||||
|
||||
- Only add APIs here when the source provides **Air Quality only**.
|
||||
- If air quality comes from a source that also provides weather, keep the API under that source's
|
||||
existing
|
||||
folder instead. You can take a look at **AccuWeather** implementation
|
||||
- A single source should have a single source-level implementation/folder, even if it exposes
|
||||
multiple endpoints.
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package com.pranshulgg.weather_master_app.core.network.sources.airquality.moenv
|
||||
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.airquality.moenv.json.MoenvStationJson
|
||||
import okhttp3.OkHttpClient
|
||||
import retrofit2.Response
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Query
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
interface MoenvApi {
|
||||
|
||||
@GET("v2/aqx_p_432")
|
||||
suspend fun fetchStations(
|
||||
@Query("api_key") apiKey: String,
|
||||
@Query("format") format: String = "json"
|
||||
): Response<List<MoenvStationJson>>
|
||||
|
||||
|
||||
companion object {
|
||||
const val BASE_URL = "https://data.moenv.gov.tw/api/"
|
||||
fun create(): MoenvApi {
|
||||
|
||||
val client = OkHttpClient.Builder().connectTimeout(30, TimeUnit.SECONDS)
|
||||
.readTimeout(30, TimeUnit.SECONDS).build()
|
||||
|
||||
return Retrofit.Builder().baseUrl(BASE_URL).client(client).addConverterFactory(
|
||||
GsonConverterFactory.create()
|
||||
).build().create(MoenvApi::class.java)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
package com.pranshulgg.weather_master_app.core.network.sources.airquality.moenv
|
||||
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.AppException
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.airquality.AirQuality
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.location.Location
|
||||
import com.pranshulgg.weather_master_app.core.model.sources.Source
|
||||
import com.pranshulgg.weather_master_app.core.model.weather.airquality.AirQualityDataPack
|
||||
import com.pranshulgg.weather_master_app.core.model.weather.airquality.FinishedAirQualityResult
|
||||
import com.pranshulgg.weather_master_app.core.network.calls.safeApiCall
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.airquality.AirQualityDao
|
||||
import com.pranshulgg.weather_master_app.data.local.mapper.airquality.sources.moenv.findClosestStation
|
||||
import com.pranshulgg.weather_master_app.data.local.mapper.airquality.sources.moenv.toDomain
|
||||
import com.pranshulgg.weather_master_app.data.repository.airquality.AirQualityCacheModel
|
||||
import com.pranshulgg.weather_master_app.data.repository.capability.AirQualityCapability
|
||||
import com.pranshulgg.weather_master_app.data.repository.capability.AlertCapability
|
||||
import com.pranshulgg.weather_master_app.data.repository.capability.WeatherCapability
|
||||
import com.pranshulgg.weather_master_app.data.repository.data.BaseRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
/**
|
||||
* MOENV (Taiwan) air quality integration implemented by https://github.com/reveler-hub
|
||||
*/
|
||||
class MoenvRepository @Inject constructor(
|
||||
val api: MoenvApi,
|
||||
val airQualityDao: AirQualityDao
|
||||
) : BaseRepository() {
|
||||
|
||||
override val weatherSource = Source.NONE
|
||||
override val alertSource = Source.NONE
|
||||
override val airQualitySource = Source.MOENV
|
||||
|
||||
override fun airQualityCapability(): AirQualityCapability {
|
||||
return object : AirQualityCapability {
|
||||
override suspend fun fetchAndProcess(
|
||||
location: Location,
|
||||
isManualRefresh: Boolean,
|
||||
isForceRefresh: Boolean,
|
||||
airQualityCacheModel: AirQualityCacheModel
|
||||
): AirQualityDataPack {
|
||||
val stations = safeApiCall {
|
||||
api.fetchStations(apiKey = airQualityCacheModel.apiKey!!)
|
||||
}.getOrThrow()
|
||||
|
||||
val closest = findClosestStation(location, stations)
|
||||
?: throw AppException.EmptyResponseBody()
|
||||
|
||||
return AirQualityDataPack(airQuality = closest.toDomain(), location)
|
||||
}
|
||||
|
||||
override suspend fun saveToDb(data: AirQualityDataPack) {
|
||||
useGenericSaveImplementationForAirQuality(airQualityDao, data)
|
||||
}
|
||||
|
||||
override fun finishedResult(data: AirQuality): FinishedAirQualityResult {
|
||||
return FinishedAirQualityResult(airQuality = data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun weatherCapability(): WeatherCapability? = null
|
||||
override fun alertCapability(): AlertCapability? = null
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package com.pranshulgg.weather_master_app.core.network.sources.airquality.moenv.json
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
|
||||
data class MoenvStationJson(
|
||||
val sitename: String?,
|
||||
val county: String?,
|
||||
val aqi: String?,
|
||||
val status: String?,
|
||||
val latitude: String?,
|
||||
val longitude: String?,
|
||||
val so2: String?,
|
||||
val co: String?,
|
||||
val o3: String?,
|
||||
val pm10: String?,
|
||||
@SerializedName("pm2.5") val pm25: String?,
|
||||
val no2: String?,
|
||||
)
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
package com.pranshulgg.weather_master_app.core.network.sources.airquality.openmeteo
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
|
||||
// TODO: ADD HOURLY-DAILY FORECAST
|
||||
data class OpenMeteoAqiDto(
|
||||
val current: OpenMeteoAqiCurrentDto
|
||||
)
|
||||
|
||||
data class OpenMeteoAqiCurrentDto(
|
||||
val time: Long,
|
||||
|
||||
@SerializedName("us_aqi")
|
||||
val usAqi: Int,
|
||||
val pm10: Double,
|
||||
|
||||
@SerializedName("pm2_5")
|
||||
val pm25: Double,
|
||||
|
||||
@SerializedName("carbon_monoxide")
|
||||
val carbonMonoxide: Double,
|
||||
|
||||
@SerializedName("nitrogen_dioxide")
|
||||
val nitrogenDioxide: Double,
|
||||
|
||||
@SerializedName("sulphur_dioxide")
|
||||
val sulphurDioxide: Double,
|
||||
val ozone: Double
|
||||
)
|
||||
|
||||
-54
@@ -1,54 +0,0 @@
|
||||
package com.pranshulgg.weather_master_app.core.network.sources.airquality.openmeteo
|
||||
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.location.Location
|
||||
import com.pranshulgg.weather_master_app.core.model.weather.airquality.AirQualityResult
|
||||
import com.pranshulgg.weather_master_app.core.model.weather.airquality.AirQualityResultType
|
||||
import com.pranshulgg.weather_master_app.core.utils.weather.cache.isCurrentAirQualitySafe
|
||||
import com.pranshulgg.weather_master_app.core.utils.weather.cache.shouldReturnAirQualityCache
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.airquality.AirQualityDao
|
||||
import com.pranshulgg.weather_master_app.data.local.mapper.airquality.toDomain
|
||||
import com.pranshulgg.weather_master_app.data.local.mapper.airquality.toEntity
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.net.UnknownHostException
|
||||
import javax.inject.Inject
|
||||
|
||||
class OpenMeteoAqiRepository @Inject constructor(
|
||||
private val api: OpenMeteoAqiApi,
|
||||
private val dao: AirQualityDao
|
||||
) {
|
||||
|
||||
suspend fun getAirQuality(
|
||||
location: Location,
|
||||
isManualRefresh: Boolean
|
||||
): AirQualityResult = withContext(Dispatchers.IO) {
|
||||
|
||||
|
||||
val cache = dao.getAirQualityForLocation(location.id)
|
||||
val shouldReturnCache = shouldReturnAirQualityCache(cache, isManualRefresh)
|
||||
|
||||
when (shouldReturnCache) {
|
||||
AirQualityResultType.RETURN_CACHE -> return@withContext AirQualityResult.Success(cache!!.toDomain())
|
||||
else -> {}
|
||||
}
|
||||
|
||||
return@withContext try {
|
||||
val response = api.fetchAirQuality(location.latitude, location.longitude)
|
||||
|
||||
val body = response.body()
|
||||
?: return@withContext AirQualityResult.Error(exception = UnknownHostException())
|
||||
|
||||
val domain = body.toDomain()
|
||||
|
||||
dao.insertCurrentAirQuality(domain.current.toEntity(location.id))
|
||||
|
||||
AirQualityResult.Success(domain)
|
||||
} catch (e: Exception) {
|
||||
|
||||
val isCacheSafe = isCurrentAirQualitySafe(cache?.toDomain())
|
||||
|
||||
AirQualityResult.Error(exception = e, if (isCacheSafe) cache?.toDomain() else null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
# Alerts
|
||||
|
||||
This folder is for alert-specific API implementations
|
||||
|
||||
### Rules
|
||||
|
||||
- Only add APIs here when the source provides **alerts only**.
|
||||
- If alerts come from a source that also provides weather, keep the API under that source's existing
|
||||
folder instead. You can take a look at **Open Meteo** implementation
|
||||
- A single source should have a single source-level implementation/folder, even if it exposes
|
||||
multiple endpoints.
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package com.pranshulgg.weather_master_app.core.network.sources.alerts.fpas
|
||||
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.ResponseBody
|
||||
import retrofit2.Response
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Path
|
||||
import retrofit2.http.Query
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
|
||||
interface FpasApi {
|
||||
|
||||
@GET("alert/area")
|
||||
suspend fun fetchAlerts(
|
||||
@Query("min_lat") minLat: Double,
|
||||
@Query("max_lat") maxLat: Double,
|
||||
@Query("min_lon") minLon: Double,
|
||||
@Query("max_lon") maxLon: Double,
|
||||
): Response<List<String>>
|
||||
|
||||
@GET("alert/{id}")
|
||||
suspend fun fetchAlertsCap(
|
||||
@Path("id") id: String,
|
||||
): Response<ResponseBody>
|
||||
|
||||
companion object {
|
||||
const val BASE_URL = "https://alerts.kde.org/"
|
||||
|
||||
fun create(): FpasApi {
|
||||
|
||||
|
||||
val client = OkHttpClient.Builder()
|
||||
.connectTimeout(30, TimeUnit.SECONDS)
|
||||
.readTimeout(30, TimeUnit.SECONDS)
|
||||
.build()
|
||||
|
||||
return Retrofit.Builder()
|
||||
.baseUrl(BASE_URL)
|
||||
.client(client)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.build()
|
||||
.create(FpasApi::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
+185
@@ -0,0 +1,185 @@
|
||||
package com.pranshulgg.weather_master_app.core.network.sources.alerts.fpas
|
||||
|
||||
import android.util.Xml
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.AppException
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.alerts.Alert
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.location.Location
|
||||
import com.pranshulgg.weather_master_app.core.model.sources.Source
|
||||
import com.pranshulgg.weather_master_app.core.model.weather.alerts.AlertResult
|
||||
import com.pranshulgg.weather_master_app.core.model.weather.alerts.AlertResultType
|
||||
import com.pranshulgg.weather_master_app.core.model.weather.alerts.AlertsDataPack
|
||||
import com.pranshulgg.weather_master_app.core.model.weather.alerts.FinishedAlertsResult
|
||||
import com.pranshulgg.weather_master_app.core.network.calls.safeApiCall
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.alerts.fpas.model.FpasCapAlert
|
||||
import com.pranshulgg.weather_master_app.core.utils.locale.getCurrentAppLocale
|
||||
import com.pranshulgg.weather_master_app.core.utils.weather.cache.shouldReturnAlertsCache
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.alerts.AlertsDao
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.weather.WeatherContextDao
|
||||
import com.pranshulgg.weather_master_app.data.local.mapper.alerts.sources.fpas.fpasAlertsMapper
|
||||
import com.pranshulgg.weather_master_app.data.local.mapper.alerts.toDomain
|
||||
import com.pranshulgg.weather_master_app.data.local.mapper.alerts.toEntity
|
||||
import com.pranshulgg.weather_master_app.data.repository.alerts.AlertCacheModel
|
||||
import com.pranshulgg.weather_master_app.data.repository.alerts.AlertRepository
|
||||
import com.pranshulgg.weather_master_app.data.repository.capability.AirQualityCapability
|
||||
import com.pranshulgg.weather_master_app.data.repository.capability.AlertCapability
|
||||
import com.pranshulgg.weather_master_app.data.repository.capability.WeatherCapability
|
||||
import com.pranshulgg.weather_master_app.data.repository.data.BaseRepository
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.xmlpull.v1.XmlPullParser
|
||||
import java.io.InputStream
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
class FpasRepository @Inject constructor(
|
||||
private val api: FpasApi,
|
||||
private val dao: AlertsDao,
|
||||
private val weatherContextDao: WeatherContextDao
|
||||
) : BaseRepository() {
|
||||
|
||||
override val alertSource = Source.FPAS
|
||||
override val weatherSource = Source.NONE
|
||||
override val airQualitySource = Source.NONE
|
||||
|
||||
override fun alertCapability(): AlertCapability? {
|
||||
return object : AlertCapability {
|
||||
override suspend fun fetchAndProcess(
|
||||
location: Location,
|
||||
isManualRefresh: Boolean,
|
||||
isForceRefresh: Boolean,
|
||||
alertCacheModel: AlertCacheModel
|
||||
): AlertsDataPack {
|
||||
val response = safeApiCall {
|
||||
api.fetchAlerts(
|
||||
minLat = location.latitude - 0.1,
|
||||
maxLat = location.latitude + 0.1,
|
||||
minLon = location.longitude - 0.1,
|
||||
maxLon = location.longitude + 0.1
|
||||
)
|
||||
}.getOrThrow()
|
||||
|
||||
|
||||
val preferredLanguage = getCurrentAppLocale().language
|
||||
|
||||
val alerts = response.mapNotNull {
|
||||
val responseAlert = api.fetchAlertsCap(it)
|
||||
|
||||
if (responseAlert.isSuccessful) {
|
||||
responseAlert.body()?.byteStream()?.use { stream ->
|
||||
parseAlertXmlBody(stream, preferredLanguage)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val domain = fpasAlertsMapper(alerts, location.id)
|
||||
|
||||
return AlertsDataPack(domain, location)
|
||||
}
|
||||
|
||||
override suspend fun saveToDb(data: AlertsDataPack, alertCacheModel: AlertCacheModel) {
|
||||
useGenericSaveImplementationForAlerts(data, alertsDao = dao, weatherContextDao)
|
||||
}
|
||||
|
||||
override fun finishedResult(data: List<Alert>): FinishedAlertsResult {
|
||||
return FinishedAlertsResult(alerts = data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun weatherCapability(): WeatherCapability? = null
|
||||
override fun airQualityCapability(): AirQualityCapability? = null
|
||||
}
|
||||
|
||||
private fun parseAlertXmlBody(stream: InputStream, preferredLanguage: String): FpasCapAlert {
|
||||
val parser = Xml.newPullParser()
|
||||
parser.setInput(stream, null)
|
||||
|
||||
val infoBlocks = mutableListOf<FpasCapAlert>()
|
||||
|
||||
var type = parser.eventType
|
||||
|
||||
var language: String? = null
|
||||
var event: String? = null
|
||||
var severity: String? = null
|
||||
var effective: String? = null
|
||||
var expires: String? = null
|
||||
var senderName: String? = null
|
||||
var description: String? = null
|
||||
var headline: String? = null
|
||||
|
||||
while (type != XmlPullParser.END_DOCUMENT) {
|
||||
|
||||
when (type) {
|
||||
XmlPullParser.START_TAG -> {
|
||||
when (parser.name) {
|
||||
// a CAP alert can carry one <info> block per language; reset per block
|
||||
// so fields from one language don't leak into another
|
||||
"info" -> {
|
||||
language = null
|
||||
event = null
|
||||
severity = null
|
||||
effective = null
|
||||
expires = null
|
||||
senderName = null
|
||||
description = null
|
||||
headline = null
|
||||
}
|
||||
|
||||
"language" -> language = parser.nextText()
|
||||
"event" -> event = parser.nextText()
|
||||
"severity" -> severity = parser.nextText()
|
||||
"effective" -> effective = parser.nextText()
|
||||
"expires" -> expires = parser.nextText()
|
||||
"senderName" -> senderName = parser.nextText()
|
||||
"description" -> description = parser.nextText()
|
||||
"headline" -> headline = parser.nextText()
|
||||
}
|
||||
}
|
||||
|
||||
XmlPullParser.END_TAG -> {
|
||||
if (parser.name == "info") {
|
||||
infoBlocks += FpasCapAlert(
|
||||
language = language,
|
||||
event = event,
|
||||
severity = severity,
|
||||
effective = effective,
|
||||
expires = expires,
|
||||
senderName = senderName,
|
||||
headline = headline,
|
||||
description = description
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
type = parser.next()
|
||||
}
|
||||
|
||||
return selectPreferredInfoBlock(infoBlocks, preferredLanguage)
|
||||
}
|
||||
|
||||
private fun selectPreferredInfoBlock(
|
||||
infoBlocks: List<FpasCapAlert>,
|
||||
preferredLanguage: String
|
||||
): FpasCapAlert {
|
||||
return infoBlocks.firstOrNull {
|
||||
it.language?.startsWith(
|
||||
preferredLanguage,
|
||||
ignoreCase = true
|
||||
) == true
|
||||
}
|
||||
?: infoBlocks.firstOrNull { it.language?.startsWith("en", ignoreCase = true) == true }
|
||||
?: infoBlocks.firstOrNull()
|
||||
?: FpasCapAlert(
|
||||
language = null,
|
||||
event = null,
|
||||
severity = null,
|
||||
effective = null,
|
||||
expires = null,
|
||||
senderName = null,
|
||||
headline = null,
|
||||
description = null
|
||||
)
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.pranshulgg.weather_master_app.core.network.sources.alerts.fpas.model
|
||||
|
||||
data class FpasCapAlert(
|
||||
val language: String?,
|
||||
val event: String?,
|
||||
val severity: String?,
|
||||
val effective: String?,
|
||||
val expires: String?,
|
||||
val senderName: String?,
|
||||
val headline: String?,
|
||||
val description: String?
|
||||
)
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
package com.pranshulgg.weather_master_app.core.network.sources.alerts.weatherapi
|
||||
|
||||
import com.pranshulgg.weather_master_app.BuildConfig
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.OkHttpClient
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Query
|
||||
import java.util.concurrent.TimeUnit
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.alerts.weatherapi.json.AlertsWeatherApiJson
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import retrofit2.Response
|
||||
|
||||
|
||||
interface AlertsWeatherApi {
|
||||
|
||||
@GET("alerts.json")
|
||||
suspend fun fetchAlerts(
|
||||
@Query("q") query: String
|
||||
): Response<AlertsWeatherApiJson>
|
||||
|
||||
|
||||
companion object {
|
||||
const val BASE_URL = "https://api.weatherapi.com/v1/"
|
||||
|
||||
fun create(): AlertsWeatherApi {
|
||||
|
||||
val auth = Interceptor { chain ->
|
||||
val original = chain.request()
|
||||
|
||||
val newUrl =
|
||||
original.url.newBuilder()
|
||||
.addQueryParameter("key", BuildConfig.WEATHERAPI_KEY)
|
||||
.build()
|
||||
val request = original.newBuilder().url(newUrl).build()
|
||||
|
||||
chain.proceed(request)
|
||||
}
|
||||
|
||||
val client = OkHttpClient.Builder()
|
||||
.addInterceptor(auth)
|
||||
.connectTimeout(30, TimeUnit.SECONDS)
|
||||
.readTimeout(30, TimeUnit.SECONDS)
|
||||
.build()
|
||||
|
||||
return Retrofit.Builder()
|
||||
.baseUrl(BASE_URL)
|
||||
.client(client)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.build()
|
||||
.create(AlertsWeatherApi::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
package com.pranshulgg.weather_master_app.core.network.sources.alerts.weatherapi
|
||||
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.alerts.Alert
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.location.Location
|
||||
import com.pranshulgg.weather_master_app.core.model.sources.Source
|
||||
import com.pranshulgg.weather_master_app.core.model.weather.alerts.AlertsDataPack
|
||||
import com.pranshulgg.weather_master_app.core.model.weather.alerts.FinishedAlertsResult
|
||||
import com.pranshulgg.weather_master_app.core.network.calls.safeApiCall
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.alerts.AlertsDao
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.weather.WeatherContextDao
|
||||
import com.pranshulgg.weather_master_app.data.local.mapper.alerts.sources.weatherapi.toDomain
|
||||
import com.pranshulgg.weather_master_app.data.repository.alerts.AlertCacheModel
|
||||
import com.pranshulgg.weather_master_app.data.repository.capability.AirQualityCapability
|
||||
import com.pranshulgg.weather_master_app.data.repository.capability.AlertCapability
|
||||
import com.pranshulgg.weather_master_app.data.repository.capability.WeatherCapability
|
||||
import com.pranshulgg.weather_master_app.data.repository.data.BaseRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
class AlertsWeatherApiRepository @Inject constructor(
|
||||
private val api: AlertsWeatherApi,
|
||||
private val dao: AlertsDao,
|
||||
private val weatherContextDao: WeatherContextDao
|
||||
) : BaseRepository() {
|
||||
|
||||
override val alertSource = Source.WEATHER_API
|
||||
override val weatherSource = Source.NONE
|
||||
override val airQualitySource = Source.NONE
|
||||
|
||||
override fun alertCapability(): AlertCapability? {
|
||||
return object : AlertCapability {
|
||||
override suspend fun fetchAndProcess(
|
||||
location: Location,
|
||||
isManualRefresh: Boolean,
|
||||
isForceRefresh: Boolean,
|
||||
alertCacheModel: AlertCacheModel
|
||||
): AlertsDataPack {
|
||||
val response = safeApiCall {
|
||||
api.fetchAlerts("${location.latitude},${location.longitude}")
|
||||
}.getOrThrow()
|
||||
|
||||
|
||||
val domain = response.toDomain(location.id)
|
||||
|
||||
return AlertsDataPack(domain, location)
|
||||
}
|
||||
|
||||
override suspend fun saveToDb(data: AlertsDataPack, alertCacheModel: AlertCacheModel) {
|
||||
useGenericSaveImplementationForAlerts(data, alertsDao = dao, weatherContextDao)
|
||||
}
|
||||
|
||||
override fun finishedResult(data: List<Alert>): FinishedAlertsResult {
|
||||
return FinishedAlertsResult(alerts = data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun weatherCapability(): WeatherCapability? = null
|
||||
override fun airQualityCapability(): AirQualityCapability? = null
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package com.pranshulgg.weather_master_app.core.network.sources.alerts.weatherapi.json
|
||||
|
||||
|
||||
data class AlertsWeatherApiJson(
|
||||
val alerts: AlertsWeatherApiAlertJson
|
||||
)
|
||||
|
||||
data class AlertsWeatherApiAlertJson(
|
||||
val alert: List<AlertsWeatherApiAlertItemJson>
|
||||
)
|
||||
|
||||
data class AlertsWeatherApiAlertItemJson(
|
||||
val event: String,
|
||||
val effective: String?,
|
||||
val expires: String?,
|
||||
val desc: String?,
|
||||
val severity: String?,
|
||||
val headline: String?
|
||||
)
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
package com.pranshulgg.weather_master_app.core.network.sources.alerts.wmosevereweather
|
||||
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.alerts.wmosevereweather.json.WmoSevereWeatherJson
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.ResponseBody
|
||||
import retrofit2.Response
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Path
|
||||
import retrofit2.http.Query
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
|
||||
interface WmoSevereWeatherApi {
|
||||
|
||||
@GET("f/wfs")
|
||||
suspend fun fetchAlerts(
|
||||
@Query("typeName") typeName: String = "local_postgis:postgis_geojsons",
|
||||
@Query("cql_filter") cqlFilter: String,
|
||||
@Query("version") version: String = "1.1.0",
|
||||
@Query("outputFormat") outputFormat: String = "json",
|
||||
@Query("request") request: String = "GetFeature",
|
||||
): Response<WmoSevereWeatherJson>
|
||||
|
||||
@GET("v2/cap-alerts/{url}")
|
||||
suspend fun fetchAlertsXml(
|
||||
@Path(value = "url", encoded = true) url: String
|
||||
): Response<ResponseBody>
|
||||
|
||||
|
||||
companion object {
|
||||
const val BASE_URL = "https://severeweather.wmo.int/"
|
||||
|
||||
fun create(): WmoSevereWeatherApi {
|
||||
|
||||
|
||||
val client = OkHttpClient.Builder()
|
||||
.connectTimeout(30, TimeUnit.SECONDS)
|
||||
.readTimeout(30, TimeUnit.SECONDS)
|
||||
.build()
|
||||
|
||||
return Retrofit.Builder()
|
||||
.baseUrl(BASE_URL)
|
||||
.client(client)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.build()
|
||||
.create(WmoSevereWeatherApi::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
+145
@@ -0,0 +1,145 @@
|
||||
package com.pranshulgg.weather_master_app.core.network.sources.alerts.wmosevereweather
|
||||
|
||||
import android.util.Xml
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.AppException
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.alerts.Alert
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.location.Location
|
||||
import com.pranshulgg.weather_master_app.core.model.sources.Source
|
||||
import com.pranshulgg.weather_master_app.core.model.weather.alerts.AlertResult
|
||||
import com.pranshulgg.weather_master_app.core.model.weather.alerts.AlertResultType
|
||||
import com.pranshulgg.weather_master_app.core.model.weather.alerts.AlertsDataPack
|
||||
import com.pranshulgg.weather_master_app.core.model.weather.alerts.FinishedAlertsResult
|
||||
import com.pranshulgg.weather_master_app.core.network.calls.safeApiCall
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.alerts.wmosevereweather.model.WmoCapAlert
|
||||
import com.pranshulgg.weather_master_app.core.utils.weather.cache.shouldReturnAlertsCache
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.alerts.AlertsDao
|
||||
import com.pranshulgg.weather_master_app.data.local.dao.weather.WeatherContextDao
|
||||
import com.pranshulgg.weather_master_app.data.local.mapper.alerts.sources.wmosevereweather.wmoSevereWeatherAlertsMapper
|
||||
import com.pranshulgg.weather_master_app.data.local.mapper.alerts.toDomain
|
||||
import com.pranshulgg.weather_master_app.data.local.mapper.alerts.toEntity
|
||||
import com.pranshulgg.weather_master_app.data.repository.alerts.AlertCacheModel
|
||||
import com.pranshulgg.weather_master_app.data.repository.alerts.AlertRepository
|
||||
import com.pranshulgg.weather_master_app.data.repository.capability.AirQualityCapability
|
||||
import com.pranshulgg.weather_master_app.data.repository.capability.AlertCapability
|
||||
import com.pranshulgg.weather_master_app.data.repository.capability.WeatherCapability
|
||||
import com.pranshulgg.weather_master_app.data.repository.data.BaseRepository
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.xmlpull.v1.XmlPullParser
|
||||
import java.io.InputStream
|
||||
import javax.inject.Inject
|
||||
|
||||
class WmoSevereWeatherRepository @Inject constructor(
|
||||
private val api: WmoSevereWeatherApi,
|
||||
private val dao: AlertsDao,
|
||||
private val weatherContextDao: WeatherContextDao
|
||||
) : BaseRepository() {
|
||||
|
||||
override val alertSource = Source.WMO_SEVERE_WEATHER
|
||||
override val weatherSource = Source.NONE
|
||||
override val airQualitySource = Source.NONE
|
||||
|
||||
override fun alertCapability(): AlertCapability? {
|
||||
return object : AlertCapability {
|
||||
override suspend fun fetchAndProcess(
|
||||
location: Location,
|
||||
isManualRefresh: Boolean,
|
||||
isForceRefresh: Boolean,
|
||||
alertCacheModel: AlertCacheModel
|
||||
): AlertsDataPack {
|
||||
|
||||
val cqlFilter =
|
||||
"INTERSECTS(wkb_geometry, POINT (${location.latitude} ${location.longitude})) AND row_type NEQ 'BOUNDARY'"
|
||||
|
||||
val response = safeApiCall { api.fetchAlerts(cqlFilter = cqlFilter) }.getOrThrow()
|
||||
|
||||
|
||||
val alertsWithCap = response.features.filter {
|
||||
it.properties != null
|
||||
}.map { feature ->
|
||||
val url = feature.properties?.capUrl ?: feature.properties?.rLink
|
||||
|
||||
val capAlert = if (!url.isNullOrBlank()) {
|
||||
val responseAlert = api.fetchAlertsXml(url)
|
||||
|
||||
if (responseAlert.isSuccessful) {
|
||||
responseAlert.body()?.byteStream()?.use { stream ->
|
||||
parseAlertXmlBody(stream)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
feature to capAlert
|
||||
}
|
||||
|
||||
|
||||
val domain = wmoSevereWeatherAlertsMapper(alertsWithCap, location.id)
|
||||
|
||||
return AlertsDataPack(domain, location)
|
||||
}
|
||||
|
||||
override suspend fun saveToDb(data: AlertsDataPack, alertCacheModel: AlertCacheModel) {
|
||||
useGenericSaveImplementationForAlerts(data, dao, weatherContextDao)
|
||||
}
|
||||
|
||||
override fun finishedResult(data: List<Alert>): FinishedAlertsResult {
|
||||
return FinishedAlertsResult(alerts = data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun weatherCapability(): WeatherCapability? = null
|
||||
override fun airQualityCapability(): AirQualityCapability? = null
|
||||
}
|
||||
|
||||
private fun parseAlertXmlBody(stream: InputStream): WmoCapAlert {
|
||||
val parser = Xml.newPullParser()
|
||||
parser.setInput(stream, null)
|
||||
|
||||
|
||||
var type = parser.eventType
|
||||
|
||||
var language: String? = null
|
||||
var event: String? = null
|
||||
var severity: String? = null
|
||||
var effective: String? = null
|
||||
var expires: String? = null
|
||||
var senderName: String? = null
|
||||
var description: String? = null
|
||||
var headline: String? = null
|
||||
|
||||
while (type != XmlPullParser.END_DOCUMENT) {
|
||||
|
||||
when (type) {
|
||||
XmlPullParser.START_TAG -> {
|
||||
when (parser.name) {
|
||||
"language" -> language = parser.nextText()
|
||||
"event" -> event = parser.nextText()
|
||||
"severity" -> severity = parser.nextText()
|
||||
"effective" -> effective = parser.nextText()
|
||||
"expires" -> expires = parser.nextText()
|
||||
"senderName" -> senderName = parser.nextText()
|
||||
"description" -> description = parser.nextText()
|
||||
"headline" -> headline = parser.nextText()
|
||||
}
|
||||
}
|
||||
}
|
||||
type = parser.next()
|
||||
}
|
||||
return WmoCapAlert(
|
||||
language = language,
|
||||
event = event,
|
||||
severity = severity,
|
||||
effective = effective,
|
||||
expires = expires,
|
||||
senderName = senderName,
|
||||
headline = headline,
|
||||
description = description
|
||||
)
|
||||
|
||||
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.pranshulgg.weather_master_app.core.network.sources.alerts.wmosevereweather.json
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class WmoSevereWeatherJson(
|
||||
val features: List<WmoSevereWeatherFeatureJson>
|
||||
)
|
||||
|
||||
data class WmoSevereWeatherFeatureJson(
|
||||
val properties: WmoSevereWeatherFeaturePropertiesJson?
|
||||
)
|
||||
|
||||
|
||||
data class WmoSevereWeatherFeaturePropertiesJson(
|
||||
@SerializedName("capurl") val capUrl: String?,
|
||||
@SerializedName("rlink") val rLink: String?,
|
||||
val description: String?,
|
||||
val event: String?,
|
||||
val effective: String?,
|
||||
val expires: String?,
|
||||
@SerializedName("s") val severity: Int?,
|
||||
val headline: String?
|
||||
)
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.pranshulgg.weather_master_app.core.network.sources.alerts.wmosevereweather.model
|
||||
|
||||
data class WmoCapAlert(
|
||||
val language: String?,
|
||||
val event: String?,
|
||||
val severity: String?,
|
||||
val effective: String?,
|
||||
val expires: String?,
|
||||
val senderName: String?,
|
||||
val headline: String?,
|
||||
val description: String?
|
||||
)
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
package com.pranshulgg.weather_master_app.core.network.sources.search.accu
|
||||
|
||||
import com.pranshulgg.weather_master_app.BuildConfig
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.search.accu.json.AccuSearchJson
|
||||
import com.pranshulgg.weather_master_app.core.network.sources.search.geonames.json.GeoNamesSearchJson
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.OkHttpClient
|
||||
import retrofit2.Response
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Query
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
|
||||
interface AccuSearchApi {
|
||||
|
||||
@GET("locations/v1/cities/search.json")
|
||||
suspend fun search(
|
||||
@Query("q") query: String,
|
||||
): Response<List<AccuSearchJson>>
|
||||
|
||||
companion object {
|
||||
|
||||
private const val BASE_URL = "https://api.accuweather.com/"
|
||||
|
||||
fun create(): AccuSearchApi {
|
||||
|
||||
val auth = Interceptor { chain ->
|
||||
val original = chain.request()
|
||||
|
||||
val newUrl =
|
||||
original.url.newBuilder().addQueryParameter("apikey", BuildConfig.ACCU_KEY)
|
||||
.build()
|
||||
val request = original.newBuilder().url(newUrl).build()
|
||||
|
||||
chain.proceed(request)
|
||||
}
|
||||
|
||||
|
||||
val client = OkHttpClient.Builder()
|
||||
.addInterceptor(auth)
|
||||
.callTimeout(30, TimeUnit.SECONDS)
|
||||
.readTimeout(30, TimeUnit.SECONDS)
|
||||
.build()
|
||||
|
||||
return Retrofit.Builder()
|
||||
.baseUrl(BASE_URL)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.client(client)
|
||||
.build()
|
||||
.create(AccuSearchApi::class.java)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.pranshulgg.weather_master_app.core.network.sources.search.accu
|
||||
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.location.Location
|
||||
import com.pranshulgg.weather_master_app.data.local.mapper.locations.toDomain
|
||||
import com.pranshulgg.weather_master_app.data.repository.data.SearchRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
class AccuSearchRepository @Inject constructor(
|
||||
private val api: AccuSearchApi
|
||||
) : SearchRepository {
|
||||
override suspend fun search(query: String): List<Location> {
|
||||
|
||||
val response = api.search(query)
|
||||
|
||||
val body = response.body() ?: return emptyList()
|
||||
|
||||
val domain = body.toDomain()
|
||||
|
||||
return domain
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package com.pranshulgg.weather_master_app.core.network.sources.search.accu.json
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
||||
data class AccuSearchJson(
|
||||
@SerializedName("EnglishName") val name: String,
|
||||
@SerializedName("Country") val country: AccuSearchCountryJson,
|
||||
@SerializedName("AdministrativeArea") val administrativeArea: AccuSearchAdministrativeAreaJson,
|
||||
@SerializedName("TimeZone") val timezone: AccuSearchTimeZoneJson,
|
||||
@SerializedName("GeoPosition") val geoPosition: AccuSearchGeoPositionJson
|
||||
)
|
||||
|
||||
data class AccuSearchCountryJson(
|
||||
@SerializedName("EnglishName") val name: String,
|
||||
@SerializedName("ID") val countryCode: String
|
||||
)
|
||||
|
||||
data class AccuSearchAdministrativeAreaJson(
|
||||
@SerializedName("EnglishName") val name: String?
|
||||
)
|
||||
|
||||
data class AccuSearchTimeZoneJson(
|
||||
@SerializedName("Name") val name: String
|
||||
)
|
||||
|
||||
data class AccuSearchGeoPositionJson(
|
||||
@SerializedName("Latitude") val latitude: Double,
|
||||
@SerializedName("Longitude") val longitude: Double
|
||||
)
|
||||
-4
@@ -25,9 +25,6 @@ interface GeoNamesSearchApi {
|
||||
private const val BASE_URL = "https://secure.geonames.org/"
|
||||
|
||||
fun create(): GeoNamesSearchApi {
|
||||
val logging = HttpLoggingInterceptor().apply {
|
||||
level = HttpLoggingInterceptor.Level.BASIC
|
||||
}
|
||||
|
||||
val auth = Interceptor { chain ->
|
||||
val original = chain.request()
|
||||
@@ -40,7 +37,6 @@ interface GeoNamesSearchApi {
|
||||
|
||||
val client = OkHttpClient.Builder()
|
||||
.addInterceptor(auth)
|
||||
.addInterceptor(logging)
|
||||
.callTimeout(30, TimeUnit.SECONDS)
|
||||
.readTimeout(30, TimeUnit.SECONDS)
|
||||
.build()
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ package com.pranshulgg.weather_master_app.core.network.sources.search.geonames
|
||||
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.location.Location
|
||||
import com.pranshulgg.weather_master_app.data.local.mapper.locations.toDomain
|
||||
import com.pranshulgg.weather_master_app.data.repository.SearchRepository
|
||||
import com.pranshulgg.weather_master_app.data.repository.data.SearchRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ import com.google.gson.annotations.SerializedName
|
||||
|
||||
|
||||
data class GeoNamesSearchJson(
|
||||
val geonames: List<GeoNamesSearchItemJson>
|
||||
val geonames: List<GeoNamesSearchItemJson>?
|
||||
)
|
||||
|
||||
data class GeoNamesSearchItemJson(
|
||||
@@ -15,7 +15,7 @@ data class GeoNamesSearchItemJson(
|
||||
val longitude: Double,
|
||||
|
||||
val name: String,
|
||||
val countryName: String,
|
||||
val countryName: String?,
|
||||
|
||||
@SerializedName("countryCode")
|
||||
val countryCode: String,
|
||||
|
||||
-4
@@ -26,9 +26,6 @@ interface GeoNamesTimezoneApi {
|
||||
private const val BASE_URL = "https://secure.geonames.org/"
|
||||
|
||||
fun create(): GeoNamesTimezoneApi {
|
||||
val logging = HttpLoggingInterceptor().apply {
|
||||
level = HttpLoggingInterceptor.Level.BASIC
|
||||
}
|
||||
|
||||
val auth = Interceptor { chain ->
|
||||
val original = chain.request()
|
||||
@@ -41,7 +38,6 @@ interface GeoNamesTimezoneApi {
|
||||
|
||||
val client = OkHttpClient.Builder()
|
||||
.addInterceptor(auth)
|
||||
.addInterceptor(logging)
|
||||
.callTimeout(30, TimeUnit.SECONDS)
|
||||
.readTimeout(30, TimeUnit.SECONDS)
|
||||
.build()
|
||||
|
||||
-4
@@ -23,12 +23,8 @@ interface OpenMeteoSearchApi {
|
||||
private const val BASE_URL = "https://geocoding-api.open-meteo.com/v1/"
|
||||
|
||||
fun create(): OpenMeteoSearchApi {
|
||||
val logging = HttpLoggingInterceptor().apply {
|
||||
level = HttpLoggingInterceptor.Level.BASIC
|
||||
}
|
||||
|
||||
val client = OkHttpClient.Builder()
|
||||
.addInterceptor(logging)
|
||||
.callTimeout(30, TimeUnit.SECONDS)
|
||||
.readTimeout(30, TimeUnit.SECONDS)
|
||||
.build()
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ package com.pranshulgg.weather_master_app.core.network.sources.search.openmeteo
|
||||
|
||||
import com.pranshulgg.weather_master_app.core.model.domain.location.Location
|
||||
import com.pranshulgg.weather_master_app.data.local.mapper.locations.toDomain
|
||||
import com.pranshulgg.weather_master_app.data.repository.SearchRepository
|
||||
import com.pranshulgg.weather_master_app.data.repository.data.SearchRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
class OpenMeteoSearchRepository @Inject constructor(
|
||||
|
||||
Loaded 100 of 679 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user