Compare commits
661 Commits
fix-editor
...
feature/im
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
59945411e8 | ||
|
|
0f2554b9b3 | ||
|
|
181739dcd2 | ||
|
|
ab8d283059 | ||
|
|
468f7c6a56 | ||
|
|
c36a76cfdc | ||
|
|
57834bc9f1 | ||
|
|
cad28f3436 | ||
|
|
cfb8b1ef0b | ||
|
|
b626577730 | ||
|
|
e8ed3e2d8b | ||
|
|
0ac3e4b67f | ||
|
|
6de0112600 | ||
|
|
4b8c35b6af | ||
|
|
c72ee27aa4 | ||
|
|
875436a1ad | ||
|
|
1ede80c33c | ||
|
|
e6de183f77 | ||
|
|
514302d20d | ||
|
|
14946e092d | ||
|
|
d9fafc7703 | ||
|
|
5e8ab57271 | ||
|
|
00c648341b | ||
|
|
4063c573ec | ||
|
|
72f908bc90 | ||
|
|
4eebe10f2e | ||
|
|
6c0d6127ba | ||
|
|
4c9381599f | ||
|
|
8650ed2ba5 | ||
|
|
600953baa7 | ||
|
|
8967280e54 | ||
|
|
57a2181e62 | ||
|
|
911cacd9e9 | ||
|
|
361be50e3f | ||
|
|
6a306ddda2 | ||
|
|
1d6045f5ac | ||
|
|
3d286f6899 | ||
|
|
859c35e387 | ||
|
|
8d16611124 | ||
|
|
36afdf182c | ||
|
|
ad448b567b | ||
|
|
e80f329f33 | ||
|
|
0c6ece1e5b | ||
|
|
5b2a72c8d6 | ||
|
|
fc3a788575 | ||
|
|
fd61dbfe32 | ||
|
|
1a11bea05e | ||
|
|
43e7c8c7f9 | ||
|
|
db90d4c443 | ||
|
|
f375c7d3e4 | ||
|
|
fc5aeeb221 | ||
|
|
31685d12bd | ||
|
|
5ffa11a7f6 | ||
|
|
08e8035fcb | ||
|
|
76b3c5ed7a | ||
|
|
29468916e3 | ||
|
|
dde5dcd8fb | ||
|
|
381184f8c4 | ||
|
|
5a78d9e517 | ||
|
|
9edf5402c9 | ||
|
|
74b49f24a8 | ||
|
|
dfcbf3045a | ||
|
|
345922e74a | ||
|
|
21475c0514 | ||
|
|
d498a7a2b9 | ||
|
|
e627c3326c | ||
|
|
ad35e83269 | ||
|
|
38f04ca70a | ||
|
|
eeeda75408 | ||
|
|
5aec94f8a9 | ||
|
|
ea274c5adf | ||
|
|
81408f7763 | ||
|
|
15dc333969 | ||
|
|
44a07c7cf6 | ||
|
|
114338ab80 | ||
|
|
64e0129107 | ||
|
|
749eea4979 | ||
|
|
7ba785aa32 | ||
|
|
b4ec3fbbf1 | ||
|
|
c0ff54afbb | ||
|
|
6807871bb0 | ||
|
|
6f07a3c03c | ||
|
|
539c270c18 | ||
|
|
a7b190116a | ||
|
|
ecba9f87be | ||
|
|
b11539d20f | ||
|
|
66469b1fd5 | ||
|
|
e098d65008 | ||
|
|
b837b9728e | ||
|
|
959f34c05c | ||
|
|
7465d4d149 | ||
|
|
670e2bbd6d | ||
|
|
7e4120e242 | ||
|
|
a76b26e64c | ||
|
|
84d91d70d1 | ||
|
|
cc2ba899e8 | ||
|
|
047efd5079 | ||
|
|
3ae297ca04 | ||
|
|
82c7bcd0db | ||
|
|
00e087023a | ||
|
|
c254f453ce | ||
|
|
fb903f48e7 | ||
|
|
248d2a87b3 | ||
|
|
268f5f012b | ||
|
|
ba0e8d5d3f | ||
|
|
925cc7a3bc | ||
|
|
e39e5a7bf0 | ||
|
|
57de6fd014 | ||
|
|
679f6644f7 | ||
|
|
b5e18fe350 | ||
|
|
9156c57b39 | ||
|
|
02bf88252c | ||
|
|
fe54930332 | ||
|
|
b7d72437de | ||
|
|
2250299608 | ||
|
|
1807109805 | ||
|
|
8b47626173 | ||
|
|
ee9474afb7 | ||
|
|
a9b4c5e256 | ||
|
|
d41f049cee | ||
|
|
0e43408bff | ||
|
|
1c0a8e00a6 | ||
|
|
c106db2422 | ||
|
|
23734558dd | ||
|
|
8ca8f54c33 | ||
|
|
cad349ca12 | ||
|
|
ac7fb315d6 | ||
|
|
d7302a2cf0 | ||
|
|
3254a1ff30 | ||
|
|
2cab3dd486 | ||
|
|
e2767f2f77 | ||
|
|
4382576bf9 | ||
|
|
e89f7e3819 | ||
|
|
bced2b7872 | ||
|
|
7c6596f826 | ||
|
|
1afad07b2d | ||
|
|
43ccb398c0 | ||
|
|
5fbeb152e5 | ||
|
|
d5e7fbabaa | ||
|
|
33ff702295 | ||
|
|
f3322cc8f1 | ||
|
|
4356d10028 | ||
|
|
371984a366 | ||
|
|
e25016354e | ||
|
|
8fe4bddb85 | ||
|
|
fc121ef396 | ||
|
|
73a1295e29 | ||
|
|
8abf57ae24 | ||
|
|
a0f14dc3ef | ||
|
|
ce8cba4f13 | ||
|
|
e726bd073b | ||
|
|
3ee5ea097b | ||
|
|
6272e8b805 | ||
|
|
ae5c323d3b | ||
|
|
afc3ede9b0 | ||
|
|
7671e0e297 | ||
|
|
005f2d8ef1 | ||
|
|
7b20acaa5a | ||
|
|
da938ec348 | ||
|
|
d32d438eeb | ||
|
|
e289caf561 | ||
|
|
e8cd0c0a52 | ||
|
|
62bdee7789 | ||
|
|
ccb9c492a8 | ||
|
|
4506e5e90a | ||
|
|
2cc772106b | ||
|
|
a82caf5da2 | ||
|
|
1cebcb7876 | ||
|
|
0247903772 | ||
|
|
1f5164660d | ||
|
|
3a835ad90d | ||
|
|
18c13ed8fe | ||
|
|
35345b9214 | ||
|
|
2c98b98765 | ||
|
|
ace224b03c | ||
|
|
23e9b07310 | ||
|
|
fdc5642b3c | ||
|
|
9c81432dfd | ||
|
|
1825796649 | ||
|
|
9c5940e872 | ||
|
|
ad77334e00 | ||
|
|
761b5b7793 | ||
|
|
eadf5260c4 | ||
|
|
bf62cd93b2 | ||
|
|
92c9f31e01 | ||
|
|
3404999bcb | ||
|
|
e9816ef3a2 | ||
|
|
f10b7c9b66 | ||
|
|
36cf1fb950 | ||
|
|
c1f4a4e3ab | ||
|
|
50a22ddf85 | ||
|
|
d3d74ff7df | ||
|
|
ed91e1e22f | ||
|
|
a765d22f4b | ||
|
|
aca0e40fd9 | ||
|
|
183613296b | ||
|
|
3d75791006 | ||
|
|
516c214174 | ||
|
|
541868e681 | ||
|
|
c18513a04d | ||
|
|
37220256fa | ||
|
|
e28a4b4e23 | ||
|
|
04d66576cb | ||
|
|
63ae8a4a86 | ||
|
|
6e0404fe8b | ||
|
|
db79ad3f47 | ||
|
|
46ac983770 | ||
|
|
03cc358e61 | ||
|
|
e457215248 | ||
|
|
bf393b8015 | ||
|
|
b8eee77646 | ||
|
|
4ef4f8798c | ||
|
|
99886fdc96 | ||
|
|
80ef5c890a | ||
|
|
c925ddd462 | ||
|
|
73d380d069 | ||
|
|
a67515118c | ||
|
|
ad46f82337 | ||
|
|
055a991fcb | ||
|
|
d23c8203a3 | ||
|
|
3b0ec278d4 | ||
|
|
55b4c77ad1 | ||
|
|
aa74541d6e | ||
|
|
5c5e6c7438 | ||
|
|
a1235b48ef | ||
|
|
e015b180a8 | ||
|
|
e3c37c470d | ||
|
|
855203bd0e | ||
|
|
6e4700121a | ||
|
|
a67b04db7b | ||
|
|
0f84d02abc | ||
|
|
85c2be9500 | ||
|
|
a5a05f501a | ||
|
|
9bb946d27e | ||
|
|
cdd089fcf3 | ||
|
|
49d4d2b6f9 | ||
|
|
8d1408997f | ||
|
|
d18a8742f1 | ||
|
|
d9d229b020 | ||
|
|
045527d502 | ||
|
|
3c29303ac8 | ||
|
|
98c6ee7904 | ||
|
|
a1dc396564 | ||
|
|
4767597fc1 | ||
|
|
1e05512c98 | ||
|
|
68908e0e87 | ||
|
|
1808b84b0b | ||
|
|
1a5595e3db | ||
|
|
a96250b937 | ||
|
|
19f4fbfcf7 | ||
|
|
35c8848b89 | ||
|
|
970f51595b | ||
|
|
b31d279e15 | ||
|
|
f708eacdc3 | ||
|
|
7827a35de9 | ||
|
|
5e0217bcb1 | ||
|
|
54debb035a | ||
|
|
3e42d3020d | ||
|
|
c7ab4c9ccf | ||
|
|
d684c3a8b2 | ||
|
|
3feee27ad6 | ||
|
|
4add55adf2 | ||
|
|
4ba90510ea | ||
|
|
4b693b301f | ||
|
|
a9fcd11e11 | ||
|
|
01ee348870 | ||
|
|
c0cec22e10 | ||
|
|
12b87cceeb | ||
|
|
b9cd40937d | ||
|
|
1efae55a85 | ||
|
|
932cf0c877 | ||
|
|
0ba6be4fe6 | ||
|
|
cdaa3184a9 | ||
|
|
03445bb45a | ||
|
|
9d649c9bce | ||
|
|
9a34e4884a | ||
|
|
df0b51f5ec | ||
|
|
2554e5d63a | ||
|
|
5479d800cf | ||
|
|
f729b8f908 | ||
|
|
af21da8f2e | ||
|
|
9d13e9f700 | ||
|
|
d9932a68d9 | ||
|
|
17a9d1851f | ||
|
|
17f68b5315 | ||
|
|
b1ce214571 | ||
|
|
cfeba093d9 | ||
|
|
69038d8edd | ||
|
|
934faf3b87 | ||
|
|
71272d51c9 | ||
|
|
b295e79677 | ||
|
|
74789675eb | ||
|
|
1234d289eb | ||
|
|
723c29bad6 | ||
|
|
343f1f320c | ||
|
|
50e70b90db | ||
|
|
a2fd5b266c | ||
|
|
ebf32f0603 | ||
|
|
4dae3a424c | ||
|
|
086aa53212 | ||
|
|
6d4b53b489 | ||
|
|
c09064d2d6 | ||
|
|
024be4ce89 | ||
|
|
513d6b3d72 | ||
|
|
513b4016b9 | ||
|
|
8de57a1b5d | ||
|
|
34aba64bde | ||
|
|
eedfe38b26 | ||
|
|
36406875fc | ||
|
|
854c2323e6 | ||
|
|
1c3694df9b | ||
|
|
305b62b1a2 | ||
|
|
5550a9f592 | ||
|
|
a97d917c7a | ||
|
|
a55e188ba8 | ||
|
|
f0a70ac4da | ||
|
|
4d675a87a6 | ||
|
|
38c0a5a034 | ||
|
|
607e901673 | ||
|
|
35b44c69b9 | ||
|
|
d920c73acb | ||
|
|
34f909e37f | ||
|
|
a33970250e | ||
|
|
297ca467d4 | ||
|
|
eeeb0908dd | ||
|
|
359a5ead1b | ||
|
|
92fe455fc3 | ||
|
|
31b2fe7e85 | ||
|
|
4b9f284ed9 | ||
|
|
85c812f271 | ||
|
|
4aa4167351 | ||
|
|
a8dfd91d12 | ||
|
|
d23321aa68 | ||
|
|
6c4ac1f2e7 | ||
|
|
35e8b4bad6 | ||
|
|
3285664e9f | ||
|
|
7839bc2b6d | ||
|
|
65f725dd00 | ||
|
|
b1f8b3d8f8 | ||
|
|
83b6cbd98e | ||
|
|
89737d9f90 | ||
|
|
3b0e873c31 | ||
|
|
4bcd82fd7a | ||
|
|
f5de8caa0d | ||
|
|
13b821e061 | ||
|
|
479f60518b | ||
|
|
a71ac363bb | ||
|
|
3b49a06d29 | ||
|
|
e443f3a8a3 | ||
|
|
6bb67318d8 | ||
|
|
0e79a5bfff | ||
|
|
20e7ff88b0 | ||
|
|
e36f57850f | ||
|
|
f76446440b | ||
|
|
873c3824e5 | ||
|
|
0db0b56be6 | ||
|
|
d3a7ec6b8c | ||
|
|
9d58dd9bab | ||
|
|
409f5f1706 | ||
|
|
1cd0c7b80a | ||
|
|
bd6a2b2c48 | ||
|
|
065a7fc683 | ||
|
|
adc55f719d | ||
|
|
4a266487b5 | ||
|
|
d7d5623cd6 | ||
|
|
5d21d3b621 | ||
|
|
e622a379fd | ||
|
|
34acf8488e | ||
|
|
6d45a324db | ||
|
|
c8ccd31fe0 | ||
|
|
6a2734acff | ||
|
|
e48aecc198 | ||
|
|
129dec46b3 | ||
|
|
cbb360b714 | ||
|
|
eb9b67c0ca | ||
|
|
c71c3d834c | ||
|
|
3ccfad63bf | ||
|
|
806ce833cf | ||
|
|
854a4d4f52 | ||
|
|
9d16428781 | ||
|
|
d3d4ab2f25 | ||
|
|
4575b0b516 | ||
|
|
62226a186a | ||
|
|
28e21acfc3 | ||
|
|
6d24a2e429 | ||
|
|
5a95ca5be8 | ||
|
|
1ad1b91cc6 | ||
|
|
a77a4f552d | ||
|
|
dade84ff7f | ||
|
|
da5a7c7137 | ||
|
|
e21d182cec | ||
|
|
189f46cb3d | ||
|
|
ee98d87b11 | ||
|
|
d3a1aa0b0d | ||
|
|
b0e304bcea | ||
|
|
e84afd37a8 | ||
|
|
64851302f4 | ||
|
|
dddbc671fb | ||
|
|
5ea0254849 | ||
|
|
7ec9380fc9 | ||
|
|
c9fb213fbb | ||
|
|
9a48f50a79 | ||
|
|
395dd8fb9e | ||
|
|
fcb88a9764 | ||
|
|
7d70cd2d3d | ||
|
|
e5fbc61c26 | ||
|
|
daf201cd6b | ||
|
|
6210dbc52a | ||
|
|
80f88f85ba | ||
|
|
027e343841 | ||
|
|
fc2f4ee57d | ||
|
|
0bd477ce9e | ||
|
|
145e778397 | ||
|
|
0287257905 | ||
|
|
4b916dff47 | ||
|
|
7d18656033 | ||
|
|
a935b677df | ||
|
|
40ca5a3b4c | ||
|
|
4f9cd8dbb7 | ||
|
|
0d08318185 | ||
|
|
961dd2ef30 | ||
|
|
f7a5dbc71c | ||
|
|
303ac1db56 | ||
|
|
a421df8f1b | ||
|
|
a8a9f56e02 | ||
|
|
236d17620d | ||
|
|
946b2a8555 | ||
|
|
6c868fb589 | ||
|
|
8bdd4b2638 | ||
|
|
d4deb90616 | ||
|
|
15744feb41 | ||
|
|
e75005df89 | ||
|
|
b1fac8f9ce | ||
|
|
4ef77c5924 | ||
|
|
9f1db293a0 | ||
|
|
03ac543ae0 | ||
|
|
cf929ba1ce | ||
|
|
f3928db1ab | ||
|
|
e92dbadd8e | ||
|
|
8eca2cb2b8 | ||
|
|
f0c5951eb0 | ||
|
|
c3d18e4177 | ||
|
|
847037b2f7 | ||
|
|
6227e50dec | ||
|
|
89b6030bc3 | ||
|
|
248f692c2b | ||
|
|
6bac78117f | ||
|
|
e3ce44878e | ||
|
|
5f99783683 | ||
|
|
3d4cc1c4d7 | ||
|
|
a2a05c5d8c | ||
|
|
c8eea0a0e4 | ||
|
|
8736a58a02 | ||
|
|
53c75ca6ef | ||
|
|
506fc227c3 | ||
|
|
4f40bdd262 | ||
|
|
7bcd1df35a | ||
|
|
1e4d63f84f | ||
|
|
7e7bb1b1b3 | ||
|
|
8e612db63f | ||
|
|
140468cf3d | ||
|
|
114466e3a6 | ||
|
|
6c90653937 | ||
|
|
aec4c510f1 | ||
|
|
8722157f33 | ||
|
|
15b2aa6445 | ||
|
|
7bddfa096f | ||
|
|
7048c7e8db | ||
|
|
508a259884 | ||
|
|
8c5c9d447f | ||
|
|
fd951c3aaa | ||
|
|
a026eb4a04 | ||
|
|
b02c43c99d | ||
|
|
c2be3a4f4d | ||
|
|
2b4155ad1d | ||
|
|
829a8a7ef8 | ||
|
|
77c3e41564 | ||
|
|
8e932b7ca0 | ||
|
|
6e5c3e83d8 | ||
|
|
a3db77285e | ||
|
|
0d864dfa10 | ||
|
|
ae3d900af6 | ||
|
|
992a1d5231 | ||
|
|
0a01ef6357 | ||
|
|
7c6e79d78d | ||
|
|
6084bb78a1 | ||
|
|
df987f6e94 | ||
|
|
a1e237a82a | ||
|
|
1e97e81fe7 | ||
|
|
3ecda367f8 | ||
|
|
afa4432521 | ||
|
|
b24bc4fda0 | ||
|
|
0cca379a97 | ||
|
|
ca9e701386 | ||
|
|
48d79acbd3 | ||
|
|
2dabc62df3 | ||
|
|
2ab7564622 | ||
|
|
0c0f19b23f | ||
|
|
1e5847e09e | ||
|
|
e6d0061ca0 | ||
|
|
35b56fe8d2 | ||
|
|
4cd7f604df | ||
|
|
e65c36eff7 | ||
|
|
2e39e96846 | ||
|
|
357019a807 | ||
|
|
bb014cbb36 | ||
|
|
5d0e7ea28b | ||
|
|
96903c512b | ||
|
|
b9acb8a213 | ||
|
|
48e625480c | ||
|
|
bc3dce6ecf | ||
|
|
0da883b40a | ||
|
|
56d230191f | ||
|
|
abdb9626d0 | ||
|
|
567eb789fc | ||
|
|
aa85b57e75 | ||
|
|
b5d9a83e1b | ||
|
|
ee2d0912fd | ||
|
|
22cb2f1829 | ||
|
|
c3f76fa7c9 | ||
|
|
6923801426 | ||
|
|
210b6ba10c | ||
|
|
b3bf5ff7a9 | ||
|
|
ab1ff2f0bb | ||
|
|
a813a5dd92 | ||
|
|
b85fc2d473 | ||
|
|
112b44802f | ||
|
|
c121d4a010 | ||
|
|
26c7f04317 | ||
|
|
1fe3e5102b | ||
|
|
e0d44e58e6 | ||
|
|
3103a7b97c | ||
|
|
ef802bfa5c | ||
|
|
a1c2f3f679 | ||
|
|
c7843effc6 | ||
|
|
1bd9ecca37 | ||
|
|
2f55f36802 | ||
|
|
af5b05df70 | ||
|
|
1b2479cad2 | ||
|
|
b92b4bff4c | ||
|
|
e8301907cd | ||
|
|
2c3b400b5d | ||
|
|
8350d24822 | ||
|
|
934f77d369 | ||
|
|
e8a9301434 | ||
|
|
58b51201d9 | ||
|
|
02bc3a9db4 | ||
|
|
b777546bc9 | ||
|
|
5b96b956e8 | ||
|
|
e90f2d7087 | ||
|
|
8c1e0d2414 | ||
|
|
007c9859dc | ||
|
|
c72cac1213 | ||
|
|
f8b6dd6d1a | ||
|
|
5e71df03af | ||
|
|
e3f74f7f6f | ||
|
|
5a759268b8 | ||
|
|
a9d98f73e4 | ||
|
|
65dcd6e035 | ||
|
|
921b802aa0 | ||
|
|
0b767de51b | ||
|
|
e9bd553116 | ||
|
|
d4fcf1687a | ||
|
|
996fb6d60f | ||
|
|
fd6d259d6c | ||
|
|
4f16d172f8 | ||
|
|
b94c3ac182 | ||
|
|
ea383c80f2 | ||
|
|
1b769f23cb | ||
|
|
d5feab78c8 | ||
|
|
043099d217 | ||
|
|
670a8a05d1 | ||
|
|
01ea478e46 | ||
|
|
ebd3ed06ab | ||
|
|
f34591228e | ||
|
|
7247ad4a05 | ||
|
|
e4fd25cb76 | ||
|
|
3c67928583 | ||
|
|
9aaa915caa | ||
|
|
43318b185b | ||
|
|
015666388f | ||
|
|
542f7687f5 | ||
|
|
5b744eae3c | ||
|
|
28cd11fdc7 | ||
|
|
29ccbd0942 | ||
|
|
30a127d2da | ||
|
|
0d7973a34c | ||
|
|
487edd7165 | ||
|
|
b3fe79b0a7 | ||
|
|
966047585c | ||
|
|
d57ca9b07c | ||
|
|
e76b7ee0a5 | ||
|
|
2b42315c53 | ||
|
|
947443b4c7 | ||
|
|
2547ab42e9 | ||
|
|
306aca0645 | ||
|
|
f2b2dc33e6 | ||
|
|
7a8f8dc565 | ||
|
|
0528115ad3 | ||
|
|
4a5ee49db6 | ||
|
|
3ca761013d | ||
|
|
bdeb123f18 | ||
|
|
3f5f84aac0 | ||
|
|
01d3bd7810 | ||
|
|
8e6d6e20d7 | ||
|
|
375185a9ea | ||
|
|
c2e9773486 | ||
|
|
5e0e7b17e2 | ||
|
|
aa90684616 | ||
|
|
fa47b4151f | ||
|
|
eca5db19a2 | ||
|
|
b053b0eab4 | ||
|
|
70da1045d7 | ||
|
|
b5fd2b0751 | ||
|
|
97f6f09882 | ||
|
|
0c773727ee | ||
|
|
952ce39f1c | ||
|
|
057c7f3f5d | ||
|
|
9439c52801 | ||
|
|
b1cebbe8f2 | ||
|
|
836a47fd96 | ||
|
|
136b2ed457 | ||
|
|
7f4006de95 | ||
|
|
dc96209ed9 | ||
|
|
9b0332d5e0 | ||
|
|
a1300fefd6 | ||
|
|
27032e853b | ||
|
|
22646e1398 | ||
|
|
6e5e7c92c9 | ||
|
|
3254109ea5 | ||
|
|
98ab2bfd8f | ||
|
|
6cbf22c163 | ||
|
|
1714c1abca | ||
|
|
1bf65c7a53 | ||
|
|
0075fde915 | ||
|
|
318c61f531 | ||
|
|
6dc502fd92 | ||
|
|
db7d7edcb5 | ||
|
|
278840bcfd | ||
|
|
f149ad7c71 | ||
|
|
ad29de8a04 | ||
|
|
0759098414 | ||
|
|
528751a3ce | ||
|
|
3dd5bd8c4a | ||
|
|
1ed84fe1b4 | ||
|
|
1dcf8daecb | ||
|
|
fc0ac1e02a | ||
|
|
a1efab6673 | ||
|
|
4a6445e241 | ||
|
|
3fadb6016c | ||
|
|
99f469ba38 | ||
|
|
d1753f449a | ||
|
|
fe19a6b0cc | ||
|
|
bb67472dee | ||
|
|
13213cf4cd | ||
|
|
b49a890849 | ||
|
|
3eb21afd42 | ||
|
|
b98021929f | ||
|
|
40ccad1181 | ||
|
|
e2db62d551 | ||
|
|
0229641917 |
19
.github/workflows/desktop.publish.yml
vendored
@@ -97,9 +97,6 @@ jobs:
|
||||
- name: Setup Node
|
||||
uses: ./.github/actions/setup-node-with-cache
|
||||
|
||||
- name: Install setuptools
|
||||
run: brew install python-setuptools
|
||||
|
||||
- name: Setup notarization
|
||||
run: |
|
||||
mkdir -p ~/private_keys/
|
||||
@@ -147,7 +144,7 @@ jobs:
|
||||
CSC_KEY_PASSWORD: ${{ secrets.mac_certs_password }}
|
||||
run: |
|
||||
npx nx run release --project @notesnook/desktop -- --variant=mas
|
||||
yarn electron-builder --mac mas --universal -p never
|
||||
npx electron-builder --mac mas --universal -p never
|
||||
working-directory: ./apps/desktop
|
||||
|
||||
- name: Build zip and dmg
|
||||
@@ -161,9 +158,9 @@ jobs:
|
||||
run: |
|
||||
npx nx run release --project @notesnook/desktop
|
||||
if [ ${{ inputs.publish-github }} == true ]; then
|
||||
yarn electron-builder --mac zip dmg --arm64 --x64 -p always
|
||||
npx electron-builder --mac zip dmg --arm64 --x64 -p always
|
||||
else
|
||||
yarn electron-builder --mac zip dmg --arm64 --x64 -p never
|
||||
npx electron-builder --mac zip dmg --arm64 --x64 -p never
|
||||
fi
|
||||
working-directory: ./apps/desktop
|
||||
|
||||
@@ -219,7 +216,7 @@ jobs:
|
||||
- name: Build snap
|
||||
if: inputs.publish-snap
|
||||
run: |
|
||||
yarn electron-builder --linux snap:x64 -p never
|
||||
npx electron-builder --linux snap:x64 -p never
|
||||
working-directory: ./apps/desktop
|
||||
|
||||
- name: Build AppImage
|
||||
@@ -227,9 +224,9 @@ jobs:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
if [ ${{ inputs.publish-github }} == true ]; then
|
||||
yarn electron-builder --linux AppImage:x64 AppImage:arm64 -p always
|
||||
npx electron-builder --linux AppImage:x64 AppImage:arm64 -p always
|
||||
else
|
||||
yarn electron-builder --linux AppImage:x64 AppImage:arm64 -p never
|
||||
npx electron-builder --linux AppImage:x64 AppImage:arm64 -p never
|
||||
fi
|
||||
working-directory: ./apps/desktop
|
||||
|
||||
@@ -254,8 +251,8 @@ jobs:
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
|
||||
- name: Install TrustedSigning
|
||||
run: Install-Module -Name TrustedSigning -RequiredVersion 0.3.15 -Force -Repository PSGallery
|
||||
- name: Install AzureCodeSigning
|
||||
run: Install-Module -Name AzureCodeSigning -RequiredVersion 0.3.0 -Force -Repository PSGallery
|
||||
shell: pwsh
|
||||
|
||||
- name: Setup Node
|
||||
|
||||
69
.github/workflows/web.beta.publish.yml
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
name: Publish @notesnook/web Beta
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- "!v3-beta"
|
||||
paths-ignore:
|
||||
- "apps/mobile/**"
|
||||
- "packages/editor-mobile/**"
|
||||
- "apps/desktop/**"
|
||||
- "apps/vericrypt/**"
|
||||
- "servers/**"
|
||||
- "packages/clipper/**"
|
||||
- "extensions/web-clipper/**"
|
||||
pull_request:
|
||||
types:
|
||||
- closed
|
||||
- ready_for_review
|
||||
- reopened
|
||||
- opened
|
||||
- synchronize
|
||||
branches:
|
||||
- master
|
||||
- "!v3-beta"
|
||||
paths-ignore:
|
||||
- "apps/mobile/**"
|
||||
- "packages/editor-mobile/**"
|
||||
- "apps/desktop/**"
|
||||
- "apps/vericrypt/**"
|
||||
- "servers/**"
|
||||
- "packages/clipper/**"
|
||||
- "extensions/web-clipper/**"
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Node
|
||||
uses: ./.github/actions/setup-node-with-cache
|
||||
|
||||
- name: Install packages
|
||||
run: |
|
||||
npm ci --ignore-scripts --prefer-offline --no-audit
|
||||
npm run bootstrap -- --scope=web
|
||||
|
||||
- name: Setup environment
|
||||
run: |
|
||||
echo "NX_CLOUD_ACCESS_TOKEN=${{ secrets.NX_CLOUD_ACCESS_TOKEN }}" >> $GITHUB_ENV
|
||||
echo "CLOUDFLARE_ACCOUNT_ID=${{ secrets.CLOUDFLARE_ACCOUNT_ID }}" >> $GITHUB_ENV
|
||||
echo "CLOUDFLARE_API_TOKEN=${{ secrets.CLOUDFLARE_API_TOKEN }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Generate beta build
|
||||
run: npm run build:beta:web
|
||||
|
||||
- name: Publish to Cloudflare Pages
|
||||
uses: unlike-ltd/github-actions-cloudflare-pages@v0.1.1
|
||||
id: pages
|
||||
with:
|
||||
cloudflare-api-token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
cloudflare-account-id: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
cloudflare-project-name: notesnook-beta-app
|
||||
directory: ./apps/web/build
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
github-environment: ${{ (github.ref == 'refs/heads/master' && 'beta') || 'preview' }}
|
||||
2
.github/workflows/web.tests.yml
vendored
@@ -67,7 +67,7 @@ jobs:
|
||||
- name: Install packages
|
||||
run: |
|
||||
npm ci --ignore-scripts --prefer-offline --no-audit
|
||||
npm install -D @playwright/test otplib dayjs @zip.js/zip.js
|
||||
npm install -D @playwright/test otplib
|
||||
|
||||
- name: Validate build extraction
|
||||
run: ls -ld ./apps/web/build/index.html
|
||||
|
||||
32
.github/workflows/web.v3-beta.publish.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: Publish @notesnook/web v3 Beta
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Node
|
||||
uses: ./.github/actions/setup-node-with-cache
|
||||
|
||||
- name: Install packages
|
||||
run: |
|
||||
npm ci --ignore-scripts --prefer-offline --no-audit
|
||||
npm run bootstrap -- --scope=web
|
||||
|
||||
- name: Setup environment
|
||||
run: |
|
||||
echo "NX_CLOUD_ACCESS_TOKEN=${{ secrets.NX_CLOUD_ACCESS_TOKEN }}" >> $GITHUB_ENV
|
||||
echo "CLOUDFLARE_ACCOUNT_ID=${{ secrets.CLOUDFLARE_ACCOUNT_ID }}" >> $GITHUB_ENV
|
||||
echo "CLOUDFLARE_API_TOKEN=${{ secrets.CLOUDFLARE_API_TOKEN }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Build
|
||||
run: npm run build:web
|
||||
|
||||
- name: Publish to Cloudflare Pages
|
||||
run: npx --yes wrangler pages deploy --project-name=notesnook-v3-beta ./apps/web/build/
|
||||
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 118 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 401 B After Width: | Height: | Size: 520 B |
|
Before Width: | Height: | Size: 543 B After Width: | Height: | Size: 917 B |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 763 B After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 353 KiB After Width: | Height: | Size: 353 KiB |
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 36 KiB |
570
apps/desktop/package-lock.json
generated
@@ -1,23 +1,23 @@
|
||||
{
|
||||
"name": "@notesnook/desktop",
|
||||
"version": "3.0.2",
|
||||
"version": "3.0.7-beta",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@notesnook/desktop",
|
||||
"version": "3.0.2",
|
||||
"version": "3.0.7-beta",
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@notesnook/crypto": "file:../../packages/crypto",
|
||||
"@trpc/client": "10.38.3",
|
||||
"@trpc/server": "10.38.3",
|
||||
"better-sqlite3-multiple-ciphers": "^9.5.0",
|
||||
"better-sqlite3-multiple-ciphers": "^9.4.0",
|
||||
"electron-trpc": "0.5.2",
|
||||
"electron-updater": "6.1.4",
|
||||
"icojs": "^0.17.1",
|
||||
"sodium-native": "^4.1.1",
|
||||
"sodium-native": "^4.0.6",
|
||||
"typed-emitter": "^2.1.0",
|
||||
"yargs": "^17.6.2",
|
||||
"zod": "^3.21.4"
|
||||
@@ -26,13 +26,11 @@
|
||||
"@types/node": "18.16.1",
|
||||
"@types/yargs": "^17.0.24",
|
||||
"chokidar": "^3.5.3",
|
||||
"electron": "^29.3.1",
|
||||
"electron-builder": "^24.13.3",
|
||||
"electron": "^28.2.1",
|
||||
"electron-builder": "^24.9.1",
|
||||
"esbuild": "^0.20.0",
|
||||
"node-gyp-build": "^4.8.0",
|
||||
"prebuildify": "^6.0.1",
|
||||
"tree-kill": "^1.2.2",
|
||||
"undici": "^6.14.1"
|
||||
"undici": "^6.6.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"dmg-license": "^1.0.11"
|
||||
@@ -70,9 +68,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/asar": {
|
||||
"version": "3.2.9",
|
||||
"resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.9.tgz",
|
||||
"integrity": "sha512-Vu2P3X2gcZ3MY9W7yH72X9+AMXwUQZEJBrsPIbX0JsdllLtoh62/Q8Wg370/DawIEVKOyfD6KtTLo645ezqxUA==",
|
||||
"version": "3.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.8.tgz",
|
||||
"integrity": "sha512-cmskk5M06ewHMZAplSiF4AlME3IrnnZhKnWbtwKVLRkdJkKyUVjMLhDIiPIx/+6zQWVlKX/LtmK9xDme7540Sg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"commander": "^5.0.0",
|
||||
@@ -171,9 +169,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/notarize": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.2.1.tgz",
|
||||
"integrity": "sha512-aL+bFMIkpR0cmmj5Zgy0LMKEpgy43/hw5zadEArgmAMWWlKc5buwFvFT9G/o/YJkvXAJm5q3iuTuLaiaXW39sg==",
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.1.0.tgz",
|
||||
"integrity": "sha512-Q02xem1D0sg4v437xHgmBLxI2iz/fc0D4K7fiVWHa/AnW8o7D751xyKNXgziA6HrTOme9ul1JfWN5ark8WH1xA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"debug": "^4.1.1",
|
||||
@@ -233,9 +231,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/universal": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.5.1.tgz",
|
||||
"integrity": "sha512-kbgXxyEauPJiQQUNG2VgUeyfQNFk6hBF11ISN2PNI6agUgPl55pv4eQmaqHzTAzchBvqZ2tQuRVaPStGf0mxGw==",
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.4.1.tgz",
|
||||
"integrity": "sha512-lE/U3UNw1YHuowNbTmKNs9UlS3En3cPgwM5MI+agIgr/B1hSze9NdOP0qn7boZaI9Lph8IDv3/24g9IxnJP7aQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@electron/asar": "^3.2.1",
|
||||
@@ -655,100 +653,13 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
||||
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"string-width": "^5.1.2",
|
||||
"string-width-cjs": "npm:string-width@^4.2.0",
|
||||
"strip-ansi": "^7.0.1",
|
||||
"strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
|
||||
"wrap-ansi": "^8.1.0",
|
||||
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui/node_modules/ansi-regex": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
|
||||
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
|
||||
"node_modules/@fastify/busboy": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz",
|
||||
"integrity": "sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui/node_modules/ansi-styles": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
|
||||
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui/node_modules/emoji-regex": {
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
||||
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@isaacs/cliui/node_modules/string-width": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
|
||||
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"eastasianwidth": "^0.2.0",
|
||||
"emoji-regex": "^9.2.2",
|
||||
"strip-ansi": "^7.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui/node_modules/strip-ansi": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
|
||||
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-regex": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
|
||||
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-styles": "^6.1.0",
|
||||
"string-width": "^5.0.1",
|
||||
"strip-ansi": "^7.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@malept/cross-spawn-promise": {
|
||||
@@ -807,16 +718,6 @@
|
||||
"resolved": "../../packages/crypto",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@pkgjs/parseargs": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
|
||||
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@sindresorhus/is": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
|
||||
@@ -1066,25 +967,26 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/app-builder-lib": {
|
||||
"version": "24.13.3",
|
||||
"resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-24.13.3.tgz",
|
||||
"integrity": "sha512-FAzX6IBit2POXYGnTCT8YHFO/lr5AapAII6zzhQO3Rw4cEDOgK+t1xhLc5tNcKlicTHlo9zxIwnYCX9X2DLkig==",
|
||||
"version": "24.9.1",
|
||||
"resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-24.9.1.tgz",
|
||||
"integrity": "sha512-Q1nYxZcio4r+W72cnIRVYofEAyjBd3mG47o+zms8HlD51zWtA/YxJb01Jei5F+jkWhge/PTQK+uldsPh6d0/4g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@develar/schema-utils": "~2.6.5",
|
||||
"@electron/notarize": "2.2.1",
|
||||
"@electron/notarize": "2.1.0",
|
||||
"@electron/osx-sign": "1.0.5",
|
||||
"@electron/universal": "1.5.1",
|
||||
"@electron/universal": "1.4.1",
|
||||
"@malept/flatpak-bundler": "^0.4.0",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"7zip-bin": "~5.2.0",
|
||||
"async-exit-hook": "^2.0.1",
|
||||
"bluebird-lst": "^1.0.9",
|
||||
"builder-util": "24.13.1",
|
||||
"builder-util-runtime": "9.2.4",
|
||||
"builder-util": "24.8.1",
|
||||
"builder-util-runtime": "9.2.3",
|
||||
"chromium-pickle-js": "^0.2.0",
|
||||
"debug": "^4.3.4",
|
||||
"ejs": "^3.1.8",
|
||||
"electron-publish": "24.13.1",
|
||||
"electron-publish": "24.8.1",
|
||||
"form-data": "^4.0.0",
|
||||
"fs-extra": "^10.1.0",
|
||||
"hosted-git-info": "^4.1.0",
|
||||
@@ -1101,16 +1003,12 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"dmg-builder": "24.13.3",
|
||||
"electron-builder-squirrel-windows": "24.13.3"
|
||||
}
|
||||
},
|
||||
"node_modules/app-builder-lib/node_modules/builder-util-runtime": {
|
||||
"version": "9.2.4",
|
||||
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.4.tgz",
|
||||
"integrity": "sha512-upp+biKpN/XZMLim7aguUyW8s0FUpDvOtK6sbanMFDAMBzpHDqdhgVYm6zc9HJ6nWo7u2Lxk60i2M6Jd3aiNrA==",
|
||||
"version": "9.2.3",
|
||||
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.3.tgz",
|
||||
"integrity": "sha512-FGhkqXdFFZ5dNC4C+yuQB9ak311rpGAw+/ASz8ZdxwODCv1GGMWgLDeofRkdi0F3VCHQEWy/aXcJQozx2nOPiw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"debug": "^4.3.4",
|
||||
@@ -1199,9 +1097,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/better-sqlite3-multiple-ciphers": {
|
||||
"version": "9.5.0",
|
||||
"resolved": "https://registry.npmjs.org/better-sqlite3-multiple-ciphers/-/better-sqlite3-multiple-ciphers-9.5.0.tgz",
|
||||
"integrity": "sha512-6A9xBRvssONJW07Lur6pmkaUwlCGz1bnjFmXrrAR3qXETUBk92OI4C/+LhMOatn5wQ8AQzLScFZC/CKUpxkTaw==",
|
||||
"version": "9.4.0",
|
||||
"resolved": "https://registry.npmjs.org/better-sqlite3-multiple-ciphers/-/better-sqlite3-multiple-ciphers-9.4.0.tgz",
|
||||
"integrity": "sha512-uQoBdShnpCdAPUmCPuLSrHtfSHAxjIFQvLnMbXHsvbWkfBP3sPfnnIaUTz7KHYRqgWNLlcQfs+9F9uqvMqau6Q==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"bindings": "^1.5.0",
|
||||
@@ -1334,16 +1232,16 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/builder-util": {
|
||||
"version": "24.13.1",
|
||||
"resolved": "https://registry.npmjs.org/builder-util/-/builder-util-24.13.1.tgz",
|
||||
"integrity": "sha512-NhbCSIntruNDTOVI9fdXz0dihaqX2YuE1D6zZMrwiErzH4ELZHE6mdiB40wEgZNprDia+FghRFgKoAqMZRRjSA==",
|
||||
"version": "24.8.1",
|
||||
"resolved": "https://registry.npmjs.org/builder-util/-/builder-util-24.8.1.tgz",
|
||||
"integrity": "sha512-ibmQ4BnnqCnJTNrdmdNlnhF48kfqhNzSeqFMXHLIl+o9/yhn6QfOaVrloZ9YUu3m0k3rexvlT5wcki6LWpjTZw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/debug": "^4.1.6",
|
||||
"7zip-bin": "~5.2.0",
|
||||
"app-builder-bin": "4.0.0",
|
||||
"bluebird-lst": "^1.0.9",
|
||||
"builder-util-runtime": "9.2.4",
|
||||
"builder-util-runtime": "9.2.3",
|
||||
"chalk": "^4.1.2",
|
||||
"cross-spawn": "^7.0.3",
|
||||
"debug": "^4.3.4",
|
||||
@@ -1370,9 +1268,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/builder-util/node_modules/builder-util-runtime": {
|
||||
"version": "9.2.4",
|
||||
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.4.tgz",
|
||||
"integrity": "sha512-upp+biKpN/XZMLim7aguUyW8s0FUpDvOtK6sbanMFDAMBzpHDqdhgVYm6zc9HJ6nWo7u2Lxk60i2M6Jd3aiNrA==",
|
||||
"version": "9.2.3",
|
||||
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.3.tgz",
|
||||
"integrity": "sha512-FGhkqXdFFZ5dNC4C+yuQB9ak311rpGAw+/ASz8ZdxwODCv1GGMWgLDeofRkdi0F3VCHQEWy/aXcJQozx2nOPiw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"debug": "^4.3.4",
|
||||
@@ -1576,59 +1474,13 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/config-file-ts": {
|
||||
"version": "0.2.6",
|
||||
"resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.6.tgz",
|
||||
"integrity": "sha512-6boGVaglwblBgJqGyxm4+xCmEGcWgnWHSWHY5jad58awQhB6gftq0G8HbzU39YqCIYHMLAiL1yjwiZ36m/CL8w==",
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.4.tgz",
|
||||
"integrity": "sha512-cKSW0BfrSaAUnxpgvpXPLaaW/umg4bqg4k3GO1JqlRfpx+d5W0GDXznCMkWotJQek5Mmz1MJVChQnz3IVaeMZQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"glob": "^10.3.10",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
},
|
||||
"node_modules/config-file-ts/node_modules/glob": {
|
||||
"version": "10.3.12",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz",
|
||||
"integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"foreground-child": "^3.1.0",
|
||||
"jackspeak": "^2.3.6",
|
||||
"minimatch": "^9.0.1",
|
||||
"minipass": "^7.0.4",
|
||||
"path-scurry": "^1.10.2"
|
||||
},
|
||||
"bin": {
|
||||
"glob": "dist/esm/bin.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/config-file-ts/node_modules/minimatch": {
|
||||
"version": "9.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz",
|
||||
"integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/config-file-ts/node_modules/minipass": {
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
|
||||
"integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
"glob": "^7.1.6",
|
||||
"typescript": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/core-util-is": {
|
||||
@@ -1817,14 +1669,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/dmg-builder": {
|
||||
"version": "24.13.3",
|
||||
"resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-24.13.3.tgz",
|
||||
"integrity": "sha512-rcJUkMfnJpfCboZoOOPf4L29TRtEieHNOeAbYPWPxlaBw/Z1RKrRA86dOI9rwaI4tQSc/RD82zTNHprfUHXsoQ==",
|
||||
"version": "24.9.1",
|
||||
"resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-24.9.1.tgz",
|
||||
"integrity": "sha512-huC+O6hvHd24Ubj3cy2GMiGLe2xGFKN3klqVMLAdcbB6SWMd1yPSdZvV8W1O01ICzCCRlZDHiv4VrNUgnPUfbQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"app-builder-lib": "24.13.3",
|
||||
"builder-util": "24.13.1",
|
||||
"builder-util-runtime": "9.2.4",
|
||||
"app-builder-lib": "24.9.1",
|
||||
"builder-util": "24.8.1",
|
||||
"builder-util-runtime": "9.2.3",
|
||||
"fs-extra": "^10.1.0",
|
||||
"iconv-lite": "^0.6.2",
|
||||
"js-yaml": "^4.1.0"
|
||||
@@ -1834,9 +1686,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/dmg-builder/node_modules/builder-util-runtime": {
|
||||
"version": "9.2.4",
|
||||
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.4.tgz",
|
||||
"integrity": "sha512-upp+biKpN/XZMLim7aguUyW8s0FUpDvOtK6sbanMFDAMBzpHDqdhgVYm6zc9HJ6nWo7u2Lxk60i2M6Jd3aiNrA==",
|
||||
"version": "9.2.3",
|
||||
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.3.tgz",
|
||||
"integrity": "sha512-FGhkqXdFFZ5dNC4C+yuQB9ak311rpGAw+/ASz8ZdxwODCv1GGMWgLDeofRkdi0F3VCHQEWy/aXcJQozx2nOPiw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"debug": "^4.3.4",
|
||||
@@ -1871,31 +1723,16 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
"version": "9.0.2",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz",
|
||||
"integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv-expand": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz",
|
||||
"integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/eastasianwidth": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
||||
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/ejs": {
|
||||
"version": "3.1.10",
|
||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
|
||||
"integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==",
|
||||
"version": "3.1.9",
|
||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz",
|
||||
"integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"jake": "^10.8.5"
|
||||
@@ -1908,14 +1745,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron": {
|
||||
"version": "29.3.1",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-29.3.1.tgz",
|
||||
"integrity": "sha512-auge1/6RVqgUd6TgIq88wKdUCJi2cjESi3jy7d+6X4JzvBGprKBqMJ8JSSFpu/Px1YJrFUKAxfy6SC+TQf1uLw==",
|
||||
"version": "28.2.1",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-28.2.1.tgz",
|
||||
"integrity": "sha512-wlzXf+OvOiVlBf9dcSeMMf7Q+N6DG+wtgFbMK0sA/JpIJcdosRbLMQwLg/LTwNVKIbmayqFLDp4FmmFkEMhbYA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@electron/get": "^2.0.0",
|
||||
"@types/node": "^20.9.0",
|
||||
"@types/node": "^18.11.18",
|
||||
"extract-zip": "^2.0.1"
|
||||
},
|
||||
"bin": {
|
||||
@@ -1926,16 +1763,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron-builder": {
|
||||
"version": "24.13.3",
|
||||
"resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-24.13.3.tgz",
|
||||
"integrity": "sha512-yZSgVHft5dNVlo31qmJAe4BVKQfFdwpRw7sFp1iQglDRCDD6r22zfRJuZlhtB5gp9FHUxCMEoWGq10SkCnMAIg==",
|
||||
"version": "24.9.1",
|
||||
"resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-24.9.1.tgz",
|
||||
"integrity": "sha512-v7BuakDuY6sKMUYM8mfQGrwyjBpZ/ObaqnenU0H+igEL10nc6ht049rsCw2HghRBdEwJxGIBuzs3jbEhNaMDmg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"app-builder-lib": "24.13.3",
|
||||
"builder-util": "24.13.1",
|
||||
"builder-util-runtime": "9.2.4",
|
||||
"app-builder-lib": "24.9.1",
|
||||
"builder-util": "24.8.1",
|
||||
"builder-util-runtime": "9.2.3",
|
||||
"chalk": "^4.1.2",
|
||||
"dmg-builder": "24.13.3",
|
||||
"dmg-builder": "24.9.1",
|
||||
"fs-extra": "^10.1.0",
|
||||
"is-ci": "^3.0.0",
|
||||
"lazy-val": "^1.0.5",
|
||||
@@ -1952,9 +1789,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron-builder/node_modules/builder-util-runtime": {
|
||||
"version": "9.2.4",
|
||||
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.4.tgz",
|
||||
"integrity": "sha512-upp+biKpN/XZMLim7aguUyW8s0FUpDvOtK6sbanMFDAMBzpHDqdhgVYm6zc9HJ6nWo7u2Lxk60i2M6Jd3aiNrA==",
|
||||
"version": "9.2.3",
|
||||
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.3.tgz",
|
||||
"integrity": "sha512-FGhkqXdFFZ5dNC4C+yuQB9ak311rpGAw+/ASz8ZdxwODCv1GGMWgLDeofRkdi0F3VCHQEWy/aXcJQozx2nOPiw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"debug": "^4.3.4",
|
||||
@@ -1965,14 +1802,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron-publish": {
|
||||
"version": "24.13.1",
|
||||
"resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-24.13.1.tgz",
|
||||
"integrity": "sha512-2ZgdEqJ8e9D17Hwp5LEq5mLQPjqU3lv/IALvgp+4W8VeNhryfGhYEQC/PgDPMrnWUp+l60Ou5SJLsu+k4mhQ8A==",
|
||||
"version": "24.8.1",
|
||||
"resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-24.8.1.tgz",
|
||||
"integrity": "sha512-IFNXkdxMVzUdweoLJNXSupXkqnvgbrn3J4vognuOY06LaS/m0xvfFYIf+o1CM8if6DuWYWoQFKPcWZt/FUjZPw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/fs-extra": "^9.0.11",
|
||||
"builder-util": "24.13.1",
|
||||
"builder-util-runtime": "9.2.4",
|
||||
"builder-util": "24.8.1",
|
||||
"builder-util-runtime": "9.2.3",
|
||||
"chalk": "^4.1.2",
|
||||
"fs-extra": "^10.1.0",
|
||||
"lazy-val": "^1.0.5",
|
||||
@@ -1980,9 +1817,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron-publish/node_modules/builder-util-runtime": {
|
||||
"version": "9.2.4",
|
||||
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.4.tgz",
|
||||
"integrity": "sha512-upp+biKpN/XZMLim7aguUyW8s0FUpDvOtK6sbanMFDAMBzpHDqdhgVYm6zc9HJ6nWo7u2Lxk60i2M6Jd3aiNrA==",
|
||||
"version": "9.2.3",
|
||||
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.3.tgz",
|
||||
"integrity": "sha512-FGhkqXdFFZ5dNC4C+yuQB9ak311rpGAw+/ASz8ZdxwODCv1GGMWgLDeofRkdi0F3VCHQEWy/aXcJQozx2nOPiw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"debug": "^4.3.4",
|
||||
@@ -2020,15 +1857,6 @@
|
||||
"tiny-typed-emitter": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/electron/node_modules/@types/node": {
|
||||
"version": "20.12.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz",
|
||||
"integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
}
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
@@ -2223,22 +2051,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/foreground-child": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
|
||||
"integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.0",
|
||||
"signal-exit": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
@@ -2749,12 +2561,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/isbinaryfile": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.2.tgz",
|
||||
"integrity": "sha512-GvcjojwonMjWbTkfMpnVHVqXW/wKMYDfEpY94/8zy8HFMOqb/VL6oeONq9v87q4ttVlaTLnGXnJD4B5B1OTGIg==",
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.0.tgz",
|
||||
"integrity": "sha512-UDdnyGvMajJUWCkib7Cei/dvyJrrvo4FIrsvSFWdPpXSUorzXrDJ0S+X5Q4ZlasfPjca4yqCNNsjbCeiy8FFeg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 18.0.0"
|
||||
"node": ">= 14.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/gjtorikian/"
|
||||
@@ -2766,24 +2578,6 @@
|
||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/jackspeak": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
|
||||
"integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@isaacs/cliui": "^8.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@pkgjs/parseargs": "^0.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jake": {
|
||||
"version": "10.8.7",
|
||||
"resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz",
|
||||
@@ -3116,18 +2910,6 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/npm-run-path": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-3.1.0.tgz",
|
||||
"integrity": "sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"path-key": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/object-keys": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
||||
@@ -3173,31 +2955,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/path-scurry": {
|
||||
"version": "1.10.2",
|
||||
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz",
|
||||
"integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lru-cache": "^10.2.0",
|
||||
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/path-scurry/node_modules/lru-cache": {
|
||||
"version": "10.2.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.1.tgz",
|
||||
"integrity": "sha512-tS24spDe/zXhWbNPErCHs/AGOzbKGHT+ybSBqmdLm8WZ1xXLWvH8Qn71QPAlqVhd0qUTWjy+Kl9JmISgDdEjsA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "14 || >=16.14"
|
||||
}
|
||||
},
|
||||
"node_modules/peek-readable": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz",
|
||||
@@ -3274,23 +3031,6 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/prebuildify": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/prebuildify/-/prebuildify-6.0.1.tgz",
|
||||
"integrity": "sha512-8Y2oOOateom/s8dNBsGIcnm6AxPmLH4/nanQzL5lQMU+sC0CMhzARZHizwr36pUPLdvBnOkCNQzxg4djuFSgIw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.5",
|
||||
"mkdirp-classic": "^0.5.3",
|
||||
"node-abi": "^3.3.0",
|
||||
"npm-run-path": "^3.1.0",
|
||||
"pump": "^3.0.0",
|
||||
"tar-fs": "^2.1.0"
|
||||
},
|
||||
"bin": {
|
||||
"prebuildify": "bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/progress": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
|
||||
@@ -3374,6 +3114,15 @@
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/read-config-file/node_modules/dotenv": {
|
||||
"version": "9.0.2",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz",
|
||||
"integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/readable-stream": {
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||
@@ -3449,6 +3198,21 @@
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/rimraf": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"glob": "^7.1.3"
|
||||
},
|
||||
"bin": {
|
||||
"rimraf": "bin.js"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/roarr": {
|
||||
"version": "2.15.4",
|
||||
"resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz",
|
||||
@@ -3586,18 +3350,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/signal-exit": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
|
||||
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/simple-concat": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
|
||||
@@ -3678,12 +3430,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/sodium-native": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.1.1.tgz",
|
||||
"integrity": "sha512-LXkAfRd4FHtkQS4X6g+nRcVaN7mWVNepV06phIsC6+IZFvGh1voW5TNQiQp2twVaMf05gZqQjuS+uWLM6gHhNQ==",
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.0.6.tgz",
|
||||
"integrity": "sha512-uYsyycwcz9kYDwpXxJmL2YZosynsxcP6RPySbARVJdC9uNDa2CMjzJ7/WsMMvThKgvAYsBWdZc7L/WSVj9lTcA==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"node-gyp-build": "^4.8.0"
|
||||
"node-gyp-build": "^4.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
@@ -3706,9 +3458,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/sprintf-js": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
|
||||
"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
|
||||
"integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
@@ -3742,21 +3494,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/string-width-cjs": {
|
||||
"name": "string-width",
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-ansi": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
@@ -3768,19 +3505,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-ansi-cjs": {
|
||||
"name": "strip-ansi",
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-json-comments": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||
@@ -3830,9 +3554,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tar": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
|
||||
"integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz",
|
||||
"integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"chownr": "^2.0.0",
|
||||
@@ -3893,12 +3617,15 @@
|
||||
"integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA=="
|
||||
},
|
||||
"node_modules/tmp": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz",
|
||||
"integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==",
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
|
||||
"integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"rimraf": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.14"
|
||||
"node": ">=8.17.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tmp-promise": {
|
||||
@@ -3987,33 +3714,30 @@
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.4.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
|
||||
"integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
|
||||
"version": "4.9.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
|
||||
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
"node": ">=4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "6.14.1",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.14.1.tgz",
|
||||
"integrity": "sha512-mAel3i4BsYhkeVPXeIPXVGPJKeBzqCieZYoFsbWfUzd68JmHByhc1Plit5WlylxXFaGpgkZB8mExlxnt+Q1p7A==",
|
||||
"version": "6.6.1",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.6.1.tgz",
|
||||
"integrity": "sha512-J0GaEp0ztu/grIE2Uq57AbK6TRb+bWbOlxu0POCzhFKA6LKbwSAev+hDQaQcgUUA9CPs8Ky+cauzTHnQrtAQEA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@fastify/busboy": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.17"
|
||||
"node": ">=18.0"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "5.26.5",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/universalify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
||||
@@ -4087,24 +3811,6 @@
|
||||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi-cjs": {
|
||||
"name": "wrap-ansi",
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@notesnook/desktop",
|
||||
"productName": "Notesnook",
|
||||
"description": "Your private note taking space",
|
||||
"version": "3.0.2",
|
||||
"version": "3.0.7-beta",
|
||||
"appAppleId": "1544027013",
|
||||
"private": true,
|
||||
"main": "./dist/index.js",
|
||||
@@ -14,11 +14,11 @@
|
||||
"@notesnook/crypto": "file:../../packages/crypto",
|
||||
"@trpc/client": "10.38.3",
|
||||
"@trpc/server": "10.38.3",
|
||||
"better-sqlite3-multiple-ciphers": "^9.5.0",
|
||||
"better-sqlite3-multiple-ciphers": "^9.4.0",
|
||||
"electron-trpc": "0.5.2",
|
||||
"electron-updater": "6.1.4",
|
||||
"icojs": "^0.17.1",
|
||||
"sodium-native": "^4.1.1",
|
||||
"sodium-native": "^4.0.6",
|
||||
"typed-emitter": "^2.1.0",
|
||||
"yargs": "^17.6.2",
|
||||
"zod": "^3.21.4"
|
||||
@@ -27,13 +27,11 @@
|
||||
"@types/node": "18.16.1",
|
||||
"@types/yargs": "^17.0.24",
|
||||
"chokidar": "^3.5.3",
|
||||
"electron": "^29.3.1",
|
||||
"electron-builder": "^24.13.3",
|
||||
"electron": "^28.2.1",
|
||||
"electron-builder": "^24.9.1",
|
||||
"esbuild": "^0.20.0",
|
||||
"node-gyp-build": "^4.8.0",
|
||||
"prebuildify": "^6.0.1",
|
||||
"tree-kill": "^1.2.2",
|
||||
"undici": "^6.14.1"
|
||||
"undici": "^6.6.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"dmg-license": "^1.0.11"
|
||||
@@ -57,8 +55,8 @@
|
||||
"productName": "Notesnook",
|
||||
"copyright": "Copyright © 2023 Streetwriters (Private) Limited",
|
||||
"artifactName": "notesnook_${os}_${arch}.${ext}",
|
||||
"generateUpdatesFilesForAllChannels": true,
|
||||
"asar": false,
|
||||
"generateUpdatesFilesForAllChannels": true,
|
||||
"files": [
|
||||
"!*.chunk.js.map",
|
||||
"!*.chunk.js.LICENSE.txt",
|
||||
@@ -221,7 +219,8 @@
|
||||
{
|
||||
"provider": "github",
|
||||
"repo": "notesnook",
|
||||
"owner": "streetwriters"
|
||||
"owner": "streetwriters",
|
||||
"channel": "beta"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
diff --git a/node_modules/node-gyp-build/bin.js b/node_modules/node-gyp-build/bin.js
|
||||
index 3fbcdf0..7ca3ab5 100644
|
||||
--- a/node_modules/node-gyp-build/bin.js
|
||||
+++ b/node_modules/node-gyp-build/bin.js
|
||||
@@ -16,7 +16,8 @@ if (!buildFromSource()) {
|
||||
}
|
||||
|
||||
function build () {
|
||||
- var args = [os.platform() === 'win32' ? 'node-gyp.cmd' : 'node-gyp', 'rebuild']
|
||||
+ var win32 = os.platform() === 'win32'
|
||||
+ var args = [win32 ? 'node-gyp.cmd' : 'node-gyp', 'rebuild']
|
||||
|
||||
try {
|
||||
var pkg = require('node-gyp/package.json')
|
||||
@@ -27,7 +28,7 @@ function build () {
|
||||
]
|
||||
} catch (_) {}
|
||||
|
||||
- proc.spawn(args[0], args.slice(1), { stdio: 'inherit' }).on('exit', function (code) {
|
||||
+ proc.spawn(args[0], args.slice(1), { stdio: 'inherit', shell: win32, windowsHide: true }).on('exit', function (code) {
|
||||
if (code || !process.argv[3]) process.exit(code)
|
||||
exec(process.argv[3]).on('exit', function (code) {
|
||||
process.exit(code)
|
||||
@@ -45,15 +46,18 @@ function preinstall () {
|
||||
|
||||
function exec (cmd) {
|
||||
if (process.platform !== 'win32') {
|
||||
- var shell = os.platform() === 'android' ? 'sh' : '/bin/sh'
|
||||
- return proc.spawn(shell, ['-c', '--', cmd], {
|
||||
+ var shell = os.platform() === 'android' ? 'sh' : true
|
||||
+ return proc.spawn(cmd, [], {
|
||||
+ shell,
|
||||
stdio: 'inherit'
|
||||
})
|
||||
}
|
||||
|
||||
- return proc.spawn(process.env.comspec || 'cmd.exe', ['/s', '/c', '"' + cmd + '"'], {
|
||||
+ return proc.spawn(cmd, [], {
|
||||
windowsVerbatimArguments: true,
|
||||
- stdio: 'inherit'
|
||||
+ stdio: 'inherit',
|
||||
+ shell: true,
|
||||
+ windowsHide: true
|
||||
})
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import path from "path";
|
||||
import fs, { readFile, writeFile } from "fs/promises";
|
||||
import { existsSync, readFileSync } from "fs";
|
||||
import { existsSync } from "fs";
|
||||
import yargs from "yargs-parser";
|
||||
import os from "os";
|
||||
import * as childProcess from "child_process";
|
||||
@@ -28,27 +28,21 @@ import { fileURLToPath } from "url";
|
||||
const args = yargs(process.argv);
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const packageJson = JSON.parse(
|
||||
readFileSync(path.join(__dirname, "..", "package.json"), "utf-8")
|
||||
);
|
||||
|
||||
const webAppPath = path.resolve(path.join(__dirname, "..", "..", "web"));
|
||||
|
||||
await fs.rm("./build/", { force: true, recursive: true });
|
||||
|
||||
if (args.rebuild || !existsSync(path.join(webAppPath, "build"))) {
|
||||
await exec(
|
||||
"npx nx build:desktop @notesnook/web",
|
||||
path.join(__dirname, "..", "..", "..")
|
||||
);
|
||||
await exec(`cd ${webAppPath} && npm run build:desktop`);
|
||||
}
|
||||
|
||||
// temporary until there's support for prebuilt binaries for linux ARM
|
||||
if (os.platform() === "linux") await patchBetterSQLite3();
|
||||
// temporary until there's support for prebuilt binaries for windows ARM & linux ARM
|
||||
await patchBetterSQLite3();
|
||||
|
||||
if (os.platform() === "win32")
|
||||
await exec(
|
||||
`npx prebuildify --arch=arm64 --strip -t electron@${packageJson.devDependencies.electron}`,
|
||||
"npx prebuildify --arch=arm64 --strip",
|
||||
path.join(__dirname, "..", "node_modules", "sodium-native")
|
||||
);
|
||||
|
||||
@@ -70,7 +64,7 @@ if (args.run) {
|
||||
if (process.platform === "win32") {
|
||||
await exec(`.\\output\\win-unpacked\\Notesnook.exe`);
|
||||
} else if (process.platform === "darwin") {
|
||||
await exec(`./output/mac/Notesnook.app/Contents/MacOS/Notesnook`);
|
||||
await exec(`./output/darwin-unpacked/Notesnook`);
|
||||
} else {
|
||||
await exec(`./output/linux-unpacked/Notesnook`);
|
||||
}
|
||||
@@ -94,7 +88,7 @@ async function patchBetterSQLite3() {
|
||||
);
|
||||
const json = JSON.parse(await readFile(jsonPath, "utf-8"));
|
||||
|
||||
json.version = "9.5.1";
|
||||
json.version = "9.4.1";
|
||||
json.homepage = "https://github.com/thecodrr/better-sqlite3-multiple-ciphers";
|
||||
json.repository.url =
|
||||
"git://github.com/thecodrr/better-sqlite3-multiple-ciphers.git";
|
||||
|
||||
@@ -53,7 +53,7 @@ async function onChange(first) {
|
||||
if (first) {
|
||||
await fs.rm("./build/", { force: true, recursive: true });
|
||||
|
||||
await exec("npx electron-builder install-app-deps");
|
||||
await exec("npx electron-rebuild");
|
||||
}
|
||||
|
||||
await exec(`npm run bundle`);
|
||||
|
||||
@@ -33,7 +33,7 @@ module.exports = async function (configuration) {
|
||||
const DescriptionUrl = "https://notesnook.com/";
|
||||
const FilesCatalog = createCatalog(configuration.path);
|
||||
|
||||
const command = `Invoke-TrustedSigning -Endpoint "${Endpoint}" -CodeSigningAccountName "${CodeSigningAccountName}" -CertificateProfileName "${CertificateProfileName}" -FileDigest "${FileDigest}" -TimestampRfc3161 "${TimestampRfc3161}" -TimestampDigest "${TimestampDigest}" -Description "${Description}" -DescriptionUrl "${DescriptionUrl}" -FilesCatalog "${FilesCatalog}"`;
|
||||
const command = `Invoke-AzureCodeSigning -Endpoint "${Endpoint}" -CodeSigningAccountName "${CodeSigningAccountName}" -CertificateProfileName "${CertificateProfileName}" -FileDigest "${FileDigest}" -TimestampRfc3161 "${TimestampRfc3161}" -TimestampDigest "${TimestampDigest}" -Description "${Description}" -DescriptionUrl "${DescriptionUrl}" -FilesCatalog "${FilesCatalog}"`;
|
||||
|
||||
console.debug("Signing", configuration.path, "using command", command);
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ import { spellCheckerRouter } from "./spell-checker";
|
||||
import { updaterRouter } from "./updater";
|
||||
import { bridgeRouter } from "./bridge";
|
||||
import { safeStorageRouter } from "./safe-storage";
|
||||
import { windowRouter } from "./window";
|
||||
|
||||
const t = initTRPC.create();
|
||||
|
||||
@@ -34,8 +33,7 @@ export const router = t.router({
|
||||
spellChecker: spellCheckerRouter,
|
||||
updater: updaterRouter,
|
||||
bridge: bridgeRouter,
|
||||
safeStorage: safeStorageRouter,
|
||||
window: windowRouter
|
||||
safeStorage: safeStorageRouter
|
||||
});
|
||||
|
||||
export const api = router.createCaller({});
|
||||
|
||||
@@ -32,7 +32,6 @@ import { AssetManager } from "../utils/asset-manager";
|
||||
import { isFlatpak } from "../utils";
|
||||
import { setupDesktopIntegration } from "../utils/desktop-integration";
|
||||
import { rm } from "fs/promises";
|
||||
import { disableCustomDns, enableCustomDns } from "../utils/custom-dns";
|
||||
|
||||
const t = initTRPC.create();
|
||||
|
||||
@@ -56,15 +55,6 @@ export const osIntegrationRouter = t.router({
|
||||
config.zoomFactor = factor;
|
||||
}),
|
||||
|
||||
customDns: t.procedure.query(() => config.customDns),
|
||||
setCustomDns: t.procedure
|
||||
.input(z.boolean())
|
||||
.mutation(({ input: customDns }) => {
|
||||
if (customDns) enableCustomDns();
|
||||
else disableCustomDns();
|
||||
config.customDns = customDns;
|
||||
}),
|
||||
|
||||
proxyRules: t.procedure.query(() => config.proxyRules),
|
||||
setProxyRules: t.procedure
|
||||
.input(z.string().optional())
|
||||
@@ -180,42 +170,16 @@ export const osIntegrationRouter = t.router({
|
||||
}),
|
||||
bringToFront: t.procedure.query(() => bringToFront()),
|
||||
changeTheme: t.procedure
|
||||
.input(
|
||||
z.object({
|
||||
theme: Theme,
|
||||
windowControlsIconColor: z.string().optional(),
|
||||
backgroundColor: z.string().optional()
|
||||
})
|
||||
)
|
||||
.mutation(
|
||||
({ input: { theme, windowControlsIconColor, backgroundColor } }) => {
|
||||
if (windowControlsIconColor) {
|
||||
config.windowControlsIconColor = windowControlsIconColor;
|
||||
if (process.platform === "win32")
|
||||
globalThis.window?.setTitleBarOverlay({
|
||||
symbolColor: windowControlsIconColor
|
||||
});
|
||||
}
|
||||
|
||||
if (backgroundColor) {
|
||||
config.backgroundColor = backgroundColor;
|
||||
}
|
||||
|
||||
setTheme(theme);
|
||||
}
|
||||
),
|
||||
.input(Theme)
|
||||
.mutation(({ input }) => setTheme(input)),
|
||||
|
||||
onThemeChanged: t.procedure.subscription(() =>
|
||||
observable<"dark" | "light">((emit) => {
|
||||
const updated = () => {
|
||||
nativeTheme.on("updated", () => {
|
||||
if (getTheme() === "system") {
|
||||
emit.next(nativeTheme.shouldUseDarkColors ? "dark" : "light");
|
||||
}
|
||||
};
|
||||
nativeTheme.on("updated", updated);
|
||||
return () => {
|
||||
nativeTheme.off("updated", updated);
|
||||
};
|
||||
});
|
||||
})
|
||||
)
|
||||
});
|
||||
|
||||
@@ -28,20 +28,16 @@ type UpdateInfo = { version: string };
|
||||
type Progress = { percent: number };
|
||||
|
||||
const t = initTRPC.create();
|
||||
let cancellationToken: CancellationToken | undefined = undefined;
|
||||
|
||||
export const updaterRouter = t.router({
|
||||
autoUpdates: t.procedure.query(() => config.automaticUpdates),
|
||||
install: t.procedure.query(() => autoUpdater.quitAndInstall()),
|
||||
download: t.procedure.query(async () => {
|
||||
if (cancellationToken) return;
|
||||
cancellationToken = new CancellationToken();
|
||||
await autoUpdater
|
||||
.downloadUpdate(cancellationToken)
|
||||
.finally(() => (cancellationToken = undefined));
|
||||
const cancellationToken = new CancellationToken();
|
||||
await autoUpdater.downloadUpdate(cancellationToken);
|
||||
}),
|
||||
check: t.procedure.query(async () => {
|
||||
await autoUpdater.checkForUpdates().catch(console.error);
|
||||
await autoUpdater.checkForUpdates();
|
||||
}),
|
||||
|
||||
toggleAutoUpdates: t.procedure
|
||||
@@ -75,7 +71,6 @@ function createSubscription<
|
||||
const listener: AppUpdaterEvents[TName] = (...args: any[]) => {
|
||||
emit.next(args[0]);
|
||||
};
|
||||
autoUpdater.removeAllListeners(eventName);
|
||||
autoUpdater.addListener(eventName, listener);
|
||||
return () => {
|
||||
autoUpdater.removeListener(eventName, listener);
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { initTRPC } from "@trpc/server";
|
||||
import { observable } from "@trpc/server/observable";
|
||||
|
||||
const t = initTRPC.create();
|
||||
|
||||
export const windowRouter = t.router({
|
||||
maximize: t.procedure.mutation(() => {
|
||||
globalThis.window?.maximize();
|
||||
}),
|
||||
restore: t.procedure.mutation(() => {
|
||||
globalThis.window?.restore();
|
||||
}),
|
||||
minimze: t.procedure.mutation(() => {
|
||||
globalThis.window?.minimize();
|
||||
}),
|
||||
maximized: t.procedure.query(() => globalThis.window?.isMaximized()),
|
||||
fullscreen: t.procedure.query(() => globalThis.window?.isFullScreen()),
|
||||
onWindowStateChanged: t.procedure.subscription(() => {
|
||||
return observable<{ maximized: boolean; fullscreen: boolean }>((emit) => {
|
||||
function listener() {
|
||||
emit.next({
|
||||
maximized: !!globalThis.window?.isMaximized(),
|
||||
fullscreen: !!globalThis.window?.isFullScreen()
|
||||
});
|
||||
}
|
||||
function enterFullscreen() {
|
||||
emit.next({
|
||||
maximized: !!globalThis.window?.isMaximized(),
|
||||
fullscreen: true
|
||||
});
|
||||
}
|
||||
function leaveFullscreen() {
|
||||
emit.next({
|
||||
maximized: !!globalThis.window?.isMaximized(),
|
||||
fullscreen: false
|
||||
});
|
||||
}
|
||||
globalThis.window?.addListener("maximize", listener);
|
||||
globalThis.window?.addListener("minimize", listener);
|
||||
globalThis.window?.addListener("unmaximize", listener);
|
||||
globalThis.window?.addListener("restore", listener);
|
||||
globalThis.window?.addListener("enter-full-screen", enterFullscreen);
|
||||
globalThis.window?.addListener("leave-full-screen", leaveFullscreen);
|
||||
globalThis.window?.addListener("leave-html-full-screen", leaveFullscreen);
|
||||
globalThis.window?.addListener("enter-html-full-screen", enterFullscreen);
|
||||
return () => {
|
||||
globalThis.window?.removeListener("maximize", listener);
|
||||
globalThis.window?.removeListener("minimize", listener);
|
||||
globalThis.window?.removeListener("unmaximize", listener);
|
||||
globalThis.window?.removeListener("restore", listener);
|
||||
globalThis.window?.removeListener("enter-full-screen", enterFullscreen);
|
||||
globalThis.window?.removeListener("leave-full-screen", leaveFullscreen);
|
||||
globalThis.window?.removeListener(
|
||||
"leave-html-full-screen",
|
||||
leaveFullscreen
|
||||
);
|
||||
globalThis.window?.removeListener(
|
||||
"enter-html-full-screen",
|
||||
enterFullscreen
|
||||
);
|
||||
};
|
||||
});
|
||||
})
|
||||
});
|
||||
@@ -35,7 +35,6 @@ import path from "path";
|
||||
import { bringToFront } from "./utils/bring-to-front";
|
||||
import { bridge } from "./api/bridge";
|
||||
import { setupDesktopIntegration } from "./utils/desktop-integration";
|
||||
import { disableCustomDns, enableCustomDns } from "./utils/custom-dns";
|
||||
|
||||
// only run a single instance
|
||||
if (!MAC_APP_STORE && !app.requestSingleInstanceLock()) {
|
||||
@@ -83,19 +82,6 @@ async function createWindow() {
|
||||
size: 512,
|
||||
format: process.platform === "win32" ? "ico" : "png"
|
||||
}),
|
||||
|
||||
titleBarStyle: "hidden",
|
||||
frame: process.platform === "win32" || process.platform === "darwin",
|
||||
titleBarOverlay: {
|
||||
height: 37,
|
||||
color: "#00000000",
|
||||
symbolColor: config.windowControlsIconColor
|
||||
},
|
||||
trafficLightPosition: {
|
||||
x: 16,
|
||||
y: 12
|
||||
},
|
||||
|
||||
webPreferences: {
|
||||
zoomFactor: config.zoomFactor,
|
||||
nodeIntegration: true,
|
||||
@@ -136,7 +122,7 @@ async function createWindow() {
|
||||
setupJumplist();
|
||||
|
||||
if (isDevelopment())
|
||||
mainWindow.webContents.openDevTools({ mode: "bottom", activate: true });
|
||||
mainWindow.webContents.openDevTools({ mode: "right", activate: true });
|
||||
|
||||
mainWindow.webContents.setWindowOpenHandler((details) => {
|
||||
shell.openExternal(details.url);
|
||||
@@ -152,9 +138,6 @@ async function createWindow() {
|
||||
app.once("ready", async () => {
|
||||
console.info("App ready. Opening window.");
|
||||
|
||||
if (config.customDns) enableCustomDns();
|
||||
else disableCustomDns();
|
||||
|
||||
if (!isDevelopment()) registerProtocol();
|
||||
await createWindow();
|
||||
configureAutoUpdater();
|
||||
|
||||
@@ -42,12 +42,7 @@ export const config = {
|
||||
zoomFactor: 1,
|
||||
theme: nativeTheme.themeSource,
|
||||
automaticUpdates: true,
|
||||
proxyRules: "",
|
||||
customDns: true,
|
||||
|
||||
backgroundColor: nativeTheme.themeSource === "dark" ? "#0f0f0f" : "#ffffff",
|
||||
windowControlsIconColor:
|
||||
nativeTheme.themeSource === "dark" ? "#ffffff" : "#000000"
|
||||
proxyRules: ""
|
||||
};
|
||||
|
||||
type ConfigKey = keyof typeof config;
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { app } from "electron";
|
||||
|
||||
export function enableCustomDns() {
|
||||
app.configureHostResolver({
|
||||
secureDnsServers: [
|
||||
"https://mozilla.cloudflare-dns.com/dns-query",
|
||||
"https://dns.quad9.net/dns-query"
|
||||
],
|
||||
enableBuiltInResolver: true
|
||||
});
|
||||
}
|
||||
|
||||
export function disableCustomDns() {
|
||||
app.configureHostResolver({
|
||||
secureDnsServers: [],
|
||||
enableBuiltInResolver: true
|
||||
});
|
||||
}
|
||||
@@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { net, protocol } from "electron";
|
||||
import { protocol } from "electron";
|
||||
import { isDevelopment } from "./index";
|
||||
import { createReadStream } from "fs";
|
||||
import { extname, normalize } from "path";
|
||||
@@ -62,7 +62,26 @@ function registerProtocol() {
|
||||
headers: { "Content-Type": extensionToMimeType[fileExtension] }
|
||||
});
|
||||
} else {
|
||||
return net.fetch(request, { bypassCustomProtocolHandlers: true });
|
||||
if (request.headers.has("X-Content-Length")) {
|
||||
request.headers.set(
|
||||
"Content-Length",
|
||||
request.headers.get("X-Content-Length") || "0"
|
||||
);
|
||||
request.headers.delete("X-Content-Length");
|
||||
}
|
||||
const headers = Object.fromEntries(request.headers.entries());
|
||||
|
||||
return await fetch(request.url, {
|
||||
signal: request.signal,
|
||||
mode: request.mode,
|
||||
headers,
|
||||
method: request.method,
|
||||
body: request.body,
|
||||
credentials: request.credentials,
|
||||
referrer: (request as any).referrer,
|
||||
duplex: "half",
|
||||
redirect: "manual"
|
||||
});
|
||||
}
|
||||
});
|
||||
console.info(`${SCHEME} protocol inteception "successful"`);
|
||||
|
||||
@@ -41,10 +41,7 @@ function setTheme(theme: Theme) {
|
||||
}
|
||||
|
||||
function getBackgroundColor() {
|
||||
return (
|
||||
config.backgroundColor ||
|
||||
(nativeTheme.shouldUseDarkColors ? "#0f0f0f" : "#ffffff")
|
||||
);
|
||||
return nativeTheme.shouldUseDarkColors ? "#0f0f0f" : "#ffffff";
|
||||
}
|
||||
|
||||
function getSystemTheme() {
|
||||
|
||||
|
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 28 KiB |
@@ -136,10 +136,11 @@ export async function validateAppLockPassword(appLockPassword) {
|
||||
const appLockCipher = CipherStorage.getMap(APPLOCK_CIPHER);
|
||||
if (!appLockCipher) return true;
|
||||
const decrypted = await decrypt(
|
||||
await Sodium.deriveKey(appLockPassword, NOTESNOOK_APPLOCK_KEY_SALT),
|
||||
{
|
||||
password: appLockPassword
|
||||
},
|
||||
appLockCipher
|
||||
);
|
||||
|
||||
DatabaseLogger.info(
|
||||
`validateAppLockPassword: ${typeof decrypted === "string"}`
|
||||
);
|
||||
@@ -318,6 +319,7 @@ export async function decrypt(password, data) {
|
||||
_data.output = "plain";
|
||||
|
||||
if (!password.salt) password.salt = data.salt;
|
||||
|
||||
return await Sodium.decrypt(password, _data);
|
||||
}
|
||||
|
||||
|
||||
@@ -218,7 +218,12 @@ export default async function downloadAttachment(
|
||||
}
|
||||
|
||||
if (options.base64 || options.text) {
|
||||
DatabaseLogger.log(`Starting to decrypt... hash: ${attachment.hash}`);
|
||||
console.log(
|
||||
"starting decrypt base64 file...",
|
||||
options.base64,
|
||||
options.text,
|
||||
attachment.hash
|
||||
);
|
||||
return await db.attachments.read(
|
||||
attachment.hash,
|
||||
options.base64 ? "base64" : "text"
|
||||
@@ -287,7 +292,7 @@ export default async function downloadAttachment(
|
||||
|
||||
return fileUri;
|
||||
} catch (e) {
|
||||
DatabaseLogger.error(e);
|
||||
console.log("download attachment error: ", e);
|
||||
if (attachment.dateUploaded) {
|
||||
RNFetchBlob.fs
|
||||
.unlink(RNFetchBlob.fs.dirs.CacheDir + `/${attachment.hash}`)
|
||||
|
||||
@@ -22,24 +22,21 @@ import NetInfo from "@react-native-community/netinfo";
|
||||
import RNFetchBlob from "react-native-blob-util";
|
||||
import { ToastManager } from "../../services/event-manager";
|
||||
import { useAttachmentStore } from "../../stores/use-attachment-store";
|
||||
import { DatabaseLogger, db } from "../database";
|
||||
import { db } from "../database";
|
||||
import { cacheDir, fileCheck } from "./utils";
|
||||
import { createCacheDir, exists } from "./io";
|
||||
|
||||
export async function downloadFile(filename, data, cancelToken) {
|
||||
if (!data) {
|
||||
DatabaseLogger.log(`Error downloading file: ${filename}, reason: No data`);
|
||||
return false;
|
||||
}
|
||||
if (!data) return false;
|
||||
|
||||
DatabaseLogger.log(`Downloading ${filename}`);
|
||||
console.log("Downloading", filename);
|
||||
await createCacheDir();
|
||||
let { url, headers } = data;
|
||||
let path = `${cacheDir}/${filename}`;
|
||||
|
||||
try {
|
||||
if (await exists(filename)) {
|
||||
DatabaseLogger.log(`File Exists already: ${filename}`);
|
||||
console.log("Exists already", filename);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -47,24 +44,13 @@ export async function downloadFile(filename, data, cancelToken) {
|
||||
method: "GET",
|
||||
headers
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
DatabaseLogger.log(
|
||||
`Error downloading file: ${filename}, ${res.status}, ${res.statusText}, reason: Unable to resolve download url`
|
||||
);
|
||||
if (!res.ok)
|
||||
throw new Error(`${res.status}: Unable to resolve download url`);
|
||||
}
|
||||
|
||||
const downloadUrl = await res.text();
|
||||
|
||||
if (!downloadUrl) {
|
||||
DatabaseLogger.log(
|
||||
`Error downloading file: ${filename}, reason: Unable to resolve download url`
|
||||
);
|
||||
throw new Error("Unable to resolve download url");
|
||||
}
|
||||
if (!downloadUrl) throw new Error("Unable to resolve download url");
|
||||
let totalSize = 0;
|
||||
DatabaseLogger.log(`Download starting: ${filename}`);
|
||||
console.log("Download starting");
|
||||
let request = RNFetchBlob.config({
|
||||
path: path,
|
||||
IOSBackgroundTask: true
|
||||
@@ -75,15 +61,13 @@ export async function downloadFile(filename, data, cancelToken) {
|
||||
.getState()
|
||||
.setProgress(0, total, filename, recieved, "download");
|
||||
totalSize = total;
|
||||
DatabaseLogger.log(`Downloading: ${filename}, ${recieved}/${total}`);
|
||||
console.log("downloading: ", recieved, total);
|
||||
});
|
||||
|
||||
cancelToken.cancel = () => {
|
||||
useAttachmentStore.getState().remove(filename);
|
||||
request.cancel();
|
||||
DatabaseLogger.log(`Download cancelled: ${filename}`);
|
||||
};
|
||||
|
||||
let response = await request;
|
||||
await fileCheck(response, totalSize);
|
||||
let status = response.info().status;
|
||||
@@ -107,10 +91,7 @@ export async function downloadFile(filename, data, cancelToken) {
|
||||
|
||||
useAttachmentStore.getState().remove(filename);
|
||||
RNFetchBlob.fs.unlink(path).catch(console.log);
|
||||
DatabaseLogger.error(e, {
|
||||
url,
|
||||
headers
|
||||
});
|
||||
console.log("Download file error:", e, url, headers);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -119,17 +100,18 @@ export async function getUploadedFileSize(hash) {
|
||||
try {
|
||||
const url = `${hosts.API_HOST}/s3?name=${hash}`;
|
||||
const token = await db.tokenManager.getAccessToken();
|
||||
|
||||
const attachmentInfo = await fetch(url, {
|
||||
method: "HEAD",
|
||||
headers: { Authorization: `Bearer ${token}` }
|
||||
});
|
||||
|
||||
const contentLength = parseInt(
|
||||
attachmentInfo.headers?.get("content-length")
|
||||
);
|
||||
return isNaN(contentLength) ? 0 : contentLength;
|
||||
} catch (e) {
|
||||
DatabaseLogger.error(e);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,9 +125,7 @@ export async function checkAttachment(hash) {
|
||||
|
||||
try {
|
||||
const size = await getUploadedFileSize(hash);
|
||||
if (size === -1) return { success: true };
|
||||
|
||||
if (size === 0) return { failed: "File length is 0." };
|
||||
if (size <= 0) return { failed: "File length is 0." };
|
||||
} catch (e) {
|
||||
return { failed: e?.message };
|
||||
}
|
||||
|
||||
@@ -21,12 +21,12 @@ import Sodium from "@ammarahmed/react-native-sodium";
|
||||
import { Platform } from "react-native";
|
||||
import RNFetchBlob from "react-native-blob-util";
|
||||
import { IOS_APPGROUPID } from "../../utils/constants";
|
||||
import { DatabaseLogger, db } from "../database";
|
||||
import { db } from "../database";
|
||||
import { cacheDir, cacheDirOld, getRandomId } from "./utils";
|
||||
|
||||
export async function readEncrypted(filename, key, cipherData) {
|
||||
await migrateFilesFromCache();
|
||||
DatabaseLogger.log("Read encrypted file...");
|
||||
console.log("Read encrypted file...");
|
||||
let path = `${cacheDir}/${filename}`;
|
||||
|
||||
try {
|
||||
@@ -34,6 +34,8 @@ export async function readEncrypted(filename, key, cipherData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const attachment = await db.attachments.attachment(filename);
|
||||
console.log("decrypting....");
|
||||
let output = await Sodium.decryptFile(
|
||||
key,
|
||||
{
|
||||
@@ -43,13 +45,12 @@ export async function readEncrypted(filename, key, cipherData) {
|
||||
},
|
||||
cipherData.outputType === "base64" ? "base64" : "text"
|
||||
);
|
||||
|
||||
DatabaseLogger.log("File decrypted...");
|
||||
console.log("file decrypted...", attachment?.mimeType);
|
||||
|
||||
return output;
|
||||
} catch (e) {
|
||||
RNFetchBlob.fs.unlink(path).catch(console.log);
|
||||
DatabaseLogger.error(e);
|
||||
console.log("readEncrypted", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -66,7 +67,7 @@ export async function hashBase64(data) {
|
||||
};
|
||||
}
|
||||
|
||||
export async function writeEncryptedBase64(data, key) {
|
||||
export async function writeEncryptedBase64({ data, key }) {
|
||||
await createCacheDir();
|
||||
let filepath = cacheDir + `/${getRandomId("imagecache_")}`;
|
||||
await RNFetchBlob.fs.writeFile(filepath, data, "base64");
|
||||
@@ -76,8 +77,6 @@ export async function writeEncryptedBase64(data, key) {
|
||||
});
|
||||
RNFetchBlob.fs.unlink(filepath).catch(console.log);
|
||||
console.log("encrypted file output: ", output);
|
||||
output.size = output.length;
|
||||
delete output.length;
|
||||
return {
|
||||
...output,
|
||||
alg: "xcha-stream"
|
||||
@@ -127,7 +126,7 @@ export async function clearFileStorage() {
|
||||
export async function createCacheDir() {
|
||||
if (!(await RNFetchBlob.fs.exists(cacheDir))) {
|
||||
await RNFetchBlob.fs.mkdir(cacheDir);
|
||||
DatabaseLogger.log("Cache directory created");
|
||||
console.log("Cache directory created");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,9 +186,6 @@ export async function exists(filename) {
|
||||
);
|
||||
|
||||
if (stat.size !== expectedFileSize) {
|
||||
DatabaseLogger.log(
|
||||
`File size mismatch: ${filename}, expected: ${expectedFileSize}, actual: ${stat.size}`
|
||||
);
|
||||
RNFetchBlob.fs
|
||||
.unlink(existsInAppGroup ? appGroupPath : path)
|
||||
.catch(console.log);
|
||||
|
||||
@@ -25,7 +25,6 @@ import { isImage, isDocument } from "@notesnook/core/dist/utils/filename";
|
||||
import { Platform } from "react-native";
|
||||
import { IOS_APPGROUPID } from "../../utils/constants";
|
||||
import { createCacheDir } from "./io";
|
||||
import { getUploadedFileSize } from "./download";
|
||||
|
||||
export async function uploadFile(filename, data, cancelToken) {
|
||||
if (!data) return false;
|
||||
@@ -34,18 +33,6 @@ export async function uploadFile(filename, data, cancelToken) {
|
||||
DatabaseLogger.info(`Preparing to upload file: ${filename}`);
|
||||
|
||||
try {
|
||||
const uploadedFileSize = await getUploadedFileSize(filename);
|
||||
if (uploadedFileSize === -1) {
|
||||
DatabaseLogger.log("Upload verification failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
const isUploaded = uploadedFileSize !== 0;
|
||||
if (isUploaded) {
|
||||
DatabaseLogger.log(`File ${filename} is already uploaded.`);
|
||||
return true;
|
||||
}
|
||||
|
||||
let res = await fetch(url, {
|
||||
method: "PUT",
|
||||
headers
|
||||
@@ -63,15 +50,7 @@ export async function uploadFile(filename, data, cancelToken) {
|
||||
let exists = await RNFetchBlob.fs.exists(uploadFilePath);
|
||||
if (!exists && Platform.OS === "ios") {
|
||||
uploadFilePath = appGroupPath;
|
||||
exists = await RNFetchBlob.fs.exists(uploadFilePath);
|
||||
}
|
||||
|
||||
if (!exists) {
|
||||
throw new Error(
|
||||
`Trying to upload file at path ${uploadFilePath} that doest not exist.`
|
||||
);
|
||||
}
|
||||
|
||||
DatabaseLogger.info(`Starting upload: ${filename}`);
|
||||
|
||||
let request = RNFetchBlob.config({
|
||||
|
||||
@@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import React, { useCallback, useEffect, useRef } from "react";
|
||||
import { AppStateStatus, Platform, TextInput, View } from "react-native";
|
||||
import { Platform, TextInput, View } from "react-native";
|
||||
//@ts-ignore
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import { enabled } from "react-native-privacy-snapshot";
|
||||
@@ -74,7 +74,6 @@ const verifyUserPassword = async (password: string) => {
|
||||
};
|
||||
|
||||
const AppLockedOverlay = () => {
|
||||
const initialLaunchBiometricRequest = useRef(true);
|
||||
const { colors } = useThemeColors();
|
||||
const user = getUser();
|
||||
const appLocked = useUserStore((state) => state.appLocked);
|
||||
@@ -83,7 +82,6 @@ const AppLockedOverlay = () => {
|
||||
const passwordInputRef = useRef<TextInput>(null);
|
||||
const password = useRef<string>();
|
||||
const appState = useAppState();
|
||||
const lastAppState = useRef<AppStateStatus>(appState);
|
||||
const biometricUnlockAwaitingUserInput = useRef(false);
|
||||
const keyboardType = useSettingStore(
|
||||
(state) => state.settings.applockKeyboardType
|
||||
@@ -133,8 +131,9 @@ const AppLockedOverlay = () => {
|
||||
if (!password.current) return;
|
||||
try {
|
||||
const unlocked = appLockHasPasswordSecurity
|
||||
? await validateAppLockPassword(password.current)
|
||||
? validateAppLockPassword(password.current)
|
||||
: await verifyUserPassword(password.current);
|
||||
|
||||
if (unlocked) {
|
||||
if (!appLockHasPasswordSecurity) {
|
||||
await setAppLockVerificationCipher(password.current);
|
||||
@@ -155,46 +154,18 @@ const AppLockedOverlay = () => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (appState === "active") {
|
||||
enabled(false);
|
||||
}
|
||||
|
||||
const prevState = lastAppState.current;
|
||||
lastAppState.current = appState;
|
||||
|
||||
if (
|
||||
biometricUnlockAwaitingUserInput.current ||
|
||||
useUserStore.getState().disableAppLockRequests
|
||||
)
|
||||
return;
|
||||
if (
|
||||
appLocked &&
|
||||
appState === "active" &&
|
||||
(prevState === "background" || initialLaunchBiometricRequest.current)
|
||||
!useSettingStore.getState().requestBiometrics
|
||||
) {
|
||||
if (SettingsService.shouldLockAppOnEnterForeground()) {
|
||||
DatabaseLogger.info("Locking app on entering foreground");
|
||||
useUserStore.getState().lockApp(true);
|
||||
}
|
||||
|
||||
if (
|
||||
!(
|
||||
biometricUnlockAwaitingUserInput.current ||
|
||||
useUserStore.getState().disableAppLockRequests ||
|
||||
!appLocked ||
|
||||
useSettingStore.getState().requestBiometrics ||
|
||||
useSettingStore.getState().appDidEnterBackgroundForAction
|
||||
)
|
||||
) {
|
||||
initialLaunchBiometricRequest.current = false;
|
||||
DatabaseLogger.info("Biometric unlock request");
|
||||
onUnlockAppRequested();
|
||||
}
|
||||
|
||||
enabled(false);
|
||||
} else {
|
||||
SettingsService.appEnteredBackground();
|
||||
|
||||
if (
|
||||
SettingsService.get().privacyScreen ||
|
||||
SettingsService.getProperty("appLockEnabled")
|
||||
) {
|
||||
enabled(true);
|
||||
}
|
||||
biometricUnlockAwaitingUserInput.current = true;
|
||||
onUnlockAppRequested();
|
||||
}
|
||||
}, [appState, onUnlockAppRequested, appLocked]);
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@ import Heading from "../ui/typography/heading";
|
||||
import Paragraph from "../ui/typography/paragraph";
|
||||
import { useTabStore } from "../../screens/editor/tiptap/use-tab-store";
|
||||
import { editorController } from "../../screens/editor/tiptap/utils";
|
||||
import SheetProvider from "../sheet-provider";
|
||||
|
||||
const Actions = ({
|
||||
attachment,
|
||||
@@ -219,11 +218,10 @@ const Actions = ({
|
||||
}}
|
||||
>
|
||||
<Dialog context={contextId} />
|
||||
<SheetProvider context={contextId} />
|
||||
<View
|
||||
style={{
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: colors.primary.border,
|
||||
borderBottomColor: colors.secondary.background,
|
||||
marginBottom: notes && notes.length > 0 ? 0 : 12
|
||||
}}
|
||||
>
|
||||
@@ -240,20 +238,36 @@ const Actions = ({
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
marginBottom: 10,
|
||||
paddingHorizontal: 12,
|
||||
marginTop: 6,
|
||||
gap: 10
|
||||
paddingHorizontal: 12
|
||||
}}
|
||||
>
|
||||
<Paragraph size={SIZE.xs} color={colors.secondary.paragraph}>
|
||||
{attachment.mimeType}
|
||||
<Paragraph
|
||||
size={SIZE.xs}
|
||||
style={{
|
||||
marginRight: 10
|
||||
}}
|
||||
color={colors.secondary.paragraph}
|
||||
>
|
||||
{attachment.type}
|
||||
</Paragraph>
|
||||
<Paragraph size={SIZE.xs} color={colors.secondary.paragraph}>
|
||||
<Paragraph
|
||||
style={{
|
||||
marginRight: 10
|
||||
}}
|
||||
size={SIZE.xs}
|
||||
color={colors.secondary.paragraph}
|
||||
>
|
||||
{formatBytes(attachment.size)}
|
||||
</Paragraph>
|
||||
|
||||
{notes.length ? (
|
||||
<Paragraph size={SIZE.xs} color={colors.secondary.paragraph}>
|
||||
<Paragraph
|
||||
style={{
|
||||
marginRight: 10
|
||||
}}
|
||||
size={SIZE.xs}
|
||||
color={colors.secondary.paragraph}
|
||||
>
|
||||
{notes.length} note
|
||||
{notes.length > 1 ? "s" : ""}
|
||||
</Paragraph>
|
||||
@@ -281,7 +295,7 @@ const Actions = ({
|
||||
<View
|
||||
style={{
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: colors.primary.border,
|
||||
borderBottomColor: colors.secondary.background,
|
||||
marginBottom: 12,
|
||||
paddingVertical: 12
|
||||
}}
|
||||
@@ -352,7 +366,7 @@ const Actions = ({
|
||||
{failed ? (
|
||||
<Notice
|
||||
type="alert"
|
||||
text={`File check failed: ${failed} Try reuploading the file to fix the issue.`}
|
||||
text={`File check failed with error: ${attachment.failed} Try reuploading the file to fix the issue.`}
|
||||
size="small"
|
||||
/>
|
||||
) : null}
|
||||
|
||||
@@ -177,7 +177,7 @@ export const AttachmentDialog = ({ note }: { note?: Note }) => {
|
||||
case "audio":
|
||||
items = note
|
||||
? db.attachments.ofNote(note.id, "audio")
|
||||
: db.attachments.audios;
|
||||
: db.attachments.all;
|
||||
break;
|
||||
case "documents":
|
||||
items = note
|
||||
|
||||
@@ -38,7 +38,6 @@ import { useSettingStore } from "../../stores/use-setting-store";
|
||||
import { eUserLoggedIn } from "../../utils/events";
|
||||
import { useUserStore } from "../../stores/use-user-store";
|
||||
import Sync from "../../services/sync";
|
||||
import { Notice } from "../ui/notice";
|
||||
|
||||
const LoginSteps = {
|
||||
emailAuth: 1,
|
||||
|
||||
@@ -87,9 +87,6 @@ export const SessionExpired = () => {
|
||||
MMKV.clearStore();
|
||||
clearAllStores();
|
||||
setVisible(false);
|
||||
useUserStore.setState({
|
||||
disableAppLockRequests: false
|
||||
});
|
||||
} catch (e) {
|
||||
ToastManager.show({
|
||||
heading: e.message,
|
||||
@@ -154,9 +151,6 @@ export const SessionExpired = () => {
|
||||
await sleep(300);
|
||||
passwordInputRef.current?.focus();
|
||||
setFocused(true);
|
||||
useUserStore.setState({
|
||||
disableAppLockRequests: true
|
||||
});
|
||||
}}
|
||||
enableSheetKeyboardHandler={true}
|
||||
visible={true}
|
||||
|
||||
@@ -18,7 +18,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import { useRoute } from "@react-navigation/native";
|
||||
import React, { useCallback, useEffect } from "react";
|
||||
import { Keyboard, View } from "react-native";
|
||||
import Animated, {
|
||||
@@ -55,7 +54,6 @@ const FloatingButton = ({
|
||||
const deviceMode = useSettingStore((state) => state.deviceMode);
|
||||
const selectionMode = useSelectionStore((state) => state.selectionMode);
|
||||
const translate = useSharedValue(0);
|
||||
const route = useRoute();
|
||||
|
||||
const animatedStyle = useAnimatedStyle(() => {
|
||||
return {
|
||||
@@ -142,13 +140,7 @@ const FloatingButton = ({
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
name={
|
||||
route.name === "Notebooks"
|
||||
? "notebook-plus"
|
||||
: route.name === "Trash"
|
||||
? "delete"
|
||||
: "plus"
|
||||
}
|
||||
name={title === "Clear all trash" ? "delete" : "plus"}
|
||||
color={colors.primary.accentForeground}
|
||||
size={SIZE.xxl}
|
||||
/>
|
||||
|
||||
@@ -21,16 +21,14 @@ import React, { PropsWithChildren, useEffect, useRef, useState } from "react";
|
||||
import { Dimensions, Platform, View, useWindowDimensions } from "react-native";
|
||||
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
|
||||
import useKeyboard from "../../hooks/use-keyboard";
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
|
||||
export const Container = ({ children }: PropsWithChildren) => {
|
||||
const { colors } = useThemeColors();
|
||||
const insets = useGlobalSafeAreaInsets();
|
||||
const keyboard = useKeyboard();
|
||||
const [height, setHeight] = useState(0);
|
||||
const windowHeightRef = useRef(Dimensions.get("window").height);
|
||||
const { height: windowHeight } = useWindowDimensions();
|
||||
const timerRef = useRef<NodeJS.Timeout>();
|
||||
|
||||
useEffect(() => {
|
||||
if (windowHeight !== windowHeightRef.current) {
|
||||
setHeight(0);
|
||||
@@ -45,17 +43,12 @@ export const Container = ({ children }: PropsWithChildren) => {
|
||||
paddingTop: Platform.OS === "android" ? 0 : insets.top,
|
||||
paddingBottom: Platform.OS === "android" ? 0 : insets.bottom,
|
||||
height: height || "100%",
|
||||
width: "100%",
|
||||
backgroundColor: colors.primary.background
|
||||
width: "100%"
|
||||
}}
|
||||
onLayout={(event) => {
|
||||
const height = event.nativeEvent.layout.height;
|
||||
clearTimeout(timerRef.current);
|
||||
timerRef.current = setTimeout(() => {
|
||||
if (!keyboard.keyboardShown) {
|
||||
setHeight(height);
|
||||
}
|
||||
}, 500);
|
||||
if (!keyboard.keyboardShown) {
|
||||
setHeight(event.nativeEvent.layout.height);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -45,8 +45,8 @@ const DialogButtons = ({
|
||||
{
|
||||
backgroundColor: colors.secondary.background,
|
||||
height: 60,
|
||||
borderBottomRightRadius: 5,
|
||||
borderBottomLeftRadius: 5,
|
||||
borderBottomRightRadius: 10,
|
||||
borderBottomLeftRadius: 10,
|
||||
paddingHorizontal: 12,
|
||||
borderTopWidth: 0.7,
|
||||
borderTopColor: getColorLinearShade(
|
||||
|
||||
@@ -36,7 +36,6 @@ import DialogButtons from "./dialog-buttons";
|
||||
import DialogHeader from "./dialog-header";
|
||||
import { useCallback } from "react";
|
||||
import { Button } from "../ui/button";
|
||||
import { getContainerBorder } from "../../utils/colors";
|
||||
|
||||
export const Dialog = ({ context = "global" }) => {
|
||||
const { colors } = useThemeColors();
|
||||
@@ -122,8 +121,7 @@ export const Dialog = ({ context = "global" }) => {
|
||||
maxHeight: 450,
|
||||
borderRadius: 5,
|
||||
backgroundColor: colors.primary.background,
|
||||
paddingTop: 12,
|
||||
...getContainerBorder(colors.primary.border, 0.5)
|
||||
paddingTop: 12
|
||||
};
|
||||
|
||||
return visible ? (
|
||||
|
||||
@@ -24,7 +24,7 @@ import {
|
||||
setAppLockVerificationCipher,
|
||||
validateAppLockPassword
|
||||
} from "../../../common/database/encryption";
|
||||
import BiometricService from "../../../services/biometrics";
|
||||
import BiometicService from "../../../services/biometrics";
|
||||
import { DDS } from "../../../services/device-detection";
|
||||
import {
|
||||
ToastManager,
|
||||
@@ -314,7 +314,6 @@ export const AppLockPassword = () => {
|
||||
new Error(
|
||||
`${keyboardType === "pin" ? "Pin" : "Password"} incorrect`
|
||||
),
|
||||
undefined,
|
||||
"local"
|
||||
);
|
||||
return;
|
||||
@@ -323,11 +322,10 @@ export const AppLockPassword = () => {
|
||||
SettingsService.setProperty("appLockHasPasswordSecurity", false);
|
||||
|
||||
if (
|
||||
!(await BiometricService.isBiometryAvailable()) ||
|
||||
!(await BiometicService.isBiometryAvailable()) ||
|
||||
SettingsService.getProperty("biometricsAuthEnabled") === false
|
||||
) {
|
||||
SettingsService.setProperty("appLockEnabled", false);
|
||||
SettingsService.setPrivacyScreen(SettingsService.get());
|
||||
ToastManager.show({
|
||||
message: "App lock disabled",
|
||||
type: "success"
|
||||
|
||||
@@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import React, { useState } from "react";
|
||||
import { Image, ScrollView, TouchableOpacity, View } from "react-native";
|
||||
import { Image as ImageType } from "react-native-image-crop-picker";
|
||||
import { ImagePickerResponse } from "react-native-image-picker";
|
||||
import { useThemeColors } from "../../../../../../packages/theme/dist";
|
||||
import { presentSheet } from "../../../services/event-manager";
|
||||
import { SIZE } from "../../../utils/size";
|
||||
@@ -32,7 +32,7 @@ export default function AttachImage({
|
||||
onAttach,
|
||||
close
|
||||
}: {
|
||||
response: ImageType[];
|
||||
response: ImagePickerResponse;
|
||||
onAttach: ({ compress }: { compress: boolean }) => void;
|
||||
close: ((ctx?: string | undefined) => void) | undefined;
|
||||
}) {
|
||||
@@ -58,14 +58,14 @@ export default function AttachImage({
|
||||
}}
|
||||
>
|
||||
<Paragraph style={{ color: colors.primary.paragraph, marginBottom: 6 }}>
|
||||
Attaching {response?.length} image(s):
|
||||
Attaching {response.assets?.length} image(s):
|
||||
</Paragraph>
|
||||
<ScrollView horizontal>
|
||||
{response?.map((item) => (
|
||||
<TouchableOpacity key={item.filename} activeOpacity={0.9}>
|
||||
{response.assets?.map((item) => (
|
||||
<TouchableOpacity key={item.fileName} activeOpacity={0.9}>
|
||||
<Image
|
||||
source={{
|
||||
uri: item.sourceURL || item.path
|
||||
uri: item.uri
|
||||
}}
|
||||
style={{
|
||||
width: 100,
|
||||
@@ -142,7 +142,7 @@ export default function AttachImage({
|
||||
|
||||
<Button
|
||||
title={`${
|
||||
(response?.length || 0) > 1 ? "Attach Images" : "Attach Image"
|
||||
(response.assets?.length || 0) > 1 ? "Attach Images" : "Attach Image"
|
||||
}`}
|
||||
type="accent"
|
||||
width="100%"
|
||||
@@ -156,16 +156,10 @@ export default function AttachImage({
|
||||
);
|
||||
}
|
||||
|
||||
AttachImage.present = (response: ImageType[], context?: string) => {
|
||||
return new Promise<
|
||||
| {
|
||||
compress: boolean;
|
||||
}
|
||||
| undefined
|
||||
>((resolve) => {
|
||||
AttachImage.present = (response: ImagePickerResponse) => {
|
||||
return new Promise((resolve) => {
|
||||
let resolved = false;
|
||||
presentSheet({
|
||||
context: context,
|
||||
component: (ref, close, update) => (
|
||||
<AttachImage
|
||||
response={response}
|
||||
|
||||
@@ -75,7 +75,7 @@ const ColorPicker = ({
|
||||
style={{
|
||||
width: "100%",
|
||||
height: 250,
|
||||
backgroundColor: colors.primary.background,
|
||||
backgroundColor: selectedColor,
|
||||
borderRadius: 10
|
||||
}}
|
||||
>
|
||||
@@ -146,16 +146,12 @@ const ColorPicker = ({
|
||||
onChangeText={(value) => {
|
||||
title.current = value;
|
||||
}}
|
||||
testID="color-title-input"
|
||||
defaultValue={title.current}
|
||||
placeholder={title.current || "Color title"}
|
||||
/>
|
||||
|
||||
<Button
|
||||
title="Add color"
|
||||
style={{
|
||||
marginBottom: 10
|
||||
}}
|
||||
onPress={async () => {
|
||||
if (!selectedColor)
|
||||
return ToastManager.error(
|
||||
@@ -174,6 +170,7 @@ const ColorPicker = ({
|
||||
return ToastManager.error(
|
||||
new Error(`Color #${selectedColor} already exists`)
|
||||
);
|
||||
|
||||
const id = await db.colors.add({
|
||||
title: title.current,
|
||||
colorCode: selectedColor
|
||||
|
||||
@@ -128,7 +128,7 @@ export class VaultDialog extends Component {
|
||||
: this.state.copyNote
|
||||
? "Unlock note to copy it. If biometrics are not working, you can enter device pin to unlock vault."
|
||||
: this.state.goToEditor
|
||||
? "Unlock note to open it in editor."
|
||||
? "Unlock note to open it in editor. If biometrics are not working, you can enter device pin to unlock vault."
|
||||
: "Enter vault password to unlock note. If biometrics are not working, you can enter device pin to unlock vault."
|
||||
: "Enter vault password to lock note. If biometrics are not working, you can enter device pin to lock note.");
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ import { eScrollEvent } from "../../utils/events";
|
||||
import { LeftMenus } from "./left-menus";
|
||||
import { RightMenus } from "./right-menus";
|
||||
import { Title } from "./title";
|
||||
import { useNavigation } from "@react-navigation/native";
|
||||
|
||||
type HeaderRightButton = {
|
||||
title: string;
|
||||
@@ -67,8 +66,6 @@ export const Header = ({
|
||||
hasSearch?: boolean;
|
||||
onSearch?: () => void;
|
||||
}) => {
|
||||
const navigation = useNavigation();
|
||||
|
||||
const { colors } = useThemeColors();
|
||||
const insets = useGlobalSafeAreaInsets();
|
||||
const [borderHidden, setBorderHidden] = useState(true);
|
||||
|
||||
@@ -71,7 +71,7 @@ export const RightMenus = ({
|
||||
testID={notesnook.ids.default.addBtn}
|
||||
icon={renderedInRoute === "Trash" ? "delete" : "plus"}
|
||||
iconSize={SIZE.xl}
|
||||
type="accent"
|
||||
type="shade"
|
||||
hitSlop={{
|
||||
top: 10,
|
||||
right: 10,
|
||||
@@ -82,7 +82,7 @@ export const RightMenus = ({
|
||||
marginLeft: 10,
|
||||
width: 32,
|
||||
height: 32,
|
||||
borderRadius: 100,
|
||||
borderRadius: 5,
|
||||
paddingHorizontal: 0,
|
||||
borderWidth: 1,
|
||||
borderColor: colors.primary.accent
|
||||
|
||||
@@ -19,12 +19,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import Sodium from "@ammarahmed/react-native-sodium";
|
||||
import dataurl from "@notesnook/core/dist/utils/dataurl";
|
||||
import type { ImageAttributes } from "@notesnook/editor/dist/extensions/image/index";
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Platform, View } from "react-native";
|
||||
import ImageViewer from "react-native-image-zoom-viewer";
|
||||
import { db } from "../../common/database";
|
||||
import downloadAttachment from "../../common/filesystem/download-attachment";
|
||||
import { cacheDir } from "../../common/filesystem/utils";
|
||||
import {
|
||||
@@ -34,13 +32,13 @@ import {
|
||||
import BaseDialog from "../dialog/base-dialog";
|
||||
import { IconButton } from "../ui/icon-button";
|
||||
import { ProgressBarComponent } from "../ui/svg/lazy";
|
||||
import type { ImageAttributes } from "@notesnook/editor/dist/extensions/image/index";
|
||||
const ImagePreview = () => {
|
||||
const { colors } = useThemeColors("dialog");
|
||||
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [image, setImage] = useState<string>();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const imageRef = useRef<ImageAttributes>();
|
||||
|
||||
useEffect(() => {
|
||||
eSubscribeEvent("ImagePreview", open);
|
||||
@@ -50,7 +48,6 @@ const ImagePreview = () => {
|
||||
}, []);
|
||||
|
||||
const open = async (image: ImageAttributes) => {
|
||||
imageRef.current = image;
|
||||
setVisible(true);
|
||||
setLoading(true);
|
||||
setTimeout(async () => {
|
||||
@@ -63,9 +60,6 @@ const ImagePreview = () => {
|
||||
type: "base64",
|
||||
uri: ""
|
||||
});
|
||||
if (imageRef.current) {
|
||||
imageRef.current.hash = hash;
|
||||
}
|
||||
}
|
||||
if (!hash) return;
|
||||
//@ts-ignore // FIX ME
|
||||
@@ -86,13 +80,7 @@ const ImagePreview = () => {
|
||||
|
||||
return (
|
||||
visible && (
|
||||
<BaseDialog
|
||||
background="black"
|
||||
animation="slide"
|
||||
visible={true}
|
||||
onRequestClose={close}
|
||||
transparent
|
||||
>
|
||||
<BaseDialog animation="slide" visible={true} onRequestClose={close}>
|
||||
<View
|
||||
style={{
|
||||
width: "100%",
|
||||
@@ -113,21 +101,6 @@ const ImagePreview = () => {
|
||||
color={colors.primary.accent}
|
||||
borderColor="transparent"
|
||||
/>
|
||||
<IconButton
|
||||
onPress={() => {
|
||||
if (imageRef.current?.hash) {
|
||||
db.fs().cancel(imageRef.current?.hash);
|
||||
}
|
||||
close();
|
||||
}}
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: Platform.OS === "android" ? 35 : 0,
|
||||
right: 12
|
||||
}}
|
||||
color={colors.static.white}
|
||||
name="close"
|
||||
/>
|
||||
</View>
|
||||
) : (
|
||||
<ImageViewer
|
||||
@@ -144,12 +117,13 @@ const ImagePreview = () => {
|
||||
width: "100%",
|
||||
justifyContent: "flex-end",
|
||||
alignItems: "center",
|
||||
height: 50,
|
||||
paddingHorizontal: 24,
|
||||
height: 80,
|
||||
marginTop: 0,
|
||||
paddingHorizontal: 12,
|
||||
position: "absolute",
|
||||
zIndex: 999,
|
||||
backgroundColor: "rgba(0,0,0,0.3)",
|
||||
marginTop: Platform.OS === "android" ? 30 : 0
|
||||
paddingTop: Platform.OS === "android" ? 30 : 0
|
||||
}}
|
||||
>
|
||||
<IconButton
|
||||
@@ -163,7 +137,7 @@ const ImagePreview = () => {
|
||||
)}
|
||||
imageUrls={[
|
||||
{
|
||||
url: image as string
|
||||
url: image
|
||||
}
|
||||
]}
|
||||
/>
|
||||
|
||||
@@ -19,6 +19,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { View } from "react-native";
|
||||
import React from "react";
|
||||
export const Footer = ({ height = 150 }) => {
|
||||
return <View style={{ height: height }} />;
|
||||
export const Footer = () => {
|
||||
return <View style={{ height: 150 }} />;
|
||||
};
|
||||
|
||||
@@ -95,7 +95,7 @@ export const NotebookHeader = ({
|
||||
style={{
|
||||
flexShrink: 1
|
||||
}}
|
||||
size={SIZE.lg}
|
||||
size={SIZE.xxl}
|
||||
>
|
||||
{notebook.title}
|
||||
</Heading>
|
||||
@@ -114,7 +114,7 @@ export const NotebookHeader = ({
|
||||
width: 40,
|
||||
height: 40
|
||||
}}
|
||||
type="transparent"
|
||||
type={isPinnedToMenu ? "secondary" : "secondary"}
|
||||
color={isPinnedToMenu ? colors.primary.accent : colors.primary.icon}
|
||||
size={SIZE.lg}
|
||||
/>
|
||||
@@ -123,7 +123,7 @@ export const NotebookHeader = ({
|
||||
onPress={onEditNotebook}
|
||||
tooltipText="Edit this notebook"
|
||||
name="pencil"
|
||||
type="transparent"
|
||||
type="secondary"
|
||||
color={colors.primary.icon}
|
||||
style={{
|
||||
width: 40,
|
||||
@@ -134,7 +134,7 @@ export const NotebookHeader = ({
|
||||
</View>
|
||||
|
||||
{notebook.description ? (
|
||||
<Paragraph size={SIZE.sm} color={colors.primary.paragraph}>
|
||||
<Paragraph size={SIZE.md} color={colors.primary.paragraph}>
|
||||
{notebook.description}
|
||||
</Paragraph>
|
||||
) : null}
|
||||
@@ -148,6 +148,10 @@ export const NotebookHeader = ({
|
||||
size={SIZE.xs}
|
||||
color={colors.secondary.paragraph}
|
||||
>
|
||||
{/* {notebook.topics.length === 1
|
||||
? "1 topic"
|
||||
: `${notebook.topics.length} topics`}
|
||||
,{" "} */}
|
||||
{notebook && totalNotes > 1
|
||||
? totalNotes + " notes"
|
||||
: totalNotes === 1
|
||||
|
||||
@@ -25,7 +25,7 @@ import { useIsCompactModeEnabled } from "../../../hooks/use-is-compact-mode-enab
|
||||
import { presentSheet } from "../../../services/event-manager";
|
||||
import SettingsService from "../../../services/settings";
|
||||
import { RouteName } from "../../../stores/use-navigation-store";
|
||||
import { getContainerBorder } from "../../../utils/colors";
|
||||
import { ColorValues, getContainerBorder } from "../../../utils/colors";
|
||||
import { GROUP } from "../../../utils/constants";
|
||||
import { SIZE } from "../../../utils/size";
|
||||
import Sort from "../../sheets/sort";
|
||||
@@ -96,9 +96,13 @@ export const SectionHeader = React.memo<
|
||||
}}
|
||||
>
|
||||
<Heading
|
||||
color={color || colors.primary.accent}
|
||||
color={
|
||||
ColorValues[color?.toLowerCase() as keyof typeof ColorValues] ||
|
||||
colors.primary.accent
|
||||
}
|
||||
size={SIZE.sm}
|
||||
style={{
|
||||
minWidth: 60,
|
||||
alignSelf: "center",
|
||||
textAlignVertical: "center"
|
||||
}}
|
||||
|
||||
@@ -211,31 +211,6 @@ const NoteItem = ({
|
||||
color={colors.error.accent}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{item.localOnly ? (
|
||||
<Icon
|
||||
testID="sync-off"
|
||||
name="sync-off"
|
||||
size={SIZE.sm}
|
||||
style={{
|
||||
marginRight: 6
|
||||
}}
|
||||
color={primaryColors.icon}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{item.readonly ? (
|
||||
<Icon
|
||||
testID="pencil-lock"
|
||||
name="pencil-lock"
|
||||
size={SIZE.sm}
|
||||
style={{
|
||||
marginRight: 6
|
||||
}}
|
||||
color={primaryColors.icon}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
<TimeSince
|
||||
style={{
|
||||
fontSize: SIZE.xs,
|
||||
@@ -251,13 +226,12 @@ const NoteItem = ({
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
marginRight: 6,
|
||||
gap: 2
|
||||
marginRight: 6
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
name="attachment"
|
||||
size={SIZE.sm}
|
||||
size={SIZE.md}
|
||||
color={primaryColors.icon}
|
||||
/>
|
||||
<Paragraph
|
||||
@@ -297,7 +271,7 @@ const NoteItem = ({
|
||||
<Icon
|
||||
testID="icon-star"
|
||||
name="star-outline"
|
||||
size={SIZE.sm}
|
||||
size={SIZE.md}
|
||||
style={{
|
||||
marginRight: 6
|
||||
}}
|
||||
@@ -314,8 +288,7 @@ const NoteItem = ({
|
||||
height={23}
|
||||
type="plain"
|
||||
textStyle={{
|
||||
textDecorationLine: "underline",
|
||||
color: colors.secondary.paragraph
|
||||
textDecorationLine: "underline"
|
||||
}}
|
||||
hitSlop={{ top: 8, bottom: 12, left: 0, right: 0 }}
|
||||
fontSize={SIZE.xs}
|
||||
@@ -397,7 +370,7 @@ const NoteItem = ({
|
||||
<Icon
|
||||
testID="icon-star"
|
||||
name="star-outline"
|
||||
size={SIZE.sm}
|
||||
size={SIZE.md}
|
||||
style={{
|
||||
marginRight: 6
|
||||
}}
|
||||
|
||||
@@ -28,12 +28,13 @@ import {
|
||||
hideSheet,
|
||||
presentSheet
|
||||
} from "../../../services/event-manager";
|
||||
import { useSelectionStore } from "../../../stores/use-selection-store";
|
||||
import { eOnLoadNote, eShowMergeDialog } from "../../../utils/events";
|
||||
import { tabBarRef } from "../../../utils/global-refs";
|
||||
|
||||
import { NotebooksWithDateEdited, TagsWithDateEdited } from "@notesnook/common";
|
||||
import NotePreview from "../../note-history/preview";
|
||||
import SelectionWrapper, { selectItem } from "../selection-wrapper";
|
||||
import SelectionWrapper from "../selection-wrapper";
|
||||
|
||||
export const openNote = async (
|
||||
item: Note,
|
||||
@@ -46,8 +47,21 @@ export const openNote = async (
|
||||
if (!isTrash) {
|
||||
note = (await db.notes.note(item.id)) as Note;
|
||||
}
|
||||
if (useSelectionStore.getState().selectionMode === item.type) {
|
||||
const {
|
||||
selectedItemsList,
|
||||
selectionMode,
|
||||
clearSelection,
|
||||
setSelectedItem
|
||||
} = useSelectionStore.getState();
|
||||
|
||||
if (selectItem(item)) return;
|
||||
if (selectedItemsList.length > 0 && selectionMode === item.type) {
|
||||
setSelectedItem(note.id);
|
||||
} else {
|
||||
clearSelection();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (note.conflicted) {
|
||||
eSendEvent(eShowMergeDialog, note);
|
||||
|
||||
@@ -27,12 +27,18 @@ import Navigation from "../../../services/navigation";
|
||||
import { useSelectionStore } from "../../../stores/use-selection-store";
|
||||
import { useTrashStore } from "../../../stores/use-trash-store";
|
||||
import { presentDialog } from "../../dialog/functions";
|
||||
import SelectionWrapper, { selectItem } from "../selection-wrapper";
|
||||
import SelectionWrapper from "../selection-wrapper";
|
||||
|
||||
export const openNotebook = (item: Notebook | BaseTrashItem<Notebook>) => {
|
||||
const isTrash = item.type === "trash";
|
||||
|
||||
if (selectItem(item)) return;
|
||||
const { selectedItemsList, setSelectedItem, selectionMode, clearSelection } =
|
||||
useSelectionStore.getState();
|
||||
if (selectedItemsList.length > 0 && selectionMode === item.type) {
|
||||
setSelectedItem(item.id);
|
||||
return;
|
||||
} else {
|
||||
clearSelection();
|
||||
}
|
||||
|
||||
if (isTrash) {
|
||||
presentDialog({
|
||||
|
||||
@@ -22,6 +22,7 @@ import React from "react";
|
||||
import { View } from "react-native";
|
||||
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||
import { notesnook } from "../../../../e2e/test.ids";
|
||||
import { useSelectionStore } from "../../../stores/use-selection-store";
|
||||
import { SIZE } from "../../../utils/size";
|
||||
import { Properties } from "../../properties";
|
||||
import ReminderSheet from "../../sheets/reminder";
|
||||
@@ -29,7 +30,7 @@ import { IconButton } from "../../ui/icon-button";
|
||||
import { ReminderTime } from "../../ui/reminder-time";
|
||||
import Heading from "../../ui/typography/heading";
|
||||
import Paragraph from "../../ui/typography/paragraph";
|
||||
import SelectionWrapper, { selectItem } from "../selection-wrapper";
|
||||
import SelectionWrapper from "../selection-wrapper";
|
||||
|
||||
const ReminderItem = React.memo(
|
||||
({
|
||||
@@ -43,7 +44,18 @@ const ReminderItem = React.memo(
|
||||
}) => {
|
||||
const { colors } = useThemeColors();
|
||||
const openReminder = () => {
|
||||
if (selectItem(item)) return;
|
||||
const {
|
||||
selectedItemsList,
|
||||
setSelectedItem,
|
||||
selectionMode,
|
||||
clearSelection
|
||||
} = useSelectionStore.getState();
|
||||
if (selectedItemsList.length > 0 && selectionMode === item.type) {
|
||||
setSelectedItem(item.id);
|
||||
return;
|
||||
} else {
|
||||
clearSelection();
|
||||
}
|
||||
|
||||
ReminderSheet.present(item, undefined, isSheet);
|
||||
};
|
||||
|
||||
@@ -26,23 +26,6 @@ import { Filler } from "./back-fill";
|
||||
import { SelectionIcon } from "./selection";
|
||||
import { Item, TrashItem } from "@notesnook/core";
|
||||
|
||||
export function selectItem(item: Item) {
|
||||
if (useSelectionStore.getState().selectionMode === item.type) {
|
||||
const { selectionMode, clearSelection, setSelectedItem } =
|
||||
useSelectionStore.getState();
|
||||
|
||||
if (selectionMode === item.type) {
|
||||
setSelectedItem(item.id);
|
||||
}
|
||||
|
||||
if (useSelectionStore.getState().selectedItemsList.length === 0) {
|
||||
clearSelection();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
type SelectionWrapperProps = PropsWithChildren<{
|
||||
item: Item;
|
||||
onPress: () => void;
|
||||
|
||||
@@ -23,12 +23,13 @@ import React from "react";
|
||||
import { View } from "react-native";
|
||||
import { notesnook } from "../../../../e2e/test.ids";
|
||||
import { TaggedNotes } from "../../../screens/notes/tagged";
|
||||
import { useSelectionStore } from "../../../stores/use-selection-store";
|
||||
import { SIZE } from "../../../utils/size";
|
||||
import { Properties } from "../../properties";
|
||||
import { IconButton } from "../../ui/icon-button";
|
||||
import Heading from "../../ui/typography/heading";
|
||||
import Paragraph from "../../ui/typography/paragraph";
|
||||
import SelectionWrapper, { selectItem } from "../selection-wrapper";
|
||||
import SelectionWrapper from "../selection-wrapper";
|
||||
|
||||
const TagItem = React.memo(
|
||||
({
|
||||
@@ -42,7 +43,18 @@ const TagItem = React.memo(
|
||||
}) => {
|
||||
const { colors } = useThemeColors();
|
||||
const onPress = () => {
|
||||
if (selectItem(item)) return;
|
||||
const {
|
||||
selectedItemsList,
|
||||
setSelectedItem,
|
||||
selectionMode,
|
||||
clearSelection
|
||||
} = useSelectionStore.getState();
|
||||
if (selectedItemsList.length > 0 && selectionMode === item.type) {
|
||||
setSelectedItem(item.id);
|
||||
return;
|
||||
} else {
|
||||
clearSelection();
|
||||
}
|
||||
|
||||
TaggedNotes.navigate(item, true);
|
||||
};
|
||||
|
||||
@@ -192,9 +192,7 @@ export default function List(props: ListProps) {
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
ListFooterComponent={
|
||||
<Footer height={props.renderedInRoute === "Notebook" ? 300 : 150} />
|
||||
}
|
||||
ListFooterComponent={<Footer />}
|
||||
ListHeaderComponent={
|
||||
<>
|
||||
{props.CustomLisHeader ? (
|
||||
|
||||
@@ -48,7 +48,6 @@ import { NoteWrapper } from "../list-items/note/wrapper";
|
||||
import { NotebookWrapper } from "../list-items/notebook/wrapper";
|
||||
import ReminderItem from "../list-items/reminder";
|
||||
import TagItem from "../list-items/tag";
|
||||
import { useIsCompactModeEnabled } from "../../hooks/use-is-compact-mode-enabled";
|
||||
|
||||
type ListItemWrapperProps<TItem = Item> = {
|
||||
group?: GroupingKey;
|
||||
@@ -76,7 +75,6 @@ export function ListItemWrapper(props: ListItemWrapperProps) {
|
||||
const refreshTimeout = useRef<NodeJS.Timeout>();
|
||||
const currentItemId = useRef<string>();
|
||||
const locked = useRef(false);
|
||||
const compactMode = useIsCompactModeEnabled(props.dataType as ItemType);
|
||||
|
||||
const refreshItem = useCallback((resolvedItem: any) => {
|
||||
if (!resolvedItem || !resolvedItem.data) {
|
||||
@@ -119,24 +117,14 @@ export function ListItemWrapper(props: ListItemWrapperProps) {
|
||||
}
|
||||
currentItemId.current = resolvedItem.item.id;
|
||||
setItem(resolvedItem.item);
|
||||
}
|
||||
|
||||
if (resolvedItem?.group) {
|
||||
setGroupHeader(resolvedItem.group);
|
||||
} else {
|
||||
setGroupHeader(undefined);
|
||||
}
|
||||
}, []);
|
||||
|
||||
if (previousIndex.current !== index) {
|
||||
previousIndex.current = index;
|
||||
const resolvedItem = items?.cacheItem(index);
|
||||
if (resolvedItem) {
|
||||
refreshItem(resolvedItem);
|
||||
} else {
|
||||
setItem(undefined);
|
||||
setGroupHeader(undefined);
|
||||
}
|
||||
refreshItem(resolvedItem);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
@@ -144,15 +132,12 @@ export function ListItemWrapper(props: ListItemWrapperProps) {
|
||||
try {
|
||||
clearTimeout(refreshTimeout.current);
|
||||
const idx = index;
|
||||
refreshTimeout.current = setTimeout(
|
||||
async () => {
|
||||
if (idx !== previousIndex.current) return;
|
||||
const resolvedItem = await items?.item(idx, resolveItems);
|
||||
if (idx !== previousIndex.current) return;
|
||||
refreshItem(resolvedItem);
|
||||
},
|
||||
items?.cacheItem(index) ? 100 : 0
|
||||
);
|
||||
refreshTimeout.current = setTimeout(async () => {
|
||||
if (idx !== previousIndex.current) return;
|
||||
const resolvedItem = await items?.item(idx, resolveItems);
|
||||
if (idx !== previousIndex.current) return;
|
||||
refreshItem(resolvedItem);
|
||||
}, 100);
|
||||
} catch (e) {
|
||||
console.log("Error", e);
|
||||
}
|
||||
@@ -163,7 +148,7 @@ export function ListItemWrapper(props: ListItemWrapperProps) {
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
height: compactMode ? 50 : 120,
|
||||
height: 120,
|
||||
width: "100%"
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -23,9 +23,9 @@ import { FlatList, StyleSheet, View } from "react-native";
|
||||
import {
|
||||
DraxList,
|
||||
DraxListProps,
|
||||
DraxListRenderItemContent
|
||||
DraxListRenderItemContent,
|
||||
DraxProvider
|
||||
} from "react-native-drax";
|
||||
|
||||
import { tabBarRef } from "../../utils/global-refs";
|
||||
import { SIZE } from "../../utils/size";
|
||||
import { useSideBarDraggingStore } from "../side-menu/dragging-store";
|
||||
@@ -74,7 +74,6 @@ function ReorderableList<T extends { id: string }>({
|
||||
const renderItemContent: DraxListRenderItemContent<T> = React.useCallback(
|
||||
(info, props) => {
|
||||
const isHidden = hiddenItemsState.indexOf(info?.item?.id) > -1;
|
||||
|
||||
return isHidden && !dragging ? null : (
|
||||
<View
|
||||
style={{
|
||||
@@ -137,49 +136,53 @@ function ReorderableList<T extends { id: string }>({
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<DraxList
|
||||
{...restProps}
|
||||
ref={listRef}
|
||||
data={getOrderedItems()}
|
||||
renderItemContent={renderItemContent}
|
||||
itemStyles={{
|
||||
hoverDragReleasedStyle: {
|
||||
display: "none"
|
||||
},
|
||||
hoverDraggingWithoutReceiverStyle: {
|
||||
opacity: 0.5
|
||||
},
|
||||
dragReleasedStyle: {
|
||||
opacity: 1
|
||||
},
|
||||
hoverDraggingStyle: {
|
||||
backgroundColor: colors.secondary.background
|
||||
<DraxProvider>
|
||||
<View style={styles.container}>
|
||||
<DraxList
|
||||
{...restProps}
|
||||
ref={listRef}
|
||||
data={getOrderedItems()}
|
||||
renderItemContent={renderItemContent}
|
||||
itemStyles={{
|
||||
hoverDragReleasedStyle: {
|
||||
display: "none"
|
||||
},
|
||||
hoverDraggingWithoutReceiverStyle: {
|
||||
opacity: 0.5
|
||||
},
|
||||
dragReleasedStyle: {
|
||||
opacity: 1
|
||||
},
|
||||
hoverDraggingStyle: {
|
||||
backgroundColor: colors.secondary.background
|
||||
}
|
||||
}}
|
||||
longPressDelay={500}
|
||||
onItemDragStart={() =>
|
||||
useSideBarDraggingStore.setState({
|
||||
dragging: true
|
||||
})
|
||||
}
|
||||
}}
|
||||
longPressDelay={500}
|
||||
onItemDragStart={() =>
|
||||
useSideBarDraggingStore.setState({
|
||||
dragging: true
|
||||
})
|
||||
}
|
||||
disableVirtualization
|
||||
itemsDraggable={disableDefaultDrag ? dragging : true}
|
||||
lockItemDragsToMainAxis
|
||||
onItemReorder={({ fromIndex, fromItem, toIndex, toItem }) => {
|
||||
const newOrder = getOrderedItems().map((item) => item.id);
|
||||
const element = newOrder.splice(fromIndex, 1)[0];
|
||||
if (toIndex === 0) {
|
||||
newOrder.unshift(element);
|
||||
} else {
|
||||
newOrder.splice(toIndex, 0, element);
|
||||
}
|
||||
setItemsOrder(newOrder);
|
||||
onListOrderChanged?.(newOrder);
|
||||
}}
|
||||
keyExtractor={(item) => (item as any).id}
|
||||
/>
|
||||
</View>
|
||||
itemsDraggable={disableDefaultDrag ? dragging : true}
|
||||
lockItemDragsToMainAxis
|
||||
onItemReorder={({ fromIndex, fromItem, toIndex, toItem }) => {
|
||||
const newOrder = getOrderedItems().map((item) => item.id);
|
||||
const element = newOrder.splice(fromIndex, 1)[0];
|
||||
if (toIndex === 0) {
|
||||
newOrder.unshift(element);
|
||||
} else {
|
||||
newOrder.splice(toIndex, 0, element);
|
||||
}
|
||||
setItemsOrder(newOrder);
|
||||
onListOrderChanged?.(newOrder);
|
||||
}}
|
||||
onItemDragEnd={(e) => {
|
||||
console.log(e.receiver?.receiveOffset);
|
||||
}}
|
||||
keyExtractor={(item) => (item as any).id}
|
||||
/>
|
||||
</View>
|
||||
</DraxProvider>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -313,7 +313,7 @@ const MergeConflicts = () => {
|
||||
height: height / 2 - (50 + insets.top / 2),
|
||||
backgroundColor: colors.primary.background,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: colors.primary.border
|
||||
borderBottomColor: colors.secondary.background
|
||||
}}
|
||||
>
|
||||
<ReadonlyEditor
|
||||
|
||||
@@ -199,9 +199,7 @@ export default function NoteHistory({
|
||||
Note version history is local only.{" "}
|
||||
<Text
|
||||
onPress={() => {
|
||||
openLinkInBrowser(
|
||||
"https://help.notesnook.com/note-version-history"
|
||||
);
|
||||
openLinkInBrowser("https://docs.notesnook.com/versionhistory");
|
||||
}}
|
||||
style={{
|
||||
color: colors.primary.accent,
|
||||
|
||||
@@ -162,7 +162,7 @@ export const features = [
|
||||
platform: "android"
|
||||
}
|
||||
],
|
||||
info: "* Free users are limited to keeping 3 notebooks and 5 tags."
|
||||
info: "* Free users are limited to keeping 3 notebooks (no limit on topics) and 5 tags."
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
@@ -111,7 +111,6 @@ export const ColorTags = ({ item }: { item: Note }) => {
|
||||
visible={visible}
|
||||
setVisible={setVisible}
|
||||
onColorAdded={async (color) => {
|
||||
await db.relations.to(note, "color").unlink();
|
||||
await db.relations.add(color, note);
|
||||
useRelationStore.getState().update();
|
||||
useMenuStore.getState().setColorNotes();
|
||||
|
||||
@@ -242,6 +242,7 @@ Properties.present = async (item, buttons = [], isSheet) => {
|
||||
"attachments",
|
||||
"lock-unlock",
|
||||
"trash",
|
||||
"remove-from-topic",
|
||||
"remove-from-notebook",
|
||||
"history",
|
||||
"read-only",
|
||||
@@ -263,8 +264,7 @@ Properties.present = async (item, buttons = [], isSheet) => {
|
||||
"trash",
|
||||
"default-notebook",
|
||||
"add-notebook",
|
||||
"move-notes",
|
||||
"move-notebook"
|
||||
"move-notes"
|
||||
]);
|
||||
break;
|
||||
case "tag":
|
||||
|
||||
@@ -73,7 +73,7 @@ export const Items = ({ item, buttons, close }) => {
|
||||
<Icon
|
||||
allowFontScaling
|
||||
name={item.icon}
|
||||
size={DDS.isTab ? SIZE.xxl : shouldShrink ? SIZE.xxl : SIZE.lg}
|
||||
size={DDS.isTab ? SIZE.xxl : SIZE.lg}
|
||||
color={
|
||||
item.on
|
||||
? colors.primary.accent
|
||||
@@ -241,8 +241,8 @@ export const Items = ({ item, buttons, close }) => {
|
||||
}}
|
||||
showsHorizontalScrollIndicator={false}
|
||||
contentContainerStyle={{
|
||||
paddingRight: 25,
|
||||
gap: 5
|
||||
gap: 10,
|
||||
paddingRight: 25
|
||||
}}
|
||||
>
|
||||
{topBarItems.map(renderTopBarItem)}
|
||||
|
||||
@@ -48,7 +48,7 @@ export const Synced = ({ item, close }) => {
|
||||
paddingTop: 10,
|
||||
marginTop: 10,
|
||||
borderTopWidth: 1,
|
||||
borderTopColor: colors.primary.border
|
||||
borderTopColor: colors.secondary.background
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
@@ -92,7 +92,7 @@ export const Synced = ({ item, close }) => {
|
||||
close();
|
||||
await sleep(300);
|
||||
await openLinkInBrowser(
|
||||
"https://help.notesnook.com/how-is-my-data-encrypted",
|
||||
"https://docs.notesnook.com/how-is-my-data-encrypted/",
|
||||
colors
|
||||
);
|
||||
} catch (e) {
|
||||
|
||||
@@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import React, { useEffect, useState } from "react";
|
||||
import React from "react";
|
||||
import { View } from "react-native";
|
||||
import { db } from "../../common/database";
|
||||
import { TaggedNotes } from "../../screens/notes/tagged";
|
||||
@@ -68,38 +68,26 @@ export const Tags = ({ item, close }) => {
|
||||
};
|
||||
|
||||
export const TagStrip = ({ item, close }) => {
|
||||
const [tags, setTags] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
db.relations
|
||||
.to(item, "tag")
|
||||
.resolve()
|
||||
.then((tags) => {
|
||||
setTags(tags);
|
||||
});
|
||||
});
|
||||
|
||||
return tags?.length > 0 ? (
|
||||
return item.tags?.length > 0 ? (
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
flexWrap: "wrap",
|
||||
alignItems: "center",
|
||||
marginTop: 10,
|
||||
gap: 5
|
||||
alignItems: "center"
|
||||
}}
|
||||
>
|
||||
{tags?.map((tag) =>
|
||||
tag ? <TagItem key={tag.id} tag={tag} close={close} /> : null
|
||||
{item.tags.map((tag) =>
|
||||
tag ? <TagItem key={tag} tag={tag} close={close} /> : null
|
||||
)}
|
||||
</View>
|
||||
) : null;
|
||||
};
|
||||
|
||||
const TagItem = ({ tag, close }) => {
|
||||
const { colors } = useThemeColors();
|
||||
const onPress = async () => {
|
||||
TaggedNotes.navigate(tag, true);
|
||||
let tags = db.tags.all;
|
||||
let _tag = tags.find((t) => t.title === tag);
|
||||
TaggedNotes.navigate(_tag, true);
|
||||
await sleep(300);
|
||||
close();
|
||||
};
|
||||
@@ -107,19 +95,20 @@ const TagItem = ({ tag, close }) => {
|
||||
const style = {
|
||||
paddingHorizontal: 0,
|
||||
borderRadius: 100,
|
||||
marginRight: 10,
|
||||
marginTop: 0,
|
||||
backgroundColor: "transparent"
|
||||
};
|
||||
return (
|
||||
<Button
|
||||
onPress={onPress}
|
||||
title={"#" + tag.title}
|
||||
type="plain"
|
||||
title={"#" + tag}
|
||||
type="secondary"
|
||||
height={20}
|
||||
fontSize={SIZE.xs}
|
||||
style={style}
|
||||
textStyle={{
|
||||
color: colors.secondary.paragraph
|
||||
textDecorationLine: "underline"
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -19,14 +19,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { Item, ItemType, VirtualizedGrouping } from "@notesnook/core";
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import {
|
||||
BackHandler,
|
||||
NativeEventSubscription,
|
||||
Platform,
|
||||
View
|
||||
} from "react-native";
|
||||
import Menu from "react-native-reanimated-material-menu/src/Menu";
|
||||
import Animated, { FadeInUp } from "react-native-reanimated";
|
||||
import { db } from "../../common/database";
|
||||
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
|
||||
import { ToastManager } from "../../services/event-manager";
|
||||
@@ -42,8 +42,6 @@ import { presentDialog } from "../dialog/functions";
|
||||
import MoveNoteSheet from "../sheets/add-to";
|
||||
import ExportNotesSheet from "../sheets/export-notes";
|
||||
import ManageTagsSheet from "../sheets/manage-tags";
|
||||
import { MoveNotebookSheet } from "../sheets/move-notebook";
|
||||
import { Button } from "../ui/button";
|
||||
import { IconButton } from "../ui/icon-button";
|
||||
import Heading from "../ui/typography/heading";
|
||||
|
||||
@@ -59,8 +57,6 @@ export const SelectionHeader = React.memo(
|
||||
type?: ItemType;
|
||||
renderedInRoute?: string;
|
||||
}) => {
|
||||
const menuRef = useRef<Menu>(null);
|
||||
const { colors: contextMenuColors } = useThemeColors("contextMenu");
|
||||
const { colors } = useThemeColors();
|
||||
const selectionMode = useSelectionStore((state) => state.selectionMode);
|
||||
const selectedItemsList = useSelectionStore(
|
||||
@@ -135,7 +131,8 @@ export const SelectionHeader = React.memo(
|
||||
}, [clearSelection, selectionMode]);
|
||||
|
||||
return selectionMode !== type || focusedRouteId !== id ? null : (
|
||||
<View
|
||||
<Animated.View
|
||||
entering={FadeInUp}
|
||||
style={{
|
||||
width: "100%",
|
||||
height: Platform.OS === "android" ? 50 + insets.top : 50,
|
||||
@@ -145,7 +142,8 @@ export const SelectionHeader = React.memo(
|
||||
alignItems: "center",
|
||||
flexDirection: "row",
|
||||
zIndex: 999,
|
||||
paddingHorizontal: 12
|
||||
paddingHorizontal: 12,
|
||||
marginVertical: 10
|
||||
}}
|
||||
>
|
||||
<View
|
||||
@@ -165,15 +163,18 @@ export const SelectionHeader = React.memo(
|
||||
borderRadius: 100,
|
||||
marginRight: 10
|
||||
}}
|
||||
type="secondary"
|
||||
onPress={() => {
|
||||
clearSelection();
|
||||
}}
|
||||
size={SIZE.xl}
|
||||
color={colors.primary.icon}
|
||||
name="close"
|
||||
/>
|
||||
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: colors.secondary.background,
|
||||
height: 40,
|
||||
borderRadius: 100,
|
||||
paddingHorizontal: 16,
|
||||
@@ -182,12 +183,11 @@ export const SelectionHeader = React.memo(
|
||||
alignItems: "center"
|
||||
}}
|
||||
>
|
||||
<Heading size={SIZE.lg} color={colors.primary.paragraph}>
|
||||
<Heading size={SIZE.md} color={colors.primary.accent}>
|
||||
{selectedItemsList.length}
|
||||
</Heading>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
@@ -210,142 +210,144 @@ export const SelectionHeader = React.memo(
|
||||
allSelected ? colors.primary.accent : colors.primary.paragraph
|
||||
}
|
||||
name="select-all"
|
||||
size={SIZE.xl}
|
||||
/>
|
||||
|
||||
{selectedItemsList.length ? (
|
||||
<Menu
|
||||
ref={menuRef}
|
||||
animationDuration={200}
|
||||
style={{
|
||||
borderRadius: 5,
|
||||
backgroundColor: contextMenuColors.primary.background,
|
||||
marginTop: -20
|
||||
}}
|
||||
onRequestClose={() => {
|
||||
menuRef.current?.hide();
|
||||
}}
|
||||
anchor={
|
||||
<IconButton
|
||||
onPress={() => {
|
||||
menuRef.current?.show();
|
||||
}}
|
||||
name="dots-vertical"
|
||||
color={colors.primary.paragraph}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{[
|
||||
{
|
||||
title:
|
||||
selectedItemsList.length > 1
|
||||
? "Move notebooks"
|
||||
: "Move notebook",
|
||||
onPress: async () => {
|
||||
const ids = selectedItemsList;
|
||||
const notebooks = await db.notebooks.all.items(ids);
|
||||
MoveNotebookSheet.present(notebooks);
|
||||
},
|
||||
visible: renderedInRoute === "Notebooks",
|
||||
icon: "arrow-right-bold-box-outline"
|
||||
},
|
||||
{
|
||||
title: "Manage tags",
|
||||
onPress: async () => {
|
||||
await sleep(100);
|
||||
ManageTagsSheet.present(selectedItemsList);
|
||||
},
|
||||
visible: type === "note",
|
||||
icon: "pound"
|
||||
},
|
||||
{
|
||||
title: "Export",
|
||||
onPress: async () => {
|
||||
await sleep(100);
|
||||
ExportNotesSheet.present(selectedItemsList);
|
||||
},
|
||||
visible: type === "note",
|
||||
icon: "export"
|
||||
},
|
||||
{
|
||||
title: "Link notebook",
|
||||
onPress: async () => {
|
||||
await sleep(100);
|
||||
MoveNoteSheet.present();
|
||||
},
|
||||
visible: type === "note",
|
||||
icon: "plus"
|
||||
},
|
||||
{
|
||||
title: "Unlink notebook",
|
||||
onPress: async () => {
|
||||
if (!id) return;
|
||||
await db.notes.removeFromNotebook(id, ...selectedItemsList);
|
||||
updateNotebook(id);
|
||||
Navigation.queueRoutesForUpdate();
|
||||
clearSelection();
|
||||
},
|
||||
visible: renderedInRoute === "Notebook",
|
||||
icon: "minus"
|
||||
},
|
||||
{
|
||||
title: "Unfavorite",
|
||||
onPress: addToFavorite,
|
||||
visible: focusedRouteId === "Favorites",
|
||||
icon: "star-off"
|
||||
},
|
||||
{
|
||||
title: `Move to trash`,
|
||||
onPress: async () => {
|
||||
deleteItems(
|
||||
undefined,
|
||||
useSelectionStore.getState().selectionMode
|
||||
).then(() => {
|
||||
useSelectionStore.getState().clearSelection();
|
||||
useSelectionStore.getState().setSelectionMode(undefined);
|
||||
});
|
||||
},
|
||||
visible: type !== "trash",
|
||||
icon: "delete"
|
||||
},
|
||||
{
|
||||
title: `Restore`,
|
||||
onPress: restoreItem,
|
||||
visible: type === "trash",
|
||||
icon: "delete-restore"
|
||||
},
|
||||
{
|
||||
title: `Delete`,
|
||||
onPress: deleteItem,
|
||||
visible: type === "trash",
|
||||
icon: "delete"
|
||||
{type !== "note" ? null : (
|
||||
<>
|
||||
<IconButton
|
||||
onPress={async () => {
|
||||
await sleep(100);
|
||||
ManageTagsSheet.present(selectedItemsList);
|
||||
}}
|
||||
style={{
|
||||
marginLeft: 10
|
||||
}}
|
||||
color={colors.primary.icon}
|
||||
tooltipText="Manage tags"
|
||||
tooltipPosition={4}
|
||||
name="pound"
|
||||
size={SIZE.xl}
|
||||
/>
|
||||
|
||||
<IconButton
|
||||
onPress={async () => {
|
||||
ExportNotesSheet.present(selectedItemsList);
|
||||
}}
|
||||
tooltipText="Export"
|
||||
tooltipPosition={4}
|
||||
style={{
|
||||
marginLeft: 10
|
||||
}}
|
||||
color={colors.primary.paragraph}
|
||||
name="export"
|
||||
size={SIZE.xl}
|
||||
/>
|
||||
|
||||
<IconButton
|
||||
onPress={async () => {
|
||||
MoveNoteSheet.present();
|
||||
}}
|
||||
style={{
|
||||
marginLeft: 10
|
||||
}}
|
||||
tooltipText="Add to notebooks"
|
||||
tooltipPosition={4}
|
||||
color={colors.primary.paragraph}
|
||||
name="plus"
|
||||
size={SIZE.xl}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
{renderedInRoute === "Notebook" ? (
|
||||
<IconButton
|
||||
onPress={async () => {
|
||||
if (selectedItemsList.length > 0) {
|
||||
if (!id) return;
|
||||
await db.notes.removeFromNotebook(id, ...selectedItemsList);
|
||||
updateNotebook(id);
|
||||
Navigation.queueRoutesForUpdate();
|
||||
clearSelection();
|
||||
}
|
||||
].map((item) =>
|
||||
!item.visible ? null : (
|
||||
<Button
|
||||
style={{
|
||||
width: 150,
|
||||
justifyContent: "flex-start",
|
||||
borderRadius: 0
|
||||
}}
|
||||
type="plain"
|
||||
buttonType={{
|
||||
text: contextMenuColors.primary.paragraph
|
||||
}}
|
||||
icon={item.icon}
|
||||
key={item.title}
|
||||
title={item.title}
|
||||
onPress={async () => {
|
||||
menuRef.current?.hide();
|
||||
if (Platform.OS === "ios") await sleep(300);
|
||||
item.onPress();
|
||||
}}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</Menu>
|
||||
}}
|
||||
style={{
|
||||
marginLeft: 10
|
||||
}}
|
||||
tooltipText={`Remove from Notebook`}
|
||||
tooltipPosition={4}
|
||||
testID="select-minus"
|
||||
color={colors.primary.paragraph}
|
||||
name="minus"
|
||||
size={SIZE.xl}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{focusedRouteId === "Favorites" ? (
|
||||
<IconButton
|
||||
onPress={addToFavorite}
|
||||
style={{
|
||||
marginLeft: 10
|
||||
}}
|
||||
tooltipText="Remove from favorites"
|
||||
tooltipPosition={4}
|
||||
color={colors.primary.paragraph}
|
||||
name="star-off"
|
||||
size={SIZE.xl}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{type === "trash" ? null : (
|
||||
<IconButton
|
||||
style={{
|
||||
marginLeft: 10
|
||||
}}
|
||||
onPress={() => {
|
||||
deleteItems(
|
||||
undefined,
|
||||
useSelectionStore.getState().selectionMode
|
||||
).then(() => {
|
||||
useSelectionStore.getState().clearSelection();
|
||||
useSelectionStore.getState().setSelectionMode(undefined);
|
||||
});
|
||||
}}
|
||||
tooltipText="Move to trash"
|
||||
tooltipPosition={1}
|
||||
color={colors.primary.paragraph}
|
||||
name="delete"
|
||||
size={SIZE.xl}
|
||||
/>
|
||||
)}
|
||||
|
||||
{type === "trash" ? (
|
||||
<>
|
||||
<IconButton
|
||||
style={{
|
||||
marginLeft: 10
|
||||
}}
|
||||
color={colors.primary.paragraph}
|
||||
onPress={restoreItem}
|
||||
name="delete-restore"
|
||||
tooltipText="Restore"
|
||||
tooltipPosition={4}
|
||||
size={SIZE.xl - 3}
|
||||
/>
|
||||
|
||||
<IconButton
|
||||
style={{
|
||||
marginLeft: 10
|
||||
}}
|
||||
color={colors.primary.paragraph}
|
||||
onPress={deleteItem}
|
||||
tooltipText="Delete"
|
||||
tooltipPosition={4}
|
||||
name="delete"
|
||||
size={SIZE.xl - 3}
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
</View>
|
||||
</View>
|
||||
</Animated.View>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -39,22 +39,17 @@ import Heading from "../../ui/typography/heading";
|
||||
import { MoveNotes } from "../move-notes/movenote";
|
||||
import { eOnNotebookUpdated } from "../../../utils/events";
|
||||
import { getParentNotebookId } from "../../../utils/notebooks";
|
||||
import { useNotebookStore } from "../../../stores/use-notebook-store";
|
||||
|
||||
export const AddNotebookSheet = ({
|
||||
notebook,
|
||||
parentNotebook,
|
||||
close,
|
||||
showMoveNotesOnComplete,
|
||||
defaultTitle
|
||||
close
|
||||
}: {
|
||||
notebook?: Notebook;
|
||||
parentNotebook?: Notebook;
|
||||
close?: (didAddNotebook: boolean) => void;
|
||||
showMoveNotesOnComplete: boolean;
|
||||
defaultTitle?: string;
|
||||
close: ((context?: string | undefined) => void) | undefined;
|
||||
}) => {
|
||||
const title = useRef(notebook?.title || defaultTitle);
|
||||
const title = useRef(notebook?.title);
|
||||
const description = useRef(notebook?.description);
|
||||
const titleInput = useRef<TextInput>(null);
|
||||
const descriptionInput = useRef<TextInput>(null);
|
||||
@@ -90,7 +85,6 @@ export const AddNotebookSheet = ({
|
||||
useMenuStore.getState().setMenuPins();
|
||||
Navigation.queueRoutesForUpdate();
|
||||
useRelationStore.getState().update();
|
||||
useNotebookStore.getState().refresh();
|
||||
|
||||
const parent =
|
||||
parentNotebook?.id || (await getParentNotebookId(notebook?.id || id));
|
||||
@@ -103,10 +97,10 @@ export const AddNotebookSheet = ({
|
||||
});
|
||||
}
|
||||
|
||||
if (!notebook && showMoveNotesOnComplete) {
|
||||
if (!notebook) {
|
||||
MoveNotes.present(await db.notebooks.notebook(id));
|
||||
} else {
|
||||
close?.(true);
|
||||
close?.();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -141,7 +135,7 @@ export const AddNotebookSheet = ({
|
||||
}}
|
||||
returnKeyLabel="Next"
|
||||
returnKeyType="next"
|
||||
defaultValue={notebook ? notebook.title : title.current}
|
||||
defaultValue={notebook ? notebook.title : ""}
|
||||
/>
|
||||
|
||||
<Input
|
||||
@@ -175,9 +169,7 @@ AddNotebookSheet.present = (
|
||||
notebook?: Notebook,
|
||||
parentNotebook?: Notebook,
|
||||
context?: string,
|
||||
onClose?: (didAddNotebook: boolean) => void,
|
||||
showMoveNotesOnComplete = true,
|
||||
defaultTitle?: string
|
||||
onClose?: () => void
|
||||
) => {
|
||||
presentSheet({
|
||||
context: context,
|
||||
@@ -185,13 +177,9 @@ AddNotebookSheet.present = (
|
||||
<AddNotebookSheet
|
||||
notebook={notebook}
|
||||
parentNotebook={parentNotebook}
|
||||
close={(didAddNotebook: boolean) => {
|
||||
close?.();
|
||||
onClose?.(didAddNotebook);
|
||||
}}
|
||||
showMoveNotesOnComplete={showMoveNotesOnComplete || false}
|
||||
defaultTitle={defaultTitle}
|
||||
close={close}
|
||||
/>
|
||||
)
|
||||
),
|
||||
onClose: onClose
|
||||
});
|
||||
};
|
||||
|
||||
@@ -19,13 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { Note } from "@notesnook/core";
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import React, {
|
||||
RefObject,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState
|
||||
} from "react";
|
||||
import React, { RefObject, useCallback, useEffect } from "react";
|
||||
import {
|
||||
ActivityIndicator,
|
||||
Keyboard,
|
||||
@@ -52,9 +46,6 @@ import { IconButton } from "../../ui/icon-button";
|
||||
import Paragraph from "../../ui/typography/paragraph";
|
||||
import { NotebookItem } from "./notebook-item";
|
||||
import { useNotebookItemSelectionStore } from "./store";
|
||||
import { AddNotebookSheet } from "../add-notebook";
|
||||
import Input from "../../ui/input";
|
||||
import { presentDialog } from "../../dialog/functions";
|
||||
|
||||
async function updateInitialSelectionState(items: string[]) {
|
||||
const relations = await db.relations
|
||||
@@ -101,11 +92,7 @@ const MoveNoteSheet = ({
|
||||
actionSheetRef: RefObject<ActionSheetRef>;
|
||||
}) => {
|
||||
const { colors } = useThemeColors();
|
||||
const [rootNotebooks, loading] = useNotebooks();
|
||||
const searchQuery = useRef("");
|
||||
const searchTimer = useRef<NodeJS.Timeout>();
|
||||
const [notebooks, setNotebooks] = useState(rootNotebooks);
|
||||
|
||||
const [notebooks, loading] = useNotebooks();
|
||||
const dimensions = useSettingStore((state) => state.dimensions);
|
||||
const selectedItemsList = useSelectionStore(
|
||||
(state) => state.selectedItemsList
|
||||
@@ -115,12 +102,6 @@ const MoveNoteSheet = ({
|
||||
(state) => state.multiSelect
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!loading) {
|
||||
setNotebooks(rootNotebooks);
|
||||
}
|
||||
}, [loading, rootNotebooks]);
|
||||
|
||||
useEffect(() => {
|
||||
const items = note ? [note.id] : selectedItemsList;
|
||||
updateInitialSelectionState(items);
|
||||
@@ -160,11 +141,6 @@ const MoveNoteSheet = ({
|
||||
actionSheetRef.current?.hide();
|
||||
};
|
||||
|
||||
const hasSelected = () => {
|
||||
const selection = useNotebookItemSelectionStore.getState().selection;
|
||||
return Object.keys(selection).some((key) => selection[key] === "selected");
|
||||
};
|
||||
|
||||
const renderNotebook = useCallback(
|
||||
({ index }: { item: boolean; index: number }) => (
|
||||
<NotebookItem items={notebooks} id={index} index={index} />
|
||||
@@ -204,7 +180,7 @@ const MoveNoteSheet = ({
|
||||
paragraph={
|
||||
!multiSelect
|
||||
? "Long press to enable multi-select."
|
||||
: "Select notebooks you want to add note(s) to."
|
||||
: "Select topics you want to add note(s) to."
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -214,20 +190,18 @@ const MoveNoteSheet = ({
|
||||
columnGap: 10
|
||||
}}
|
||||
>
|
||||
{hasSelected() ? (
|
||||
<IconButton
|
||||
name="restore"
|
||||
color={colors.primary.icon}
|
||||
onPress={() => {
|
||||
const items = note ? [note.id] : selectedItemsList;
|
||||
updateInitialSelectionState(items);
|
||||
}}
|
||||
style={{
|
||||
width: 40,
|
||||
height: 40
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
<IconButton
|
||||
name="restore"
|
||||
type="secondaryAccented"
|
||||
onPress={() => {
|
||||
const items = note ? [note.id] : selectedItemsList;
|
||||
updateInitialSelectionState(items);
|
||||
}}
|
||||
style={{
|
||||
width: 40,
|
||||
height: 40
|
||||
}}
|
||||
/>
|
||||
|
||||
<Button
|
||||
height={40}
|
||||
@@ -256,51 +230,6 @@ const MoveNoteSheet = ({
|
||||
style={{
|
||||
width: "100%"
|
||||
}}
|
||||
keyboardShouldPersistTaps="handled"
|
||||
ListHeaderComponent={
|
||||
<View
|
||||
style={{
|
||||
paddingHorizontal: 12,
|
||||
width: "100%",
|
||||
paddingTop: 12
|
||||
}}
|
||||
>
|
||||
<Input
|
||||
placeholder="Search notebooks...."
|
||||
button={{
|
||||
icon: "plus",
|
||||
onPress: () => {
|
||||
AddNotebookSheet.present(
|
||||
undefined,
|
||||
undefined,
|
||||
"link-notebooks",
|
||||
undefined,
|
||||
false,
|
||||
searchQuery.current
|
||||
);
|
||||
},
|
||||
color: colors.primary.icon
|
||||
}}
|
||||
onChangeText={(value) => {
|
||||
searchQuery.current = value;
|
||||
if (!searchQuery.current) {
|
||||
setNotebooks(rootNotebooks);
|
||||
return;
|
||||
}
|
||||
searchTimer.current = setTimeout(() => {
|
||||
db.lookup
|
||||
.notebooks(searchQuery.current)
|
||||
.sorted()
|
||||
.then((result) => {
|
||||
if (searchQuery.current === value) {
|
||||
setNotebooks(result);
|
||||
}
|
||||
});
|
||||
}, 300);
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
}
|
||||
estimatedItemSize={50}
|
||||
renderItem={renderNotebook}
|
||||
ListEmptyComponent={
|
||||
@@ -336,8 +265,7 @@ MoveNoteSheet.present = (note?: Note) => {
|
||||
presentSheet({
|
||||
component: (ref) => <MoveNoteSheet actionSheetRef={ref} note={note} />,
|
||||
enableGesturesInScrollView: false,
|
||||
noBottomPadding: true,
|
||||
keyboardHandlerDisabled: true
|
||||
noBottomPadding: true
|
||||
});
|
||||
};
|
||||
export default MoveNoteSheet;
|
||||
|
||||
@@ -226,13 +226,7 @@ export const NotebookItem = ({
|
||||
testID={notesnook.ids.notebook.menu}
|
||||
onPress={() => {
|
||||
if (!item) return;
|
||||
AddNotebookSheet.present(
|
||||
undefined,
|
||||
item,
|
||||
"link-notebooks",
|
||||
undefined,
|
||||
false
|
||||
);
|
||||
AddNotebookSheet.present(undefined, item, "link-notebooks");
|
||||
}}
|
||||
left={0}
|
||||
right={0}
|
||||
|
||||
@@ -43,7 +43,6 @@ type TabItem = {
|
||||
locked?: boolean;
|
||||
noteLocked?: boolean;
|
||||
readonly?: boolean;
|
||||
pinned?: boolean;
|
||||
};
|
||||
|
||||
const TabItemComponent = (props: {
|
||||
@@ -84,6 +83,7 @@ const TabItemComponent = (props: {
|
||||
onPress={() => {
|
||||
if (!props.isFocused) {
|
||||
useTabStore.getState().focusTab(props.tab.id);
|
||||
props.close?.();
|
||||
if (props.tab.locked) {
|
||||
eSendEvent(eUnlockNote);
|
||||
}
|
||||
@@ -94,7 +94,6 @@ const TabItemComponent = (props: {
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
props.close?.();
|
||||
}}
|
||||
onLongPress={() => {
|
||||
useTabStore.getState().updateTab(props.tab.id, {
|
||||
@@ -130,9 +129,7 @@ const TabItemComponent = (props: {
|
||||
: colors.primary.paragraph
|
||||
}
|
||||
style={{
|
||||
fontFamily: props.tab.previewTab
|
||||
? "OpenSans-Italic"
|
||||
: "OpenSans-Regular"
|
||||
fontStyle: props.tab.previewTab ? "italic" : "normal"
|
||||
}}
|
||||
numberOfLines={1}
|
||||
size={SIZE.md}
|
||||
@@ -141,50 +138,24 @@ const TabItemComponent = (props: {
|
||||
</Paragraph>
|
||||
</View>
|
||||
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
gap: 5,
|
||||
paddingRight: 12
|
||||
<IconButton
|
||||
name="close"
|
||||
size={SIZE.lg}
|
||||
color={colors.primary.icon}
|
||||
onPress={() => {
|
||||
const isLastTab = useTabStore.getState().tabs.length === 1;
|
||||
useTabStore.getState().removeTab(props.tab.id);
|
||||
// The last tab is not actually removed, it is just cleaned up.
|
||||
if (isLastTab) {
|
||||
editorController.current?.reset(props.tab.id, true, true);
|
||||
props.close?.();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<IconButton
|
||||
name="pin"
|
||||
size={SIZE.lg}
|
||||
color={props.tab.pinned ? colors.primary.accent : colors.primary.icon}
|
||||
onPress={() => {
|
||||
useTabStore.getState().updateTab(props.tab.id, {
|
||||
pinned: !props.tab.pinned,
|
||||
previewTab: false
|
||||
});
|
||||
}}
|
||||
top={0}
|
||||
left={0}
|
||||
right={20}
|
||||
bottom={0}
|
||||
/>
|
||||
|
||||
{!props.tab?.pinned ? (
|
||||
<IconButton
|
||||
name="close"
|
||||
size={SIZE.lg}
|
||||
color={colors.primary.icon}
|
||||
onPress={() => {
|
||||
const isLastTab = useTabStore.getState().tabs.length === 1;
|
||||
useTabStore.getState().removeTab(props.tab.id);
|
||||
// The last tab is not actually removed, it is just cleaned up.
|
||||
if (isLastTab) {
|
||||
editorController.current?.reset(props.tab.id, true, true);
|
||||
props.close?.();
|
||||
}
|
||||
}}
|
||||
top={0}
|
||||
left={0}
|
||||
right={20}
|
||||
bottom={0}
|
||||
/>
|
||||
) : null}
|
||||
</View>
|
||||
top={0}
|
||||
left={0}
|
||||
right={20}
|
||||
bottom={0}
|
||||
/>
|
||||
</Pressable>
|
||||
);
|
||||
};
|
||||
@@ -252,16 +223,7 @@ export default function EditorTabs({
|
||||
/>
|
||||
</View>
|
||||
|
||||
<FlatList
|
||||
windowSize={3}
|
||||
data={tabs.sort((t1, t2) => {
|
||||
if (t1.pinned && t2.pinned) return 0;
|
||||
if (t1.pinned) return -1;
|
||||
if (t2.pinned) return 1;
|
||||
return 0;
|
||||
})}
|
||||
renderItem={renderTabItem}
|
||||
/>
|
||||
<FlatList windowSize={3} data={tabs} renderItem={renderTabItem} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ import { getElevationStyle } from "../../../utils/elevation";
|
||||
import { eCloseSheet } from "../../../utils/events";
|
||||
import { SIZE, ph, pv } from "../../../utils/size";
|
||||
import { sleep } from "../../../utils/time";
|
||||
import { Dialog } from "../../dialog";
|
||||
import DialogHeader from "../../dialog/dialog-header";
|
||||
import { ProTag } from "../../premium/pro-tag";
|
||||
import { Button } from "../../ui/button";
|
||||
@@ -48,6 +47,7 @@ import { Pressable } from "../../ui/pressable";
|
||||
import Seperator from "../../ui/seperator";
|
||||
import Heading from "../../ui/typography/heading";
|
||||
import Paragraph from "../../ui/typography/paragraph";
|
||||
import { Dialog } from "../../dialog";
|
||||
|
||||
const ExportNotesSheet = ({
|
||||
ids,
|
||||
@@ -71,7 +71,7 @@ const ExportNotesSheet = ({
|
||||
const [status, setStatus] = useState<string>();
|
||||
const premium = useUserStore((state) => state.premium);
|
||||
|
||||
const exportNoteAs = async (
|
||||
const save = async (
|
||||
type: "pdf" | "txt" | "md" | "html" | "md-frontmatter"
|
||||
) => {
|
||||
if (exporting) return;
|
||||
@@ -81,18 +81,9 @@ const ExportNotesSheet = ({
|
||||
setComplete(false);
|
||||
let result;
|
||||
if (ids.length > 1) {
|
||||
result = await Exporter.bulkExport(
|
||||
db.notes.all.where((eb) => eb("id", "in", ids)),
|
||||
type,
|
||||
setStatus
|
||||
);
|
||||
result = await Exporter.bulkExport(ids, type, setStatus);
|
||||
} else {
|
||||
const note = await db.notes.note(ids[0]);
|
||||
if (!note) {
|
||||
setExporting(false);
|
||||
return;
|
||||
}
|
||||
result = await Exporter.exportNote(note, type, setStatus);
|
||||
result = await Exporter.exportNote(ids[0], type);
|
||||
await sleep(1000);
|
||||
}
|
||||
if (!result) {
|
||||
@@ -110,7 +101,7 @@ const ExportNotesSheet = ({
|
||||
{
|
||||
title: "PDF",
|
||||
func: async () => {
|
||||
await exportNoteAs("pdf");
|
||||
await save("pdf");
|
||||
},
|
||||
icon: "file-pdf-box",
|
||||
desc: "View in any pdf reader app",
|
||||
@@ -120,7 +111,7 @@ const ExportNotesSheet = ({
|
||||
{
|
||||
title: "Markdown",
|
||||
func: async () => {
|
||||
await exportNoteAs("md");
|
||||
await save("md");
|
||||
},
|
||||
icon: "language-markdown",
|
||||
desc: "View in any text or markdown editor",
|
||||
@@ -130,7 +121,7 @@ const ExportNotesSheet = ({
|
||||
{
|
||||
title: "Markdown + Frontmatter",
|
||||
func: async () => {
|
||||
await exportNoteAs("md-frontmatter");
|
||||
await save("md-frontmatter");
|
||||
},
|
||||
icon: "language-markdown",
|
||||
desc: "View in any text or markdown editor",
|
||||
@@ -140,7 +131,7 @@ const ExportNotesSheet = ({
|
||||
{
|
||||
title: "Plain Text",
|
||||
func: async () => {
|
||||
await exportNoteAs("txt");
|
||||
await save("txt");
|
||||
},
|
||||
icon: "card-text",
|
||||
desc: "View in any text editor",
|
||||
@@ -150,7 +141,7 @@ const ExportNotesSheet = ({
|
||||
{
|
||||
title: "HTML",
|
||||
func: async () => {
|
||||
await exportNoteAs("html");
|
||||
await save("html");
|
||||
},
|
||||
icon: "language-html5",
|
||||
desc: "View in any web browser & html reader",
|
||||
@@ -259,9 +250,11 @@ const ExportNotesSheet = ({
|
||||
<>
|
||||
<ActivityIndicator />
|
||||
<Paragraph>
|
||||
{`${
|
||||
status ? `${status})` : `Exporting notes`
|
||||
}... Please wait`}
|
||||
{ids.length === 1
|
||||
? "Exporting note... Please wait"
|
||||
: `Exporting notes${
|
||||
status ? ` (${status})` : ``
|
||||
}... Please wait`}
|
||||
</Paragraph>
|
||||
</>
|
||||
) : (
|
||||
|
||||
@@ -141,7 +141,7 @@ Logged in: ${user ? "yes" : "no"}`,
|
||||
defaultValue={title.current}
|
||||
style={{
|
||||
borderWidth: 1,
|
||||
borderColor: colors.primary.border,
|
||||
borderColor: colors.secondary.background,
|
||||
borderRadius: 5,
|
||||
padding: 12,
|
||||
fontFamily: "OpenSans-Regular",
|
||||
@@ -178,7 +178,7 @@ For example:
|
||||
}}
|
||||
style={{
|
||||
borderWidth: 1,
|
||||
borderColor: colors.primary.border,
|
||||
borderColor: colors.secondary.background,
|
||||
borderRadius: 5,
|
||||
padding: 12,
|
||||
fontFamily: "OpenSans-Regular",
|
||||
|
||||
@@ -219,7 +219,7 @@ export default function LinkNote(props: {
|
||||
<View
|
||||
style={{
|
||||
paddingHorizontal: 12,
|
||||
minHeight: "100%",
|
||||
minHeight: 400,
|
||||
maxHeight: "100%"
|
||||
}}
|
||||
>
|
||||
@@ -311,7 +311,6 @@ export default function LinkNote(props: {
|
||||
style={{
|
||||
marginTop: 10
|
||||
}}
|
||||
keyboardShouldPersistTaps="handled"
|
||||
windowSize={3}
|
||||
keyExtractor={(item) => item.id}
|
||||
data={nodes}
|
||||
@@ -325,7 +324,6 @@ export default function LinkNote(props: {
|
||||
onSelectNote={onSelectNote}
|
||||
/>
|
||||
)}
|
||||
keyboardShouldPersistTaps="handled"
|
||||
style={{
|
||||
marginTop: 10
|
||||
}}
|
||||
|
||||
@@ -96,12 +96,9 @@ export default function Migrate() {
|
||||
});
|
||||
setLoading(true);
|
||||
await sleep(1);
|
||||
const { error, report } = await BackupService.run(false, "local");
|
||||
const { error } = await BackupService.run(false, "local");
|
||||
if (error) {
|
||||
ToastManager.error(error, "Backup failed");
|
||||
if (report) {
|
||||
reportError(error);
|
||||
}
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
@@ -162,14 +159,13 @@ export default function Migrate() {
|
||||
}}
|
||||
>
|
||||
Migrating database{progress ? `(${progress?.collection})` : null}
|
||||
{progress ? `(${progress.current}/${progress.total}) ` : null}
|
||||
... please wait
|
||||
{progress ? `(${progress.current}/${progress.total}) ` : null}...
|
||||
please wait
|
||||
</Paragraph>
|
||||
|
||||
<View
|
||||
style={{
|
||||
width: 200,
|
||||
alignSelf: "center"
|
||||
width: 200
|
||||
}}
|
||||
>
|
||||
<ProgressBarComponent
|
||||
|
||||
@@ -1,361 +0,0 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import { Notebook, VirtualizedGrouping } from "@notesnook/core";
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import { Text, View } from "react-native";
|
||||
import { FlatList } from "react-native-actions-sheet";
|
||||
import create from "zustand";
|
||||
import { db } from "../../../common/database";
|
||||
import { useNotebook } from "../../../hooks/use-notebook";
|
||||
import { eSendEvent, presentSheet } from "../../../services/event-manager";
|
||||
import {
|
||||
useNotebookStore,
|
||||
useNotebooks
|
||||
} from "../../../stores/use-notebook-store";
|
||||
import { eOnNotebookUpdated } from "../../../utils/events";
|
||||
import {
|
||||
findRootNotebookId,
|
||||
getParentNotebookId
|
||||
} from "../../../utils/notebooks";
|
||||
import { SIZE } from "../../../utils/size";
|
||||
import { Dialog } from "../../dialog";
|
||||
import DialogHeader from "../../dialog/dialog-header";
|
||||
import { presentDialog } from "../../dialog/functions";
|
||||
import SheetProvider from "../../sheet-provider";
|
||||
import { Button } from "../../ui/button";
|
||||
import { IconButton } from "../../ui/icon-button";
|
||||
import { Pressable } from "../../ui/pressable";
|
||||
import Seperator from "../../ui/seperator";
|
||||
import Paragraph from "../../ui/typography/paragraph";
|
||||
import { AddNotebookSheet } from "../add-notebook";
|
||||
|
||||
const useNotebookExpandedStore = create<{
|
||||
expanded: {
|
||||
[id: string]: boolean;
|
||||
};
|
||||
setExpanded: (id: string) => void;
|
||||
}>((set, get) => ({
|
||||
expanded: {},
|
||||
setExpanded(id: string) {
|
||||
set({
|
||||
expanded: {
|
||||
...get().expanded,
|
||||
[id]: !get().expanded[id]
|
||||
}
|
||||
});
|
||||
}
|
||||
}));
|
||||
|
||||
export const MoveNotebookSheet = ({
|
||||
selectedNotebooks,
|
||||
close
|
||||
}: {
|
||||
selectedNotebooks: Notebook[];
|
||||
close?: () => void;
|
||||
}) => {
|
||||
const [notebooks] = useNotebooks();
|
||||
const { colors } = useThemeColors();
|
||||
const [moveToTop, setMoveToTop] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
for (const notebook of selectedNotebooks) {
|
||||
const root = await findRootNotebookId(notebook.id);
|
||||
if (root !== notebook.id) {
|
||||
setMoveToTop(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
})();
|
||||
}, [selectedNotebooks]);
|
||||
|
||||
const renderItem = useCallback(
|
||||
({ index }: { index: number }) => {
|
||||
return (
|
||||
<NotebookItem
|
||||
id={index}
|
||||
items={notebooks}
|
||||
level={0}
|
||||
selectedNotebooks={selectedNotebooks}
|
||||
onPress={async (selectedNotebook) => {
|
||||
presentDialog({
|
||||
title: `Move ${
|
||||
selectedNotebooks.length > 1
|
||||
? selectedNotebooks.length + " notebooks"
|
||||
: selectedNotebooks[0].title
|
||||
}`,
|
||||
paragraph: `Are you sure you want to move ${
|
||||
selectedNotebooks.length > 1
|
||||
? selectedNotebooks.length + " notebooks"
|
||||
: selectedNotebooks[0].title
|
||||
} to ${selectedNotebook.title}?`,
|
||||
positiveText: "Move",
|
||||
context: "move-notebook",
|
||||
positivePress: async () => {
|
||||
for (const notebook of selectedNotebooks) {
|
||||
const parent = await getParentNotebookId(notebook.id);
|
||||
const root = await findRootNotebookId(notebook.id);
|
||||
|
||||
if (selectedNotebook.id === notebook.id) continue;
|
||||
|
||||
if (root !== notebook.id) {
|
||||
await db.relations.unlink(
|
||||
{
|
||||
type: "notebook",
|
||||
id: parent
|
||||
},
|
||||
notebook
|
||||
);
|
||||
eSendEvent(eOnNotebookUpdated, parent);
|
||||
}
|
||||
|
||||
await db.relations.add(selectedNotebook, notebook);
|
||||
eSendEvent(eOnNotebookUpdated, selectedNotebook.id);
|
||||
eSendEvent(eOnNotebookUpdated, notebook.id);
|
||||
}
|
||||
useNotebookStore.getState().refresh();
|
||||
close?.();
|
||||
}
|
||||
});
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
[selectedNotebooks, notebooks, close]
|
||||
);
|
||||
|
||||
return (
|
||||
<View>
|
||||
<SheetProvider context="move-notebook" />
|
||||
<Dialog context="move-notebook" />
|
||||
|
||||
<View
|
||||
style={{
|
||||
paddingHorizontal: 12
|
||||
}}
|
||||
>
|
||||
<DialogHeader
|
||||
title={`Moving ${
|
||||
selectedNotebooks.length > 1
|
||||
? selectedNotebooks.length + " notebooks"
|
||||
: selectedNotebooks[0].title
|
||||
}`}
|
||||
paragraph={"Select the notebook you want to move this notebook to."}
|
||||
/>
|
||||
</View>
|
||||
<Seperator />
|
||||
|
||||
<FlatList
|
||||
data={notebooks?.placeholders}
|
||||
renderItem={renderItem}
|
||||
windowSize={1}
|
||||
ListHeaderComponent={
|
||||
<View
|
||||
style={{
|
||||
paddingHorizontal: 12
|
||||
}}
|
||||
>
|
||||
{moveToTop ? (
|
||||
<Button
|
||||
title="Move to top"
|
||||
style={{
|
||||
alignSelf: "flex-start",
|
||||
width: "100%",
|
||||
justifyContent: "space-between"
|
||||
}}
|
||||
icon="arrow-up-bold"
|
||||
iconPosition="right"
|
||||
type="secondaryAccented"
|
||||
onPress={async () => {
|
||||
for (const notebook of selectedNotebooks) {
|
||||
const parent = await getParentNotebookId(notebook.id);
|
||||
const root = await findRootNotebookId(notebook.id);
|
||||
if (root !== notebook.id) {
|
||||
await db.relations.unlink(
|
||||
{
|
||||
type: "notebook",
|
||||
id: parent
|
||||
},
|
||||
notebook
|
||||
);
|
||||
eSendEvent(eOnNotebookUpdated, parent);
|
||||
eSendEvent(eOnNotebookUpdated, notebook.id);
|
||||
}
|
||||
}
|
||||
useNotebookStore.getState().refresh();
|
||||
close?.();
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
</View>
|
||||
}
|
||||
ListEmptyComponent={
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
height: 200
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
color: colors.secondary.icon
|
||||
}}
|
||||
>
|
||||
No notebooks
|
||||
</Text>
|
||||
</View>
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const NotebookItem = ({
|
||||
id,
|
||||
onPress,
|
||||
items,
|
||||
level = 0,
|
||||
selectedNotebooks
|
||||
}: {
|
||||
id: string | number;
|
||||
level?: number;
|
||||
items?: VirtualizedGrouping<Notebook>;
|
||||
onPress: (item: Notebook) => void;
|
||||
selectedNotebooks: Notebook[];
|
||||
}) => {
|
||||
const { nestedNotebooks, notebook } = useNotebook(id, items, true);
|
||||
|
||||
const isExpanded = useNotebookExpandedStore((state) =>
|
||||
!notebook ? false : state.expanded[notebook.id]
|
||||
);
|
||||
const { colors } = useThemeColors();
|
||||
|
||||
return selectedNotebooks.find(
|
||||
(n) => n.id === notebook?.id
|
||||
) ? null : !notebook ? (
|
||||
<View
|
||||
style={{
|
||||
height: 45
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<View
|
||||
style={{
|
||||
minHeight: 45,
|
||||
borderRadius: 0
|
||||
}}
|
||||
>
|
||||
<Pressable
|
||||
onPress={() => onPress(notebook)}
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
paddingHorizontal: 12,
|
||||
height: 45
|
||||
}}
|
||||
>
|
||||
{nestedNotebooks?.placeholders.length ? (
|
||||
<IconButton
|
||||
name={isExpanded ? "chevron-down" : "chevron-right"}
|
||||
color={colors.primary.icon}
|
||||
size={20}
|
||||
onPress={() => {
|
||||
if (!notebook) return;
|
||||
useNotebookExpandedStore.getState().setExpanded(notebook.id);
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<View
|
||||
style={{
|
||||
width: 35,
|
||||
height: 30,
|
||||
justifyContent: "center",
|
||||
alignItems: "center"
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
flexGrow: 1,
|
||||
alignItems: "center"
|
||||
}}
|
||||
>
|
||||
<Paragraph
|
||||
numberOfLines={1}
|
||||
style={{
|
||||
color: colors.primary.paragraph,
|
||||
fontSize: 15
|
||||
}}
|
||||
>
|
||||
{notebook.title}
|
||||
</Paragraph>
|
||||
|
||||
<IconButton
|
||||
name="plus"
|
||||
onPress={() => {
|
||||
if (!notebook) return;
|
||||
AddNotebookSheet.present(
|
||||
undefined,
|
||||
notebook,
|
||||
"move-notebooks",
|
||||
undefined,
|
||||
false
|
||||
);
|
||||
}}
|
||||
size={SIZE.lg}
|
||||
/>
|
||||
</View>
|
||||
</Pressable>
|
||||
|
||||
{nestedNotebooks?.placeholders?.length && isExpanded ? (
|
||||
<View
|
||||
style={{
|
||||
paddingLeft: level + 1 > 0 && level + 1 < 5 ? 15 : 0,
|
||||
marginTop: 5
|
||||
}}
|
||||
>
|
||||
{nestedNotebooks.placeholders.map((item, index) => (
|
||||
<NotebookItem
|
||||
key={notebook?.id + index}
|
||||
id={index}
|
||||
onPress={onPress}
|
||||
level={level + 1}
|
||||
items={nestedNotebooks}
|
||||
selectedNotebooks={selectedNotebooks}
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
) : null}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
MoveNotebookSheet.present = async (notebooks: Notebook[]) => {
|
||||
presentSheet({
|
||||
component: (ref, close) => (
|
||||
<MoveNotebookSheet selectedNotebooks={notebooks} close={close} />
|
||||
),
|
||||
keyboardHandlerDisabled: true
|
||||
});
|
||||
};
|
||||
@@ -20,8 +20,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import { VirtualizedGrouping } from "@notesnook/core";
|
||||
import { Note, Notebook } from "@notesnook/core/dist/types";
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import React, { RefObject, useEffect, useRef, useState } from "react";
|
||||
import { ActivityIndicator, TextInput, View } from "react-native";
|
||||
import React, { RefObject, useEffect, useState } from "react";
|
||||
import { View } from "react-native";
|
||||
import { ActionSheetRef } from "react-native-actions-sheet";
|
||||
import { FlashList } from "react-native-actions-sheet/dist/src/views/FlashList";
|
||||
import { db } from "../../../common/database";
|
||||
@@ -35,7 +35,6 @@ import { Dialog } from "../../dialog";
|
||||
import DialogHeader from "../../dialog/dialog-header";
|
||||
import { Button } from "../../ui/button";
|
||||
import { IconButton } from "../../ui/icon-button";
|
||||
import Input from "../../ui/input";
|
||||
import { Pressable } from "../../ui/pressable";
|
||||
import Seperator from "../../ui/seperator";
|
||||
import Paragraph from "../../ui/typography/paragraph";
|
||||
@@ -51,60 +50,39 @@ export const MoveNotes = ({
|
||||
}) => {
|
||||
const { colors } = useThemeColors();
|
||||
const currentNotebook = notebook;
|
||||
const inputRef = useRef<TextInput>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const selectionCount = useItemSelectionStore(
|
||||
(state) =>
|
||||
Object.keys(state.selection).filter(
|
||||
(k) =>
|
||||
state.selection?.[k] === "selected" ||
|
||||
state.selection[k] === "deselected"
|
||||
state.initialState?.[k] !== "selected" &&
|
||||
state.selection[k] !== "deselected"
|
||||
)?.length > 0
|
||||
);
|
||||
|
||||
const [notes, setNotes] = useState<VirtualizedGrouping<Note>>();
|
||||
|
||||
const loadNotes = React.useCallback(
|
||||
async (query?: string) => {
|
||||
setLoading(true);
|
||||
const notes = query
|
||||
? db.lookup.notes(query).sorted()
|
||||
: db.notes?.all.sorted(db.settings.getGroupOptions("notes") as any);
|
||||
|
||||
notes
|
||||
.then(async (notes) => {
|
||||
await notes.item(0);
|
||||
setNotes(notes);
|
||||
setLoading(false);
|
||||
})
|
||||
.catch(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
|
||||
db.relations
|
||||
.from(currentNotebook, "note")
|
||||
.get()
|
||||
.then((existingNotes) => {
|
||||
const selection: { [name: string]: any } = {};
|
||||
existingNotes.forEach((rel) => {
|
||||
selection[rel.toId] = "selected";
|
||||
});
|
||||
useItemSelectionStore.setState({
|
||||
selection: selection,
|
||||
initialState: selection
|
||||
});
|
||||
});
|
||||
},
|
||||
[currentNotebook]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
loadNotes();
|
||||
db.notes?.all.sorted(db.settings.getGroupOptions("notes")).then((notes) => {
|
||||
setNotes(notes);
|
||||
});
|
||||
db.relations
|
||||
.from(currentNotebook, "note")
|
||||
.get()
|
||||
.then((existingNotes) => {
|
||||
const selection: { [name: string]: any } = {};
|
||||
existingNotes.forEach((rel) => {
|
||||
selection[rel.toId] = "selected";
|
||||
});
|
||||
useItemSelectionStore.setState({
|
||||
selection: selection,
|
||||
initialState: selection
|
||||
});
|
||||
});
|
||||
|
||||
return () => {
|
||||
useItemSelectionStore.getState().reset();
|
||||
};
|
||||
}, [currentNotebook, loadNotes]);
|
||||
}, [currentNotebook]);
|
||||
|
||||
const renderItem = React.useCallback(
|
||||
({ index }: { item: boolean; index: number }) => {
|
||||
@@ -118,33 +96,19 @@ export const MoveNotes = ({
|
||||
style={{
|
||||
paddingHorizontal: 12,
|
||||
maxHeight: "100%",
|
||||
height: "100%"
|
||||
height: notes?.placeholders.length
|
||||
? 50 * (notes?.placeholders.length + 2)
|
||||
: 300
|
||||
}}
|
||||
>
|
||||
<Dialog context="local" />
|
||||
|
||||
<DialogHeader
|
||||
title={`Add notes to ${currentNotebook.title}`}
|
||||
paragraph={"Select the notes you want to move to this Notebook."}
|
||||
paragraph={"Select the topic in which you would like to move notes."}
|
||||
/>
|
||||
<Seperator />
|
||||
|
||||
<Input
|
||||
button={{
|
||||
icon: "magnify",
|
||||
color: colors.primary.accent,
|
||||
size: SIZE.lg,
|
||||
onPress: () => {}
|
||||
}}
|
||||
testID="search-input"
|
||||
fwdRef={inputRef}
|
||||
autoCapitalize="none"
|
||||
onChangeText={(v) => {
|
||||
loadNotes(v && v.trim() === "" ? undefined : v.trim());
|
||||
}}
|
||||
placeholder="Search a note"
|
||||
/>
|
||||
|
||||
<FlashList
|
||||
ListEmptyComponent={
|
||||
<View
|
||||
@@ -154,17 +118,13 @@ export const MoveNotes = ({
|
||||
alignItems: "center"
|
||||
}}
|
||||
>
|
||||
{loading ? (
|
||||
<ActivityIndicator size="large" color={colors.primary.accent} />
|
||||
) : (
|
||||
<Paragraph color={colors.secondary.paragraph}>
|
||||
No notes to show
|
||||
</Paragraph>
|
||||
)}
|
||||
<Paragraph color={colors.secondary.paragraph}>
|
||||
No notes to show
|
||||
</Paragraph>
|
||||
</View>
|
||||
}
|
||||
estimatedItemSize={50}
|
||||
data={loading ? [] : notes?.placeholders}
|
||||
data={notes?.placeholders}
|
||||
renderItem={renderItem}
|
||||
/>
|
||||
|
||||
@@ -175,12 +135,6 @@ export const MoveNotes = ({
|
||||
currentNotebook.id,
|
||||
...useItemSelectionStore.getState().getSelectedItemIds()
|
||||
);
|
||||
|
||||
await db.notes?.removeFromNotebook(
|
||||
currentNotebook.id,
|
||||
...useItemSelectionStore.getState().getDeselectedItemIds()
|
||||
);
|
||||
|
||||
updateNotebook(currentNotebook.id);
|
||||
Navigation.queueRoutesForUpdate();
|
||||
fwdRef?.current?.hide();
|
||||
@@ -207,12 +161,11 @@ const SelectableNoteItem = React.memo(
|
||||
const selected = useItemSelectionStore((state) =>
|
||||
item?.id ? state.selection[item.id] === "selected" : false
|
||||
);
|
||||
|
||||
const exists = useItemSelectionStore((state) =>
|
||||
item?.id ? state.initialState[item.id] === "selected" : false
|
||||
);
|
||||
|
||||
return (
|
||||
return exists ? null : (
|
||||
<Pressable
|
||||
testID="listitem.select"
|
||||
onPress={() => {
|
||||
@@ -252,14 +205,8 @@ const SelectableNoteItem = React.memo(
|
||||
? "check-circle-outline"
|
||||
: "checkbox-blank-circle-outline"
|
||||
}
|
||||
type="plain"
|
||||
color={
|
||||
selected
|
||||
? colors.selected.icon
|
||||
: exists && !selected
|
||||
? colors.static.red
|
||||
: colors.primary.icon
|
||||
}
|
||||
type="selected"
|
||||
color={selected ? colors.selected.icon : colors.primary.icon}
|
||||
/>
|
||||
|
||||
<View
|
||||
|
||||
@@ -17,14 +17,13 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import React from "react";
|
||||
import { Platform, View } from "react-native";
|
||||
import { ScrollView } from "react-native-actions-sheet";
|
||||
import { getVersion } from "react-native-device-info";
|
||||
import { features } from "../../../features";
|
||||
import { eSendEvent, presentSheet } from "../../../services/event-manager";
|
||||
import SettingsService from "../../../services/settings";
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import { eCloseSheet } from "../../../utils/events";
|
||||
import { SIZE } from "../../../utils/size";
|
||||
import { Button } from "../../ui/button";
|
||||
@@ -37,13 +36,7 @@ export type FeatureType = {
|
||||
platform?: "ios" | "android";
|
||||
};
|
||||
|
||||
const NewFeature = ({
|
||||
features,
|
||||
version
|
||||
}: {
|
||||
features: FeatureType[];
|
||||
version?: string | null;
|
||||
}) => {
|
||||
const NewFeature = ({ features }: { features: FeatureType[] }) => {
|
||||
const { colors } = useThemeColors();
|
||||
|
||||
return (
|
||||
@@ -51,33 +44,30 @@ const NewFeature = ({
|
||||
style={{
|
||||
alignItems: "center",
|
||||
paddingHorizontal: 12,
|
||||
paddingTop: 12,
|
||||
maxHeight: "100%"
|
||||
paddingTop: 12
|
||||
}}
|
||||
>
|
||||
<Heading color={colors.secondary.heading} size={SIZE.md}>
|
||||
{!version ? "New version " : `v${version} `}Highlights 🎉
|
||||
New Version Highlights 🎉
|
||||
</Heading>
|
||||
|
||||
<Seperator />
|
||||
|
||||
<ScrollView>
|
||||
{features.map((item) => (
|
||||
<View
|
||||
key={item.title}
|
||||
style={{
|
||||
backgroundColor: colors.secondary.background,
|
||||
padding: 12,
|
||||
borderRadius: 10,
|
||||
width: "100%",
|
||||
marginBottom: 10
|
||||
}}
|
||||
>
|
||||
<Heading size={SIZE.lg - 2}>{item.title}</Heading>
|
||||
<Paragraph selectable>{item.body}</Paragraph>
|
||||
</View>
|
||||
))}
|
||||
</ScrollView>
|
||||
{features.map((item) => (
|
||||
<View
|
||||
key={item.title}
|
||||
style={{
|
||||
backgroundColor: colors.secondary.background,
|
||||
padding: 12,
|
||||
borderRadius: 10,
|
||||
width: "100%",
|
||||
marginBottom: 10
|
||||
}}
|
||||
>
|
||||
<Heading size={SIZE.lg - 2}>{item.title}</Heading>
|
||||
<Paragraph>{item.body}</Paragraph>
|
||||
</View>
|
||||
))}
|
||||
<Seperator />
|
||||
|
||||
<Button
|
||||
@@ -118,13 +108,7 @@ NewFeature.present = () => {
|
||||
);
|
||||
if (_features.length === 0) return;
|
||||
presentSheet({
|
||||
component: (
|
||||
<NewFeature
|
||||
features={features}
|
||||
version={SettingsService.getProperty("version")}
|
||||
/>
|
||||
),
|
||||
disableClosing: true
|
||||
component: <NewFeature features={features} />
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
@@ -19,19 +19,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import { Notebook, VirtualizedGrouping } from "@notesnook/core";
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
Platform,
|
||||
RefreshControl,
|
||||
View,
|
||||
useWindowDimensions
|
||||
} from "react-native";
|
||||
import { RefreshControl, View, useWindowDimensions } from "react-native";
|
||||
import ActionSheet, { ActionSheetRef } from "react-native-actions-sheet";
|
||||
import { FlashList } from "react-native-actions-sheet/dist/src/views/FlashList";
|
||||
import Config from "react-native-config";
|
||||
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||
import create from "zustand";
|
||||
import { notesnook } from "../../../../e2e/test.ids";
|
||||
import { db } from "../../../common/database";
|
||||
import { MMKV } from "../../../common/database/mmkv";
|
||||
import { useNotebook } from "../../../hooks/use-notebook";
|
||||
import NotebookScreen from "../../../screens/notebook";
|
||||
@@ -49,7 +43,6 @@ import { IconButton } from "../../ui/icon-button";
|
||||
import { Pressable } from "../../ui/pressable";
|
||||
import Paragraph from "../../ui/typography/paragraph";
|
||||
import { AddNotebookSheet } from "../add-notebook";
|
||||
import { MoveNotebookSheet } from "../move-notebook";
|
||||
import Sort from "../sort";
|
||||
|
||||
const useItemSelectionStore = createItemSelectionStore(true, false);
|
||||
@@ -68,8 +61,7 @@ class NotebookSheetConfig {
|
||||
}
|
||||
|
||||
static get(item: ConfigItem) {
|
||||
const value = MMKV.getInt(NotebookSheetConfig.makeId(item));
|
||||
return typeof value === "number" ? value : 0;
|
||||
return MMKV.getInt(NotebookSheetConfig.makeId(item)) || 0;
|
||||
}
|
||||
|
||||
static set(item: ConfigItem, index = 0) {
|
||||
@@ -132,6 +124,11 @@ export const NotebookSheet = () => {
|
||||
if (!focusedRouteId) return;
|
||||
const nextRoot = await findRootNotebookId(focusedRouteId);
|
||||
if (nextRoot !== currentItem.current) {
|
||||
console.log(
|
||||
"NotebookSheet.useEffect.canShow",
|
||||
"Root changed to",
|
||||
nextRoot
|
||||
);
|
||||
useItemSelectionStore.setState({
|
||||
enabled: false,
|
||||
selection: {}
|
||||
@@ -140,14 +137,17 @@ export const NotebookSheet = () => {
|
||||
currentItem.current = nextRoot;
|
||||
const snapPoint = NotebookSheetConfig.get({
|
||||
type: "notebook",
|
||||
id: focusedRouteId as string
|
||||
id: nextRoot as string
|
||||
});
|
||||
|
||||
if (ref.current?.isOpen()) {
|
||||
ref.current?.snapToIndex(snapPoint);
|
||||
} else {
|
||||
ref.current?.show(snapPoint);
|
||||
setTimeout(() => {
|
||||
ref.current?.show(snapPoint);
|
||||
}, 150);
|
||||
}
|
||||
console.log("NotebookSheet.useEffect.didShow", focusedRouteId);
|
||||
setRoot(nextRoot);
|
||||
onRequestUpdate();
|
||||
});
|
||||
@@ -160,7 +160,7 @@ export const NotebookSheet = () => {
|
||||
ref.current?.hide();
|
||||
}
|
||||
}
|
||||
}, [canShow, focusedRouteId]);
|
||||
}, [canShow, onRequestUpdate, focusedRouteId]);
|
||||
|
||||
return (
|
||||
<ActionSheet
|
||||
@@ -196,56 +196,11 @@ export const NotebookSheet = () => {
|
||||
backgroundColor: colors.secondary.background
|
||||
}}
|
||||
keyboardHandlerEnabled={false}
|
||||
snapPoints={
|
||||
Config.isTesting === "true"
|
||||
? [100]
|
||||
: [Platform.OS === "android" ? 15 : 10, 100]
|
||||
}
|
||||
snapPoints={Config.isTesting === "true" ? [100] : [20, 100]}
|
||||
initialSnapIndex={1}
|
||||
backgroundInteractionEnabled
|
||||
gestureEnabled
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
position: "absolute",
|
||||
right: 24 + normalize(50),
|
||||
marginTop: -80
|
||||
}}
|
||||
>
|
||||
<Pressable
|
||||
testID={notesnook.buttons.add}
|
||||
type="secondary"
|
||||
onPress={() => {
|
||||
if (!notebook) return;
|
||||
AddNotebookSheet.present(
|
||||
undefined,
|
||||
notebook,
|
||||
undefined,
|
||||
undefined,
|
||||
false
|
||||
);
|
||||
}}
|
||||
style={{
|
||||
borderRadius: 100
|
||||
}}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
height: normalize(50),
|
||||
width: normalize(50)
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
name="notebook-plus"
|
||||
color={colors.primary.icon}
|
||||
size={SIZE.xxl}
|
||||
/>
|
||||
</View>
|
||||
</Pressable>
|
||||
</View>
|
||||
|
||||
<View
|
||||
style={{
|
||||
position: "absolute",
|
||||
@@ -265,8 +220,8 @@ export const NotebookSheet = () => {
|
||||
style={{
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
height: normalize(50),
|
||||
width: normalize(50)
|
||||
height: normalize(60),
|
||||
width: normalize(60)
|
||||
}}
|
||||
>
|
||||
<Icon name="plus" color="white" size={SIZE.xxl} />
|
||||
@@ -323,26 +278,6 @@ export const NotebookSheet = () => {
|
||||
size={22}
|
||||
/>
|
||||
|
||||
<IconButton
|
||||
style={{
|
||||
marginLeft: 10,
|
||||
width: 40 * fontScale,
|
||||
height: 40 * fontScale
|
||||
}}
|
||||
onPress={async () => {
|
||||
const ids = useItemSelectionStore
|
||||
.getState()
|
||||
.getSelectedItemIds();
|
||||
const notebooks = await db.notebooks.all.items(ids);
|
||||
MoveNotebookSheet.present(notebooks);
|
||||
}}
|
||||
color={colors.primary.icon}
|
||||
tooltipText="Clear selection"
|
||||
tooltipPosition={1}
|
||||
name="arrow-right-bold-box-outline"
|
||||
size={22}
|
||||
/>
|
||||
|
||||
<IconButton
|
||||
style={{
|
||||
marginLeft: 10,
|
||||
@@ -384,6 +319,20 @@ export const NotebookSheet = () => {
|
||||
height: 40 * fontScale
|
||||
}}
|
||||
/>
|
||||
<IconButton
|
||||
name="plus"
|
||||
onPress={() => {
|
||||
if (!notebook) return;
|
||||
AddNotebookSheet.present(undefined, notebook, undefined);
|
||||
}}
|
||||
testID="add-notebook-button"
|
||||
color={colors.primary.icon}
|
||||
size={22}
|
||||
style={{
|
||||
width: 40 * fontScale,
|
||||
height: 40 * fontScale
|
||||
}}
|
||||
/>
|
||||
|
||||
<IconButton
|
||||
name={collapsed ? "chevron-up" : "chevron-down"}
|
||||
|
||||
@@ -357,9 +357,7 @@ const PublishNoteSheet = ({
|
||||
}}
|
||||
onPress={async () => {
|
||||
try {
|
||||
await openLinkInBrowser(
|
||||
"https://help.notesnook.com/publish-notes-with-monographs"
|
||||
);
|
||||
await openLinkInBrowser("https://docs.notesnook.com/monographs/");
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ export default function ReminderNotify({
|
||||
? 160 * references?.placeholders?.length
|
||||
: 500,
|
||||
borderTopWidth: 1,
|
||||
borderTopColor: colors.primary.border,
|
||||
borderTopColor: colors.secondary.background,
|
||||
marginTop: 5,
|
||||
paddingTop: 5
|
||||
}}
|
||||
|
||||
@@ -18,12 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import React, { RefObject, useRef, useState } from "react";
|
||||
import {
|
||||
Platform,
|
||||
TextInput,
|
||||
View,
|
||||
ScrollView as RNScrollView
|
||||
} from "react-native";
|
||||
import { Platform, TextInput, View } from "react-native";
|
||||
import { ActionSheetRef, ScrollView } from "react-native-actions-sheet";
|
||||
import DateTimePickerModal from "react-native-modal-datetime-picker";
|
||||
import {
|
||||
@@ -369,7 +364,7 @@ export default function ReminderSheet({
|
||||
))}
|
||||
</View>
|
||||
|
||||
<RNScrollView showsHorizontalScrollIndicator={false} horizontal>
|
||||
<ScrollView showsHorizontalScrollIndicator={false} horizontal>
|
||||
{recurringMode === RecurringModes.Daily ||
|
||||
recurringMode === RecurringModes.Year
|
||||
? null
|
||||
@@ -430,7 +425,7 @@ export default function ReminderSheet({
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</RNScrollView>
|
||||
</ScrollView>
|
||||
</View>
|
||||
) : null}
|
||||
|
||||
|
||||
@@ -48,7 +48,6 @@ import { Button } from "../../ui/button";
|
||||
import Seperator from "../../ui/seperator";
|
||||
import SheetWrapper from "../../ui/sheet";
|
||||
import Paragraph from "../../ui/typography/paragraph";
|
||||
import { useUserStore } from "../../../stores/use-user-store";
|
||||
|
||||
const RestoreDataSheet = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
@@ -247,6 +246,7 @@ const RestoreDataComponent = ({ close, setRestoring, restoring }) => {
|
||||
await db.backup.import(backup, password, key);
|
||||
});
|
||||
await db.initCollections();
|
||||
initialize();
|
||||
refreshAllStores();
|
||||
ToastManager.show({
|
||||
heading: "Backup restored successfully.",
|
||||
@@ -285,9 +285,9 @@ const RestoreDataComponent = ({ close, setRestoring, restoring }) => {
|
||||
|
||||
const backupFiles = await RNFetchBlob.fs.ls(zipOutputFolder);
|
||||
|
||||
// if (backupFiles.findIndex((file) => file === ".nnbackup") === -1) {
|
||||
// throw new Error("Backup file is invalid");
|
||||
// }
|
||||
if (backupFiles.findIndex((file) => file === ".nnbackup") === -1) {
|
||||
throw new Error("Backup file is invalid");
|
||||
}
|
||||
|
||||
await db.transaction(async () => {
|
||||
let password;
|
||||
@@ -384,20 +384,10 @@ const RestoreDataComponent = ({ close, setRestoring, restoring }) => {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
useUserStore.setState({
|
||||
disableAppLockRequests: true
|
||||
});
|
||||
console.log("disabled...");
|
||||
const file = await DocumentPicker.pickSingle({
|
||||
copyTo: "cachesDirectory"
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
useUserStore.setState({
|
||||
disableAppLockRequests: false
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
if (file.name.endsWith(".nnbackupz")) {
|
||||
setRestoring(true);
|
||||
await restoreFromZip(file.fileCopyUri, true);
|
||||
@@ -409,11 +399,6 @@ const RestoreDataComponent = ({ close, setRestoring, restoring }) => {
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("error", e.stack);
|
||||
setTimeout(() => {
|
||||
useUserStore.setState({
|
||||
disableAppLockRequests: false
|
||||
});
|
||||
}, 1000);
|
||||
setRestoring(false);
|
||||
backupError(e);
|
||||
}
|
||||
@@ -430,7 +415,7 @@ const RestoreDataComponent = ({ close, setRestoring, restoring }) => {
|
||||
borderRadius: 0,
|
||||
flexDirection: "row",
|
||||
borderBottomWidth: 0.5,
|
||||
borderBottomColor: colors.primary.border
|
||||
borderBottomColor: colors.secondary.background
|
||||
}}
|
||||
>
|
||||
<View
|
||||
|
||||
@@ -50,7 +50,7 @@ const Sort = ({ type, screen }) => {
|
||||
const setOrderBy = async () => {
|
||||
let _groupOptions = {
|
||||
...groupOptions,
|
||||
sortDirection: groupOptions?.sortDirection === "asc" ? "desc" : "asc"
|
||||
sortDirection: groupOptions.sortDirection === "asc" ? "desc" : "asc"
|
||||
};
|
||||
if (type === "topics") {
|
||||
_groupOptions.groupBy = "none";
|
||||
@@ -85,7 +85,7 @@ const Sort = ({ type, screen }) => {
|
||||
|
||||
<Button
|
||||
title={
|
||||
groupOptions?.sortDirection === "asc"
|
||||
groupOptions.sortDirection === "asc"
|
||||
? groupOptions.groupBy === "abc" ||
|
||||
groupOptions.sortBy === "title"
|
||||
? "A - Z"
|
||||
@@ -100,7 +100,7 @@ const Sort = ({ type, screen }) => {
|
||||
: "New - Old"
|
||||
}
|
||||
icon={
|
||||
groupOptions?.sortDirection === "asc"
|
||||
groupOptions.sortDirection === "asc"
|
||||
? "sort-ascending"
|
||||
: "sort-descending"
|
||||
}
|
||||
@@ -127,7 +127,7 @@ const Sort = ({ type, screen }) => {
|
||||
justifyContent: "flex-start",
|
||||
flexWrap: "wrap",
|
||||
borderBottomWidth: isTopicSheet ? 0 : 1,
|
||||
borderBottomColor: colors.primary.border,
|
||||
borderBottomColor: colors.secondary.background,
|
||||
marginBottom: 12,
|
||||
paddingHorizontal: 12,
|
||||
paddingBottom: 12,
|
||||
@@ -229,7 +229,7 @@ const Sort = ({ type, screen }) => {
|
||||
|
||||
if (item === "abc") {
|
||||
_groupOptions.sortBy = "title";
|
||||
_groupOptions.sortDirection = "desc";
|
||||
_groupOptions.sortDirection = "asc";
|
||||
}
|
||||
|
||||
updateGroupOptions(_groupOptions);
|
||||
|
||||
@@ -170,7 +170,6 @@ export const Update = ({ version: appVersion, fwdRef }) => {
|
||||
lineHeight: 20,
|
||||
marginTop: 10
|
||||
}}
|
||||
selectable
|
||||
>
|
||||
{version.body}
|
||||
</Paragraph>
|
||||
@@ -182,7 +181,6 @@ export const Update = ({ version: appVersion, fwdRef }) => {
|
||||
style={{
|
||||
marginBottom: 5
|
||||
}}
|
||||
selectable
|
||||
>
|
||||
• {item}
|
||||
</Paragraph>
|
||||
|
||||
@@ -43,10 +43,6 @@ export const ColorSection = React.memo(
|
||||
]);
|
||||
const loading = useSettingStore((state) => state.isAppLoading);
|
||||
const setColorNotes = useMenuStore((state) => state.setColorNotes);
|
||||
const [order, hiddensItems] = useMenuStore((state) => [
|
||||
state.order["colors"],
|
||||
state.hiddenItems["colors"]
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!loading) {
|
||||
@@ -63,8 +59,8 @@ export const ColorSection = React.memo(
|
||||
db.settings.setSideBarHiddenItems("colors", data);
|
||||
}}
|
||||
disableDefaultDrag={true}
|
||||
itemOrder={order}
|
||||
hiddenItems={hiddensItems}
|
||||
itemOrder={db.settings.getSideBarOrder("colors")}
|
||||
hiddenItems={db.settings.getSideBarHiddenItems("colors")}
|
||||
alwaysBounceVertical={false}
|
||||
data={colorNotes}
|
||||
style={{
|
||||
|
||||
@@ -19,13 +19,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import React, { useCallback } from "react";
|
||||
import { View } from "react-native";
|
||||
import { DraxProvider, DraxScrollView } from "react-native-drax";
|
||||
import { FlatList, View } from "react-native";
|
||||
import { notesnook } from "../../../e2e/test.ids";
|
||||
import { db } from "../../common/database";
|
||||
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
|
||||
import { DDS } from "../../services/device-detection";
|
||||
import { eSendEvent } from "../../services/event-manager";
|
||||
import { useMenuStore } from "../../stores/use-menu-store";
|
||||
import Navigation from "../../services/navigation";
|
||||
import { useSettingStore } from "../../stores/use-setting-store";
|
||||
import { useThemeStore } from "../../stores/use-theme-store";
|
||||
import { useUserStore } from "../../stores/use-user-store";
|
||||
import { SUBSCRIPTION_STATUS } from "../../utils/constants";
|
||||
import { eOpenPremiumDialog } from "../../utils/events";
|
||||
@@ -47,14 +49,30 @@ export const SideMenu = React.memo(
|
||||
);
|
||||
const isAppLoading = useSettingStore((state) => state.isAppLoading);
|
||||
const dragging = useSideBarDraggingStore((state) => state.dragging);
|
||||
const [order, hiddensItems] = useMenuStore((state) => [
|
||||
state.order["routes"],
|
||||
state.hiddenItems["routes"]
|
||||
]);
|
||||
|
||||
const introCompleted = useSettingStore(
|
||||
(state) => state.settings.introCompleted
|
||||
);
|
||||
const BottomItemsList = [
|
||||
{
|
||||
name: isDark ? "Day" : "Night",
|
||||
icon: "theme-light-dark",
|
||||
func: () => {
|
||||
useThemeStore.getState().setColorScheme();
|
||||
},
|
||||
switch: true,
|
||||
on: !!isDark,
|
||||
close: false
|
||||
},
|
||||
{
|
||||
name: "Settings",
|
||||
icon: "cog-outline",
|
||||
close: true,
|
||||
func: () => {
|
||||
Navigation.navigate("Settings");
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const pro = {
|
||||
name: "Notesnook Pro",
|
||||
@@ -74,8 +92,8 @@ export const SideMenu = React.memo(
|
||||
onHiddenItemsChanged={(data) => {
|
||||
db.settings.setSideBarHiddenItems("routes", data);
|
||||
}}
|
||||
itemOrder={order}
|
||||
hiddenItems={hiddensItems}
|
||||
itemOrder={db.settings.getSideBarOrder("routes")}
|
||||
hiddenItems={db.settings.getSideBarHiddenItems("routes")}
|
||||
alwaysBounceVertical={false}
|
||||
data={MenuItemsList}
|
||||
style={{
|
||||
@@ -97,7 +115,7 @@ export const SideMenu = React.memo(
|
||||
<PinnedSection />
|
||||
</>
|
||||
),
|
||||
[order, hiddensItems]
|
||||
[]
|
||||
);
|
||||
|
||||
return !isAppLoading && introCompleted ? (
|
||||
@@ -116,12 +134,16 @@ export const SideMenu = React.memo(
|
||||
paddingTop: insets.top
|
||||
}}
|
||||
>
|
||||
<DraxProvider>
|
||||
<DraxScrollView nestedScrollEnabled={false}>
|
||||
{renderItem()}
|
||||
</DraxScrollView>
|
||||
</DraxProvider>
|
||||
|
||||
<FlatList
|
||||
alwaysBounceVertical={false}
|
||||
contentContainerStyle={{
|
||||
flexGrow: 1
|
||||
}}
|
||||
showsVerticalScrollIndicator={false}
|
||||
data={[0]}
|
||||
keyExtractor={() => "mainMenuView"}
|
||||
renderItem={renderItem}
|
||||
/>
|
||||
<View
|
||||
style={{
|
||||
paddingHorizontal: 12
|
||||
@@ -131,6 +153,26 @@ export const SideMenu = React.memo(
|
||||
subscriptionType === SUBSCRIPTION_STATUS.BASIC ? (
|
||||
<MenuItem testID={pro.name} key={pro.name} item={pro} index={0} />
|
||||
) : null}
|
||||
|
||||
{BottomItemsList.slice(DDS.isLargeTablet() ? 0 : 1, 3).map(
|
||||
(item, index) => (
|
||||
<MenuItem
|
||||
testID={
|
||||
item.name == "Night mode"
|
||||
? notesnook.ids.menu.nightmode
|
||||
: item.name
|
||||
}
|
||||
key={item.name}
|
||||
item={item}
|
||||
index={index}
|
||||
rightBtn={
|
||||
DDS.isLargeTablet() || item.name === "Notesnook Pro"
|
||||
? undefined
|
||||
: BottomItemsList[0]
|
||||
}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</View>
|
||||
|
||||
{dragging ? (
|
||||
@@ -162,7 +204,14 @@ export const SideMenu = React.memo(
|
||||
/>
|
||||
</View>
|
||||
) : (
|
||||
<UserStatus />
|
||||
<View
|
||||
style={{
|
||||
width: "100%",
|
||||
paddingHorizontal: 0
|
||||
}}
|
||||
>
|
||||
<UserStatus />
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -44,7 +44,7 @@ export const PinnedSection = React.memo(
|
||||
const menuPins = useMenuStore((state) => state.menuPins);
|
||||
const loading = useSettingStore((state) => state.isAppLoading);
|
||||
const setMenuPins = useMenuStore((state) => state.setMenuPins);
|
||||
const [order] = useMenuStore((state) => [state.order["shortcuts"]]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!loading) {
|
||||
setMenuPins();
|
||||
@@ -61,13 +61,7 @@ export const PinnedSection = React.memo(
|
||||
Navigation.closeDrawer();
|
||||
});
|
||||
};
|
||||
const renderItem = ({
|
||||
item,
|
||||
index
|
||||
}: {
|
||||
item: Notebook | Tag;
|
||||
index: number;
|
||||
}) => {
|
||||
const renderItem = ({ item }: { item: Notebook | Tag; index: number }) => {
|
||||
return <PinItem item={item} onPress={onPress} />;
|
||||
};
|
||||
|
||||
@@ -83,7 +77,7 @@ export const PinnedSection = React.memo(
|
||||
}}
|
||||
onHiddenItemsChanged={(data) => {}}
|
||||
canHideItems={false}
|
||||
itemOrder={order}
|
||||
itemOrder={db.settings.getSideBarOrder("shortcuts")}
|
||||
hiddenItems={[]}
|
||||
alwaysBounceVertical={false}
|
||||
data={menuPins}
|
||||
@@ -100,10 +94,7 @@ export const PinnedSection = React.memo(
|
||||
<Notice
|
||||
size="small"
|
||||
type="information"
|
||||
text="Add shortcuts for notebooks and tags here."
|
||||
style={{
|
||||
marginHorizontal: 12
|
||||
}}
|
||||
text="Add shortcuts for notebooks, topics and tags here."
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -25,20 +25,19 @@ import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
|
||||
import useSyncProgress from "../../hooks/use-sync-progress";
|
||||
import { eSendEvent } from "../../services/event-manager";
|
||||
import Navigation from "../../services/navigation";
|
||||
import Sync from "../../services/sync";
|
||||
import { useThemeStore } from "../../stores/use-theme-store";
|
||||
import { SyncStatus, useUserStore } from "../../stores/use-user-store";
|
||||
import { eOpenLoginDialog } from "../../utils/events";
|
||||
import { tabBarRef } from "../../utils/global-refs";
|
||||
import { SIZE } from "../../utils/size";
|
||||
import { IconButton } from "../ui/icon-button";
|
||||
import { Pressable } from "../ui/pressable";
|
||||
import { TimeSince } from "../ui/time-since";
|
||||
import Paragraph from "../ui/typography/paragraph";
|
||||
|
||||
const PROFILE_PIC_URL = `https://picsum.photos/id/177/367/267`;
|
||||
|
||||
export const UserStatus = () => {
|
||||
const { colors, isDark } = useThemeColors();
|
||||
const { colors } = useThemeColors();
|
||||
const user = useUserStore((state) => state.user);
|
||||
const syncing = useUserStore((state) => state.syncing);
|
||||
const lastSyncStatus = useUserStore((state) => state.lastSyncStatus);
|
||||
@@ -56,8 +55,7 @@ export const UserStatus = () => {
|
||||
alignSelf: "center",
|
||||
paddingBottom: Platform.OS === "ios" ? insets.bottom / 2 : null,
|
||||
borderTopWidth: 1,
|
||||
borderTopColor: colors.primary.border,
|
||||
backgroundColor: colors.primary.background
|
||||
borderTopColor: colors.secondary.background
|
||||
}}
|
||||
>
|
||||
<View
|
||||
@@ -68,9 +66,13 @@ export const UserStatus = () => {
|
||||
}}
|
||||
>
|
||||
<Pressable
|
||||
onPress={() => {
|
||||
Navigation.navigate("Settings");
|
||||
tabBarRef.current.closeDrawer();
|
||||
onPress={async () => {
|
||||
if (user) {
|
||||
Sync.run();
|
||||
} else {
|
||||
tabBarRef.current?.closeDrawer();
|
||||
eSendEvent(eOpenLoginDialog);
|
||||
}
|
||||
}}
|
||||
type="plain"
|
||||
style={{
|
||||
@@ -78,8 +80,7 @@ export const UserStatus = () => {
|
||||
justifyContent: "flex-start",
|
||||
padding: 12,
|
||||
borderRadius: 0,
|
||||
alignItems: "center",
|
||||
gap: 10
|
||||
alignItems: "center"
|
||||
}}
|
||||
>
|
||||
{userProfile?.profilePicture ? (
|
||||
@@ -90,19 +91,11 @@ export const UserStatus = () => {
|
||||
style={{
|
||||
width: 35,
|
||||
height: 35,
|
||||
borderRadius: 100
|
||||
borderRadius: 100,
|
||||
marginRight: 10
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Icon
|
||||
name="cog-outline"
|
||||
size={SIZE.lg - 2}
|
||||
color={colors.secondary.icon}
|
||||
style={{
|
||||
paddingLeft: 8
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
) : null}
|
||||
|
||||
<View
|
||||
style={{
|
||||
@@ -111,12 +104,22 @@ export const UserStatus = () => {
|
||||
}}
|
||||
>
|
||||
<Paragraph
|
||||
numberOfLines={1}
|
||||
style={{
|
||||
flexWrap: "wrap"
|
||||
}}
|
||||
size={SIZE.sm}
|
||||
color={colors.primary.heading}
|
||||
>
|
||||
{!user || !userProfile?.fullName
|
||||
? "Settings"
|
||||
{!user
|
||||
? "Login to sync your notes."
|
||||
: lastSyncStatus === SyncStatus.Failed
|
||||
? "Sync failed, tap to retry"
|
||||
: syncing
|
||||
? `Syncing your notes${
|
||||
progress ? ` (${progress.current})` : ""
|
||||
}`
|
||||
: !userProfile?.fullName
|
||||
? "Tap to sync"
|
||||
: userProfile.fullName}
|
||||
</Paragraph>
|
||||
|
||||
@@ -131,20 +134,16 @@ export const UserStatus = () => {
|
||||
"Not logged in"
|
||||
) : lastSynced && lastSynced !== "Never" ? (
|
||||
<>
|
||||
{syncing
|
||||
? `Syncing ${progress ? `(${progress.current})` : ""}`
|
||||
: lastSyncStatus === SyncStatus.Failed
|
||||
{lastSyncStatus === SyncStatus.Failed
|
||||
? "Sync failed"
|
||||
: "Synced"}{" "}
|
||||
{!syncing ? (
|
||||
<TimeSince
|
||||
style={{
|
||||
fontSize: SIZE.xs,
|
||||
color: colors.secondary.paragraph
|
||||
}}
|
||||
time={lastSynced}
|
||||
/>
|
||||
) : null}
|
||||
<TimeSince
|
||||
style={{
|
||||
fontSize: SIZE.xs,
|
||||
color: colors.secondary.paragraph
|
||||
}}
|
||||
time={lastSynced}
|
||||
/>
|
||||
{isOffline ? " (offline)" : ""}
|
||||
</>
|
||||
) : (
|
||||
@@ -152,7 +151,7 @@ export const UserStatus = () => {
|
||||
)}{" "}
|
||||
<Icon
|
||||
name="checkbox-blank-circle"
|
||||
size={9}
|
||||
size={11}
|
||||
allowFontScaling
|
||||
color={
|
||||
!user || lastSyncStatus === SyncStatus.Failed
|
||||
@@ -165,80 +164,25 @@ export const UserStatus = () => {
|
||||
</Paragraph>
|
||||
</View>
|
||||
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
gap: 0
|
||||
}}
|
||||
>
|
||||
<IconButton
|
||||
hitSlop={{
|
||||
top: 10,
|
||||
bottom: 10
|
||||
}}
|
||||
onPress={() => {
|
||||
useThemeStore.getState().setColorScheme();
|
||||
}}
|
||||
name="theme-light-dark"
|
||||
color={isDark ? colors.primary.accent : colors.primary.icon}
|
||||
size={SIZE.lg}
|
||||
style={{
|
||||
borderRadius: 100,
|
||||
width: 40,
|
||||
height: 40
|
||||
}}
|
||||
/>
|
||||
|
||||
<Pressable
|
||||
style={{
|
||||
borderRadius: 100,
|
||||
width: 40,
|
||||
height: 40
|
||||
}}
|
||||
hitSlop={{
|
||||
top: 10,
|
||||
bottom: 10
|
||||
}}
|
||||
onPress={() => {
|
||||
if (user) {
|
||||
Sync.run();
|
||||
} else {
|
||||
tabBarRef.current?.closeDrawer();
|
||||
eSendEvent(eOpenLoginDialog);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{user ? (
|
||||
syncing ? (
|
||||
<ActivityIndicator
|
||||
color={colors.primary.accent}
|
||||
size={SIZE.xl}
|
||||
/>
|
||||
) : lastSyncStatus === SyncStatus.Failed ? (
|
||||
<Icon
|
||||
color={colors.error.icon}
|
||||
name="sync-alert"
|
||||
size={SIZE.lg}
|
||||
allowFontScaling
|
||||
/>
|
||||
) : (
|
||||
<Icon
|
||||
allowFontScaling
|
||||
color={colors.primary.icon}
|
||||
name="sync"
|
||||
size={SIZE.lg}
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
<Icon
|
||||
allowFontScaling
|
||||
color={colors.primary.accent}
|
||||
size={SIZE.lg}
|
||||
name="login"
|
||||
/>
|
||||
)}
|
||||
</Pressable>
|
||||
</View>
|
||||
{user ? (
|
||||
syncing ? (
|
||||
<ActivityIndicator color={colors.primary.accent} size={SIZE.xl} />
|
||||
) : lastSyncStatus === SyncStatus.Failed ? (
|
||||
<Icon
|
||||
color={colors.error.icon}
|
||||
name="sync-alert"
|
||||
size={SIZE.lg}
|
||||
allowFontScaling
|
||||
/>
|
||||
) : (
|
||||
<Icon
|
||||
allowFontScaling
|
||||
color={colors.primary.accent}
|
||||
name="sync"
|
||||
size={SIZE.lg}
|
||||
/>
|
||||
)
|
||||
) : null}
|
||||
</Pressable>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -59,7 +59,7 @@ export interface TabsRef {
|
||||
lock: () => boolean;
|
||||
openDrawer: (animated?: boolean) => void;
|
||||
closeDrawer: (animated?: boolean) => void;
|
||||
page: () => number;
|
||||
page: number;
|
||||
setScrollEnabled: () => true;
|
||||
isDrawerOpen: () => boolean;
|
||||
node: RefObject<Animated.View>;
|
||||
@@ -121,12 +121,7 @@ export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
|
||||
} else {
|
||||
if (prevWidths.current?.sidebar !== widths.sidebar) {
|
||||
translateX.value =
|
||||
!appState || (appState && appState?.movedAway)
|
||||
? widths.sidebar
|
||||
: editorPosition;
|
||||
if (translateX.value === editorPosition) {
|
||||
onChangeTab?.({ i: 2, from: 1 });
|
||||
}
|
||||
!appState || appState?.movedAway ? widths.sidebar : editorPosition;
|
||||
}
|
||||
}
|
||||
isLoaded.current = true;
|
||||
@@ -239,7 +234,7 @@ export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
|
||||
onDrawerStateChange(false);
|
||||
isDrawerOpen.value = false;
|
||||
},
|
||||
page: () => currentTab.value,
|
||||
page: currentTab.value,
|
||||
setScrollEnabled: () => true,
|
||||
node: node
|
||||
}),
|
||||
|
||||
@@ -28,7 +28,6 @@ import { Toast } from "../../toast";
|
||||
import { useAppState } from "../../../hooks/use-app-state";
|
||||
import SettingsService from "../../../services/settings";
|
||||
import { useUserStore } from "../../../stores/use-user-store";
|
||||
import { getContainerBorder } from "../../../utils/colors";
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -74,17 +73,9 @@ const SheetWrapper = ({
|
||||
borderTopLeftRadius: 15,
|
||||
alignSelf: "center",
|
||||
borderBottomRightRadius: 0,
|
||||
borderBottomLeftRadius: 0,
|
||||
...getContainerBorder(colors.primary.border, 0.5),
|
||||
borderBottomWidth: 0
|
||||
borderBottomLeftRadius: 0
|
||||
};
|
||||
}, [
|
||||
colors.primary.background,
|
||||
colors.primary.border,
|
||||
largeTablet,
|
||||
smallTablet,
|
||||
width
|
||||
]);
|
||||
}, [colors.primary.background, largeTablet, smallTablet, width]);
|
||||
|
||||
const _onOpen = () => {
|
||||
if (lockEvents.current) return;
|
||||
|
||||