Compare commits
625 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4d46caee4 | ||
|
|
f92063dfe9 | ||
|
|
ce07e467f3 | ||
|
|
f6adc99187 | ||
|
|
950645cc96 | ||
|
|
cb71b6074d | ||
|
|
bb87dc2e14 | ||
|
|
ce49e4afc6 | ||
|
|
ea89f90edb | ||
|
|
8cba22024a | ||
|
|
9044193aa3 | ||
|
|
b145bb422b | ||
|
|
5a4f67d70a | ||
|
|
09c3dbbebc | ||
|
|
ad1f85ffcc | ||
|
|
ec8eb39599 | ||
|
|
adca4c3af9 | ||
|
|
a133b271d0 | ||
|
|
e0257445ef | ||
|
|
65c774d0d0 | ||
|
|
2e5f0a3725 | ||
|
|
ebae9b78b1 | ||
|
|
b73586f81b | ||
|
|
74d658f928 | ||
|
|
24a1572752 | ||
|
|
80099635be | ||
|
|
cd28526ccc | ||
|
|
277e10daf1 | ||
|
|
a6fb3c87c4 | ||
|
|
bf6474a488 | ||
|
|
08f8d6ac6a | ||
|
|
0c80efc686 | ||
|
|
e1b6561b70 | ||
|
|
56e91db0b4 | ||
|
|
ce3b6fdc37 | ||
|
|
885427fa85 | ||
|
|
b77365e60f | ||
|
|
b3d601aa35 | ||
|
|
f1aca45ce3 | ||
|
|
46b1902af2 | ||
|
|
96cee7e5c2 | ||
|
|
8a32811226 | ||
|
|
18dbaee4b5 | ||
|
|
9c7cea23a7 | ||
|
|
519b085dd2 | ||
|
|
66d3bc6c7b | ||
|
|
40270f219a | ||
|
|
08fba15fee | ||
|
|
379e1a354b | ||
|
|
eacfca715c | ||
|
|
4bfff4b7e9 | ||
|
|
bbad583e53 | ||
|
|
359202a594 | ||
|
|
7f68f7dd9d | ||
|
|
77a9de570c | ||
|
|
a02b193b90 | ||
|
|
789eb30d2b | ||
|
|
7a653a5bb7 | ||
|
|
c929977773 | ||
|
|
d21ec9d727 | ||
|
|
5332d0ac62 | ||
|
|
6508eb57fc | ||
|
|
b7cc19b719 | ||
|
|
925ebf3210 | ||
|
|
b1ff6805eb | ||
|
|
1f4646dbdc | ||
|
|
6612e77579 | ||
|
|
2fd6d5cd2e | ||
|
|
0531b97e19 | ||
|
|
7336b52e14 | ||
|
|
cc03275ad3 | ||
|
|
09909514d5 | ||
|
|
a3dd8cb00d | ||
|
|
d207f7e2b2 | ||
|
|
cc348e5d35 | ||
|
|
aeed19532f | ||
|
|
b52f870e29 | ||
|
|
7889c32be0 | ||
|
|
1ca91d684f | ||
|
|
648f76bd22 | ||
|
|
f8d772149b | ||
|
|
181156de10 | ||
|
|
a038a3366f | ||
|
|
c43dc175d0 | ||
|
|
fd3f7f4a37 | ||
|
|
20e5c0e292 | ||
|
|
768c639d2b | ||
|
|
9bd7f8347b | ||
|
|
ae57022102 | ||
|
|
12d95dd4b1 | ||
|
|
57ac5cb9bf | ||
|
|
24508be4d4 | ||
|
|
9136ff3ea3 | ||
|
|
4460d80b72 | ||
|
|
eb8c178603 | ||
|
|
ad08cfaad0 | ||
|
|
96845ad7cf | ||
|
|
16412821bf | ||
|
|
3c0f4402a8 | ||
|
|
260087d1fa | ||
|
|
3361ef949a | ||
|
|
dfe0e960dc | ||
|
|
98e0623cb7 | ||
|
|
97084db4de | ||
|
|
165c76bb69 | ||
|
|
e0e4145481 | ||
|
|
8c4e7e0e43 | ||
|
|
dee41dad9e | ||
|
|
47d596af08 | ||
|
|
4019a7c225 | ||
|
|
db0c199674 | ||
|
|
f11a1fd9cc | ||
|
|
892754bbae | ||
|
|
a0de0c2005 | ||
|
|
6b5f5c54dd | ||
|
|
fdac632b1c | ||
|
|
43f804c7a8 | ||
|
|
e85220d727 | ||
|
|
489d46e922 | ||
|
|
b2fdb049e2 | ||
|
|
878031cae8 | ||
|
|
aeb0b90281 | ||
|
|
83eb04eed3 | ||
|
|
aeb3916741 | ||
|
|
c42b0677d1 | ||
|
|
08f7e4900c | ||
|
|
8e5c31f7f3 | ||
|
|
23e777cd94 | ||
|
|
fe22bb1035 | ||
|
|
0da9c7f965 | ||
|
|
48adb0b256 | ||
|
|
b2eeeeddfb | ||
|
|
5ee2b6de48 | ||
|
|
4e0b5d79df | ||
|
|
027fac90b4 | ||
|
|
24118e0dc3 | ||
|
|
faf478a092 | ||
|
|
f4a7b00b1b | ||
|
|
df7680e06c | ||
|
|
bbe68974b2 | ||
|
|
aad300bd9c | ||
|
|
12ce568d3c | ||
|
|
25d3f76f9e | ||
|
|
aece93d63d | ||
|
|
45e667abf7 | ||
|
|
5869b39035 | ||
|
|
d981d57a8f | ||
|
|
1f9d1edc5c | ||
|
|
4944ee6078 | ||
|
|
c4b2b909e0 | ||
|
|
08f3928ebc | ||
|
|
350c177be8 | ||
|
|
d3103cb966 | ||
|
|
eec3721e9d | ||
|
|
8058f8f376 | ||
|
|
eae67fd482 | ||
|
|
d10727b87d | ||
|
|
52d6dc9376 | ||
|
|
6ff38e8068 | ||
|
|
b54f4a846c | ||
|
|
b69fa34b9f | ||
|
|
e1f050ac7e | ||
|
|
76668b65fc | ||
|
|
7524cc31c1 | ||
|
|
a7f832107d | ||
|
|
674b0d7285 | ||
|
|
d618a09f6d | ||
|
|
995b1fe63c | ||
|
|
6200f4f790 | ||
|
|
a16c312292 | ||
|
|
1d907bc2d4 | ||
|
|
d267ba4cde | ||
|
|
07c31ebde1 | ||
|
|
2c353628a3 | ||
|
|
3d170d88fb | ||
|
|
90171b2ebd | ||
|
|
36298893db | ||
|
|
ca7d71eed4 | ||
|
|
d0e2771a2f | ||
|
|
6b80bc5b5e | ||
|
|
016a613fd5 | ||
|
|
c6865f48f5 | ||
|
|
3935bd67f8 | ||
|
|
917993a4fa | ||
|
|
1d807002f8 | ||
|
|
f95e1138a0 | ||
|
|
1d16d74383 | ||
|
|
4713e99c7b | ||
|
|
1e122b36a3 | ||
|
|
c87335ff56 | ||
|
|
b8dd0e2fb1 | ||
|
|
3a754d5703 | ||
|
|
e39fa172cb | ||
|
|
8c0d2b67e4 | ||
|
|
12cba1f8fb | ||
|
|
bf5ae30bda | ||
|
|
2973b47555 | ||
|
|
65cba31306 | ||
|
|
629920c2b3 | ||
|
|
e0f00fd4f5 | ||
|
|
083680b563 | ||
|
|
9a637c484b | ||
|
|
175ef04c70 | ||
|
|
1d11f8316c | ||
|
|
bb8027d663 | ||
|
|
bfa5c66006 | ||
|
|
0a606f6d23 | ||
|
|
e4611508ca | ||
|
|
3a8ac8298d | ||
|
|
6ab6d0d205 | ||
|
|
30d398f5f1 | ||
|
|
85de7d08fd | ||
|
|
9f9724ce36 | ||
|
|
264acd0532 | ||
|
|
7a495c9bd6 | ||
|
|
42549bf1a6 | ||
|
|
56c97001fa | ||
|
|
4ad8b1aef8 | ||
|
|
92e8160505 | ||
|
|
0b19cdc95c | ||
|
|
c4b6674492 | ||
|
|
cd2fa7943b | ||
|
|
6245f25b7c | ||
|
|
3c29d4a19f | ||
|
|
f917952083 | ||
|
|
6fe22a5fa4 | ||
|
|
8ea12399d3 | ||
|
|
2947d9aeec | ||
|
|
17551f813b | ||
|
|
8022a0cd92 | ||
|
|
e5edaeb147 | ||
|
|
4b1bd48487 | ||
|
|
980a539ad2 | ||
|
|
cef329376b | ||
|
|
230546d57f | ||
|
|
b418ef0f99 | ||
|
|
343245f290 | ||
|
|
5ec2db5dca | ||
|
|
c21f4e1d2e | ||
|
|
a49404b877 | ||
|
|
1982408881 | ||
|
|
4e352e1430 | ||
|
|
4fa0f5ffeb | ||
|
|
fc91894336 | ||
|
|
176f66b437 | ||
|
|
0a0a5bd60f | ||
|
|
e5504e0bdf | ||
|
|
220c068822 | ||
|
|
1214c17389 | ||
|
|
a82f6b16b7 | ||
|
|
7f74574a7f | ||
|
|
6d6185dc5e | ||
|
|
21e0b08716 | ||
|
|
651a6d6b3d | ||
|
|
658054b13d | ||
|
|
58ebfb71d1 | ||
|
|
842fb976cd | ||
|
|
8c28183410 | ||
|
|
5ae1036f4d | ||
|
|
cf70854af5 | ||
|
|
da1f7bea4f | ||
|
|
a8180a04ab | ||
|
|
55acdfba2a | ||
|
|
4b4498e84d | ||
|
|
f483653506 | ||
|
|
6e3def2c13 | ||
|
|
6416378b78 | ||
|
|
3591bce1b5 | ||
|
|
174a00c469 | ||
|
|
f07cb350d4 | ||
|
|
3d8fbe05f3 | ||
|
|
1fc1d69dae | ||
|
|
af401e7b27 | ||
|
|
bc274b2cf7 | ||
|
|
488c732f3c | ||
|
|
4d58e52729 | ||
|
|
0b7d7bbe7f | ||
|
|
75ac9fd38d | ||
|
|
d8d7b6a766 | ||
|
|
aaa7bae55f | ||
|
|
1786a5e910 | ||
|
|
d9d93ffad3 | ||
|
|
032b9f1f17 | ||
|
|
eba629e5a7 | ||
|
|
41fb8b6bf4 | ||
|
|
430e6025fa | ||
|
|
57a16c4904 | ||
|
|
4525aee9a1 | ||
|
|
e99aae3ed4 | ||
|
|
a9cff1f49a | ||
|
|
f5b0f06bba | ||
|
|
f65e72fdc1 | ||
|
|
979565691f | ||
|
|
9c115efecb | ||
|
|
1ce7749826 | ||
|
|
ef232aba88 | ||
|
|
0c9619a550 | ||
|
|
8b9d20d908 | ||
|
|
1006254090 | ||
|
|
b784f94a64 | ||
|
|
34c382daea | ||
|
|
1b57be1d64 | ||
|
|
25676cff8c | ||
|
|
476c9f5840 | ||
|
|
d663f047bd | ||
|
|
7663a53e1c | ||
|
|
117d8b99df | ||
|
|
bec69b4706 | ||
|
|
0beb876cb4 | ||
|
|
666eb75779 | ||
|
|
b31bcc2a9c | ||
|
|
2c1458e026 | ||
|
|
8d65b5117e | ||
|
|
1e0c8a594f | ||
|
|
b05da7d27c | ||
|
|
00e6cf537a | ||
|
|
c2c1c6dfcc | ||
|
|
753d4cd981 | ||
|
|
86cfc10741 | ||
|
|
492e2f2e7e | ||
|
|
560cceca9b | ||
|
|
f19f8ca2a7 | ||
|
|
925cf982ca | ||
|
|
30a7e3b429 | ||
|
|
f978c6f7d7 | ||
|
|
facbf8ec02 | ||
|
|
ac338e9299 | ||
|
|
d18e6412f0 | ||
|
|
373096b339 | ||
|
|
bb4bff50b3 | ||
|
|
c9baf04505 | ||
|
|
938fec1ab3 | ||
|
|
ed9f04332e | ||
|
|
c20e8d1aea | ||
|
|
3a13f111eb | ||
|
|
6c95c683ba | ||
|
|
d666f59c1b | ||
|
|
28869498ae | ||
|
|
81104a3f38 | ||
|
|
48cdbf6b6b | ||
|
|
7e9ce00166 | ||
|
|
c3431b0921 | ||
|
|
27210317fd | ||
|
|
312b51a5fd | ||
|
|
96a649ca9c | ||
|
|
445d8168e1 | ||
|
|
24a219853e | ||
|
|
4271159294 | ||
|
|
9ff94a4402 | ||
|
|
448b8fa160 | ||
|
|
aa46eb4c6d | ||
|
|
7e35fa8710 | ||
|
|
66b9e9b5c1 | ||
|
|
ad45bafd62 | ||
|
|
4cb2b34d11 | ||
|
|
2b8482cb06 | ||
|
|
57bc6ad98e | ||
|
|
8ec8816e45 | ||
|
|
801bc2ab66 | ||
|
|
5fec87e688 | ||
|
|
9490c00f9f | ||
|
|
a14dde8183 | ||
|
|
b742cda635 | ||
|
|
2e92acbfd5 | ||
|
|
7af904d860 | ||
|
|
59289a2f40 | ||
|
|
b08d0a76ee | ||
|
|
cc8fdbe4a6 | ||
|
|
64eb477f4f | ||
|
|
68f368dc94 | ||
|
|
219d9b2a59 | ||
|
|
a7e1506ea0 | ||
|
|
f61cfaa781 | ||
|
|
66de395549 | ||
|
|
242f382da3 | ||
|
|
a879bd09b4 | ||
|
|
ed273fbfce | ||
|
|
31cb8f9fab | ||
|
|
2aeb6598dc | ||
|
|
9810083304 | ||
|
|
23fd0482c8 | ||
|
|
39f9e16a61 | ||
|
|
c3a5e759b7 | ||
|
|
f9d5aeee91 | ||
|
|
371631856a | ||
|
|
73f33bc0a3 | ||
|
|
ed595a3815 | ||
|
|
7c8fa27aaf | ||
|
|
b326b1b3d7 | ||
|
|
f527064e55 | ||
|
|
3a074ef6c5 | ||
|
|
7fbae16a53 | ||
|
|
98018ca590 | ||
|
|
7d5724d8d5 | ||
|
|
ba17a5592c | ||
|
|
7332e81e6e | ||
|
|
5aeacef511 | ||
|
|
8f3fd3b37e | ||
|
|
0fd58860a8 | ||
|
|
8edd3774d2 | ||
|
|
dd1a4cba76 | ||
|
|
1123fb3ca6 | ||
|
|
5bfd340176 | ||
|
|
7cb2f203b1 | ||
|
|
412d0a19e7 | ||
|
|
f2a50141b7 | ||
|
|
7f65ce0e84 | ||
|
|
8f577a4368 | ||
|
|
09f89afe2a | ||
|
|
d1dcdc2f50 | ||
|
|
e31a5f705c | ||
|
|
04314d507b | ||
|
|
409c5a0ba3 | ||
|
|
68f09125d4 | ||
|
|
ac2d4911fe | ||
|
|
26c2eaddff | ||
|
|
d41d6bd758 | ||
|
|
86b8bbfb5f | ||
|
|
7658b4c9fe | ||
|
|
f1384eef34 | ||
|
|
c7c4a011ef | ||
|
|
bdd73135f0 | ||
|
|
b367410aaf | ||
|
|
c27404cc3a | ||
|
|
9ff2359b4c | ||
|
|
d28ecb509e | ||
|
|
048e7d0ef6 | ||
|
|
1b49a6f3f7 | ||
|
|
fd6e4880d2 | ||
|
|
f27bbd318f | ||
|
|
79dfb11fa4 | ||
|
|
3bf9126595 | ||
|
|
a5a90dfbdd | ||
|
|
ac767f63ae | ||
|
|
782862294d | ||
|
|
eded4b2e16 | ||
|
|
707ba55e1d | ||
|
|
b71a533024 | ||
|
|
36093b9199 | ||
|
|
bd14a35e23 | ||
|
|
406da9732c | ||
|
|
219aa06835 | ||
|
|
43decb21f4 | ||
|
|
b152da9d21 | ||
|
|
14ce2305ce | ||
|
|
a65cb92f37 | ||
|
|
4a54115e31 | ||
|
|
3a80838b4c | ||
|
|
bb16da0f4a | ||
|
|
714ae7b9f0 | ||
|
|
f5f60cc9eb | ||
|
|
057c5f7ec8 | ||
|
|
d704588624 | ||
|
|
c82a6cc0e1 | ||
|
|
603d83ba1b | ||
|
|
fd15235124 | ||
|
|
0c1e5a9628 | ||
|
|
6403d135ea | ||
|
|
a7b33c48b3 | ||
|
|
4e31190291 | ||
|
|
e99a06654e | ||
|
|
cf4d0565c5 | ||
|
|
6b5a874db5 | ||
|
|
defc7a8fa4 | ||
|
|
06d568e61d | ||
|
|
6064c88f2c | ||
|
|
77b3430339 | ||
|
|
0f125cd63f | ||
|
|
65f84b116f | ||
|
|
2d008a5cc3 | ||
|
|
4dcd4483e9 | ||
|
|
0102ce2144 | ||
|
|
71d5887bcc | ||
|
|
76ce301d91 | ||
|
|
692ccd7838 | ||
|
|
bf97b1c115 | ||
|
|
6eda3c68a8 | ||
|
|
ca9a53bde9 | ||
|
|
9b9327c25e | ||
|
|
a2be4c73a1 | ||
|
|
720987197d | ||
|
|
c52e83fe10 | ||
|
|
e97e03b814 | ||
|
|
ac9b85e10b | ||
|
|
8e80af657f | ||
|
|
93f9afd98d | ||
|
|
c9178db87d | ||
|
|
18743f66e8 | ||
|
|
72ae2ec5c4 | ||
|
|
0a407d869e | ||
|
|
8c8b684cb4 | ||
|
|
63d1b86b5e | ||
|
|
49a9055a73 | ||
|
|
4f444bd3c9 | ||
|
|
1efab98f91 | ||
|
|
b8677b4c02 | ||
|
|
e6400d8305 | ||
|
|
7bdfdcc1f8 | ||
|
|
9d9c12a52d | ||
|
|
1aa9da57aa | ||
|
|
0b57e42652 | ||
|
|
9a988e82c4 | ||
|
|
9e83448cd0 | ||
|
|
8d9a3cbb1e | ||
|
|
fc5a40ace0 | ||
|
|
9f2d0b5b07 | ||
|
|
7e98e98ad0 | ||
|
|
f6085aa89b | ||
|
|
32905aa16b | ||
|
|
8a240d506b | ||
|
|
b6f07fdf85 | ||
|
|
9a7ab172ac | ||
|
|
3d6c70629d | ||
|
|
c8d13a6fa1 | ||
|
|
b24ac01493 | ||
|
|
be21da5e3b | ||
|
|
b6fea7dc9b | ||
|
|
adc2e96bf2 | ||
|
|
807dc612a7 | ||
|
|
1612de8231 | ||
|
|
4576ddf09c | ||
|
|
bb96de47be | ||
|
|
ccfc56e629 | ||
|
|
e6cde49247 | ||
|
|
1de41a8d24 | ||
|
|
953c62cc66 | ||
|
|
c2f5569010 | ||
|
|
baef35d263 | ||
|
|
8b8345d0e6 | ||
|
|
3bab677607 | ||
|
|
79362162d2 | ||
|
|
ca537c6321 | ||
|
|
79382ce6f8 | ||
|
|
ea70aa21a9 | ||
|
|
e9f1b2a9b4 | ||
|
|
981513086b | ||
|
|
9f4bfe75d1 | ||
|
|
dcd8bbbd01 | ||
|
|
cadfa5e034 | ||
|
|
76ea0c4978 | ||
|
|
c1321203c1 | ||
|
|
a8388db1c3 | ||
|
|
f0589c2f33 | ||
|
|
fbe7d64d5d | ||
|
|
a5722b2445 | ||
|
|
18e57e20ed | ||
|
|
5b83bf35d0 | ||
|
|
97fb8d8561 | ||
|
|
fe5a72ae90 | ||
|
|
643a48afec | ||
|
|
e50598dfa3 | ||
|
|
46fb1f0ac0 | ||
|
|
eaaeee6ee7 | ||
|
|
522c5562eb | ||
|
|
ef8c63c176 | ||
|
|
12537ec7f3 | ||
|
|
8b791ed19e | ||
|
|
a1fdd0c0d2 | ||
|
|
0b7097082d | ||
|
|
c903192d7c | ||
|
|
d8b5e0f5a1 | ||
|
|
fb8d476c34 | ||
|
|
b4652e2486 | ||
|
|
b0d37dc997 | ||
|
|
778930015e | ||
|
|
fb8c45a86d | ||
|
|
13b0533277 | ||
|
|
6cb6b1534d | ||
|
|
4098f2e498 | ||
|
|
19093a4ead | ||
|
|
c7e2cb9d06 | ||
|
|
6be22170d8 | ||
|
|
2077b0ab4c | ||
|
|
bc2ca86a95 | ||
|
|
a443582ca9 | ||
|
|
2162397575 | ||
|
|
6cfb32570b | ||
|
|
a8d66fd0a4 | ||
|
|
b46d3d28a9 | ||
|
|
44372059cd | ||
|
|
64668147d9 | ||
|
|
e21e71b442 | ||
|
|
10f646f125 | ||
|
|
187b76e04c | ||
|
|
f2c36cae37 | ||
|
|
77a6357ae4 | ||
|
|
6c1be53f86 | ||
|
|
59e02f047b | ||
|
|
321250f30e | ||
|
|
7559036abe | ||
|
|
6080b57f8a | ||
|
|
ddf654a641 | ||
|
|
bf8e187962 | ||
|
|
cf252c3ec4 | ||
|
|
d65541fb3e | ||
|
|
20ef99cfc7 | ||
|
|
87a003918d | ||
|
|
f5c3c90f37 | ||
|
|
ee690092ba | ||
|
|
34a386abce | ||
|
|
05f4c42bf9 | ||
|
|
1510dc9bc2 | ||
|
|
2a85b621f5 | ||
|
|
97abf2f230 | ||
|
|
1f2d38730d | ||
|
|
5c000f50aa | ||
|
|
581931b679 | ||
|
|
709a91b1db | ||
|
|
6ddb8d01ec | ||
|
|
81d3144da2 | ||
|
|
be2e8b7169 | ||
|
|
a21774031b | ||
|
|
de4dc9b9a0 | ||
|
|
7ae2859c78 | ||
|
|
8228472031 | ||
|
|
7ca5a2bd02 | ||
|
|
8858c7f619 | ||
|
|
992d7e3303 | ||
|
|
bce135cba8 | ||
|
|
8c30bedefb | ||
|
|
e26f2910f3 | ||
|
|
0b1208a11c | ||
|
|
261919f17a | ||
|
|
4206cbd557 | ||
|
|
edc203c9ed |
2
.bundle/config
Normal file
@@ -0,0 +1,2 @@
|
||||
---
|
||||
BUNDLE_PATH: "vendor/bundle"
|
||||
9
.editorconfig
Normal file
@@ -0,0 +1,9 @@
|
||||
# EditorConfig is awesome: https://EditorConfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
2
.env
@@ -1,4 +1,4 @@
|
||||
VITE_APP_API_URL=http://localhost:2021
|
||||
VITE_IS_LANDING_DEFAULT=false
|
||||
VITE_IS_LANDING_DEFAULT=true
|
||||
VITE_OPENREPLAY_PROJECT_KEY=
|
||||
VITE_IS_SELF_HOSTED=false
|
||||
@@ -2,3 +2,4 @@ VITE_APP_API_URL=http://localhost:2021
|
||||
VITE_APP_REDIRECT_URL=http://localhost:5173
|
||||
VITE_APP_GOOGLE_CLIENT_ID=USE_YOUR_OWN_CLIENT_ID
|
||||
VITE_IS_SELF_HOSTED=true
|
||||
VITE_IS_LANDING_DEFAULT=true
|
||||
25
.github/workflows/build.yml
vendored
@@ -2,39 +2,20 @@ name: Build validation
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main", "develop" ]
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [ "main", "develop" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [20.x, 22.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
- name: Use Node.js 20
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
node-version: 20.x
|
||||
cache: 'npm'
|
||||
- name: Install dependencies
|
||||
run: npm i
|
||||
- run: npm run build
|
||||
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js 22
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: 'npm'
|
||||
- name: Install dependencies
|
||||
run: npm i
|
||||
# Lint currently reporting lots of preexisting issues
|
||||
# - run: npm run lint
|
||||
|
||||
26
.gitignore
vendored
@@ -23,4 +23,28 @@ dist-ssr
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
resources/android/**/*
|
||||
resources/android/**/*
|
||||
resources/ios/**/*
|
||||
|
||||
# Secrets (pulled via scripts/pull-secrets.sh)
|
||||
.env.production
|
||||
android/app/google-services.json
|
||||
android/app/release/*.jks
|
||||
android/keystore.properties
|
||||
android/local.properties
|
||||
android/play-service-account.json
|
||||
ios/App/App/GoogleService-Info.plist
|
||||
ios/*.p8
|
||||
|
||||
# Release build outputs
|
||||
build/android
|
||||
build/ios
|
||||
fastlane/report.xml
|
||||
fastlane/Preview.html
|
||||
fastlane/.env
|
||||
fastlane/*.log
|
||||
vendor/bundle
|
||||
|
||||
# Claude Code skills cache
|
||||
.agents/
|
||||
skills-lock.json
|
||||
85
AUTOMATED_RELEASE.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# Automated Release Pipeline
|
||||
|
||||
Builds and (optionally) uploads signed Android and iOS release artifacts from the CLI — no Android Studio or Xcode GUI needed for routine releases.
|
||||
|
||||
## Quick start
|
||||
|
||||
```sh
|
||||
./scripts/pull-secrets.sh # pulls all signing secrets from Vaultwarden
|
||||
./scripts/release.sh # bump patch version, build + sign both platforms
|
||||
./scripts/release.sh --upload # also upload: Android → Play internal track, iOS → TestFlight
|
||||
```
|
||||
|
||||
Common flags on `release.sh`:
|
||||
|
||||
| Flag | Effect |
|
||||
|---|---|
|
||||
| `--android` / `--ios` | Build only one platform |
|
||||
| `--bump minor\|major` | Bump type (default: `patch`) |
|
||||
| `--skip-bump` | Build with the current version, don't bump |
|
||||
| `--upload` | Upload after building |
|
||||
| `--track TRACK` | Play Store track for `--upload` (default: `internal`) |
|
||||
|
||||
Outputs:
|
||||
- Android: `android/app/build/outputs/bundle/release/app-release.aab`
|
||||
- iOS: `build/ios/Donetick.ipa`
|
||||
|
||||
## One-time machine setup
|
||||
|
||||
1. `bundle install` — installs fastlane (Ruby gems, local to the repo via `vendor/bundle`)
|
||||
2. `./scripts/pull-secrets.sh` — pulls all secrets below from Vaultwarden
|
||||
3. `android/local.properties` needs `sdk.dir=<path to Android SDK>` — not pulled from vault, machine-specific. Android Studio creates this automatically; if building headless-only, create it manually.
|
||||
4. Export `ASC_ISSUER_ID` (App Store Connect API key issuer ID) — either in your shell profile, or add it to the `Donetick Env Production` vault note so `pull-secrets.sh` delivers it into `.env.production` (which `release.sh` auto-sources).
|
||||
5. A working Apple Distribution certificate + the `Donetick App Store(fastline)` provisioning profile must be installed in your keychain / `~/Library/MobileDevice/Provisioning Profiles/` (see "iOS signing model" below) — **not** currently pulled from vault, machine-specific one-time setup.
|
||||
|
||||
## Secrets pulled by `scripts/pull-secrets.sh`
|
||||
|
||||
All secrets live in Vaultwarden (`https://www.bitwarden.com`) as Secure Notes, named exactly as below:
|
||||
|
||||
| Vault item name | Written to | Encoding |
|
||||
|---|---|---|
|
||||
| Donetick Google Services Android | `android/app/google-services.json` | raw |
|
||||
| Donetick Android Keystore | `android/app/release/donetick.jks` | base64 |
|
||||
| Donetick Keystore Password | (used inline for `android/keystore.properties`) | raw |
|
||||
| Donetick Google Play Service Account | `android/play-service-account.json` | raw |
|
||||
| Donetick Google Services iOS | `ios/App/App/GoogleService-Info.plist` | raw |
|
||||
| Donetick App Store Connect Key | `ios/AuthKey_84F695CDQ3.p8` | base64 |
|
||||
| Donetick Env Production | `.env.production` | raw |
|
||||
|
||||
None of these files are committed to git — all covered by `.gitignore`.
|
||||
|
||||
## iOS signing model (important — don't relitigate this)
|
||||
|
||||
The App target uses **manual signing for Release**, not Automatic. This was a deliberate choice, not the default:
|
||||
|
||||
- The project has **two** Apple Distribution-type certificates on the Apple Developer account: an Xcode Cloud–managed one (private key never leaves Apple, can't be used for local CLI signing) and a plain one created via Xcode → Settings → Accounts → Manage Certificates (private key is in the local keychain, usable). Automatic signing kept binding to the wrong (Managed) one.
|
||||
- Fix: `ios/App/App.xcodeproj/project.pbxproj` → App target → Release config has `CODE_SIGN_STYLE = Manual`, `CODE_SIGN_IDENTITY = "Apple Distribution"`, `PROVISIONING_PROFILE_SPECIFIER = "Donetick App Store(fastline)"`. Debug config is untouched (still Automatic, for local dev builds in Xcode).
|
||||
- `fastlane/Fastfile`'s `ios release` lane passes explicit `export_options: { signingStyle: "manual", provisioningProfiles: {...} }` to `build_app` — do **not** switch this back to `-allowProvisioningUpdates`/automatic without a good reason, it re-triggers the ambiguous cert selection.
|
||||
|
||||
**If you ever add/change an entitlement** (new Capability in Signing & Capabilities, e.g. a new permission), the existing provisioning profile becomes stale and exports will fail with an error like `"App.app" requires a provisioning profile with the X feature`. Fix:
|
||||
1. developer.apple.com → Identifiers → `com.donetick.app` → confirm the new capability is checked
|
||||
2. developer.apple.com → Profiles → find `Donetick App Store(fastline)` → regenerate it → download
|
||||
3. Install it locally: get its UUID (`security cms -D -i <file>.mobileprovision | plutil -extract UUID xml1 -o - -`) and copy to `~/Library/MobileDevice/Provisioning Profiles/<uuid>.mobileprovision`
|
||||
|
||||
**If the Distribution certificate ever expires/is revoked**, redo the one-time Xcode step: Settings → Accounts → Manage Certificates → `+` → Apple Distribution, then regenerate the profile as above.
|
||||
|
||||
## Android signing model
|
||||
|
||||
Standard keystore signing via `android/keystore.properties`, read by `android/app/build.gradle`. One historical gotcha already fixed: `storeFile` must be `release/donetick.jks` (relative to the `android/app` module dir), **not** `app/release/donetick.jks` — that extra `app/` silently resolved to a double-nested wrong path and broke CLI builds (Android Studio may have masked this before).
|
||||
|
||||
## Play Store upload gotchas
|
||||
|
||||
- The service account (`fastline-471@donetick-5f910.iam.gserviceaccount.com`) needs the **Google Play Android Developer API enabled** in its GCP project (`donetick-5f910`), **and** explicit per-app release permission granted in Play Console → Users and permissions (not just account-level access) — **and you have to actually click Save**, the UI will silently not persist it otherwise.
|
||||
- Google Play Console permission changes can take time to propagate on Google's backend even after saving (historically documented as up to ~24h, though in practice it was near-instant once actually saved).
|
||||
- The Play Developer API requires the app to have had **at least one manual release** uploaded through the Play Console website before API uploads work at all — not an issue for Donetick (already satisfied) but relevant if this is ever set up for a brand-new app.
|
||||
|
||||
## Fastlane lanes reference
|
||||
|
||||
```sh
|
||||
bundle exec fastlane android release # build signed .aab
|
||||
bundle exec fastlane android apk # build signed .apk (sideloading/testing)
|
||||
bundle exec fastlane android upload [track:X] # upload .aab to Play Store (default track: internal)
|
||||
|
||||
bundle exec fastlane ios release # build signed .ipa
|
||||
bundle exec fastlane ios upload # upload .ipa to TestFlight
|
||||
```
|
||||
233
Gemfile.lock
Normal file
@@ -0,0 +1,233 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
CFPropertyList (3.0.8)
|
||||
abbrev (0.1.2)
|
||||
addressable (2.9.0)
|
||||
public_suffix (>= 2.0.2, < 8.0)
|
||||
artifactory (3.0.17)
|
||||
atomos (0.1.3)
|
||||
aws-eventstream (1.3.2)
|
||||
aws-partitions (1.1109.0)
|
||||
aws-sdk-core (3.224.1)
|
||||
aws-eventstream (~> 1, >= 1.3.0)
|
||||
aws-partitions (~> 1, >= 1.992.0)
|
||||
aws-sigv4 (~> 1.9)
|
||||
base64
|
||||
jmespath (~> 1, >= 1.6.1)
|
||||
logger
|
||||
aws-sdk-kms (1.101.0)
|
||||
aws-sdk-core (~> 3, >= 3.216.0)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sdk-s3 (1.188.0)
|
||||
aws-sdk-core (~> 3, >= 3.224.1)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sigv4 (1.11.0)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
babosa (1.0.4)
|
||||
base64 (0.2.0)
|
||||
claide (1.1.0)
|
||||
colored (1.2)
|
||||
colored2 (3.1.2)
|
||||
commander (4.6.0)
|
||||
highline (~> 2.0.0)
|
||||
csv (3.3.5)
|
||||
declarative (0.0.20)
|
||||
digest-crc (0.7.0)
|
||||
rake (>= 12.0.0, < 14.0.0)
|
||||
domain_name (0.5.20190701)
|
||||
unf (>= 0.0.5, < 1.0.0)
|
||||
dotenv (2.8.1)
|
||||
emoji_regex (3.2.3)
|
||||
excon (0.109.0)
|
||||
faraday (1.10.6)
|
||||
faraday-em_http (~> 1.0)
|
||||
faraday-em_synchrony (~> 1.0)
|
||||
faraday-excon (~> 1.1)
|
||||
faraday-httpclient (~> 1.0)
|
||||
faraday-multipart (~> 1.0)
|
||||
faraday-net_http (~> 1.0)
|
||||
faraday-net_http_persistent (~> 1.0)
|
||||
faraday-patron (~> 1.0)
|
||||
faraday-rack (~> 1.0)
|
||||
faraday-retry (~> 1.0)
|
||||
ruby2_keywords (>= 0.0.4)
|
||||
faraday-cookie_jar (0.0.8)
|
||||
faraday (>= 0.8.0)
|
||||
http-cookie (>= 1.0.0)
|
||||
faraday-em_http (1.0.0)
|
||||
faraday-em_synchrony (1.0.1)
|
||||
faraday-excon (1.1.0)
|
||||
faraday-httpclient (1.0.1)
|
||||
faraday-multipart (1.2.0)
|
||||
multipart-post (~> 2.0)
|
||||
faraday-net_http (1.0.2)
|
||||
faraday-net_http_persistent (1.2.0)
|
||||
faraday-patron (1.0.0)
|
||||
faraday-rack (1.0.0)
|
||||
faraday-retry (1.0.4)
|
||||
faraday_middleware (1.2.1)
|
||||
faraday (~> 1.0)
|
||||
fastimage (2.4.1)
|
||||
fastlane (2.230.0)
|
||||
CFPropertyList (>= 2.3, < 4.0.0)
|
||||
abbrev (~> 0.1.2)
|
||||
addressable (>= 2.8, < 3.0.0)
|
||||
artifactory (~> 3.0)
|
||||
aws-sdk-s3 (~> 1.0)
|
||||
babosa (>= 1.0.3, < 2.0.0)
|
||||
base64 (~> 0.2.0)
|
||||
bundler (>= 1.12.0, < 3.0.0)
|
||||
colored (~> 1.2)
|
||||
commander (~> 4.6)
|
||||
csv (~> 3.3)
|
||||
dotenv (>= 2.1.1, < 3.0.0)
|
||||
emoji_regex (>= 0.1, < 4.0)
|
||||
excon (>= 0.71.0, < 1.0.0)
|
||||
faraday (~> 1.0)
|
||||
faraday-cookie_jar (~> 0.0.6)
|
||||
faraday_middleware (~> 1.0)
|
||||
fastimage (>= 2.1.0, < 3.0.0)
|
||||
fastlane-sirp (>= 1.0.0)
|
||||
gh_inspector (>= 1.1.2, < 2.0.0)
|
||||
google-apis-androidpublisher_v3 (~> 0.3)
|
||||
google-apis-playcustomapp_v1 (~> 0.1)
|
||||
google-cloud-env (>= 1.6.0, < 2.0.0)
|
||||
google-cloud-storage (~> 1.31)
|
||||
highline (~> 2.0)
|
||||
http-cookie (~> 1.0.5)
|
||||
json (< 3.0.0)
|
||||
jwt (>= 2.1.0, < 3)
|
||||
logger (>= 1.6, < 2.0)
|
||||
mini_magick (>= 4.9.4, < 5.0.0)
|
||||
multipart-post (>= 2.0.0, < 3.0.0)
|
||||
mutex_m (~> 0.3.0)
|
||||
naturally (~> 2.2)
|
||||
nkf (~> 0.2.0)
|
||||
optparse (>= 0.1.1, < 1.0.0)
|
||||
plist (>= 3.1.0, < 4.0.0)
|
||||
rubyzip (>= 2.0.0, < 3.0.0)
|
||||
security (= 0.1.5)
|
||||
simctl (~> 1.6.3)
|
||||
terminal-notifier (>= 2.0.0, < 3.0.0)
|
||||
terminal-table (~> 3)
|
||||
tty-screen (>= 0.6.3, < 1.0.0)
|
||||
tty-spinner (>= 0.8.0, < 1.0.0)
|
||||
word_wrap (~> 1.0.0)
|
||||
xcodeproj (>= 1.13.0, < 2.0.0)
|
||||
xcpretty (~> 0.4.1)
|
||||
xcpretty-travis-formatter (>= 0.0.3, < 2.0.0)
|
||||
fastlane-sirp (1.1.0)
|
||||
gh_inspector (1.1.3)
|
||||
google-apis-androidpublisher_v3 (0.54.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-apis-core (0.11.3)
|
||||
addressable (~> 2.5, >= 2.5.1)
|
||||
googleauth (>= 0.16.2, < 2.a)
|
||||
httpclient (>= 2.8.1, < 3.a)
|
||||
mini_mime (~> 1.0)
|
||||
representable (~> 3.0)
|
||||
retriable (>= 2.0, < 4.a)
|
||||
rexml
|
||||
google-apis-iamcredentials_v1 (0.17.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-apis-playcustomapp_v1 (0.13.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-apis-storage_v1 (0.29.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-cloud-core (1.6.1)
|
||||
google-cloud-env (>= 1.0, < 3.a)
|
||||
google-cloud-errors (~> 1.0)
|
||||
google-cloud-env (1.6.0)
|
||||
faraday (>= 0.17.3, < 3.0)
|
||||
google-cloud-errors (1.3.1)
|
||||
google-cloud-storage (1.45.0)
|
||||
addressable (~> 2.8)
|
||||
digest-crc (~> 0.4)
|
||||
google-apis-iamcredentials_v1 (~> 0.1)
|
||||
google-apis-storage_v1 (~> 0.29.0)
|
||||
google-cloud-core (~> 1.6)
|
||||
googleauth (>= 0.16.2, < 2.a)
|
||||
mini_mime (~> 1.0)
|
||||
googleauth (1.8.1)
|
||||
faraday (>= 0.17.3, < 3.a)
|
||||
jwt (>= 1.4, < 3.0)
|
||||
multi_json (~> 1.11)
|
||||
os (>= 0.9, < 2.0)
|
||||
signet (>= 0.16, < 2.a)
|
||||
highline (2.0.3)
|
||||
http-cookie (1.0.8)
|
||||
domain_name (~> 0.5)
|
||||
httpclient (2.9.0)
|
||||
mutex_m
|
||||
jmespath (1.6.2)
|
||||
json (2.7.6)
|
||||
jwt (2.10.3)
|
||||
base64
|
||||
logger (1.7.0)
|
||||
mini_magick (4.13.2)
|
||||
mini_mime (1.1.5)
|
||||
multi_json (1.15.0)
|
||||
multipart-post (2.4.1)
|
||||
mutex_m (0.3.0)
|
||||
nanaimo (0.4.0)
|
||||
naturally (2.3.0)
|
||||
nkf (0.2.0)
|
||||
optparse (0.8.1)
|
||||
os (1.1.4)
|
||||
plist (3.7.2)
|
||||
public_suffix (5.1.1)
|
||||
rake (13.4.2)
|
||||
representable (3.2.0)
|
||||
declarative (< 0.1.0)
|
||||
trailblazer-option (>= 0.1.1, < 0.2.0)
|
||||
uber (< 0.2.0)
|
||||
retriable (3.8.0)
|
||||
rexml (3.4.4)
|
||||
rouge (3.28.0)
|
||||
ruby2_keywords (0.0.5)
|
||||
rubyzip (2.4.1)
|
||||
security (0.1.5)
|
||||
signet (0.18.0)
|
||||
addressable (~> 2.8)
|
||||
faraday (>= 0.17.5, < 3.a)
|
||||
jwt (>= 1.5, < 3.0)
|
||||
multi_json (~> 1.10)
|
||||
simctl (1.6.10)
|
||||
CFPropertyList
|
||||
naturally
|
||||
terminal-notifier (2.0.0)
|
||||
terminal-table (3.0.2)
|
||||
unicode-display_width (>= 1.1.1, < 3)
|
||||
trailblazer-option (0.1.2)
|
||||
tty-cursor (0.7.1)
|
||||
tty-screen (0.8.2)
|
||||
tty-spinner (0.9.3)
|
||||
tty-cursor (~> 0.7)
|
||||
uber (0.1.0)
|
||||
unf (0.2.0)
|
||||
unicode-display_width (2.6.0)
|
||||
word_wrap (1.0.0)
|
||||
xcodeproj (1.28.1)
|
||||
CFPropertyList (>= 2.3.3, < 4.0)
|
||||
atomos (~> 0.1.3)
|
||||
base64
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
nanaimo (~> 0.4.0)
|
||||
nkf
|
||||
rexml (>= 3.3.6, < 4.0)
|
||||
xcpretty (0.4.1)
|
||||
rouge (~> 3.28.0)
|
||||
xcpretty-travis-formatter (1.0.1)
|
||||
xcpretty (~> 0.2, >= 0.0.7)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
fastlane
|
||||
|
||||
BUNDLED WITH
|
||||
2.4.10
|
||||
@@ -20,12 +20,9 @@ As an avid for open-source, I was eager to create a solution that could benefit
|
||||
- Recurring Tasks: Schedule tasks to repeat daily, weekly, monthly, or yearly, with flexible customization options.
|
||||
- Progress Tracking: Track the completion status of tasks and view historical data.
|
||||
|
||||
## Installation
|
||||
## Development Environment
|
||||
|
||||
1. Clone the repository:
|
||||
2. Navigate to the project directory: `cd frontend`
|
||||
3. Download dependency `npm install`
|
||||
4. Run locally `npm start`
|
||||
Follow the full instructions here: https://github.com/donetick/donetick?tab=readme-ov-file#development-environment
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -41,7 +38,7 @@ Contributions are welcome! If you would like to contribute to Donetick, please f
|
||||
|
||||
Donetick is a work in progress and has been a fantastic learning experience for me as I've honed my React skills,I'm looking for collaborators to help improve and refine the Donetick. Feel free to open PR or suggest changes.
|
||||
|
||||
## Plans :
|
||||
## Plans:
|
||||
|
||||
My goal is to expand Donetick by offering a hosted infrastructure option. This will make it even easier for users to access and utilize Donetick's features without the need for self-hosting.
|
||||
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
def keystorePropertiesFile = rootProject.file("keystore.properties")
|
||||
def keystoreProperties = new Properties()
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
||||
}
|
||||
|
||||
android {
|
||||
namespace "com.donetick.app"
|
||||
compileSdk rootProject.ext.compileSdkVersion
|
||||
@@ -7,8 +13,8 @@ android {
|
||||
applicationId "com.donetick.app"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
versionCode 55
|
||||
versionName "1.2.34"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
aaptOptions {
|
||||
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
||||
@@ -16,8 +22,19 @@ android {
|
||||
ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~'
|
||||
}
|
||||
}
|
||||
signingConfigs {
|
||||
release {
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
storeFile file(keystoreProperties['storeFile'])
|
||||
storePassword keystoreProperties['storePassword']
|
||||
keyAlias keystoreProperties['keyAlias']
|
||||
keyPassword keystoreProperties['keyPassword']
|
||||
}
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
signingConfig keystorePropertiesFile.exists() ? signingConfigs.release : signingConfigs.debug
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
|
||||
@@ -9,13 +9,24 @@ android {
|
||||
|
||||
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
|
||||
dependencies {
|
||||
implementation project(':capacitor-community-speech-recognition')
|
||||
implementation project(':capacitor-community-sqlite')
|
||||
implementation project(':capacitor-app')
|
||||
implementation project(':capacitor-browser')
|
||||
implementation project(':capacitor-device')
|
||||
implementation project(':capacitor-haptics')
|
||||
implementation project(':capacitor-local-llm')
|
||||
implementation project(':capacitor-local-notifications')
|
||||
implementation project(':capacitor-network')
|
||||
implementation project(':capacitor-preferences')
|
||||
implementation project(':capacitor-push-notifications')
|
||||
implementation project(':capacitor-status-bar')
|
||||
implementation project(':capgo-capacitor-document-scanner')
|
||||
implementation project(':capgo-capacitor-nfc')
|
||||
implementation project(':capgo-capacitor-social-login')
|
||||
implementation project(':jcesarmobile-capacitor-ocr')
|
||||
implementation project(':revenuecat-purchases-capacitor')
|
||||
implementation project(':revenuecat-purchases-capacitor-ui')
|
||||
implementation project(':capacitor-plugin-safe-area')
|
||||
|
||||
}
|
||||
|
||||
37
android/app/release/output-metadata.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"version": 3,
|
||||
"artifactType": {
|
||||
"type": "APK",
|
||||
"kind": "Directory"
|
||||
},
|
||||
"applicationId": "com.donetick.app",
|
||||
"variantName": "release",
|
||||
"elements": [
|
||||
{
|
||||
"type": "SINGLE",
|
||||
"filters": [],
|
||||
"attributes": [],
|
||||
"versionCode": 25,
|
||||
"versionName": "1.2.3",
|
||||
"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": 28
|
||||
}
|
||||
@@ -1,14 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
android:theme="@style/AppTheme"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:usesCleartextTraffic="true">
|
||||
<activity
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode|navigation"
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/title_activity_main"
|
||||
android:theme="@style/AppTheme.NoActionBarLaunch"
|
||||
@@ -18,6 +21,79 @@
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
<!-- Deep link intent filter for OAuth and other donetick:// URLs -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="donetick" />
|
||||
</intent-filter>
|
||||
|
||||
<!-- NFC NDEF dispatch: open app directly when a donetick:// tag is scanned -->
|
||||
<intent-filter>
|
||||
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:scheme="donetick" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!-- Home-screen widgets -->
|
||||
<receiver
|
||||
android:name=".widget.TodayWidgetProvider"
|
||||
android:exported="false"
|
||||
android:label="@string/widget_today_label">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/widget_today_info" />
|
||||
</receiver>
|
||||
<receiver
|
||||
android:name=".widget.WeekWidgetProvider"
|
||||
android:exported="false"
|
||||
android:label="@string/widget_week_label">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/widget_week_info" />
|
||||
</receiver>
|
||||
<receiver
|
||||
android:name=".widget.PeopleWidgetProvider"
|
||||
android:exported="false"
|
||||
android:label="@string/widget_people_label">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/widget_people_info" />
|
||||
</receiver>
|
||||
<receiver
|
||||
android:name=".widget.QuickCaptureWidgetProvider"
|
||||
android:exported="false"
|
||||
android:label="@string/widget_quick_label">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/widget_quick_capture_info" />
|
||||
</receiver>
|
||||
<service
|
||||
android:name=".widget.WidgetListService"
|
||||
android:exported="false"
|
||||
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
||||
<activity
|
||||
android:name=".widget.WidgetConfigActivity"
|
||||
android:exported="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<provider
|
||||
@@ -27,9 +103,44 @@
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
|
||||
<!-- Push Notifications Icon -->
|
||||
<meta-data
|
||||
android:name="com.google.firebase.messaging.default_notification_icon"
|
||||
android:resource="@mipmap/ic_launcher" />
|
||||
|
||||
<!-- Push Notifications Color -->
|
||||
<meta-data
|
||||
android:name="com.google.firebase.messaging.default_notification_color"
|
||||
android:resource="@android:color/white" />
|
||||
</application>
|
||||
|
||||
<!-- Permissions -->
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
|
||||
<!-- Android 14+ partial photo access via system photo picker; no READ_MEDIA_IMAGES needed -->
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
|
||||
<!-- Explicitly block READ_MEDIA_IMAGES if any library injects it -->
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" tools:node="remove" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" tools:node="remove" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<!-- Remove advertising ID / Privacy Sandbox ad permissions if transitive SDKs inject them. -->
|
||||
<uses-permission android:name="com.google.android.gms.permission.AD_ID" tools:node="remove" />
|
||||
<uses-permission android:name="android.permission.ACCESS_ADSERVICES_ATTRIBUTION" tools:node="remove" />
|
||||
<uses-permission android:name="android.permission.ACCESS_ADSERVICES_AD_ID" tools:node="remove" />
|
||||
<uses-permission android:name="android.permission.ACCESS_ADSERVICES_CUSTOM_AUDIENCE" tools:node="remove" />
|
||||
<uses-permission android:name="android.permission.ACCESS_ADSERVICES_TOPICS" tools:node="remove" />
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
|
||||
<!-- Voice task capture -->
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<!-- Android 11+ package visibility for the system speech recognition service -->
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.speech.RecognitionService" />
|
||||
</intent>
|
||||
</queries>
|
||||
</manifest>
|
||||
|
||||
@@ -2,4 +2,57 @@ package com.donetick.app;
|
||||
|
||||
import com.getcapacitor.BridgeActivity;
|
||||
|
||||
public class MainActivity extends BridgeActivity {}
|
||||
import ee.forgr.capacitor.social.login.GoogleProvider;
|
||||
import ee.forgr.capacitor.social.login.SocialLoginPlugin;
|
||||
import ee.forgr.capacitor.social.login.ModifiedMainActivityForSocialLoginPlugin;
|
||||
import com.getcapacitor.PluginHandle;
|
||||
import com.getcapacitor.Plugin;
|
||||
import android.content.Intent;
|
||||
import android.nfc.NfcAdapter;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.donetick.app.widget.WidgetBridgePlugin;
|
||||
|
||||
|
||||
public class MainActivity extends BridgeActivity implements ModifiedMainActivityForSocialLoginPlugin {
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
registerPlugin(WidgetBridgePlugin.class);
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
// Capacitor only forwards ACTION_VIEW deep links, so normalize Donetick NFC intents before dispatch.
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())
|
||||
&& intent.getData() != null
|
||||
&& "donetick".equals(intent.getData().getScheme())) {
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
}
|
||||
super.onNewIntent(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if (requestCode >= GoogleProvider.REQUEST_AUTHORIZE_GOOGLE_MIN && requestCode < GoogleProvider.REQUEST_AUTHORIZE_GOOGLE_MAX) {
|
||||
PluginHandle pluginHandle = getBridge().getPlugin("SocialLogin");
|
||||
if (pluginHandle == null) {
|
||||
Log.i("Google Activity Result", "SocialLogin login handle is null");
|
||||
return;
|
||||
}
|
||||
Plugin plugin = pluginHandle.getInstance();
|
||||
if (!(plugin instanceof SocialLoginPlugin)) {
|
||||
Log.i("Google Activity Result", "SocialLogin plugin instance is not SocialLoginPlugin");
|
||||
return;
|
||||
}
|
||||
((SocialLoginPlugin) plugin).handleGoogleLoginIntent(requestCode, data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void IHaveModifiedTheMainActivityForTheUseWithSocialLoginPlugin() {}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package com.donetick.app.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.BitmapShader;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Shader;
|
||||
import android.graphics.Typeface;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Member avatars for the widgets: downloads and circle-crops profile photos
|
||||
* (cached on disk for a day) and falls back to a colored initials disc.
|
||||
* Downloads must only happen from a background/binder thread —
|
||||
* RemoteViewsFactory.onDataSetChanged qualifies.
|
||||
*/
|
||||
final class AvatarCache {
|
||||
private static final String TAG = "DonetickWidget";
|
||||
private static final String DIR = "widget_avatars";
|
||||
private static final long MAX_AGE_MS = 24 * 60 * 60 * 1000;
|
||||
private static final int SIZE_PX = 96;
|
||||
|
||||
// Joy-ish palette for initials discs; picked by hashing the member id so
|
||||
// each person keeps a stable color.
|
||||
private static final int[] PALETTE = {
|
||||
0xFF0B6BCB, 0xFF147D57, 0xFF9C4DD3, 0xFFC2410C,
|
||||
0xFF0E7490, 0xFFB02A5B, 0xFF5B21B6, 0xFF937800,
|
||||
};
|
||||
|
||||
private AvatarCache() {}
|
||||
|
||||
/** Photo avatar or null; never throws, never touches the network on failure loops. */
|
||||
static Bitmap photo(Context context, WidgetStore.Member member) {
|
||||
if (member == null || member.image == null || !member.image.startsWith("http")) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
File dir = new File(context.getCacheDir(), DIR);
|
||||
if (!dir.exists()) dir.mkdirs();
|
||||
File file = new File(dir, member.id + ".png");
|
||||
if (file.exists()
|
||||
&& System.currentTimeMillis() - file.lastModified() < MAX_AGE_MS) {
|
||||
return BitmapFactory.decodeFile(file.getAbsolutePath());
|
||||
}
|
||||
Bitmap downloaded = download(member.image);
|
||||
if (downloaded == null) {
|
||||
// Keep serving a stale copy rather than nothing.
|
||||
return file.exists() ? BitmapFactory.decodeFile(file.getAbsolutePath()) : null;
|
||||
}
|
||||
Bitmap circled = circleCrop(downloaded);
|
||||
try (FileOutputStream out = new FileOutputStream(file)) {
|
||||
circled.compress(Bitmap.CompressFormat.PNG, 100, out);
|
||||
}
|
||||
return circled;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Avatar load failed for member " + member.id, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** Colored disc with the member's first initial — the no-photo fallback. */
|
||||
static Bitmap initials(WidgetStore.Member member) {
|
||||
String name = member != null && member.name != null ? member.name.trim() : "";
|
||||
String letter = name.isEmpty()
|
||||
? "?"
|
||||
: new String(Character.toChars(name.codePointAt(0))).toUpperCase(Locale.getDefault());
|
||||
int color = PALETTE[Math.abs((member != null ? member.id : "?").hashCode()) % PALETTE.length];
|
||||
|
||||
Bitmap bitmap = Bitmap.createBitmap(SIZE_PX, SIZE_PX, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
paint.setColor(color);
|
||||
canvas.drawCircle(SIZE_PX / 2f, SIZE_PX / 2f, SIZE_PX / 2f, paint);
|
||||
|
||||
Paint text = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
text.setColor(Color.WHITE);
|
||||
text.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
|
||||
text.setTextSize(SIZE_PX * 0.42f);
|
||||
text.setTextAlign(Paint.Align.CENTER);
|
||||
Rect bounds = new Rect();
|
||||
text.getTextBounds(letter, 0, letter.length(), bounds);
|
||||
canvas.drawText(letter, SIZE_PX / 2f, SIZE_PX / 2f + bounds.height() / 2f, text);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
/** Best avatar for a member: photo when available, initials otherwise. */
|
||||
static Bitmap get(Context context, WidgetStore.Member member) {
|
||||
Bitmap photo = photo(context, member);
|
||||
return photo != null ? photo : initials(member);
|
||||
}
|
||||
|
||||
private static Bitmap download(String imageUrl) {
|
||||
HttpURLConnection connection = null;
|
||||
try {
|
||||
connection = (HttpURLConnection) new URL(imageUrl).openConnection();
|
||||
connection.setConnectTimeout(8000);
|
||||
connection.setReadTimeout(10000);
|
||||
if (connection.getResponseCode() != 200) return null;
|
||||
try (InputStream stream = connection.getInputStream()) {
|
||||
Bitmap raw = BitmapFactory.decodeStream(stream);
|
||||
if (raw == null) return null;
|
||||
return Bitmap.createScaledBitmap(raw, SIZE_PX, SIZE_PX, true);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Avatar download failed", e);
|
||||
return null;
|
||||
} finally {
|
||||
if (connection != null) connection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
private static Bitmap circleCrop(Bitmap source) {
|
||||
Bitmap output = Bitmap.createBitmap(SIZE_PX, SIZE_PX, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(output);
|
||||
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
paint.setShader(new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
|
||||
canvas.drawCircle(SIZE_PX / 2f, SIZE_PX / 2f, SIZE_PX / 2f, paint);
|
||||
return output;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.donetick.app.widget;
|
||||
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetProvider;
|
||||
import android.content.Context;
|
||||
|
||||
import com.donetick.app.R;
|
||||
|
||||
/** "People" home-screen widget: every circle member with their task load. */
|
||||
public class PeopleWidgetProvider extends AppWidgetProvider {
|
||||
@Override
|
||||
public void onUpdate(Context context, AppWidgetManager manager, int[] appWidgetIds) {
|
||||
for (int id : appWidgetIds) {
|
||||
manager.updateAppWidget(id, WidgetUi.build(context, WidgetUi.MODE_PEOPLE, id));
|
||||
}
|
||||
// Reload rows; the factory refreshes from the server when stale, which
|
||||
// is what keeps the widget current while the app stays closed.
|
||||
manager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.widget_list);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.donetick.app.widget;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetProvider;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import com.donetick.app.R;
|
||||
|
||||
/**
|
||||
* "Quick Capture" home-screen widget: three shortcuts straight into the
|
||||
* add-task flow (type, scan, speak). Purely a launcher — it shows no task
|
||||
* data, so it never needs a refresh cycle.
|
||||
*/
|
||||
public class QuickCaptureWidgetProvider extends AppWidgetProvider {
|
||||
// Handled in src/CapacitorListener.js → /chores?add_task=1[&mode=…]
|
||||
private static final String URI_TYPE = "donetick://chores/add";
|
||||
private static final String URI_SCAN = "donetick://chores/add?mode=scan";
|
||||
private static final String URI_VOICE = "donetick://chores/add?mode=voice";
|
||||
|
||||
@Override
|
||||
public void onUpdate(Context context, AppWidgetManager manager, int[] appWidgetIds) {
|
||||
for (int id : appWidgetIds) {
|
||||
manager.updateAppWidget(id, build(context));
|
||||
}
|
||||
}
|
||||
|
||||
private static RemoteViews build(Context context) {
|
||||
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_quick_capture);
|
||||
views.setOnClickPendingIntent(R.id.quick_type, deepLink(context, 10, URI_TYPE));
|
||||
views.setOnClickPendingIntent(R.id.quick_scan, deepLink(context, 11, URI_SCAN));
|
||||
views.setOnClickPendingIntent(R.id.quick_voice, deepLink(context, 12, URI_VOICE));
|
||||
return views;
|
||||
}
|
||||
|
||||
private static PendingIntent deepLink(Context context, int requestCode, String uri) {
|
||||
Intent intent = new Intent(context, com.donetick.app.MainActivity.class);
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
// Distinct data per tile so the three PendingIntents aren't collapsed.
|
||||
intent.setData(Uri.parse(uri));
|
||||
return PendingIntent.getActivity(context, requestCode, intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.donetick.app.widget;
|
||||
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetProvider;
|
||||
import android.content.Context;
|
||||
|
||||
import com.donetick.app.R;
|
||||
|
||||
/** "Today" home-screen widget: tasks due today plus anything awaiting approval. */
|
||||
public class TodayWidgetProvider extends AppWidgetProvider {
|
||||
@Override
|
||||
public void onUpdate(Context context, AppWidgetManager manager, int[] appWidgetIds) {
|
||||
for (int id : appWidgetIds) {
|
||||
manager.updateAppWidget(id, WidgetUi.build(context, WidgetUi.MODE_TODAY, id));
|
||||
}
|
||||
// Reload rows; the factory refreshes from the server when stale, which
|
||||
// is what keeps the widget current while the app stays closed.
|
||||
manager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.widget_list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeleted(Context context, int[] appWidgetIds) {
|
||||
for (int id : appWidgetIds) {
|
||||
WidgetStore.removeWidgetOptions(context, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.donetick.app.widget;
|
||||
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetProvider;
|
||||
import android.content.Context;
|
||||
|
||||
import com.donetick.app.R;
|
||||
|
||||
/** "Next 7 Days" home-screen widget: upcoming tasks grouped by day. */
|
||||
public class WeekWidgetProvider extends AppWidgetProvider {
|
||||
@Override
|
||||
public void onUpdate(Context context, AppWidgetManager manager, int[] appWidgetIds) {
|
||||
for (int id : appWidgetIds) {
|
||||
manager.updateAppWidget(id, WidgetUi.build(context, WidgetUi.MODE_WEEK, id));
|
||||
}
|
||||
manager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.widget_list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeleted(Context context, int[] appWidgetIds) {
|
||||
for (int id : appWidgetIds) {
|
||||
WidgetStore.removeWidgetOptions(context, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.donetick.app.widget;
|
||||
|
||||
import com.getcapacitor.Plugin;
|
||||
import com.getcapacitor.PluginCall;
|
||||
import com.getcapacitor.PluginMethod;
|
||||
import com.getcapacitor.annotation.CapacitorPlugin;
|
||||
|
||||
/**
|
||||
* JS bridge for the home-screen widgets (see src/service/WidgetService.js).
|
||||
* Persists the task snapshot + API config and redraws the widgets.
|
||||
*/
|
||||
@CapacitorPlugin(name = "WidgetBridge")
|
||||
public class WidgetBridgePlugin extends Plugin {
|
||||
|
||||
@PluginMethod
|
||||
public void update(PluginCall call) {
|
||||
String data = call.getString("data");
|
||||
String config = call.getString("config");
|
||||
if (data != null) WidgetStore.saveData(getContext(), data);
|
||||
if (config != null) WidgetStore.saveConfig(getContext(), config);
|
||||
WidgetUi.refreshAll(getContext());
|
||||
call.resolve();
|
||||
}
|
||||
|
||||
@PluginMethod
|
||||
public void clear(PluginCall call) {
|
||||
WidgetStore.clear(getContext());
|
||||
WidgetUi.refreshAll(getContext());
|
||||
call.resolve();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.donetick.app.widget;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Switch;
|
||||
|
||||
import com.donetick.app.R;
|
||||
|
||||
/**
|
||||
* Placement / long-press configuration for the Today and Next 7 Days widgets.
|
||||
* One option for now: include tasks assigned to other circle members
|
||||
* (stored per appWidgetId so mixed setups work side by side).
|
||||
*/
|
||||
public class WidgetConfigActivity extends Activity {
|
||||
private int appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
appWidgetId = getIntent().getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
|
||||
AppWidgetManager.INVALID_APPWIDGET_ID);
|
||||
// Cancelled result until Save, so backing out never adds a half-configured widget.
|
||||
setResult(RESULT_CANCELED, resultIntent());
|
||||
if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
setContentView(R.layout.widget_config);
|
||||
|
||||
Switch includeOthers = findViewById(R.id.config_include_others);
|
||||
includeOthers.setChecked(WidgetStore.includeOthers(this, appWidgetId));
|
||||
|
||||
findViewById(R.id.config_save).setOnClickListener(v -> {
|
||||
WidgetStore.setIncludeOthers(this, appWidgetId, includeOthers.isChecked());
|
||||
WidgetUi.refreshAll(this);
|
||||
setResult(RESULT_OK, resultIntent());
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
||||
private Intent resultIntent() {
|
||||
return new Intent().putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
package com.donetick.app.widget;
|
||||
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.view.View;
|
||||
import android.widget.RemoteViews;
|
||||
import android.widget.RemoteViewsService;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.donetick.app.R;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
/** Feeds task rows, day-group headers, and people rows to the widget ListView. */
|
||||
public class WidgetListService extends RemoteViewsService {
|
||||
@Override
|
||||
public RemoteViewsFactory onGetViewFactory(Intent intent) {
|
||||
String mode = intent.getStringExtra(WidgetUi.EXTRA_MODE);
|
||||
int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
|
||||
AppWidgetManager.INVALID_APPWIDGET_ID);
|
||||
return new WidgetListFactory(getApplicationContext(),
|
||||
mode != null ? mode : WidgetUi.MODE_TODAY, appWidgetId);
|
||||
}
|
||||
|
||||
static class Row {
|
||||
final String header; // non-null for day-group headers
|
||||
final WidgetStore.Task task; // non-null for task rows
|
||||
final WidgetStore.Member person; // non-null for people rows
|
||||
int todayCount;
|
||||
int weekCount;
|
||||
|
||||
Row(String header, WidgetStore.Task task, WidgetStore.Member person) {
|
||||
this.header = header;
|
||||
this.task = task;
|
||||
this.person = person;
|
||||
}
|
||||
}
|
||||
|
||||
static class WidgetListFactory implements RemoteViewsFactory {
|
||||
private final Context context;
|
||||
private final String mode;
|
||||
private final int appWidgetId;
|
||||
private List<Row> rows = new ArrayList<>();
|
||||
private final Map<String, Bitmap> avatars = new HashMap<>();
|
||||
private String myUserId;
|
||||
private boolean includeOthers;
|
||||
|
||||
WidgetListFactory(Context context, String mode, int appWidgetId) {
|
||||
this.context = context;
|
||||
this.mode = mode;
|
||||
this.appWidgetId = appWidgetId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {}
|
||||
|
||||
@Override
|
||||
public void onDataSetChanged() {
|
||||
// Runs on a binder thread, so synchronous network work is allowed
|
||||
// here. This is the background-refresh path: the 30-minute
|
||||
// updatePeriodMillis cycle lands here via notifyAppWidgetViewDataChanged.
|
||||
boolean refreshed = WidgetStore.refreshFromServerIfStale(context);
|
||||
|
||||
myUserId = WidgetStore.userId(context);
|
||||
includeOthers = WidgetStore.includeOthers(context, appWidgetId);
|
||||
List<WidgetStore.Task> allTasks = WidgetStore.loadTasks(context);
|
||||
List<WidgetStore.Member> members = WidgetStore.loadMembers(context);
|
||||
|
||||
if (WidgetUi.MODE_PEOPLE.equals(mode)) {
|
||||
rows = buildPeopleRows(allTasks, members);
|
||||
loadAvatars(members);
|
||||
} else {
|
||||
List<WidgetStore.Task> tasks =
|
||||
WidgetStore.visibleTasks(context, allTasks, includeOthers);
|
||||
rows = WidgetUi.MODE_TODAY.equals(mode)
|
||||
? buildTodayRows(tasks)
|
||||
: buildWeekRows(tasks);
|
||||
if (includeOthers) loadAvatars(members);
|
||||
}
|
||||
|
||||
if (refreshed) {
|
||||
// Counts and "Updated …" line live outside the list.
|
||||
WidgetUi.updateHeaders(context);
|
||||
}
|
||||
}
|
||||
|
||||
/** Resolve avatars for everyone up front — getViewAt must not block. */
|
||||
private void loadAvatars(List<WidgetStore.Member> members) {
|
||||
avatars.clear();
|
||||
for (WidgetStore.Member member : members) {
|
||||
avatars.put(member.id, AvatarCache.get(context, member));
|
||||
}
|
||||
}
|
||||
|
||||
private List<Row> buildTodayRows(List<WidgetStore.Task> tasks) {
|
||||
List<Row> result = new ArrayList<>();
|
||||
for (WidgetStore.Task task : WidgetStore.todaySubset(tasks)) {
|
||||
result.add(new Row(null, task, null));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<Row> buildWeekRows(List<WidgetStore.Task> tasks) {
|
||||
List<Row> result = new ArrayList<>();
|
||||
long startOfToday = WidgetStore.endOfDay(-1) + 1;
|
||||
SimpleDateFormat dayFormat = new SimpleDateFormat("EEE, MMM d", Locale.getDefault());
|
||||
|
||||
List<WidgetStore.Task> approvals = new ArrayList<>();
|
||||
List<WidgetStore.Task> scheduled = new ArrayList<>();
|
||||
for (WidgetStore.Task task : tasks) {
|
||||
if (task.approval) approvals.add(task);
|
||||
else if (task.dueDate != null) scheduled.add(task);
|
||||
}
|
||||
|
||||
if (!approvals.isEmpty()) {
|
||||
result.add(new Row(context.getString(R.string.widget_group_approval), null, null));
|
||||
for (WidgetStore.Task task : approvals) result.add(new Row(null, task, null));
|
||||
}
|
||||
|
||||
String currentGroup = null;
|
||||
for (WidgetStore.Task task : scheduled) {
|
||||
String group;
|
||||
if (task.dueDate < startOfToday) {
|
||||
group = context.getString(R.string.widget_group_overdue);
|
||||
} else if (task.dueDate <= WidgetStore.endOfDay(0)) {
|
||||
group = context.getString(R.string.widget_group_today);
|
||||
} else if (task.dueDate <= WidgetStore.endOfDay(1)) {
|
||||
group = context.getString(R.string.widget_group_tomorrow);
|
||||
} else {
|
||||
group = dayFormat.format(new Date(task.dueDate));
|
||||
}
|
||||
if (!group.equals(currentGroup)) {
|
||||
result.add(new Row(group, null, null));
|
||||
currentGroup = group;
|
||||
}
|
||||
result.add(new Row(null, task, null));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** One row per member with today/week workloads, busiest first. */
|
||||
private List<Row> buildPeopleRows(List<WidgetStore.Task> tasks,
|
||||
List<WidgetStore.Member> members) {
|
||||
List<Row> result = new ArrayList<>();
|
||||
List<WidgetStore.Task> todayTasks = WidgetStore.todaySubset(tasks);
|
||||
for (WidgetStore.Member member : members) {
|
||||
Row row = new Row(null, null, member);
|
||||
for (WidgetStore.Task task : tasks) {
|
||||
if (member.id.equals(task.assignedTo)) row.weekCount++;
|
||||
}
|
||||
for (WidgetStore.Task task : todayTasks) {
|
||||
if (member.id.equals(task.assignedTo)) row.todayCount++;
|
||||
}
|
||||
result.add(row);
|
||||
}
|
||||
java.util.Collections.sort(result, (a, b) -> {
|
||||
if (a.todayCount != b.todayCount) return b.todayCount - a.todayCount;
|
||||
if (a.weekCount != b.weekCount) return b.weekCount - a.weekCount;
|
||||
return a.person.name.compareToIgnoreCase(b.person.name);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RemoteViews getViewAt(int position) {
|
||||
if (position < 0 || position >= rows.size()) return null;
|
||||
Row row = rows.get(position);
|
||||
|
||||
if (row.header != null) {
|
||||
RemoteViews views = new RemoteViews(context.getPackageName(),
|
||||
R.layout.widget_row_day_header);
|
||||
views.setTextViewText(R.id.row_day, row.header);
|
||||
return views;
|
||||
}
|
||||
|
||||
if (row.person != null) {
|
||||
return buildPersonRow(row);
|
||||
}
|
||||
|
||||
WidgetStore.Task task = row.task;
|
||||
RemoteViews views = new RemoteViews(context.getPackageName(),
|
||||
R.layout.widget_row_task);
|
||||
views.setTextViewText(R.id.row_title, task.name);
|
||||
|
||||
boolean overdue = !task.approval && task.dueDate != null
|
||||
&& task.dueDate < System.currentTimeMillis();
|
||||
int secondary = ContextCompat.getColor(context, R.color.widget_text_secondary);
|
||||
int warning = ContextCompat.getColor(context, R.color.widget_warning);
|
||||
int danger = ContextCompat.getColor(context, R.color.widget_overdue);
|
||||
|
||||
String meta;
|
||||
int metaColor;
|
||||
if (task.approval) {
|
||||
meta = context.getString(R.string.widget_meta_approval);
|
||||
metaColor = warning;
|
||||
} else if (overdue) {
|
||||
meta = context.getString(R.string.widget_meta_overdue);
|
||||
metaColor = danger;
|
||||
} else {
|
||||
meta = android.text.format.DateFormat.getTimeFormat(context)
|
||||
.format(new Date(task.dueDate));
|
||||
metaColor = secondary;
|
||||
}
|
||||
views.setTextViewText(R.id.row_meta, meta);
|
||||
views.setTextColor(R.id.row_meta, metaColor);
|
||||
|
||||
int ringColor;
|
||||
if (task.approval) ringColor = warning;
|
||||
else if (overdue || task.priority == 1) ringColor = danger;
|
||||
else if (task.priority == 2) ringColor = warning;
|
||||
else ringColor = ContextCompat.getColor(context, R.color.widget_ring_neutral);
|
||||
views.setInt(R.id.row_ring, "setColorFilter", ringColor);
|
||||
|
||||
// In "everyone" mode, show who a task belongs to (own tasks stay clean).
|
||||
Bitmap avatar = includeOthers && task.assignedTo != null
|
||||
&& !task.assignedTo.equals(myUserId)
|
||||
? avatars.get(task.assignedTo)
|
||||
: null;
|
||||
if (avatar != null) {
|
||||
views.setImageViewBitmap(R.id.row_avatar, avatar);
|
||||
views.setViewVisibility(R.id.row_avatar, View.VISIBLE);
|
||||
} else {
|
||||
views.setViewVisibility(R.id.row_avatar, View.GONE);
|
||||
}
|
||||
|
||||
Intent fillIn = new Intent();
|
||||
fillIn.setData(Uri.parse("donetick://chores/" + task.id));
|
||||
views.setOnClickFillInIntent(R.id.row_root, fillIn);
|
||||
return views;
|
||||
}
|
||||
|
||||
private RemoteViews buildPersonRow(Row row) {
|
||||
RemoteViews views = new RemoteViews(context.getPackageName(),
|
||||
R.layout.widget_row_person);
|
||||
Bitmap avatar = avatars.get(row.person.id);
|
||||
if (avatar == null) avatar = AvatarCache.initials(row.person);
|
||||
views.setImageViewBitmap(R.id.person_avatar, avatar);
|
||||
views.setTextViewText(R.id.person_name, row.person.name);
|
||||
views.setTextViewText(R.id.person_counts, context.getString(
|
||||
R.string.widget_person_counts, row.todayCount, row.weekCount));
|
||||
|
||||
// Highlight the today-count when someone has work due today.
|
||||
int accent = ContextCompat.getColor(context, R.color.widget_accent);
|
||||
int secondary = ContextCompat.getColor(context, R.color.widget_text_secondary);
|
||||
views.setTextColor(R.id.person_counts, row.todayCount > 0 ? accent : secondary);
|
||||
|
||||
Intent fillIn = new Intent();
|
||||
fillIn.setData(Uri.parse("donetick://chores"));
|
||||
views.setOnClickFillInIntent(R.id.person_root, fillIn);
|
||||
return views;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RemoteViews getLoadingView() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getViewTypeCount() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasStableIds() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return rows.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
package com.donetick.app.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Shared storage + refresh logic for the home-screen widgets.
|
||||
*
|
||||
* The web app pushes a pre-filtered snapshot through WidgetBridgePlugin
|
||||
* whenever its chores cache changes. When the app has not run for a while,
|
||||
* {@link #refreshFromServerIfStale} re-fetches the list directly so the
|
||||
* widget stays current in the background (driven by the 30-minute
|
||||
* updatePeriodMillis cycle).
|
||||
*
|
||||
* Snapshot JSON: {version, lastUpdated,
|
||||
* tasks:[{id, name, dueDate, priority, approval, assignedTo}],
|
||||
* members:[{id, name, image}]}
|
||||
* Config JSON: {serverUrl, token, userId}
|
||||
*
|
||||
* Since v2 the snapshot holds every member's tasks; widgets narrow it down to
|
||||
* the current user unless the per-widget "include others" option is on.
|
||||
*/
|
||||
public final class WidgetStore {
|
||||
private static final String TAG = "DonetickWidget";
|
||||
private static final String PREFS = "donetick_widget";
|
||||
private static final String KEY_DATA = "widget_tasks";
|
||||
private static final String KEY_CONFIG = "widget_config";
|
||||
private static final String KEY_INCLUDE_OTHERS_PREFIX = "include_others_";
|
||||
|
||||
// Same filtering window as src/service/WidgetService.js
|
||||
private static final int WINDOW_DAYS = 7;
|
||||
private static final int MAX_TASKS = 100;
|
||||
// Don't hit the network if the app (or a previous refresh) updated the
|
||||
// snapshot recently; also guards against notify->refresh loops.
|
||||
private static final long STALE_MS = 10 * 60 * 1000;
|
||||
|
||||
private static final Object REFRESH_LOCK = new Object();
|
||||
|
||||
private WidgetStore() {}
|
||||
|
||||
public static class Task {
|
||||
public String id;
|
||||
public String name;
|
||||
public Long dueDate; // epoch millis, null when unscheduled
|
||||
public int priority;
|
||||
public boolean approval;
|
||||
public String assignedTo; // member userId, null when unassigned
|
||||
}
|
||||
|
||||
public static class Member {
|
||||
public String id;
|
||||
public String name;
|
||||
public String image; // avatar URL, may be null
|
||||
}
|
||||
|
||||
private static SharedPreferences prefs(Context context) {
|
||||
return context.getApplicationContext()
|
||||
.getSharedPreferences(PREFS, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
public static void saveData(Context context, String json) {
|
||||
prefs(context).edit().putString(KEY_DATA, json).apply();
|
||||
}
|
||||
|
||||
public static void saveConfig(Context context, String json) {
|
||||
prefs(context).edit().putString(KEY_CONFIG, json).apply();
|
||||
}
|
||||
|
||||
public static void clear(Context context) {
|
||||
prefs(context).edit().clear().apply();
|
||||
}
|
||||
|
||||
public static boolean hasConfig(Context context) {
|
||||
return prefs(context).getString(KEY_CONFIG, null) != null;
|
||||
}
|
||||
|
||||
/** The signed-in user's id from the pushed config, or null. */
|
||||
public static String userId(Context context) {
|
||||
try {
|
||||
String raw = prefs(context).getString(KEY_CONFIG, null);
|
||||
if (raw == null) return null;
|
||||
Object id = new JSONObject(raw).opt("userId");
|
||||
return id == null ? null : String.valueOf(id);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** Per-widget "include tasks assigned to others" option (default off). */
|
||||
public static boolean includeOthers(Context context, int appWidgetId) {
|
||||
return prefs(context).getBoolean(KEY_INCLUDE_OTHERS_PREFIX + appWidgetId, false);
|
||||
}
|
||||
|
||||
public static void setIncludeOthers(Context context, int appWidgetId, boolean value) {
|
||||
prefs(context).edit()
|
||||
.putBoolean(KEY_INCLUDE_OTHERS_PREFIX + appWidgetId, value)
|
||||
.apply();
|
||||
}
|
||||
|
||||
public static void removeWidgetOptions(Context context, int appWidgetId) {
|
||||
prefs(context).edit()
|
||||
.remove(KEY_INCLUDE_OTHERS_PREFIX + appWidgetId)
|
||||
.apply();
|
||||
}
|
||||
|
||||
public static long lastUpdated(Context context) {
|
||||
try {
|
||||
String raw = prefs(context).getString(KEY_DATA, null);
|
||||
if (raw == null) return 0;
|
||||
return new JSONObject(raw).optLong("lastUpdated", 0);
|
||||
} catch (Exception e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Task> loadTasks(Context context) {
|
||||
List<Task> tasks = new ArrayList<>();
|
||||
try {
|
||||
String raw = prefs(context).getString(KEY_DATA, null);
|
||||
if (raw == null) return tasks;
|
||||
JSONArray arr = new JSONObject(raw).optJSONArray("tasks");
|
||||
if (arr == null) return tasks;
|
||||
for (int i = 0; i < arr.length(); i++) {
|
||||
JSONObject obj = arr.optJSONObject(i);
|
||||
if (obj == null) continue;
|
||||
Task task = new Task();
|
||||
task.id = String.valueOf(obj.opt("id"));
|
||||
task.name = obj.optString("name", "");
|
||||
task.dueDate = obj.isNull("dueDate") ? null : obj.optLong("dueDate");
|
||||
task.priority = obj.optInt("priority", 0);
|
||||
task.approval = obj.optBoolean("approval", false);
|
||||
// v1 snapshots carried only the user's own tasks and had no
|
||||
// assignedTo — treat those rows as "mine".
|
||||
task.assignedTo = obj.has("assignedTo")
|
||||
? (obj.isNull("assignedTo") ? null : String.valueOf(obj.opt("assignedTo")))
|
||||
: userId(context);
|
||||
tasks.add(task);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Failed to parse widget snapshot", e);
|
||||
}
|
||||
return tasks;
|
||||
}
|
||||
|
||||
public static List<Member> loadMembers(Context context) {
|
||||
List<Member> members = new ArrayList<>();
|
||||
try {
|
||||
String raw = prefs(context).getString(KEY_DATA, null);
|
||||
if (raw == null) return members;
|
||||
JSONArray arr = new JSONObject(raw).optJSONArray("members");
|
||||
if (arr == null) return members;
|
||||
for (int i = 0; i < arr.length(); i++) {
|
||||
JSONObject obj = arr.optJSONObject(i);
|
||||
if (obj == null) continue;
|
||||
Member member = new Member();
|
||||
member.id = String.valueOf(obj.opt("id"));
|
||||
member.name = obj.optString("name", "");
|
||||
member.image = obj.isNull("image") ? null : obj.optString("image", null);
|
||||
members.add(member);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Failed to parse widget members", e);
|
||||
}
|
||||
return members;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tasks a today/week widget should render: everything when includeOthers,
|
||||
* otherwise the user's own tasks plus approvals (which wait on them).
|
||||
*/
|
||||
public static List<Task> visibleTasks(Context context, List<Task> tasks, boolean includeOthers) {
|
||||
if (includeOthers) return tasks;
|
||||
String me = userId(context);
|
||||
List<Task> mine = new ArrayList<>();
|
||||
for (Task task : tasks) {
|
||||
if (task.approval || (me != null && me.equals(task.assignedTo))) {
|
||||
mine.add(task);
|
||||
}
|
||||
}
|
||||
return mine;
|
||||
}
|
||||
|
||||
/** Tasks the Today widget shows: awaiting approval, overdue, or due today. */
|
||||
public static List<Task> todaySubset(List<Task> tasks) {
|
||||
long endOfToday = endOfDay(0);
|
||||
List<Task> subset = new ArrayList<>();
|
||||
for (Task task : tasks) {
|
||||
if (task.approval || (task.dueDate != null && task.dueDate <= endOfToday)) {
|
||||
subset.add(task);
|
||||
}
|
||||
}
|
||||
return subset;
|
||||
}
|
||||
|
||||
public static long endOfDay(int daysFromNow) {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.add(Calendar.DAY_OF_YEAR, daysFromNow);
|
||||
cal.set(Calendar.HOUR_OF_DAY, 23);
|
||||
cal.set(Calendar.MINUTE, 59);
|
||||
cal.set(Calendar.SECOND, 59);
|
||||
cal.set(Calendar.MILLISECOND, 999);
|
||||
return cal.getTimeInMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch /chores/ from the configured server and rebuild the snapshot.
|
||||
* Returns true when a network refresh actually happened and succeeded.
|
||||
* Safe to call from RemoteViewsFactory.onDataSetChanged (binder thread).
|
||||
*/
|
||||
public static boolean refreshFromServerIfStale(Context context) {
|
||||
synchronized (REFRESH_LOCK) {
|
||||
long age = System.currentTimeMillis() - lastUpdated(context);
|
||||
if (age < STALE_MS) return false;
|
||||
|
||||
String rawConfig = prefs(context).getString(KEY_CONFIG, null);
|
||||
if (rawConfig == null) return false;
|
||||
|
||||
HttpURLConnection connection = null;
|
||||
try {
|
||||
JSONObject config = new JSONObject(rawConfig);
|
||||
String serverUrl = config.optString("serverUrl", "");
|
||||
String token = config.optString("token", "");
|
||||
if (serverUrl.isEmpty() || token.isEmpty()) return false;
|
||||
|
||||
URL url = new URL(serverUrl + "/chores/");
|
||||
connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setConnectTimeout(10000);
|
||||
connection.setReadTimeout(15000);
|
||||
connection.setRequestProperty("Authorization", "Bearer " + token);
|
||||
connection.setRequestProperty("Accept", "application/json");
|
||||
|
||||
if (connection.getResponseCode() != 200) {
|
||||
// Expired token or server trouble — keep the last snapshot,
|
||||
// the UI surfaces staleness via the "Updated …" line.
|
||||
Log.w(TAG, "Widget refresh got HTTP " + connection.getResponseCode());
|
||||
return false;
|
||||
}
|
||||
|
||||
JSONArray chores = new JSONObject(readAll(connection.getInputStream()))
|
||||
.optJSONArray("res");
|
||||
if (chores == null) return false;
|
||||
|
||||
// The chores endpoint has no member profiles, so carry the
|
||||
// member list over from the previous snapshot (it changes
|
||||
// rarely and the app re-pushes it on every open).
|
||||
JSONArray members = null;
|
||||
String previous = prefs(context).getString(KEY_DATA, null);
|
||||
if (previous != null) {
|
||||
members = new JSONObject(previous).optJSONArray("members");
|
||||
}
|
||||
|
||||
JSONObject snapshot = new JSONObject();
|
||||
snapshot.put("version", 2);
|
||||
snapshot.put("lastUpdated", System.currentTimeMillis());
|
||||
snapshot.put("tasks", filterChores(chores));
|
||||
snapshot.put("members", members == null ? new JSONArray() : members);
|
||||
saveData(context, snapshot.toString());
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Widget background refresh failed", e);
|
||||
return false;
|
||||
} finally {
|
||||
if (connection != null) connection.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Mirror of buildWidgetTasks in src/service/WidgetService.js. */
|
||||
private static JSONArray filterChores(JSONArray chores) throws Exception {
|
||||
long cutoff = endOfDay(WINDOW_DAYS);
|
||||
List<JSONObject> selected = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < chores.length(); i++) {
|
||||
JSONObject chore = chores.optJSONObject(i);
|
||||
if (chore == null || chore.opt("id") == null) continue;
|
||||
|
||||
boolean approval = chore.optInt("status", 0) == 3;
|
||||
Long dueDate = parseDate(chore.optString("nextDueDate", null));
|
||||
boolean inWindow = dueDate != null && dueDate <= cutoff;
|
||||
if (!approval && !inWindow) continue;
|
||||
|
||||
JSONObject task = new JSONObject();
|
||||
task.put("id", chore.opt("id"));
|
||||
task.put("name", chore.optString("name", ""));
|
||||
task.put("dueDate", dueDate == null ? JSONObject.NULL : dueDate);
|
||||
task.put("priority", chore.optInt("priority", 0));
|
||||
task.put("approval", approval);
|
||||
task.put("assignedTo", chore.isNull("assignedTo")
|
||||
? JSONObject.NULL
|
||||
: String.valueOf(chore.opt("assignedTo")));
|
||||
selected.add(task);
|
||||
}
|
||||
|
||||
Collections.sort(selected, (a, b) -> {
|
||||
boolean aApproval = a.optBoolean("approval");
|
||||
boolean bApproval = b.optBoolean("approval");
|
||||
if (aApproval != bApproval) return aApproval ? -1 : 1;
|
||||
long aDue = a.isNull("dueDate") ? Long.MAX_VALUE : a.optLong("dueDate");
|
||||
long bDue = b.isNull("dueDate") ? Long.MAX_VALUE : b.optLong("dueDate");
|
||||
return Long.compare(aDue, bDue);
|
||||
});
|
||||
|
||||
JSONArray result = new JSONArray();
|
||||
for (int i = 0; i < selected.size() && i < MAX_TASKS; i++) {
|
||||
result.put(selected.get(i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Long parseDate(String value) {
|
||||
if (value == null || value.isEmpty() || "null".equals(value)) return null;
|
||||
try {
|
||||
return OffsetDateTime.parse(value).toInstant().toEpochMilli();
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static String readAll(InputStream stream) throws Exception {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(stream, StandardCharsets.UTF_8))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
builder.append(line);
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
141
android/app/src/main/java/com/donetick/app/widget/WidgetUi.java
Normal file
@@ -0,0 +1,141 @@
|
||||
package com.donetick.app.widget;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.view.View;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import com.donetick.app.MainActivity;
|
||||
import com.donetick.app.R;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/** Builds the shell RemoteViews shared by the widgets and pushes updates. */
|
||||
public final class WidgetUi {
|
||||
public static final String MODE_TODAY = "today";
|
||||
public static final String MODE_WEEK = "week";
|
||||
public static final String MODE_PEOPLE = "people";
|
||||
public static final String EXTRA_MODE = "com.donetick.app.widget.MODE";
|
||||
|
||||
private WidgetUi() {}
|
||||
|
||||
/** Full refresh: redraw headers and reload list content (used by the JS bridge). */
|
||||
public static void refreshAll(Context context) {
|
||||
updateHeaders(context);
|
||||
AppWidgetManager manager = AppWidgetManager.getInstance(context);
|
||||
manager.notifyAppWidgetViewDataChanged(
|
||||
widgetIds(context, manager, TodayWidgetProvider.class), R.id.widget_list);
|
||||
manager.notifyAppWidgetViewDataChanged(
|
||||
widgetIds(context, manager, WeekWidgetProvider.class), R.id.widget_list);
|
||||
manager.notifyAppWidgetViewDataChanged(
|
||||
widgetIds(context, manager, PeopleWidgetProvider.class), R.id.widget_list);
|
||||
}
|
||||
|
||||
/** Redraw title/count/subtitle only — safe to call from the list factory. */
|
||||
public static void updateHeaders(Context context) {
|
||||
AppWidgetManager manager = AppWidgetManager.getInstance(context);
|
||||
for (int id : widgetIds(context, manager, TodayWidgetProvider.class)) {
|
||||
manager.updateAppWidget(id, build(context, MODE_TODAY, id));
|
||||
}
|
||||
for (int id : widgetIds(context, manager, WeekWidgetProvider.class)) {
|
||||
manager.updateAppWidget(id, build(context, MODE_WEEK, id));
|
||||
}
|
||||
for (int id : widgetIds(context, manager, PeopleWidgetProvider.class)) {
|
||||
manager.updateAppWidget(id, build(context, MODE_PEOPLE, id));
|
||||
}
|
||||
}
|
||||
|
||||
private static int[] widgetIds(Context context, AppWidgetManager manager, Class<?> provider) {
|
||||
return manager.getAppWidgetIds(new ComponentName(context, provider));
|
||||
}
|
||||
|
||||
public static RemoteViews build(Context context, String mode, int appWidgetId) {
|
||||
boolean today = MODE_TODAY.equals(mode);
|
||||
boolean people = MODE_PEOPLE.equals(mode);
|
||||
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_shell);
|
||||
|
||||
int titleRes = today ? R.string.widget_today_title
|
||||
: people ? R.string.widget_people_title
|
||||
: R.string.widget_week_title;
|
||||
views.setTextViewText(R.id.widget_title, context.getString(titleRes));
|
||||
|
||||
if (people) {
|
||||
views.setViewVisibility(R.id.widget_count, View.GONE);
|
||||
} else {
|
||||
boolean includeOthers = WidgetStore.includeOthers(context, appWidgetId);
|
||||
List<WidgetStore.Task> tasks = WidgetStore.visibleTasks(
|
||||
context, WidgetStore.loadTasks(context), includeOthers);
|
||||
int count = (today ? WidgetStore.todaySubset(tasks) : tasks).size();
|
||||
views.setTextViewText(R.id.widget_count, String.valueOf(count));
|
||||
views.setViewVisibility(R.id.widget_count, count > 0 ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
views.setTextViewText(R.id.widget_subtitle, subtitle(context));
|
||||
|
||||
if (!WidgetStore.hasConfig(context)) {
|
||||
views.setTextViewText(R.id.widget_empty,
|
||||
context.getString(R.string.widget_signed_out));
|
||||
} else {
|
||||
int emptyRes = today ? R.string.widget_empty_today
|
||||
: people ? R.string.widget_empty_people
|
||||
: R.string.widget_empty_week;
|
||||
views.setTextViewText(R.id.widget_empty, context.getString(emptyRes));
|
||||
}
|
||||
|
||||
// The Today widget gets a quick-add button that deep links straight
|
||||
// into the in-app AddTaskModal.
|
||||
if (today) {
|
||||
Intent addTask = new Intent(context, MainActivity.class);
|
||||
addTask.setAction(Intent.ACTION_VIEW);
|
||||
addTask.setData(Uri.parse("donetick://chores/add"));
|
||||
views.setOnClickPendingIntent(R.id.widget_add, PendingIntent.getActivity(
|
||||
context, 2, addTask,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE));
|
||||
views.setViewVisibility(R.id.widget_add, View.VISIBLE);
|
||||
} else {
|
||||
views.setViewVisibility(R.id.widget_add, View.GONE);
|
||||
}
|
||||
|
||||
// List content comes from WidgetListService; mode travels in the intent
|
||||
// and the unique data URI keeps the adapters from being collapsed.
|
||||
Intent adapterIntent = new Intent(context, WidgetListService.class);
|
||||
adapterIntent.putExtra(EXTRA_MODE, mode);
|
||||
adapterIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
|
||||
adapterIntent.setData(Uri.parse("donetickwidget://" + mode + "/" + appWidgetId));
|
||||
views.setRemoteAdapter(R.id.widget_list, adapterIntent);
|
||||
views.setEmptyView(R.id.widget_list, R.id.widget_empty);
|
||||
|
||||
// Row taps deep link into the chore view; the row's fill-in intent
|
||||
// supplies the donetick://chores/<id> data URI.
|
||||
Intent rowTemplate = new Intent(context, MainActivity.class);
|
||||
rowTemplate.setAction(Intent.ACTION_VIEW);
|
||||
views.setPendingIntentTemplate(R.id.widget_list, PendingIntent.getActivity(
|
||||
context, 1, rowTemplate,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE));
|
||||
|
||||
// Anywhere else on the widget simply opens the app.
|
||||
Intent openApp = new Intent(context, MainActivity.class);
|
||||
views.setOnClickPendingIntent(R.id.widget_container, PendingIntent.getActivity(
|
||||
context, 0, openApp,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE));
|
||||
|
||||
return views;
|
||||
}
|
||||
|
||||
private static String subtitle(Context context) {
|
||||
String date = new SimpleDateFormat("EEE, MMM d", Locale.getDefault())
|
||||
.format(new Date());
|
||||
long lastUpdated = WidgetStore.lastUpdated(context);
|
||||
if (lastUpdated <= 0) return date;
|
||||
String time = android.text.format.DateFormat.getTimeFormat(context)
|
||||
.format(new Date(lastUpdated));
|
||||
return date + " · " + context.getString(R.string.widget_updated_at, time);
|
||||
}
|
||||
}
|
||||
1
android/app/src/main/res/.impeccable/hook.cache.json
Normal file
@@ -0,0 +1 @@
|
||||
{"version":1,"sessions":{}}
|
||||
|
After Width: | Height: | Size: 23 KiB |
BIN
android/app/src/main/res/drawable-nodpi/widget_preview_quick.png
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
BIN
android/app/src/main/res/drawable-nodpi/widget_preview_today.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
android/app/src/main/res/drawable-nodpi/widget_preview_week.png
Normal file
|
After Width: | Height: | Size: 47 KiB |
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||
<solid android:color="@color/widget_bg" />
|
||||
<!-- Match the launcher's system-wide widget corner radius on Android 12+ -->
|
||||
<corners android:radius="@android:dimen/system_app_widget_background_radius" />
|
||||
</shape>
|
||||
11
android/app/src/main/res/drawable/ic_widget_add.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="@color/widget_accent">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z" />
|
||||
</vector>
|
||||
14
android/app/src/main/res/drawable/ic_widget_mic.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="@color/widget_accent">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,14c1.66,0 3,-1.34 3,-3V5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v6C9,12.66 10.34,14 12,14z" />
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M17,11c0,2.76 -2.24,5 -5,5s-5,-2.24 -5,-5H5c0,3.53 2.61,6.43 6,6.92V21h2v-3.08c3.39,-0.49 6,-3.39 6,-6.92H17z" />
|
||||
</vector>
|
||||
15
android/app/src/main/res/drawable/ic_widget_scan.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="@color/widget_accent">
|
||||
<!-- Framing corners plus a scan line: reads as "scan" at widget size. -->
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M4,4h5v2H6v3H4V4zM15,4h5v5h-2V6h-3V4zM4,15h2v3h3v2H4V15zM18,15h2v5h-5v-2h3V15z" />
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M3,11h18v2H3V11z" />
|
||||
</vector>
|
||||
5
android/app/src/main/res/drawable/widget_background.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||
<solid android:color="@color/widget_bg" />
|
||||
<corners android:radius="24dp" />
|
||||
</shape>
|
||||
5
android/app/src/main/res/drawable/widget_count_bg.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||
<solid android:color="@color/widget_accent_soft" />
|
||||
<corners android:radius="10dp" />
|
||||
</shape>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Initials disc stand-in for the picker previews; placed widgets get the
|
||||
real cached avatars from AvatarCache. -->
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
|
||||
<solid android:color="@color/widget_accent_soft" />
|
||||
<size android:width="28dp" android:height="28dp" />
|
||||
</shape>
|
||||
6
android/app/src/main/res/drawable/widget_ring.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
|
||||
<solid android:color="@android:color/transparent" />
|
||||
<stroke android:width="2dp" android:color="#FFFFFF" />
|
||||
<size android:width="18dp" android:height="18dp" />
|
||||
</shape>
|
||||
6
android/app/src/main/res/drawable/widget_tile_bg.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Tappable tile on the Quick Capture widget. -->
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||
<solid android:color="@color/widget_accent_soft" />
|
||||
<corners android:radius="18dp" />
|
||||
</shape>
|
||||
43
android/app/src/main/res/layout/widget_config.xml
Normal file
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/widget_bg"
|
||||
android:orientation="vertical"
|
||||
android:padding="24dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/widget_config_title"
|
||||
android:textColor="@color/widget_text_primary"
|
||||
android:textSize="22sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<Switch
|
||||
android:id="@+id/config_include_others"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:minHeight="48dp"
|
||||
android:text="@string/widget_config_include_others"
|
||||
android:textColor="@color/widget_text_primary"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="@string/widget_config_include_others_hint"
|
||||
android:textColor="@color/widget_text_secondary"
|
||||
android:textSize="13sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/config_save"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="32dp"
|
||||
android:backgroundTint="@color/widget_accent"
|
||||
android:text="@string/widget_config_save"
|
||||
android:textColor="#FFFFFF" />
|
||||
</LinearLayout>
|
||||
182
android/app/src/main/res/layout/widget_preview_people.xml
Normal file
@@ -0,0 +1,182 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Widget-picker preview for the People widget. See widget_preview_today.xml
|
||||
for why the real shell can't be previewed directly. Avatars are initials
|
||||
discs here; placed widgets get the real photos from AvatarCache.
|
||||
Keep in visual sync with widget_shell.xml + widget_row_person.xml. -->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/widget_background"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingTop="14dp"
|
||||
android:paddingBottom="10dp">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toStartOf="@+id/preview_count"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/widget_people_title"
|
||||
android:textColor="@color/widget_text_primary"
|
||||
android:textSize="15sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/preview_count"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:background="@drawable/widget_count_bg"
|
||||
android:gravity="center"
|
||||
android:minWidth="22dp"
|
||||
android:paddingStart="7dp"
|
||||
android:paddingEnd="7dp"
|
||||
android:paddingTop="2dp"
|
||||
android:paddingBottom="2dp"
|
||||
android:text="@string/widget_preview_count_people"
|
||||
android:textColor="@color/widget_accent"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold" />
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="1dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/widget_preview_updated"
|
||||
android:textColor="@color/widget_text_secondary"
|
||||
android:textSize="11sp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="44dp"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingBottom="5dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:background="@drawable/widget_preview_avatar"
|
||||
android:gravity="center"
|
||||
android:text="@string/widget_preview_initials_1"
|
||||
android:textColor="@color/widget_accent"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/widget_preview_person_1"
|
||||
android:textColor="@color/widget_text_primary"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/widget_preview_counts_1"
|
||||
android:textColor="@color/widget_text_secondary"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="44dp"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingBottom="5dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:background="@drawable/widget_preview_avatar"
|
||||
android:gravity="center"
|
||||
android:text="@string/widget_preview_initials_2"
|
||||
android:textColor="@color/widget_accent"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/widget_preview_person_2"
|
||||
android:textColor="@color/widget_text_primary"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/widget_preview_counts_2"
|
||||
android:textColor="@color/widget_text_secondary"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="44dp"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingBottom="5dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:background="@drawable/widget_preview_avatar"
|
||||
android:gravity="center"
|
||||
android:text="@string/widget_preview_initials_3"
|
||||
android:textColor="@color/widget_accent"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/widget_preview_person_3"
|
||||
android:textColor="@color/widget_text_primary"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/widget_preview_counts_3"
|
||||
android:textColor="@color/widget_text_secondary"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
182
android/app/src/main/res/layout/widget_preview_today.xml
Normal file
@@ -0,0 +1,182 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Widget-picker preview for the Today widget. Mirrors widget_shell.xml, but
|
||||
with literal sample rows: the real shell fills its ListView from a
|
||||
RemoteViewsFactory, which the picker never binds, so it would render blank.
|
||||
Keep in visual sync with widget_shell.xml + widget_row_task.xml. -->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/widget_background"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingTop="14dp"
|
||||
android:paddingBottom="10dp">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toStartOf="@+id/preview_count"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/widget_today_title"
|
||||
android:textColor="@color/widget_text_primary"
|
||||
android:textSize="15sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/preview_count"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toStartOf="@+id/preview_add"
|
||||
android:background="@drawable/widget_count_bg"
|
||||
android:gravity="center"
|
||||
android:minWidth="22dp"
|
||||
android:paddingStart="7dp"
|
||||
android:paddingEnd="7dp"
|
||||
android:paddingTop="2dp"
|
||||
android:paddingBottom="2dp"
|
||||
android:text="@string/widget_preview_count_today"
|
||||
android:textColor="@color/widget_accent"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/preview_add"
|
||||
android:layout_width="26dp"
|
||||
android:layout_height="26dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="6dp"
|
||||
android:background="@drawable/widget_count_bg"
|
||||
android:contentDescription="@string/widget_add_task"
|
||||
android:padding="5dp"
|
||||
android:src="@drawable/ic_widget_add" />
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="1dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/widget_preview_updated"
|
||||
android:textColor="@color/widget_text_secondary"
|
||||
android:textSize="11sp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="40dp"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/widget_ring"
|
||||
android:tint="@color/widget_overdue" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/widget_preview_task_1"
|
||||
android:textColor="@color/widget_text_primary"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/widget_meta_overdue"
|
||||
android:textColor="@color/widget_overdue"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="40dp"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/widget_ring"
|
||||
android:tint="@color/widget_ring_neutral" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/widget_preview_task_2"
|
||||
android:textColor="@color/widget_text_primary"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/widget_preview_meta_1"
|
||||
android:textColor="@color/widget_text_secondary"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="40dp"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/widget_ring"
|
||||
android:tint="@color/widget_ring_neutral" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/widget_preview_task_3"
|
||||
android:textColor="@color/widget_text_primary"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/widget_preview_meta_2"
|
||||
android:textColor="@color/widget_text_secondary"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
193
android/app/src/main/res/layout/widget_preview_week.xml
Normal file
@@ -0,0 +1,193 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Widget-picker preview for the Next 7 Days widget. See widget_preview_today.xml
|
||||
for why the real shell can't be previewed directly. Keep in visual sync with
|
||||
widget_shell.xml + widget_row_day_header.xml + widget_row_task.xml. -->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/widget_background"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingTop="14dp"
|
||||
android:paddingBottom="10dp">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toStartOf="@+id/preview_count"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/widget_week_title"
|
||||
android:textColor="@color/widget_text_primary"
|
||||
android:textSize="15sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/preview_count"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:background="@drawable/widget_count_bg"
|
||||
android:gravity="center"
|
||||
android:minWidth="22dp"
|
||||
android:paddingStart="7dp"
|
||||
android:paddingEnd="7dp"
|
||||
android:paddingTop="2dp"
|
||||
android:paddingBottom="2dp"
|
||||
android:text="@string/widget_preview_count_week"
|
||||
android:textColor="@color/widget_accent"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold" />
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="1dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/widget_preview_updated"
|
||||
android:textColor="@color/widget_text_secondary"
|
||||
android:textSize="11sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:letterSpacing="0.08"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="2dp"
|
||||
android:text="@string/widget_group_today"
|
||||
android:textAllCaps="true"
|
||||
android:textColor="@color/widget_text_secondary"
|
||||
android:textSize="10sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="40dp"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/widget_ring"
|
||||
android:tint="@color/widget_ring_neutral" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/widget_preview_task_1"
|
||||
android:textColor="@color/widget_text_primary"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/widget_preview_meta_1"
|
||||
android:textColor="@color/widget_text_secondary"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="40dp"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/widget_ring"
|
||||
android:tint="@color/widget_ring_neutral" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/widget_preview_task_2"
|
||||
android:textColor="@color/widget_text_primary"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/widget_preview_meta_2"
|
||||
android:textColor="@color/widget_text_secondary"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:letterSpacing="0.08"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="2dp"
|
||||
android:text="@string/widget_group_tomorrow"
|
||||
android:textAllCaps="true"
|
||||
android:textColor="@color/widget_text_secondary"
|
||||
android:textSize="10sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="40dp"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/widget_ring"
|
||||
android:tint="@color/widget_ring_neutral" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/widget_preview_task_3"
|
||||
android:textColor="@color/widget_text_primary"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/widget_preview_meta_1"
|
||||
android:textColor="@color/widget_text_secondary"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
110
android/app/src/main/res/layout/widget_quick_capture.xml
Normal file
@@ -0,0 +1,110 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Quick Capture widget: three one-tap ways into the add-task flow. -->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/quick_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/widget_background"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingBottom="12dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:baselineAligned="false"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/quick_type"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/widget_tile_bg"
|
||||
android:contentDescription="@string/widget_quick_type"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:contentDescription="@string/widget_quick_type"
|
||||
android:src="@drawable/ic_widget_add" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:maxLines="1"
|
||||
android:text="@string/widget_quick_type"
|
||||
android:textColor="@color/widget_accent"
|
||||
android:textSize="11sp"
|
||||
android:textStyle="bold" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/quick_scan"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/widget_tile_bg"
|
||||
android:contentDescription="@string/widget_quick_scan"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:contentDescription="@string/widget_quick_scan"
|
||||
android:src="@drawable/ic_widget_scan" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:maxLines="1"
|
||||
android:text="@string/widget_quick_scan"
|
||||
android:textColor="@color/widget_accent"
|
||||
android:textSize="11sp"
|
||||
android:textStyle="bold" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/quick_voice"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/widget_tile_bg"
|
||||
android:contentDescription="@string/widget_quick_voice"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:contentDescription="@string/widget_quick_voice"
|
||||
android:src="@drawable/ic_widget_mic" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:maxLines="1"
|
||||
android:text="@string/widget_quick_voice"
|
||||
android:textColor="@color/widget_accent"
|
||||
android:textSize="11sp"
|
||||
android:textStyle="bold" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
12
android/app/src/main/res/layout/widget_row_day_header.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/row_day"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:letterSpacing="0.08"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="2dp"
|
||||
android:textAllCaps="true"
|
||||
android:textColor="@color/widget_text_secondary"
|
||||
android:textSize="10sp"
|
||||
android:textStyle="bold" />
|
||||
37
android/app/src/main/res/layout/widget_row_person.xml
Normal file
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/person_root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="44dp"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingBottom="5dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/person_avatar"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:importantForAccessibility="no" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/person_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="@color/widget_text_primary"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/person_counts"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/widget_text_secondary"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
46
android/app/src/main/res/layout/widget_row_task.xml
Normal file
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/row_root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="40dp"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/row_ring"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/widget_ring" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/row_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="@color/widget_text_primary"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/row_meta"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/widget_text_secondary"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<!-- Assignee avatar, shown only in "everyone" mode for others' tasks. -->
|
||||
<ImageView
|
||||
android:id="@+id/row_avatar"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
93
android/app/src/main/res/layout/widget_shell.xml
Normal file
@@ -0,0 +1,93 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/widget_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/widget_background"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingTop="14dp"
|
||||
android:paddingBottom="10dp">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widget_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toStartOf="@id/widget_count"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="@color/widget_text_primary"
|
||||
android:textSize="15sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widget_count"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toStartOf="@+id/widget_add"
|
||||
android:layout_centerVertical="true"
|
||||
android:background="@drawable/widget_count_bg"
|
||||
android:minWidth="22dp"
|
||||
android:gravity="center"
|
||||
android:paddingStart="7dp"
|
||||
android:paddingEnd="7dp"
|
||||
android:paddingTop="2dp"
|
||||
android:paddingBottom="2dp"
|
||||
android:textColor="@color/widget_accent"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<!-- Quick-add, shown on the Today widget only (deep links to the
|
||||
in-app AddTaskModal). Gone by default so the other widgets keep
|
||||
the count pill flush with the edge. -->
|
||||
<ImageView
|
||||
android:id="@+id/widget_add"
|
||||
android:layout_width="26dp"
|
||||
android:layout_height="26dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="6dp"
|
||||
android:background="@drawable/widget_count_bg"
|
||||
android:contentDescription="@string/widget_add_task"
|
||||
android:padding="5dp"
|
||||
android:src="@drawable/ic_widget_add"
|
||||
android:visibility="gone" />
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widget_subtitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="1dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="@color/widget_text_secondary"
|
||||
android:textSize="11sp" />
|
||||
|
||||
<ListView
|
||||
android:id="@+id/widget_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="6dp"
|
||||
android:divider="@null"
|
||||
android:dividerHeight="0dp"
|
||||
android:listSelector="@android:color/transparent"
|
||||
android:scrollbars="none" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widget_empty"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:lineSpacingExtra="3dp"
|
||||
android:textColor="@color/widget_text_secondary"
|
||||
android:textSize="13sp"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
12
android/app/src/main/res/values-night/colors.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="widget_bg">#181C20</color>
|
||||
<color name="widget_text_primary">#F0F4F8</color>
|
||||
<color name="widget_text_secondary">#9FA6AD</color>
|
||||
<color name="widget_accent">#4B9BE8</color>
|
||||
<color name="widget_accent_soft">#12395F</color>
|
||||
<color name="widget_overdue">#F09898</color>
|
||||
<color name="widget_warning">#F3C896</color>
|
||||
<color name="widget_ring_neutral">#555E68</color>
|
||||
<color name="widget_divider">#252B31</color>
|
||||
</resources>
|
||||
13
android/app/src/main/res/values/colors.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Home-screen widget palette (values-night overrides for dark mode) -->
|
||||
<color name="widget_bg">#FFFFFF</color>
|
||||
<color name="widget_text_primary">#171A1C</color>
|
||||
<color name="widget_text_secondary">#6B7681</color>
|
||||
<color name="widget_accent">#0B6BCB</color>
|
||||
<color name="widget_accent_soft">#E3EFFB</color>
|
||||
<color name="widget_overdue">#C41C1C</color>
|
||||
<color name="widget_warning">#B26A00</color>
|
||||
<color name="widget_ring_neutral">#B8C0C9</color>
|
||||
<color name="widget_divider">#EDF1F5</color>
|
||||
</resources>
|
||||
@@ -4,4 +4,58 @@
|
||||
<string name="title_activity_main">Donetick</string>
|
||||
<string name="package_name">com.donetick.app</string>
|
||||
<string name="custom_url_scheme">com.donetick.app</string>
|
||||
|
||||
<!-- Home-screen widgets -->
|
||||
<string name="widget_today_label">Today</string>
|
||||
<string name="widget_week_label">Next 7 Days</string>
|
||||
<string name="widget_today_description">Your tasks due today, plus anything waiting on you.</string>
|
||||
<string name="widget_week_description">Your tasks for the next 7 days, grouped by day.</string>
|
||||
<string name="widget_today_title">Today</string>
|
||||
<string name="widget_week_title">Next 7 days</string>
|
||||
<string name="widget_empty_today">All caught up!\nNothing due today</string>
|
||||
<string name="widget_empty_week">All caught up!\nNothing due this week</string>
|
||||
<string name="widget_signed_out">Open Donetick and sign in\nto see your tasks</string>
|
||||
<string name="widget_meta_overdue">Overdue</string>
|
||||
<string name="widget_meta_approval">Approve</string>
|
||||
<string name="widget_group_approval">Needs approval</string>
|
||||
<string name="widget_group_overdue">Overdue</string>
|
||||
<string name="widget_group_today">Today</string>
|
||||
<string name="widget_group_tomorrow">Tomorrow</string>
|
||||
<string name="widget_updated_at">Updated %s</string>
|
||||
<string name="widget_add_task">Add task</string>
|
||||
<string name="widget_people_label">People</string>
|
||||
<string name="widget_people_description">Everyone in your circle with their tasks for today and the week ahead.</string>
|
||||
<string name="widget_people_title">People</string>
|
||||
<string name="widget_empty_people">No circle members yet</string>
|
||||
<string name="widget_person_counts">%1$d today · %2$d this week</string>
|
||||
<string name="widget_quick_label">Quick Capture</string>
|
||||
<string name="widget_quick_description">Capture a task in one tap — type it, scan it, or say it.</string>
|
||||
<string name="widget_quick_type">Type</string>
|
||||
<string name="widget_quick_scan">Scan</string>
|
||||
<string name="widget_quick_voice">Speak</string>
|
||||
<string name="widget_config_title">Widget options</string>
|
||||
<string name="widget_config_include_others">Show everyone\'s tasks</string>
|
||||
<string name="widget_config_include_others_hint">Include tasks assigned to other members of your circle. Their avatar appears next to their tasks.</string>
|
||||
<string name="widget_config_save">Save</string>
|
||||
|
||||
<!-- Sample data for the widget-picker previews (never shown on a placed
|
||||
widget). Kept generic so it reads well in any locale. -->
|
||||
<string name="widget_preview_updated">Updated just now</string>
|
||||
<string name="widget_preview_task_1">Take out the bins</string>
|
||||
<string name="widget_preview_task_2">Water the plants</string>
|
||||
<string name="widget_preview_task_3">Book the vet</string>
|
||||
<string name="widget_preview_meta_1">6:00 PM</string>
|
||||
<string name="widget_preview_meta_2">8:30 PM</string>
|
||||
<string name="widget_preview_count_today">3</string>
|
||||
<string name="widget_preview_count_week">7</string>
|
||||
<string name="widget_preview_count_people">4</string>
|
||||
<string name="widget_preview_person_1">Alex</string>
|
||||
<string name="widget_preview_person_2">Sam</string>
|
||||
<string name="widget_preview_person_3">Jordan</string>
|
||||
<string name="widget_preview_initials_1">A</string>
|
||||
<string name="widget_preview_initials_2">S</string>
|
||||
<string name="widget_preview_initials_3">J</string>
|
||||
<string name="widget_preview_counts_1">2 today · 5 this week</string>
|
||||
<string name="widget_preview_counts_2">1 today · 3 this week</string>
|
||||
<string name="widget_preview_counts_3">0 today · 2 this week</string>
|
||||
</resources>
|
||||
|
||||
15
android/app/src/main/res/xml/network_security_config.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<!--
|
||||
Trust both the system CA store and user-installed CA certificates.
|
||||
This lets self-hosted Donetick instances that use custom or self-signed
|
||||
certificates work once the user installs their CA on the device, without
|
||||
having to modify/repackage the APK. See donetick/donetick#727.
|
||||
-->
|
||||
<base-config cleartextTrafficPermitted="true">
|
||||
<trust-anchors>
|
||||
<certificates src="system" />
|
||||
<certificates src="user" />
|
||||
</trust-anchors>
|
||||
</base-config>
|
||||
</network-security-config>
|
||||
15
android/app/src/main/res/xml/widget_people_info.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:description="@string/widget_people_description"
|
||||
android:initialLayout="@layout/widget_shell"
|
||||
android:previewLayout="@layout/widget_preview_people"
|
||||
android:previewImage="@drawable/widget_preview_people"
|
||||
android:minWidth="180dp"
|
||||
android:minHeight="110dp"
|
||||
android:minResizeWidth="110dp"
|
||||
android:minResizeHeight="110dp"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
android:targetCellWidth="3"
|
||||
android:targetCellHeight="2"
|
||||
android:updatePeriodMillis="1800000"
|
||||
android:widgetCategory="home_screen" />
|
||||
17
android/app/src/main/res/xml/widget_quick_capture_info.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- The layout is fully static (no bound data), so it doubles as its own
|
||||
API 31+ preview. -->
|
||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:description="@string/widget_quick_description"
|
||||
android:initialLayout="@layout/widget_quick_capture"
|
||||
android:previewLayout="@layout/widget_quick_capture"
|
||||
android:previewImage="@drawable/widget_preview_quick"
|
||||
android:minWidth="180dp"
|
||||
android:minHeight="70dp"
|
||||
android:minResizeWidth="180dp"
|
||||
android:minResizeHeight="60dp"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
android:targetCellWidth="4"
|
||||
android:targetCellHeight="1"
|
||||
android:updatePeriodMillis="0"
|
||||
android:widgetCategory="home_screen" />
|
||||
17
android/app/src/main/res/xml/widget_today_info.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:description="@string/widget_today_description"
|
||||
android:initialLayout="@layout/widget_shell"
|
||||
android:previewLayout="@layout/widget_preview_today"
|
||||
android:previewImage="@drawable/widget_preview_today"
|
||||
android:minWidth="180dp"
|
||||
android:minHeight="110dp"
|
||||
android:minResizeWidth="110dp"
|
||||
android:minResizeHeight="110dp"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
android:targetCellWidth="3"
|
||||
android:targetCellHeight="2"
|
||||
android:updatePeriodMillis="1800000"
|
||||
android:configure="com.donetick.app.widget.WidgetConfigActivity"
|
||||
android:widgetFeatures="reconfigurable|configuration_optional"
|
||||
android:widgetCategory="home_screen" />
|
||||
17
android/app/src/main/res/xml/widget_week_info.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:description="@string/widget_week_description"
|
||||
android:initialLayout="@layout/widget_shell"
|
||||
android:previewLayout="@layout/widget_preview_week"
|
||||
android:previewImage="@drawable/widget_preview_week"
|
||||
android:minWidth="250dp"
|
||||
android:minHeight="180dp"
|
||||
android:minResizeWidth="180dp"
|
||||
android:minResizeHeight="110dp"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
android:targetCellWidth="4"
|
||||
android:targetCellHeight="3"
|
||||
android:updatePeriodMillis="1800000"
|
||||
android:configure="com.donetick.app.widget.WidgetConfigActivity"
|
||||
android:widgetFeatures="reconfigurable|configuration_optional"
|
||||
android:widgetCategory="home_screen" />
|
||||
@@ -7,8 +7,8 @@ buildscript {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:8.2.1'
|
||||
classpath 'com.google.gms:google-services:4.4.0'
|
||||
classpath 'com.android.tools.build:gradle:8.10.1'
|
||||
classpath 'com.google.gms:google-services:4.4.2'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
@@ -22,6 +22,12 @@ allprojects {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
configurations.configureEach {
|
||||
// The app does not use Advertising ID. Exclude RevenueCat's transitive
|
||||
// ads identifier dependency so Play Console does not require an AD_ID declaration.
|
||||
exclude group: 'com.google.android.gms', module: 'play-services-ads-identifier'
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
|
||||
@@ -2,15 +2,33 @@
|
||||
include ':capacitor-android'
|
||||
project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor')
|
||||
|
||||
include ':capacitor-community-speech-recognition'
|
||||
project(':capacitor-community-speech-recognition').projectDir = new File('../node_modules/@capacitor-community/speech-recognition/android')
|
||||
|
||||
include ':capacitor-community-sqlite'
|
||||
project(':capacitor-community-sqlite').projectDir = new File('../node_modules/@capacitor-community/sqlite/android')
|
||||
|
||||
include ':capacitor-app'
|
||||
project(':capacitor-app').projectDir = new File('../node_modules/@capacitor/app/android')
|
||||
|
||||
include ':capacitor-browser'
|
||||
project(':capacitor-browser').projectDir = new File('../node_modules/@capacitor/browser/android')
|
||||
|
||||
include ':capacitor-device'
|
||||
project(':capacitor-device').projectDir = new File('../node_modules/@capacitor/device/android')
|
||||
|
||||
include ':capacitor-haptics'
|
||||
project(':capacitor-haptics').projectDir = new File('../node_modules/@capacitor/haptics/android')
|
||||
|
||||
include ':capacitor-local-llm'
|
||||
project(':capacitor-local-llm').projectDir = new File('../node_modules/@capacitor/local-llm/android')
|
||||
|
||||
include ':capacitor-local-notifications'
|
||||
project(':capacitor-local-notifications').projectDir = new File('../node_modules/@capacitor/local-notifications/android')
|
||||
|
||||
include ':capacitor-network'
|
||||
project(':capacitor-network').projectDir = new File('../node_modules/@capacitor/network/android')
|
||||
|
||||
include ':capacitor-preferences'
|
||||
project(':capacitor-preferences').projectDir = new File('../node_modules/@capacitor/preferences/android')
|
||||
|
||||
@@ -20,8 +38,23 @@ project(':capacitor-push-notifications').projectDir = new File('../node_modules/
|
||||
include ':capacitor-status-bar'
|
||||
project(':capacitor-status-bar').projectDir = new File('../node_modules/@capacitor/status-bar/android')
|
||||
|
||||
include ':capgo-capacitor-document-scanner'
|
||||
project(':capgo-capacitor-document-scanner').projectDir = new File('../node_modules/@capgo/capacitor-document-scanner/android')
|
||||
|
||||
include ':capgo-capacitor-nfc'
|
||||
project(':capgo-capacitor-nfc').projectDir = new File('../node_modules/@capgo/capacitor-nfc/android')
|
||||
|
||||
include ':capgo-capacitor-social-login'
|
||||
project(':capgo-capacitor-social-login').projectDir = new File('../node_modules/@capgo/capacitor-social-login/android')
|
||||
|
||||
include ':jcesarmobile-capacitor-ocr'
|
||||
project(':jcesarmobile-capacitor-ocr').projectDir = new File('../node_modules/@jcesarmobile/capacitor-ocr/android')
|
||||
|
||||
include ':revenuecat-purchases-capacitor'
|
||||
project(':revenuecat-purchases-capacitor').projectDir = new File('../node_modules/@revenuecat/purchases-capacitor/android')
|
||||
|
||||
include ':revenuecat-purchases-capacitor-ui'
|
||||
project(':revenuecat-purchases-capacitor-ui').projectDir = new File('../node_modules/@revenuecat/purchases-capacitor-ui/android')
|
||||
|
||||
include ':capacitor-plugin-safe-area'
|
||||
project(':capacitor-plugin-safe-area').projectDir = new File('../node_modules/capacitor-plugin-safe-area/android')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
ext {
|
||||
minSdkVersion = 22
|
||||
compileSdkVersion = 34
|
||||
targetSdkVersion = 34
|
||||
androidxActivityVersion = '1.8.0'
|
||||
androidxAppCompatVersion = '1.6.1'
|
||||
androidxCoordinatorLayoutVersion = '1.2.0'
|
||||
androidxCoreVersion = '1.12.0'
|
||||
androidxFragmentVersion = '1.6.2'
|
||||
minSdkVersion = 28
|
||||
compileSdkVersion = 36
|
||||
targetSdkVersion = 36
|
||||
androidxActivityVersion = '1.11.0'
|
||||
androidxAppCompatVersion = '1.7.1'
|
||||
androidxCoordinatorLayoutVersion = '1.3.0'
|
||||
androidxCoreVersion = '1.17.0'
|
||||
androidxFragmentVersion = '1.8.9'
|
||||
coreSplashScreenVersion = '1.0.1'
|
||||
androidxWebkitVersion = '1.9.0'
|
||||
androidxWebkitVersion = '1.14.0'
|
||||
junitVersion = '4.13.2'
|
||||
androidxJunitVersion = '1.1.5'
|
||||
androidxEspressoCoreVersion = '3.5.1'
|
||||
androidxJunitVersion = '1.3.0'
|
||||
androidxEspressoCoreVersion = '3.7.0'
|
||||
cordovaAndroidVersion = '10.1.1'
|
||||
}
|
||||
firebaseMessagingVersion = '24.1.0'
|
||||
}
|
||||
|
||||
BIN
assets/ipad_dashbard_calendar.png
Normal file
|
After Width: | Height: | Size: 419 KiB |
84
bump-version.js
Executable file
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { execSync } from 'child_process'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import { fileURLToPath } from 'url'
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url)
|
||||
const __dirname = path.dirname(__filename)
|
||||
|
||||
// Read package.json
|
||||
const packageJsonPath = path.join(__dirname, 'package.json')
|
||||
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
|
||||
|
||||
// Get current version
|
||||
const currentVersion = packageJson.version
|
||||
console.log(`Current version: ${currentVersion}`)
|
||||
|
||||
// Parse version (assuming semver format: major.minor.patch)
|
||||
const versionParts = currentVersion.split('.').map(Number)
|
||||
const [major, minor, patch] = versionParts
|
||||
|
||||
// Bump patch version by default (can be modified to accept arguments for major/minor)
|
||||
const bumpType = process.argv[2] || 'patch'
|
||||
let newVersion
|
||||
|
||||
switch (bumpType) {
|
||||
case 'major':
|
||||
newVersion = `${major + 1}.0.0`
|
||||
break
|
||||
case 'minor':
|
||||
newVersion = `${major}.${minor + 1}.0`
|
||||
break
|
||||
case 'patch':
|
||||
default:
|
||||
newVersion = `${major}.${minor}.${patch + 1}`
|
||||
break
|
||||
}
|
||||
|
||||
console.log(`New version: ${newVersion}`)
|
||||
|
||||
// Update package.json
|
||||
packageJson.version = newVersion
|
||||
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n')
|
||||
console.log('✓ Updated package.json')
|
||||
|
||||
// Read Android build.gradle to get current versionCode
|
||||
const buildGradlePath = path.join(__dirname, 'android', 'app', 'build.gradle')
|
||||
let buildGradle = fs.readFileSync(buildGradlePath, 'utf8')
|
||||
|
||||
// Extract current versionCode
|
||||
const versionCodeMatch = buildGradle.match(/versionCode\s+(\d+)/)
|
||||
const currentVersionCode = versionCodeMatch ? parseInt(versionCodeMatch[1]) : 1
|
||||
const newVersionCode = currentVersionCode + 1
|
||||
|
||||
console.log(`Android versionCode: ${currentVersionCode} → ${newVersionCode}`)
|
||||
|
||||
// Use capacitor-set-version to update both iOS and Android
|
||||
try {
|
||||
console.log('\nUpdating iOS and Android versions...')
|
||||
|
||||
// Set version and build number for both platforms
|
||||
execSync(
|
||||
`npx capacitor-set-version set -v ${newVersion} -b ${newVersionCode}`,
|
||||
{
|
||||
stdio: 'inherit',
|
||||
},
|
||||
)
|
||||
|
||||
console.log('\n✓ Successfully bumped version to', newVersion)
|
||||
console.log(`✓ Build number: ${newVersionCode}`)
|
||||
console.log('\nNext steps:')
|
||||
console.log('1. Review the changes')
|
||||
console.log(
|
||||
'2. Commit: git add . && git commit -m "Bump version to ' +
|
||||
newVersion +
|
||||
'"',
|
||||
)
|
||||
console.log('3. Tag: git tag v' + newVersion)
|
||||
console.log('4. Push: git push origin develop --tags')
|
||||
} catch (error) {
|
||||
console.error('Error updating versions:', error.message)
|
||||
process.exit(1)
|
||||
}
|
||||
@@ -1,26 +1,44 @@
|
||||
import type { CapacitorConfig } from '@capacitor/cli';
|
||||
import type { CapacitorConfig } from '@capacitor/cli'
|
||||
|
||||
const config: CapacitorConfig = {
|
||||
appId: 'com.donetick.app',
|
||||
appName: 'Donetick',
|
||||
webDir: 'dist',
|
||||
|
||||
android: {
|
||||
allowMixedContent: true,
|
||||
},
|
||||
plugins: {
|
||||
PushNotifications: {
|
||||
presentationOptions: ['badge', 'sound', 'alert'],
|
||||
},
|
||||
LocalNotifications: {
|
||||
smallIcon: "ic_stat_icon_config_sample",
|
||||
iconColor: "#488AFF",
|
||||
sound: "beep.wav",
|
||||
smallIcon: 'ic_stat_icon_config_sample',
|
||||
iconColor: '#488AFF',
|
||||
sound: 'beep.wav',
|
||||
},
|
||||
GoogleAuth: {
|
||||
scopes: ['profile', 'email', 'openid'],
|
||||
clientId: process.env.VITE_APP_GOOGLE_CLIENT_ID,
|
||||
androidClientId: process.env.VITE_APP_ANDRIOD_CLIENT_ID,
|
||||
iosClientId: process.env.VITE_APP_IOS_CLIENT_ID,
|
||||
CapacitorSQLite: {
|
||||
// The offline cache opens databases with encrypted: false / no-encryption.
|
||||
// @capacitor-community/sqlite defaults native encryption to true when this
|
||||
// block is absent; on Android that can make plugin load fail with
|
||||
// "CapacitorSQLitePlugin: null" before JS gets a chance to open the DB.
|
||||
iosIsEncryption: false,
|
||||
androidIsEncryption: false,
|
||||
},
|
||||
SocialLogin: {
|
||||
providers: {
|
||||
google: true,
|
||||
facebook: false,
|
||||
apple: true,
|
||||
twitter: false,
|
||||
},
|
||||
},
|
||||
// GoogleAuth: {
|
||||
// scopes: ['profile', 'email', 'openid'],
|
||||
// clientId: process.env.VITE_APP_GOOGLE_CLIENT_ID,
|
||||
// androidClientId: process.env.VITE_APP_ANDRIOD_CLIENT_ID,
|
||||
// iosClientId: process.env.VITE_APP_IOS_CLIENT_ID,
|
||||
// },
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
||||
export default config
|
||||
|
||||
15
crowdin.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
# Crowdin configuration for Donetick
|
||||
# See: https://support.crowdin.com/configuration-file/
|
||||
|
||||
project_id: "donetick"
|
||||
api_token_env: CROWDIN_API_TOKEN
|
||||
preserve_hierarchy: true
|
||||
|
||||
languages_mapping:
|
||||
two_letters_code:
|
||||
zh-CN: zh-CN
|
||||
|
||||
files:
|
||||
- source: /public/locales/en/*.json
|
||||
translation: /public/locales/%two_letters_code%/%original_file_name%
|
||||
update_option: update_as_unapproved
|
||||
4
fastlane/Appfile
Normal file
@@ -0,0 +1,4 @@
|
||||
app_identifier("com.donetick.app")
|
||||
team_id("6UJJ78R3BS")
|
||||
|
||||
apple_id(ENV["APPLE_ID"]) if ENV["APPLE_ID"]
|
||||
114
fastlane/Fastfile
Normal file
@@ -0,0 +1,114 @@
|
||||
require "shellwords"
|
||||
|
||||
default_platform(:ios)
|
||||
|
||||
IOS_KEY_PATH = File.expand_path("../ios/AuthKey_84F695CDQ3.p8")
|
||||
IOS_OUTPUT_DIR = File.expand_path("../build/ios")
|
||||
ANDROID_PROJECT_DIR = File.expand_path("../android")
|
||||
PLAY_JSON_KEY_PATH = File.expand_path("../android/play-service-account.json")
|
||||
|
||||
platform :ios do
|
||||
desc "Build a signed, App Store-ready .ipa"
|
||||
lane :release do
|
||||
Dir.chdir(File.expand_path("../ios/App")) do
|
||||
Bundler.with_clean_env do
|
||||
sh("pod install --repo-update")
|
||||
end
|
||||
end
|
||||
|
||||
build_app(
|
||||
workspace: "ios/App/App.xcworkspace",
|
||||
scheme: "App",
|
||||
export_method: "app-store",
|
||||
output_directory: IOS_OUTPUT_DIR,
|
||||
output_name: "Donetick.ipa",
|
||||
export_options: {
|
||||
signingStyle: "manual",
|
||||
provisioningProfiles: {
|
||||
"com.donetick.app" => "Donetick App Store(fastline)",
|
||||
"com.donetick.app.widget" => "Donetick Widget App Store(fastline)",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
UI.success("Signed .ipa at #{IOS_OUTPUT_DIR}/Donetick.ipa")
|
||||
end
|
||||
|
||||
desc "Upload the built .ipa to TestFlight"
|
||||
lane :upload do
|
||||
UI.user_error!("Missing #{IOS_KEY_PATH} — run scripts/pull-secrets.sh first") unless File.exist?(IOS_KEY_PATH)
|
||||
UI.user_error!("ASC_ISSUER_ID is not set (App Store Connect API key issuer id)") if ENV["ASC_ISSUER_ID"].to_s.empty?
|
||||
|
||||
ipa_path = File.join(IOS_OUTPUT_DIR, "Donetick.ipa")
|
||||
UI.user_error!("Missing #{ipa_path} — run `fastlane ios release` first") unless File.exist?(ipa_path)
|
||||
|
||||
api_key = app_store_connect_api_key(
|
||||
key_id: ENV["ASC_KEY_ID"] || "84F695CDQ3",
|
||||
issuer_id: ENV["ASC_ISSUER_ID"],
|
||||
key_filepath: IOS_KEY_PATH,
|
||||
duration: 1200,
|
||||
in_house: false,
|
||||
)
|
||||
|
||||
upload_to_testflight(
|
||||
api_key: api_key,
|
||||
ipa: ipa_path,
|
||||
skip_waiting_for_build_processing: true,
|
||||
skip_submission: true,
|
||||
)
|
||||
|
||||
UI.success("Uploaded to TestFlight")
|
||||
end
|
||||
end
|
||||
|
||||
platform :android do
|
||||
desc "Build a signed release .aab"
|
||||
lane :release do
|
||||
keystore_properties = File.join(ANDROID_PROJECT_DIR, "keystore.properties")
|
||||
UI.user_error!("Missing #{keystore_properties} — run scripts/pull-secrets.sh first") unless File.exist?(keystore_properties)
|
||||
|
||||
gradle(
|
||||
task: "bundle",
|
||||
build_type: "Release",
|
||||
project_dir: "#{ANDROID_PROJECT_DIR}/",
|
||||
)
|
||||
|
||||
aab_path = lane_context[SharedValues::GRADLE_AAB_OUTPUT_PATH]
|
||||
UI.success("Signed .aab at #{aab_path}")
|
||||
end
|
||||
|
||||
desc "Build a signed release .apk (for sideloading/testing)"
|
||||
lane :apk do
|
||||
keystore_properties = File.join(ANDROID_PROJECT_DIR, "keystore.properties")
|
||||
UI.user_error!("Missing #{keystore_properties} — run scripts/pull-secrets.sh first") unless File.exist?(keystore_properties)
|
||||
|
||||
gradle(
|
||||
task: "assemble",
|
||||
build_type: "Release",
|
||||
project_dir: "#{ANDROID_PROJECT_DIR}/",
|
||||
)
|
||||
|
||||
apk_path = lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH]
|
||||
UI.success("Signed .apk at #{apk_path}")
|
||||
end
|
||||
|
||||
desc "Upload the built .aab to the Play Store (internal testing track by default)"
|
||||
lane :upload do |options|
|
||||
UI.user_error!("Missing #{PLAY_JSON_KEY_PATH} — run scripts/pull-secrets.sh first") unless File.exist?(PLAY_JSON_KEY_PATH)
|
||||
|
||||
aab_path = File.join(ANDROID_PROJECT_DIR, "app/build/outputs/bundle/release/app-release.aab")
|
||||
UI.user_error!("Missing #{aab_path} — run `fastlane android release` first") unless File.exist?(aab_path)
|
||||
|
||||
upload_to_play_store(
|
||||
json_key: PLAY_JSON_KEY_PATH,
|
||||
package_name: "com.donetick.app",
|
||||
aab: aab_path,
|
||||
track: options[:track] || "internal",
|
||||
skip_upload_metadata: true,
|
||||
skip_upload_images: true,
|
||||
skip_upload_screenshots: true,
|
||||
)
|
||||
|
||||
UI.success("Uploaded to Play Store (#{options[:track] || 'internal'} track)")
|
||||
end
|
||||
end
|
||||
69
fastlane/README.md
Normal file
@@ -0,0 +1,69 @@
|
||||
fastlane documentation
|
||||
----
|
||||
|
||||
# Installation
|
||||
|
||||
Make sure you have the latest version of the Xcode command line tools installed:
|
||||
|
||||
```sh
|
||||
xcode-select --install
|
||||
```
|
||||
|
||||
For _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane)
|
||||
|
||||
# Available Actions
|
||||
|
||||
## iOS
|
||||
|
||||
### ios release
|
||||
|
||||
```sh
|
||||
[bundle exec] fastlane ios release
|
||||
```
|
||||
|
||||
Build a signed, App Store-ready .ipa
|
||||
|
||||
### ios upload
|
||||
|
||||
```sh
|
||||
[bundle exec] fastlane ios upload
|
||||
```
|
||||
|
||||
Upload the built .ipa to TestFlight
|
||||
|
||||
----
|
||||
|
||||
|
||||
## Android
|
||||
|
||||
### android release
|
||||
|
||||
```sh
|
||||
[bundle exec] fastlane android release
|
||||
```
|
||||
|
||||
Build a signed release .aab
|
||||
|
||||
### android apk
|
||||
|
||||
```sh
|
||||
[bundle exec] fastlane android apk
|
||||
```
|
||||
|
||||
Build a signed release .apk (for sideloading/testing)
|
||||
|
||||
### android upload
|
||||
|
||||
```sh
|
||||
[bundle exec] fastlane android upload
|
||||
```
|
||||
|
||||
Upload the built .aab to the Play Store (internal testing track by default)
|
||||
|
||||
----
|
||||
|
||||
This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run.
|
||||
|
||||
More information about _fastlane_ can be found on [fastlane.tools](https://fastlane.tools).
|
||||
|
||||
The documentation of _fastlane_ can be found on [docs.fastlane.tools](https://docs.fastlane.tools).
|
||||
@@ -3,8 +3,13 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<!-- <link rel="icon" type="image/svg+xml" href="/logo.svg" /> -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<!-- <title>FE Template</title> -->
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, viewport-fit=cover"
|
||||
/>
|
||||
|
||||
<title>Donetick</title>
|
||||
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
|
||||
|
||||
@@ -14,8 +14,13 @@
|
||||
504EC30F1FED79650016851F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30E1FED79650016851F /* Assets.xcassets */; };
|
||||
504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC3101FED79650016851F /* LaunchScreen.storyboard */; };
|
||||
50B271D11FEDC1A000F3C39B /* public in Resources */ = {isa = PBXBuildFile; fileRef = 50B271D01FEDC1A000F3C39B /* public */; };
|
||||
72FA9293C4A649D1BA0E5917 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 71866EB277374608AD02C137 /* PrivacyInfo.xcprivacy */; };
|
||||
A084ECDBA7D38E1E42DFC39D /* Pods_App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */; };
|
||||
D1115B492C653D60004C6043 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = D1115B482C653D60004C6043 /* GoogleService-Info.plist */; };
|
||||
D0AC000000000000000000B1 /* WidgetBridgePlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0AC000000000000000000A1 /* WidgetBridgePlugin.swift */; };
|
||||
D0AC000000000000000000B2 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0AC000000000000000000A2 /* MainViewController.swift */; };
|
||||
D0AC000000000000000000B3 /* DonetickWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0AC000000000000000000A3 /* DonetickWidget.swift */; };
|
||||
D0AC000000000000000000B4 /* DonetickWidgetExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = D0AC000000000000000000A4 /* DonetickWidgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@@ -28,13 +33,44 @@
|
||||
504EC3111FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
504EC3131FED79650016851F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
50B271D01FEDC1A000F3C39B /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = "<group>"; };
|
||||
71866EB277374608AD02C137 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||
AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.release.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.release.xcconfig"; sourceTree = "<group>"; };
|
||||
D1115B482C653D60004C6043 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||
D1115B4A2C659D51004C6043 /* App.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = App.entitlements; sourceTree = "<group>"; };
|
||||
FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.debug.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
D0AC000000000000000000A1 /* WidgetBridgePlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WidgetBridgePlugin.swift; sourceTree = "<group>"; };
|
||||
D0AC000000000000000000A2 /* MainViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = "<group>"; };
|
||||
D0AC000000000000000000A3 /* DonetickWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DonetickWidget.swift; sourceTree = "<group>"; };
|
||||
D0AC000000000000000000A4 /* DonetickWidgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = DonetickWidgetExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D0AC000000000000000000A5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
D0AC000000000000000000A6 /* DonetickWidget.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DonetickWidget.entitlements; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
D0AC000000000000000000C2 /* Embed App Extensions */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 13;
|
||||
files = (
|
||||
D0AC000000000000000000B4 /* DonetickWidgetExtension.appex in Embed App Extensions */,
|
||||
);
|
||||
name = "Embed App Extensions";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
D0AC000000000000000000E2 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 504EC2FC1FED79650016851F /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D0AC000000000000000000D1;
|
||||
remoteInfo = DonetickWidgetExtension;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
504EC3011FED79650016851F /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
@@ -44,6 +80,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D0AC000000000000000000D3 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
@@ -59,16 +102,29 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
504EC3061FED79650016851F /* App */,
|
||||
D0AC000000000000000000C1 /* DonetickWidget */,
|
||||
504EC3051FED79650016851F /* Products */,
|
||||
7F8756D8B27F46E3366F6CEA /* Pods */,
|
||||
27E2DDA53C4D2A4D1A88CE4A /* Frameworks */,
|
||||
71866EB277374608AD02C137 /* PrivacyInfo.xcprivacy */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D0AC000000000000000000C1 /* DonetickWidget */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D0AC000000000000000000A3 /* DonetickWidget.swift */,
|
||||
D0AC000000000000000000A5 /* Info.plist */,
|
||||
D0AC000000000000000000A6 /* DonetickWidget.entitlements */,
|
||||
);
|
||||
path = DonetickWidget;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
504EC3051FED79650016851F /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
504EC3041FED79650016851F /* App.app */,
|
||||
D0AC000000000000000000A4 /* DonetickWidgetExtension.appex */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@@ -79,6 +135,8 @@
|
||||
D1115B4A2C659D51004C6043 /* App.entitlements */,
|
||||
50379B222058CBB4000EE86E /* capacitor.config.json */,
|
||||
504EC3071FED79650016851F /* AppDelegate.swift */,
|
||||
D0AC000000000000000000A2 /* MainViewController.swift */,
|
||||
D0AC000000000000000000A1 /* WidgetBridgePlugin.swift */,
|
||||
504EC30B1FED79650016851F /* Main.storyboard */,
|
||||
504EC30E1FED79650016851F /* Assets.xcassets */,
|
||||
504EC3101FED79650016851F /* LaunchScreen.storyboard */,
|
||||
@@ -111,30 +169,53 @@
|
||||
504EC3011FED79650016851F /* Frameworks */,
|
||||
504EC3021FED79650016851F /* Resources */,
|
||||
9592DBEFFC6D2A0C8D5DEB22 /* [CP] Embed Pods Frameworks */,
|
||||
D0AC000000000000000000C2 /* Embed App Extensions */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
D0AC000000000000000000E1 /* PBXTargetDependency */,
|
||||
);
|
||||
name = App;
|
||||
productName = App;
|
||||
productReference = 504EC3041FED79650016851F /* App.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
D0AC000000000000000000D1 /* DonetickWidgetExtension */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D0AC000000000000000000F1 /* Build configuration list for PBXNativeTarget "DonetickWidgetExtension" */;
|
||||
buildPhases = (
|
||||
D0AC000000000000000000D2 /* Sources */,
|
||||
D0AC000000000000000000D3 /* Frameworks */,
|
||||
D0AC000000000000000000D4 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = DonetickWidgetExtension;
|
||||
productName = DonetickWidgetExtension;
|
||||
productReference = D0AC000000000000000000A4 /* DonetickWidgetExtension.appex */;
|
||||
productType = "com.apple.product-type.app-extension";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
504EC2FC1FED79650016851F /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0920;
|
||||
LastUpgradeCheck = 0920;
|
||||
LastSwiftUpdateCheck = 920;
|
||||
LastUpgradeCheck = 920;
|
||||
TargetAttributes = {
|
||||
504EC3031FED79650016851F = {
|
||||
CreatedOnToolsVersion = 9.2;
|
||||
LastSwiftMigration = 1100;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
D0AC000000000000000000D1 = {
|
||||
CreatedOnToolsVersion = 15.0;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 504EC2FF1FED79650016851F /* Build configuration list for PBXProject "App" */;
|
||||
@@ -153,6 +234,7 @@
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
504EC3031FED79650016851F /* App */,
|
||||
D0AC000000000000000000D1 /* DonetickWidgetExtension */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@@ -169,6 +251,14 @@
|
||||
504EC30D1FED79650016851F /* Main.storyboard in Resources */,
|
||||
2FAD9763203C412B000D30F8 /* config.xml in Resources */,
|
||||
D1115B492C653D60004C6043 /* GoogleService-Info.plist in Resources */,
|
||||
72FA9293C4A649D1BA0E5917 /* PrivacyInfo.xcprivacy in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D0AC000000000000000000D4 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -216,11 +306,29 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
504EC3081FED79650016851F /* AppDelegate.swift in Sources */,
|
||||
D0AC000000000000000000B2 /* MainViewController.swift in Sources */,
|
||||
D0AC000000000000000000B1 /* WidgetBridgePlugin.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D0AC000000000000000000D2 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D0AC000000000000000000B3 /* DonetickWidget.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
D0AC000000000000000000E1 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D0AC000000000000000000D1 /* DonetickWidgetExtension */;
|
||||
targetProxy = D0AC000000000000000000E2 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
504EC30B1FED79650016851F /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
@@ -270,7 +378,6 @@
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
@@ -289,7 +396,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@@ -327,7 +434,6 @@
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
@@ -340,7 +446,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
@@ -353,18 +459,17 @@
|
||||
baseConfigurationReference = FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATION = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = App/App.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = 55;
|
||||
DEVELOPMENT_TEAM = 6UJJ78R3BS;
|
||||
INFOPLIST_FILE = App/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 1.0;
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
|
||||
MARKETING_VERSION = 1.2.34;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.donetick.app;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
@@ -375,14 +480,17 @@
|
||||
baseConfigurationReference = AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATION = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = App/App.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CODE_SIGN_IDENTITY = "Apple Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "Donetick App Store(fastline)";
|
||||
CURRENT_PROJECT_VERSION = 55;
|
||||
DEVELOPMENT_TEAM = 6UJJ78R3BS;
|
||||
INFOPLIST_FILE = App/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 1.0;
|
||||
MARKETING_VERSION = 1.2.34;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.donetick.app;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";
|
||||
@@ -391,6 +499,48 @@
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
D0AC000000000000000000F2 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = DonetickWidget/DonetickWidget.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 55;
|
||||
DEVELOPMENT_TEAM = 6UJJ78R3BS;
|
||||
INFOPLIST_FILE = DonetickWidget/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 1.2.34;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.donetick.app.widget;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
D0AC000000000000000000F3 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = DonetickWidget/DonetickWidget.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "Donetick Widget App Store(fastline)";
|
||||
CURRENT_PROJECT_VERSION = 55;
|
||||
DEVELOPMENT_TEAM = 6UJJ78R3BS;
|
||||
INFOPLIST_FILE = DonetickWidget/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 1.2.34;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.donetick.app.widget;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
@@ -412,6 +562,15 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
D0AC000000000000000000F1 /* Build configuration list for PBXNativeTarget "DonetickWidgetExtension" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
D0AC000000000000000000F2 /* Debug */,
|
||||
D0AC000000000000000000F3 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 504EC2FC1FED79650016851F /* Project object */;
|
||||
|
||||
@@ -4,5 +4,17 @@
|
||||
<dict>
|
||||
<key>aps-environment</key>
|
||||
<string>development</string>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>group.com.donetick.app</string>
|
||||
</array>
|
||||
<key>com.apple.developer.applesignin</key>
|
||||
<array>
|
||||
<string>Default</string>
|
||||
</array>
|
||||
<key>com.apple.developer.nfc.readersession.formats</key>
|
||||
<array>
|
||||
<string>TAG</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import UIKit
|
||||
import Capacitor
|
||||
|
||||
import FirebaseCore
|
||||
import FirebaseMessaging
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
@@ -8,6 +9,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
// Override point for customization after application launch.
|
||||
FirebaseApp.configure()
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -46,10 +48,17 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
return ApplicationDelegateProxy.shared.application(application, continue: userActivity, restorationHandler: restorationHandler)
|
||||
}
|
||||
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
|
||||
NotificationCenter.default.post(name: .capacitorDidRegisterForRemoteNotifications, object: deviceToken)
|
||||
Messaging.messaging().apnsToken = deviceToken
|
||||
Messaging.messaging().token(completion: { (token, error) in
|
||||
if let error = error {
|
||||
NotificationCenter.default.post(name: .capacitorDidFailToRegisterForRemoteNotifications, object: error)
|
||||
} else if let token = token {
|
||||
NotificationCenter.default.post(name: .capacitorDidRegisterForRemoteNotifications, object: token)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
|
||||
NotificationCenter.default.post(name: .capacitorDidFailToRegisterForRemoteNotifications, object: error)
|
||||
NotificationCenter.default.post(name: .capacitorDidFailToRegisterForRemoteNotifications, object: error)
|
||||
}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 53 KiB |
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"images" : [
|
||||
"images": [
|
||||
{
|
||||
"filename" : "AppIcon-512@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
"idiom": "universal",
|
||||
"size": "1024x1024",
|
||||
"filename": "AppIcon-512@2x.png",
|
||||
"platform": "ios"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
"info": {
|
||||
"author": "xcode",
|
||||
"version": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,56 @@
|
||||
{
|
||||
"images" : [
|
||||
"images": [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "splash-2732x2732-2.png",
|
||||
"scale" : "1x"
|
||||
"idiom": "universal",
|
||||
"filename": "Default@1x~universal~anyany.png",
|
||||
"scale": "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "splash-2732x2732-1.png",
|
||||
"scale" : "2x"
|
||||
"idiom": "universal",
|
||||
"filename": "Default@2x~universal~anyany.png",
|
||||
"scale": "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "splash-2732x2732.png",
|
||||
"scale" : "3x"
|
||||
"idiom": "universal",
|
||||
"filename": "Default@3x~universal~anyany.png",
|
||||
"scale": "3x"
|
||||
},
|
||||
{
|
||||
"appearances": [
|
||||
{
|
||||
"appearance": "luminosity",
|
||||
"value": "dark"
|
||||
}
|
||||
],
|
||||
"idiom": "universal",
|
||||
"scale": "1x",
|
||||
"filename": "Default@1x~universal~anyany-dark.png"
|
||||
},
|
||||
{
|
||||
"appearances": [
|
||||
{
|
||||
"appearance": "luminosity",
|
||||
"value": "dark"
|
||||
}
|
||||
],
|
||||
"idiom": "universal",
|
||||
"scale": "2x",
|
||||
"filename": "Default@2x~universal~anyany-dark.png"
|
||||
},
|
||||
{
|
||||
"appearances": [
|
||||
{
|
||||
"appearance": "luminosity",
|
||||
"value": "dark"
|
||||
}
|
||||
],
|
||||
"idiom": "universal",
|
||||
"scale": "3x",
|
||||
"filename": "Default@3x~universal~anyany-dark.png"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
"info": {
|
||||
"version": 1,
|
||||
"author": "xcode"
|
||||
}
|
||||
}
|
||||
BIN
ios/App/App/Assets.xcassets/Splash.imageset/Default@1x~universal~anyany-dark.png
vendored
Normal file
|
After Width: | Height: | Size: 169 KiB |
BIN
ios/App/App/Assets.xcassets/Splash.imageset/Default@1x~universal~anyany.png
vendored
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
ios/App/App/Assets.xcassets/Splash.imageset/Default@2x~universal~anyany-dark.png
vendored
Normal file
|
After Width: | Height: | Size: 169 KiB |
BIN
ios/App/App/Assets.xcassets/Splash.imageset/Default@2x~universal~anyany.png
vendored
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
ios/App/App/Assets.xcassets/Splash.imageset/Default@3x~universal~anyany-dark.png
vendored
Normal file
|
After Width: | Height: | Size: 169 KiB |
BIN
ios/App/App/Assets.xcassets/Splash.imageset/Default@3x~universal~anyany.png
vendored
Normal file
|
After Width: | Height: | Size: 52 KiB |
@@ -11,7 +11,7 @@
|
||||
<!--Bridge View Controller-->
|
||||
<scene sceneID="tne-QT-ifu">
|
||||
<objects>
|
||||
<viewController id="BYZ-38-t0r" customClass="CAPBridgeViewController" customModule="Capacitor" sceneMemberID="viewController"/>
|
||||
<viewController id="BYZ-38-t0r" customClass="MainViewController" customModule="App" customModuleProvider="target" sceneMemberID="viewController"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
</scene>
|
||||
|
||||
84
ios/App/App/Info.plist
Normal file
@@ -0,0 +1,84 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NFCReaderUsageDescription</key>
|
||||
<string>Donetick uses NFC to read and write chore tags for quick task completion.</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Donetick</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(MARKETING_VERSION)</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>This app needs access to camera to take photos to attach to task or use as profile photo</string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>This app needs access to photo library to select images to attach to task or use as profile photo</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>This app uses the microphone to let you create tasks by speaking</string>
|
||||
<key>NSSpeechRecognitionUsageDescription</key>
|
||||
<string>This app uses on-device speech recognition to turn your voice into tasks</string>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsLocalNetworking</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<true/>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>com.donetick.app</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>donetick</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>com.googleusercontent.apps.682262497914-5dacpk46qcc1494lood6ch8ul9c83kop</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
9
ios/App/App/MainViewController.swift
Normal file
@@ -0,0 +1,9 @@
|
||||
import Capacitor
|
||||
import UIKit
|
||||
|
||||
/// Registers app-local Capacitor plugins; referenced from Main.storyboard.
|
||||
class MainViewController: CAPBridgeViewController {
|
||||
override func capacitorDidLoad() {
|
||||
bridge?.registerPluginInstance(WidgetBridgePlugin())
|
||||
}
|
||||
}
|
||||
46
ios/App/App/WidgetBridgePlugin.swift
Normal file
@@ -0,0 +1,46 @@
|
||||
import Capacitor
|
||||
import Foundation
|
||||
import WidgetKit
|
||||
|
||||
/// JS bridge for the home-screen widgets (see src/service/WidgetService.js).
|
||||
/// Persists the task snapshot + API config in the shared App Group so the
|
||||
/// widget extension can read them, then asks WidgetKit to redraw.
|
||||
@objc(WidgetBridgePlugin)
|
||||
public class WidgetBridgePlugin: CAPPlugin, CAPBridgedPlugin {
|
||||
public let identifier = "WidgetBridgePlugin"
|
||||
public let jsName = "WidgetBridge"
|
||||
public let pluginMethods: [CAPPluginMethod] = [
|
||||
CAPPluginMethod(name: "update", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "clear", returnType: CAPPluginReturnPromise),
|
||||
]
|
||||
|
||||
static let appGroup = "group.com.donetick.app"
|
||||
static let dataKey = "widget_tasks"
|
||||
static let configKey = "widget_config"
|
||||
|
||||
@objc func update(_ call: CAPPluginCall) {
|
||||
guard let defaults = UserDefaults(suiteName: Self.appGroup) else {
|
||||
call.reject("App Group \(Self.appGroup) unavailable")
|
||||
return
|
||||
}
|
||||
if let data = call.getString("data") {
|
||||
defaults.set(data, forKey: Self.dataKey)
|
||||
}
|
||||
if let config = call.getString("config") {
|
||||
defaults.set(config, forKey: Self.configKey)
|
||||
}
|
||||
WidgetCenter.shared.reloadAllTimelines()
|
||||
call.resolve()
|
||||
}
|
||||
|
||||
@objc func clear(_ call: CAPPluginCall) {
|
||||
guard let defaults = UserDefaults(suiteName: Self.appGroup) else {
|
||||
call.reject("App Group \(Self.appGroup) unavailable")
|
||||
return
|
||||
}
|
||||
defaults.removeObject(forKey: Self.dataKey)
|
||||
defaults.removeObject(forKey: Self.configKey)
|
||||
WidgetCenter.shared.reloadAllTimelines()
|
||||
call.resolve()
|
||||
}
|
||||
}
|
||||
10
ios/App/DonetickWidget/DonetickWidget.entitlements
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>group.com.donetick.app</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
1107
ios/App/DonetickWidget/DonetickWidget.swift
Normal file
29
ios/App/DonetickWidget/Info.plist
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Donetick</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(MARKETING_VERSION)</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionPointIdentifier</key>
|
||||
<string>com.apple.widgetkit-extension</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,6 +1,6 @@
|
||||
require_relative '../../node_modules/@capacitor/ios/scripts/pods_helpers'
|
||||
|
||||
platform :ios, '13.0'
|
||||
platform :ios, '15.0'
|
||||
use_frameworks!
|
||||
|
||||
# workaround to avoid Xcode caching of Pods that requires
|
||||
@@ -11,19 +11,31 @@ install! 'cocoapods', :disable_input_output_paths => true
|
||||
def capacitor_pods
|
||||
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
|
||||
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
|
||||
pod 'CapacitorCommunitySpeechRecognition', :path => '../../node_modules/@capacitor-community/speech-recognition'
|
||||
pod 'CapacitorCommunitySqlite', :path => '../../node_modules/@capacitor-community/sqlite'
|
||||
pod 'CapacitorApp', :path => '../../node_modules/@capacitor/app'
|
||||
pod 'CapacitorBrowser', :path => '../../node_modules/@capacitor/browser'
|
||||
pod 'CapacitorDevice', :path => '../../node_modules/@capacitor/device'
|
||||
pod 'CapacitorHaptics', :path => '../../node_modules/@capacitor/haptics'
|
||||
pod 'CapacitorLocalLlm', :path => '../../node_modules/@capacitor/local-llm'
|
||||
pod 'CapacitorLocalNotifications', :path => '../../node_modules/@capacitor/local-notifications'
|
||||
pod 'CapacitorNetwork', :path => '../../node_modules/@capacitor/network'
|
||||
pod 'CapacitorPreferences', :path => '../../node_modules/@capacitor/preferences'
|
||||
pod 'CapacitorPushNotifications', :path => '../../node_modules/@capacitor/push-notifications'
|
||||
pod 'CapacitorStatusBar', :path => '../../node_modules/@capacitor/status-bar'
|
||||
pod 'CapgoCapacitorDocumentScanner', :path => '../../node_modules/@capgo/capacitor-document-scanner'
|
||||
pod 'CapgoCapacitorNfc', :path => '../../node_modules/@capgo/capacitor-nfc'
|
||||
pod 'CapgoCapacitorSocialLogin', :path => '../../node_modules/@capgo/capacitor-social-login'
|
||||
pod 'JcesarmobileCapacitorOcr', :path => '../../node_modules/@jcesarmobile/capacitor-ocr'
|
||||
pod 'RevenuecatPurchasesCapacitor', :path => '../../node_modules/@revenuecat/purchases-capacitor'
|
||||
pod 'RevenuecatPurchasesCapacitorUi', :path => '../../node_modules/@revenuecat/purchases-capacitor-ui'
|
||||
pod 'CapacitorPluginSafeArea', :path => '../../node_modules/capacitor-plugin-safe-area'
|
||||
end
|
||||
|
||||
target 'App' do
|
||||
capacitor_pods
|
||||
# Add your Pods here
|
||||
pod 'FirebaseMessaging' # Add this line
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
|
||||
@@ -1,105 +1,190 @@
|
||||
PODS:
|
||||
- Alamofire (5.10.2)
|
||||
- AppAuth (1.7.6):
|
||||
- AppAuth/Core (= 1.7.6)
|
||||
- AppAuth/ExternalUserAgent (= 1.7.6)
|
||||
- AppAuth/Core (1.7.6)
|
||||
- AppAuth/ExternalUserAgent (1.7.6):
|
||||
- AppAuth (2.1.0):
|
||||
- AppAuth/Core (= 2.1.0)
|
||||
- AppAuth/ExternalUserAgent (= 2.1.0)
|
||||
- AppAuth/Core (2.1.0)
|
||||
- AppAuth/ExternalUserAgent (2.1.0):
|
||||
- AppAuth/Core
|
||||
- AppCheckCore (11.2.0):
|
||||
- AppCheckCore (11.3.0):
|
||||
- GoogleUtilities/Environment (~> 8.0)
|
||||
- GoogleUtilities/UserDefaults (~> 8.0)
|
||||
- PromisesObjC (~> 2.4)
|
||||
- Capacitor (7.2.0):
|
||||
- PromisesSwift (~> 2.4)
|
||||
- RecaptchaInterop (~> 101.0)
|
||||
- Capacitor (8.4.1):
|
||||
- CapacitorCordova
|
||||
- CapacitorApp (7.0.1):
|
||||
- CapacitorApp (8.1.0):
|
||||
- Capacitor
|
||||
- CapacitorCommunitySqlite (7.0.0):
|
||||
- CapacitorBrowser (8.0.3):
|
||||
- Capacitor
|
||||
- CapacitorCommunitySpeechRecognition (7.0.1):
|
||||
- Capacitor
|
||||
- CapacitorCommunitySqlite (8.1.0):
|
||||
- Capacitor
|
||||
- SQLCipher
|
||||
- ZIPFoundation
|
||||
- CapacitorCordova (7.2.0)
|
||||
- CapacitorDevice (7.0.1):
|
||||
- CapacitorCordova (8.4.1)
|
||||
- CapacitorDevice (8.0.2):
|
||||
- Capacitor
|
||||
- CapacitorLocalNotifications (7.0.1):
|
||||
- CapacitorHaptics (8.0.2):
|
||||
- Capacitor
|
||||
- CapacitorNetwork (7.0.1):
|
||||
- CapacitorLocalLlm (1.0.0):
|
||||
- Capacitor
|
||||
- CapacitorPluginSafeArea (4.0.0):
|
||||
- CapacitorLocalNotifications (8.2.0):
|
||||
- Capacitor
|
||||
- CapacitorPreferences (7.0.1):
|
||||
- CapacitorNetwork (8.0.1):
|
||||
- Capacitor
|
||||
- CapacitorPushNotifications (7.0.1):
|
||||
- CapacitorPluginSafeArea (5.0.1):
|
||||
- Capacitor
|
||||
- CapacitorStatusBar (7.0.1):
|
||||
- CapacitorPreferences (8.0.1):
|
||||
- Capacitor
|
||||
- CapgoCapacitorSocialLogin (7.5.3):
|
||||
- CapacitorPushNotifications (8.1.1):
|
||||
- Capacitor
|
||||
- CapacitorStatusBar (8.0.2):
|
||||
- Capacitor
|
||||
- CapgoCapacitorDocumentScanner (8.4.0):
|
||||
- Capacitor
|
||||
- CapgoCapacitorNfc (8.2.2):
|
||||
- Capacitor
|
||||
- CapgoCapacitorSocialLogin (8.3.38):
|
||||
- Alamofire (~> 5.10.2)
|
||||
- Capacitor
|
||||
- FBSDKCoreKit (= 17.4.0)
|
||||
- FBSDKLoginKit (= 17.4.0)
|
||||
- GoogleSignIn (~> 8.0.0)
|
||||
- FBAEMKit (17.4.0):
|
||||
- FBSDKCoreKit_Basics (= 17.4.0)
|
||||
- FBSDKCoreKit (17.4.0):
|
||||
- FBAEMKit (= 17.4.0)
|
||||
- FBSDKCoreKit_Basics (= 17.4.0)
|
||||
- FBSDKCoreKit_Basics (17.4.0)
|
||||
- FBSDKLoginKit (17.4.0):
|
||||
- FBSDKCoreKit (= 17.4.0)
|
||||
- GoogleSignIn (8.0.0):
|
||||
- AppAuth (< 2.0, >= 1.7.3)
|
||||
- GoogleSignIn (~> 9.0.0)
|
||||
- FirebaseCore (12.15.0):
|
||||
- FirebaseCoreInternal (~> 12.15.0)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/Logger (~> 8.1)
|
||||
- FirebaseCoreInternal (12.15.0):
|
||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||
- FirebaseInstallations (12.15.0):
|
||||
- FirebaseCore (~> 12.15.0)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||
- PromisesObjC (~> 2.4)
|
||||
- FirebaseMessaging (12.15.0):
|
||||
- FirebaseCore (~> 12.15.0)
|
||||
- FirebaseInstallations (~> 12.15.0)
|
||||
- GoogleDataTransport (~> 10.1)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/Reachability (~> 8.1)
|
||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||
- nanopb (~> 3.30910.0)
|
||||
- GoogleDataTransport (10.1.0):
|
||||
- nanopb (~> 3.30910.0)
|
||||
- PromisesObjC (~> 2.4)
|
||||
- GoogleSignIn (9.0.0):
|
||||
- AppAuth (~> 2.0)
|
||||
- AppCheckCore (~> 11.0)
|
||||
- GTMAppAuth (< 5.0, >= 4.1.1)
|
||||
- GTMAppAuth (~> 5.0)
|
||||
- GTMSessionFetcher/Core (~> 3.3)
|
||||
- GoogleUtilities/Environment (8.0.2):
|
||||
- GoogleUtilities/AppDelegateSwizzler (8.1.2):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Network
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Logger (8.0.2):
|
||||
- GoogleUtilities/Environment (8.1.2):
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Logger (8.1.2):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Privacy (8.0.2)
|
||||
- GoogleUtilities/UserDefaults (8.0.2):
|
||||
- GoogleUtilities/Network (8.1.2):
|
||||
- GoogleUtilities/Logger
|
||||
- "GoogleUtilities/NSData+zlib"
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Reachability
|
||||
- "GoogleUtilities/NSData+zlib (8.1.2)":
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Privacy (8.1.2)
|
||||
- GoogleUtilities/Reachability (8.1.2):
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Privacy
|
||||
- GTMAppAuth (4.1.1):
|
||||
- AppAuth/Core (~> 1.7)
|
||||
- GoogleUtilities/UserDefaults (8.1.2):
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Privacy
|
||||
- GTMAppAuth (5.0.0):
|
||||
- AppAuth/Core (~> 2.0)
|
||||
- GTMSessionFetcher/Core (< 4.0, >= 3.3)
|
||||
- GTMSessionFetcher/Core (3.5.0)
|
||||
- PromisesObjC (2.4.0)
|
||||
- SQLCipher (4.7.0):
|
||||
- SQLCipher/standard (= 4.7.0)
|
||||
- SQLCipher/common (4.7.0)
|
||||
- SQLCipher/standard (4.7.0):
|
||||
- JcesarmobileCapacitorOcr (0.3.0):
|
||||
- Capacitor
|
||||
- nanopb (3.30910.0):
|
||||
- nanopb/decode (= 3.30910.0)
|
||||
- nanopb/encode (= 3.30910.0)
|
||||
- nanopb/decode (3.30910.0)
|
||||
- nanopb/encode (3.30910.0)
|
||||
- PromisesObjC (2.4.1)
|
||||
- PromisesSwift (2.4.1):
|
||||
- PromisesObjC (= 2.4.1)
|
||||
- PurchasesHybridCommon (17.55.1):
|
||||
- RevenueCat (= 5.67.1)
|
||||
- PurchasesHybridCommonUI (17.55.1):
|
||||
- PurchasesHybridCommon (= 17.55.1)
|
||||
- RevenueCatUI (= 5.67.1)
|
||||
- RecaptchaInterop (101.0.0)
|
||||
- RevenueCat (5.67.1)
|
||||
- RevenuecatPurchasesCapacitor (12.3.2):
|
||||
- Capacitor
|
||||
- PurchasesHybridCommon (= 17.55.1)
|
||||
- RevenuecatPurchasesCapacitorUi (12.3.2):
|
||||
- Capacitor
|
||||
- PurchasesHybridCommonUI (= 17.55.1)
|
||||
- RevenueCatUI (5.67.1):
|
||||
- RevenueCat (= 5.67.1)
|
||||
- SQLCipher (4.10.0):
|
||||
- SQLCipher/standard (= 4.10.0)
|
||||
- SQLCipher/common (4.10.0)
|
||||
- SQLCipher/standard (4.10.0):
|
||||
- SQLCipher/common
|
||||
- ZIPFoundation (0.9.19)
|
||||
- ZIPFoundation (0.9.20)
|
||||
|
||||
DEPENDENCIES:
|
||||
- "Capacitor (from `../../node_modules/@capacitor/ios`)"
|
||||
- "CapacitorApp (from `../../node_modules/@capacitor/app`)"
|
||||
- "CapacitorBrowser (from `../../node_modules/@capacitor/browser`)"
|
||||
- "CapacitorCommunitySpeechRecognition (from `../../node_modules/@capacitor-community/speech-recognition`)"
|
||||
- "CapacitorCommunitySqlite (from `../../node_modules/@capacitor-community/sqlite`)"
|
||||
- "CapacitorCordova (from `../../node_modules/@capacitor/ios`)"
|
||||
- "CapacitorDevice (from `../../node_modules/@capacitor/device`)"
|
||||
- "CapacitorHaptics (from `../../node_modules/@capacitor/haptics`)"
|
||||
- "CapacitorLocalLlm (from `../../node_modules/@capacitor/local-llm`)"
|
||||
- "CapacitorLocalNotifications (from `../../node_modules/@capacitor/local-notifications`)"
|
||||
- "CapacitorNetwork (from `../../node_modules/@capacitor/network`)"
|
||||
- CapacitorPluginSafeArea (from `../../node_modules/capacitor-plugin-safe-area`)
|
||||
- "CapacitorPreferences (from `../../node_modules/@capacitor/preferences`)"
|
||||
- "CapacitorPushNotifications (from `../../node_modules/@capacitor/push-notifications`)"
|
||||
- "CapacitorStatusBar (from `../../node_modules/@capacitor/status-bar`)"
|
||||
- "CapgoCapacitorDocumentScanner (from `../../node_modules/@capgo/capacitor-document-scanner`)"
|
||||
- "CapgoCapacitorNfc (from `../../node_modules/@capgo/capacitor-nfc`)"
|
||||
- "CapgoCapacitorSocialLogin (from `../../node_modules/@capgo/capacitor-social-login`)"
|
||||
- FirebaseMessaging
|
||||
- "JcesarmobileCapacitorOcr (from `../../node_modules/@jcesarmobile/capacitor-ocr`)"
|
||||
- "RevenuecatPurchasesCapacitor (from `../../node_modules/@revenuecat/purchases-capacitor`)"
|
||||
- "RevenuecatPurchasesCapacitorUi (from `../../node_modules/@revenuecat/purchases-capacitor-ui`)"
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- Alamofire
|
||||
- AppAuth
|
||||
- AppCheckCore
|
||||
- FBAEMKit
|
||||
- FBSDKCoreKit
|
||||
- FBSDKCoreKit_Basics
|
||||
- FBSDKLoginKit
|
||||
- FirebaseCore
|
||||
- FirebaseCoreInternal
|
||||
- FirebaseInstallations
|
||||
- FirebaseMessaging
|
||||
- GoogleDataTransport
|
||||
- GoogleSignIn
|
||||
- GoogleUtilities
|
||||
- GTMAppAuth
|
||||
- GTMSessionFetcher
|
||||
- nanopb
|
||||
- PromisesObjC
|
||||
- PromisesSwift
|
||||
- PurchasesHybridCommon
|
||||
- PurchasesHybridCommonUI
|
||||
- RecaptchaInterop
|
||||
- RevenueCat
|
||||
- RevenueCatUI
|
||||
- SQLCipher
|
||||
- ZIPFoundation
|
||||
|
||||
@@ -108,10 +193,20 @@ EXTERNAL SOURCES:
|
||||
:path: "../../node_modules/@capacitor/ios"
|
||||
CapacitorApp:
|
||||
:path: "../../node_modules/@capacitor/app"
|
||||
CapacitorBrowser:
|
||||
:path: "../../node_modules/@capacitor/browser"
|
||||
CapacitorCommunitySpeechRecognition:
|
||||
:path: "../../node_modules/@capacitor-community/speech-recognition"
|
||||
CapacitorCommunitySqlite:
|
||||
:path: "../../node_modules/@capacitor-community/sqlite"
|
||||
CapacitorCordova:
|
||||
:path: "../../node_modules/@capacitor/ios"
|
||||
CapacitorDevice:
|
||||
:path: "../../node_modules/@capacitor/device"
|
||||
CapacitorHaptics:
|
||||
:path: "../../node_modules/@capacitor/haptics"
|
||||
CapacitorLocalLlm:
|
||||
:path: "../../node_modules/@capacitor/local-llm"
|
||||
CapacitorLocalNotifications:
|
||||
:path: "../../node_modules/@capacitor/local-notifications"
|
||||
CapacitorNetwork:
|
||||
@@ -124,37 +219,64 @@ EXTERNAL SOURCES:
|
||||
:path: "../../node_modules/@capacitor/push-notifications"
|
||||
CapacitorStatusBar:
|
||||
:path: "../../node_modules/@capacitor/status-bar"
|
||||
CapgoCapacitorDocumentScanner:
|
||||
:path: "../../node_modules/@capgo/capacitor-document-scanner"
|
||||
CapgoCapacitorNfc:
|
||||
:path: "../../node_modules/@capgo/capacitor-nfc"
|
||||
CapgoCapacitorSocialLogin:
|
||||
:path: "../../node_modules/@capgo/capacitor-social-login"
|
||||
JcesarmobileCapacitorOcr:
|
||||
:path: "../../node_modules/@jcesarmobile/capacitor-ocr"
|
||||
RevenuecatPurchasesCapacitor:
|
||||
:path: "../../node_modules/@revenuecat/purchases-capacitor"
|
||||
RevenuecatPurchasesCapacitorUi:
|
||||
:path: "../../node_modules/@revenuecat/purchases-capacitor-ui"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Alamofire: 7193b3b92c74a07f85569e1a6c4f4237291e7496
|
||||
AppAuth: d4f13a8fe0baf391b2108511793e4b479691fb73
|
||||
AppCheckCore: cc8fd0a3a230ddd401f326489c99990b013f0c4f
|
||||
Capacitor: 03bc7cbdde6a629a8b910a9d7d78c3cc7ed09ea7
|
||||
CapacitorApp: febecbb9582cb353aed037e18ec765141f880fe9
|
||||
CapacitorCommunitySqlite: b11e556cf5d149f9e0b6fbbb47959a6cd718c3d0
|
||||
CapacitorCordova: 5967b9ba03915ef1d585469d6e31f31dc49be96f
|
||||
CapacitorDevice: c6f6d587dd310527f8a48bf09c4e7b4a4cf14329
|
||||
CapacitorLocalNotifications: c2212755b33d2513b8bb325096ce3a64d4039ae3
|
||||
CapacitorNetwork: 15cb4385f0913a8ceb5e9a4d7af1ec554bdb8de8
|
||||
CapacitorPluginSafeArea: 22031c3436269ca80fac90ec2c94bc7c1e59a81d
|
||||
CapacitorPreferences: 6c98117d4d7508034a4af9db64d6b26fc75d7b94
|
||||
CapacitorPushNotifications: 6a2794788c583dd89215f1805ca4bced1b13dbdf
|
||||
CapacitorStatusBar: 6e7af040d8fc4dd655999819625cae9c2d74c36f
|
||||
CapgoCapacitorSocialLogin: 0daa087f32775c656fbfba09b8eae7c089b85ce2
|
||||
FBAEMKit: 58cb5f302cdd715a56d4c1d0dfdd2e423ac1421a
|
||||
FBSDKCoreKit: 94d7461d0cecf441b1ba7c41acfff41daa8ccd41
|
||||
FBSDKCoreKit_Basics: 151b43db8b834d3f0e02f95d36a44ffd36265e45
|
||||
FBSDKLoginKit: 5c1cd53c91a2282b3a4fe6e6d3dcf2b8b0d33d55
|
||||
GoogleSignIn: ce8c89bb9b37fb624b92e7514cc67335d1e277e4
|
||||
GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
|
||||
GTMAppAuth: f69bd07d68cd3b766125f7e072c45d7340dea0de
|
||||
AppAuth: ef4da5a3fc2e10b90c09a0a94a9baeaedc0341d5
|
||||
AppCheckCore: 214137f5c378d1dec88a68425c467fe65aaff637
|
||||
Capacitor: 35242afe195b1e53c58ca1b827d1b444c5e6602b
|
||||
CapacitorApp: 449ffe26375e96f8aaaee625ac6e01e5c57c8650
|
||||
CapacitorBrowser: c987c73d09d8bd3b5ec13f06338b1e14d5d2be69
|
||||
CapacitorCommunitySpeechRecognition: 3e03566c44c2bb3b52391a33d4518b1adbdeb38f
|
||||
CapacitorCommunitySqlite: eac6acfb852f46e7988fc59604d7f900498d354e
|
||||
CapacitorCordova: eebe6bcf807b1b06f3f48237650f96bbcd0eef09
|
||||
CapacitorDevice: 14cba6f88d1c3074cbf825fea977c8c526453ff8
|
||||
CapacitorHaptics: 296f771ecd89c7a1bd92a7b6826a7d268e2e70f5
|
||||
CapacitorLocalLlm: a05516151a02923a9e7dae9949d3817e85e321f0
|
||||
CapacitorLocalNotifications: 2615aa008f608b95d3921a778ee1988abf1e6148
|
||||
CapacitorNetwork: 8812ce60d11fb63d8f2e4ba51a49b2e59892ebe2
|
||||
CapacitorPluginSafeArea: 874619c00586248f1694210e72038123d422c2d9
|
||||
CapacitorPreferences: cca2021f386efb75947c850334447d9ff22b14f1
|
||||
CapacitorPushNotifications: ec08d589c226a2c0db7c032ec1bf5b044ec85f8e
|
||||
CapacitorStatusBar: 01d5763b4ed720de5ce2edbc938de6a98f4c8f32
|
||||
CapgoCapacitorDocumentScanner: 7ad9e8ed9c054d551bfc948660d995b9545723d8
|
||||
CapgoCapacitorNfc: 8ea158143c441e1cf6d231a971e375511558d027
|
||||
CapgoCapacitorSocialLogin: 5de0c9295188cbd9116d13e4581494f3bbaa3414
|
||||
FirebaseCore: 2e86a4ea1684d4381707069e4a6d89ac808e901e
|
||||
FirebaseCoreInternal: 6ab6a02c94446c026d2cf35cf5383842ebaa4992
|
||||
FirebaseInstallations: eb29ccbf64eaedf86fd5b2ccc7fabde567660b52
|
||||
FirebaseMessaging: 40017d7bc8457ee295b0f41d480a80fdabc9994e
|
||||
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
||||
GoogleSignIn: c7f09cfbc85a1abf69187be091997c317cc33b77
|
||||
GoogleUtilities: 766ace00c6b10d8148408f329d10c4f051931850
|
||||
GTMAppAuth: 217a876b249c3c585a54fd6f73e6b58c4f5c4238
|
||||
GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6
|
||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||
SQLCipher: ba9d0076041ed767c5bd3d3f77098318d04a403c
|
||||
ZIPFoundation: b8c29ea7ae353b309bc810586181fd073cb3312c
|
||||
JcesarmobileCapacitorOcr: d3668e104d7ad8968a9d00fd4766e18fea0fe305
|
||||
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
||||
PromisesObjC: 752c3227f599e3467650e47ea36f433eeb10c273
|
||||
PromisesSwift: 217dea0fd5d2ad65222a109c48698add13cc1c5b
|
||||
PurchasesHybridCommon: ecd9d7c586287625f1225b8de5e24c1021502270
|
||||
PurchasesHybridCommonUI: 3056a3d261529f6adb8f74ecc3ab7f1cc0d3fab4
|
||||
RecaptchaInterop: 11e0b637842dfb48308d242afc3f448062325aba
|
||||
RevenueCat: 9357239a9f0978285e68983637b8a602e65c94f0
|
||||
RevenuecatPurchasesCapacitor: c299be01b1a5c1d5eb118c30eadc84160944ecf2
|
||||
RevenuecatPurchasesCapacitorUi: dc2ec0d97638ebe4ac0078452f5c212b1525ea1c
|
||||
RevenueCatUI: 6f9291da540f98baf405b5bdfc46b2d5547b704a
|
||||
SQLCipher: eb79c64049cb002b4e9fcb30edb7979bf4706dfc
|
||||
ZIPFoundation: dfd3d681c4053ff7e2f7350bc4e53b5dba3f5351
|
||||
|
||||
PODFILE CHECKSUM: 54ec5ec72c1c5e3e8d03bd96cc1ec0deaf577d9e
|
||||
PODFILE CHECKSUM: 1099083fe561f8852fcef1bfcff4051f45db9770
|
||||
|
||||
COCOAPODS: 1.15.2
|
||||
COCOAPODS: 1.16.2
|
||||
|
||||
29
ios/App/PrivacyInfo.xcprivacy
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSPrivacyTracking</key>
|
||||
<false/>
|
||||
<key>NSPrivacyAccessedAPITypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>85F4.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>CA92.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>NSPrivacyCollectedDataTypes</key>
|
||||
<array/>
|
||||
</dict>
|
||||
</plist>
|
||||
0
ios/Podfile
Normal file
207
ios/Pods/Pods.xcodeproj/project.pbxproj
generated
Normal file
@@ -0,0 +1,207 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
93BAFDF14BA360977052E7B9CCC18E94 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CF1408CF629C7361332E53B88F7BD30C = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9D940727FF8FB9C785EB98E56350EF41 /* Podfile */,
|
||||
D89477F20FB1DE18A04690586D7808C4 /* Frameworks */,
|
||||
93BAFDF14BA360977052E7B9CCC18E94 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D89477F20FB1DE18A04690586D7808C4 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
BFDFE7DC352907FC980B868725387E98 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 1600;
|
||||
LastUpgradeCheck = 1600;
|
||||
};
|
||||
buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
Base,
|
||||
en,
|
||||
);
|
||||
mainGroup = CF1408CF629C7361332E53B88F7BD30C;
|
||||
minimizedProjectReferenceProxies = 0;
|
||||
preferredProjectObjectVersion = 77;
|
||||
productRefGroup = 93BAFDF14BA360977052E7B9CCC18E94 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
2426522C419C0DE4525883EA7AABC025 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"POD_CONFIGURATION_RELEASE=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
STRIP_INSTALLED_PRODUCT = NO;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
SWIFT_VERSION = 5.0;
|
||||
SYMROOT = "${SRCROOT}/../build";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
8F9FEBB7130A3DF8746ED9AA46FE33FA /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"POD_CONFIGURATION_DEBUG=1",
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
STRIP_INSTALLED_PRODUCT = NO;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
SYMROOT = "${SRCROOT}/../build";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
8F9FEBB7130A3DF8746ED9AA46FE33FA /* Debug */,
|
||||
2426522C419C0DE4525883EA7AABC025 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = BFDFE7DC352907FC980B868725387E98 /* Project object */;
|
||||
}
|
||||
8280
package-lock.json
generated
84
package.json
@@ -1,8 +1,12 @@
|
||||
{
|
||||
"name": "donetick",
|
||||
"private": true,
|
||||
"version": "0.1.99",
|
||||
"version": "1.2.34",
|
||||
"type": "module",
|
||||
"engines": {
|
||||
"node": ">=20.0.0",
|
||||
"npm": ">=9.0.0"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,jsx,ts,tsx}": [
|
||||
"eslint --fix",
|
||||
@@ -13,64 +17,105 @@
|
||||
"start": "vite --host",
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"build-selfhosted": "vite build --mode selfhosted",
|
||||
"build-cf": "rm -rf package-lock.json && npm install && npm install --force @rollup/rollup-linux-x64-gnu@4.34.9 @swc/core-linux-x64-gnu && vite build",
|
||||
"build-selfhosted": "rm -rf package-lock.json && npm install && npm install --force @rollup/rollup-linux-x64-gnu@4.34.9 @swc/core-linux-x64-gnu && vite build --mode selfhosted",
|
||||
"build-win": "del package-lock.json && npm install && npm install --force @rollup/rollup-win32-x64-msvc @swc/core-win32-x64-msvc && vite build --mode selfhosted",
|
||||
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
|
||||
"preview": "vite preview",
|
||||
"setup-m1": "rm -rf node_modules package-lock.json && npm install && npm install --force @rollup/rollup-darwin-arm64 @swc/core-darwin-arm64",
|
||||
"setup-apple-silicon": "npm install --no-optional && npm install --force @rollup/rollup-darwin-arm64 @swc/core-darwin-arm64",
|
||||
"test-cloudflare-build": "rm -rf node_modules package-lock.json && npm install && npm install --force @rollup/rollup-linux-x64-gnu@4.34.9 @swc/core-linux-x64-gnu && vite build",
|
||||
"release": "npm version patch && npm run build && git push origin develop --tags",
|
||||
"merge": "git checkout main && git merge develop && git push origin main && git checkout develop",
|
||||
"ionic:build": "npm run build",
|
||||
"ionic:serve": "npm run start"
|
||||
"ionic:serve": "npm run start",
|
||||
"android": "npm run build && npx cap sync android",
|
||||
"android:dev": "npx cap run android --live-reload",
|
||||
"cap": "npm run build && npx cap sync",
|
||||
"bump": "node bump-version.js patch",
|
||||
"bump:minor": "node bump-version.js minor",
|
||||
"bump:major": "node bump-version.js major",
|
||||
"bump:patch": "node bump-version.js patch",
|
||||
"postinstall": "patch-package"
|
||||
},
|
||||
"dependencies": {
|
||||
"@capacitor-community/sqlite": "^6.0.2",
|
||||
"@capacitor/android": "^6.1.1",
|
||||
"@capacitor/app": "^6.0.0",
|
||||
"@capacitor/cli": "^6.1.1",
|
||||
"@capacitor/core": "^6.1.1",
|
||||
"@capacitor/device": "^6.0.2",
|
||||
"@capacitor/ios": "6.1.1",
|
||||
"@capacitor/local-notifications": "^6.0.0",
|
||||
"@capacitor/network": "^6.0.3",
|
||||
"@capacitor/preferences": "^6.0.1",
|
||||
"@capacitor/push-notifications": "^6.0.1",
|
||||
"@codetrix-studio/capacitor-google-auth": "^3.4.0-rc.4",
|
||||
"@capacitor-community/speech-recognition": "^7.0.1",
|
||||
"@capacitor-community/sqlite": "^8.0.0",
|
||||
"@capacitor/android": "^8.0.0",
|
||||
"@capacitor/app": "^8.0.0",
|
||||
"@capacitor/browser": "^8.0.0",
|
||||
"@capacitor/core": "^8.0.0",
|
||||
"@capacitor/device": "^8.0.0",
|
||||
"@capacitor/haptics": "^8.0.2",
|
||||
"@capacitor/ios": "^8.0.0",
|
||||
"@capacitor/local-llm": "^1.0.0",
|
||||
"@capacitor/local-notifications": "^8.0.0",
|
||||
"@capacitor/network": "^8.0.0",
|
||||
"@capacitor/preferences": "^8.0.0",
|
||||
"@capacitor/push-notifications": "^8.0.0",
|
||||
"@capacitor/status-bar": "^8.0.0",
|
||||
"@capgo/capacitor-document-scanner": "^8.4.0",
|
||||
"@capgo/capacitor-nfc": "^8.0.0",
|
||||
"@capgo/capacitor-social-login": "^8.3.38",
|
||||
"@dnd-kit/core": "^6.3.1",
|
||||
"@dnd-kit/sortable": "^10.0.0",
|
||||
"@dnd-kit/utilities": "^3.2.2",
|
||||
"@emotion/react": "^11.11.3",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@mui/icons-material": "^5.15.2",
|
||||
"@hello-pangea/dnd": "^18.0.1",
|
||||
"@jcesarmobile/capacitor-ocr": "^0.3.0",
|
||||
"@meauxt/react-swipeable-list": "^1.0.0",
|
||||
"@mui/icons-material": "^5.16.13",
|
||||
"@mui/joy": "^5.0.0-beta.20",
|
||||
"@mui/material": "^5.15.2",
|
||||
"@openreplay/tracker": "^14.0.4",
|
||||
"@revenuecat/purchases-capacitor": "^12.0.0",
|
||||
"@revenuecat/purchases-capacitor-ui": "^12.0.0",
|
||||
"@swc/core": "^1.12.5",
|
||||
"@tanstack/react-query": "^5.17.0",
|
||||
"aos": "^2.3.4",
|
||||
"browser-image-compression": "^2.0.2",
|
||||
"caniuse-lite": "^1.0.30001769",
|
||||
"capacitor-plugin-safe-area": "^5.0.0",
|
||||
"chrono-node": "^2.7.7",
|
||||
"dotenv": "^16.4.5",
|
||||
"esm": "^3.2.25",
|
||||
"farmhash": "^4.0.1",
|
||||
"event-source-polyfill": "^1.0.31",
|
||||
"fuse.js": "^7.0.0",
|
||||
"i18next": "^25.8.14",
|
||||
"i18next-browser-languagedetector": "^8.2.1",
|
||||
"i18next-http-backend": "^3.0.2",
|
||||
"js-cookie": "^3.0.5",
|
||||
"moment": "^2.30.1",
|
||||
"murmurhash": "^2.0.1",
|
||||
"prop-types": "^15.8.1",
|
||||
"qrcode": "^1.5.4",
|
||||
"quill": "^2.0.3",
|
||||
"quilljs-markdown": "^1.2.0",
|
||||
"react": "^18.2.0",
|
||||
"react-calendar": "^5.1.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-easy-crop": "^5.4.2",
|
||||
"react-i18next": "^16.5.6",
|
||||
"react-router-dom": "^6.21.1",
|
||||
"react-transition-group": "^4.4.5",
|
||||
"reactjs-social-login": "^2.6.3",
|
||||
"recharts": "^2.15.0",
|
||||
"reusify": "^1.0.4",
|
||||
"tesseract.js": "^7.0.0",
|
||||
"vite-plugin-pwa": "^0.20.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@capacitor/assets": "^3.0.5",
|
||||
"@capacitor/cli": "^8.0.0",
|
||||
"@tanstack/eslint-plugin-query": "^5.14.6",
|
||||
"@types/react": "^18.2.43",
|
||||
"@types/react-dom": "^18.2.17",
|
||||
"@vite-pwa/assets-generator": "^0.2.4",
|
||||
"@vitejs/plugin-react-swc": "^3.5.0",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"baseline-browser-mapping": "^2.9.19",
|
||||
"capacitor-set-version": "^2.2.0",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-prettier": "^5.1.2",
|
||||
@@ -82,10 +127,15 @@
|
||||
"eslint-plugin-sort-keys-fix": "^1.1.2",
|
||||
"eslint-plugin-tailwindcss": "^3.13.1",
|
||||
"husky": "^8.0.3",
|
||||
"patch-package": "^8.0.1",
|
||||
"postcss": "^8.4.32",
|
||||
"prettier": "^3.1.1",
|
||||
"prettier-plugin-tailwindcss": "^0.5.10",
|
||||
"tailwindcss": "^3.4.0",
|
||||
"typescript": "^5.8.0",
|
||||
"vite": "^5.2.13"
|
||||
},
|
||||
"allowScripts": {
|
||||
"tesseract.js@7.0.0": true
|
||||
}
|
||||
}
|
||||
|
||||
484
patches/@capacitor-community+speech-recognition+7.0.1.patch
Normal file
@@ -0,0 +1,484 @@
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/.transforms/3b668565d422d3defdbffac23d2ae7a9/results.bin b/node_modules/@capacitor-community/speech-recognition/android/build/.transforms/3b668565d422d3defdbffac23d2ae7a9/results.bin
|
||||
new file mode 100644
|
||||
index 0000000..7ed749e
|
||||
--- /dev/null
|
||||
+++ b/node_modules/@capacitor-community/speech-recognition/android/build/.transforms/3b668565d422d3defdbffac23d2ae7a9/results.bin
|
||||
@@ -0,0 +1 @@
|
||||
+o/bundleLibRuntimeToDirDebug
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/.transforms/3b668565d422d3defdbffac23d2ae7a9/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/getcapacitor/community/speechrecognition/Constants.dex b/node_modules/@capacitor-community/speech-recognition/android/build/.transforms/3b668565d422d3defdbffac23d2ae7a9/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/getcapacitor/community/speechrecognition/Constants.dex
|
||||
new file mode 100644
|
||||
index 0000000..720cd1e
|
||||
Binary files /dev/null and b/node_modules/@capacitor-community/speech-recognition/android/build/.transforms/3b668565d422d3defdbffac23d2ae7a9/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/getcapacitor/community/speechrecognition/Constants.dex differ
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/.transforms/3b668565d422d3defdbffac23d2ae7a9/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/getcapacitor/community/speechrecognition/Receiver.dex b/node_modules/@capacitor-community/speech-recognition/android/build/.transforms/3b668565d422d3defdbffac23d2ae7a9/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/getcapacitor/community/speechrecognition/Receiver.dex
|
||||
new file mode 100644
|
||||
index 0000000..5d21223
|
||||
Binary files /dev/null and b/node_modules/@capacitor-community/speech-recognition/android/build/.transforms/3b668565d422d3defdbffac23d2ae7a9/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/getcapacitor/community/speechrecognition/Receiver.dex differ
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/.transforms/3b668565d422d3defdbffac23d2ae7a9/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/getcapacitor/community/speechrecognition/SpeechRecognition$SpeechRecognitionListener.dex b/node_modules/@capacitor-community/speech-recognition/android/build/.transforms/3b668565d422d3defdbffac23d2ae7a9/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/getcapacitor/community/speechrecognition/SpeechRecognition$SpeechRecognitionListener.dex
|
||||
new file mode 100644
|
||||
index 0000000..668e631
|
||||
Binary files /dev/null and b/node_modules/@capacitor-community/speech-recognition/android/build/.transforms/3b668565d422d3defdbffac23d2ae7a9/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/getcapacitor/community/speechrecognition/SpeechRecognition$SpeechRecognitionListener.dex differ
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/.transforms/3b668565d422d3defdbffac23d2ae7a9/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/getcapacitor/community/speechrecognition/SpeechRecognition.dex b/node_modules/@capacitor-community/speech-recognition/android/build/.transforms/3b668565d422d3defdbffac23d2ae7a9/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/getcapacitor/community/speechrecognition/SpeechRecognition.dex
|
||||
new file mode 100644
|
||||
index 0000000..59b8c5b
|
||||
Binary files /dev/null and b/node_modules/@capacitor-community/speech-recognition/android/build/.transforms/3b668565d422d3defdbffac23d2ae7a9/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/getcapacitor/community/speechrecognition/SpeechRecognition.dex differ
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/.transforms/3b668565d422d3defdbffac23d2ae7a9/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin b/node_modules/@capacitor-community/speech-recognition/android/build/.transforms/3b668565d422d3defdbffac23d2ae7a9/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin
|
||||
new file mode 100644
|
||||
index 0000000..d60cb42
|
||||
Binary files /dev/null and b/node_modules/@capacitor-community/speech-recognition/android/build/.transforms/3b668565d422d3defdbffac23d2ae7a9/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin differ
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/.transforms/a9f31cd11f0b4f2759dee65fdc12b529/results.bin b/node_modules/@capacitor-community/speech-recognition/android/build/.transforms/a9f31cd11f0b4f2759dee65fdc12b529/results.bin
|
||||
new file mode 100644
|
||||
index 0000000..0d259dd
|
||||
--- /dev/null
|
||||
+++ b/node_modules/@capacitor-community/speech-recognition/android/build/.transforms/a9f31cd11f0b4f2759dee65fdc12b529/results.bin
|
||||
@@ -0,0 +1 @@
|
||||
+o/classes
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/.transforms/a9f31cd11f0b4f2759dee65fdc12b529/transformed/classes/classes_dex/classes.dex b/node_modules/@capacitor-community/speech-recognition/android/build/.transforms/a9f31cd11f0b4f2759dee65fdc12b529/transformed/classes/classes_dex/classes.dex
|
||||
new file mode 100644
|
||||
index 0000000..d4d71e5
|
||||
Binary files /dev/null and b/node_modules/@capacitor-community/speech-recognition/android/build/.transforms/a9f31cd11f0b4f2759dee65fdc12b529/transformed/classes/classes_dex/classes.dex differ
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml
|
||||
new file mode 100644
|
||||
index 0000000..b81ecea
|
||||
--- /dev/null
|
||||
+++ b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml
|
||||
@@ -0,0 +1,15 @@
|
||||
+<?xml version="1.0" encoding="utf-8"?>
|
||||
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
+ package="com.getcapacitor.community.speechrecognition.speechrecognition" >
|
||||
+
|
||||
+ <uses-sdk android:minSdkVersion="28" />
|
||||
+
|
||||
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
+
|
||||
+ <queries>
|
||||
+ <intent>
|
||||
+ <action android:name="android.speech.RecognitionService" />
|
||||
+ </intent>
|
||||
+ </queries>
|
||||
+
|
||||
+</manifest>
|
||||
\ No newline at end of file
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json
|
||||
new file mode 100644
|
||||
index 0000000..b3c0af9
|
||||
--- /dev/null
|
||||
+++ b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json
|
||||
@@ -0,0 +1,18 @@
|
||||
+{
|
||||
+ "version": 3,
|
||||
+ "artifactType": {
|
||||
+ "type": "AAPT_FRIENDLY_MERGED_MANIFESTS",
|
||||
+ "kind": "Directory"
|
||||
+ },
|
||||
+ "applicationId": "com.getcapacitor.community.speechrecognition.speechrecognition",
|
||||
+ "variantName": "debug",
|
||||
+ "elements": [
|
||||
+ {
|
||||
+ "type": "SINGLE",
|
||||
+ "filters": [],
|
||||
+ "attributes": [],
|
||||
+ "outputFile": "AndroidManifest.xml"
|
||||
+ }
|
||||
+ ],
|
||||
+ "elementType": "File"
|
||||
+}
|
||||
\ No newline at end of file
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties
|
||||
new file mode 100644
|
||||
index 0000000..1211b1e
|
||||
--- /dev/null
|
||||
+++ b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties
|
||||
@@ -0,0 +1,6 @@
|
||||
+aarFormatVersion=1.0
|
||||
+aarMetadataVersion=1.0
|
||||
+minCompileSdk=1
|
||||
+minCompileSdkExtension=0
|
||||
+minAndroidGradlePluginVersion=1.0.0
|
||||
+coreLibraryDesugaringEnabled=false
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json
|
||||
new file mode 100644
|
||||
index 0000000..9e26dfe
|
||||
--- /dev/null
|
||||
+++ b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json
|
||||
@@ -0,0 +1 @@
|
||||
+{}
|
||||
\ No newline at end of file
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar
|
||||
new file mode 100644
|
||||
index 0000000..ff6ad96
|
||||
Binary files /dev/null and b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar differ
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar
|
||||
new file mode 100644
|
||||
index 0000000..eb6f866
|
||||
Binary files /dev/null and b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar differ
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt
|
||||
new file mode 100644
|
||||
index 0000000..f7ac549
|
||||
--- /dev/null
|
||||
+++ b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt
|
||||
@@ -0,0 +1,3 @@
|
||||
+int id webview 0x0
|
||||
+int layout bridge_layout_main 0x0
|
||||
+int string my_string 0x0
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/layout_bridge_layout_main.xml.flat b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/layout_bridge_layout_main.xml.flat
|
||||
new file mode 100644
|
||||
index 0000000..183eadd
|
||||
Binary files /dev/null and b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/layout_bridge_layout_main.xml.flat differ
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties
|
||||
new file mode 100644
|
||||
index 0000000..4e5a864
|
||||
--- /dev/null
|
||||
+++ b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties
|
||||
@@ -0,0 +1,2 @@
|
||||
+#Mon Jul 20 15:42:26 EDT 2026
|
||||
+com.getcapacitor.community.speechrecognition.speechrecognition.capacitor-community-speech-recognition-main-6\:/layout/bridge_layout_main.xml=/Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/packaged_res/debug/packageDebugResources/layout/bridge_layout_main.xml
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/incremental/debug/packageDebugResources/merged.dir/values/values.xml b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/incremental/debug/packageDebugResources/merged.dir/values/values.xml
|
||||
new file mode 100644
|
||||
index 0000000..e95bf66
|
||||
--- /dev/null
|
||||
+++ b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/incremental/debug/packageDebugResources/merged.dir/values/values.xml
|
||||
@@ -0,0 +1,4 @@
|
||||
+<?xml version="1.0" encoding="utf-8"?>
|
||||
+<resources>
|
||||
+ <string name="my_string">Just a simple string</string>
|
||||
+</resources>
|
||||
\ No newline at end of file
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml
|
||||
new file mode 100644
|
||||
index 0000000..3058471
|
||||
--- /dev/null
|
||||
+++ b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml
|
||||
@@ -0,0 +1,2 @@
|
||||
+<?xml version="1.0" encoding="utf-8"?>
|
||||
+<merger version="3"><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="main$Generated" generated="true" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/res"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="main" generated-set="main$Generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/res"><file name="bridge_layout_main" path="/Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/res/layout/bridge_layout_main.xml" qualifiers="" type="layout"/><file path="/Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/res/values/colors.xml" qualifiers=""/><file path="/Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/res/values/styles.xml" qualifiers=""/><file path="/Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/res/values/strings.xml" qualifiers=""><string name="my_string">Just a simple string</string></file></source></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="debug$Generated" generated="true" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/debug/res"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="debug" generated-set="debug$Generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/debug/res"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="generated$Generated" generated="true" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/build/generated/res/resValues/debug"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="generated" generated-set="generated$Generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/build/generated/res/resValues/debug"/></dataSet><mergedItems/></merger>
|
||||
\ No newline at end of file
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/incremental/mergeDebugAssets/merger.xml b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/incremental/mergeDebugAssets/merger.xml
|
||||
new file mode 100644
|
||||
index 0000000..8c51637
|
||||
--- /dev/null
|
||||
+++ b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/incremental/mergeDebugAssets/merger.xml
|
||||
@@ -0,0 +1,2 @@
|
||||
+<?xml version="1.0" encoding="utf-8"?>
|
||||
+<merger version="3"><dataSet config="main" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/assets"/></dataSet><dataSet config="debug" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/debug/assets"/></dataSet><dataSet config="generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/shader_assets/debug/compileDebugShaders/out"/></dataSet></merger>
|
||||
\ No newline at end of file
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml
|
||||
new file mode 100644
|
||||
index 0000000..472210d
|
||||
--- /dev/null
|
||||
+++ b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml
|
||||
@@ -0,0 +1,2 @@
|
||||
+<?xml version="1.0" encoding="utf-8"?>
|
||||
+<merger version="3"><dataSet config="main" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/jniLibs"/></dataSet><dataSet config="debug" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/debug/jniLibs"/></dataSet></merger>
|
||||
\ No newline at end of file
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/incremental/mergeDebugShaders/merger.xml b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/incremental/mergeDebugShaders/merger.xml
|
||||
new file mode 100644
|
||||
index 0000000..6bebd8c
|
||||
--- /dev/null
|
||||
+++ b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/incremental/mergeDebugShaders/merger.xml
|
||||
@@ -0,0 +1,2 @@
|
||||
+<?xml version="1.0" encoding="utf-8"?>
|
||||
+<merger version="3"><dataSet config="main" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/shaders"/></dataSet><dataSet config="debug" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/debug/shaders"/></dataSet></merger>
|
||||
\ No newline at end of file
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/getcapacitor/community/speechrecognition/Constants.class b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/getcapacitor/community/speechrecognition/Constants.class
|
||||
new file mode 100644
|
||||
index 0000000..3094bd9
|
||||
Binary files /dev/null and b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/getcapacitor/community/speechrecognition/Constants.class differ
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/getcapacitor/community/speechrecognition/Receiver.class b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/getcapacitor/community/speechrecognition/Receiver.class
|
||||
new file mode 100644
|
||||
index 0000000..af9be6c
|
||||
Binary files /dev/null and b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/getcapacitor/community/speechrecognition/Receiver.class differ
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/getcapacitor/community/speechrecognition/SpeechRecognition$SpeechRecognitionListener.class b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/getcapacitor/community/speechrecognition/SpeechRecognition$SpeechRecognitionListener.class
|
||||
new file mode 100644
|
||||
index 0000000..a056329
|
||||
Binary files /dev/null and b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/getcapacitor/community/speechrecognition/SpeechRecognition$SpeechRecognitionListener.class differ
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/getcapacitor/community/speechrecognition/SpeechRecognition.class b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/getcapacitor/community/speechrecognition/SpeechRecognition.class
|
||||
new file mode 100644
|
||||
index 0000000..57a50fe
|
||||
Binary files /dev/null and b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/getcapacitor/community/speechrecognition/SpeechRecognition.class differ
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt
|
||||
new file mode 100644
|
||||
index 0000000..80ec5cb
|
||||
--- /dev/null
|
||||
+++ b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt
|
||||
@@ -0,0 +1,5 @@
|
||||
+R_DEF: Internal format may change without notice
|
||||
+local
|
||||
+id webview
|
||||
+layout bridge_layout_main
|
||||
+string my_string
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt
|
||||
new file mode 100644
|
||||
index 0000000..6010dd3
|
||||
--- /dev/null
|
||||
+++ b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt
|
||||
@@ -0,0 +1,21 @@
|
||||
+1<?xml version="1.0" encoding="utf-8"?>
|
||||
+2<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
+3 package="com.getcapacitor.community.speechrecognition.speechrecognition" >
|
||||
+4
|
||||
+5 <uses-sdk android:minSdkVersion="28" />
|
||||
+6
|
||||
+7 <uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
+7-->/Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/AndroidManifest.xml:4:5-71
|
||||
+7-->/Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/AndroidManifest.xml:4:22-68
|
||||
+8
|
||||
+9 <queries>
|
||||
+9-->/Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/AndroidManifest.xml:5:5-9:15
|
||||
+10 <intent>
|
||||
+10-->/Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/AndroidManifest.xml:6:7-8:16
|
||||
+11 <action android:name="android.speech.RecognitionService" />
|
||||
+11-->/Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/AndroidManifest.xml:7:9-68
|
||||
+11-->/Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/AndroidManifest.xml:7:17-65
|
||||
+12 </intent>
|
||||
+13 </queries>
|
||||
+14
|
||||
+15</manifest>
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml
|
||||
new file mode 100644
|
||||
index 0000000..b81ecea
|
||||
--- /dev/null
|
||||
+++ b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml
|
||||
@@ -0,0 +1,15 @@
|
||||
+<?xml version="1.0" encoding="utf-8"?>
|
||||
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
+ package="com.getcapacitor.community.speechrecognition.speechrecognition" >
|
||||
+
|
||||
+ <uses-sdk android:minSdkVersion="28" />
|
||||
+
|
||||
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
+
|
||||
+ <queries>
|
||||
+ <intent>
|
||||
+ <action android:name="android.speech.RecognitionService" />
|
||||
+ </intent>
|
||||
+ </queries>
|
||||
+
|
||||
+</manifest>
|
||||
\ No newline at end of file
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json
|
||||
new file mode 100644
|
||||
index 0000000..0637a08
|
||||
--- /dev/null
|
||||
+++ b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json
|
||||
@@ -0,0 +1 @@
|
||||
+[]
|
||||
\ No newline at end of file
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt
|
||||
new file mode 100644
|
||||
index 0000000..08f4ebe
|
||||
--- /dev/null
|
||||
+++ b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt
|
||||
@@ -0,0 +1 @@
|
||||
+0 Warning/Error
|
||||
\ No newline at end of file
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/packaged_res/debug/packageDebugResources/layout/bridge_layout_main.xml b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/packaged_res/debug/packageDebugResources/layout/bridge_layout_main.xml
|
||||
new file mode 100644
|
||||
index 0000000..56fec15
|
||||
--- /dev/null
|
||||
+++ b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/packaged_res/debug/packageDebugResources/layout/bridge_layout_main.xml
|
||||
@@ -0,0 +1,15 @@
|
||||
+<?xml version="1.0" encoding="utf-8"?>
|
||||
+<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
+ xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
+ xmlns:tools="http://schemas.android.com/tools"
|
||||
+ android:layout_width="match_parent"
|
||||
+ android:layout_height="match_parent"
|
||||
+ tools:context="com.getcapacitor.BridgeActivity"
|
||||
+ >
|
||||
+
|
||||
+ <WebView
|
||||
+ android:id="@+id/webview"
|
||||
+ android:layout_width="fill_parent"
|
||||
+ android:layout_height="fill_parent" />
|
||||
+
|
||||
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/packaged_res/debug/packageDebugResources/values/values.xml b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/packaged_res/debug/packageDebugResources/values/values.xml
|
||||
new file mode 100644
|
||||
index 0000000..e95bf66
|
||||
--- /dev/null
|
||||
+++ b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/packaged_res/debug/packageDebugResources/values/values.xml
|
||||
@@ -0,0 +1,4 @@
|
||||
+<?xml version="1.0" encoding="utf-8"?>
|
||||
+<resources>
|
||||
+ <string name="my_string">Just a simple string</string>
|
||||
+</resources>
|
||||
\ No newline at end of file
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/getcapacitor/community/speechrecognition/Constants.class b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/getcapacitor/community/speechrecognition/Constants.class
|
||||
new file mode 100644
|
||||
index 0000000..3094bd9
|
||||
Binary files /dev/null and b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/getcapacitor/community/speechrecognition/Constants.class differ
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/getcapacitor/community/speechrecognition/Receiver.class b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/getcapacitor/community/speechrecognition/Receiver.class
|
||||
new file mode 100644
|
||||
index 0000000..af9be6c
|
||||
Binary files /dev/null and b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/getcapacitor/community/speechrecognition/Receiver.class differ
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/getcapacitor/community/speechrecognition/SpeechRecognition$SpeechRecognitionListener.class b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/getcapacitor/community/speechrecognition/SpeechRecognition$SpeechRecognitionListener.class
|
||||
new file mode 100644
|
||||
index 0000000..a056329
|
||||
Binary files /dev/null and b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/getcapacitor/community/speechrecognition/SpeechRecognition$SpeechRecognitionListener.class differ
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/getcapacitor/community/speechrecognition/SpeechRecognition.class b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/getcapacitor/community/speechrecognition/SpeechRecognition.class
|
||||
new file mode 100644
|
||||
index 0000000..57a50fe
|
||||
Binary files /dev/null and b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/getcapacitor/community/speechrecognition/SpeechRecognition.class differ
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar
|
||||
new file mode 100644
|
||||
index 0000000..c701569
|
||||
Binary files /dev/null and b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar differ
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt
|
||||
new file mode 100644
|
||||
index 0000000..f0ee474
|
||||
--- /dev/null
|
||||
+++ b/node_modules/@capacitor-community/speech-recognition/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt
|
||||
@@ -0,0 +1,4 @@
|
||||
+com.getcapacitor.community.speechrecognition.speechrecognition
|
||||
+id webview
|
||||
+layout bridge_layout_main
|
||||
+string my_string
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/outputs/logs/manifest-merger-debug-report.txt b/node_modules/@capacitor-community/speech-recognition/android/build/outputs/logs/manifest-merger-debug-report.txt
|
||||
new file mode 100644
|
||||
index 0000000..102bc47
|
||||
--- /dev/null
|
||||
+++ b/node_modules/@capacitor-community/speech-recognition/android/build/outputs/logs/manifest-merger-debug-report.txt
|
||||
@@ -0,0 +1,28 @@
|
||||
+-- Merging decision tree log ---
|
||||
+manifest
|
||||
+ADDED from /Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/AndroidManifest.xml:2:3-10:14
|
||||
+INJECTED from /Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/AndroidManifest.xml:2:3-10:14
|
||||
+ package
|
||||
+ INJECTED from /Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/AndroidManifest.xml
|
||||
+ xmlns:android
|
||||
+ ADDED from /Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/AndroidManifest.xml:2:13-71
|
||||
+uses-permission#android.permission.RECORD_AUDIO
|
||||
+ADDED from /Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/AndroidManifest.xml:4:5-71
|
||||
+ android:name
|
||||
+ ADDED from /Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/AndroidManifest.xml:4:22-68
|
||||
+queries
|
||||
+ADDED from /Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/AndroidManifest.xml:5:5-9:15
|
||||
+intent#action:name:android.speech.RecognitionService
|
||||
+ADDED from /Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/AndroidManifest.xml:6:7-8:16
|
||||
+action#android.speech.RecognitionService
|
||||
+ADDED from /Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/AndroidManifest.xml:7:9-68
|
||||
+ android:name
|
||||
+ ADDED from /Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/AndroidManifest.xml:7:17-65
|
||||
+uses-sdk
|
||||
+INJECTED from /Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/AndroidManifest.xml reason: use-sdk injection requested
|
||||
+INJECTED from /Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/AndroidManifest.xml
|
||||
+INJECTED from /Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/AndroidManifest.xml
|
||||
+ android:targetSdkVersion
|
||||
+ INJECTED from /Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/AndroidManifest.xml
|
||||
+ android:minSdkVersion
|
||||
+ INJECTED from /Users/mohamad-macbook-air/workspace/temp/dt-frontend-worktrees/support-audio-input/node_modules/@capacitor-community/speech-recognition/android/src/main/AndroidManifest.xml
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/SpeechRecognition$SpeechRecognitionListener.class.uniqueId1 b/node_modules/@capacitor-community/speech-recognition/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/SpeechRecognition$SpeechRecognitionListener.class.uniqueId1
|
||||
new file mode 100644
|
||||
index 0000000..dac1e83
|
||||
Binary files /dev/null and b/node_modules/@capacitor-community/speech-recognition/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/SpeechRecognition$SpeechRecognitionListener.class.uniqueId1 differ
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/SpeechRecognition.class.uniqueId0 b/node_modules/@capacitor-community/speech-recognition/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/SpeechRecognition.class.uniqueId0
|
||||
new file mode 100644
|
||||
index 0000000..836f0ad
|
||||
Binary files /dev/null and b/node_modules/@capacitor-community/speech-recognition/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/SpeechRecognition.class.uniqueId0 differ
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin b/node_modules/@capacitor-community/speech-recognition/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin
|
||||
new file mode 100644
|
||||
index 0000000..c57ddd3
|
||||
Binary files /dev/null and b/node_modules/@capacitor-community/speech-recognition/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin differ
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/android/src/main/java/com/getcapacitor/community/speechrecognition/SpeechRecognition.java b/node_modules/@capacitor-community/speech-recognition/android/src/main/java/com/getcapacitor/community/speechrecognition/SpeechRecognition.java
|
||||
index a99ea69..5cabbd7 100644
|
||||
--- a/node_modules/@capacitor-community/speech-recognition/android/src/main/java/com/getcapacitor/community/speechrecognition/SpeechRecognition.java
|
||||
+++ b/node_modules/@capacitor-community/speech-recognition/android/src/main/java/com/getcapacitor/community/speechrecognition/SpeechRecognition.java
|
||||
@@ -81,13 +81,18 @@ public class SpeechRecognition extends Plugin implements Constants {
|
||||
String prompt = call.getString("prompt", null);
|
||||
boolean partialResults = call.getBoolean("partialResults", false);
|
||||
boolean popup = call.getBoolean("popup", false);
|
||||
- beginListening(language, maxResults, prompt, partialResults, popup, call);
|
||||
+ JSArray contextualStrings = call.getArray("contextualStrings", new JSArray());
|
||||
+ beginListening(language, maxResults, prompt, partialResults, popup, contextualStrings, call);
|
||||
}
|
||||
|
||||
@PluginMethod
|
||||
public void stop(final PluginCall call) {
|
||||
try {
|
||||
stopListening();
|
||||
+ // This never resolved the call on success, only rejected on
|
||||
+ // exception — any caller doing `await stop()` (e.g. a JS-side
|
||||
+ // restart loop) would hang forever waiting on this promise.
|
||||
+ call.resolve();
|
||||
} catch (Exception ex) {
|
||||
call.reject(ex.getLocalizedMessage());
|
||||
}
|
||||
@@ -157,6 +162,7 @@ public class SpeechRecognition extends Plugin implements Constants {
|
||||
String prompt,
|
||||
final boolean partialResults,
|
||||
boolean showPopup,
|
||||
+ JSArray contextualStrings,
|
||||
PluginCall call
|
||||
) {
|
||||
Logger.info(getLogTag(), "Beginning to listen for audible speech");
|
||||
@@ -168,6 +174,19 @@ public class SpeechRecognition extends Plugin implements Constants {
|
||||
intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, bridge.getActivity().getPackageName());
|
||||
intent.putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, partialResults);
|
||||
intent.putExtra("android.speech.extra.DICTATION_MODE", partialResults);
|
||||
+ intent.putExtra(RecognizerIntent.EXTRA_PREFER_OFFLINE, true);
|
||||
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && contextualStrings != null && contextualStrings.length() > 0) {
|
||||
+ ArrayList<String> biasingStrings = new ArrayList<>();
|
||||
+ for (int i = 0; i < contextualStrings.length(); i++) {
|
||||
+ String value = contextualStrings.optString(i, null);
|
||||
+ if (value != null && !value.trim().isEmpty()) {
|
||||
+ biasingStrings.add(value);
|
||||
+ }
|
||||
+ }
|
||||
+ if (!biasingStrings.isEmpty()) {
|
||||
+ intent.putStringArrayListExtra(RecognizerIntent.EXTRA_BIASING_STRINGS, biasingStrings);
|
||||
+ }
|
||||
+ }
|
||||
|
||||
if (prompt != null) {
|
||||
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, prompt);
|
||||
@@ -283,6 +302,25 @@ public class SpeechRecognition extends Plugin implements Constants {
|
||||
SpeechRecognition.this.stopListening();
|
||||
String errorMssg = getErrorText(error);
|
||||
|
||||
+ // Unlike onEndOfSpeech, this previously never told the JS side the
|
||||
+ // session ended — silence commonly ends a session via ERROR_SPEECH_TIMEOUT
|
||||
+ // / ERROR_NO_MATCH rather than onEndOfSpeech, so without this the caller's
|
||||
+ // restart loop never fires and listening state gets stuck forever.
|
||||
+ bridge
|
||||
+ .getWebView()
|
||||
+ .post(() -> {
|
||||
+ try {
|
||||
+ SpeechRecognition.this.lock.lock();
|
||||
+ SpeechRecognition.this.listening(false);
|
||||
+
|
||||
+ JSObject ret = new JSObject();
|
||||
+ ret.put("status", "stopped");
|
||||
+ SpeechRecognition.this.notifyListeners(LISTENING_EVENT, ret);
|
||||
+ } finally {
|
||||
+ SpeechRecognition.this.lock.unlock();
|
||||
+ }
|
||||
+ });
|
||||
+
|
||||
if (this.call != null) {
|
||||
call.reject(errorMssg);
|
||||
}
|
||||
diff --git a/node_modules/@capacitor-community/speech-recognition/ios/Plugin/Plugin.swift b/node_modules/@capacitor-community/speech-recognition/ios/Plugin/Plugin.swift
|
||||
index 5d1b35b..899c7a6 100644
|
||||
--- a/node_modules/@capacitor-community/speech-recognition/ios/Plugin/Plugin.swift
|
||||
+++ b/node_modules/@capacitor-community/speech-recognition/ios/Plugin/Plugin.swift
|
||||
@@ -54,6 +54,7 @@ public class SpeechRecognition: CAPPlugin {
|
||||
let language: String = call.getString("language") ?? "en-US"
|
||||
let maxResults: Int = call.getInt("maxResults") ?? self.defaultMatches
|
||||
let partialResults: Bool = call.getBool("partialResults") ?? false
|
||||
+ let contextualStrings: [String] = call.getArray("contextualStrings", String.self) ?? []
|
||||
|
||||
if self.recognitionTask != nil {
|
||||
self.recognitionTask?.cancel()
|
||||
@@ -79,6 +80,12 @@ public class SpeechRecognition: CAPPlugin {
|
||||
|
||||
self.recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
|
||||
self.recognitionRequest?.shouldReportPartialResults = partialResults
|
||||
+ if !contextualStrings.isEmpty {
|
||||
+ self.recognitionRequest?.contextualStrings = contextualStrings
|
||||
+ }
|
||||
+ if #available(iOS 13, *), self.speechRecognizer?.supportsOnDeviceRecognition == true {
|
||||
+ self.recognitionRequest?.requiresOnDeviceRecognition = true
|
||||
+ }
|
||||
|
||||
let inputNode: AVAudioInputNode = self.audioEngine!.inputNode
|
||||
let format: AVAudioFormat = inputNode.outputFormat(forBus: 0)
|
||||
75
public/locales/ar/chores.json
Normal file
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"title": "المهام",
|
||||
"myChores": "مهامي",
|
||||
"allChores": "جميع المهام",
|
||||
"addChore": "إضافة مهمة",
|
||||
"editChore": "تعديل مهمة",
|
||||
"deleteChore": "حذف مهمة",
|
||||
"completeChore": "إكمال مهمة",
|
||||
"dueDate": "تاريخ الاستحقاق",
|
||||
"assignedTo": "مُسند إلى",
|
||||
"priority": "الأولوية",
|
||||
"status": "الحالة",
|
||||
"description": "الوصف",
|
||||
"choreView": {
|
||||
"assignment": "التعيين",
|
||||
"assigned": "المعين",
|
||||
"last": "الأخير",
|
||||
"schedule": "الجدول",
|
||||
"due": "الاستحقاق",
|
||||
"statistics": "الإحصائيات",
|
||||
"completed": "مكتمل",
|
||||
"times": "مرات",
|
||||
"details": "التفاصيل",
|
||||
"createdBy": "أنشئ بواسطة",
|
||||
"na": "غير متوفر",
|
||||
"taskCompleted": "المهمة مكتملة",
|
||||
"taskCompletedMessage": "تم وضع علامة مكتملة على مهمتك",
|
||||
"taskCompletionUndone": "تم التراجع عن إكمال المهمة.",
|
||||
"taskSkipUndone": "تم التراجع عن تخطي المهمة.",
|
||||
"undoSuccessful": "التراجع ناجح",
|
||||
"undoFailed": "فشل التراجع",
|
||||
"undoFailedMessage": "تعذر التراجع عن الإجراء. يرجى المحاولة مرة أخرى.",
|
||||
"resetTimer": "إعادة تعيين المؤقت",
|
||||
"resetTimerConfirmation": "هل أنت متأكد من أنك تريد إعادة تعيين المؤقت؟ سيؤدي هذا إلى مسح جميع سجلات الوقت منذ بدء المهمة.",
|
||||
"clearAllTimeRecords": "مسح جميع سجلات الوقت",
|
||||
"clearAllTimeConfirmation": "سيؤدي هذا إلى حذف جميع المؤقتات لهذه المهمة بشكل دائم وإعادتها إلى حالة \"لم تبدأ\".",
|
||||
"descriptionTitle": "الوصف",
|
||||
"description": "الوصف :",
|
||||
"previousNote": "الملاحظة السابقة",
|
||||
"previousNoteLabel": "الملاحظة السابقة:",
|
||||
"subtasksLabel": "المهام الفرعية :",
|
||||
"taskActions": "إجراءات المهمة",
|
||||
"addNote": "أضف ملاحظة",
|
||||
"additionalNotes": "ملاحظات إضافية:",
|
||||
"notePlaceholder": "أضف ملاحظة حول الإكمال...",
|
||||
"setCustomCompletionTime": "تعيين وقت إكمال مخصص",
|
||||
"skipTask": "تخطي المهمة",
|
||||
"skipTaskConfirmation": "هل أنت متأكد من أنك تريد تخطي هذه المهمة؟",
|
||||
"markComplete": "وضع علامة مكتمل",
|
||||
"markAsDone": "وضع علامة كمنجز",
|
||||
"edit": "تعديل",
|
||||
"archive": "أرشفة",
|
||||
"unarchive": "إلغاء الأرشفة",
|
||||
"viewHistory": "عرض السجل",
|
||||
"history": "السجل",
|
||||
"startTimer": "بدء المؤقت",
|
||||
"start": "بدء",
|
||||
"pauseTimer": "إيقاف المؤقت مؤقتاً",
|
||||
"approve": "موافقة",
|
||||
"reject": "رفض",
|
||||
"pendingApproval": "في انتظار الموافقة",
|
||||
"undo": "تراجع",
|
||||
"skip": "تخطي",
|
||||
"cancel": "إلغاء",
|
||||
"noPriority": "بدون أولوية",
|
||||
"subtasks": "المهام الفرعية",
|
||||
"noDescription": "لا يوجد وصف متاح",
|
||||
"timer": {
|
||||
"active": "المؤقت نشط",
|
||||
"paused": "المؤقت متوقف مؤقتاً",
|
||||
"reset": "إعادة تعيين المؤقت",
|
||||
"delete": "حذف الجلسة"
|
||||
}
|
||||
}
|
||||
}
|
||||
33
public/locales/ar/common.json
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"save": "حفظ",
|
||||
"cancel": "إلغاء",
|
||||
"delete": "حذف",
|
||||
"edit": "تعديل",
|
||||
"close": "إغلاق",
|
||||
"confirm": "تأكيد",
|
||||
"loading": "جارٍ التحميل...",
|
||||
"error": "خطأ",
|
||||
"success": "نجح",
|
||||
"warning": "تحذير",
|
||||
"refresh": "تحديث",
|
||||
"copy": "نسخ",
|
||||
"copied": "تم النسخ!",
|
||||
"settings": "الإعدادات",
|
||||
"yes": "نعم",
|
||||
"no": "لا",
|
||||
"back": "رجوع",
|
||||
"backToCalendar": "العودة إلى التقويم",
|
||||
"logout": "تسجيل الخروج",
|
||||
"version": "النسخة",
|
||||
"navigation": {
|
||||
"allTasks": "جميع المهام",
|
||||
"archived": "المؤرشفة",
|
||||
"things": "الأشياء",
|
||||
"labels": "التسميات",
|
||||
"projects": "المشاريع",
|
||||
"filters": "الفلاتر",
|
||||
"activities": "الأنشطة",
|
||||
"points": "النقاط",
|
||||
"settings": "الإعدادات"
|
||||
}
|
||||
}
|
||||
174
public/locales/ar/settings.json
Normal file
@@ -0,0 +1,174 @@
|
||||
{
|
||||
"title": "الإعدادات",
|
||||
"circleSettings": {
|
||||
"title": "إعدادات الدائرة",
|
||||
"description": "يتم ربط حسابك تلقائيًا بدائرة عند إنشاء واحدة أو الانضمام إليها. ادعُ الأصدقاء بسهولة من خلال مشاركة رمز الدائرة الفريد أو الرابط أدناه. ستتلقى إشعارًا أدناه عندما يطلب شخص ما الانضمام إلى دائرتك. إذا كنت ترغب في المغادرة، فما عليك سوى الضغط على زر 'مغادرة الدائرة'.",
|
||||
"circleCode": "رمز الدائرة",
|
||||
"copyCode": "نسخ الرمز",
|
||||
"copyLink": "نسخ الرابط",
|
||||
"codeCopied": "تم نسخ رمز الدائرة!",
|
||||
"linkCopied": "تم نسخ الرابط!",
|
||||
"joinCircle": "الانضمام إلى دائرة",
|
||||
"joinCirclePlaceholder": "أدخل رمز الدائرة",
|
||||
"join": "انضمام",
|
||||
"leave": "مغادرة الدائرة",
|
||||
"leaveConfirmTitle": "مغادرة الدائرة",
|
||||
"leaveConfirmMessage": "هل أنت متأكد من أنك تريد مغادرة هذه الدائرة؟",
|
||||
"circleMembers": "أعضاء الدائرة",
|
||||
"circleMemberRequests": "طلبات انضمام الأعضاء",
|
||||
"admin": "مشرف",
|
||||
"member": "عضو",
|
||||
"pending": "قيد الانتظار",
|
||||
"accept": "قبول",
|
||||
"reject": "رفض",
|
||||
"makeAdmin": "جعله مشرف",
|
||||
"makeMember": "جعله عضو",
|
||||
"remove": "إزالة",
|
||||
"webhookURL": "رابط Webhook",
|
||||
"webhookDescription": "أدخل رابط webhook لتلقي إشعارات أحداث الدائرة",
|
||||
"webhookPlaceholder": "https://your-webhook-url.com"
|
||||
},
|
||||
"accountSettings": {
|
||||
"title": "إعدادات الحساب",
|
||||
"subscription": "الاشتراك",
|
||||
"subscriptionStatus": "الخطة الحالية",
|
||||
"free": "مجاني",
|
||||
"plus": "بلس",
|
||||
"upgrade": "ترقية",
|
||||
"cancel": "إلغاء",
|
||||
"changePassword": "تغيير كلمة المرور",
|
||||
"password": "كلمة المرور",
|
||||
"dangerZone": "منطقة الخطر",
|
||||
"dangerZoneDescription": "بمجرد حذف حسابك، لا يمكن التراجع. يرجى التأكد.",
|
||||
"deleteAccount": "حذف الحساب"
|
||||
},
|
||||
"localization": {
|
||||
"title": "التوطين",
|
||||
"description": "تخصيص اللغة وتنسيق التاريخ والتفضيلات الإقليمية لحسابك.",
|
||||
"language": "اللغة",
|
||||
"languageDescription": "اختر لغتك المفضلة",
|
||||
"dateFormat": "تنسيق التاريخ",
|
||||
"dateFormatDescription": "اختر كيفية عرض التواريخ في التطبيق",
|
||||
"timeFormat": "تنسيق الوقت",
|
||||
"timeFormatDescription": "اختر تنسيق 12 أو 24 ساعة",
|
||||
"12hour": "12 ساعة (ص/م)",
|
||||
"24hour": "24 ساعة",
|
||||
"firstDayOfWeek": "أول يوم في الأسبوع",
|
||||
"firstDayOfWeekDescription": "اختر اليوم الذي يبدأ به أسبوعك",
|
||||
"sunday": "الأحد",
|
||||
"monday": "الاثنين",
|
||||
"saturday": "السبت",
|
||||
"formats": {
|
||||
"mdy": "MM/DD/YYYY (الولايات المتحدة)",
|
||||
"dmy": "DD/MM/YYYY (أوروبا)",
|
||||
"ymd": "YYYY-MM-DD (ISO)",
|
||||
"long": "تنسيق طويل (مثل 1 يناير 2024)",
|
||||
"short": "تنسيق قصير (مثل 1 يناير 2024)"
|
||||
}
|
||||
},
|
||||
"sidepanel": {
|
||||
"title": "تخصيص اللوحة الجانبية",
|
||||
"description": "قم بتخصيص تخطيط ورؤية البطاقات في اللوحة الجانبية. هذا القسم متاح فقط على أجهزة الشاشة الكبيرة مثل الأجهزة اللوحية وأجهزة سطح المكتب."
|
||||
},
|
||||
"theme": {
|
||||
"title": "تفضيلات المظهر",
|
||||
"description": "اختر كيف يبدو الموقع لك. حدد مظهرًا واحدًا أو قم بالمزامنة مع نظامك والتبديل تلقائيًا بين مظاهر النهار والليل.",
|
||||
"themeMode": "وضع المظهر",
|
||||
"light": "فاتح",
|
||||
"dark": "داكن",
|
||||
"system": "النظام"
|
||||
},
|
||||
"notifications": {
|
||||
"settingsSaved": "تم حفظ الإعدادات بنجاح",
|
||||
"settingsSaveFailed": "فشل حفظ الإعدادات",
|
||||
"invalidWebhook": "رابط webhook غير صالح"
|
||||
},
|
||||
"profile": {
|
||||
"title": "إعدادات الملف الشخصي",
|
||||
"description": "تحديث اسم العرض وصورة الملف الشخصي.",
|
||||
"photoUpdated": "تم تحديث الصورة",
|
||||
"photoUpdatedMessage": "تم تحديث صورة ملفك الشخصي بنجاح!",
|
||||
"uploadFailed": "فشل التحميل",
|
||||
"uploadFailedMessage": "فشل تحميل صورتك. يرجى المحاولة مرة أخرى.",
|
||||
"profileUpdated": "تم تحديث الملف الشخصي",
|
||||
"profileUpdatedMessage": "تم حفظ معلومات ملفك الشخصي بنجاح!",
|
||||
"updateFailed": "فشل التحديث",
|
||||
"updateFailedMessage": "تعذر تحديث ملفك الشخصي. يرجى التحقق من اتصالك والمحاولة مرة أخرى.",
|
||||
"changePhoto": "تغيير الصورة",
|
||||
"displayName": "اسم العرض",
|
||||
"displayNamePlaceholder": "أدخل اسم العرض الخاص بك",
|
||||
"timezone": "المنطقة الزمنية",
|
||||
"timezonePlaceholder": "اختر منطقتك الزمنية",
|
||||
"save": "حفظ",
|
||||
"cancel": "إلغاء"
|
||||
},
|
||||
"overview": {
|
||||
"title": "الإعدادات",
|
||||
"subtitle": "قم بتخصيص تجربتك وإدارة تفضيلات حسابك",
|
||||
"upgrade": {
|
||||
"title": "الترقية إلى بلس",
|
||||
"description": "افتح ميزات قوية لتعزيز إنتاجيتك",
|
||||
"button": "الترقية الآن",
|
||||
"features": {
|
||||
"richText": "أوصاف نصية منسقة",
|
||||
"notifications": "إشعارات المهام",
|
||||
"apiIntegrations": "تكاملات API",
|
||||
"advancedAutomation": "أتمتة متقدمة"
|
||||
}
|
||||
},
|
||||
"sections": {
|
||||
"profile": {
|
||||
"title": "إعدادات الملف الشخصي",
|
||||
"description": "تحديث معلومات ملفك الشخصي والصورة واسم العرض وتفضيلات المنطقة الزمنية."
|
||||
},
|
||||
"circle": {
|
||||
"title": "إعدادات الدائرة",
|
||||
"description": "إدارة دائرتك ودعوة الأعضاء والتعامل مع طلبات الانضمام."
|
||||
},
|
||||
"account": {
|
||||
"title": "إعدادات الحساب",
|
||||
"description": "إدارة اشتراكك وتغيير كلمة المرور وخيارات حذف الحساب."
|
||||
},
|
||||
"subaccounts": {
|
||||
"title": "الحسابات المُدارة",
|
||||
"description": "إنشاء وإدارة حسابات فرعية لتسجيل الدخول وإكمال المهام المعينة."
|
||||
},
|
||||
"notifications": {
|
||||
"title": "الإشعارات",
|
||||
"description": "تكوين الإشعارات الفورية وتنبيهات البريد الإلكتروني ووجهات الإشعارات للمهام."
|
||||
},
|
||||
"mfa": {
|
||||
"title": "المصادقة متعددة العوامل",
|
||||
"description": "إضافة طبقة إضافية من الأمان باستخدام MFA مع تطبيقات المصادقة."
|
||||
},
|
||||
"apitokens": {
|
||||
"title": "رموز API",
|
||||
"description": "إنشاء وإدارة رموز الوصول لتكاملات الطرف الثالث والوصول إلى API."
|
||||
},
|
||||
"storage": {
|
||||
"title": "إعدادات التخزين",
|
||||
"description": "نسخ احتياطي واستعادة بياناتك وإدارة التخزين المحلي وتفضيلات المزامنة."
|
||||
},
|
||||
"sidepanel": {
|
||||
"title": "تخصيص اللوحة الجانبية",
|
||||
"description": "قم بتخصيص تخطيط ورؤية البطاقات في واجهة اللوحة الجانبية."
|
||||
},
|
||||
"theme": {
|
||||
"title": "تفضيلات المظهر",
|
||||
"description": "اختر مظهرك المفضل وقم بتكوين إعدادات الوضع الداكن/الفاتح."
|
||||
},
|
||||
"localization": {
|
||||
"title": "التوطين",
|
||||
"description": "تخصيص اللغة وتنسيق التاريخ وتنسيق الوقت والتفضيلات الإقليمية."
|
||||
},
|
||||
"advanced": {
|
||||
"title": "الإعدادات المتقدمة",
|
||||
"description": "تكوين webhooks والتحديثات في الوقت الفعلي وميزات متقدمة أخرى لتعزيز الإنتاجية."
|
||||
},
|
||||
"developer": {
|
||||
"title": "إعدادات المطور",
|
||||
"description": "عرض المعلومات الفنية حول رموز المصادقة واتصالات SSE وبيانات التصحيح."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||