Compare commits
663 Commits
fix-remind
...
3.0.11-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d85ca35db | ||
|
|
71aaaf4801 | ||
|
|
1ae7b232ed | ||
|
|
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
|
||||
|
||||
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
|
||||
|
||||
|
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.0",
|
||||
"version": "3.0.8-beta",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@notesnook/desktop",
|
||||
"version": "3.0.0",
|
||||
"version": "3.0.8-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.0",
|
||||
"version": "3.0.8-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({});
|
||||
|
||||
@@ -170,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
|
||||
);
|
||||
};
|
||||
});
|
||||
})
|
||||
});
|
||||
@@ -82,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,
|
||||
@@ -135,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);
|
||||
@@ -151,15 +138,6 @@ async function createWindow() {
|
||||
app.once("ready", async () => {
|
||||
console.info("App ready. Opening window.");
|
||||
|
||||
app.configureHostResolver({
|
||||
secureDnsServers: [
|
||||
"https://mozilla.cloudflare-dns.com/dns-query",
|
||||
"https://dns.quad9.net/dns-query"
|
||||
],
|
||||
enableBuiltInResolver: true,
|
||||
secureDnsMode: "automatic"
|
||||
});
|
||||
|
||||
if (!isDevelopment()) registerProtocol();
|
||||
await createWindow();
|
||||
configureAutoUpdater();
|
||||
|
||||
@@ -42,11 +42,7 @@ export const config = {
|
||||
zoomFactor: 1,
|
||||
theme: nativeTheme.themeSource,
|
||||
automaticUpdates: true,
|
||||
proxyRules: "",
|
||||
|
||||
backgroundColor: nativeTheme.themeSource === "dark" ? "#0f0f0f" : "#ffffff",
|
||||
windowControlsIconColor:
|
||||
nativeTheme.themeSource === "dark" ? "#ffffff" : "#000000"
|
||||
proxyRules: ""
|
||||
};
|
||||
|
||||
type ConfigKey = keyof typeof config;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -67,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");
|
||||
@@ -77,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"
|
||||
|
||||
@@ -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]);
|
||||
|
||||
|
||||
@@ -221,7 +221,7 @@ const Actions = ({
|
||||
<View
|
||||
style={{
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: colors.primary.border,
|
||||
borderBottomColor: colors.secondary.background,
|
||||
marginBottom: notes && notes.length > 0 ? 0 : 12
|
||||
}}
|
||||
>
|
||||
@@ -295,7 +295,7 @@ const Actions = ({
|
||||
<View
|
||||
style={{
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: colors.primary.border,
|
||||
borderBottomColor: colors.secondary.background,
|
||||
marginBottom: 12,
|
||||
paddingVertical: 12
|
||||
}}
|
||||
|
||||
@@ -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 ? (
|
||||
|
||||
@@ -314,7 +314,6 @@ export const AppLockPassword = () => {
|
||||
new Error(
|
||||
`${keyboardType === "pin" ? "Pin" : "Password"} incorrect`
|
||||
),
|
||||
undefined,
|
||||
"local"
|
||||
);
|
||||
return;
|
||||
@@ -327,7 +326,6 @@ export const AppLockPassword = () => {
|
||||
SettingsService.getProperty("biometricsAuthEnabled") === false
|
||||
) {
|
||||
SettingsService.setProperty("appLockEnabled", false);
|
||||
SettingsService.setPrivacyScreen(SettingsService.get());
|
||||
ToastManager.show({
|
||||
message: "App lock disabled",
|
||||
type: "success"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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"
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -44,7 +44,6 @@ import ExportNotesSheet from "../sheets/export-notes";
|
||||
import ManageTagsSheet from "../sheets/manage-tags";
|
||||
import { IconButton } from "../ui/icon-button";
|
||||
import Heading from "../ui/typography/heading";
|
||||
import { MoveNotebookSheet } from "../sheets/move-notebook";
|
||||
|
||||
export const SelectionHeader = React.memo(
|
||||
({
|
||||
@@ -214,24 +213,7 @@ export const SelectionHeader = React.memo(
|
||||
size={SIZE.xl}
|
||||
/>
|
||||
|
||||
{renderedInRoute === "Notebooks" && selectedItemsList.length ? (
|
||||
<IconButton
|
||||
style={{
|
||||
marginLeft: 10
|
||||
}}
|
||||
onPress={async () => {
|
||||
const ids = selectedItemsList;
|
||||
const notebooks = await db.notebooks.all.items(ids);
|
||||
MoveNotebookSheet.present(notebooks);
|
||||
}}
|
||||
tooltipText="Move notebooks"
|
||||
tooltipPosition={1}
|
||||
name="arrow-right-bold-box-outline"
|
||||
size={SIZE.xl}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{type !== "note" || !selectedItemsList.length ? null : (
|
||||
{type !== "note" ? null : (
|
||||
<>
|
||||
<IconButton
|
||||
onPress={async () => {
|
||||
@@ -278,14 +260,16 @@ export const SelectionHeader = React.memo(
|
||||
</>
|
||||
)}
|
||||
|
||||
{renderedInRoute === "Notebook" && selectedItemsList.length ? (
|
||||
{renderedInRoute === "Notebook" ? (
|
||||
<IconButton
|
||||
onPress={async () => {
|
||||
if (!id) return;
|
||||
await db.notes.removeFromNotebook(id, ...selectedItemsList);
|
||||
updateNotebook(id);
|
||||
Navigation.queueRoutesForUpdate();
|
||||
clearSelection();
|
||||
if (selectedItemsList.length > 0) {
|
||||
if (!id) return;
|
||||
await db.notes.removeFromNotebook(id, ...selectedItemsList);
|
||||
updateNotebook(id);
|
||||
Navigation.queueRoutesForUpdate();
|
||||
clearSelection();
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
marginLeft: 10
|
||||
@@ -299,7 +283,7 @@ export const SelectionHeader = React.memo(
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{focusedRouteId === "Favorites" && selectedItemsList.length ? (
|
||||
{focusedRouteId === "Favorites" ? (
|
||||
<IconButton
|
||||
onPress={addToFavorite}
|
||||
style={{
|
||||
@@ -313,7 +297,7 @@ export const SelectionHeader = React.memo(
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{type === "trash" || !selectedItemsList.length ? null : (
|
||||
{type === "trash" ? null : (
|
||||
<IconButton
|
||||
style={{
|
||||
marginLeft: 10
|
||||
@@ -335,7 +319,7 @@ export const SelectionHeader = React.memo(
|
||||
/>
|
||||
)}
|
||||
|
||||
{type === "trash" && selectedItemsList.length ? (
|
||||
{type === "trash" ? (
|
||||
<>
|
||||
<IconButton
|
||||
style={{
|
||||
|
||||
@@ -39,18 +39,15 @@ 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
|
||||
close
|
||||
}: {
|
||||
notebook?: Notebook;
|
||||
parentNotebook?: Notebook;
|
||||
close?: (didAddNotebook: boolean) => void;
|
||||
showMoveNotesOnComplete: boolean;
|
||||
close: ((context?: string | undefined) => void) | undefined;
|
||||
}) => {
|
||||
const title = useRef(notebook?.title);
|
||||
const description = useRef(notebook?.description);
|
||||
@@ -88,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));
|
||||
@@ -101,10 +97,10 @@ export const AddNotebookSheet = ({
|
||||
});
|
||||
}
|
||||
|
||||
if (!notebook && showMoveNotesOnComplete) {
|
||||
if (!notebook) {
|
||||
MoveNotes.present(await db.notebooks.notebook(id));
|
||||
} else {
|
||||
close?.(true);
|
||||
close?.();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -173,8 +169,7 @@ AddNotebookSheet.present = (
|
||||
notebook?: Notebook,
|
||||
parentNotebook?: Notebook,
|
||||
context?: string,
|
||||
onClose?: (didAddNotebook: boolean) => void,
|
||||
showMoveNotesOnComplete = true
|
||||
onClose?: () => void
|
||||
) => {
|
||||
presentSheet({
|
||||
context: context,
|
||||
@@ -182,12 +177,9 @@ AddNotebookSheet.present = (
|
||||
<AddNotebookSheet
|
||||
notebook={notebook}
|
||||
parentNotebook={parentNotebook}
|
||||
close={(didAddNotebook: boolean) => {
|
||||
close?.();
|
||||
onClose?.(didAddNotebook);
|
||||
}}
|
||||
showMoveNotesOnComplete={showMoveNotesOnComplete || false}
|
||||
close={close}
|
||||
/>
|
||||
)
|
||||
),
|
||||
onClose: onClose
|
||||
});
|
||||
};
|
||||
|
||||
@@ -46,7 +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";
|
||||
|
||||
async function updateInitialSelectionState(items: string[]) {
|
||||
const relations = await db.relations
|
||||
@@ -142,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} />
|
||||
@@ -186,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."
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -196,21 +190,18 @@ const MoveNoteSheet = ({
|
||||
columnGap: 10
|
||||
}}
|
||||
>
|
||||
{hasSelected() ? (
|
||||
<IconButton
|
||||
name="restore"
|
||||
type="secondaryAccented"
|
||||
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}
|
||||
@@ -239,36 +230,6 @@ const MoveNoteSheet = ({
|
||||
style={{
|
||||
width: "100%"
|
||||
}}
|
||||
ListHeaderComponent={
|
||||
<View
|
||||
style={{
|
||||
paddingHorizontal: 12,
|
||||
width: "100%"
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
title="Add new notebook"
|
||||
style={{
|
||||
alignSelf: "flex-start",
|
||||
paddingHorizontal: 12,
|
||||
justifyContent: "space-between"
|
||||
}}
|
||||
onPress={() => {
|
||||
AddNotebookSheet.present(
|
||||
undefined,
|
||||
undefined,
|
||||
"link-notebooks",
|
||||
undefined,
|
||||
false
|
||||
);
|
||||
}}
|
||||
icon="plus"
|
||||
iconPosition="right"
|
||||
type="secondaryAccented"
|
||||
width="100%"
|
||||
/>
|
||||
</View>
|
||||
}
|
||||
estimatedItemSize={50}
|
||||
renderItem={renderNotebook}
|
||||
ListEmptyComponent={
|
||||
@@ -304,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",
|
||||
|
||||
@@ -159,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,344 +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 } 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 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",
|
||||
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
|
||||
}}
|
||||
>
|
||||
<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?.();
|
||||
}}
|
||||
/>
|
||||
</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;
|
||||
};
|
||||
|
||||
@@ -44,8 +44,6 @@ import { Pressable } from "../../ui/pressable";
|
||||
import Paragraph from "../../ui/typography/paragraph";
|
||||
import { AddNotebookSheet } from "../add-notebook";
|
||||
import Sort from "../sort";
|
||||
import { MoveNotebookSheet } from "../move-notebook";
|
||||
import { db } from "../../../common/database";
|
||||
|
||||
const useItemSelectionStore = createItemSelectionStore(true, false);
|
||||
|
||||
@@ -139,7 +137,7 @@ export const NotebookSheet = () => {
|
||||
currentItem.current = nextRoot;
|
||||
const snapPoint = NotebookSheetConfig.get({
|
||||
type: "notebook",
|
||||
id: focusedRouteId as string
|
||||
id: nextRoot as string
|
||||
});
|
||||
|
||||
if (ref.current?.isOpen()) {
|
||||
@@ -203,47 +201,6 @@ export const NotebookSheet = () => {
|
||||
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.accent}
|
||||
size={SIZE.xxl}
|
||||
/>
|
||||
</View>
|
||||
</Pressable>
|
||||
</View>
|
||||
|
||||
<View
|
||||
style={{
|
||||
position: "absolute",
|
||||
@@ -263,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} />
|
||||
@@ -321,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,
|
||||
@@ -382,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.",
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,15 +19,13 @@ 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 Navigation from "../../services/navigation";
|
||||
import { useMenuStore } from "../../stores/use-menu-store";
|
||||
import { useSettingStore } from "../../stores/use-setting-store";
|
||||
import { useThemeStore } from "../../stores/use-theme-store";
|
||||
import { useUserStore } from "../../stores/use-user-store";
|
||||
@@ -51,10 +49,6 @@ 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
|
||||
@@ -98,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={{
|
||||
@@ -140,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
|
||||
@@ -155,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 ? (
|
||||
@@ -186,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."
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -20,13 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import { useNetInfo } from "@react-native-community/netinfo";
|
||||
import React from "react";
|
||||
import {
|
||||
ActivityIndicator,
|
||||
Image,
|
||||
Platform,
|
||||
TouchableOpacity,
|
||||
View
|
||||
} from "react-native";
|
||||
import { ActivityIndicator, Image, Platform, View } from "react-native";
|
||||
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
|
||||
import useSyncProgress from "../../hooks/use-sync-progress";
|
||||
@@ -39,7 +33,8 @@ import { SIZE } from "../../utils/size";
|
||||
import { Pressable } from "../ui/pressable";
|
||||
import { TimeSince } from "../ui/time-since";
|
||||
import Paragraph from "../ui/typography/paragraph";
|
||||
import Navigation from "../../services/navigation";
|
||||
|
||||
const PROFILE_PIC_URL = `https://picsum.photos/id/177/367/267`;
|
||||
|
||||
export const UserStatus = () => {
|
||||
const { colors } = useThemeColors();
|
||||
@@ -60,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
|
||||
@@ -72,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={{
|
||||
@@ -82,8 +80,7 @@ export const UserStatus = () => {
|
||||
justifyContent: "flex-start",
|
||||
padding: 12,
|
||||
borderRadius: 0,
|
||||
alignItems: "center",
|
||||
gap: 10
|
||||
alignItems: "center"
|
||||
}}
|
||||
>
|
||||
{userProfile?.profilePicture ? (
|
||||
@@ -94,7 +91,8 @@ export const UserStatus = () => {
|
||||
style={{
|
||||
width: 35,
|
||||
height: 35,
|
||||
borderRadius: 100
|
||||
borderRadius: 100,
|
||||
marginRight: 10
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
@@ -106,7 +104,9 @@ export const UserStatus = () => {
|
||||
}}
|
||||
>
|
||||
<Paragraph
|
||||
numberOfLines={1}
|
||||
style={{
|
||||
flexWrap: "wrap"
|
||||
}}
|
||||
size={SIZE.sm}
|
||||
color={colors.primary.heading}
|
||||
>
|
||||
@@ -115,7 +115,9 @@ export const UserStatus = () => {
|
||||
: lastSyncStatus === SyncStatus.Failed
|
||||
? "Sync failed, tap to retry"
|
||||
: syncing
|
||||
? `Syncing ${progress ? `(${progress.current})` : ""}`
|
||||
? `Syncing your notes${
|
||||
progress ? ` (${progress.current})` : ""
|
||||
}`
|
||||
: !userProfile?.fullName
|
||||
? "Tap to sync"
|
||||
: userProfile.fullName}
|
||||
@@ -162,56 +164,25 @@ export const UserStatus = () => {
|
||||
</Paragraph>
|
||||
</View>
|
||||
|
||||
<Pressable
|
||||
style={{
|
||||
borderRadius: 100,
|
||||
width: 40,
|
||||
height: 40
|
||||
}}
|
||||
hitSlop={{
|
||||
top: 10,
|
||||
bottom: 10,
|
||||
left: 20
|
||||
}}
|
||||
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.accent}
|
||||
name="sync"
|
||||
size={SIZE.lg}
|
||||
/>
|
||||
)
|
||||
{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}
|
||||
name="login"
|
||||
/>
|
||||
)}
|
||||
</Pressable>
|
||||
)
|
||||
) : null}
|
||||
</Pressable>
|
||||
</View>
|
||||
</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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -129,9 +129,9 @@ const notebooks: { id: string; steps: TStep[] } = {
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Notebook > Notes",
|
||||
text: "Every Notebook can have notes and sub notebooks.",
|
||||
walkthroughItem: (colors: any) => (
|
||||
title: "Notebook > Topic > Notes",
|
||||
text: "Every Notebook has various topics which are like sections that hold all your notes.",
|
||||
walkthroughItem: (colors: ThemeStore["colors"]) => (
|
||||
<View
|
||||
style={{
|
||||
width: "100%",
|
||||
@@ -245,7 +245,7 @@ const notebooks: { id: string; steps: TStep[] } = {
|
||||
},
|
||||
{
|
||||
title: "Easy access",
|
||||
text: "You can create shortcuts of frequently accessed notebooks in the side menu",
|
||||
text: "You can create shortcuts of frequently accessed notebooks or topics in Side Menu",
|
||||
walkthroughItem: () => (
|
||||
<View
|
||||
style={{
|
||||
|
||||
@@ -19,35 +19,4 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { FeatureType } from "./components/sheets/new-feature";
|
||||
|
||||
export const features: FeatureType[] = [
|
||||
{
|
||||
title: "Bi-directional note linking",
|
||||
body: "Now you can link notes to each other in both directions."
|
||||
},
|
||||
{
|
||||
title: "Tabs",
|
||||
body: "Tabs allow you to have multiple notes open at the same time. You can switch between them easily."
|
||||
},
|
||||
{
|
||||
title: "Nested notebooks",
|
||||
body: "You can now create notebooks inside other notebooks."
|
||||
},
|
||||
{
|
||||
title: "At-rest encryption",
|
||||
body: "Your notes are now encrypted when stored on the device."
|
||||
},
|
||||
{
|
||||
title: "Material You themed icon",
|
||||
body: "The app now has a Material You themed icon that changes color based on the wallpaper.",
|
||||
platform: "android"
|
||||
},
|
||||
{
|
||||
title: "New note quick settings tile",
|
||||
body: "You can now add a new note tile to quickly create notes from quick settings panel.",
|
||||
platform: "android"
|
||||
},
|
||||
{
|
||||
title: "And so much more...",
|
||||
body: "V3 packs so much that it's hard to put everything here, check out our blog at Notesnook V3 is here, and it's packed with new features and improvements such as bi-directional note linking, better syncing, at-rest encryption, nested notebooks, editor tabs, better app lock and so much more. https://blog.notesnook.com/introducing-notesnook-v3."
|
||||
}
|
||||
];
|
||||
export const features: FeatureType[] = [];
|
||||
|
||||
@@ -67,7 +67,6 @@ import { convertNoteToText } from "../utils/note-to-text";
|
||||
import { sleep } from "../utils/time";
|
||||
import { ReferencesList } from "../components/sheets/references";
|
||||
import { createInternalLink } from "@notesnook/core";
|
||||
import { MoveNotebookSheet } from "../components/sheets/move-notebook";
|
||||
|
||||
export const useActions = ({
|
||||
close,
|
||||
@@ -198,22 +197,19 @@ export const useActions = ({
|
||||
paragraph: "Change the title of the tag " + item.title,
|
||||
positivePress: async (value: string) => {
|
||||
if (!value || value === "" || value.trimStart().length == 0) return;
|
||||
try {
|
||||
await db.tags.add({
|
||||
id: item.id,
|
||||
title: value
|
||||
});
|
||||
|
||||
eSendEvent(Navigation.routeNames.TaggedNotes);
|
||||
InteractionManager.runAfterInteractions(() => {
|
||||
useTagStore.getState().refresh();
|
||||
useMenuStore.getState().setMenuPins();
|
||||
Navigation.queueRoutesForUpdate();
|
||||
useRelationStore.getState().update();
|
||||
});
|
||||
} catch (e) {
|
||||
ToastManager.error(e as Error, undefined, "local");
|
||||
}
|
||||
await db.tags.add({
|
||||
id: item.id,
|
||||
title: value
|
||||
});
|
||||
|
||||
eSendEvent(Navigation.routeNames.TaggedNotes);
|
||||
InteractionManager.runAfterInteractions(() => {
|
||||
useTagStore.getState().refresh();
|
||||
useMenuStore.getState().setMenuPins();
|
||||
Navigation.queueRoutesForUpdate();
|
||||
useRelationStore.getState().update();
|
||||
});
|
||||
},
|
||||
input: true,
|
||||
defaultValue: item.title,
|
||||
@@ -491,14 +487,6 @@ export const useActions = ({
|
||||
func: () => {
|
||||
MoveNotes.present(item);
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "move-notebook",
|
||||
title: "Move notebook",
|
||||
icon: "arrow-right-bold-box-outline",
|
||||
func: () => {
|
||||
MoveNotebookSheet.present([item]);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -748,45 +736,41 @@ export const useActions = ({
|
||||
}
|
||||
|
||||
async function copyContent() {
|
||||
try {
|
||||
if (processingId.current === "copyContent") {
|
||||
ToastManager.show({
|
||||
heading: "Please wait...",
|
||||
message: "We are preparing your note for copy to clipboard",
|
||||
context: "local"
|
||||
});
|
||||
if (processingId.current === "copyContent") {
|
||||
ToastManager.show({
|
||||
heading: "Please wait...",
|
||||
message: "We are preparing your note for copy to clipboard",
|
||||
context: "local"
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!checkItemSynced()) return;
|
||||
if (locked) {
|
||||
close();
|
||||
await sleep(300);
|
||||
openVault({
|
||||
copyNote: true,
|
||||
novault: true,
|
||||
locked: true,
|
||||
item: item,
|
||||
title: "Copy note",
|
||||
description: "Unlock note to copy to clipboard."
|
||||
});
|
||||
} else {
|
||||
processingId.current = "copyContent";
|
||||
|
||||
const text = await convertNoteToText(item as Note, true);
|
||||
if (!text) {
|
||||
ToastManager.error(new Error(Errors.export("text")));
|
||||
return;
|
||||
}
|
||||
|
||||
if (locked) {
|
||||
close();
|
||||
await sleep(300);
|
||||
openVault({
|
||||
copyNote: true,
|
||||
novault: true,
|
||||
locked: true,
|
||||
item: item,
|
||||
title: "Copy note",
|
||||
description: "Unlock note to copy to clipboard."
|
||||
});
|
||||
} else {
|
||||
processingId.current = "copyContent";
|
||||
const text = await convertNoteToText(item as Note, true);
|
||||
if (!text) {
|
||||
ToastManager.error(new Error(Errors.export("text")));
|
||||
return;
|
||||
}
|
||||
Clipboard.setString(text);
|
||||
processingId.current = undefined;
|
||||
ToastManager.show({
|
||||
heading: "Note copied to clipboard",
|
||||
type: "success",
|
||||
context: "local"
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
ToastManager.error(e as Error);
|
||||
Clipboard.setString(text);
|
||||
processingId.current = undefined;
|
||||
ToastManager.show({
|
||||
heading: "Note copied to clipboard",
|
||||
type: "success",
|
||||
context: "local"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,14 +17,12 @@ 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 { User } from "@notesnook/core";
|
||||
import {
|
||||
EV,
|
||||
EVENTS,
|
||||
SYNC_CHECK_IDS,
|
||||
SyncStatusEvent
|
||||
} from "@notesnook/core/dist/common";
|
||||
import { EventManagerSubscription } from "@notesnook/core/dist/utils/event-manager";
|
||||
import notifee from "@notifee/react-native";
|
||||
import NetInfo, {
|
||||
NetInfoState,
|
||||
@@ -46,6 +44,10 @@ import RNBootSplash from "react-native-bootsplash";
|
||||
import { checkVersion } from "react-native-check-version";
|
||||
import Config from "react-native-config";
|
||||
import * as RNIap from "react-native-iap";
|
||||
import { User } from "@notesnook/core";
|
||||
import { EventManagerSubscription } from "@notesnook/core/dist/utils/event-manager";
|
||||
//@ts-ignore
|
||||
import { enabled } from "react-native-privacy-snapshot";
|
||||
import { DatabaseLogger, db, setupDatabase } from "../common/database";
|
||||
import { MMKV } from "../common/database/mmkv";
|
||||
import Migrate from "../components/sheets/migrate";
|
||||
@@ -73,7 +75,6 @@ import {
|
||||
setRecoveryKeyMessage,
|
||||
setUpdateAvailableMessage
|
||||
} from "../services/message";
|
||||
import Notifications from "../services/notifications";
|
||||
import PremiumService from "../services/premium";
|
||||
import SettingsService from "../services/settings";
|
||||
import Sync from "../services/sync";
|
||||
@@ -83,7 +84,6 @@ import { useMessageStore } from "../stores/use-message-store";
|
||||
import { useSettingStore } from "../stores/use-setting-store";
|
||||
import { SyncStatus, useUserStore } from "../stores/use-user-store";
|
||||
import { updateStatusBarColor } from "../utils/colors";
|
||||
import { BETA } from "../utils/constants";
|
||||
import {
|
||||
eClearEditor,
|
||||
eCloseSheet,
|
||||
@@ -97,6 +97,8 @@ import {
|
||||
import { getGithubVersion } from "../utils/github-version";
|
||||
import { tabBarRef } from "../utils/global-refs";
|
||||
import { sleep } from "../utils/time";
|
||||
import Notifications from "../services/notifications";
|
||||
import { BETA } from "../utils/constants";
|
||||
|
||||
const onCheckSyncStatus = async (type: SyncStatusEvent) => {
|
||||
const { disableSync, disableAutoSync } = SettingsService.get();
|
||||
@@ -244,19 +246,19 @@ async function checkForShareExtensionLaunchedInBackground() {
|
||||
}
|
||||
|
||||
async function saveEditorState() {
|
||||
if (!editorState().movedAway) {
|
||||
if (editorState().currentlyEditing) {
|
||||
const id = useTabStore.getState().getCurrentNoteId();
|
||||
const note = id ? await db.notes.note(id) : undefined;
|
||||
const locked = note && (await db.vaults.itemExists(note));
|
||||
if (locked) return;
|
||||
const state = JSON.stringify({
|
||||
editing: editorState().currentlyEditing,
|
||||
note: note,
|
||||
movedAway: editorState().movedAway,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
|
||||
MMKV.setString("appState", state);
|
||||
} else {
|
||||
MMKV.removeItem("appState");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,7 +390,7 @@ export const useAppEvents = () => {
|
||||
setUser(user);
|
||||
|
||||
useUserStore.setState({
|
||||
profile: db.settings.getProfile()
|
||||
profile: await db.user.getProfile()
|
||||
});
|
||||
|
||||
if (SettingsService.get().sessionExpired) {
|
||||
@@ -511,8 +513,18 @@ export const useAppEvents = () => {
|
||||
|
||||
const onAppStateChanged = async (state: AppStateStatus) => {
|
||||
if (state === "active") {
|
||||
if (SettingsService.shouldLockAppOnEnterForeground()) {
|
||||
useUserStore.getState().lockApp(true);
|
||||
}
|
||||
|
||||
notifee.setBadgeCount(0);
|
||||
updateStatusBarColor();
|
||||
if (
|
||||
!SettingsService.canLockAppInBackground() &&
|
||||
!SettingsService.get().privacyScreen
|
||||
) {
|
||||
enabled(false);
|
||||
}
|
||||
|
||||
checkAutoBackup();
|
||||
await reconnectSSE();
|
||||
@@ -532,6 +544,7 @@ export const useAppEvents = () => {
|
||||
//@ts-ignore
|
||||
globalThis["IS_SHARE_EXTENSION"] = false;
|
||||
} else {
|
||||
SettingsService.appEnteredBackground();
|
||||
const id = useTabStore.getState().getCurrentNoteId();
|
||||
const note = id ? await db.notes.note(id) : undefined;
|
||||
const locked = note && (await db.vaults.itemExists(note));
|
||||
@@ -545,8 +558,7 @@ export const useAppEvents = () => {
|
||||
!useUserStore.getState().appLocked &&
|
||||
!useUserStore.getState().disableAppLockRequests
|
||||
) {
|
||||
if (SettingsService.shouldLockAppOnEnterForeground()) {
|
||||
DatabaseLogger.log(`AppEvents: Locking app on enter background`);
|
||||
if (SettingsService.getProperty("appLockTimer") === 0) {
|
||||
useUserStore.getState().lockApp(true);
|
||||
}
|
||||
|
||||
@@ -557,6 +569,13 @@ export const useAppEvents = () => {
|
||||
Keyboard.dismiss();
|
||||
}
|
||||
}
|
||||
if (
|
||||
(SettingsService.get().privacyScreen ||
|
||||
SettingsService.canLockAppInBackground()) &&
|
||||
!useSettingStore.getState().requestBiometrics
|
||||
) {
|
||||
enabled(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -679,9 +698,6 @@ export const useAppEvents = () => {
|
||||
|
||||
if (db.isInitialized) {
|
||||
Notifications.setupReminders(true);
|
||||
if (SettingsService.get().notifNotes) {
|
||||
Notifications.pinQuickNote(false);
|
||||
}
|
||||
useSettingStore.getState().setAppLoading(false);
|
||||
DatabaseLogger.info("Database initialized");
|
||||
}
|
||||
|
||||
@@ -64,7 +64,6 @@ import { useSettingStore } from "../stores/use-setting-store";
|
||||
import {
|
||||
eClearEditor,
|
||||
eCloseFullscreenEditor,
|
||||
eOnEnterEditor,
|
||||
eOnLoadNote,
|
||||
eOpenFullscreenEditor,
|
||||
eUnlockNote
|
||||
@@ -165,7 +164,9 @@ const _TabsHolder = () => {
|
||||
_deviceMode === "smallTablet"
|
||||
? dimensions.width -
|
||||
valueLimiter(dimensions.width * 0.4, 300, 450)
|
||||
: dimensions.width * 0.48,
|
||||
: dimensions.width > 1100
|
||||
? dimensions.width * 0.55
|
||||
: dimensions.width * 0.5,
|
||||
zIndex: null,
|
||||
paddingHorizontal: 0
|
||||
}
|
||||
@@ -256,7 +257,9 @@ const _TabsHolder = () => {
|
||||
position: "relative",
|
||||
width:
|
||||
current === "tablet"
|
||||
? size.width * 0.48
|
||||
? size.width > 1100
|
||||
? size.width * 0.55
|
||||
: size.width * 0.5
|
||||
: current === "smallTablet"
|
||||
? size.width - valueLimiter(size.width * 0.4, 300, 450)
|
||||
: size.width,
|
||||
@@ -268,9 +271,6 @@ const _TabsHolder = () => {
|
||||
if (!needsUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
const state = getAppState();
|
||||
|
||||
setTimeout(() => {
|
||||
switch (current) {
|
||||
case "tablet":
|
||||
@@ -285,8 +285,7 @@ const _TabsHolder = () => {
|
||||
break;
|
||||
case "mobile":
|
||||
if (
|
||||
state &&
|
||||
!state?.movedAway &&
|
||||
!editorState().movedAway &&
|
||||
useTabStore.getState().getCurrentNoteId()
|
||||
) {
|
||||
tabBarRef.current?.goToIndex(2, false);
|
||||
@@ -368,9 +367,15 @@ const _TabsHolder = () => {
|
||||
editor: dimensions.width - valueLimiter(dimensions.width * 0.4, 300, 450)
|
||||
},
|
||||
tablet: {
|
||||
sidebar: dimensions.width * 0.22,
|
||||
sidebar:
|
||||
dimensions.width > 1100
|
||||
? dimensions.width * 0.15
|
||||
: dimensions.width * 0.2,
|
||||
list: dimensions.width * 0.3,
|
||||
editor: dimensions.width * 0.48
|
||||
editor:
|
||||
dimensions.width > 1100
|
||||
? dimensions.width * 0.55
|
||||
: dimensions.width * 0.5
|
||||
}
|
||||
};
|
||||
|
||||
@@ -506,12 +511,11 @@ const _TabsHolder = () => {
|
||||
};
|
||||
export const TabHolder = React.memo(_TabsHolder, () => true);
|
||||
|
||||
const onChangeTab = async (event) => {
|
||||
if (event.i === 2) {
|
||||
const onChangeTab = async (obj) => {
|
||||
if (obj.i === 2) {
|
||||
editorState().movedAway = false;
|
||||
editorState().isFocused = true;
|
||||
activateKeepAwake();
|
||||
|
||||
if (!useTabStore.getState().getCurrentNoteId()) {
|
||||
eSendEvent(eOnLoadNote, {
|
||||
newNote: true
|
||||
@@ -520,12 +524,12 @@ const onChangeTab = async (event) => {
|
||||
if (
|
||||
useTabStore.getState().getTab(useTabStore.getState().currentTab).locked
|
||||
) {
|
||||
console.log("Unlocking note....");
|
||||
eSendEvent(eUnlockNote);
|
||||
}
|
||||
eSendEvent(eOnEnterEditor);
|
||||
}
|
||||
} else {
|
||||
if (event.from === 2) {
|
||||
if (obj.from === 2) {
|
||||
deactivateKeepAwake();
|
||||
editorState().movedAway = true;
|
||||
editorState().isFocused = false;
|
||||
|
||||
@@ -40,8 +40,7 @@
|
||||
"@trpc/client": "10.38.3",
|
||||
"@trpc/react-query": "10.38.3",
|
||||
"@trpc/server": "10.38.3",
|
||||
"kysely": "^0.26.3",
|
||||
"pathe": "1.1.2"
|
||||
"kysely": "^0.26.3"
|
||||
},
|
||||
"sideEffects": false
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import React, {
|
||||
forwardRef,
|
||||
useCallback,
|
||||
@@ -32,12 +33,17 @@ import WebView from "react-native-webview";
|
||||
import { ShouldStartLoadRequest } from "react-native-webview/lib/WebViewTypes";
|
||||
import { notesnook } from "../../../e2e/test.ids";
|
||||
import { db } from "../../common/database";
|
||||
import { IconButton } from "../../components/ui/icon-button";
|
||||
import { useDBItem } from "../../hooks/use-db-item";
|
||||
import useKeyboard from "../../hooks/use-keyboard";
|
||||
import BiometicService from "../../services/biometrics";
|
||||
import {
|
||||
ToastManager,
|
||||
eSendEvent,
|
||||
eSubscribeEvent
|
||||
} from "../../services/event-manager";
|
||||
import { useSettingStore } from "../../stores/use-setting-store";
|
||||
import { getElevationStyle } from "../../utils/elevation";
|
||||
import {
|
||||
eOnLoadNote,
|
||||
eUnlockNote,
|
||||
@@ -45,13 +51,13 @@ import {
|
||||
eUnlockWithPassword
|
||||
} from "../../utils/events";
|
||||
import { openLinkInBrowser } from "../../utils/functions";
|
||||
import EditorOverlay from "./loading";
|
||||
import { EDITOR_URI } from "./source";
|
||||
import { EditorProps, useEditorType } from "./tiptap/types";
|
||||
import { useEditor } from "./tiptap/use-editor";
|
||||
import { useEditorEvents } from "./tiptap/use-editor-events";
|
||||
import { syncTabs, useTabStore } from "./tiptap/use-tab-store";
|
||||
import { editorController, editorState } from "./tiptap/utils";
|
||||
import EditorOverlay from "./loading";
|
||||
|
||||
const style: ViewStyle = {
|
||||
height: "100%",
|
||||
@@ -99,7 +105,6 @@ const Editor = React.memo(
|
||||
useImperativeHandle(ref, () => ({
|
||||
get: () => editor
|
||||
}));
|
||||
useLockedNoteHandler();
|
||||
|
||||
const onError = useCallback(() => {
|
||||
renderKey.current =
|
||||
@@ -173,6 +178,7 @@ const Editor = React.memo(
|
||||
onMessage={onMessage || undefined}
|
||||
/>
|
||||
<EditorOverlay editor={editor} editorId={editorId} />
|
||||
<LockOverlay />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -182,8 +188,12 @@ const Editor = React.memo(
|
||||
|
||||
export default Editor;
|
||||
|
||||
const useLockedNoteHandler = () => {
|
||||
const tab = useTabStore((state) => state.getTab(state.currentTab));
|
||||
const LockOverlay = () => {
|
||||
const tab = useTabStore((state) =>
|
||||
state.tabs.find((t) => t.id === state.currentTab)
|
||||
);
|
||||
const isAppLoading = useSettingStore((state) => state.isAppLoading);
|
||||
const [item] = useDBItem(isAppLoading ? undefined : tab?.noteId, "note");
|
||||
const tabRef = useRef(tab);
|
||||
tabRef.current = tab;
|
||||
|
||||
@@ -191,8 +201,8 @@ const useLockedNoteHandler = () => {
|
||||
for (const tab of useTabStore.getState().tabs) {
|
||||
const noteId = useTabStore.getState().getTab(tab.id)?.noteId;
|
||||
if (!noteId) continue;
|
||||
if (tabRef.current && tabRef.current.noteLocked) {
|
||||
useTabStore.getState().updateTab(tabRef.current.id, {
|
||||
if (tab.noteLocked) {
|
||||
useTabStore.getState().updateTab(tab.id, {
|
||||
locked: true
|
||||
});
|
||||
}
|
||||
@@ -214,18 +224,15 @@ const useLockedNoteHandler = () => {
|
||||
useEffect(() => {
|
||||
const unlockWithBiometrics = async () => {
|
||||
try {
|
||||
if (!tabRef.current?.noteLocked || !tabRef.current) return;
|
||||
if (!item || !tabRef.current) return;
|
||||
console.log("Trying to unlock with biometrics...");
|
||||
const credentials = await BiometicService.getCredentials(
|
||||
"Unlock note",
|
||||
"Unlock note to open it in editor. If biometrics are not working, you can enter device pin to unlock vault."
|
||||
);
|
||||
|
||||
if (credentials && credentials?.password && tabRef.current.noteId) {
|
||||
const note = await db.vault.open(
|
||||
tabRef.current.noteId,
|
||||
credentials?.password
|
||||
);
|
||||
if (credentials && credentials?.password) {
|
||||
const note = await db.vault.open(item.id, credentials?.password);
|
||||
eSendEvent(eOnLoadNote, {
|
||||
item: note
|
||||
});
|
||||
@@ -246,7 +253,7 @@ const useLockedNoteHandler = () => {
|
||||
password: string;
|
||||
biometrics?: boolean;
|
||||
}) => {
|
||||
if (!tabRef.current?.noteId || !tabRef.current) return;
|
||||
if (!item || !tabRef.current) return;
|
||||
if (!password || password.trim().length === 0) {
|
||||
ToastManager.show({
|
||||
heading: "Password not entered",
|
||||
@@ -257,11 +264,10 @@ const useLockedNoteHandler = () => {
|
||||
}
|
||||
|
||||
try {
|
||||
const note = await db.vault.open(tabRef.current?.noteId, password);
|
||||
if (enrollBiometrics && note) {
|
||||
const note = await db.vault.open(item.id, password);
|
||||
if (enrollBiometrics) {
|
||||
try {
|
||||
const unlocked = await db.vault.unlock(password);
|
||||
if (!unlocked) throw new Error("Incorrect vault password");
|
||||
await db.vault.unlock(password);
|
||||
await BiometicService.storeCredentials(password);
|
||||
eSendEvent("vaultUpdated");
|
||||
ToastManager.show({
|
||||
@@ -283,7 +289,8 @@ const useLockedNoteHandler = () => {
|
||||
heading: "Incorrect password",
|
||||
message:
|
||||
"Please enter the correct vault password to enable biometrics.",
|
||||
type: "error"
|
||||
type: "error",
|
||||
context: "local"
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -297,7 +304,8 @@ const useLockedNoteHandler = () => {
|
||||
console.log(e);
|
||||
ToastManager.show({
|
||||
heading: "Incorrect password",
|
||||
type: "error"
|
||||
type: "error",
|
||||
context: "local"
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -309,9 +317,7 @@ const useLockedNoteHandler = () => {
|
||||
useTabStore.getState().biometryEnrolled &&
|
||||
!editorState().movedAway)
|
||||
) {
|
||||
setTimeout(() => {
|
||||
unlockWithBiometrics();
|
||||
}, 150);
|
||||
unlockWithBiometrics();
|
||||
} else {
|
||||
console.log("Biometrics unavailable.", editorState().movedAway);
|
||||
if (!editorState().movedAway) {
|
||||
@@ -337,7 +343,7 @@ const useLockedNoteHandler = () => {
|
||||
return () => {
|
||||
subs.map((s) => s?.unsubscribe());
|
||||
};
|
||||
}, [tab?.id, tab?.locked]);
|
||||
}, [item]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -124,13 +124,12 @@ const statusBar = statusBars[${tabId}];
|
||||
|
||||
if (typeof editor !== "undefined") {
|
||||
editor.commands.blur();
|
||||
editor.commands.clearContent(false);
|
||||
}
|
||||
|
||||
typeof editorTitle !== "undefined" && editorTitle.current && editorTitle.current?.blur();
|
||||
if (typeof editorController.content !== undefined) editorController.content.current = '';
|
||||
if (typeof editorController.content !== undefined) editorController.content.current = null;
|
||||
editorController.onUpdate();
|
||||
editorController.setTitle('');
|
||||
editorController.setTitle(null);
|
||||
if (typeof statusBar !== "undefined") {
|
||||
statusBar.current.resetWords();
|
||||
statusBar.current.set({date:"",saved:""});
|
||||
|
||||
@@ -47,6 +47,5 @@ export const EventTypes = {
|
||||
unlock: "editor-events:unlock",
|
||||
unlockWithBiometrics: "editor-events:unlock-biometrics",
|
||||
disableReadonlyMode: "editor-events:disable-readonly-mode",
|
||||
readonlyEditorLoaded: "readonlyEditorLoaded",
|
||||
error: "editorError"
|
||||
readonlyEditorLoaded: "readonlyEditorLoaded"
|
||||
};
|
||||
|
||||
@@ -24,7 +24,7 @@ import { ItemReference } from "@notesnook/core/dist/types";
|
||||
import type { Attachment } from "@notesnook/editor/dist/extensions/attachment/index";
|
||||
import { getDefaultPresets } from "@notesnook/editor/dist/toolbar/tool-definitions";
|
||||
import Clipboard from "@react-native-clipboard/clipboard";
|
||||
import React, { useCallback, useEffect, useRef } from "react";
|
||||
import { useCallback, useEffect, useRef } from "react";
|
||||
import {
|
||||
BackHandler,
|
||||
InteractionManager,
|
||||
@@ -34,7 +34,7 @@ import {
|
||||
useWindowDimensions
|
||||
} from "react-native";
|
||||
import { WebViewMessageEvent } from "react-native-webview";
|
||||
import { DatabaseLogger, db } from "../../../common/database";
|
||||
import { db } from "../../../common/database";
|
||||
import downloadAttachment from "../../../common/filesystem/download-attachment";
|
||||
import EditorTabs from "../../../components/sheets/editor-tabs";
|
||||
import LinkNote from "../../../components/sheets/link-note";
|
||||
@@ -47,8 +47,7 @@ import {
|
||||
ToastManager,
|
||||
eSendEvent,
|
||||
eSubscribeEvent,
|
||||
eUnSubscribeEvent,
|
||||
presentSheet
|
||||
eUnSubscribeEvent
|
||||
} from "../../../services/event-manager";
|
||||
import Navigation from "../../../services/navigation";
|
||||
import SettingsService from "../../../services/settings";
|
||||
@@ -60,7 +59,6 @@ import {
|
||||
eClearEditor,
|
||||
eCloseFullscreenEditor,
|
||||
eEditorTabFocused,
|
||||
eOnEnterEditor,
|
||||
eOnLoadNote,
|
||||
eOpenFullscreenEditor,
|
||||
eOpenLoginDialog,
|
||||
@@ -76,7 +74,6 @@ import { EventTypes } from "./editor-events";
|
||||
import { EditorMessage, EditorProps, useEditorType } from "./types";
|
||||
import { useTabStore } from "./use-tab-store";
|
||||
import { EditorEvents, editorState } from "./utils";
|
||||
import { Issue } from "../../../components/sheets/github/issue";
|
||||
|
||||
const publishNote = async () => {
|
||||
const user = useUserStore.getState().user;
|
||||
@@ -270,13 +267,13 @@ export const useEditorEvents = (
|
||||
}, [editor, deviceMode, fullscreen]);
|
||||
|
||||
const onHardwareBackPress = useCallback(() => {
|
||||
if (tabBarRef.current?.page === 2) {
|
||||
if (editorState().currentlyEditing) {
|
||||
onBackPress();
|
||||
return true;
|
||||
}
|
||||
}, [onBackPress]);
|
||||
|
||||
const onEnterEditor = useCallback(async () => {
|
||||
const onLoadNote = useCallback(async () => {
|
||||
InteractionManager.runAfterInteractions(() => {
|
||||
if (!DDS.isTab) {
|
||||
handleBack.current = BackHandler.addEventListener(
|
||||
@@ -331,16 +328,16 @@ export const useEditorEvents = (
|
||||
}, [fullscreen, onHardwareBackPress]);
|
||||
|
||||
useEffect(() => {
|
||||
eSubscribeEvent(eOnEnterEditor, onEnterEditor);
|
||||
eSubscribeEvent(eOnLoadNote + editor.editorId, onLoadNote);
|
||||
eSubscribeEvent(
|
||||
eClearEditor + editor.editorId,
|
||||
onClearEditorSessionRequest
|
||||
);
|
||||
return () => {
|
||||
eUnSubscribeEvent(eClearEditor, onClearEditorSessionRequest);
|
||||
eUnSubscribeEvent(eOnEnterEditor, onEnterEditor);
|
||||
eUnSubscribeEvent(eOnLoadNote, onLoadNote);
|
||||
};
|
||||
}, [editor.editorId, onClearEditorSessionRequest, onEnterEditor]);
|
||||
}, [editor.editorId, onClearEditorSessionRequest, onLoadNote]);
|
||||
|
||||
const onMessage = useCallback(
|
||||
async (event: WebViewMessageEvent) => {
|
||||
@@ -370,7 +367,6 @@ export const useEditorEvents = (
|
||||
|
||||
switch (editorMessage.type) {
|
||||
case EventTypes.content:
|
||||
DatabaseLogger.log("EventTypes.content");
|
||||
editor.saveContent({
|
||||
type: editorMessage.type,
|
||||
content: editorMessage.value.html as string,
|
||||
@@ -380,7 +376,6 @@ export const useEditorEvents = (
|
||||
});
|
||||
break;
|
||||
case EventTypes.title:
|
||||
DatabaseLogger.log("EventTypes.title");
|
||||
editor.saveContent({
|
||||
type: editorMessage.type,
|
||||
title: editorMessage.value as string,
|
||||
@@ -579,18 +574,6 @@ export const useEditorEvents = (
|
||||
EditorTabs.present();
|
||||
break;
|
||||
}
|
||||
case EventTypes.error: {
|
||||
presentSheet({
|
||||
component: (
|
||||
<Issue
|
||||
defaultBody={editorMessage.value.stack}
|
||||
defaultTitle={editorMessage.value.message}
|
||||
issueTitle={editorMessage.value.message}
|
||||
/>
|
||||
)
|
||||
});
|
||||
break;
|
||||
}
|
||||
case EventTypes.tabFocused: {
|
||||
console.log(
|
||||
"Focused tab",
|
||||
@@ -50,7 +50,6 @@ import { useTagStore } from "../../../stores/use-tag-store";
|
||||
import {
|
||||
eEditorTabFocused,
|
||||
eOnLoadNote,
|
||||
eShowMergeDialog,
|
||||
eUpdateNoteInEditor
|
||||
} from "../../../utils/events";
|
||||
import { tabBarRef } from "../../../utils/global-refs";
|
||||
@@ -201,8 +200,7 @@ export const useEditor = (
|
||||
useTabStore.getState().updateTab(tabId, {
|
||||
noteId: undefined,
|
||||
locked: false,
|
||||
noteLocked: false,
|
||||
readonly: false
|
||||
noteLocked: false
|
||||
});
|
||||
},
|
||||
[commands, editorSessionHistory, postMessage]
|
||||
@@ -226,11 +224,7 @@ export const useEditor = (
|
||||
}
|
||||
let note = id ? await db.notes?.note(id) : undefined;
|
||||
const locked = note && (await db.vaults.itemExists(note));
|
||||
|
||||
if (note?.conflicted) {
|
||||
eSendEvent(eShowMergeDialog, note);
|
||||
return;
|
||||
}
|
||||
if (note?.conflicted) return;
|
||||
|
||||
if (isContentInvalid(data) && id) {
|
||||
// Create a new history session if recieved empty or invalid content
|
||||
@@ -249,7 +243,7 @@ export const useEditor = (
|
||||
noteData.title = title;
|
||||
|
||||
if (ignoreEdit) {
|
||||
DatabaseLogger.log("Ignoring edits...");
|
||||
console.log("Ignoring edits...");
|
||||
noteData.dateEdited = note?.dateEdited;
|
||||
}
|
||||
|
||||
@@ -267,22 +261,8 @@ export const useEditor = (
|
||||
});
|
||||
}
|
||||
|
||||
let saved = false;
|
||||
setTimeout(() => {
|
||||
if (saved) return;
|
||||
commands.setStatus(
|
||||
getFormattedDate(note ? note.dateEdited : Date.now(), "date-time"),
|
||||
"Saving",
|
||||
tabId
|
||||
);
|
||||
}, 50);
|
||||
|
||||
if (!locked) {
|
||||
DatabaseLogger.log(`Saving note: ${id}...`);
|
||||
id = await db.notes?.add({ ...noteData });
|
||||
saved = true;
|
||||
DatabaseLogger.log(`Note saved: ${id}...`);
|
||||
|
||||
if (!note && id) {
|
||||
editorSessionHistory.newSession(id);
|
||||
if (id) {
|
||||
@@ -387,9 +367,6 @@ export const useEditor = (
|
||||
blockId?: string;
|
||||
presistTab?: boolean;
|
||||
}) => {
|
||||
if (!event) return;
|
||||
console.log(event.item?.id, event?.item?.title, "loading note...");
|
||||
|
||||
if (event.blockId) {
|
||||
blockIdRef.current = event.blockId;
|
||||
}
|
||||
@@ -424,11 +401,10 @@ export const useEditor = (
|
||||
if (currentTab?.previewTab && item.id !== currentTab.noteId) {
|
||||
await commands.setLoading(true, useTabStore.getState().currentTab);
|
||||
}
|
||||
const isLockedNote = await db.vaults.itemExists(
|
||||
event.item as ItemReference
|
||||
);
|
||||
const tabLocked =
|
||||
isLockedNote && !(event.item as NoteWithContent).content;
|
||||
|
||||
const noteIsLocked =
|
||||
(await db.vaults.itemExists(event.item as ItemReference)) &&
|
||||
!(event.item as NoteWithContent).content;
|
||||
|
||||
// If note was already opened in a tab, focus that tab.
|
||||
if (typeof event.tabId !== "number") {
|
||||
@@ -437,8 +413,8 @@ export const useEditor = (
|
||||
if (typeof tabId === "number") {
|
||||
useTabStore.getState().updateTab(tabId, {
|
||||
readonly: event.item.readonly || readonly,
|
||||
locked: tabLocked,
|
||||
noteLocked: isLockedNote
|
||||
locked: noteIsLocked,
|
||||
noteLocked: noteIsLocked
|
||||
});
|
||||
useTabStore.getState().focusTab(tabId);
|
||||
setTimeout(() => {
|
||||
@@ -455,8 +431,8 @@ export const useEditor = (
|
||||
// Open note in new tab.
|
||||
useTabStore.getState().newTab({
|
||||
readonly: event.item.readonly || readonly,
|
||||
locked: tabLocked,
|
||||
noteLocked: isLockedNote,
|
||||
locked: noteIsLocked,
|
||||
noteLocked: noteIsLocked,
|
||||
noteId: event.item.id,
|
||||
previewTab: false
|
||||
});
|
||||
@@ -466,8 +442,8 @@ export const useEditor = (
|
||||
// Otherwise we focus the preview tab or create one to open the note in.
|
||||
useTabStore.getState().focusPreviewTab(event.item.id, {
|
||||
readonly: event.item.readonly || readonly,
|
||||
locked: tabLocked,
|
||||
noteLocked: isLockedNote
|
||||
locked: noteIsLocked,
|
||||
noteLocked: noteIsLocked
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -491,7 +467,7 @@ export const useEditor = (
|
||||
state.current.movedAway = false;
|
||||
state.current.currentlyEditing = true;
|
||||
|
||||
if (!tabLocked) {
|
||||
if (!noteIsLocked) {
|
||||
await loadContent(item);
|
||||
}
|
||||
|
||||
@@ -554,7 +530,6 @@ export const useEditor = (
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
postMessage(EditorEvents.theme, theme);
|
||||
},
|
||||
[
|
||||
commands,
|
||||
@@ -563,8 +538,7 @@ export const useEditor = (
|
||||
overlay,
|
||||
postMessage,
|
||||
readonly,
|
||||
reset,
|
||||
theme
|
||||
reset
|
||||
]
|
||||
);
|
||||
|
||||
@@ -573,14 +547,13 @@ export const useEditor = (
|
||||
data: Note | ContentItem | TrashItem | DeletedItem,
|
||||
isLocal?: boolean
|
||||
) => {
|
||||
console.log("Local changes in editor", isLocal, data?.id);
|
||||
if (SettingsService.get().disableRealtimeSync && !isLocal) return;
|
||||
if (!data) return;
|
||||
|
||||
if (isDeleted(data) || isTrashItem(data)) {
|
||||
const tabId = useTabStore.getState().getTabForNote(data.id);
|
||||
if (tabId !== undefined) {
|
||||
console.log("Removing tab");
|
||||
await commands.clearContent(tabId);
|
||||
useTabStore.getState().removeTab(tabId);
|
||||
}
|
||||
return;
|
||||
@@ -653,10 +626,7 @@ export const useEditor = (
|
||||
}
|
||||
|
||||
if (data.type === "tiptap" && note && !isLocal) {
|
||||
if (lastContentChangeTime.current[noteId] >= data.dateEdited) {
|
||||
lock.current = false;
|
||||
return;
|
||||
}
|
||||
if (lastContentChangeTime.current[noteId] >= data.dateEdited) return;
|
||||
|
||||
if (locked && isEncryptedContent(data)) {
|
||||
const decryptedContent = await db.vault?.decryptContent(data, noteId);
|
||||
@@ -679,10 +649,7 @@ export const useEditor = (
|
||||
}
|
||||
} else {
|
||||
const _nextContent = data.data;
|
||||
if (_nextContent === currentContents.current?.data) {
|
||||
lock.current = false;
|
||||
return;
|
||||
}
|
||||
if (_nextContent === currentContents.current?.data) return;
|
||||
lastContentChangeTime.current[note.id] = note.dateEdited;
|
||||
await postMessage(EditorEvents.updatehtml, _nextContent, tabId);
|
||||
if (!isEncryptedContent(data)) {
|
||||
@@ -722,19 +689,12 @@ export const useEditor = (
|
||||
ignoreEdit: boolean;
|
||||
tabId: number;
|
||||
}) => {
|
||||
DatabaseLogger.log(`Saving content...`);
|
||||
if (
|
||||
lock.current ||
|
||||
(currentLoadingNoteId.current &&
|
||||
currentLoadingNoteId.current === noteId)
|
||||
) {
|
||||
DatabaseLogger.log(`Skipped saving conent:
|
||||
|
||||
lock.current: ${lock.current}
|
||||
currentLoadingNoteId.current: ${currentLoadingNoteId.current}
|
||||
`);
|
||||
)
|
||||
return;
|
||||
}
|
||||
|
||||
if (noteId) {
|
||||
lastContentChangeTime.current[noteId] = Date.now();
|
||||
@@ -821,15 +781,13 @@ export const useEditor = (
|
||||
|
||||
const onLoad = useCallback(async () => {
|
||||
if (currentNotes.current) overlay(true);
|
||||
setTimeout(() => {
|
||||
postMessage(EditorEvents.theme, theme);
|
||||
});
|
||||
postMessage(EditorEvents.theme, theme);
|
||||
commands.setInsets(
|
||||
isDefaultEditor ? insets : { top: 0, left: 0, right: 0, bottom: 0 }
|
||||
);
|
||||
await commands.setSettings();
|
||||
|
||||
if (!state.current.ready) {
|
||||
if (!state.current.ready && (await onReady())) {
|
||||
state.current.ready = true;
|
||||
}
|
||||
|
||||
@@ -842,6 +800,7 @@ export const useEditor = (
|
||||
}
|
||||
}
|
||||
}, [
|
||||
onReady,
|
||||
postMessage,
|
||||
theme,
|
||||
commands,
|
||||
|
||||
@@ -76,7 +76,6 @@ export type TabItem = {
|
||||
readonly?: boolean;
|
||||
locked?: boolean;
|
||||
noteLocked?: boolean;
|
||||
pinned?: boolean;
|
||||
};
|
||||
|
||||
const history = new History();
|
||||
|
||||
@@ -165,7 +165,6 @@ export function getAppState() {
|
||||
if (canRestoreAppState(appState)) {
|
||||
return appState;
|
||||
} else {
|
||||
clearAppState();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import SettingsService from "../../services/settings";
|
||||
import useNavigationStore from "../../stores/use-navigation-store";
|
||||
import { useNotes } from "../../stores/use-notes-store";
|
||||
import { openEditor } from "../notes/common";
|
||||
import LinkNote from "../../components/sheets/link-note";
|
||||
|
||||
export const Home = ({ navigation, route }: NavigationProps<"Notes">) => {
|
||||
const [notes, loading] = useNotes();
|
||||
@@ -79,9 +80,7 @@ export const Home = ({ navigation, route }: NavigationProps<"Notes">) => {
|
||||
loading: "Loading your notes"
|
||||
}}
|
||||
/>
|
||||
{!notes || !notes.placeholders?.length ? null : (
|
||||
<FloatingButton title="Create a new note" onPress={openEditor} />
|
||||
)}
|
||||
<FloatingButton title="Create a new note" onPress={openEditor} />
|
||||
</DelayLayout>
|
||||
</>
|
||||
);
|
||||
|
||||