Compare commits
641 Commits
auth-v4.3.
...
retention-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c93f9adb02 | ||
|
|
aa3d852280 | ||
|
|
6b92bace0c | ||
|
|
70c857641c | ||
|
|
d5b137ea82 | ||
|
|
8b02edb19f | ||
|
|
daf1d632e7 | ||
|
|
0e435b6bcf | ||
|
|
a2643f2cd0 | ||
|
|
abe0ef0a03 | ||
|
|
0f24ba01f5 | ||
|
|
d904aab804 | ||
|
|
1d8aaa49e7 | ||
|
|
39509813c6 | ||
|
|
f362943ab6 | ||
|
|
976eee005c | ||
|
|
9b15ab2f2f | ||
|
|
31f6671626 | ||
|
|
c32e4be8be | ||
|
|
6ae9003585 | ||
|
|
851aed6a78 | ||
|
|
7732f9eee9 | ||
|
|
06099f00c6 | ||
|
|
8e0b0da68f | ||
|
|
55dbc3a8db | ||
|
|
f6744d4b47 | ||
|
|
fbf626b578 | ||
|
|
9508695bba | ||
|
|
5d5e418676 | ||
|
|
ccfd7abf83 | ||
|
|
645014460b | ||
|
|
e32af8e0e5 | ||
|
|
6e2f645905 | ||
|
|
5e091af787 | ||
|
|
f9dbbb8cc9 | ||
|
|
1fc72383a3 | ||
|
|
c040ae9dcc | ||
|
|
f70148d652 | ||
|
|
60f94362d2 | ||
|
|
a9bf825dde | ||
|
|
004525ddeb | ||
|
|
2ff03d7303 | ||
|
|
fcaf46fcd1 | ||
|
|
d8c50ce3fa | ||
|
|
15ed5e9d7b | ||
|
|
ef6e4ebbcd | ||
|
|
60b3e0977e | ||
|
|
f183c56c20 | ||
|
|
01e9d79a22 | ||
|
|
ff22c69ca6 | ||
|
|
f609cef79e | ||
|
|
016b031bf1 | ||
|
|
c7a2001405 | ||
|
|
3871a538ab | ||
|
|
b52ac3ff5d | ||
|
|
be33ee5a1c | ||
|
|
8df7c1b9a4 | ||
|
|
e8997c16a6 | ||
|
|
141d761ecb | ||
|
|
fe5feb0394 | ||
|
|
7ec0c6dbdb | ||
|
|
be84e1856d | ||
|
|
9808ea5d8e | ||
|
|
2577b9c93a | ||
|
|
0981ba5989 | ||
|
|
c2959d06b0 | ||
|
|
eed42c9df5 | ||
|
|
ec30ace822 | ||
|
|
7fa9e2a627 | ||
|
|
ac0c96ae29 | ||
|
|
9900c346b5 | ||
|
|
2108461450 | ||
|
|
270dd02e20 | ||
|
|
e6deea1533 | ||
|
|
d303a40cc7 | ||
|
|
08d435b920 | ||
|
|
efa4c46f6e | ||
|
|
ab5c02d792 | ||
|
|
20a26eac3b | ||
|
|
3cd5127488 | ||
|
|
e77a8cdf9b | ||
|
|
77e4506d2a | ||
|
|
c170384607 | ||
|
|
ce7a564cbd | ||
|
|
0d6f71c193 | ||
|
|
ab04bd66a5 | ||
|
|
9f3c4c8542 | ||
|
|
879f16a2dd | ||
|
|
136f8d17cc | ||
|
|
4539acd239 | ||
|
|
4d37e415e7 | ||
|
|
361283f072 | ||
|
|
3b4f9ecc22 | ||
|
|
d1289bb467 | ||
|
|
b81098f88d | ||
|
|
432883685d | ||
|
|
55094b7f2a | ||
|
|
5c9d6610c1 | ||
|
|
da1ac0696b | ||
|
|
c61667290b | ||
|
|
61e306e1b3 | ||
|
|
da565172fc | ||
|
|
c686c75141 | ||
|
|
d8617cb782 | ||
|
|
7a12f6edde | ||
|
|
f0c489587f | ||
|
|
b9a81c3693 | ||
|
|
f143add013 | ||
|
|
7d71a0c9a4 | ||
|
|
fb5bd0bdec | ||
|
|
adbaba8a44 | ||
|
|
01d0915004 | ||
|
|
332e759e6a | ||
|
|
e7b5815039 | ||
|
|
a1557e8d27 | ||
|
|
8d667333e3 | ||
|
|
2843cc36d9 | ||
|
|
1019047eb2 | ||
|
|
42a085221c | ||
|
|
e08b228d05 | ||
|
|
3eee5a5fdc | ||
|
|
97c03a4985 | ||
|
|
f3974cdb8a | ||
|
|
dc402b7bca | ||
|
|
5082343708 | ||
|
|
4e34ecd580 | ||
|
|
fb897d237d | ||
|
|
b6a1a77bf7 | ||
|
|
168ef20e0f | ||
|
|
d880255fc8 | ||
|
|
1b1c33977d | ||
|
|
07f89bb1d6 | ||
|
|
47b0d51f22 | ||
|
|
8e313840fd | ||
|
|
5e489843fa | ||
|
|
5dea3fd8b0 | ||
|
|
8dd9dc16ad | ||
|
|
d31db6d678 | ||
|
|
a928e87747 | ||
|
|
064092a3e6 | ||
|
|
a76561ebe9 | ||
|
|
6321f50e6c | ||
|
|
df8ca468db | ||
|
|
4623e05eb5 | ||
|
|
edf6baef6e | ||
|
|
611d2684c4 | ||
|
|
93dd0c4943 | ||
|
|
83fdda46a3 | ||
|
|
23943aae89 | ||
|
|
f01d0ff274 | ||
|
|
d158db9499 | ||
|
|
9186b272b6 | ||
|
|
60f1172033 | ||
|
|
5843aee3d6 | ||
|
|
f6b186a167 | ||
|
|
aa9096134d | ||
|
|
1370f0523c | ||
|
|
c1051b8a10 | ||
|
|
b4d532bb41 | ||
|
|
4327fbb9e5 | ||
|
|
636d2a8069 | ||
|
|
21e0edcb85 | ||
|
|
8b11989e0f | ||
|
|
5bc6505cb8 | ||
|
|
a0184013f8 | ||
|
|
d0b5f84854 | ||
|
|
4bb2aea5d2 | ||
|
|
298faf8e0a | ||
|
|
e816504576 | ||
|
|
1506009a55 | ||
|
|
8930a0ddbc | ||
|
|
8611d5644d | ||
|
|
5df815da58 | ||
|
|
59e2906bdc | ||
|
|
79e8fffc7a | ||
|
|
bbd81a6385 | ||
|
|
1ba31e9442 | ||
|
|
7cf8ccdc7e | ||
|
|
ae6e2b1349 | ||
|
|
a65493192f | ||
|
|
cf538a713b | ||
|
|
3440bbd772 | ||
|
|
657a57f46a | ||
|
|
f6db2daaee | ||
|
|
2d8ffae74b | ||
|
|
1efaefbf9c | ||
|
|
29f5693078 | ||
|
|
94bd9f4dd6 | ||
|
|
ce9c08c607 | ||
|
|
347140c14c | ||
|
|
97bc768092 | ||
|
|
cdb81c621d | ||
|
|
bd7fec03d3 | ||
|
|
0c904d37c8 | ||
|
|
dc9f665029 | ||
|
|
4b0536a5b2 | ||
|
|
c2efd198a6 | ||
|
|
a2a74e2166 | ||
|
|
b0f8258a90 | ||
|
|
c75937759f | ||
|
|
466f31bbb9 | ||
|
|
09f6922ccf | ||
|
|
eacc364498 | ||
|
|
3c3ce516f5 | ||
|
|
7fe070b5ae | ||
|
|
13bcfe61ed | ||
|
|
4d3926c150 | ||
|
|
7d92b5923b | ||
|
|
864f0317fa | ||
|
|
a928676280 | ||
|
|
2073134e7a | ||
|
|
5a411d1d4d | ||
|
|
5f1d767b9c | ||
|
|
1ecff890f0 | ||
|
|
38aae47445 | ||
|
|
e4cd1434df | ||
|
|
f907beab62 | ||
|
|
f2e336c35a | ||
|
|
a8b2423d77 | ||
|
|
f8f2e6f7c7 | ||
|
|
e103d7490e | ||
|
|
f068d6ef24 | ||
|
|
3ec3f9f2e1 | ||
|
|
25c472e584 | ||
|
|
7b69c86cba | ||
|
|
1d197694ef | ||
|
|
4c9a37f3c8 | ||
|
|
59bc454f5c | ||
|
|
dd9f3f993d | ||
|
|
f5b20cf8d0 | ||
|
|
2f9d664b05 | ||
|
|
2bfb52168e | ||
|
|
c4fe18bbc1 | ||
|
|
d3a47eedda | ||
|
|
28717ce2f2 | ||
|
|
082d15b41b | ||
|
|
a582f40fa5 | ||
|
|
c706904263 | ||
|
|
8a73b19a3e | ||
|
|
dd53cd5f47 | ||
|
|
368b0c946a | ||
|
|
6ead2ab843 | ||
|
|
eb3ec77bb6 | ||
|
|
037a699790 | ||
|
|
678e97e937 | ||
|
|
6f02a048b6 | ||
|
|
e1f0605345 | ||
|
|
3cab14a1eb | ||
|
|
1f090642f2 | ||
|
|
51235bf81b | ||
|
|
4bd31aeea8 | ||
|
|
f2736c43c1 | ||
|
|
145ad5d309 | ||
|
|
c6b4cba8b4 | ||
|
|
70daffd23e | ||
|
|
bd4f1071e5 | ||
|
|
8abd38c57a | ||
|
|
098832ccc9 | ||
|
|
3b3e670c50 | ||
|
|
25b39be91c | ||
|
|
f67b47183f | ||
|
|
18a951ccf3 | ||
|
|
ca5a2c8fa2 | ||
|
|
cfe58aa248 | ||
|
|
4d9a1c6389 | ||
|
|
cf5d64554a | ||
|
|
5b9752544a | ||
|
|
1496e9fd5a | ||
|
|
1fb3779310 | ||
|
|
2d8d137029 | ||
|
|
343108d470 | ||
|
|
7bfc5cb08d | ||
|
|
ae0a8028d1 | ||
|
|
7215f12d76 | ||
|
|
29d09bf143 | ||
|
|
8afc337b62 | ||
|
|
a1b0eec83b | ||
|
|
f4de138b08 | ||
|
|
1b45dfee0e | ||
|
|
a57041d0d2 | ||
|
|
6e57cc9e79 | ||
|
|
79a73ffd09 | ||
|
|
9425f80ef5 | ||
|
|
7de9b747a9 | ||
|
|
adb8c2bdd6 | ||
|
|
069a9fba58 | ||
|
|
0268c47c45 | ||
|
|
b7f59a18bd | ||
|
|
8e4dd04588 | ||
|
|
05f2b3c43e | ||
|
|
4580e04bf6 | ||
|
|
970e631808 | ||
|
|
0a40f2fef4 | ||
|
|
5334388041 | ||
|
|
0737054363 | ||
|
|
85c40dfe29 | ||
|
|
719c5584f7 | ||
|
|
93747a87ec | ||
|
|
6cf881dd60 | ||
|
|
22539c2a2f | ||
|
|
6ff909d3b8 | ||
|
|
0b609a9159 | ||
|
|
7998f8ac53 | ||
|
|
0d223a759e | ||
|
|
b27e5938f1 | ||
|
|
fcaebe2256 | ||
|
|
23d1c054aa | ||
|
|
c0669a138a | ||
|
|
150fd6f153 | ||
|
|
e8e407a249 | ||
|
|
4cd4445e65 | ||
|
|
357926806b | ||
|
|
223043e75c | ||
|
|
41a688357c | ||
|
|
ca83e781dd | ||
|
|
5535fdead5 | ||
|
|
96194bdfe4 | ||
|
|
e31d132855 | ||
|
|
77aef5db3f | ||
|
|
79415880fc | ||
|
|
959a2d65a4 | ||
|
|
5abc0e3dc1 | ||
|
|
b43d8e0851 | ||
|
|
3b577b1881 | ||
|
|
0a1f984082 | ||
|
|
798977e395 | ||
|
|
cca47db499 | ||
|
|
1030f8eda8 | ||
|
|
279cbb3938 | ||
|
|
9afa495d7e | ||
|
|
69874bbcf6 | ||
|
|
787beb951d | ||
|
|
4c820b7bf8 | ||
|
|
d25fe9296b | ||
|
|
51f13191b3 | ||
|
|
9d4d3dc159 | ||
|
|
76e7f694f1 | ||
|
|
60b484a2ad | ||
|
|
75385a6e02 | ||
|
|
575f1744a2 | ||
|
|
90f05021c5 | ||
|
|
c9fc6f9e3e | ||
|
|
1d2de2ab76 | ||
|
|
a51dfb2d7f | ||
|
|
3c2a821045 | ||
|
|
fdefd2720c | ||
|
|
c57b93f0d9 | ||
|
|
1cbb00ec3d | ||
|
|
ee3f4451ed | ||
|
|
aabaa89add | ||
|
|
7556287716 | ||
|
|
31ab4962f9 | ||
|
|
dfba8478b7 | ||
|
|
5a6c385132 | ||
|
|
c6827cc3f4 | ||
|
|
7002d2b464 | ||
|
|
c062cc8aae | ||
|
|
448ad06902 | ||
|
|
ae6092d2ab | ||
|
|
658b8e5297 | ||
|
|
b164fde81b | ||
|
|
8593ae8fbc | ||
|
|
d3e4771055 | ||
|
|
41e2a93b20 | ||
|
|
bfa2251d6d | ||
|
|
8363b7b7d3 | ||
|
|
cd072113bb | ||
|
|
dbf4d055d4 | ||
|
|
424fbf1169 | ||
|
|
bf4d15db9c | ||
|
|
4de0421f88 | ||
|
|
6273313df9 | ||
|
|
104a9bbb94 | ||
|
|
866958389c | ||
|
|
c762d16fa5 | ||
|
|
8ee3fb84b1 | ||
|
|
901b3df9f5 | ||
|
|
b9c9d76e5d | ||
|
|
a173ca5cd8 | ||
|
|
86eb974dc3 | ||
|
|
099771dfe6 | ||
|
|
1d0ab2cd43 | ||
|
|
db5a56c6f6 | ||
|
|
4db1a39de2 | ||
|
|
255a170088 | ||
|
|
56623099b3 | ||
|
|
a069b1b7e4 | ||
|
|
55345cf60e | ||
|
|
d91555f8f2 | ||
|
|
a0049f4e78 | ||
|
|
d4199790bb | ||
|
|
9a36c24227 | ||
|
|
9341c63ed0 | ||
|
|
ca25756717 | ||
|
|
b81448d366 | ||
|
|
d9db651ff7 | ||
|
|
1da0870bc5 | ||
|
|
1e2027b6a9 | ||
|
|
579afbd6b5 | ||
|
|
fec0b867fe | ||
|
|
2977a91d17 | ||
|
|
e30cb93502 | ||
|
|
1b59ea1377 | ||
|
|
fc8a0b2f37 | ||
|
|
93ad3d65fd | ||
|
|
b261f72864 | ||
|
|
55e0a8de6f | ||
|
|
bd12d1e885 | ||
|
|
0aabee9e3b | ||
|
|
5d28c0038a | ||
|
|
7a31cc982a | ||
|
|
bad8d9bf2a | ||
|
|
73d67277b7 | ||
|
|
b5130f1ab6 | ||
|
|
d8e3807049 | ||
|
|
1388e34659 | ||
|
|
ee2c836a2a | ||
|
|
6379cdd70b | ||
|
|
fe9989fd5f | ||
|
|
34cdefe028 | ||
|
|
15ec21f3c8 | ||
|
|
2efc645c31 | ||
|
|
ea7109e577 | ||
|
|
444e1a1490 | ||
|
|
969b0c1655 | ||
|
|
bdd5036cf8 | ||
|
|
6fd2db8d0b | ||
|
|
7eae2936bd | ||
|
|
f29b8f933b | ||
|
|
ad27bd3b35 | ||
|
|
8bab350624 | ||
|
|
21fd608ed7 | ||
|
|
4229238768 | ||
|
|
d86f4de8ce | ||
|
|
f0b8e3b4af | ||
|
|
aa422889f3 | ||
|
|
0738caaa2b | ||
|
|
c981af5470 | ||
|
|
f5eca5b671 | ||
|
|
74036bad60 | ||
|
|
95f7735164 | ||
|
|
740c1093ff | ||
|
|
04bf4527d8 | ||
|
|
b9a8f58dec | ||
|
|
5c66511a31 | ||
|
|
4c204e2a2a | ||
|
|
291833e1e1 | ||
|
|
be99d92bf2 | ||
|
|
e94b1966bd | ||
|
|
bc0399dfeb | ||
|
|
c4822a1caf | ||
|
|
a390d3ff2e | ||
|
|
3d8d4bd8bf | ||
|
|
8555358fa3 | ||
|
|
9999ffa52c | ||
|
|
9d60e980f8 | ||
|
|
b680129af5 | ||
|
|
732fa6b3d9 | ||
|
|
c3a7952c42 | ||
|
|
fdb4b0374c | ||
|
|
250bc3edcf | ||
|
|
822285fd3d | ||
|
|
f5ea4b0a05 | ||
|
|
174d9fb82e | ||
|
|
101e27514b | ||
|
|
fc480e8ce6 | ||
|
|
2cbc4998df | ||
|
|
40812ec7c3 | ||
|
|
09b4025f11 | ||
|
|
7b169fe903 | ||
|
|
9d222cd007 | ||
|
|
cfe6343d63 | ||
|
|
e15fb04ee0 | ||
|
|
6bbfcb1d13 | ||
|
|
b9bb7c074d | ||
|
|
5a7f83212b | ||
|
|
01071676ce | ||
|
|
aadacda2f6 | ||
|
|
bc0d832105 | ||
|
|
0a1c1e441e | ||
|
|
4e95f4b36f | ||
|
|
5a3b72b141 | ||
|
|
c88e04535c | ||
|
|
b12a4dd235 | ||
|
|
f24d6b882d | ||
|
|
199c2d0c95 | ||
|
|
7508d9c86b | ||
|
|
b586281207 | ||
|
|
8510a88e9e | ||
|
|
2dc202d984 | ||
|
|
48aec5df86 | ||
|
|
2440c38530 | ||
|
|
b1ce3edf28 | ||
|
|
80ea75e2d2 | ||
|
|
f592d73d87 | ||
|
|
28295e2b83 | ||
|
|
6be4b29331 | ||
|
|
ba435ad974 | ||
|
|
799f9f2878 | ||
|
|
39e1f7bfe7 | ||
|
|
5d7ce9f542 | ||
|
|
eefd740a4d | ||
|
|
ef6e859e76 | ||
|
|
404e8c3214 | ||
|
|
c47ddab7ba | ||
|
|
74849bd257 | ||
|
|
a76a7abc2a | ||
|
|
bd7a16a85c | ||
|
|
cd634b98a0 | ||
|
|
7b871195c8 | ||
|
|
bed0b0f902 | ||
|
|
cdf46acd8b | ||
|
|
af7698e29e | ||
|
|
713972af9b | ||
|
|
1c2b9634db | ||
|
|
bf8173708d | ||
|
|
125eca1847 | ||
|
|
6474ff25a7 | ||
|
|
112a4844ee | ||
|
|
eb9e97080f | ||
|
|
633184852e | ||
|
|
46a090535f | ||
|
|
360223bd2f | ||
|
|
d11ff14ecd | ||
|
|
60781ba86b | ||
|
|
02d2db3e43 | ||
|
|
4035a06040 | ||
|
|
2d16d958e3 | ||
|
|
a682fb4ece | ||
|
|
bc65e2c256 | ||
|
|
3457cc1369 | ||
|
|
5ffd513826 | ||
|
|
d1df2962cb | ||
|
|
cf7d46fd70 | ||
|
|
875a747e24 | ||
|
|
0e4fa1ad4c | ||
|
|
939d1a5d40 | ||
|
|
0f62c4fa79 | ||
|
|
038f6b33e1 | ||
|
|
bd0818ec7d | ||
|
|
1267587ae5 | ||
|
|
168a4936f8 | ||
|
|
eb11d80d79 | ||
|
|
dbc1cec05a | ||
|
|
95c9f5877c | ||
|
|
34034a77a2 | ||
|
|
1da4770728 | ||
|
|
353b2274d1 | ||
|
|
56f15a33af | ||
|
|
85e0fef80b | ||
|
|
f3eb4c9acf | ||
|
|
70924b7416 | ||
|
|
21028e4985 | ||
|
|
4ba22fd677 | ||
|
|
ac43ecf45b | ||
|
|
a974a95fb2 | ||
|
|
eb7f350102 | ||
|
|
b2e4b82d5c | ||
|
|
a88e281800 | ||
|
|
279319bd52 | ||
|
|
6a3c3d5b5b | ||
|
|
f36cc9ec06 | ||
|
|
8981668052 | ||
|
|
cba4f538f8 | ||
|
|
8b787c7373 | ||
|
|
30c4a72e69 | ||
|
|
bfd9a0d760 | ||
|
|
2d2696e4ee | ||
|
|
4f0bee517e | ||
|
|
e536e34808 | ||
|
|
8a13c9071c | ||
|
|
e35fae6c3c | ||
|
|
313a7064f8 | ||
|
|
a550dcce57 | ||
|
|
63b9b926a1 | ||
|
|
4500a8f620 | ||
|
|
90bf99c20b | ||
|
|
838b7e2a88 | ||
|
|
99f882043b | ||
|
|
dd0c5ed770 | ||
|
|
2f3c00fc99 | ||
|
|
acad6895e8 | ||
|
|
1774a8019f | ||
|
|
f5ce53d8ca | ||
|
|
e5720c1906 | ||
|
|
9803720603 | ||
|
|
86ba1eed5d | ||
|
|
9ab55ed1e4 | ||
|
|
bf7e10eab6 | ||
|
|
8383d7dd56 | ||
|
|
7174cbac3b | ||
|
|
52c7c1b4ed | ||
|
|
2187b3ec6e | ||
|
|
d1af77dbef | ||
|
|
33ee599f3c | ||
|
|
0247d3f458 | ||
|
|
38c64ac05f | ||
|
|
220a6cbc4b | ||
|
|
4797e03119 | ||
|
|
02d730eaae | ||
|
|
070907fc69 | ||
|
|
01b65eb608 | ||
|
|
3ab8c348b0 | ||
|
|
7af57bd7c8 | ||
|
|
1ac64b5a31 | ||
|
|
2431c81c44 | ||
|
|
f0b23a495c | ||
|
|
677ad0dc00 | ||
|
|
142020e26a | ||
|
|
195bd114f9 | ||
|
|
6b91228273 | ||
|
|
1166b53383 | ||
|
|
041a657877 | ||
|
|
d0ee33131e | ||
|
|
a33ace26dd | ||
|
|
d8826199e0 | ||
|
|
e389a2c4a2 | ||
|
|
2283f4a25d | ||
|
|
e55ddefa21 | ||
|
|
76b9c30332 | ||
|
|
ce681d83da | ||
|
|
11bc17e766 | ||
|
|
69c71d23c3 | ||
|
|
214573e0c2 | ||
|
|
2e3ac8b485 | ||
|
|
47f0c88ed8 | ||
|
|
162ce32b8e | ||
|
|
a1dbdfd6ba | ||
|
|
74072b952d | ||
|
|
7e5a2c4377 | ||
|
|
f27a2c68ec | ||
|
|
709a3756f0 | ||
|
|
e1a0c1c847 | ||
|
|
763217c6df | ||
|
|
66d9c100ca | ||
|
|
ba2ae29e3a | ||
|
|
a72694116a | ||
|
|
3fc24d139b | ||
|
|
50ab944579 | ||
|
|
2b28661f89 | ||
|
|
cfa02f631c |
14
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -26,6 +26,20 @@ body:
|
||||
label: Version
|
||||
description: The version can be seen at the bottom of settings.
|
||||
placeholder: e.g. v1.2.3
|
||||
- type: input
|
||||
attributes:
|
||||
label: Last working version
|
||||
description: >
|
||||
The version where the feature was last known to be working. It is
|
||||
fine if you don't remember the exact version (mention roughly
|
||||
then), but if there just isn't a last known working version, then
|
||||
it is likely that what is being reported is not an issue but a
|
||||
feature request. The difference between the two categories is not
|
||||
just semantic - feature requests use GitHub discussions and so can
|
||||
be [upvoted by the
|
||||
community](https://github.com/ente-io/ente/discussions/categories/feature-requests)
|
||||
(issues can't be).
|
||||
placeholder: e.g. v1.2.3
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: What product are you using?
|
||||
|
||||
4
.github/workflows/auth-crowdin-push.yml
vendored
@@ -9,6 +9,10 @@ on:
|
||||
# Or the workflow itself is changed
|
||||
- ".github/workflows/auth-crowdin.yml"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
push-sources-to-crowdin:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
4
.github/workflows/auth-crowdin-sync.yml
vendored
@@ -8,6 +8,10 @@ on:
|
||||
# Also allow manually running the workflow.
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
synchronize-with-crowdin:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
3
.github/workflows/auth-internal-release.yml
vendored
@@ -6,6 +6,9 @@ on:
|
||||
env:
|
||||
FLUTTER_VERSION: "3.24.3"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
5
.github/workflows/auth-lint.yml
vendored
@@ -10,6 +10,9 @@ on:
|
||||
env:
|
||||
FLUTTER_VERSION: "3.24.3"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -30,7 +33,7 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
- name: Verify all icons are less than 20KB
|
||||
run: |
|
||||
find assets/custom-icons -type f -name "*.svg" | while read -r file; do
|
||||
|
||||
3
.github/workflows/auth-release.yml
vendored
@@ -31,6 +31,9 @@ on:
|
||||
env:
|
||||
FLUTTER_VERSION: "3.24.3"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build-linux-latest:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
4
.github/workflows/cli-release.yml
vendored
@@ -12,6 +12,10 @@ on:
|
||||
tags:
|
||||
- "cli-v*"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
draft-release:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
53
.github/workflows/codeql.yml
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
# The only reason we're making a custom CodeQL configuration is because the
|
||||
# default setup does not have an option to run daily / weekly instead of per
|
||||
# push, which is too slow.
|
||||
#
|
||||
# In the future, it might become faster. Then just delete this file, and revert
|
||||
# to the default configuration.
|
||||
#
|
||||
# References:
|
||||
# https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/
|
||||
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
workflow_dispatch: # Allow running manually
|
||||
schedule:
|
||||
- cron: "22 1 * * 1"
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze (${{ matrix.language }})
|
||||
runs-on: 'ubuntu-latest'
|
||||
permissions:
|
||||
contents: read
|
||||
# Required for all workflows.
|
||||
security-events: write
|
||||
# Required to fetch internal or private CodeQL packs.
|
||||
packages: read
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- language: actions
|
||||
build-mode: none
|
||||
- language: go
|
||||
build-mode: autobuild
|
||||
- language: javascript-typescript
|
||||
build-mode: none
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
build-mode: ${{ matrix.build-mode }}
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
3
.github/workflows/copycat-db-release.yml
vendored
@@ -3,6 +3,9 @@ name: "Release (copycat-db)"
|
||||
on:
|
||||
workflow_dispatch: # Run manually
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
5
.github/workflows/desktop-lint.yml
vendored
@@ -7,6 +7,9 @@ on:
|
||||
- "desktop/**"
|
||||
- ".github/workflows/desktop-lint.yml"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -20,7 +23,7 @@ jobs:
|
||||
- name: Setup node and enable yarn caching
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
node-version: 22
|
||||
cache: "yarn"
|
||||
cache-dependency-path: "desktop/yarn.lock"
|
||||
|
||||
|
||||
5
.github/workflows/docs-deploy.yml
vendored
@@ -10,6 +10,9 @@ on:
|
||||
# Also allow manually running the workflow
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -25,7 +28,7 @@ jobs:
|
||||
- name: Setup node and enable yarn caching
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
node-version: 22
|
||||
cache: "yarn"
|
||||
cache-dependency-path: "docs/yarn.lock"
|
||||
|
||||
|
||||
5
.github/workflows/docs-verify-build.yml
vendored
@@ -10,6 +10,9 @@ on:
|
||||
- "docs/**"
|
||||
- ".github/workflows/docs-verify-build.yml"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
verify-build:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -25,7 +28,7 @@ jobs:
|
||||
- name: Setup node and enable yarn caching
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
node-version: 22
|
||||
cache: "yarn"
|
||||
cache-dependency-path: "docs/yarn.lock"
|
||||
|
||||
|
||||
5
.github/workflows/infra-deploy-staff.yml
vendored
@@ -10,6 +10,9 @@ on:
|
||||
# Also allow manually running the workflow
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -25,7 +28,7 @@ jobs:
|
||||
- name: Setup node and enable yarn caching
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
node-version: 22
|
||||
cache: "yarn"
|
||||
cache-dependency-path: "infra/staff/yarn.lock"
|
||||
|
||||
|
||||
5
.github/workflows/infra-lint-staff.yml
vendored
@@ -7,6 +7,9 @@ on:
|
||||
- "infra/staff/**"
|
||||
- ".github/workflows/infra-deploy-staff.yml"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -22,7 +25,7 @@ jobs:
|
||||
- name: Setup node and enable yarn caching
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
node-version: 22
|
||||
cache: "yarn"
|
||||
cache-dependency-path: "infra/staff/yarn.lock"
|
||||
|
||||
|
||||
4
.github/workflows/mobile-crowdin-push.yml
vendored
@@ -9,6 +9,10 @@ on:
|
||||
# Or the workflow itself is changed
|
||||
- ".github/workflows/mobile-crowdin.yml"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
push-sources-to-crowdin:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
4
.github/workflows/mobile-crowdin-sync.yml
vendored
@@ -8,6 +8,10 @@ on:
|
||||
# Also allow manually running the workflow.
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
synchronize-with-crowdin:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -6,6 +6,9 @@ on:
|
||||
env:
|
||||
FLUTTER_VERSION: "3.24.3"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -54,7 +57,7 @@ jobs:
|
||||
packageName: io.ente.photos
|
||||
releaseFiles: mobile/build/app/outputs/bundle/playstoreRelease/app-playstore-release.aab
|
||||
track: internal
|
||||
|
||||
|
||||
- name: Notify Discord
|
||||
uses: sarisia/actions-status-discord@v1
|
||||
with:
|
||||
|
||||
4
.github/workflows/mobile-lint.yml
vendored
@@ -8,9 +8,11 @@ on:
|
||||
- ".github/workflows/mobile-lint.yml"
|
||||
|
||||
env:
|
||||
|
||||
FLUTTER_VERSION: "3.24.3"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
3
.github/workflows/mobile-release.yml
vendored
@@ -11,6 +11,9 @@ on:
|
||||
env:
|
||||
FLUTTER_VERSION: "3.24.3"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
3
.github/workflows/server-lint.yml
vendored
@@ -7,6 +7,9 @@ on:
|
||||
- "server/**"
|
||||
- ".github/workflows/server-lint.yml"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
4
.github/workflows/server-publish-ghcr.yml
vendored
@@ -7,6 +7,10 @@ on:
|
||||
# Run manually if needed to publish out of schedule.
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write # for pushing the `ghcr/server` branch
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
3
.github/workflows/server-release.yml
vendored
@@ -3,6 +3,9 @@ name: "Release (server)"
|
||||
on:
|
||||
workflow_dispatch: # Run manually
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
4
.github/workflows/web-crowdin-push-both.yml
vendored
@@ -12,6 +12,10 @@ on:
|
||||
# `gh workflow run web-crowdin-push-both.yml --ref <my-branch>`
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
push-both-to-crowdin:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
9
.github/workflows/web-crowdin-sync.yml
vendored
@@ -22,6 +22,15 @@ on:
|
||||
# Also allow manually running the workflow.
|
||||
workflow_dispatch:
|
||||
|
||||
# "In order to push translations and create pull requests, the Crowdin GitHub
|
||||
# action requires the `GITHUB_TOKEN` to have write permission on the `contents`
|
||||
# and `pull-requests`.
|
||||
#
|
||||
# - https://github.com/crowdin/github-action?tab=readme-ov-file#permissions
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
synchronize-with-crowdin:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
5
.github/workflows/web-deploy-one.yml
vendored
@@ -15,6 +15,9 @@ on:
|
||||
- "payments"
|
||||
- "photos"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -30,7 +33,7 @@ jobs:
|
||||
- name: Setup node and enable yarn caching
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
node-version: 22
|
||||
cache: "yarn"
|
||||
cache-dependency-path: "web/yarn.lock"
|
||||
|
||||
|
||||
5
.github/workflows/web-deploy-preview.yml
vendored
@@ -15,6 +15,9 @@ on:
|
||||
- "payments"
|
||||
- "photos"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -30,7 +33,7 @@ jobs:
|
||||
- name: Setup node and enable yarn caching
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
node-version: 22
|
||||
cache: "yarn"
|
||||
cache-dependency-path: "web/yarn.lock"
|
||||
|
||||
|
||||
5
.github/workflows/web-deploy-staging.yml
vendored
@@ -11,6 +11,9 @@ on:
|
||||
# Also allow manually running the workflow
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -38,7 +41,7 @@ jobs:
|
||||
- name: Setup node and enable yarn caching
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
node-version: 22
|
||||
cache: "yarn"
|
||||
cache-dependency-path: "web/yarn.lock"
|
||||
|
||||
|
||||
5
.github/workflows/web-deploy.yml
vendored
@@ -19,6 +19,9 @@ on:
|
||||
# Also allow manually running the workflow
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -34,7 +37,7 @@ jobs:
|
||||
- name: Setup node and enable yarn caching
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
node-version: 22
|
||||
cache: "yarn"
|
||||
cache-dependency-path: "web/yarn.lock"
|
||||
|
||||
|
||||
5
.github/workflows/web-lint.yml
vendored
@@ -7,6 +7,9 @@ on:
|
||||
- "web/**"
|
||||
- ".github/workflows/web-lint.yml"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
# Cancel in-progress lint runs when a new commit is pushed.
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -25,7 +28,7 @@ jobs:
|
||||
- name: Setup node and enable yarn caching
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
node-version: 22
|
||||
cache: "yarn"
|
||||
cache-dependency-path: "web/yarn.lock"
|
||||
|
||||
|
||||
4
.github/workflows/web-publish-ghcr.yml
vendored
@@ -7,6 +7,10 @@ on:
|
||||
# Run manually if needed to publish out of schedule.
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write # for pushing the `ghcr/web` branch
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -35,7 +35,7 @@ Private sharing. Collaborative albums. Family plans. Easy import, easier export.
|
||||
Background uploads. The list goes on. And of course, all of this, while being
|
||||
fully end-to-end encrypted across platforms.
|
||||
|
||||
Ente Photos is a paid service, but we offer 5GB of free storage.
|
||||
Ente Photos is a paid service, but we offer 10GB of free storage.
|
||||
You can also clone this repository and choose to self-host.
|
||||
|
||||
<br />
|
||||
|
||||
3
auth/.fvmrc
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"flutter": "3.24.3"
|
||||
}
|
||||
5
auth/.gitignore
vendored
@@ -41,4 +41,7 @@ lib/generated_plugin_registrant.dart
|
||||
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
|
||||
|
||||
android/key.properties
|
||||
dist/
|
||||
dist/
|
||||
|
||||
# FVM Version Cache
|
||||
.fvm/
|
||||
2
auth/android/.gitignore
vendored
@@ -5,6 +5,8 @@ gradle-wrapper.jar
|
||||
/gradlew.bat
|
||||
/local.properties
|
||||
GeneratedPluginRegistrant.java
|
||||
/app/.cxx/
|
||||
/.kotlin/
|
||||
|
||||
# Remember to never publicly share your keystore.
|
||||
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
|
||||
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 6.2 KiB |
|
After Width: | Height: | Size: 8.7 KiB |
@@ -1,6 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
<foreground>
|
||||
<inset
|
||||
android:drawable="@drawable/ic_launcher_foreground"
|
||||
android:inset="0%" />
|
||||
</foreground>
|
||||
<monochrome>
|
||||
<inset
|
||||
android:drawable="@drawable/ic_launcher_monochrome"
|
||||
android:inset="0%" />
|
||||
</monochrome>
|
||||
</adaptive-icon>
|
||||
|
||||
@@ -285,6 +285,15 @@
|
||||
"title": "CSGORoll",
|
||||
"slug": "csgoroll"
|
||||
},
|
||||
{
|
||||
"title": "Cwallet",
|
||||
"altNames": [
|
||||
"cwallet",
|
||||
"c-wallet",
|
||||
"c wallet",
|
||||
"cwallet.com"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "DCS",
|
||||
"altNames": [
|
||||
@@ -376,6 +385,13 @@
|
||||
],
|
||||
"hex": "858585"
|
||||
},
|
||||
{
|
||||
"title": "Fanatical",
|
||||
"slug": "fanatical",
|
||||
"altNames": [
|
||||
"FANATICAL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Fastmail"
|
||||
},
|
||||
@@ -405,6 +421,9 @@
|
||||
"title": "Firefox",
|
||||
"slug": "mozilla"
|
||||
},
|
||||
{
|
||||
"title": "fortrabbit"
|
||||
},
|
||||
{
|
||||
"title": "ForUsAll"
|
||||
},
|
||||
@@ -658,6 +677,14 @@
|
||||
"mathworks"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Mbin",
|
||||
"altNames": [
|
||||
"kbin",
|
||||
"thebrainbin",
|
||||
"gehirneimer"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Mercado Livre",
|
||||
"slug": "mercado_livre",
|
||||
@@ -888,6 +915,13 @@
|
||||
{
|
||||
"title": "PostNL"
|
||||
},
|
||||
{
|
||||
"title": "Postmark",
|
||||
"slug": "postmarkapp",
|
||||
"altNames": [
|
||||
"postmarkapp"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "PostScan Mail",
|
||||
"slug": "postscanmail",
|
||||
@@ -952,6 +986,15 @@
|
||||
"slug": "realvnc",
|
||||
"hex": "488aec"
|
||||
},
|
||||
{
|
||||
"title": "RedotPay",
|
||||
"altNames": [
|
||||
"redotpay",
|
||||
"redot pay",
|
||||
"redot-pay",
|
||||
"redotpay.com"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Registro br",
|
||||
"slug": "registro_br",
|
||||
|
||||
@@ -1 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 150 150"><defs><style>.e{fill:#2a54ff;}.f{fill:url(#d);}.g{fill:none;}</style><linearGradient id="d" x1="17.68" y1="116.45" x2="132.14" y2="32.11" gradientTransform="matrix(1, 0, 0, 1, 0, 0)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#2a54ff"/><stop offset=".52" stop-color="#2143cb"/><stop offset="1" stop-color="#2a54ff"/></linearGradient></defs><g id="b"><path id="c" class="g" d="M0,0H150V150H0V0Z"/></g><path class="f" d="M140.2,22.33c-25.18-.09-49.79,10.83-66.63,29.47-6.06,6.27-10.1,13.95-14.96,21.06-11.64,15.93-29.81,25.14-49.5,25.13h0v28.65h0c25.17,.1,49.78-10.86,66.63-29.5,6.03-6.27,10.13-13.94,14.96-21.06,11.64-15.91,29.81-25.12,49.5-25.11V22.33h0Z"/><path class="e" d="M140.2,97.99c-19.68,0-37.86-9.2-49.5-25.11-4.81-7.12-8.92-14.78-14.94-21.06C58.95,33.18,34.3,22.24,9.13,22.35h0v28.65h0c21.8-.11,42.05,11.62,53.01,30.46,3.22,5.62,7.06,10.9,11.45,15.74,16.83,18.63,41.46,29.59,66.63,29.5l-.02-28.7h0Z"/></svg>
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="a" viewBox="0 0 150 150">
|
||||
<defs>
|
||||
<linearGradient id="d" x1="17.68" y1="116.45" x2="132.14" y2="32.11"
|
||||
gradientTransform="matrix(1, 0, 0, 1, 0, 0)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#2a54ff" />
|
||||
<stop offset=".52" stop-color="#2143cb" />
|
||||
<stop offset="1" stop-color="#2a54ff" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g id="b">
|
||||
<path id="c" d="M0,0H150V150H0V0Z" fill="none" />
|
||||
</g>
|
||||
<path
|
||||
d="M140.2,22.33c-25.18-.09-49.79,10.83-66.63,29.47-6.06,6.27-10.1,13.95-14.96,21.06-11.64,15.93-29.81,25.14-49.5,25.13h0v28.65h0c25.17,.1,49.78-10.86,66.63-29.5,6.03-6.27,10.13-13.94,14.96-21.06,11.64-15.91,29.81-25.12,49.5-25.11V22.33h0Z"
|
||||
fill="url(#d)" />
|
||||
<path
|
||||
d="M140.2,97.99c-19.68,0-37.86-9.2-49.5-25.11-4.81-7.12-8.92-14.78-14.94-21.06C58.95,33.18,34.3,22.24,9.13,22.35h0v28.65h0c21.8-.11,42.05,11.62,53.01,30.46,3.22,5.62,7.06,10.9,11.45,15.74,16.83,18.63,41.46,29.59,66.63,29.5l-.02-28.7h0Z"
|
||||
fill="#2a54ff" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -1,130 +1,59 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 27.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 30 30" style="enable-background:new 0 0 30 30;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#C5C8CA;}
|
||||
.st1{fill:#9DA4A8;}
|
||||
.st2{fill:#B7BBBD;}
|
||||
.st3{fill:#CBCFD1;}
|
||||
.st4{fill:#BBBFC2;}
|
||||
.st5{fill:#CACDCE;}
|
||||
.st6{fill:#BFC3C5;}
|
||||
.st7{fill:#BCC0C2;}
|
||||
.st8{fill:#BDC1C4;}
|
||||
.st9{fill:#C7CACC;}
|
||||
.st10{fill:url(#SVGID_1_);}
|
||||
.st11{fill:#FFFFFF;}
|
||||
.st12{fill:#B8BCBF;}
|
||||
.st13{fill:#C4C7C9;}
|
||||
.st14{fill:#C1C5C7;}
|
||||
.st15{fill:url(#SVGID_00000003093454306001190100000011813141018663887528_);}
|
||||
.st16{fill:url(#SVGID_00000017503418065689336600000007511615486600436881_);}
|
||||
.st17{fill:url(#SVGID_00000057845154053127761930000017803385842445649033_);}
|
||||
.st18{fill:url(#SVGID_00000156571711195124538550000006687723982713171592_);}
|
||||
.st19{fill:#DF3030;}
|
||||
.st20{fill:url(#SVGID_00000001636660173574603980000008731795684331757470_);}
|
||||
.st21{fill:#17181C;}
|
||||
.st22{fill:url(#SVGID_00000180343933242210086490000003762167186865041053_);}
|
||||
.st23{fill:url(#SVGID_00000015338415700440354440000005681408021599925436_);}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M14.4,29.5c0.1,0,0.1,0,0.2,0c0.1,0,0.2,0,0.2,0H14.4z"/>
|
||||
<path class="st1" d="M15.3,29.5h0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0L15.3,29.5
|
||||
C15.2,29.5,15.3,29.5,15.3,29.5z"/>
|
||||
<path class="st2" d="M15.3,29.5L15.3,29.5l-0.2,0C15.2,29.5,15.2,29.5,15.3,29.5z"/>
|
||||
<path class="st3" d="M15.5,29.5L15.5,29.5L15.5,29.5L15.5,29.5L15.5,29.5z"/>
|
||||
<path class="st0" d="M14.1,29.5c0.1,0,0.1,0,0.2,0H14.1z"/>
|
||||
<path class="st4" d="M13.9,29.5C13.9,29.5,14,29.5,13.9,29.5c0.1,0,0.1,0,0.2,0H13.9z"/>
|
||||
<path class="st5" d="M13.6,29.5C13.6,29.5,13.6,29.5,13.6,29.5c0.1,0,0.1,0,0.1,0H13.6z"/>
|
||||
<path class="st6" d="M13.7,29.5C13.8,29.5,13.8,29.5,13.7,29.5c0.1,0,0.1,0,0.1,0H13.7z"/>
|
||||
<path class="st7" d="M13.3,29.4C13.3,29.4,13.3,29.4,13.3,29.4C13.4,29.4,13.4,29.4,13.3,29.4L13.3,29.4z"/>
|
||||
<path class="st8" d="M13.4,29.5C13.4,29.4,13.5,29.4,13.4,29.5C13.5,29.4,13.5,29.4,13.4,29.5L13.4,29.5z"/>
|
||||
<path class="st8" d="M13.1,29.4C13.1,29.4,13.1,29.4,13.1,29.4C13.1,29.4,13.1,29.4,13.1,29.4L13.1,29.4z"/>
|
||||
<path class="st9" d="M13.2,29.4C13.2,29.4,13.2,29.4,13.2,29.4C13.2,29.4,13.2,29.4,13.2,29.4C13.2,29.4,13.2,29.4,13.2,29.4
|
||||
C13.3,29.4,13.3,29.4,13.2,29.4L13.2,29.4z"/>
|
||||
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="21.8812" y1="-88.078" x2="8.2545" y2="-104.6955" gradientTransform="matrix(1 0 0 -1 0 -81.48)">
|
||||
<stop offset="0" style="stop-color:#020037"/>
|
||||
<stop offset="1" style="stop-color:#050F62"/>
|
||||
</linearGradient>
|
||||
<path class="st10" d="M15,0.4C11.1,0.4,7.5,2,4.7,4.7C2,7.4,0.5,11.1,0.5,15c0,1.7,0.3,3.4,0.9,5.1c0.3,0,0.5,0,0.8,0
|
||||
c2.9,0,5.8,0.9,8.2,2.6c2.4,1.7,4.2,4.1,5.1,6.9c3.8-0.1,7.4-1.7,10-4.4c2.6-2.7,4.1-6.4,4.1-10.1c0-3.9-1.5-7.6-4.3-10.3
|
||||
C22.6,2,18.9,0.4,15,0.4"/>
|
||||
<path class="st11" d="M20.7,22.5C20.7,22.5,20.7,22.5,20.7,22.5L20.7,22.5c0,0.4,0.1,0.8,0.3,1c0.2,0.2,0.6,0.3,1,0.3c0,0,0,0,0,0
|
||||
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0c-0.4,0-0.7,0.1-1,0.3c-0.2,0.2-0.3,0.6-0.3,1c0,0,0,0,0,0c0,0,0,0,0,0
|
||||
c0,0,0,0,0,0c0,0,0,0,0,0h0l0,0c0-0.4-0.1-0.7-0.3-1c-0.2-0.2-0.6-0.3-1-0.3c0,0,0,0,0,0l0,0c0,0,0,0,0,0s0,0,0,0c0,0,0,0,0,0
|
||||
c0,0,0,0,0,0c0.4,0,0.7-0.1,1-0.3S20.7,22.9,20.7,22.5C20.7,22.5,20.7,22.5,20.7,22.5C20.7,22.5,20.7,22.5,20.7,22.5z"/>
|
||||
<path class="st11" d="M6.9,15.5C6.9,15.5,6.9,15.5,6.9,15.5L6.9,15.5c0,0.4,0.1,0.8,0.3,1c0.2,0.2,0.6,0.3,1,0.3c0,0,0,0,0,0
|
||||
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0c-0.4,0-0.7,0.1-1,0.3c-0.2,0.2-0.3,0.6-0.3,1c0,0,0,0,0,0c0,0,0,0,0,0
|
||||
c0,0,0,0,0,0c0,0,0,0,0,0h0l0,0c0-0.4-0.1-0.7-0.3-1c-0.2-0.2-0.6-0.3-1-0.3c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
|
||||
c0,0,0,0,0,0c0.4,0,0.7-0.1,1-0.3C6.8,16.2,6.9,15.9,6.9,15.5C6.9,15.5,6.9,15.5,6.9,15.5C6.9,15.5,6.9,15.5,6.9,15.5z"/>
|
||||
<path class="st11" d="M10.6,4.1L10.6,4.1C10.7,4.1,10.7,4.1,10.6,4.1c0,0.3,0.1,0.5,0.3,0.7c0.2,0.2,0.4,0.3,0.7,0.2h0v0l0,0l0,0
|
||||
l0,0l0,0c-0.3,0-0.5,0.1-0.7,0.2c-0.2,0.2-0.3,0.4-0.2,0.7l0,0l0,0l0,0l0,0h0v0c0-0.3-0.1-0.5-0.2-0.7C10.2,5.1,10,5,9.7,5.1h0v0v0
|
||||
h0C10,5,10.2,5,10.4,4.8C10.6,4.6,10.7,4.3,10.6,4.1C10.6,4.1,10.6,4.1,10.6,4.1C10.6,4.1,10.6,4.1,10.6,4.1z"/>
|
||||
<path class="st12" d="M12.8,29.4C12.8,29.4,12.8,29.4,12.8,29.4C12.8,29.4,12.8,29.4,12.8,29.4C12.8,29.4,12.8,29.4,12.8,29.4
|
||||
C12.8,29.4,12.8,29.4,12.8,29.4L12.8,29.4z"/>
|
||||
<path class="st13" d="M13,29.4C13,29.4,13,29.4,13,29.4C13,29.4,13,29.4,13,29.4L13,29.4z"/>
|
||||
<path class="st14" d="M12.9,29.4C12.9,29.4,12.9,29.4,12.9,29.4C12.9,29.4,12.9,29.4,12.9,29.4L12.9,29.4z"/>
|
||||
|
||||
<linearGradient id="SVGID_00000173122186048074043340000017421439166240502921_" gradientUnits="userSpaceOnUse" x1="19.2457" y1="-89.3156" x2="22.9553" y2="-91.7188" gradientTransform="matrix(1 0 0 -1 0 -81.48)">
|
||||
<stop offset="0" style="stop-color:#E5E5E5"/>
|
||||
<stop offset="1" style="stop-color:#B7B8C1"/>
|
||||
</linearGradient>
|
||||
<path style="fill:url(#SVGID_00000173122186048074043340000017421439166240502921_);" d="M21.8,1.2c-1.4,0.7-3,1.9-4.4,4.2
|
||||
c-2.5,3.9-3.2,7.4-3.2,7.4L16,14l0.3,0.2l1.9,1.2c0,0,2.9-2,5.4-5.9c1.5-2.3,2-4.3,2-5.8c-0.8-0.1-1.5-0.4-2.2-0.8
|
||||
C22.8,2.5,22.2,1.9,21.8,1.2z"/>
|
||||
|
||||
<linearGradient id="SVGID_00000127763695479642710240000017533313096818365313_" gradientUnits="userSpaceOnUse" x1="21.2378" y1="-99.9826" x2="19.0472" y2="-97.8815" gradientTransform="matrix(1 0 0 -1 0 -81.48)">
|
||||
<stop offset="0" style="stop-color:#EC4F4F"/>
|
||||
<stop offset="1" style="stop-color:#A91919"/>
|
||||
</linearGradient>
|
||||
<path style="fill:url(#SVGID_00000127763695479642710240000017533313096818365313_);" d="M20.8,16.8c0.9-1.4,0.3-3.2,0-3.8
|
||||
c-0.7,0.8-1.5,1.5-2.3,2.1c0.1,0.4,0.3,0.8,0.3,1.2c0,0.1,0,0.2-0.1,0.3c-0.4,0.6-0.8,1.3-1.1,2c-0.1,0.1-0.1,0.2-0.1,0.3
|
||||
c-0.1,0.2-0.1,0.3,0,0.5c0,0.3,0.2,0.5,0.3,0.8c0,0,0.1,0.1,0.1,0.1c0.1,0,0.1,0.1,0.2,0.1s0.1,0,0.2-0.1c0.1-0.1,0.3-0.2,0.4-0.4
|
||||
C19.5,19,19.8,18.5,20.8,16.8z"/>
|
||||
|
||||
<linearGradient id="SVGID_00000060717637781723915790000002744012061535479481_" gradientUnits="userSpaceOnUse" x1="11.3158" y1="-99.2586" x2="14.8122" y2="-101.5237" gradientTransform="matrix(1 0 0 -1 0 -81.48)">
|
||||
<stop offset="0" style="stop-color:#F2A518"/>
|
||||
<stop offset="1" style="stop-color:#F4E23E"/>
|
||||
</linearGradient>
|
||||
<path style="fill:url(#SVGID_00000060717637781723915790000002744012061535479481_);" d="M15.1,15.7l-1.7-1.1c-2,3.1-3.3,7-2.4,7.5
|
||||
c0.9,0.6,3.9-2.2,5.9-5.3L15.1,15.7z"/>
|
||||
|
||||
<linearGradient id="SVGID_00000070084874335106853820000008402293642909580433_" gradientUnits="userSpaceOnUse" x1="-4386.2534" y1="747.6443" x2="-4497.9517" y2="769.0099" gradientTransform="matrix(1 0 0 -1 0 -81.48)">
|
||||
<stop offset="0" style="stop-color:#EC4F4F"/>
|
||||
<stop offset="1" style="stop-color:#A91919"/>
|
||||
</linearGradient>
|
||||
<path style="fill:url(#SVGID_00000070084874335106853820000008402293642909580433_);" d="M15.2,9.5c-0.7-0.1-2.5,0.1-3.4,1.5
|
||||
c-1.1,1.6-1.5,2.1-2,3.2c-0.1,0.2-0.1,0.3-0.2,0.5c0,0.1,0,0.1,0,0.2C9.6,15,9.7,15,9.7,15c0,0,0.1,0,0.2,0.1c0.3,0.1,0.6,0,0.8,0
|
||||
c0.2,0,0.3-0.1,0.4-0.2c0.1-0.1,0.2-0.2,0.3-0.3c0.5-0.6,0.9-1.2,1.3-1.8c0.1-0.1,0.2-0.2,0.3-0.2c0.4-0.1,0.8-0.1,1.2-0.2l0,0
|
||||
C14.5,11.4,14.8,10.4,15.2,9.5z"/>
|
||||
<path class="st19" d="M25,0.6c-0.2-0.1-1.5-0.2-3.2,0.7c0.4,0.7,1,1.2,1.6,1.7c0.7,0.4,1.4,0.7,2.2,0.8C25.7,1.9,25.1,0.7,25,0.6z"
|
||||
/>
|
||||
<path class="st19" d="M18.4,15.5L14,12.7c-0.1,0-0.1,0-0.2,0l-0.9,1.4c0,0.1,0,0.1,0,0.2l4.4,2.8c0.1,0,0.1,0,0.2,0l0.9-1.4
|
||||
C18.4,15.6,18.4,15.6,18.4,15.5z"/>
|
||||
|
||||
<linearGradient id="SVGID_00000044894753735506851200000013592864944465274029_" gradientUnits="userSpaceOnUse" x1="14.9436" y1="-95.9217" x2="16.3716" y2="-96.8468" gradientTransform="matrix(1 0 0 -1 0 -81.48)">
|
||||
<stop offset="0" style="stop-color:#B71E1E"/>
|
||||
<stop offset="0.44" style="stop-color:#DF3030"/>
|
||||
<stop offset="1" style="stop-color:#C51D1D"/>
|
||||
</linearGradient>
|
||||
<path style="fill:url(#SVGID_00000044894753735506851200000013592864944465274029_);" d="M17.8,11.6c-0.4-0.2-2.1,1.6-3.2,3.3
|
||||
c-0.8,1.2-1.4,3-1.1,3.2c0.4,0.2,1.7-1,2.5-2.3C17.1,14.2,18.1,11.9,17.8,11.6z"/>
|
||||
<path class="st21" d="M21.2,8.6c1.3,0,2.3-1,2.3-2.3s-1-2.3-2.3-2.3c-1.3,0-2.3,1-2.3,2.3S20,8.6,21.2,8.6z"/>
|
||||
|
||||
<linearGradient id="SVGID_00000090987122570624474440000002432161440392897685_" gradientUnits="userSpaceOnUse" x1="20.068" y1="-87.0655" x2="22.3556" y2="-88.5473" gradientTransform="matrix(1 0 0 -1 0 -81.48)">
|
||||
<stop offset="0" style="stop-color:#CED1EC"/>
|
||||
<stop offset="1" style="stop-color:#FFFFFF"/>
|
||||
</linearGradient>
|
||||
<path style="fill:url(#SVGID_00000090987122570624474440000002432161440392897685_);" d="M21.2,7.7c0.8,0,1.4-0.6,1.4-1.4
|
||||
S22,5,21.2,5c-0.8,0-1.4,0.6-1.4,1.4S20.5,7.7,21.2,7.7z"/>
|
||||
|
||||
<linearGradient id="SVGID_00000044151119195171880090000016489263670362291109_" gradientUnits="userSpaceOnUse" x1="14.4192" y1="-110.4727" x2="2.0973" y2="-101.7197" gradientTransform="matrix(1 0 0 -1 0 -81.48)">
|
||||
<stop offset="0" style="stop-color:#B7B7BD"/>
|
||||
<stop offset="0.68" style="stop-color:#EFEFEF"/>
|
||||
</linearGradient>
|
||||
<path style="fill:url(#SVGID_00000044151119195171880090000016489263670362291109_);" d="M2.1,20c-0.3,0-0.5,0-0.8,0
|
||||
c1,2.8,2.9,5.2,5.3,6.9s5.3,2.6,8.3,2.6c0.1,0,0.3,0,0.4,0c-0.9-2.8-2.7-5.2-5.1-6.9C7.9,20.9,5.1,20,2.1,20z"/>
|
||||
</g>
|
||||
</svg>
|
||||
<svg xml:space="preserve" xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" id="Layer_1" x="0" y="0" version="1.1"
|
||||
viewBox="0 0 30 30">
|
||||
<path d="M14.4 29.5h.4z" fill="#c5c8ca" />
|
||||
<path fill="#9da4a8" d="M15.3 29.5h.1zc-.1 0 0 0 0 0" />
|
||||
<path fill="#b7bbbd" d="M15.3 29.5h-.2z" />
|
||||
<path d="M14.1 29.5h.2z" fill="#c5c8ca" />
|
||||
<path fill="#bbbfc2" d="M13.9 29.5s.1 0 0 0h.2z" />
|
||||
<path fill="#cacdce" d="M13.6 29.5h.1z" />
|
||||
<path fill="#bfc3c5" d="M13.7 29.5q.15 0 0 0h.1z" />
|
||||
<path fill="#bcc0c2" d="M13.3 29.4q.15 0 0 0" />
|
||||
<path fill="#bdc1c4" d="M13.4 29.5c0-.1.1-.1 0 0q.15-.15 0 0m-.3-.1" />
|
||||
<path fill="#c7cacc" d="M13.2 29.4q.15 0 0 0" />
|
||||
<linearGradient id="SVGID_1_" x1="21.8812" x2="8.2545" y1="-88.078" y2="-104.6955" gradientTransform="matrix(1 0 0 -1 0 -81.48)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#020037" />
|
||||
<stop offset="1" stop-color="#050f62" />
|
||||
</linearGradient>
|
||||
<path fill="url(#SVGID_1_)" d="M15 .4C11.1.4 7.5 2 4.7 4.7 2 7.4.5 11.1.5 15q0 2.55.9 5.1h.8c2.9 0 5.8.9 8.2 2.6s4.2 4.1 5.1 6.9c3.8-.1 7.4-1.7 10-4.4s4.1-6.4 4.1-10.1c0-3.9-1.5-7.6-4.3-10.3C22.6 2 18.9.4 15 .4" />
|
||||
<path fill="#fff" d="M20.7 22.5c0 .4.1.8.3 1s.6.3 1 .3c-.4 0-.7.1-1 .3-.2.2-.3.6-.3 1 0-.4-.1-.7-.3-1-.2-.2-.6-.3-1-.3.4 0 .7-.1 1-.3s.3-.6.3-1m-13.8-7c0 .4.1.8.3 1s.6.3 1 .3c-.4 0-.7.1-1 .3-.2.2-.3.6-.3 1 0-.4-.1-.7-.3-1-.2-.2-.6-.3-1-.3.4 0 .7-.1 1-.3.2-.3.3-.6.3-1m3.7-11.4q.15 0 0 0c0 .3.1.5.3.7s.4.3.7.2c-.3 0-.5.1-.7.2-.2.2-.3.4-.2.7 0-.3-.1-.5-.2-.7-.3-.1-.5-.2-.8-.1.3-.1.5-.1.7-.3s.3-.5.2-.7" />
|
||||
<linearGradient id="SVGID_00000173122186048074043340000017421439166240502921_" x1="19.2457" x2="22.9553" y1="-89.3156" y2="-91.7188" gradientTransform="matrix(1 0 0 -1 0 -81.48)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#e5e5e5" />
|
||||
<stop offset="1" stop-color="#b7b8c1" />
|
||||
</linearGradient>
|
||||
<path fill="url(#SVGID_00000173122186048074043340000017421439166240502921_)" d="M21.8 1.2c-1.4.7-3 1.9-4.4 4.2-2.5 3.9-3.2 7.4-3.2 7.4L16 14l.3.2 1.9 1.2s2.9-2 5.4-5.9c1.5-2.3 2-4.3 2-5.8-.8-.1-1.5-.4-2.2-.8-.6-.4-1.2-1-1.6-1.7" />
|
||||
<linearGradient id="SVGID_00000127763695479642710240000017533313096818365313_" x1="21.2378" x2="19.0472" y1="-99.9826" y2="-97.8815" gradientTransform="matrix(1 0 0 -1 0 -81.48)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#ec4f4f" />
|
||||
<stop offset="1" stop-color="#a91919" />
|
||||
</linearGradient>
|
||||
<path fill="url(#SVGID_00000127763695479642710240000017533313096818365313_)" d="M20.8 16.8c.9-1.4.3-3.2 0-3.8-.7.8-1.5 1.5-2.3 2.1.1.4.3.8.3 1.2 0 .1 0 .2-.1.3-.4.6-.8 1.3-1.1 2-.1.1-.1.2-.1.3-.1.2-.1.3 0 .5 0 .3.2.5.3.8l.1.1c.1 0 .1.1.2.1s.1 0 .2-.1.3-.2.4-.4c.8-.9 1.1-1.4 2.1-3.1" />
|
||||
<linearGradient id="SVGID_00000060717637781723915790000002744012061535479481_" x1="11.3158" x2="14.8122" y1="-99.2586" y2="-101.5237" gradientTransform="matrix(1 0 0 -1 0 -81.48)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#f2a518" />
|
||||
<stop offset="1" stop-color="#f4e23e" />
|
||||
</linearGradient>
|
||||
<path fill="url(#SVGID_00000060717637781723915790000002744012061535479481_)" d="m15.1 15.7-1.7-1.1c-2 3.1-3.3 7-2.4 7.5.9.6 3.9-2.2 5.9-5.3z" />
|
||||
<linearGradient id="SVGID_00000070084874335106853820000008402293642909580433_" x1="-4386.2534" x2="-4497.9517" y1="747.6443" y2="769.0099" gradientTransform="matrix(1 0 0 -1 0 -81.48)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#ec4f4f" />
|
||||
<stop offset="1" stop-color="#a91919" />
|
||||
</linearGradient>
|
||||
<path fill="url(#SVGID_00000070084874335106853820000008402293642909580433_)" d="M15.2 9.5c-.7-.1-2.5.1-3.4 1.5-1.1 1.6-1.5 2.1-2 3.2-.1.2-.1.3-.2.5v.2c0 .1.1.1.1.1s.1 0 .2.1c.3.1.6 0 .8 0s.3-.1.4-.2l.3-.3c.5-.6.9-1.2 1.3-1.8.1-.1.2-.2.3-.2.4-.1.8-.1 1.2-.2.3-1 .6-2 1-2.9" />
|
||||
<path fill="#df3030" d="M25 .6c-.2-.1-1.5-.2-3.2.7.4.7 1 1.2 1.6 1.7.7.4 1.4.7 2.2.8.1-1.9-.5-3.1-.6-3.2m-6.6 14.9L14 12.7h-.2l-.9 1.4v.2l4.4 2.8h.2l.9-1.4z" />
|
||||
<linearGradient id="SVGID_00000044894753735506851200000013592864944465274029_" x1="14.9436" x2="16.3716" y1="-95.9217" y2="-96.8468" gradientTransform="matrix(1 0 0 -1 0 -81.48)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#b71e1e" />
|
||||
<stop offset=".44" stop-color="#df3030" />
|
||||
<stop offset="1" stop-color="#c51d1d" />
|
||||
</linearGradient>
|
||||
<path fill="url(#SVGID_00000044894753735506851200000013592864944465274029_)" d="M17.8 11.6c-.4-.2-2.1 1.6-3.2 3.3-.8 1.2-1.4 3-1.1 3.2.4.2 1.7-1 2.5-2.3 1.1-1.6 2.1-3.9 1.8-4.2" />
|
||||
<path fill="#17181c" d="M21.2 8.6c1.3 0 2.3-1 2.3-2.3S22.5 4 21.2 4s-2.3 1-2.3 2.3 1.1 2.3 2.3 2.3" />
|
||||
<linearGradient id="SVGID_00000090987122570624474440000002432161440392897685_" x1="20.068" x2="22.3556" y1="-87.0655" y2="-88.5473" gradientTransform="matrix(1 0 0 -1 0 -81.48)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#ced1ec" />
|
||||
<stop offset="1" stop-color="#fff" />
|
||||
</linearGradient>
|
||||
<path fill="url(#SVGID_00000090987122570624474440000002432161440392897685_)" d="M21.2 7.7c.8 0 1.4-.6 1.4-1.4S22 5 21.2 5s-1.4.6-1.4 1.4.7 1.3 1.4 1.3" />
|
||||
<linearGradient id="SVGID_00000044151119195171880090000016489263670362291109_" x1="14.4192" x2="2.0973" y1="-110.4727" y2="-101.7197" gradientTransform="matrix(1 0 0 -1 0 -81.48)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#b7b7bd" />
|
||||
<stop offset=".68" stop-color="#efefef" />
|
||||
</linearGradient>
|
||||
<path fill="url(#SVGID_00000044151119195171880090000016489263670362291109_)" d="M2.1 20h-.8c1 2.8 2.9 5.2 5.3 6.9s5.3 2.6 8.3 2.6h.4c-.9-2.8-2.7-5.2-5.1-6.9C7.9 20.9 5.1 20 2.1 20" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 5.6 KiB |
1
auth/assets/custom-icons/icons/cwallet.svg
Normal file
|
After Width: | Height: | Size: 16 KiB |
44
auth/assets/custom-icons/icons/fanatical.svg
Normal file
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 399.76401 400"
|
||||
preserveAspectRatio="xMinYMid"
|
||||
aria-labelledby="navbar-fanatical-logo"
|
||||
version="1.1"
|
||||
id="svg2"
|
||||
sodipodi:docname="Untitled.svg"
|
||||
width="399.76401"
|
||||
height="400"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="namedview2"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:zoom="0.69295302"
|
||||
inkscape:cx="205.64165"
|
||||
inkscape:cy="207.08475"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="938"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2" />
|
||||
<g
|
||||
fill="none"
|
||||
id="g2">
|
||||
<path
|
||||
fill="#ff9800"
|
||||
d="m 2.8756,166.0056 h 284.671 a 2.9981,2.9981 0 0 0 2.7221,-1.7424 l 25.8632,-56.0452 c 0.6946,-1.504 0.0391,-3.2867 -1.464,-3.9817 a 2.9968,2.9968 0 0 0 -1.258,-0.2767 L 24.4917,103.9952 C 58.4482,42.0187 124.261,0 199.882,0 c 110.3917,0 199.882,89.543 199.882,200 0,110.457 -89.4903,200 -199.882,200 C 89.4902,400 0,310.457 0,200 0,188.412 0.985,177.054 2.8756,166.0056 Z M 125.9256,328 c 0,2.2091 1.7898,4 3.9977,4 h 5.1722 l 62.8312,-79.0111 h 49.4291 a 2.9981,2.9981 0 0 0 2.722,-1.7422 l 25.835,-55.976 a 3.0015,3.0015 0 0 0 0.2761,-1.2577 c 0,-1.6569 -1.3423,-3 -2.9982,-3 H 125.9257 V 328 Z"
|
||||
id="path1" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
1
auth/assets/custom-icons/icons/fortrabbit.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300"><path d="M115 144c0 6-2 12-7 16s-9 7-16 7-11-3-16-7-6-10-6-16 2-12 6-16 10-7 16-7 12 3 16 7c5 5 7 10 7 16zm71-23-8 38-7 34a63 63 0 0 1-36 42c-5 2-11 3-17 3s-10 0-14-2l-7-4c-2-1-4-3-4-5l-1-6c0-4 1-7 3-9s6-4 10-4l9 2c3 1 4 4 6 6l4 8 3 7c3-3 5-7 7-13l7-22 16-75h-18l2-9h18l1-7c1-6 4-11 7-17s7-10 12-14c4-4 10-8 16-10s11-4 17-4l13 1 8 4 4 6 1 6a15 15 0 0 1-3 8l-4 4-7 1-8-2-6-6-4-8-3-7c-3 3-5 7-7 12l-6 23-2 10h22l-2 9h-22z"/></svg>
|
||||
|
After Width: | Height: | Size: 491 B |
@@ -1,4 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 724 264">
|
||||
<path
|
||||
d="M38.53 260.65H.43V27.86h38.1zm86.46 2.77c-42.25 0-66.48-22.96-66.48-63V89.33h38.1v108.28c0 23.61 8.7 32.39 32.12 32.39 30.35 0 42.73-14.54 42.73-50.17v-90.5h38.1v171.33h-36.54v-29.91c-4.99 22.98-27.12 32.67-48.03 32.67zm347.2-2.77H434.4V149.87c0-22.5-7.01-30.87-25.88-30.87-24.28 0-37.11 14.45-37.11 41.79v99.86h-37.79V149.87c0-21.93-7.23-30.87-24.94-30.87-31.59 0-38.05 32.96-38.05 41.79v99.86h-38.1V89.33h36.54v29.96c6.49-21.02 27.02-33.71 47.72-33.71 20.69 0 38.09 7.9 45.64 33.71 10.13-26.76 28.35-33.71 50.15-33.71 37.88 0 59.61 18.88 59.61 51.81v123.26h0zm76.65 2.77c-52.62 0-61.55-33.45-61.55-50.52 0-20.1 8.83-38.21 27.93-45.55 8.41-3.11 16.52-5.43 24.84-7.1 7.33-1.47 18.64-3.03 26.91-4.17l2.73-.38c14.38-2 29.67-9.21 29.67-18.62 0-16-20.51-18.39-32.74-18.39-13.87 0-23.64 3.57-27.53 10.05-3.49 6.46-3.73 7.97-4.62 13.6l-.62 4.43h-38.1l.68-5.61c1.35-11.14 3.41-19.03 6.48-24.83 10.54-20.39 31.77-30.75 63.08-30.75 26.11 0 44.63 8.23 53.26 15.94 5.31 4.6 9.1 9.84 11.89 16.46 5.84 12.36 6.32 20.63 6.32 29.4v86.43c0 8.07.78 14.97 2.31 20.5l1.76 6.35h-38.91l-.7-4.19c-.5-2.96-.67-19.75-.88-26.23-8.99 23.61-28.27 33.18-52.21 33.18zm50.53-93.72c-7.97 6.11-20.47 9.6-38.62 13.23-31.27 5.78-36.54 13.06-36.54 27.22 0 12.5 10.63 20.26 27.75 20.26 33.23 0 47.41-15.48 47.41-51.77v-8.94zm124.2-105.51C688.46 64.19 660 35.73 660 .62c0 35.11-28.46 63.57-63.57 63.57h0c35.11 0 63.57 28.46 63.57 63.57h0c0-35.11 28.46-63.57 63.57-63.57z" />
|
||||
</svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 724 264">
|
||||
<path
|
||||
d="M38.53 260.65H.43V27.86h38.1zm86.46 2.77c-42.25 0-66.48-22.96-66.48-63V89.33h38.1v108.28c0 23.61 8.7 32.39 32.12 32.39 30.35 0 42.73-14.54 42.73-50.17v-90.5h38.1v171.33h-36.54v-29.91c-4.99 22.98-27.12 32.67-48.03 32.67zm347.2-2.77H434.4V149.87c0-22.5-7.01-30.87-25.88-30.87-24.28 0-37.11 14.45-37.11 41.79v99.86h-37.79V149.87c0-21.93-7.23-30.87-24.94-30.87-31.59 0-38.05 32.96-38.05 41.79v99.86h-38.1V89.33h36.54v29.96c6.49-21.02 27.02-33.71 47.72-33.71 20.69 0 38.09 7.9 45.64 33.71 10.13-26.76 28.35-33.71 50.15-33.71 37.88 0 59.61 18.88 59.61 51.81v123.26h0zm76.65 2.77c-52.62 0-61.55-33.45-61.55-50.52 0-20.1 8.83-38.21 27.93-45.55 8.41-3.11 16.52-5.43 24.84-7.1 7.33-1.47 18.64-3.03 26.91-4.17l2.73-.38c14.38-2 29.67-9.21 29.67-18.62 0-16-20.51-18.39-32.74-18.39-13.87 0-23.64 3.57-27.53 10.05-3.49 6.46-3.73 7.97-4.62 13.6l-.62 4.43h-38.1l.68-5.61c1.35-11.14 3.41-19.03 6.48-24.83 10.54-20.39 31.77-30.75 63.08-30.75 26.11 0 44.63 8.23 53.26 15.94 5.31 4.6 9.1 9.84 11.89 16.46 5.84 12.36 6.32 20.63 6.32 29.4v86.43c0 8.07.78 14.97 2.31 20.5l1.76 6.35h-38.91l-.7-4.19c-.5-2.96-.67-19.75-.88-26.23-8.99 23.61-28.27 33.18-52.21 33.18zm50.53-93.72c-7.97 6.11-20.47 9.6-38.62 13.23-31.27 5.78-36.54 13.06-36.54 27.22 0 12.5 10.63 20.26 27.75 20.26 33.23 0 47.41-15.48 47.41-51.77v-8.94zm124.2-105.51C688.46 64.19 660 35.73 660 .62c0 35.11-28.46 63.57-63.57 63.57h0c35.11 0 63.57 28.46 63.57 63.57h0c0-35.11 28.46-63.57 63.57-63.57z"
|
||||
fill="#ffffff" style="mix-blend-mode: difference;" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
24
auth/assets/custom-icons/icons/mbin.svg
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="320" height="320" viewBox="0 0 320 320" version="1.1" id="svg1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs id="defs1">
|
||||
<linearGradient xlink:href="#linearGradient8" id="linearGradient9" x1="105.88936" y1="-7.966506" x2="153.52075" y2="74.533493" gradientUnits="userSpaceOnUse"/>
|
||||
<linearGradient id="linearGradient8">
|
||||
<stop style="stop-color:#2de2e6;stop-opacity:1;" offset="0" id="stop8"/>
|
||||
<stop style="stop-color:#3399ff;stop-opacity:1;" offset="1" id="stop11"/>
|
||||
</linearGradient>
|
||||
<linearGradient xlink:href="#linearGradient6" id="linearGradient7" x1="97.229103" y1="82.033493" x2="97.229103" y2="107.03349" gradientUnits="userSpaceOnUse"/>
|
||||
<linearGradient id="linearGradient6">
|
||||
<stop style="stop-color:#f623ac;stop-opacity:1;" offset="0" id="stop6"/>
|
||||
<stop style="stop-color:#f706cf;stop-opacity:1;" offset="1" id="stop7"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect style="display:inline;opacity:1;fill:#29144a;fill-opacity:0;stroke:none;stroke-width:4.39823;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1" id="rect35" width="323.65826" height="325.41187" x="0" y="-2.7059329"/>
|
||||
<g id="g1" transform="matrix(0.97092512,0,0,0.95099897,34.423647,35.890832)">
|
||||
<g id="layer1" style="display:inline;fill:none" transform="matrix(2.12871,0,0,2.0000001,-90.126008,15.218211)">
|
||||
<path style="display:inline;opacity:1;fill:url(#linearGradient9);fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1" d="M 92.898977,-25.466506 23.616945,94.53349 a 4.9999999,4.9999999 60 0 0 4.330127,7.5 H 166.51114 a 4.9999996,4.9999996 120 0 0 4.33012,-7.499999 L 101.55923,-25.466506 a 5.0000002,5.0000002 180 0 0 -8.660253,0 z" id="path5" transform="translate(5.8501312,19.942587)"/>
|
||||
<path id="path1" style="display:inline;opacity:1;fill:#241734;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1" d="M 103.61607,27.033498 60.315284,102.0335 H 77.635596 L 90.625831,79.533498 103.61607,102.0335 116.60825,79.533498 129.59849,102.0335 h 17.32031 z m 0,15 10.82666,18.74973 a 7.4997612,7.4997612 90 0 1 0,7.50054 l -10.82666,18.74973 -10.824962,-18.74959 a 7.5008819,7.5008819 90 0 1 0,-7.50082 z" transform="translate(-0.5188027,0.07359983)"/>
|
||||
<path style="display:inline;opacity:1;fill:url(#linearGradient7);fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1" d="M 27.947072,102.03349 H 166.51114 a 5.0000006,5.0000006 120 0 0 4.33012,-7.5 l -7.21687,-12.499996 h -40.41452 l -12.99038,-22.5 -12.990386,22.5 -12.990381,-22.5 -12.990381,22.5 H 30.833821 L 23.616945,94.53349 a 5,5 60 0 0 4.330127,7.5 z" id="path6" transform="matrix(1.0011548,0,0,1.0030727,5.7535451,19.687436)"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
1
auth/assets/custom-icons/icons/postmarkapp.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><path id="A" d="M128 117v6a5 5 0 0 0-5 5h-6a5 5 0 1 0-10 0h-6a5 5 0 1 0-10 0h-6a5 5 0 1 0-10 0h-6a5 5 0 1 0-10 0h-6a5 5 0 1 0-10 0h-6a5 5 0 1 0-10 0h-6a5 5 0 1 0-10 0H5a5 5 0 0 0-5-5v-6a5 5 0 1 0 0-10v-6a5 5 0 0 0 0-10v-6a5 5 0 0 0 0-10v-6a5 5 0 0 0 0-10v-6a5 5 0 0 0 0-10v-6a5 5 0 0 0 0-10v-6a5 5 0 0 0 0-10V5a5 5 0 0 0 5-5h6a5 5 0 0 0 10 0h6a5 5 0 0 0 10 0h6a5 5 0 0 0 10 0h6a5 5 0 0 0 10 0h6a5 5 0 0 0 10 0h6a5 5 0 0 0 10 0h6a5 5 0 1 0 10 0h6a5 5 0 0 0 5 5v6a5 5 0 1 0 0 10v6a5 5 0 1 0 0 10v6a5 5 0 1 0 0 10v6a5 5 0 1 0 0 10v6a5 5 0 1 0 0 10v6a5 5 0 1 0 0 10v6a5 5 0 1 0 0 10z"/><rect id="B" width="96" height="96" x="16" y="16" rx="2"/></defs><g transform="matrix(.492308 0 0 .492308 .492308 .492308)" fill="none" fill-rule="evenodd"><use xlink:href="#A" fill="#f0f0f0"/><path d="M128.5 116.5v7h-.5a4.5 4.5 0 0 0-4.5 4.5v.5h-7v-.5a4.5 4.5 0 0 0-9 0v.5h-7v-.5a4.5 4.5 0 0 0-9 0v.5h-7v-.5a4.5 4.5 0 0 0-9 0v.5h-7v-.5a4.5 4.5 0 0 0-9 0v.5h-7v-.5a4.5 4.5 0 0 0-9 0v.5h-7v-.5a4.5 4.5 0 0 0-9 0v.5h-7v-.5a4.5 4.5 0 0 0-9 0v.5h-7v-.5a4.5 4.5 0 0 0-4.5-4.5h-.5v-7H0a4.5 4.5 0 0 0 0-9h-.5v-7H0a4.5 4.5 0 1 0 0-9h-.5v-7H0a4.5 4.5 0 1 0 0-9h-.5v-7H0a4.5 4.5 0 1 0 0-9h-.5v-7H0a4.5 4.5 0 1 0 0-9h-.5v-7H0a4.5 4.5 0 1 0 0-9h-.5v-7H0a4.5 4.5 0 1 0 0-9h-.5v-7H0A4.5 4.5 0 0 0 4.5 0v-.5h7V0a4.5 4.5 0 1 0 9 0v-.5h7V0a4.5 4.5 0 1 0 9 0v-.5h7V0a4.5 4.5 0 1 0 9 0v-.5h7V0a4.5 4.5 0 1 0 9 0v-.5h7V0a4.5 4.5 0 1 0 9 0v-.5h7V0a4.5 4.5 0 1 0 9 0v-.5h7V0a4.5 4.5 0 0 0 9 0v-.5h7V0a4.5 4.5 0 0 0 4.5 4.5h.5v7h-.5a4.5 4.5 0 0 0 0 9h.5v7h-.5a4.5 4.5 0 0 0 0 9h.5v7h-.5a4.5 4.5 0 0 0 0 9h.5v7h-.5a4.5 4.5 0 0 0 0 9h.5v7h-.5a4.5 4.5 0 0 0 0 9h.5v7h-.5a4.5 4.5 0 0 0 0 9h.5v7h-.5a4.5 4.5 0 0 0 0 9z" stroke="#ccc"/><path d="M127.5 117.478a5.5 5.5 0 0 1 0-10.956v-5.044a5.5 5.5 0 0 1 0-10.956v-5.044a5.5 5.5 0 0 1 0-10.956v-5.044a5.5 5.5 0 0 1 0-10.956v-5.044a5.5 5.5 0 0 1 0-10.956v-5.044a5.5 5.5 0 0 1 0-10.956v-5.044a5.5 5.5 0 0 1 0-10.956V5.478A5.502 5.502 0 0 1 122.522.5h-5.044a5.5 5.5 0 0 1-10.956 0h-5.044a5.5 5.5 0 0 1-10.956 0h-5.044a5.5 5.5 0 0 1-10.956 0h-5.044a5.5 5.5 0 0 1-10.956 0h-5.044a5.5 5.5 0 0 1-10.956 0h-5.044a5.5 5.5 0 0 1-10.956 0h-5.044a5.5 5.5 0 0 1-10.956 0H5.478A5.502 5.502 0 0 1 .5 5.478v5.044a5.5 5.5 0 0 1 0 10.956v5.044a5.5 5.5 0 0 1 0 10.956v5.044a5.5 5.5 0 0 1 0 10.956v5.044a5.5 5.5 0 0 1 0 10.956v5.044a5.5 5.5 0 0 1 0 10.956v5.044a5.5 5.5 0 0 1 0 10.956v5.044a5.5 5.5 0 0 1 0 10.956v5.044a5.502 5.502 0 0 1 4.978 4.978h5.044a5.5 5.5 0 0 1 10.956 0h5.044a5.5 5.5 0 0 1 10.956 0h5.044a5.5 5.5 0 0 1 10.956 0h5.044a5.5 5.5 0 0 1 10.956 0h5.044a5.5 5.5 0 0 1 10.956 0h5.044a5.5 5.5 0 0 1 10.956 0h5.044a5.5 5.5 0 0 1 10.956 0h5.044a5.502 5.502 0 0 1 4.978-4.978z" stroke="#fff"/><use xlink:href="#B" fill="#fedd00"/><rect width="95" height="95" x="16.5" y="16.5" rx="2" stroke="#d9b500"/><rect width="97" height="97" x="15.5" y="15.5" rx="2" stroke="#fff"/><path d="M50.3 86.084V42.3H43V35h25.886c16.168 0 19.522 10.664 19.522 18.06 0 5.934-2.408 10.492-4.902 12.986-4.042 4.042-9.546 4.988-17.888 4.988h-6.536v15.05h7.654v7.3H43v-7.3zm8.772-22.102h7.3c10.75 0 13.072-4.988 13.072-11.008 0-6.88-3.87-10.664-10.32-10.664H59.082z" fill="#000"/></g></svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
1
auth/assets/custom-icons/icons/redotpay.svg
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
auth/assets/generation-icons/icon-monochrome.png
Normal file
|
After Width: | Height: | Size: 489 KiB |
@@ -66,14 +66,14 @@ class Configuration {
|
||||
|
||||
String? _volatilePassword;
|
||||
|
||||
final _secureStorageOptionsIOS = const IOSOptions(
|
||||
accessibility: KeychainAccessibility.first_unlock_this_device,
|
||||
);
|
||||
|
||||
Future<void> init() async {
|
||||
_preferences = await SharedPreferences.getInstance();
|
||||
sqfliteFfiInit();
|
||||
_secureStorage = const FlutterSecureStorage();
|
||||
_secureStorage = const FlutterSecureStorage(
|
||||
iOptions: IOSOptions(
|
||||
accessibility: KeychainAccessibility.first_unlock_this_device,
|
||||
),
|
||||
);
|
||||
_tempDirectory = (await DirectoryUtils.getDirectoryForInit()).path;
|
||||
final tempDirectory = io.Directory(_tempDirectory);
|
||||
try {
|
||||
@@ -98,7 +98,6 @@ class Configuration {
|
||||
Future<void> _initOfflineAccount() async {
|
||||
_offlineAuthKey = await _secureStorage.read(
|
||||
key: offlineAuthSecretKey,
|
||||
iOptions: _secureStorageOptionsIOS,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -108,22 +107,18 @@ class Configuration {
|
||||
unawaited(
|
||||
_secureStorage.delete(
|
||||
key: key,
|
||||
iOptions: _secureStorageOptionsIOS,
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
_key = await _secureStorage.read(
|
||||
key: keyKey,
|
||||
iOptions: _secureStorageOptionsIOS,
|
||||
);
|
||||
_secretKey = await _secureStorage.read(
|
||||
key: secretKeyKey,
|
||||
iOptions: _secureStorageOptionsIOS,
|
||||
);
|
||||
_authSecretKey = await _secureStorage.read(
|
||||
key: authSecretKeyKey,
|
||||
iOptions: _secureStorageOptionsIOS,
|
||||
);
|
||||
if (_key == null) {
|
||||
await logout(autoLogout: true);
|
||||
@@ -136,7 +131,6 @@ class Configuration {
|
||||
for (String key in onlineSecureKeys) {
|
||||
await _secureStorage.delete(
|
||||
key: key,
|
||||
iOptions: _secureStorageOptionsIOS,
|
||||
);
|
||||
}
|
||||
await LockScreenSettings.instance.removePinAndPassword();
|
||||
@@ -396,7 +390,6 @@ class Configuration {
|
||||
await _secureStorage.write(
|
||||
key: keyKey,
|
||||
value: key,
|
||||
iOptions: _secureStorageOptionsIOS,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -405,7 +398,6 @@ class Configuration {
|
||||
await _secureStorage.write(
|
||||
key: secretKeyKey,
|
||||
value: secretKey,
|
||||
iOptions: _secureStorageOptionsIOS,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -414,7 +406,6 @@ class Configuration {
|
||||
await _secureStorage.write(
|
||||
key: authSecretKeyKey,
|
||||
value: authSecretKey,
|
||||
iOptions: _secureStorageOptionsIOS,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -463,18 +454,15 @@ class Configuration {
|
||||
Future<void> optForOfflineMode() async {
|
||||
if ((await _secureStorage.containsKey(
|
||||
key: offlineAuthSecretKey,
|
||||
iOptions: _secureStorageOptionsIOS,
|
||||
))) {
|
||||
_offlineAuthKey = await _secureStorage.read(
|
||||
key: offlineAuthSecretKey,
|
||||
iOptions: _secureStorageOptionsIOS,
|
||||
);
|
||||
} else {
|
||||
_offlineAuthKey = CryptoUtil.bin2base64(CryptoUtil.generateKey());
|
||||
await _secureStorage.write(
|
||||
key: offlineAuthSecretKey,
|
||||
value: _offlineAuthKey,
|
||||
iOptions: _secureStorageOptionsIOS,
|
||||
);
|
||||
}
|
||||
await _preferences.setBool(hasOptedForOfflineModeKey, true);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"account": "الحساب",
|
||||
"unlock": "فتح القفل",
|
||||
"unlock": "فتح القُفْل",
|
||||
"recoveryKey": "مفتاح الاسترداد",
|
||||
"counterAppBarTitle": "العداد",
|
||||
"@counterAppBarTitle": {
|
||||
@@ -16,7 +16,7 @@
|
||||
"secretCanNotBeEmpty": "لا يمكن أن يكون رمز السر فارغ",
|
||||
"bothIssuerAndAccountCanNotBeEmpty": "لا يمكن أن يكون المُصدر والحساب فارغًا",
|
||||
"incorrectDetails": "بيانات غير صحيحة",
|
||||
"pleaseVerifyDetails": "من فضلك تأكد من بياناتك وحاول مرة أخرى",
|
||||
"pleaseVerifyDetails": "الرجاء التأكد من البيانات وإعادة المحاولة",
|
||||
"codeIssuerHint": "المصدِّر",
|
||||
"codeSecretKeyHint": "الرمز السري",
|
||||
"secret": "سري",
|
||||
@@ -36,7 +36,7 @@
|
||||
"codeAccountHint": "الحساب (you@domain.com)",
|
||||
"codeTagHint": "وسم",
|
||||
"accountKeyType": "نوع المفتاح",
|
||||
"sessionExpired": "انتهت صلاحية الجلسة",
|
||||
"sessionExpired": "انتهت صَلاحِيَة الجِلسة",
|
||||
"@sessionExpired": {
|
||||
"description": "Title of the dialog when the users current session is invalid/expired"
|
||||
},
|
||||
@@ -48,6 +48,8 @@
|
||||
"nextTotpTitle": "التالي",
|
||||
"deleteCodeTitle": "حذف الرمز؟",
|
||||
"deleteCodeMessage": "هل أنت متأكد من أنك تريد حذف هذه الشيفرة؟ هذا الإجراء لا رجعة فيه.",
|
||||
"trashCode": "حذف الكود؟",
|
||||
"trashCodeMessage": "هل أنت متيقِّن أنك تريد حذف الكود الخاص بـ {account}؟",
|
||||
"trash": "سلة المهملات",
|
||||
"viewLogsAction": "عرض السجلات",
|
||||
"sendLogsDescription": "سوف يُرسل هذا السجلات لنا لمساعدتنا على تصحيح مشكلتك. بينما نتخذ الاحتياطات لضمان عدم تسجيل المعلومات الحساسة، نشجعك على رؤية هذه السجلات قبل مشاركتها.",
|
||||
@@ -63,7 +65,7 @@
|
||||
},
|
||||
"copyEmailAction": "نسخ البريد الإلكتروني",
|
||||
"exportLogsAction": "تصدير السجلات",
|
||||
"reportABug": "الابلاغ عن خلل تقني",
|
||||
"reportABug": "ألإبلاغ عن خلل تقني",
|
||||
"crashAndErrorReporting": "الإبلاغ عن الأعطال والأخطاء",
|
||||
"reportBug": "الإبلاغ عن خلل",
|
||||
"emailUsMessage": "الرجاء مراسلتنا على {email}",
|
||||
@@ -79,22 +81,24 @@
|
||||
"blog": "المدونة",
|
||||
"merchandise": "إدارة المنتجات",
|
||||
"verifyPassword": "التحقق من كلمة المرور",
|
||||
"pleaseWait": "الرجاء الإنتظار...",
|
||||
"pleaseWait": "انتظر قليلاً...",
|
||||
"generatingEncryptionKeysTitle": "توليد مفاتيح التشفير...",
|
||||
"recreatePassword": "إعادة كتابة كلمة المرور",
|
||||
"recreatePasswordMessage": "الجهاز الحالي ليس قويًا بما يكفي للتحقق من كلمة المرور الخاصة بك، لذا نحتاج إلى إعادة إنشائها مرة واحدة بطريقة تعمل مع جميع الأجهزة.\n\nالرجاء تسجيل الدخول باستخدام مفتاح الاسترداد وإعادة إنشاء كلمة المرور الخاصة بك (يمكنك استخدام نفس كلمة المرور مرة أخرى إذا كنت ترغب في ذلك).",
|
||||
"useRecoveryKey": "استخدم مفتاح الاسترداد",
|
||||
"incorrectPasswordTitle": "كلمة المرور غير صحيحة",
|
||||
"welcomeBack": "مرحبًا مجددًا!",
|
||||
"madeWithLoveAtPrefix": "مصنوعة بـ❤️ في ",
|
||||
"emailAlreadyRegistered": "البريد الإلكتروني مُسَجَّل من قبل.",
|
||||
"emailNotRegistered": "البريد الإلكتروني غير مُسَجَّل.",
|
||||
"madeWithLoveAtPrefix": "مصنوعة بـ❤️ في",
|
||||
"supportDevs": "اشترك في <bold-green>ente</bold-green> لدعمنا",
|
||||
"supportDiscount": "استخدم رمز القسيمة \"AUTH\" للحصول على 10% خصم من السنة الأولى",
|
||||
"supportDiscount": "استخدم رمز القسيمة \"AUTH\" للحصول على 10% خَصْم من السنة الأولى",
|
||||
"changeEmail": "غير البريد الإلكتروني",
|
||||
"changePassword": "غير كلمة المرور",
|
||||
"data": "البيانات",
|
||||
"importCodes": "استورد شيفرات",
|
||||
"importTypePlainText": "نص بسيط",
|
||||
"importTypeEnteEncrypted": "تصدير مشفر ente",
|
||||
"importTypeEnteEncrypted": "تصدير مشفَّر ente",
|
||||
"passwordForDecryptingExport": "كلمة المرور لفك تشفير التصدير",
|
||||
"passwordEmptyError": "لا يمكن أن تكون كلمة المرور فارغة",
|
||||
"importFromApp": "استورد الشيفرات من {appName}",
|
||||
@@ -111,10 +115,11 @@
|
||||
"importLabel": "استيراد",
|
||||
"importInstruction": "الرجاء تحديد ملف يحتوي على قائمة بالرموز الخاصة بك بالشكل التالي",
|
||||
"importCodeDelimiterInfo": "يمكن فصل الرموز بفاصلة أو سطر جديد",
|
||||
"selectFile": "اختيار الملف",
|
||||
"selectFile": "حدد مِلَفّ",
|
||||
"emailVerificationToggle": "تأكيد عنوان البريد الإلكتروني",
|
||||
"emailVerificationEnableWarning": "لتجنب إقفال حسابك، تأكد من تخزين نسخة من بريدك الإلكتروني 2FA خارج Ente Auth قبل تمكين التحقق من البريد الإلكتروني.",
|
||||
"authToChangeEmailVerificationSetting": "الرجاء المصادقة لتغيير التحقق من البريد الإلكتروني",
|
||||
"authenticateGeneric": "الرجاء المصادقة",
|
||||
"authToViewYourRecoveryKey": "الرجاء المصادقة لعرض مفتاح الاسترداد الخاص بك",
|
||||
"authToChangeYourEmail": "الرجاء المصادقة لتغيير بريدك الإلكتروني",
|
||||
"authToChangeYourPassword": "الرجاء المصادقة لتغيير كلمة المرور الخاصة بك",
|
||||
@@ -129,7 +134,7 @@
|
||||
"general": "العامة",
|
||||
"settings": "الإعدادات",
|
||||
"copied": "تم النسخ",
|
||||
"pleaseTryAgain": "حاول مرة اخرى",
|
||||
"pleaseTryAgain": "يرجى المحاولة مرة أخرى",
|
||||
"existingUser": "المستخدم موجود",
|
||||
"newUser": "جديد في Ente",
|
||||
"delete": "حذف",
|
||||
@@ -142,6 +147,8 @@
|
||||
"leaveFamily": "مغادرة خطة العائلة",
|
||||
"leaveFamilyMessage": "هل أنت متأكد من الخروج من خطة العائلة؟",
|
||||
"inFamilyPlanMessage": "أنت مندرج ضمن خطة عائلية!",
|
||||
"hintForMobile": "اضغط مطولاً على الكود لتعديل أو إزالته.",
|
||||
"hintForDesktop": "انقر بزر الأيمن على الكود لتعديله.",
|
||||
"scan": "مسح",
|
||||
"scanACode": "فحص رمز Qr",
|
||||
"verify": "التحقق",
|
||||
@@ -151,6 +158,7 @@
|
||||
"twoFactorAuthTitle": "المصادقة الثنائية",
|
||||
"passkeyAuthTitle": "التحقق من مفتاح المرور",
|
||||
"verifyPasskey": "تحقق من مفتاح المرور",
|
||||
"loginWithTOTP": "",
|
||||
"recoverAccount": "إسترجاع الحساب",
|
||||
"enterRecoveryKeyHint": "أدخل رمز الاسترداد",
|
||||
"recover": "استرداد",
|
||||
@@ -172,7 +180,7 @@
|
||||
"yesSendFeedbackAction": "نعم، ارسل الملاحظات",
|
||||
"noDeleteAccountAction": "لا، حذف الحساب",
|
||||
"initiateAccountDeleteTitle": "الرجاء المصادقة لبدء حذف الحساب",
|
||||
"sendEmail": "ارسل بريد الكتروني",
|
||||
"sendEmail": "إرسال بريد إلكتروني",
|
||||
"createNewAccount": "إنشاء حساب جديد",
|
||||
"weakStrength": "ضعيف",
|
||||
"strongStrength": "قوي",
|
||||
@@ -184,9 +192,9 @@
|
||||
"language": "اللغة",
|
||||
"social": "وسائل التواصل",
|
||||
"security": "الأمان",
|
||||
"lockscreen": "شاشة القفل",
|
||||
"authToChangeLockscreenSetting": "الرجاء المصادقة لتغيير إعدادات شاشة القفل",
|
||||
"deviceLockEnablePreSteps": "لتمكين قفل التطبيق، فضلا أعد شيفرة مرور للجهاز أو قفل الشاشة في إعدادات نظامك.",
|
||||
"lockscreen": "شاشة القُفْل",
|
||||
"authToChangeLockscreenSetting": "الرجاء المصادقة لتغيير إعدادات شاشة القُفْل",
|
||||
"deviceLockEnablePreSteps": "لتفعيل قُفْل الجهاز، اضبط رمز مرور أو قُفْل الشاشة من الإعدادات",
|
||||
"viewActiveSessions": "عرض الجلسات النشطة",
|
||||
"authToViewYourActiveSessions": "الرجاء المصادقة لعرض جلساتك النشطة",
|
||||
"searchHint": "بحث...",
|
||||
@@ -199,6 +207,7 @@
|
||||
"edit": "تعديل",
|
||||
"share": "مشاركة",
|
||||
"shareCodes": "شارك الرموز",
|
||||
"shareCodesDuration": "حدد المدة التي تريد أن تشارك فيها ألاكوا د.",
|
||||
"restore": "استعادة",
|
||||
"copiedToClipboard": "تم النسخ إلى الحافظة",
|
||||
"copiedNextToClipboard": "تم نسخ الرموز التالية إلى الحافظة",
|
||||
@@ -326,6 +335,7 @@
|
||||
}
|
||||
},
|
||||
"manualSort": "مخصّص",
|
||||
"editOrder": "تعديل الطلب",
|
||||
"mostFrequentlyUsed": "مستخدم بكثرة",
|
||||
"mostRecentlyUsed": "مستخدمة مؤخراً",
|
||||
"activeSessions": "الجلسات النشطة",
|
||||
@@ -447,6 +457,9 @@
|
||||
"customEndpoint": "متصل بـ{endpoint}",
|
||||
"pinText": "ثبت",
|
||||
"unpinText": "ألغِ التثبيت",
|
||||
"pinnedCodeMessage": "ثُبِّت {code}",
|
||||
"unpinnedCodeMessage": "أُلغِي تثبيت {code}",
|
||||
"pinned": "ثُبِّت",
|
||||
"tags": "الأوسمة",
|
||||
"createNewTag": "أنشيء وسم جديد",
|
||||
"tag": "وسم",
|
||||
@@ -459,9 +472,9 @@
|
||||
"viewRawCodes": "عرض الشيفرات الأصلية",
|
||||
"rawCodes": "الشيفرات الأصلية",
|
||||
"rawCodeData": "بيانات الشيفرات الأصلية",
|
||||
"appLock": "قفل التطبيق",
|
||||
"appLock": "قُفْل التطبيق",
|
||||
"noSystemLockFound": "لا يوجد قفل نظام",
|
||||
"toEnableAppLockPleaseSetupDevicePasscodeOrScreen": "لتمكين قفل التطبيق، فضلا أعد شيفرة مرور الجهاز أو قفل الشاشة في إعدادات نظامك.",
|
||||
"toEnableAppLockPleaseSetupDevicePasscodeOrScreen": "لتفعيل قُفْل التطبيق، اضبط رمز مرور الجهاز أو قُفْل الشاشة من الإعدادات.",
|
||||
"autoLock": "قفل تلقائي",
|
||||
"immediately": "فورًا",
|
||||
"reEnterPassword": "أعد إدخال كلمة المرور",
|
||||
@@ -475,14 +488,30 @@
|
||||
"hideContentDescriptionAndroid": "يخفي محتوى التطبيق في مبدل التطبيقات ويمنع لقطات الشاشة",
|
||||
"hideContentDescriptioniOS": "يخفي محتوى التطبيق في مبدل التطبيقات",
|
||||
"autoLockFeatureDescription": "الوقت الذي بعده ينقفل التطبيق بعدما يوضع في الخلفية",
|
||||
"appLockDescription": "اختر بين شاشة القفل الافتراضية الخاصة بجهازك وشاشة قفل مخصصة برقم تعريف شخصي أو كلمة مرور.",
|
||||
"appLockDescription": "اختر نوع قُفْل الشاشة: افتراضي أو مخصص.",
|
||||
"pinLock": "قفل رقم التعريف الشخصي",
|
||||
"enterPin": "أدخل رقم التعريف الشخصي",
|
||||
"setNewPin": "عين رقم تعريف شخصي جديد",
|
||||
"importFailureDescNew": "تعذر إعراب الملف المنتقى.",
|
||||
"appLockNotEnabled": "قُفْل التطبيق غير مفعل ",
|
||||
"appLockNotEnabledDescription": "لحماية بياناتك، فعِّل قُفْل التطبيق من إعدادات الأمان ← قُفْل التطبيق",
|
||||
"authToViewPasskey": "الرجاء المصادقة لعرض مفتاح الاسترداد الخاص بك",
|
||||
"appLockOfflineModeWarning": "لقد اخترتَ المُتابعة دون نُسخ احتياطية. إذا نَسيتَ قُفْل التطبيق، فلن تتمكن من الوصول إلى بياناتك.",
|
||||
"duplicateCodes": "رموز مكررة",
|
||||
"noDuplicates": "✨ لا تكرارات",
|
||||
"youveNoDuplicateCodesThatCanBeCleared": "لا توجد لديك أي أكواد مكررة يمكن حذفها",
|
||||
"deduplicateCodes": "أكواد مكررة",
|
||||
"deselectAll": "ألغِ تحديد الكل",
|
||||
"selectAll": "حدد الكل",
|
||||
"deleteDuplicates": "احذف التكرار"
|
||||
"deleteDuplicates": "احذف التكرار",
|
||||
"plainHTML": "HTML عَادِي ",
|
||||
"tellUsWhatYouThink": "شاركنا برأيك",
|
||||
"dropReviewiOS": "اترك مراجعة على أبل ستور",
|
||||
"dropReviewAndroid": "اترك مراجعة بلاي ستور",
|
||||
"supportEnte": "دعم <bold-green>ente</bold-green></bold-green>",
|
||||
"giveUsAStarOnGithub": "من فضلك أعطِنا نجمة على جيت هاب",
|
||||
"free5GB": "5GB مجانًا على <bold-green>ente</bold-green> صور",
|
||||
"loginWithAuthAccount": "سجّل الدخول باستخدام حساب المُصادقة",
|
||||
"freeStorageOffer": "خَصْم 10٪ على صور <bold-green>ente</bold-green>",
|
||||
"freeStorageOfferDescription": "استخدم الكود \"AUTH\" وأحصل على 10٪ خَصْم في السنة الأولى"
|
||||
}
|
||||
@@ -504,6 +504,7 @@
|
||||
"deleteDuplicates": "Duplikate löschen",
|
||||
"plainHTML": "Reines HTML",
|
||||
"tellUsWhatYouThink": "Sagen Sie uns, was Sie denken",
|
||||
"dropReviewiOS": "Hinterlasse eine Rezension im App Store",
|
||||
"dropReviewAndroid": "Hinterlasse eine Rezension im Google Play Store",
|
||||
"supportEnte": "Support <bold-green>ente</bold-green>",
|
||||
"giveUsAStarOnGithub": "Gib uns einen Stern auf Github",
|
||||
|
||||
@@ -506,6 +506,8 @@
|
||||
"deleteDuplicates": "Eliminar duplicados",
|
||||
"plainHTML": "HTML plano",
|
||||
"tellUsWhatYouThink": "Cuéntanos cuál es su opinión",
|
||||
"dropReviewiOS": "Deja una reseña en la App Store",
|
||||
"dropReviewAndroid": "Deja una reseña en la Play Store",
|
||||
"supportEnte": "Apoya a <bold-green>ente</bold-green>",
|
||||
"giveUsAStarOnGithub": "Danos una estrella en GitHub",
|
||||
"free5GB": "5 GB gratis en <bold-green>ente</bold-green> Fotos",
|
||||
|
||||
@@ -499,12 +499,15 @@
|
||||
"appLockOfflineModeWarning": "Vous avez choisi de fonctionner sans sauvegardes. Si vous oubliez votre outil Applock, vous serez bloqué dans l'accès à vos données.",
|
||||
"duplicateCodes": "Codes dupliqués",
|
||||
"noDuplicates": "✨ Pas de doublons",
|
||||
"youveNoDuplicateCodesThatCanBeCleared": "Vous n'avez aucun code en doublon pouvant être supprimé",
|
||||
"deduplicateCodes": "Codes dédupliqués",
|
||||
"deselectAll": "Tout désélectionner",
|
||||
"selectAll": "Tout sélectionner",
|
||||
"deleteDuplicates": "Supprimer les doublons",
|
||||
"plainHTML": "HTML Pur",
|
||||
"tellUsWhatYouThink": "Dites-nous ce que vous pensez",
|
||||
"dropReviewiOS": "Laisser un avis sur l'App Store",
|
||||
"dropReviewAndroid": "Laisser un avis sur le Play Store",
|
||||
"supportEnte": "Soutenir <bold-green>Ente</bold-green>",
|
||||
"giveUsAStarOnGithub": "Donnez-nous une étoile sur Github",
|
||||
"free5GB": "5 Go gratuits sur <bold-green>Ente</bold-green> Photos",
|
||||
|
||||
@@ -506,6 +506,8 @@
|
||||
"deleteDuplicates": "Ištrinti dublikatus",
|
||||
"plainHTML": "Grynasis HTML",
|
||||
"tellUsWhatYouThink": "Pasakykite mums, ką manote",
|
||||
"dropReviewiOS": "Rašyti apžvalgą parduotuvėje „App Store“",
|
||||
"dropReviewAndroid": "Rašyti apžvalgą parduotuvėje „Play“ parduotuvė“",
|
||||
"giveUsAStarOnGithub": "Suteikite mums žvaigždutę platformoje „Github“",
|
||||
"free5GB": "5 GB nemokami programai „<bold-green>ente</bold-green>“ nuotraukos",
|
||||
"loginWithAuthAccount": "Prisijungti su jūsų „Auth“ paskyra",
|
||||
|
||||
@@ -506,6 +506,8 @@
|
||||
"deleteDuplicates": "Dubbelen verwijderen",
|
||||
"plainHTML": "Alleen HTML",
|
||||
"tellUsWhatYouThink": "Vertel ons wat je vindt",
|
||||
"dropReviewiOS": "Laat een beoordeling achter in de App Store",
|
||||
"dropReviewAndroid": "Laat een beoordeling achter in de Play Store",
|
||||
"supportEnte": "Steun <bold-green>ente</bold-green>",
|
||||
"giveUsAStarOnGithub": "Geef ons een ster op Github",
|
||||
"free5GB": "5GB gratis op <bold-green>ente</bold-green> Photos",
|
||||
|
||||
1
auth/lib/l10n/arb/app_or.arb
Normal file
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -83,22 +83,22 @@
|
||||
"verifyPassword": "Подтверждение пароля",
|
||||
"pleaseWait": "Пожалуйста, подождите...",
|
||||
"generatingEncryptionKeysTitle": "Генерируем ключи шифрования...",
|
||||
"recreatePassword": "Воссоздать пароль заново",
|
||||
"recreatePassword": "Повторное создание пароля",
|
||||
"recreatePasswordMessage": "Текущее устройство недостаточно мощное для проверки пароля, поэтому нам нужно регенерировать его один раз таким образом, чтобы работать со всеми устройствами. \n\nПожалуйста, войдите, используя ваш ключ восстановления и сгенерируйте ваш пароль (вы можете использовать тот же самый, если пожелаете).",
|
||||
"useRecoveryKey": "Использовать ключ восстановления",
|
||||
"incorrectPasswordTitle": "Неправильный пароль",
|
||||
"welcomeBack": "С возвращением!",
|
||||
"emailAlreadyRegistered": "Адрес электронной почты уже зарегистрирован.",
|
||||
"emailNotRegistered": "Адрес электронной почты не зарегистрирован.",
|
||||
"madeWithLoveAtPrefix": "сделана с ❤️ в ",
|
||||
"madeWithLoveAtPrefix": "сделано с ❤️ в ",
|
||||
"supportDevs": "Подпишитесь на <bold-green>ente</bold-green> для поддержки нашего проекта",
|
||||
"supportDiscount": "Используйте код скидки \"AUTH\", чтобы получить скидку 10% на первый год",
|
||||
"changeEmail": "Изменить почту",
|
||||
"supportDiscount": "Используйте кодовое слово \"AUTH\", чтобы получить скидку 10% на первый год",
|
||||
"changeEmail": "Изменить адрес электронной почты",
|
||||
"changePassword": "Изменить пароль",
|
||||
"data": "Данные",
|
||||
"importCodes": "Импортировать коды",
|
||||
"importTypePlainText": "Обычный текст",
|
||||
"importTypeEnteEncrypted": "Ente Зашифрованный экспорт",
|
||||
"importTypeEnteEncrypted": "Зашифрованный экспорт из Ente",
|
||||
"passwordForDecryptingExport": "Пароль для расшифровки экспорта",
|
||||
"passwordEmptyError": "Пароль не может быть пустым",
|
||||
"importFromApp": "Импорт кодов из {appName}",
|
||||
@@ -106,27 +106,27 @@
|
||||
"importSelectJsonFile": "Выбрать JSON-файл",
|
||||
"importSelectAppExport": "Выбрать файл экспорта {appName}",
|
||||
"importEnteEncGuide": "Выберите зашифрованный JSON файл, экспортированный из Ente",
|
||||
"importRaivoGuide": "Используйте опцию «Export OTPs to Zip archive» в настройках Raivo.\n\nРаспакуйте zip-архив и импортируйте JSON-файл.",
|
||||
"importBitwardenGuide": "Используйте опцию \"Экспортировать хранилище\" в Bitwarden Tools и импортируйте незашифрованный JSON файл.",
|
||||
"importRaivoGuide": "Используйте опцию «Экспорт OTP-кодов в Zip-архив» в настройках Raivo.\n\nРаспакуйте zip-архив и импортируйте JSON-файл.",
|
||||
"importBitwardenGuide": "Используйте опцию \"Экспортировать хранилище\" в Bitwarden и импортируйте незашифрованный JSON-файл.",
|
||||
"importAegisGuide": "Используйте опцию «Экспортировать хранилище» в настройках Aegis.\n\nЕсли ваше хранилище зашифровано, то для его расшифровки потребуется ввести пароль хранилища.",
|
||||
"import2FasGuide": "Используйте опцию \"Settings->Backup -Export\" в 2FAS.\n\nЕсли ваша резервная копия зашифрована, то для расшифровки резервной копии необходимо ввести пароль",
|
||||
"importLastpassGuide": "Используйте опцию \"Перенести аккаунты\" в настройках Lastpass Authenticator и нажмите на \"Экспортировать учетные записи в файл\". Импортируйте загружённый JSON файл.",
|
||||
"import2FasGuide": "Используйте опцию \"Настройки->Резервное копирование -Экспорт\" в 2FAS.\n\nЕсли ваша резервная копия зашифрована, то для расшифровки резервной копии необходимо ввести пароль",
|
||||
"importLastpassGuide": "Используйте опцию \"Перенести аккаунты\" в настройках Lastpass Authenticator и нажмите на \"Экспортировать учетные записи в файл\". Импортируйте загружённый JSON-файл.",
|
||||
"exportCodes": "Экспортировать коды",
|
||||
"importLabel": "Импорт",
|
||||
"importInstruction": "Пожалуйста, выберите файл, содержащий список ваших кодов в следующем формате",
|
||||
"importCodeDelimiterInfo": "Коды могут быть разделены запятой или новой строкой",
|
||||
"selectFile": "Выбрать файл",
|
||||
"emailVerificationToggle": "Подтверждение электронной почты",
|
||||
"emailVerificationEnableWarning": "Если вы храните у нас двухфакторную аутентификацию в своей электронной почте, включение проверки электронной почты может привести к тупиковой ситуации. Если у вас заблокирован доступ к одной службе, возможно, вы не сможете войти в другую.",
|
||||
"emailVerificationToggle": "Подтверждение адреса электронной почты",
|
||||
"emailVerificationEnableWarning": "Чтобы избежать блокировки вашей учетной записи, обязательно сохраните копию вашего электронного письма 2FA за пределами Ente Auth, прежде чем активировать проверку электронной почты.",
|
||||
"authToChangeEmailVerificationSetting": "Авторизуйтесь, чтобы изменить подтверждение электронной почты",
|
||||
"authenticateGeneric": "Пожалуйста, авторизуйтесь",
|
||||
"authToViewYourRecoveryKey": "Пожалуйста, авторизуйтесь для просмотра вашего ключа восстановления",
|
||||
"authToChangeYourEmail": "Пожалуйста, авторизуйтесь, чтобы изменить адрес электронной почты",
|
||||
"authToChangeYourPassword": "Пожалуйста, авторизуйтесь, чтобы изменить пароль",
|
||||
"authToViewSecrets": "Пожалуйста, авторизуйтесь для просмотра ваших секретов",
|
||||
"authToInitiateSignIn": "Пожалуйста, авторизуйтесь, чтобы начать вход для резервного копирования.",
|
||||
"authToInitiateSignIn": "Пожалуйста, авторизуйтесь, чтобы получить доступ к резервному копированию.",
|
||||
"ok": "Ок",
|
||||
"cancel": "Отменить",
|
||||
"cancel": "Отмена",
|
||||
"yes": "Да",
|
||||
"no": "Нет",
|
||||
"email": "Электронная почта",
|
||||
@@ -136,30 +136,31 @@
|
||||
"copied": "Скопировано",
|
||||
"pleaseTryAgain": "Пожалуйста, попробуйте ещё раз",
|
||||
"existingUser": "Существующий пользователь",
|
||||
"newUser": "Впервые здесь, в Ente",
|
||||
"newUser": "Впервые в Ente",
|
||||
"delete": "Удалить",
|
||||
"enterYourPasswordHint": "Введите пароль",
|
||||
"forgotPassword": "Забыл пароль",
|
||||
"oops": "Ой",
|
||||
"suggestFeatures": "Предложить идеи",
|
||||
"faq": "FAQ",
|
||||
"somethingWentWrongMessage": "Что-то пошло не так. Попробуйте еще раз",
|
||||
"faq": "ЧаВо",
|
||||
"somethingWentWrongMessage": "Что-то пошло не так, пожалуйста, попробуйте еще раз",
|
||||
"leaveFamily": "Покинуть семью",
|
||||
"leaveFamilyMessage": "Вы уверены, что хотите отказаться от семейного плана?",
|
||||
"inFamilyPlanMessage": "Вы на семейном плане!",
|
||||
"hintForMobile": "Длительное нажмите на код для редактирования или удаления.",
|
||||
"hintForDesktop": "Щелкните правой кнопкой мыши по коду, чтобы изменить или удалить.",
|
||||
"hintForMobile": "Нажмите на код и удерживайте, чтобы редактировать его или удалить.",
|
||||
"hintForDesktop": "Щелкните правой кнопкой мыши по коду, чтобы редактировать его или удалить.",
|
||||
"scan": "Сканировать",
|
||||
"scanACode": "Сканировать QR-код",
|
||||
"verify": "Подтвердить",
|
||||
"verifyEmail": "Подтвердить электронную почту",
|
||||
"verifyEmail": "Подтвердить адрес электронной почты",
|
||||
"enterCodeHint": "Введите 6-значный код из\nвашего приложения-аутентификатора",
|
||||
"lostDeviceTitle": "Потеряно устройство?",
|
||||
"twoFactorAuthTitle": "Двухфакторная аутентификация",
|
||||
"passkeyAuthTitle": "Проверка с помощью пароля",
|
||||
"passkeyAuthTitle": "Проверка с помощью ключа доступа",
|
||||
"verifyPasskey": "Подтвердить пароль",
|
||||
"loginWithTOTP": "Войти с помощью TOTP",
|
||||
"recoverAccount": "Восстановить аккаунт",
|
||||
"enterRecoveryKeyHint": "Введите свой ключ восстановления",
|
||||
"enterRecoveryKeyHint": "Введите ключ восстановления",
|
||||
"recover": "Восстановить",
|
||||
"contactSupportViaEmailMessage": "Пожалуйста, отправьте электронное письмо на адрес {email} с вашего зарегистрированного адреса электронной почты",
|
||||
"@contactSupportViaEmailMessage": {
|
||||
@@ -171,7 +172,7 @@
|
||||
},
|
||||
"invalidQRCode": "Неверный QR-код",
|
||||
"noRecoveryKeyTitle": "Нет ключа восстановления?",
|
||||
"enterEmailHint": "Введите свою почту",
|
||||
"enterEmailHint": "Введите адрес электронной почты",
|
||||
"invalidEmailTitle": "Неверный адрес электронной почты",
|
||||
"invalidEmailMessage": "Пожалуйста, введите действительный адрес электронной почты.",
|
||||
"deleteAccount": "Удалить аккаунт",
|
||||
@@ -182,7 +183,7 @@
|
||||
"sendEmail": "Отправить электронное письмо",
|
||||
"createNewAccount": "Создать новый аккаунт",
|
||||
"weakStrength": "Слабый",
|
||||
"strongStrength": "Крепкий",
|
||||
"strongStrength": "Сильный",
|
||||
"moderateStrength": "Средний",
|
||||
"confirmPassword": "Подтвердить пароль",
|
||||
"close": "Закрыть",
|
||||
@@ -333,6 +334,9 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"manualSort": "Ручная",
|
||||
"editOrder": "Изменить порядок",
|
||||
"mostFrequentlyUsed": "Частота использования",
|
||||
"mostRecentlyUsed": "Недавно использованные",
|
||||
"activeSessions": "Активные сеансы",
|
||||
"somethingWentWrongPleaseTryAgain": "Что-то пошло не так. Попробуйте еще раз",
|
||||
@@ -376,7 +380,7 @@
|
||||
"deleteCodeAuthMessage": "Аутентификация для удаления кода",
|
||||
"showQRAuthMessage": "Аутентификация для отображения QR-кода",
|
||||
"confirmAccountDeleteTitle": "Подтвердить удаление аккаунта",
|
||||
"confirmAccountDeleteMessage": "Эта учетная запись связана с другими приложениями Ente, если вы ими пользуетесь.\n\nЗагруженные вами данные во всех приложениях ente будут запланированы к удалению, а ваша учетная запись будет удалена без возможности восстановления.",
|
||||
"confirmAccountDeleteMessage": "Эта учетная запись связана с другими приложениями Ente, если вы ими пользуетесь.\n\nЗагруженные вами данные во всех приложениях Ente будут запланированы к удалению, а ваша учетная запись будет удалена без возможности восстановления.",
|
||||
"androidBiometricHint": "Подтвердите личность",
|
||||
"@androidBiometricHint": {
|
||||
"description": "Hint message advising the user how to authenticate with biometrics. It is used on Android side. Maximum 60 characters."
|
||||
@@ -436,7 +440,7 @@
|
||||
"signOutOtherDevices": "Выйти из других устройств",
|
||||
"doNotSignOut": "Не выходить",
|
||||
"hearUsWhereTitle": "Как вы узнали о Ente? (необязательно)",
|
||||
"hearUsExplanation": "Будет полезно, если вы укажете, где нашли нас, так как мы не отслеживаем установки приложения",
|
||||
"hearUsExplanation": "Мы не отслеживаем установки приложений. Было бы полезно, если бы вы сказали, где нас нашли!",
|
||||
"recoveryKeySaved": "Ключ восстановления сохранён в папке Загрузки!",
|
||||
"waitingForBrowserRequest": "Ожидание запроса браузера...",
|
||||
"waitingForVerification": "Ожидание подтверждения...",
|
||||
@@ -453,6 +457,9 @@
|
||||
"customEndpoint": "Подключено к {endpoint}",
|
||||
"pinText": "Прикрепить",
|
||||
"unpinText": "Открепить",
|
||||
"pinnedCodeMessage": "{code} был закреплен",
|
||||
"unpinnedCodeMessage": "{code} был откреплен",
|
||||
"pinned": "Закреплено",
|
||||
"tags": "Метки",
|
||||
"createNewTag": "Создать новую метку",
|
||||
"tag": "Метка",
|
||||
@@ -462,9 +469,9 @@
|
||||
"deleteTagMessage": "Вы уверены, что хотите удалить эту метку? Это действие необратимо.",
|
||||
"somethingWentWrongParsingCode": "Мы не смогли разобрать коды {x}.",
|
||||
"updateNotAvailable": "Обновление недоступно",
|
||||
"viewRawCodes": "Просмотр сырых кодов",
|
||||
"rawCodes": "Сырые коды",
|
||||
"rawCodeData": "Сырая информация кодов",
|
||||
"viewRawCodes": "Просмотр необработанных кодов",
|
||||
"rawCodes": "Необработанные коды",
|
||||
"rawCodeData": "Необработанные кодовые данные",
|
||||
"appLock": "Блокировка приложения",
|
||||
"noSystemLockFound": "Системная блокировка не найдена",
|
||||
"toEnableAppLockPleaseSetupDevicePasscodeOrScreen": "Чтобы включить блокировку, настройте пароль устройства или блокировку экрана в настройках системы.",
|
||||
@@ -482,20 +489,28 @@
|
||||
"hideContentDescriptioniOS": "Скрывает содержимое приложения в переключателе приложений",
|
||||
"autoLockFeatureDescription": "Время в фоне, после которого приложение блокируется",
|
||||
"appLockDescription": "Выберите между экраном блокировки вашего устройства и пользовательским экраном блокировки с PIN-кодом или паролем.",
|
||||
"pinLock": "Pin Замок",
|
||||
"pinLock": "Pin блокировка",
|
||||
"enterPin": "Введите PIN",
|
||||
"setNewPin": "Установите новый PIN",
|
||||
"importFailureDescNew": "Не удалось обработать выбранный файл.",
|
||||
"appLockNotEnabled": "Блокировка приложения отключена",
|
||||
"appLockNotEnabledDescription": "Пожалуйста, включите блокировку приложения в безопасности > Блокировка приложений",
|
||||
"appLockNotEnabledDescription": "Пожалуйста, включите блокировку приложения в разделе Безопасность > Блокировка приложений",
|
||||
"authToViewPasskey": "Пожалуйста, авторизуйтесь, чтобы просмотреть пароль",
|
||||
"appLockOfflineModeWarning": "Вы решили продолжить работу без резервного копирования. Если вы забудете свой пароль, доступ к вашим данным будет заблокирован.",
|
||||
"duplicateCodes": "Дублировать коды",
|
||||
"noDuplicates": "✨ Дубликатов нет",
|
||||
"youveNoDuplicateCodesThatCanBeCleared": "У вас нет повторяющихся кодов, которые можно было бы удалить",
|
||||
"deduplicateCodes": "Дедупликационные коды",
|
||||
"deselectAll": "Снять выделение",
|
||||
"selectAll": "Выбрать все",
|
||||
"deleteDuplicates": "Удалить повторяющиеся",
|
||||
"plainHTML": "Обычный HTML",
|
||||
"tellUsWhatYouThink": "Расскажите нам, что вы думаете",
|
||||
"free5GB": "5GB бесплатно на <bold-green>ente</bold-green> фото",
|
||||
"dropReviewiOS": "Оставьте отзыв в App Store",
|
||||
"dropReviewAndroid": "Оставьте отзыв в Play Store",
|
||||
"supportEnte": "Поддержка <bold-green>ente</bold-green>",
|
||||
"giveUsAStarOnGithub": "Поставьте нам звезду на Github",
|
||||
"free5GB": "5Гб бесплатного пространства на <bold-green>ente</bold-green> Фото",
|
||||
"loginWithAuthAccount": "Войти с помощью учетной записи Auth",
|
||||
"freeStorageOffer": "Скидка 10% на <bold-green>ente</bold-green> фото",
|
||||
"freeStorageOfferDescription": "Используйте код \"AUTH\", чтобы получить скидку 10% в первый год"
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
{}
|
||||
{
|
||||
"importScanQrCode": ""
|
||||
}
|
||||
@@ -51,7 +51,7 @@
|
||||
"trashCode": "Xóa mã?",
|
||||
"trashCodeMessage": "Bạn có chắc chắn muốn xóa mã cho {account} không?",
|
||||
"trash": "Xóa",
|
||||
"viewLogsAction": "Xem các bản ghi",
|
||||
"viewLogsAction": "Xem nhật ký",
|
||||
"sendLogsDescription": "Thao tác này sẽ gửi nhật ký để giúp chúng tôi gỡ lỗi sự cố của bạn. Mặc dù chúng tôi thực hiện các biện pháp phòng ngừa để đảm bảo rằng thông tin nhạy cảm không được ghi lại, nhưng chúng tôi khuyến khích bạn xem các nhật ký này trước khi chia sẻ chúng.",
|
||||
"preparingLogsTitle": "Đang chuẩn bị nhật ký...",
|
||||
"emailLogsTitle": "Nhật ký email",
|
||||
@@ -506,6 +506,8 @@
|
||||
"deleteDuplicates": "Xóa trùng lặp",
|
||||
"plainHTML": "HTML thuần",
|
||||
"tellUsWhatYouThink": "Hãy cho chúng tôi biết bạn nghĩ gì",
|
||||
"dropReviewiOS": "Đánh giá ngay trên App Store",
|
||||
"dropReviewAndroid": "Đánh giá ngay trên Play Store",
|
||||
"supportEnte": "Hỗ trợ <bold-green>ente</bold-green>",
|
||||
"giveUsAStarOnGithub": "Cho chúng tôi ngôi sao trên Github",
|
||||
"free5GB": "Miễn phí 5GB cho <bold-green>ente</bold-green> Hình ảnh",
|
||||
|
||||
@@ -504,10 +504,10 @@
|
||||
"deselectAll": "取消全选",
|
||||
"selectAll": "全选",
|
||||
"deleteDuplicates": "删除重复项",
|
||||
"plainHTML": "Plain HTML",
|
||||
"plainHTML": "纯 HTML",
|
||||
"tellUsWhatYouThink": "告诉我们您的想法",
|
||||
"dropReviewiOS": "在 App Store 上发表评测",
|
||||
"dropReviewAndroid": "在 Play 商店上发表评测",
|
||||
"dropReviewiOS": "在 App Store 上发表评论",
|
||||
"dropReviewAndroid": "在 Play 商店上发表评价",
|
||||
"supportEnte": "支持 <bold-green>ente</bold-green>",
|
||||
"giveUsAStarOnGithub": "在 Github 上给我们一个星标",
|
||||
"free5GB": "<bold-green>ente</bold-green> Photos 上 5GB 可用空间",
|
||||
|
||||
@@ -506,6 +506,8 @@
|
||||
"deleteDuplicates": "刪除重複項",
|
||||
"plainHTML": "Plain HTML",
|
||||
"tellUsWhatYouThink": "告訴我們您的想法",
|
||||
"dropReviewiOS": "在 App Store 上發表意見",
|
||||
"dropReviewAndroid": "在 Play 商店上發表評測",
|
||||
"supportEnte": "支援 <bold-green>ente</bold-green>",
|
||||
"giveUsAStarOnGithub": "在 Github 上給我們一個星標",
|
||||
"free5GB": "<bold-green>ente</bold-green> Photos 上 5GB 可用空間",
|
||||
|
||||
@@ -114,18 +114,19 @@ class Code {
|
||||
CodeDisplay? display,
|
||||
int digits, {
|
||||
Algorithm algorithm = Algorithm.sha1,
|
||||
int period = defaultPeriod,
|
||||
}) {
|
||||
final String encodedIssuer = Uri.encodeQueryComponent(issuer);
|
||||
return Code(
|
||||
account,
|
||||
issuer,
|
||||
digits,
|
||||
defaultPeriod,
|
||||
period,
|
||||
secret,
|
||||
algorithm,
|
||||
type,
|
||||
0,
|
||||
"otpauth://${type.name}/$issuer:$account?algorithm=${algorithm.name.toUpperCase()}&digits=$digits&issuer=$encodedIssuer&period=30&secret=$secret",
|
||||
"otpauth://${type.name}/$issuer:$account?algorithm=${algorithm.name.toUpperCase()}&digits=$digits&issuer=$encodedIssuer&period=$period&secret=$secret",
|
||||
display: display ?? CodeDisplay(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,10 +3,12 @@ import 'package:flutter/material.dart';
|
||||
|
||||
class FieldLabel extends StatelessWidget {
|
||||
final String label;
|
||||
final double width;
|
||||
|
||||
const FieldLabel(
|
||||
this.label, {
|
||||
super.key,
|
||||
this.width = 80,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -14,7 +16,7 @@ class FieldLabel extends StatelessWidget {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(right: 12.0),
|
||||
child: SizedBox(
|
||||
width: 80,
|
||||
width: width,
|
||||
child: Text(
|
||||
label,
|
||||
style: getEnteTextTheme(context).miniBoldMuted,
|
||||
|
||||
@@ -18,6 +18,7 @@ import 'package:ente_auth/ui/components/buttons/button_widget.dart';
|
||||
import 'package:ente_auth/ui/components/custom_icon_widget.dart';
|
||||
import 'package:ente_auth/ui/components/models/button_result.dart';
|
||||
import 'package:ente_auth/ui/custom_icon_page.dart';
|
||||
import 'package:ente_auth/ui/topt_selector_widget.dart';
|
||||
import 'package:ente_auth/ui/utils/icon_utils.dart';
|
||||
import 'package:ente_auth/utils/dialog_util.dart';
|
||||
import 'package:ente_auth/utils/toast_util.dart';
|
||||
@@ -40,11 +41,13 @@ class _SetupEnterSecretKeyPageState extends State<SetupEnterSecretKeyPage> {
|
||||
final int _notesLimit = 500;
|
||||
final int _otherTextLimit = 200;
|
||||
final int defaultDigits = 6;
|
||||
final int defaultPeriodInSeconds = 30;
|
||||
late TextEditingController _issuerController;
|
||||
late TextEditingController _accountController;
|
||||
late TextEditingController _secretController;
|
||||
late TextEditingController _notesController;
|
||||
late TextEditingController _digitsController;
|
||||
late TextEditingController _periodController;
|
||||
late bool _secretKeyObscured;
|
||||
late List<String> selectedTags = [...?widget.code?.display.tags];
|
||||
List<String> allTags = [];
|
||||
@@ -53,6 +56,8 @@ class _SetupEnterSecretKeyPageState extends State<SetupEnterSecretKeyPage> {
|
||||
String _customIconID = "";
|
||||
late IconType _iconSrc;
|
||||
late Algorithm _algorithm;
|
||||
late Type _type;
|
||||
final ValueNotifier<bool> showAdvancedOptions = ValueNotifier<bool>(false);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -74,6 +79,11 @@ class _SetupEnterSecretKeyPageState extends State<SetupEnterSecretKeyPage> {
|
||||
? widget.code!.digits.toString()
|
||||
: defaultDigits.toString(),
|
||||
);
|
||||
_periodController = TextEditingController(
|
||||
text: widget.code != null
|
||||
? widget.code!.period.toString()
|
||||
: defaultPeriodInSeconds.toString(),
|
||||
);
|
||||
|
||||
_secretKeyObscured = widget.code != null;
|
||||
_loadTags();
|
||||
@@ -112,6 +122,7 @@ class _SetupEnterSecretKeyPageState extends State<SetupEnterSecretKeyPage> {
|
||||
: IconType.customIcon;
|
||||
|
||||
_algorithm = widget.code == null ? Algorithm.sha1 : widget.code!.algorithm;
|
||||
_type = widget.code == null ? Type.totp : widget.code!.type;
|
||||
|
||||
super.initState();
|
||||
}
|
||||
@@ -134,6 +145,7 @@ class _SetupEnterSecretKeyPageState extends State<SetupEnterSecretKeyPage> {
|
||||
_accountController.dispose();
|
||||
_notesController.dispose();
|
||||
_digitsController.dispose();
|
||||
_periodController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -282,76 +294,7 @@ class _SetupEnterSecretKeyPageState extends State<SetupEnterSecretKeyPage> {
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
widget.code == null
|
||||
? Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
splashColor: Colors.transparent,
|
||||
highlightColor: Colors.transparent,
|
||||
hoverColor: Colors.transparent,
|
||||
),
|
||||
child: ExpansionTile(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
),
|
||||
collapsedShape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
),
|
||||
collapsedBackgroundColor: Colors.transparent,
|
||||
tilePadding: EdgeInsets.zero,
|
||||
title: Text(
|
||||
"Advanced",
|
||||
style: getEnteTextTheme(context).small,
|
||||
),
|
||||
children: <Widget>[
|
||||
Row(
|
||||
children: [
|
||||
const FieldLabel("Digits"),
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
keyboardType: TextInputType.number,
|
||||
// The validator receives the text that the user has entered.
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return "Please enter a number";
|
||||
}
|
||||
final intValue = int.tryParse(value);
|
||||
if (intValue == null) {
|
||||
return "Only integers are allowed";
|
||||
}
|
||||
if (intValue < 1 || intValue > 10) {
|
||||
return "OTP digits must be between 1 and 10";
|
||||
}
|
||||
return null;
|
||||
},
|
||||
maxLines: 1,
|
||||
decoration: const InputDecoration(
|
||||
contentPadding: EdgeInsets.symmetric(
|
||||
vertical: 12.0,
|
||||
),
|
||||
),
|
||||
style: getEnteTextTheme(context).small,
|
||||
controller: _digitsController,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 22),
|
||||
Row(
|
||||
children: [
|
||||
const FieldLabel("Algorithm"),
|
||||
AlgorithmSelectorWidget(
|
||||
currentAlgorithm: _algorithm,
|
||||
onSelected: (newAlgorithm) async {
|
||||
setState(() {
|
||||
_algorithm = newAlgorithm;
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
],
|
||||
),
|
||||
)
|
||||
? advanceOptionWidget()
|
||||
: const SizedBox.shrink(),
|
||||
const SizedBox(height: 12),
|
||||
Wrap(
|
||||
@@ -419,11 +362,25 @@ class _SetupEnterSecretKeyPageState extends State<SetupEnterSecretKeyPage> {
|
||||
return;
|
||||
}
|
||||
|
||||
final period =
|
||||
int.tryParse(_periodController.text.trim());
|
||||
if (period != null && (period < 10 || period > 60)) {
|
||||
String message =
|
||||
"Period must be between 10 and 60 seconds";
|
||||
_showIncorrectDetailsDialog(
|
||||
context,
|
||||
message: message,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((_accountController.text.trim().isEmpty &&
|
||||
_issuerController.text.trim().isEmpty) ||
|
||||
_secretController.text.trim().isEmpty ||
|
||||
_digitsController.text.trim().isEmpty ||
|
||||
digits == null) {
|
||||
digits == null ||
|
||||
_periodController.text.trim().isEmpty ||
|
||||
period == null) {
|
||||
String message;
|
||||
if (_secretController.text.trim().isEmpty) {
|
||||
message = context.l10n.secretCanNotBeEmpty;
|
||||
@@ -431,6 +388,10 @@ class _SetupEnterSecretKeyPageState extends State<SetupEnterSecretKeyPage> {
|
||||
message = "Digits cannot be empty";
|
||||
} else if (digits == null) {
|
||||
message = "Digits is not a integer";
|
||||
} else if (_periodController.text.isEmpty) {
|
||||
message = "Period cannot be empty";
|
||||
} else if (period == null) {
|
||||
message = "Period is not a integer";
|
||||
} else {
|
||||
message =
|
||||
context.l10n.bothIssuerAndAccountCanNotBeEmpty;
|
||||
@@ -462,6 +423,7 @@ class _SetupEnterSecretKeyPageState extends State<SetupEnterSecretKeyPage> {
|
||||
final secret = _secretController.text.trim().replaceAll(' ', '');
|
||||
final notes = _notesController.text.trim();
|
||||
final digits = int.tryParse(_digitsController.text.trim());
|
||||
final period = int.tryParse(_periodController.text.trim());
|
||||
|
||||
final isStreamCode = issuer.toLowerCase() == "steam" ||
|
||||
issuer.toLowerCase().contains('steampowered.com');
|
||||
@@ -498,13 +460,14 @@ class _SetupEnterSecretKeyPageState extends State<SetupEnterSecretKeyPage> {
|
||||
|
||||
final Code newCode = widget.code == null
|
||||
? Code.fromAccountAndSecret(
|
||||
isStreamCode ? Type.steam : Type.totp,
|
||||
isStreamCode ? Type.steam : _type,
|
||||
account,
|
||||
issuer,
|
||||
secret,
|
||||
display,
|
||||
isStreamCode ? Code.steamDigits : digits!,
|
||||
algorithm: _algorithm,
|
||||
period: period!,
|
||||
)
|
||||
: widget.code!.copyWith(
|
||||
account: account,
|
||||
@@ -513,6 +476,8 @@ class _SetupEnterSecretKeyPageState extends State<SetupEnterSecretKeyPage> {
|
||||
display: display,
|
||||
algorithm: _algorithm,
|
||||
digits: digits!,
|
||||
type: _type,
|
||||
period: period,
|
||||
);
|
||||
|
||||
// Verify the validity of the code
|
||||
@@ -558,4 +523,159 @@ class _SetupEnterSecretKeyPageState extends State<SetupEnterSecretKeyPage> {
|
||||
_iconSrc = newCustomIcon.type;
|
||||
});
|
||||
}
|
||||
|
||||
Widget advanceOptionWidget() {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
showAdvancedOptions.value = !showAdvancedOptions.value;
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
'Advanced',
|
||||
),
|
||||
ValueListenableBuilder<bool>(
|
||||
valueListenable: showAdvancedOptions,
|
||||
builder: (context, isExpanded, child) {
|
||||
return Icon(
|
||||
isExpanded
|
||||
? Icons.keyboard_arrow_up
|
||||
: Icons.keyboard_arrow_down,
|
||||
size: 24,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
ValueListenableBuilder<bool>(
|
||||
valueListenable: showAdvancedOptions,
|
||||
builder: (context, isExpanded, child) {
|
||||
return AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
transitionBuilder: (child, animation) {
|
||||
return SizeTransition(
|
||||
sizeFactor: animation,
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
child: isExpanded
|
||||
? SizedBox(
|
||||
width: 400,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 16,
|
||||
),
|
||||
child: GridView.count(
|
||||
crossAxisCount: 2,
|
||||
shrinkWrap: true,
|
||||
childAspectRatio: 2.5,
|
||||
crossAxisSpacing: 16,
|
||||
mainAxisSpacing: 14,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
const FieldLabel("Algorithm", width: 60),
|
||||
AlgorithmSelectorWidget(
|
||||
currentAlgorithm: _algorithm,
|
||||
onSelected: (newAlgorithm) async {
|
||||
setState(() {
|
||||
_algorithm = newAlgorithm;
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
const FieldLabel("Type", width: 60),
|
||||
ToptSelectorWidget(
|
||||
currentTopt: _type,
|
||||
onSelected: (newTopt) async {
|
||||
setState(() {
|
||||
_type = newTopt;
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
const FieldLabel("Period", width: 60),
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
keyboardType: TextInputType.number,
|
||||
// The validator receives the text that the user has entered.
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return "Please enter a number";
|
||||
}
|
||||
final intValue = int.tryParse(value);
|
||||
if (intValue == null) {
|
||||
return "Only integers are allowed";
|
||||
}
|
||||
if (intValue < 1 || intValue > 60) {
|
||||
return "Period must be between 1 and 60";
|
||||
}
|
||||
return null;
|
||||
},
|
||||
maxLines: 1,
|
||||
style: getEnteTextTheme(
|
||||
context,
|
||||
).small,
|
||||
controller: _periodController,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
const FieldLabel("Digits", width: 60),
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
keyboardType: TextInputType.number,
|
||||
// The validator receives the text that the user has entered.
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return "Please enter a number";
|
||||
}
|
||||
final intValue = int.tryParse(value);
|
||||
if (intValue == null) {
|
||||
return "Only integers are allowed";
|
||||
}
|
||||
if (intValue < 1 || intValue > 10) {
|
||||
return "OTP digits must be between 1 and 10";
|
||||
}
|
||||
return null;
|
||||
},
|
||||
maxLines: 1,
|
||||
style: getEnteTextTheme(
|
||||
context,
|
||||
).small,
|
||||
controller: _digitsController,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -580,7 +580,9 @@ class _HomePageState extends State<HomePage> {
|
||||
|
||||
return ClipRect(
|
||||
child: CodeWidget(
|
||||
key: ValueKey('${code.hashCode}_${newIndex}_$_codeSortKey'),
|
||||
key: ValueKey(
|
||||
'${code.hashCode}_${newIndex}_$_codeSortKey',
|
||||
),
|
||||
code,
|
||||
isCompactMode: isCompactMode,
|
||||
sortKey: _codeSortKey,
|
||||
@@ -667,11 +669,13 @@ class _HomePageState extends State<HomePage> {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int lastScanTime = DateTime.now().millisecondsSinceEpoch - 1000;
|
||||
void _handleDeeplink(BuildContext context, String? link) {
|
||||
bool isAccountConfigured = Configuration.instance.hasConfiguredAccount();
|
||||
bool isOfflineModeEnabled = Configuration.instance.hasOptedForOfflineMode() &&
|
||||
Configuration.instance.getOfflineSecretKey() != null;
|
||||
bool isOfflineModeEnabled =
|
||||
Configuration.instance.hasOptedForOfflineMode() &&
|
||||
Configuration.instance.getOfflineSecretKey() != null;
|
||||
if (!(isAccountConfigured || isOfflineModeEnabled) || link == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -94,6 +94,7 @@ Future<int?> _processAegisExportFile(
|
||||
final isEncrypted = decodedJson['header']['slots'] != null;
|
||||
Map? aegisDB;
|
||||
if (isEncrypted) {
|
||||
await dialog.hide();
|
||||
String? password;
|
||||
try {
|
||||
await showTextInputDialog(
|
||||
@@ -109,6 +110,7 @@ Future<int?> _processAegisExportFile(
|
||||
await dialog.hide();
|
||||
return null;
|
||||
}
|
||||
await dialog.show();
|
||||
final content = decryptAegisVault(decodedJson, password: password!);
|
||||
aegisDB = jsonDecode(content);
|
||||
} catch (e, s) {
|
||||
|
||||
@@ -159,6 +159,8 @@ class _ItemsWidgetState extends State<ItemsWidget> {
|
||||
return 'Lietuvių';
|
||||
case 'nl':
|
||||
return 'Nederlands';
|
||||
case 'no':
|
||||
return 'Norsk';
|
||||
case 'pl':
|
||||
return 'Polski';
|
||||
case 'pt':
|
||||
|
||||
72
auth/lib/ui/topt_selector_widget.dart
Normal file
@@ -0,0 +1,72 @@
|
||||
import 'package:ente_auth/models/code.dart';
|
||||
import 'package:ente_auth/theme/ente_theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ToptSelectorWidget extends StatelessWidget {
|
||||
final Type currentTopt;
|
||||
final void Function(Type) onSelected;
|
||||
const ToptSelectorWidget({
|
||||
super.key,
|
||||
required this.currentTopt,
|
||||
required this.onSelected,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Text toptOptionText(Type type) {
|
||||
return Text(
|
||||
type.name.toUpperCase(),
|
||||
style: getEnteTextTheme(context).small,
|
||||
);
|
||||
}
|
||||
|
||||
return GestureDetector(
|
||||
onTapDown: (TapDownDetails details) async {
|
||||
final int? selectedValue = await showMenu<int>(
|
||||
context: context,
|
||||
position: RelativeRect.fromLTRB(
|
||||
details.globalPosition.dx,
|
||||
details.globalPosition.dy,
|
||||
details.globalPosition.dx,
|
||||
details.globalPosition.dy + 300,
|
||||
),
|
||||
items: List.generate(Type.values.length, (index) {
|
||||
return PopupMenuItem(
|
||||
value: index,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
toptOptionText(Type.values[index]),
|
||||
if (Type.values[index] == currentTopt)
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: Theme.of(context).iconTheme.color,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
if (selectedValue != null) {
|
||||
onSelected(Type.values[selectedValue]);
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.only(bottom: 4),
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
bottom: BorderSide(color: Theme.of(context).dividerColor),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
toptOptionText(currentTopt),
|
||||
const SizedBox(width: 8),
|
||||
const Icon(Icons.arrow_drop_down),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import "dart:convert";
|
||||
import "dart:io";
|
||||
import "dart:typed_data";
|
||||
|
||||
import "package:ente_auth/core/configuration.dart";
|
||||
@@ -49,6 +50,8 @@ class LockScreenSettings {
|
||||
/// Function to Check if the migration for lock screen changes has
|
||||
/// already been done by checking a stored boolean value.
|
||||
await runLockScreenChangesMigration();
|
||||
|
||||
await _clearLsDataInKeychainIfFreshInstall();
|
||||
}
|
||||
|
||||
Future<void> setOfflineModeWarningStatus(bool value) async {
|
||||
@@ -210,4 +213,17 @@ class LockScreenSettings {
|
||||
Future<bool> isPasswordSet() async {
|
||||
return await _secureStorage.containsKey(key: password);
|
||||
}
|
||||
|
||||
// If the app was uninstalled (without logging out if it was used with
|
||||
// backups), keychain items of the app persist in the keychain. To avoid using
|
||||
// old keychain items, we delete them on reinstall.
|
||||
Future<void> _clearLsDataInKeychainIfFreshInstall() async {
|
||||
if ((Platform.isIOS || Platform.isMacOS) &&
|
||||
!Configuration.instance.isLoggedIn() &&
|
||||
!Configuration.instance.hasOptedForOfflineMode()) {
|
||||
await _secureStorage.delete(key: password);
|
||||
await _secureStorage.delete(key: pin);
|
||||
await _secureStorage.delete(key: saltKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,12 +148,17 @@ flutter:
|
||||
fonts:
|
||||
- asset: fonts/Montserrat-Bold.ttf
|
||||
|
||||
flutter_icons:
|
||||
# run "dart run flutter_launcher_icons" to generate icons
|
||||
flutter_launcher_icons:
|
||||
image_path: "assets/generation-icons/icon-light.png"
|
||||
|
||||
android: "launcher_icon"
|
||||
adaptive_icon_foreground: "assets/generation-icons/icon-light-adaptive-fg.png"
|
||||
adaptive_icon_background: "assets/generation-icons/icon-light-adaptive-bg.png"
|
||||
adaptive_icon_monochrome: "assets/generation-icons/icon-monochrome.png"
|
||||
adaptive_icon_foreground_inset: 0
|
||||
|
||||
ios: true
|
||||
image_path: "assets/generation-icons/icon-light.png"
|
||||
remove_alpha_ios: true
|
||||
|
||||
flutter_native_splash:
|
||||
|
||||
@@ -60,7 +60,7 @@ ente account list
|
||||
#### Change export directory
|
||||
|
||||
```shell
|
||||
ente account update --email email@domain.com --dir ~/photos
|
||||
ente account update --app auth/photos --email email@domain.com --dir ~/photos
|
||||
```
|
||||
|
||||
### Export
|
||||
|
||||
@@ -135,7 +135,7 @@ func (c *ClICtrl) UpdateFreeStorage(ctx context.Context, params model.AdminActio
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Updating storage for user %s to %s (old %s) with new expirty %s (old %s) \n",
|
||||
fmt.Printf("Updating storage for user %s to %s (old %s) with new expiry %s (old %s) \n",
|
||||
params.UserEmail,
|
||||
utils.ByteCountDecimalGIB(storageSize), utils.ByteCountDecimalGIB(userDetails.Subscription.Storage),
|
||||
date.Format("2006-01-02"),
|
||||
|
||||
@@ -22,6 +22,9 @@ on:
|
||||
tags:
|
||||
- "v[0-9]+.[0-9]+.[0-9]+"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ${{ matrix.os }}
|
||||
@@ -49,7 +52,7 @@ jobs:
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
node-version: 22
|
||||
|
||||
- name: Increase yarn timeout
|
||||
# `yarn install` times out sometimes on the Windows runner,
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
# CHANGELOG
|
||||
|
||||
## v1.7.11 (Unreleased)
|
||||
## v1.7.13 (Unreleased)
|
||||
|
||||
- .
|
||||
|
||||
## v1.7.12
|
||||
|
||||
- Improved video player with streaming support (for already processed videos).
|
||||
- Support Arabic translations.
|
||||
|
||||
## v1.7.11
|
||||
|
||||
- Improved file viewer.
|
||||
- Improved live photo experience.
|
||||
- .
|
||||
|
||||
## v1.7.10
|
||||
|
||||
|
||||
BIN
desktop/build/icon.ico
Normal file
|
After Width: | Height: | Size: 113 KiB |
@@ -39,6 +39,10 @@ export default ts.config(
|
||||
"error",
|
||||
{ allowTernary: true },
|
||||
],
|
||||
// Allow force unwrapping potentially optional values.
|
||||
//
|
||||
// See: [Note: non-null-assertions have better stack trace]
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ente",
|
||||
"version": "1.7.11-beta",
|
||||
"version": "1.7.13-beta",
|
||||
"private": true,
|
||||
"description": "Desktop client for Ente Photos",
|
||||
"repository": "github:ente-io/photos-desktop",
|
||||
@@ -27,36 +27,36 @@
|
||||
"dependencies": {
|
||||
"any-shell-escape": "^0.1.1",
|
||||
"auto-launch": "^5.0.6",
|
||||
"chokidar": "^3.6.0",
|
||||
"chokidar": "^4.0.3",
|
||||
"clip-bpe-js": "^0.0.6",
|
||||
"comlink": "^4.4.2",
|
||||
"compare-versions": "^6.1.1",
|
||||
"electron-log": "^5.3.2",
|
||||
"electron-log": "^5.3.4",
|
||||
"electron-store": "^8.2.0",
|
||||
"electron-updater": "^6.4.0",
|
||||
"electron-updater": "^6.6.2",
|
||||
"ffmpeg-static": "^5.2.0",
|
||||
"lru-cache": "^11.0.2",
|
||||
"lru-cache": "^11.1.0",
|
||||
"next-electron-server": "^1.0.0",
|
||||
"node-stream-zip": "^1.15.0",
|
||||
"onnxruntime-node": "^1.20.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.22.0",
|
||||
"@tsconfig/node20": "^20.1.4",
|
||||
"@eslint/js": "^9.25.0",
|
||||
"@tsconfig/node22": "^22.0.1",
|
||||
"@types/auto-launch": "^5.0.5",
|
||||
"@types/ffmpeg-static": "^3.0.3",
|
||||
"ajv": "^8.17.1",
|
||||
"concurrently": "^9.1.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"electron": "^34.3.4",
|
||||
"electron-builder": "^26.0.0",
|
||||
"electron": "^35.2.0",
|
||||
"electron-builder": "^26.0.12",
|
||||
"eslint": "^9",
|
||||
"prettier": "3.5.3",
|
||||
"prettier-plugin-organize-imports": "^4.1.0",
|
||||
"prettier-plugin-packagejson": "^2.5.10",
|
||||
"shx": "^0.3.4",
|
||||
"typescript": "^5.8.2",
|
||||
"typescript-eslint": "^8.26.1"
|
||||
"typescript": "^5.8.3",
|
||||
"typescript-eslint": "^8.30.1"
|
||||
},
|
||||
"packageManager": "yarn@1.22.22",
|
||||
"productName": "ente"
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
*
|
||||
* Note that `vips.js` would've already run once `beforeBuild.js` is run, but on
|
||||
* our CI we prepare builds for multiple architectures in one go, so we need to
|
||||
* unconditonally replace the binary with the relevant one for the current
|
||||
* unconditionally replace the binary with the relevant one for the current
|
||||
* architecture being built (which might be different from the one we're running
|
||||
* on). `beforeBuild.js` runs for each architecture being built.
|
||||
*
|
||||
|
||||
@@ -35,6 +35,7 @@ import log, { initLogging } from "./main/log";
|
||||
import { createApplicationMenu, createTrayContextMenu } from "./main/menu";
|
||||
import { setupAutoUpdater } from "./main/services/app-update";
|
||||
import autoLauncher from "./main/services/auto-launcher";
|
||||
import { shouldHideDockIcon } from "./main/services/store";
|
||||
import { createWatcher } from "./main/services/watch";
|
||||
import { userPreferences } from "./main/stores/user-preferences";
|
||||
import { migrateLegacyWatchStoreIfNeeded } from "./main/stores/watch";
|
||||
@@ -385,8 +386,8 @@ const createMainWindow = () => {
|
||||
const wasAutoLaunched = autoLauncher.wasAutoLaunched();
|
||||
if (wasAutoLaunched) {
|
||||
// Don't automatically show the app's window if we were auto-launched.
|
||||
// On macOS, also hide the dock icon on macOS.
|
||||
if (process.platform == "darwin") app.dock.hide();
|
||||
// On macOS, also hide the dock icon.
|
||||
app.dock?.hide();
|
||||
} else {
|
||||
// Show our window otherwise, maximizing it if we're not asked to set it
|
||||
// to a specific size.
|
||||
@@ -421,14 +422,18 @@ const createMainWindow = () => {
|
||||
|
||||
window.on("hide", () => {
|
||||
// On macOS, when hiding the window also hide the app's icon in the dock
|
||||
// if the user has selected the Settings > Hide dock icon checkbox.
|
||||
if (process.platform == "darwin" && userPreferences.get("hideDockIcon"))
|
||||
app.dock.hide();
|
||||
// unless the user has unchecked the Settings > Hide dock icon checkbox.
|
||||
if (shouldHideDockIcon()) {
|
||||
// macOS emits a window "hide" event when going fullscreen, and if
|
||||
// we hide the dock icon there then the window disappears. So ignore
|
||||
// this scenario.
|
||||
if (!window.isFullScreen()) {
|
||||
app.dock?.hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
window.on("show", () => {
|
||||
if (process.platform == "darwin") void app.dock.show();
|
||||
});
|
||||
window.on("show", () => void app.dock?.show());
|
||||
|
||||
// Let ipcRenderer know when mainWindow is in the foreground so that it can
|
||||
// in turn inform the renderer process.
|
||||
@@ -609,7 +614,7 @@ const handleBackOnStripeCheckout = (window: BrowserWindow) =>
|
||||
*
|
||||
* But this is an issue for uploads in the self hosted apps (or when we
|
||||
* ourselves are trying to test things by with an arbitrary S3 bucket without
|
||||
* going via a worker). During upload, theer is no redirection, so the request
|
||||
* going via a worker). During upload, there is no redirection, so the request
|
||||
* ACAO is "ente://app" but the response ACAO is `null` which don't match,
|
||||
* causing the request to fail.
|
||||
*
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
} from "electron";
|
||||
import { allowWindowClose } from "../main";
|
||||
import { forceCheckForAppUpdates } from "./services/app-update";
|
||||
import { userPreferences } from "./stores/user-preferences";
|
||||
import { setShouldHideDockIcon, shouldHideDockIcon } from "./services/store";
|
||||
|
||||
/** Create and return the entries in the app's main menu bar */
|
||||
export const createApplicationMenu = (mainWindow: BrowserWindow) => {
|
||||
@@ -15,7 +15,7 @@ export const createApplicationMenu = (mainWindow: BrowserWindow) => {
|
||||
//
|
||||
// Whenever the menu is redrawn the current value of these variables is used
|
||||
// to set the checked state for the various settings checkboxes.
|
||||
let shouldHideDockIcon = !!userPreferences.get("hideDockIcon");
|
||||
let hideDockIcon = shouldHideDockIcon();
|
||||
|
||||
const macOSOnly = (options: MenuItemConstructorOptions[]) =>
|
||||
process.platform == "darwin" ? options : [];
|
||||
@@ -24,9 +24,9 @@ export const createApplicationMenu = (mainWindow: BrowserWindow) => {
|
||||
|
||||
const toggleHideDockIcon = () => {
|
||||
// Persist
|
||||
userPreferences.set("hideDockIcon", !shouldHideDockIcon);
|
||||
setShouldHideDockIcon(!hideDockIcon);
|
||||
// And update the in-memory state
|
||||
shouldHideDockIcon = !shouldHideDockIcon;
|
||||
hideDockIcon = !hideDockIcon;
|
||||
};
|
||||
|
||||
const handleHelp = () =>
|
||||
@@ -48,7 +48,7 @@ export const createApplicationMenu = (mainWindow: BrowserWindow) => {
|
||||
{
|
||||
label: "Hide Dock Icon",
|
||||
type: "checkbox",
|
||||
checked: shouldHideDockIcon,
|
||||
checked: hideDockIcon,
|
||||
click: toggleHideDockIcon,
|
||||
},
|
||||
],
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import pathToFfmpeg from "ffmpeg-static";
|
||||
import { randomBytes } from "node:crypto";
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import type { ZipItem } from "../../types/ipc";
|
||||
import { ensure } from "../utils/common";
|
||||
import log from "../log";
|
||||
import { execAsync } from "../utils/electron";
|
||||
import {
|
||||
deleteTempFileIgnoringErrors,
|
||||
@@ -99,18 +101,17 @@ const ffmpegBinaryPath = () => {
|
||||
// This substitution of app.asar by app.asar.unpacked is suggested by the
|
||||
// ffmpeg-static library author themselves:
|
||||
// https://github.com/eugeneware/ffmpeg-static/issues/16
|
||||
return ensure(pathToFfmpeg).replace("app.asar", "app.asar.unpacked");
|
||||
return pathToFfmpeg!.replace("app.asar", "app.asar.unpacked");
|
||||
};
|
||||
|
||||
/**
|
||||
* A variant of {@link ffmpegExec} adapted to work with streams so that it can
|
||||
* handle the MP4 conversion of large video files.
|
||||
*
|
||||
* See: [Note: Convert to MP4]
|
||||
|
||||
* @param inputFilePath The path to a file on the user's local file system. This
|
||||
* is the video we want to convert.
|
||||
* @param inputFilePath The path to a file on the user's local file system where
|
||||
*
|
||||
* @param outputFilePath The path to a file on the user's local file system where
|
||||
* we should write the converted MP4 video.
|
||||
*/
|
||||
export const ffmpegConvertToMP4 = async (
|
||||
@@ -130,3 +131,350 @@ export const ffmpegConvertToMP4 = async (
|
||||
|
||||
await execAsync(cmd);
|
||||
};
|
||||
|
||||
export interface FFmpegGenerateHLSPlaylistAndSegmentsResult {
|
||||
playlistPath: string;
|
||||
videoPath: string;
|
||||
dimensions: { width: number; height: number };
|
||||
}
|
||||
|
||||
/**
|
||||
* A bespoke variant of {@link ffmpegExec} for generation of HLS playlists for
|
||||
* videos.
|
||||
*
|
||||
* See: [Note: Preview variant of videos]
|
||||
|
||||
* @param inputFilePath The path to a file on the user's local file system. This
|
||||
* is the video we want to generate an streamable HLS playlist for.
|
||||
*
|
||||
* @param outputPathPrefix The path to unique, unused and temporary prefix on
|
||||
* the user's local file system. This function will write the generated HLS
|
||||
* playlist and video segments under this prefix.
|
||||
*
|
||||
* @returns The paths to two files on the user's local file system - one
|
||||
* containing the generated HLS playlist, and the other containing the
|
||||
* transcoded and encrypted video segments that the HLS playlist refers to.
|
||||
*/
|
||||
export const ffmpegGenerateHLSPlaylistAndSegments = async (
|
||||
inputFilePath: string,
|
||||
outputPathPrefix: string,
|
||||
): Promise<FFmpegGenerateHLSPlaylistAndSegmentsResult> => {
|
||||
// [Note: Tonemapping HDR to HD]
|
||||
//
|
||||
// BT.709 ("HD") is a standard that describes things like how color is
|
||||
// encoded, the range of values, and their "meaning" - i.e. how to map the
|
||||
// values in the video to the pixels on the screen.
|
||||
//
|
||||
// It is not the only such standard, there are three common examples:
|
||||
//
|
||||
// - BT.601 ("Standard-Definition" or SD)
|
||||
// - BT.709 ("High-Definition" or HD)
|
||||
// - BT.2020 ("Ultra-High-Definition" or UHD, aka HDR^).
|
||||
//
|
||||
// ^ HDR ("High-Dynamic-Range") is an addendum to BT.2020, but for our
|
||||
// purpose here we can treat it as as alias.
|
||||
//
|
||||
// BT.709 is the most common amongst these for older files out stored on
|
||||
// computers, and they conform mostly to the standard (one notable exception
|
||||
// is that the BT.709 standard also recommends using the yuv422p pixel
|
||||
// format, but de facto yuv420p is used because many video players only
|
||||
// support yuv420p).
|
||||
//
|
||||
// Since BT.709 is the most widely supported standard, we use it when
|
||||
// generating the HLS playlist so to allow playback across the widest
|
||||
// possible hardware/OS/browser combinations.
|
||||
//
|
||||
// If we convert HDR to HD without naively, then the colors look washed out
|
||||
// compared to the original. To resolve this, we use a ffmpeg filterchain
|
||||
// that uses the tonemap filter.
|
||||
//
|
||||
// However applying this tonemap to videos that are already HD leads to a
|
||||
// brightness drop. So we conditionally apply this filter chain only if the
|
||||
// colorspace is not already BT.709.
|
||||
//
|
||||
// Reference:
|
||||
// - https://trac.ffmpeg.org/wiki/colorspace
|
||||
const isBT709 = await detectIsBT709(inputFilePath);
|
||||
|
||||
// We want the generated playlist to refer to the chunks as "output.ts".
|
||||
//
|
||||
// So we arrange things accordingly: We use the `outputPathPrefix` as our
|
||||
// working directory, and then ask ffmpeg to generate a playlist with the
|
||||
// name "output.m3u8".
|
||||
//
|
||||
// ffmpeg will automatically place the segments in a file with the same base
|
||||
// name as the playlist, but with a ".ts" extension. And since we use the
|
||||
// "single_file" option, all the segments will be placed in a file named
|
||||
// "output.ts".
|
||||
|
||||
await fs.mkdir(outputPathPrefix);
|
||||
|
||||
const playlistPath = path.join(outputPathPrefix, "output.m3u8");
|
||||
const videoPath = path.join(outputPathPrefix, "output.ts");
|
||||
|
||||
// Generate a cryptographically secure random key (16 bytes).
|
||||
const keyBytes = randomBytes(16);
|
||||
const keyB64 = keyBytes.toString("base64");
|
||||
|
||||
// Convert it to a data: URI that will be added to the playlist.
|
||||
const keyURI = `data:text/plain;base64,${keyB64}`;
|
||||
|
||||
// Determine two paths - one where we will write the key itself, and where
|
||||
// we will write the "key info" that provides ffmpeg the `keyURI` and the
|
||||
// `keyPath;.
|
||||
const keyPath = playlistPath + ".key";
|
||||
const keyInfoPath = playlistPath + ".key-info";
|
||||
|
||||
// Generate a "key info":
|
||||
//
|
||||
// - the first line specifies the key URI that is written into the playlist.
|
||||
// - the second line specifies the path to the local filesystem file from
|
||||
// where ffmpeg should read the key.
|
||||
const keyInfo = [keyURI, keyPath].join("\n");
|
||||
|
||||
// Overview:
|
||||
//
|
||||
// - H.264 video HD 720p 30fps.
|
||||
// - AAC audio 128kbps.
|
||||
// - Encrypted HLS playlist with a single file containing all the chunks.
|
||||
//
|
||||
// Reference:
|
||||
// - `man ffmpeg-all`
|
||||
// - https://trac.ffmpeg.org/wiki/Encode/H.264
|
||||
//
|
||||
const command = [
|
||||
ffmpegBinaryPath(),
|
||||
// Reduce the amount of output lines we have to parse.
|
||||
["-hide_banner"],
|
||||
// Input file. We don't need any extra options that apply to the input file.
|
||||
"-i",
|
||||
inputFilePath,
|
||||
// The remaining options apply to the next output file (`playlistPath`).
|
||||
//
|
||||
// ---
|
||||
//
|
||||
// `-vf` creates a filter graph for the video stream. This is a string
|
||||
// of the form `filter1=key=value:key=value.filter2=key=value`, that is,
|
||||
// a comma separated list of filters chained together.
|
||||
[
|
||||
"-vf",
|
||||
[
|
||||
// Scales the video to maximum 720p height, keeping aspect
|
||||
// ratio, and keeping the calculated dimension divisible by 2
|
||||
// (some of the other operations require an even pixel count).
|
||||
"scale=-2:720",
|
||||
// Convert the video to a constant 30 fps, duplicating or
|
||||
// dropping frames as necessary.
|
||||
"fps=30",
|
||||
// If the video is not in the HD color space (bt709), convert
|
||||
// it. Before conversion, tone map colors so that they work the
|
||||
// same across the change in the dyamic range.
|
||||
//
|
||||
// 1. The tonemap filter only works linear light, so we first
|
||||
// use zscale with transfer=linear to linearize the input.
|
||||
//
|
||||
// 2. Then we use the tonemap, with the hable option that is
|
||||
// best for preserving details. desat=0 turns off the default
|
||||
// desaturation.
|
||||
//
|
||||
// 3. Use zscale again to "convert to BT.709" by asking it to
|
||||
// set the all three of color primaries, transfer
|
||||
// characteristics and colorspace matrix to 709 (Note: the
|
||||
// constants specified in the tonemap filter help do not
|
||||
// include the "bt" prefix)
|
||||
//
|
||||
// See: https://ffmpeg.org/ffmpeg-filters.html#tonemap-1
|
||||
//
|
||||
// See: [Note: Tonemapping HDR to HD]
|
||||
isBT709
|
||||
? []
|
||||
: [
|
||||
"zscale=transfer=linear",
|
||||
"tonemap=tonemap=hable:desat=0",
|
||||
"zscale=primaries=709:transfer=709:matrix=709",
|
||||
],
|
||||
// Output using the most widely supported pixel format: 8-bit
|
||||
// YUV planar color space with 4:2:0 chroma subsampling.
|
||||
"format=yuv420p",
|
||||
]
|
||||
.flat()
|
||||
.join(","),
|
||||
],
|
||||
// Video codec H.264
|
||||
//
|
||||
// - `-c:v libx264` converts the video stream to use the H.264 codec.
|
||||
//
|
||||
// - We don't supply a bitrate, instead it uses the default CRF ("23")
|
||||
// as recommended in the ffmpeg trac.
|
||||
//
|
||||
// - We don't supply a preset, it'll use the default ("medium")
|
||||
["-c:v", "libx264"],
|
||||
// Audio codec AAC
|
||||
//
|
||||
// - `-c:a aac` converts the audio stream to use the AAC codec
|
||||
//
|
||||
// - We don't supply a bitrate, it'll use the AAC default 128k bps.
|
||||
["-c:a", "aac"],
|
||||
// Generate a HLS playlist.
|
||||
["-f", "hls"],
|
||||
// Tell ffmpeg where to find the key, and the URI for the key to write
|
||||
// into the generated playlist. Implies "-hls_enc 1".
|
||||
["-hls_key_info_file", keyInfoPath],
|
||||
// Generate as many playlist entries as needed (default limit is 5).
|
||||
["-hls_list_size", "0"],
|
||||
// Place all the video segments within the same .ts file (with the same
|
||||
// path as the playlist file but with a ".ts" extension).
|
||||
["-hls_flags", "single_file"],
|
||||
// Output path where the playlist should be generated.
|
||||
playlistPath,
|
||||
].flat();
|
||||
|
||||
let dimensions: ReturnType<typeof detectVideoDimensions>;
|
||||
|
||||
try {
|
||||
// Write the key and the keyInfo to their desired paths.
|
||||
await Promise.all([
|
||||
fs.writeFile(keyPath, keyBytes),
|
||||
fs.writeFile(keyInfoPath, keyInfo, { encoding: "utf8" }),
|
||||
]);
|
||||
|
||||
// Run the ffmpeg command to generate the HLS playlist and segments.
|
||||
//
|
||||
// Note: Depending on the size of the input file, this may take long!
|
||||
const { stderr: conversionStderr } = await execAsync(command);
|
||||
|
||||
// Determine the dimensions of the generated video from the stderr
|
||||
// output produced by ffmpeg during the conversion.
|
||||
dimensions = detectVideoDimensions(conversionStderr);
|
||||
} catch (e) {
|
||||
log.error("HLS generation failed", e);
|
||||
await Promise.all([
|
||||
deleteTempFileIgnoringErrors(playlistPath),
|
||||
deleteTempFileIgnoringErrors(videoPath),
|
||||
]);
|
||||
throw e;
|
||||
} finally {
|
||||
await Promise.all([
|
||||
deleteTempFileIgnoringErrors(keyInfoPath),
|
||||
deleteTempFileIgnoringErrors(keyPath),
|
||||
// ffmpeg writes a /path/output.ts.tmp, clear it out too.
|
||||
deleteTempFileIgnoringErrors(videoPath + ".tmp"),
|
||||
]);
|
||||
}
|
||||
|
||||
return { playlistPath, videoPath, dimensions };
|
||||
};
|
||||
|
||||
/**
|
||||
* A regex that matches the first line of the form
|
||||
*
|
||||
* Stream #0:0: Video: h264 (High 10) ([27][0][0][0] / 0x001B), yuv420p10le(tv, bt2020nc/bt2020/arib-std-b67), 1920x1080, 30 fps, 30 tbr, 90k tbn
|
||||
*
|
||||
* The part after Video: is the first capture group.
|
||||
*/
|
||||
const videoStreamLineRegex = /Stream #.+: Video:(.+)\n/;
|
||||
|
||||
/** {@link videoStreamLineRegex}, but global. */
|
||||
const videoStreamLinesRegex = /Stream #.+: Video:(.+)\n/g;
|
||||
|
||||
/**
|
||||
* A regex that matches <digits>x<digits> pair preceded by a space and followed
|
||||
* by a trailing comma. See {@link videoStreamLineRegex} for the context in
|
||||
* which it is used.
|
||||
*/
|
||||
const videoDimensionsRegex = / (\d+)x(\d+),/;
|
||||
|
||||
/**
|
||||
* Heuristically determine if the given video uses the BT.709 colorspace.
|
||||
*
|
||||
* This function tries to determine the input colorspace by scanning the ffmpeg
|
||||
* info output for the video stream line, and checking if it contains the string
|
||||
* "bt709". See: [Note: Parsing CLI output might break on ffmpeg updates].
|
||||
*/
|
||||
const detectIsBT709 = async (inputFilePath: string) => {
|
||||
const videoInfo = await pseudoFFProbeVideo(inputFilePath);
|
||||
const videoStreamLine = videoStreamLineRegex.exec(videoInfo)?.at(1);
|
||||
return !!videoStreamLine?.includes("bt709");
|
||||
};
|
||||
|
||||
/**
|
||||
* Heuristically detect the dimensions of the given video from the log output of
|
||||
* the ffmpeg invocation during the HLS playlist generation.
|
||||
*
|
||||
* This function tries to determine the width and height of the generated video
|
||||
* from the output log written by ffmpeg on its stderr during the generation
|
||||
* process, scanning it for the last video stream line, and trying to match a
|
||||
* "<digits>x<digits>" regex.
|
||||
*
|
||||
* See: [Note: Parsing CLI output might break on ffmpeg updates].
|
||||
*/
|
||||
const detectVideoDimensions = (conversionStderr: string) => {
|
||||
// There is a nicer way to do it - by running `pseudoFFProbeVideo` on the
|
||||
// generated playlist. However, that playlist includes a data URL that
|
||||
// specifies the encryption info, and ffmpeg refuses to read that unless we
|
||||
// specify the "-allowed_extensions ALL" or something to that effect.
|
||||
//
|
||||
// Unfortunately, our current ffmpeg binary (5.x) does not support that
|
||||
// option. So we instead parse the conversion output itself.
|
||||
//
|
||||
// This is also nice, since it saves on an extra ffmpeg invocation. But we
|
||||
// now need to be careful to find the right video stream line, since the
|
||||
// conversion output includes both the input and output video stream lines.
|
||||
//
|
||||
// To match the right (output) video stream line, we use a global regex, and
|
||||
// use the last match since that'd correspond to the single video stream
|
||||
// written in the output.
|
||||
const videoStreamLine = Array.from(
|
||||
conversionStderr.matchAll(videoStreamLinesRegex),
|
||||
)
|
||||
.at(-1) /* Last Stream...: Video: line in the output */
|
||||
?.at(1); /* First capture group */
|
||||
if (videoStreamLine) {
|
||||
const [, ws, hs] = videoDimensionsRegex.exec(videoStreamLine) ?? [];
|
||||
if (ws && hs) {
|
||||
const w = parseInt(ws);
|
||||
const h = parseInt(hs);
|
||||
if (w && h) {
|
||||
return { width: w, height: h };
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new Error(
|
||||
`Unable to detect video dimensions from stream line [${videoStreamLine ?? ""}]`,
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* We don't have the ffprobe binary at hand, so we make do by grepping the log
|
||||
* output of ffmpeg.
|
||||
*
|
||||
* > [Note: Parsing CLI output might break on ffmpeg updates]
|
||||
* >
|
||||
* > Needless to say, while this works currently, this is liable to break in the
|
||||
* > future. So if something stops working after updating ffmpeg, look here!
|
||||
*
|
||||
* @returns the stderr of ffmpeg after running it on the input file. The exact
|
||||
* command we run is:
|
||||
*
|
||||
* ffmpeg -i in.mov -an -frames:v 0 -f null - 2>info.txt
|
||||
*
|
||||
* And the returned string is the contents of the `info.txt` thus produced.
|
||||
*/
|
||||
const pseudoFFProbeVideo = async (inputFilePath: string) => {
|
||||
const command = [
|
||||
ffmpegPathPlaceholder,
|
||||
// Reduce the amount of output lines we have to parse.
|
||||
["-hide_banner"],
|
||||
["-i", inputPathPlaceholder],
|
||||
"-an",
|
||||
["-frames:v", "0"],
|
||||
["-f", "null"],
|
||||
"-",
|
||||
].flat();
|
||||
|
||||
const cmd = substitutePlaceholders(command, inputFilePath, /* NA */ "");
|
||||
|
||||
const { stderr } = await execAsync(cmd);
|
||||
|
||||
return stderr;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { FSWatcher } from "chokidar";
|
||||
import log from "../log";
|
||||
import { clearConvertToMP4Results } from "../stream";
|
||||
import { clearPendingVideoResults } from "../stream";
|
||||
import { clearStores } from "./store";
|
||||
import { watchReset } from "./watch";
|
||||
import { clearOpenZipCache } from "./zip";
|
||||
@@ -22,9 +22,9 @@ export const logout = (watcher: FSWatcher) => {
|
||||
ignoreError("FS watch", e);
|
||||
}
|
||||
try {
|
||||
clearConvertToMP4Results();
|
||||
clearPendingVideoResults();
|
||||
} catch (e) {
|
||||
ignoreError("convert-to-mp4", e);
|
||||
ignoreError("video", e);
|
||||
}
|
||||
try {
|
||||
clearStores();
|
||||
|
||||
@@ -16,7 +16,7 @@ import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import * as ort from "onnxruntime-node";
|
||||
import { messagePortMainEndpoint } from "../utils/comlink";
|
||||
import { ensure, wait } from "../utils/common";
|
||||
import { wait } from "../utils/common";
|
||||
import { writeStream } from "../utils/stream";
|
||||
|
||||
/**
|
||||
@@ -68,7 +68,7 @@ process.parentPort.once("message", (e) => {
|
||||
detectFaces,
|
||||
computeFaceEmbeddings,
|
||||
},
|
||||
messagePortMainEndpoint(ensure(e.ports[0])),
|
||||
messagePortMainEndpoint(e.ports[0]!),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -80,7 +80,7 @@ process.parentPort.once("message", (e) => {
|
||||
let _userDataPath: string | undefined;
|
||||
|
||||
/** Equivalent to app.getPath("userData") */
|
||||
const userDataPath = () => ensure(_userDataPath);
|
||||
const userDataPath = () => _userDataPath!;
|
||||
|
||||
const parseInitData = (data: unknown) => {
|
||||
if (
|
||||
@@ -131,10 +131,8 @@ const makeCachedInferenceSession = (
|
||||
const createSession = (modelPath: string) =>
|
||||
createInferenceSession(modelPath);
|
||||
|
||||
const cachedInferenceSession = () => {
|
||||
if (!session) session = download().then(createSession);
|
||||
return session;
|
||||
};
|
||||
const cachedInferenceSession = () =>
|
||||
(session ??= download().then(createSession));
|
||||
|
||||
return cachedInferenceSession;
|
||||
};
|
||||
@@ -252,7 +250,7 @@ export const computeCLIPImageEmbedding = async (
|
||||
const results = await session.run(feeds);
|
||||
log.debugString(`ONNX/CLIP image embedding took ${Date.now() - t} ms`);
|
||||
/* Need these model specific casts to type the result */
|
||||
return ensure(results.output).data as Float32Array;
|
||||
return results.output!.data as Float32Array;
|
||||
};
|
||||
|
||||
const cachedCLIPTextSession = makeCachedInferenceSession(
|
||||
@@ -261,10 +259,7 @@ const cachedCLIPTextSession = makeCachedInferenceSession(
|
||||
);
|
||||
|
||||
let _tokenizer: Tokenizer | undefined;
|
||||
const getTokenizer = () => {
|
||||
if (!_tokenizer) _tokenizer = new Tokenizer();
|
||||
return _tokenizer;
|
||||
};
|
||||
const getTokenizer = () => (_tokenizer ??= new Tokenizer());
|
||||
|
||||
/**
|
||||
* Compute CLIP embeddings for an text snippet.
|
||||
@@ -295,7 +290,7 @@ export const computeCLIPTextEmbeddingIfAvailable = async (text: string) => {
|
||||
const t = Date.now();
|
||||
const results = await session.run(feeds);
|
||||
log.debugString(`ONNX/CLIP text embedding took ${Date.now() - t} ms`);
|
||||
return ensure(results.output).data as Float32Array;
|
||||
return results.output!.data as Float32Array;
|
||||
};
|
||||
|
||||
const cachedFaceDetectionSession = makeCachedInferenceSession(
|
||||
@@ -316,7 +311,7 @@ export const detectFaces = async (
|
||||
const t = Date.now();
|
||||
const results = await session.run(feeds);
|
||||
log.debugString(`ONNX/YOLO face detection took ${Date.now() - t} ms`);
|
||||
return ensure(results.output).data;
|
||||
return results.output!.data;
|
||||
};
|
||||
|
||||
const cachedFaceEmbeddingSession = makeCachedInferenceSession(
|
||||
|
||||
@@ -42,3 +42,31 @@ export const lastShownChangelogVersion = (): number | undefined =>
|
||||
|
||||
export const setLastShownChangelogVersion = (version: number) =>
|
||||
userPreferences.set("lastShownChangelogVersion", version);
|
||||
|
||||
/**
|
||||
* Return true if the dock icon should be hidden when the window is closed
|
||||
* [macOS only].
|
||||
*
|
||||
* On macOS, if this function returns true then when hiding ("closing" it with
|
||||
* the x traffic light) the window we also hide the app's icon in the dock. The
|
||||
* user can modify their preference using the Menu bar > ente > Settings > Hide
|
||||
* dock icon checkbox.
|
||||
*
|
||||
* If the user has not set a value for this preference (i.e., the value is
|
||||
* `undefined`), we use the default `true`. This is confusing, but this way we
|
||||
* can retain the preexisting preference key instead of doing a migration.
|
||||
*
|
||||
* Value | Behaviour
|
||||
* ----------|--------------
|
||||
* undefined | default (hide)
|
||||
* false | show
|
||||
* true | hide
|
||||
*
|
||||
* On non-macOS platforms, it always returns false.
|
||||
*/
|
||||
export const shouldHideDockIcon = (): boolean =>
|
||||
process.platform == "darwin" &&
|
||||
userPreferences.get("hideDockIcon") !== false;
|
||||
|
||||
export const setShouldHideDockIcon = (hide: boolean) =>
|
||||
userPreferences.set("hideDockIcon", hide);
|
||||
|
||||
@@ -7,9 +7,12 @@ import fs from "node:fs/promises";
|
||||
import { Writable } from "node:stream";
|
||||
import { pathToFileURL } from "node:url";
|
||||
import log from "./log";
|
||||
import { ffmpegConvertToMP4 } from "./services/ffmpeg";
|
||||
import {
|
||||
ffmpegConvertToMP4,
|
||||
ffmpegGenerateHLSPlaylistAndSegments,
|
||||
type FFmpegGenerateHLSPlaylistAndSegmentsResult,
|
||||
} from "./services/ffmpeg";
|
||||
import { markClosableZip, openZip } from "./services/zip";
|
||||
import { ensure } from "./utils/common";
|
||||
import { writeStream } from "./utils/stream";
|
||||
import {
|
||||
deleteTempFile,
|
||||
@@ -57,25 +60,39 @@ const handleStreamRequest = async (request: Request): Promise<Response> => {
|
||||
const { host, searchParams } = new URL(url);
|
||||
switch (host) {
|
||||
case "read":
|
||||
return handleRead(ensure(searchParams.get("path")));
|
||||
return handleRead(searchParams.get("path")!);
|
||||
|
||||
case "read-zip":
|
||||
return handleReadZip(
|
||||
ensure(searchParams.get("zipPath")),
|
||||
ensure(searchParams.get("entryName")),
|
||||
searchParams.get("zipPath")!,
|
||||
searchParams.get("entryName")!,
|
||||
);
|
||||
|
||||
case "write":
|
||||
return handleWrite(ensure(searchParams.get("path")), request);
|
||||
return handleWrite(searchParams.get("path")!, request);
|
||||
|
||||
case "video": {
|
||||
const op = searchParams.get("op");
|
||||
if (op) {
|
||||
switch (op) {
|
||||
case "convert-to-mp4":
|
||||
return handleConvertToMP4Write(request);
|
||||
case "generate-hls":
|
||||
return handleGenerateHLSWrite(request);
|
||||
default:
|
||||
return new Response(`Unknown op ${op}`, {
|
||||
status: 404,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
case "convert-to-mp4": {
|
||||
const token = searchParams.get("token");
|
||||
const done = searchParams.get("done") !== null;
|
||||
return token
|
||||
? done
|
||||
? handleConvertToMP4ReadDone(token)
|
||||
: handleConvertToMP4Read(token)
|
||||
: handleConvertToMP4Write(request);
|
||||
if (!token) {
|
||||
return new Response("Missing token", { status: 404 });
|
||||
}
|
||||
|
||||
return done ? handleVideoDone(token) : handleVideoRead(token);
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -166,21 +183,21 @@ const handleReadZip = async (zipPath: string, entryName: string) => {
|
||||
};
|
||||
|
||||
const handleWrite = async (path: string, request: Request) => {
|
||||
await writeStream(path, ensure(request.body));
|
||||
await writeStream(path, request.body!);
|
||||
return new Response("", { status: 200 });
|
||||
};
|
||||
|
||||
/**
|
||||
* A map from token to file paths for convert-to-mp4 requests that we have
|
||||
* received.
|
||||
* A map from token to file paths generated as a result of stream://video
|
||||
* requests we have received.
|
||||
*/
|
||||
const convertToMP4Results = new Map<string, string>();
|
||||
const pendingVideoResults = new Map<string, string>();
|
||||
|
||||
/**
|
||||
* Clear any in-memory state for in-flight convert-to-mp4 requests. Meant to be
|
||||
* called during logout.
|
||||
* Clear any in-memory state for in-flight streamed video processing requests.
|
||||
* Meant to be called during logout.
|
||||
*/
|
||||
export const clearConvertToMP4Results = () => convertToMP4Results.clear();
|
||||
export const clearPendingVideoResults = () => pendingVideoResults.clear();
|
||||
|
||||
/**
|
||||
* [Note: Convert to MP4]
|
||||
@@ -195,26 +212,26 @@ export const clearConvertToMP4Results = () => convertToMP4Results.clear();
|
||||
* mode for the Web fetch API). So we need to simulate that using two different
|
||||
* streaming requests.
|
||||
*
|
||||
* renderer → main stream://convert-to-mp4
|
||||
* renderer → main stream://video?op=convert-to-mp4
|
||||
* → request.body is the original video
|
||||
* ← response is a token
|
||||
* ← response is [token]
|
||||
*
|
||||
* renderer → main stream://convert-to-mp4?token=<token>
|
||||
* renderer → main stream://video?token=<token>
|
||||
* ← response.body is the converted video
|
||||
*
|
||||
* renderer → main stream://convert-to-mp4?token=<token>&done
|
||||
* renderer → main stream://video?token=<token>&done
|
||||
* ← 200 OK
|
||||
*
|
||||
* Note that the conversion itself is not streaming. The conversion still
|
||||
* happens in a single shot, we are just streaming the data across the IPC
|
||||
* boundary to allow us to pass large amounts of data without running out of
|
||||
* memory.
|
||||
* happens in a single invocation of ffmpeg, we are just streaming the data
|
||||
* across the IPC boundary to allow us to pass large amounts of data without
|
||||
* running out of memory.
|
||||
*
|
||||
* See also: [Note: IPC streams]
|
||||
*/
|
||||
const handleConvertToMP4Write = async (request: Request) => {
|
||||
const inputTempFilePath = await makeTempFilePath();
|
||||
await writeStream(inputTempFilePath, ensure(request.body));
|
||||
await writeStream(inputTempFilePath, request.body!);
|
||||
|
||||
const outputTempFilePath = await makeTempFilePath("mp4");
|
||||
try {
|
||||
@@ -228,25 +245,61 @@ const handleConvertToMP4Write = async (request: Request) => {
|
||||
}
|
||||
|
||||
const token = randomUUID();
|
||||
convertToMP4Results.set(token, outputTempFilePath);
|
||||
return new Response(token, { status: 200 });
|
||||
pendingVideoResults.set(token, outputTempFilePath);
|
||||
return new Response(JSON.stringify([token]), { status: 200 });
|
||||
};
|
||||
|
||||
const handleConvertToMP4Read = async (token: string) => {
|
||||
const filePath = convertToMP4Results.get(token);
|
||||
const handleVideoRead = async (token: string) => {
|
||||
const filePath = pendingVideoResults.get(token);
|
||||
if (!filePath)
|
||||
return new Response(`Unknown token ${token}`, { status: 404 });
|
||||
|
||||
return net.fetch(pathToFileURL(filePath).toString());
|
||||
};
|
||||
|
||||
const handleConvertToMP4ReadDone = async (token: string) => {
|
||||
const filePath = convertToMP4Results.get(token);
|
||||
const handleVideoDone = async (token: string) => {
|
||||
const filePath = pendingVideoResults.get(token);
|
||||
if (!filePath)
|
||||
return new Response(`Unknown token ${token}`, { status: 404 });
|
||||
|
||||
await deleteTempFile(filePath);
|
||||
|
||||
convertToMP4Results.delete(token);
|
||||
pendingVideoResults.delete(token);
|
||||
return new Response("", { status: 200 });
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a HLS playlist for the given video.
|
||||
*
|
||||
* See: [Note: Convert to MP4] for the general architecture of commands that do
|
||||
* renderer <-> main I/O using streams.
|
||||
*
|
||||
* The difference here is that we the conversion generates two streams - one for
|
||||
* the HLS playlist itself, and one for the file containing the encrypted and
|
||||
* transcoded video chunks. So instead of returning a single token, we return a
|
||||
* JSON array containing two tokens so that the renderer can read them off
|
||||
* separately.
|
||||
*/
|
||||
const handleGenerateHLSWrite = async (request: Request) => {
|
||||
const inputTempFilePath = await makeTempFilePath();
|
||||
await writeStream(inputTempFilePath, request.body!);
|
||||
|
||||
const outputFilePathPrefix = await makeTempFilePath();
|
||||
let paths: FFmpegGenerateHLSPlaylistAndSegmentsResult;
|
||||
try {
|
||||
paths = await ffmpegGenerateHLSPlaylistAndSegments(
|
||||
inputTempFilePath,
|
||||
outputFilePathPrefix,
|
||||
);
|
||||
} finally {
|
||||
await deleteTempFileIgnoringErrors(inputTempFilePath);
|
||||
}
|
||||
|
||||
const playlistToken = randomUUID();
|
||||
const videoToken = randomUUID();
|
||||
pendingVideoResults.set(playlistToken, paths.playlistPath);
|
||||
pendingVideoResults.set(videoToken, paths.videoPath);
|
||||
return new Response(JSON.stringify([playlistToken, videoToken]), {
|
||||
status: 200,
|
||||
});
|
||||
};
|
||||
|
||||
2
desktop/src/main/types/any-shell-escape.d.ts
vendored
@@ -12,7 +12,7 @@
|
||||
*
|
||||
* yields (on POSIX shells):
|
||||
*
|
||||
* curl -v -H 'Location;' -H 'User-Agent: FoorBar'"'"'s so-called "Browser"' 'http://www.daveeddy.com/?name=dave&age=24'
|
||||
* curl -v -H 'Location;' -H 'User-Agent: FooBar'"'"'s so-called "Browser"' 'http://www.daveeddy.com/?name=dave&age=24'
|
||||
*
|
||||
* or (on Windows):
|
||||
*
|
||||
|
||||
@@ -5,15 +5,6 @@
|
||||
* currently a common package that both of them share.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Throw an exception if the given value is `null` or `undefined`.
|
||||
*/
|
||||
export const ensure = <T>(v: T | null | undefined): T => {
|
||||
if (v === null) throw new Error("Required value was null");
|
||||
if (v === undefined) throw new Error("Required value was not found");
|
||||
return v;
|
||||
};
|
||||
|
||||
/**
|
||||
* Wait for {@link ms} milliseconds
|
||||
*
|
||||
|
||||
@@ -27,7 +27,7 @@ const writeNodeStream = async (filePath: string, fileStream: Readable) => {
|
||||
|
||||
fileStream.pipe(writeable);
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
writeable.on("finish", resolve);
|
||||
writeable.on("error", (err) => {
|
||||
if (existsSync(filePath)) {
|
||||
|
||||
@@ -5,7 +5,6 @@ import path from "node:path";
|
||||
import type { ZipItem } from "../../types/ipc";
|
||||
import log from "../log";
|
||||
import { markClosableZip, openZip } from "../services/zip";
|
||||
import { ensure } from "./common";
|
||||
|
||||
/**
|
||||
* Our very own directory within the system temp directory. Go crazy, but
|
||||
@@ -20,17 +19,21 @@ const enteTempDirPath = async () => {
|
||||
/** Generate a random string suitable for being used as a file name prefix */
|
||||
const randomPrefix = () => {
|
||||
const ch = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
const randomChar = () => ensure(ch[Math.floor(Math.random() * ch.length)]);
|
||||
const randomChar = () => ch[Math.floor(Math.random() * ch.length)]!;
|
||||
|
||||
return Array(10).fill("").map(randomChar).join("");
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the path to a temporary file with the given {@link suffix}.
|
||||
* Return the path to a temporary file with an optional {@link extension}.
|
||||
*
|
||||
* The function returns the path to a file in the system temp directory (in an
|
||||
* Ente specific folder therin) with a random prefix and an (optional)
|
||||
* {@link extension}.
|
||||
* {@link extension}. The parent directory is guaranteed to exist.
|
||||
*
|
||||
* @param extension A string, if provided, is used as the extension for the
|
||||
* generated path. It will be automatically prefixed by a dot, so don't include
|
||||
* the dot in the provided string.
|
||||
*
|
||||
* It ensures that there is no existing item with the same name already.
|
||||
*
|
||||
@@ -64,7 +67,7 @@ export const deleteTempFile = async (tempFilePath: string) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* A variant of {@link deleteTempFile} that supresses any errors, making it
|
||||
* A variant of {@link deleteTempFile} that suppresses any errors, making it
|
||||
* safe to call them in a sequence without needing to handle the scenario where
|
||||
* one of them failing causes the rest to be skipped.
|
||||
*/
|
||||
|
||||
@@ -335,7 +335,7 @@ const clearPendingUploads = () => ipcRenderer.invoke("clearPendingUploads");
|
||||
* >
|
||||
* > https://www.electronjs.org/docs/latest/api/context-bridge#methods
|
||||
*
|
||||
* The copy itself is relatively fast, but the problem with transfering large
|
||||
* The copy itself is relatively fast, but the problem with transferring large
|
||||
* amounts of data is potentially running out of memory during the copy.
|
||||
*
|
||||
* For an alternative, see [Note: IPC streams].
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
* Recommended target, lib and other settings for code running in the
|
||||
* version of Node.js bundled with Electron.
|
||||
*
|
||||
* Currently, with Electron 30, this is Node.js 20.11.1.
|
||||
* https://www.electronjs.org/blog/electron-30-0
|
||||
* Currently, with Electron 35, this is Node.js 22.14.0.
|
||||
* https://www.electronjs.org/blog/electron-35-0
|
||||
*/
|
||||
"extends": "@tsconfig/node20/tsconfig.json",
|
||||
"extends": "@tsconfig/node22/tsconfig.json",
|
||||
|
||||
/* TSConfig docs: https://aka.ms/tsconfig.json */
|
||||
"compilerOptions": {
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
ajv "^6.12.0"
|
||||
ajv-keywords "^3.4.1"
|
||||
|
||||
"@electron/asar@3.2.18":
|
||||
"@electron/asar@3.2.18", "@electron/asar@^3.2.7":
|
||||
version "3.2.18"
|
||||
resolved "https://registry.yarnpkg.com/@electron/asar/-/asar-3.2.18.tgz#fa607f829209bab8b9e0ce6658d3fe81b2cba517"
|
||||
integrity sha512-2XyvMe3N3Nrs8cV39IKELRHTYUWFKrmqqSY1U+GMlc0jvqjIVnoxhNd2H4JolWQncbJi1DCvb5TNxZuI2fEjWg==
|
||||
@@ -34,15 +34,6 @@
|
||||
glob "^7.1.6"
|
||||
minimatch "^3.0.4"
|
||||
|
||||
"@electron/asar@^3.2.7":
|
||||
version "3.2.10"
|
||||
resolved "https://registry.yarnpkg.com/@electron/asar/-/asar-3.2.10.tgz#615cf346b734b23cafa4e0603551010bd0e50aa8"
|
||||
integrity sha512-mvBSwIBUeiRscrCeJE1LwctAriBj65eUDm0Pc11iE5gRwzkmsdbS7FnZ1XUWjpSeQWL1L5g12Fc/SchPM9DUOw==
|
||||
dependencies:
|
||||
commander "^5.0.0"
|
||||
glob "^7.1.6"
|
||||
minimatch "^3.0.4"
|
||||
|
||||
"@electron/fuses@^1.8.0":
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@electron/fuses/-/fuses-1.8.0.tgz#ad34d3cc4703b1258b83f6989917052cfc1490a0"
|
||||
@@ -177,10 +168,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.9.1.tgz#4a97e85e982099d6c7ee8410aacb55adaa576f06"
|
||||
integrity sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==
|
||||
|
||||
"@eslint/js@^9.22.0":
|
||||
version "9.22.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.22.0.tgz#4ff53649ded7cbce90b444b494c234137fa1aa3d"
|
||||
integrity sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==
|
||||
"@eslint/js@^9.25.0":
|
||||
version "9.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.25.0.tgz#4656b39de7cbf12fd66e7d54d9a26d05855b2a5a"
|
||||
integrity sha512-iWhsUS8Wgxz9AXNfvfOPFSW4VfMXdVhp1hjkZVhXCrpgh/aLcc45rX6MPu+tIVUWDw0HfNwth7O28M1xDxNf9w==
|
||||
|
||||
"@eslint/object-schema@^2.1.4":
|
||||
version "2.1.4"
|
||||
@@ -290,10 +281,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
|
||||
integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
|
||||
|
||||
"@tsconfig/node20@^20.1.4":
|
||||
version "20.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@tsconfig/node20/-/node20-20.1.4.tgz#3457d42eddf12d3bde3976186ab0cd22b85df928"
|
||||
integrity sha512-sqgsT69YFeLWf5NtJ4Xq/xAF8p4ZQHlmGW74Nu2tD4+g5fAsposc4ZfaaPixVu4y01BEiDCWLRDCvDM5JOsRxg==
|
||||
"@tsconfig/node22@^22.0.1":
|
||||
version "22.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@tsconfig/node22/-/node22-22.0.1.tgz#27e3ee9b359e31e5b94690bf2bad5a923c1d57d0"
|
||||
integrity sha512-VkgOa3n6jvs1p+r3DiwBqeEwGAwEvnVCg/hIjiANl5IEcqP3G0u5m8cBJspe1t9qjZRlZ7WFgqq5bJrGdgAKMg==
|
||||
|
||||
"@types/auto-launch@^5.0.5":
|
||||
version "5.0.5"
|
||||
@@ -346,25 +337,18 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.34.tgz#10964ba0dee6ac4cd462e2795b6bebd407303433"
|
||||
integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==
|
||||
|
||||
"@types/node@*":
|
||||
version "22.5.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.5.4.tgz#83f7d1f65bc2ed223bdbf57c7884f1d5a4fa84e8"
|
||||
integrity sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==
|
||||
"@types/node@*", "@types/node@^22.7.7":
|
||||
version "22.14.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.14.0.tgz#d3bfa3936fef0dbacd79ea3eb17d521c628bb47e"
|
||||
integrity sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA==
|
||||
dependencies:
|
||||
undici-types "~6.19.2"
|
||||
undici-types "~6.21.0"
|
||||
|
||||
"@types/node@^10.0.3":
|
||||
version "10.17.60"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b"
|
||||
integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==
|
||||
|
||||
"@types/node@^20.9.0":
|
||||
version "20.16.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.16.5.tgz#d43c7f973b32ffdf9aa7bd4f80e1072310fd7a53"
|
||||
integrity sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA==
|
||||
dependencies:
|
||||
undici-types "~6.19.2"
|
||||
|
||||
"@types/plist@^3.0.1":
|
||||
version "3.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/plist/-/plist-3.0.5.tgz#9a0c49c0f9886c8c8696a7904dd703f6284036e0"
|
||||
@@ -392,62 +376,62 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@typescript-eslint/eslint-plugin@8.26.1":
|
||||
version "8.26.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.26.1.tgz#3e48eb847924161843b092c87a9b65176b53782f"
|
||||
integrity sha512-2X3mwqsj9Bd3Ciz508ZUtoQQYpOhU/kWoUqIf49H8Z0+Vbh6UF/y0OEYp0Q0axOGzaBGs7QxRwq0knSQ8khQNA==
|
||||
"@typescript-eslint/eslint-plugin@8.30.1":
|
||||
version "8.30.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.30.1.tgz#9beb9e4fbfdde40410e96587cc56dded1942cdf1"
|
||||
integrity sha512-v+VWphxMjn+1t48/jO4t950D6KR8JaJuNXzi33Ve6P8sEmPr5k6CEXjdGwT6+LodVnEa91EQCtwjWNUCPweo+Q==
|
||||
dependencies:
|
||||
"@eslint-community/regexpp" "^4.10.0"
|
||||
"@typescript-eslint/scope-manager" "8.26.1"
|
||||
"@typescript-eslint/type-utils" "8.26.1"
|
||||
"@typescript-eslint/utils" "8.26.1"
|
||||
"@typescript-eslint/visitor-keys" "8.26.1"
|
||||
"@typescript-eslint/scope-manager" "8.30.1"
|
||||
"@typescript-eslint/type-utils" "8.30.1"
|
||||
"@typescript-eslint/utils" "8.30.1"
|
||||
"@typescript-eslint/visitor-keys" "8.30.1"
|
||||
graphemer "^1.4.0"
|
||||
ignore "^5.3.1"
|
||||
natural-compare "^1.4.0"
|
||||
ts-api-utils "^2.0.1"
|
||||
|
||||
"@typescript-eslint/parser@8.26.1":
|
||||
version "8.26.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.26.1.tgz#0e2f915a497519fc43f52cf2ecbfa607ff56f72e"
|
||||
integrity sha512-w6HZUV4NWxqd8BdeFf81t07d7/YV9s7TCWrQQbG5uhuvGUAW+fq1usZ1Hmz9UPNLniFnD8GLSsDpjP0hm1S4lQ==
|
||||
"@typescript-eslint/parser@8.30.1":
|
||||
version "8.30.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.30.1.tgz#8a9fa650b046e64656e21d4fdff86535b6a084b6"
|
||||
integrity sha512-H+vqmWwT5xoNrXqWs/fesmssOW70gxFlgcMlYcBaWNPIEWDgLa4W9nkSPmhuOgLnXq9QYgkZ31fhDyLhleCsAg==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "8.26.1"
|
||||
"@typescript-eslint/types" "8.26.1"
|
||||
"@typescript-eslint/typescript-estree" "8.26.1"
|
||||
"@typescript-eslint/visitor-keys" "8.26.1"
|
||||
"@typescript-eslint/scope-manager" "8.30.1"
|
||||
"@typescript-eslint/types" "8.30.1"
|
||||
"@typescript-eslint/typescript-estree" "8.30.1"
|
||||
"@typescript-eslint/visitor-keys" "8.30.1"
|
||||
debug "^4.3.4"
|
||||
|
||||
"@typescript-eslint/scope-manager@8.26.1":
|
||||
version "8.26.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.26.1.tgz#5e6ad0ac258ccf79462e91c3f43a3f1f7f31a6cc"
|
||||
integrity sha512-6EIvbE5cNER8sqBu6V7+KeMZIC1664d2Yjt+B9EWUXrsyWpxx4lEZrmvxgSKRC6gX+efDL/UY9OpPZ267io3mg==
|
||||
"@typescript-eslint/scope-manager@8.30.1":
|
||||
version "8.30.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.30.1.tgz#f99c7efd53b5ff9fb57e55be71eb855603fd80b7"
|
||||
integrity sha512-+C0B6ChFXZkuaNDl73FJxRYT0G7ufVPOSQkqkpM/U198wUwUFOtgo1k/QzFh1KjpBitaK7R1tgjVz6o9HmsRPg==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.26.1"
|
||||
"@typescript-eslint/visitor-keys" "8.26.1"
|
||||
"@typescript-eslint/types" "8.30.1"
|
||||
"@typescript-eslint/visitor-keys" "8.30.1"
|
||||
|
||||
"@typescript-eslint/type-utils@8.26.1":
|
||||
version "8.26.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.26.1.tgz#462f0bae09de72ac6e8e1af2ebe588c23224d7f8"
|
||||
integrity sha512-Kcj/TagJLwoY/5w9JGEFV0dclQdyqw9+VMndxOJKtoFSjfZhLXhYjzsQEeyza03rwHx2vFEGvrJWJBXKleRvZg==
|
||||
"@typescript-eslint/type-utils@8.30.1":
|
||||
version "8.30.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.30.1.tgz#151ee0529d6e6df19d8a3a23e81c809d2e4f6b1a"
|
||||
integrity sha512-64uBF76bfQiJyHgZISC7vcNz3adqQKIccVoKubyQcOnNcdJBvYOILV1v22Qhsw3tw3VQu5ll8ND6hycgAR5fEA==
|
||||
dependencies:
|
||||
"@typescript-eslint/typescript-estree" "8.26.1"
|
||||
"@typescript-eslint/utils" "8.26.1"
|
||||
"@typescript-eslint/typescript-estree" "8.30.1"
|
||||
"@typescript-eslint/utils" "8.30.1"
|
||||
debug "^4.3.4"
|
||||
ts-api-utils "^2.0.1"
|
||||
|
||||
"@typescript-eslint/types@8.26.1":
|
||||
version "8.26.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.26.1.tgz#d5978721670cff263348d5062773389231a64132"
|
||||
integrity sha512-n4THUQW27VmQMx+3P+B0Yptl7ydfceUj4ON/AQILAASwgYdZ/2dhfymRMh5egRUrvK5lSmaOm77Ry+lmXPOgBQ==
|
||||
"@typescript-eslint/types@8.30.1":
|
||||
version "8.30.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.30.1.tgz#20ff6d66ab3d8fe0533aeb7092a487393d53f925"
|
||||
integrity sha512-81KawPfkuulyWo5QdyG/LOKbspyyiW+p4vpn4bYO7DM/hZImlVnFwrpCTnmNMOt8CvLRr5ojI9nU1Ekpw4RcEw==
|
||||
|
||||
"@typescript-eslint/typescript-estree@8.26.1":
|
||||
version "8.26.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.26.1.tgz#eb0e4ce31753683d83be53441a409fd5f0b34afd"
|
||||
integrity sha512-yUwPpUHDgdrv1QJ7YQal3cMVBGWfnuCdKbXw1yyjArax3353rEJP1ZA+4F8nOlQ3RfS2hUN/wze3nlY+ZOhvoA==
|
||||
"@typescript-eslint/typescript-estree@8.30.1":
|
||||
version "8.30.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.30.1.tgz#f5c133e4a76a54d25607434f2c276409d7bec4ba"
|
||||
integrity sha512-kQQnxymiUy9tTb1F2uep9W6aBiYODgq5EMSk6Nxh4Z+BDUoYUSa029ISs5zTzKBFnexQEh71KqwjKnRz58lusQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.26.1"
|
||||
"@typescript-eslint/visitor-keys" "8.26.1"
|
||||
"@typescript-eslint/types" "8.30.1"
|
||||
"@typescript-eslint/visitor-keys" "8.30.1"
|
||||
debug "^4.3.4"
|
||||
fast-glob "^3.3.2"
|
||||
is-glob "^4.0.3"
|
||||
@@ -455,22 +439,22 @@
|
||||
semver "^7.6.0"
|
||||
ts-api-utils "^2.0.1"
|
||||
|
||||
"@typescript-eslint/utils@8.26.1":
|
||||
version "8.26.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.26.1.tgz#54cc58469955f25577f659753b71a0e117a0539f"
|
||||
integrity sha512-V4Urxa/XtSUroUrnI7q6yUTD3hDtfJ2jzVfeT3VK0ciizfK2q/zGC0iDh1lFMUZR8cImRrep6/q0xd/1ZGPQpg==
|
||||
"@typescript-eslint/utils@8.30.1":
|
||||
version "8.30.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.30.1.tgz#23d4824394765948fe73dc7113892f85fdc80efd"
|
||||
integrity sha512-T/8q4R9En2tcEsWPQgB5BQ0XJVOtfARcUvOa8yJP3fh9M/mXraLxZrkCfGb6ChrO/V3W+Xbd04RacUEqk1CFEQ==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.4.0"
|
||||
"@typescript-eslint/scope-manager" "8.26.1"
|
||||
"@typescript-eslint/types" "8.26.1"
|
||||
"@typescript-eslint/typescript-estree" "8.26.1"
|
||||
"@typescript-eslint/scope-manager" "8.30.1"
|
||||
"@typescript-eslint/types" "8.30.1"
|
||||
"@typescript-eslint/typescript-estree" "8.30.1"
|
||||
|
||||
"@typescript-eslint/visitor-keys@8.26.1":
|
||||
version "8.26.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.26.1.tgz#c5267fcc82795cf10280363023837deacad2647c"
|
||||
integrity sha512-AjOC3zfnxd6S4Eiy3jwktJPclqhFHNyd8L6Gycf9WUPoKZpgM5PjkxY1X7uSy61xVpiJDhhk7XT2NVsN3ALTWg==
|
||||
"@typescript-eslint/visitor-keys@8.30.1":
|
||||
version "8.30.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.30.1.tgz#510955ef1fb56e08da4b7953a3377258e5942e36"
|
||||
integrity sha512-aEhgas7aJ6vZnNFC7K4/vMGDGyOiqWcYZPpIWrTKuTAlsvDNKy2GFDqh9smL+iq069ZvR0YzEeq0B8NJlLzjFA==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.26.1"
|
||||
"@typescript-eslint/types" "8.30.1"
|
||||
eslint-visitor-keys "^4.2.0"
|
||||
|
||||
"@xmldom/xmldom@^0.8.8":
|
||||
@@ -571,23 +555,15 @@ any-shell-escape@^0.1.1:
|
||||
resolved "https://registry.yarnpkg.com/any-shell-escape/-/any-shell-escape-0.1.1.tgz#d55ab972244c71a9a5e1ab0879f30bf110806959"
|
||||
integrity sha512-36j4l5HVkboyRhIWgtMh1I9i8LTdFqVwDEHy1cp+QioJyKgAUG40X0W8s7jakWRta/Sjvm8mUG1fU6Tj8mWagQ==
|
||||
|
||||
anymatch@~3.1.2:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
|
||||
integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
|
||||
dependencies:
|
||||
normalize-path "^3.0.0"
|
||||
picomatch "^2.0.4"
|
||||
|
||||
app-builder-bin@5.0.0-alpha.12:
|
||||
version "5.0.0-alpha.12"
|
||||
resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-5.0.0-alpha.12.tgz#2daf82f8badc698e0adcc95ba36af4ff0650dc80"
|
||||
integrity sha512-j87o0j6LqPL3QRr8yid6c+Tt5gC7xNfYo6uQIQkorAC6MpeayVMZrEDzKmJJ/Hlv7EnOQpaRm53k6ktDYZyB6w==
|
||||
|
||||
app-builder-lib@26.0.0:
|
||||
version "26.0.0"
|
||||
resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-26.0.0.tgz#726b8b2c058f04f854aba70c7245d48454905980"
|
||||
integrity sha512-vZTt6Nc401IHBHISqspcO9tUF80ddOP5ehh2B4goLefM+zdT75CvuQUuqz7yzRgW16pHLqCvKMws0FbJQfLB5w==
|
||||
app-builder-lib@26.0.12:
|
||||
version "26.0.12"
|
||||
resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-26.0.12.tgz#2e33df936e0f78d4266b058ece90308ea981eefb"
|
||||
integrity sha512-+/CEPH1fVKf6HowBUs6LcAIoRcjeqgvAeoSE+cl7Y7LndyQ9ViGPYibNk7wmhMHzNgHIuIbw4nWADPO+4mjgWw==
|
||||
dependencies:
|
||||
"@develar/schema-utils" "~2.6.5"
|
||||
"@electron/asar" "3.2.18"
|
||||
@@ -599,16 +575,15 @@ app-builder-lib@26.0.0:
|
||||
"@malept/flatpak-bundler" "^0.4.0"
|
||||
"@types/fs-extra" "9.0.13"
|
||||
async-exit-hook "^2.0.1"
|
||||
bluebird-lst "^1.0.9"
|
||||
builder-util "26.0.0"
|
||||
builder-util-runtime "9.3.0"
|
||||
builder-util "26.0.11"
|
||||
builder-util-runtime "9.3.1"
|
||||
chromium-pickle-js "^0.2.0"
|
||||
config-file-ts "0.2.8-rc1"
|
||||
debug "^4.3.4"
|
||||
dotenv "^16.4.5"
|
||||
dotenv-expand "^11.0.6"
|
||||
ejs "^3.1.8"
|
||||
electron-publish "26.0.0"
|
||||
electron-publish "26.0.11"
|
||||
fs-extra "^10.1.0"
|
||||
hosted-git-info "^4.1.0"
|
||||
is-ci "^3.0.0"
|
||||
@@ -617,10 +592,12 @@ app-builder-lib@26.0.0:
|
||||
json5 "^2.2.3"
|
||||
lazy-val "^1.0.5"
|
||||
minimatch "^10.0.0"
|
||||
plist "3.1.0"
|
||||
resedit "^1.7.0"
|
||||
semver "^7.3.8"
|
||||
tar "^6.1.12"
|
||||
temp-file "^3.4.0"
|
||||
tiny-async-pool "1.3.0"
|
||||
|
||||
applescript@^1.0.0:
|
||||
version "1.0.0"
|
||||
@@ -688,11 +665,6 @@ base64-js@^1.3.1, base64-js@^1.5.1:
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
||||
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
|
||||
|
||||
binary-extensions@^2.0.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522"
|
||||
integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==
|
||||
|
||||
bl@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
|
||||
@@ -702,18 +674,6 @@ bl@^4.1.0:
|
||||
inherits "^2.0.4"
|
||||
readable-stream "^3.4.0"
|
||||
|
||||
bluebird-lst@^1.0.9:
|
||||
version "1.0.9"
|
||||
resolved "https://registry.yarnpkg.com/bluebird-lst/-/bluebird-lst-1.0.9.tgz#a64a0e4365658b9ab5fe875eb9dfb694189bb41c"
|
||||
integrity sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==
|
||||
dependencies:
|
||||
bluebird "^3.5.5"
|
||||
|
||||
bluebird@^3.5.5:
|
||||
version "3.7.2"
|
||||
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
|
||||
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
|
||||
|
||||
boolean@^3.0.1:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.2.0.tgz#9e5294af4e98314494cbb17979fa54ca159f116b"
|
||||
@@ -734,7 +694,7 @@ brace-expansion@^2.0.1:
|
||||
dependencies:
|
||||
balanced-match "^1.0.0"
|
||||
|
||||
braces@^3.0.3, braces@~3.0.2:
|
||||
braces@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
|
||||
integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
|
||||
@@ -759,24 +719,23 @@ buffer@^5.1.0, buffer@^5.5.0:
|
||||
base64-js "^1.3.1"
|
||||
ieee754 "^1.1.13"
|
||||
|
||||
builder-util-runtime@9.3.0:
|
||||
version "9.3.0"
|
||||
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-9.3.0.tgz#58d97c279bb8626a10d779e1cf22fea0eb25f5e8"
|
||||
integrity sha512-wR81YIybr41JITLSltwtTsZXkgTwcpBol7LGOyB5A8fKCcZaYLDWgUqDwmsjhlgADD6sGD5ieyzS/5wbL2l/qQ==
|
||||
builder-util-runtime@9.3.1:
|
||||
version "9.3.1"
|
||||
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-9.3.1.tgz#0daedde0f6d381f2a00a50a407b166fe7dca1a67"
|
||||
integrity sha512-2/egrNDDnRaxVwK3A+cJq6UOlqOdedGA7JPqCeJjN2Zjk1/QB/6QUi3b714ScIGS7HafFXTyzJEOr5b44I3kvQ==
|
||||
dependencies:
|
||||
debug "^4.3.4"
|
||||
sax "^1.2.4"
|
||||
|
||||
builder-util@26.0.0:
|
||||
version "26.0.0"
|
||||
resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-26.0.0.tgz#e5bc122f3e9e94fa2e3afd2e837e81ce9f177359"
|
||||
integrity sha512-iLN4R0UAzSz4MxPmz+6vnXMqaY5BMd2FSNlM9f7eHSRYqZrsoTHCSrd7W4Kr4qFIdUxLlRz3X2npATapXzomIg==
|
||||
builder-util@26.0.11:
|
||||
version "26.0.11"
|
||||
resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-26.0.11.tgz#ad85b92c93f2b976b973e1d87337e0c6813fcb8f"
|
||||
integrity sha512-xNjXfsldUEe153h1DraD0XvDOpqGR0L5eKFkdReB7eFW5HqysDZFfly4rckda6y9dF39N3pkPlOblcfHKGw+uA==
|
||||
dependencies:
|
||||
"7zip-bin" "~5.2.0"
|
||||
"@types/debug" "^4.1.6"
|
||||
app-builder-bin "5.0.0-alpha.12"
|
||||
bluebird-lst "^1.0.9"
|
||||
builder-util-runtime "9.3.0"
|
||||
builder-util-runtime "9.3.1"
|
||||
chalk "^4.1.2"
|
||||
cross-spawn "^7.0.6"
|
||||
debug "^4.3.4"
|
||||
@@ -789,6 +748,7 @@ builder-util@26.0.0:
|
||||
source-map-support "^0.5.19"
|
||||
stat-mode "^1.0.0"
|
||||
temp-file "^3.4.0"
|
||||
tiny-async-pool "1.3.0"
|
||||
|
||||
cacache@^16.1.0:
|
||||
version "16.1.3"
|
||||
@@ -850,20 +810,12 @@ chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2:
|
||||
ansi-styles "^4.1.0"
|
||||
supports-color "^7.1.0"
|
||||
|
||||
chokidar@^3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
|
||||
integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
|
||||
chokidar@^4.0.3:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30"
|
||||
integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==
|
||||
dependencies:
|
||||
anymatch "~3.1.2"
|
||||
braces "~3.0.2"
|
||||
glob-parent "~5.1.2"
|
||||
is-binary-path "~2.1.0"
|
||||
is-glob "~4.0.1"
|
||||
normalize-path "~3.0.0"
|
||||
readdirp "~3.6.0"
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
readdirp "^4.0.1"
|
||||
|
||||
chownr@^2.0.0:
|
||||
version "2.0.0"
|
||||
@@ -1046,16 +998,7 @@ cross-env@^7.0.3:
|
||||
dependencies:
|
||||
cross-spawn "^7.0.1"
|
||||
|
||||
cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2:
|
||||
version "7.0.3"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
|
||||
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
|
||||
dependencies:
|
||||
path-key "^3.1.0"
|
||||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
cross-spawn@^7.0.6:
|
||||
cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.6:
|
||||
version "7.0.6"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
|
||||
integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
|
||||
@@ -1153,14 +1096,14 @@ dir-compare@^4.2.0:
|
||||
minimatch "^3.0.5"
|
||||
p-limit "^3.1.0 "
|
||||
|
||||
dmg-builder@26.0.0:
|
||||
version "26.0.0"
|
||||
resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-26.0.0.tgz#6dc81be31f7ffe9f8a5fc77ce7f83eba33ae9aa7"
|
||||
integrity sha512-NyyTgm1U56ytpFvuGjj63PYug3v+oYYbPc8e08EiHP6G4TvMwYabmSzFtanfoO1iI7xOljpW/fW7SNCHHElsfw==
|
||||
dmg-builder@26.0.12:
|
||||
version "26.0.12"
|
||||
resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-26.0.12.tgz#6996ad0bab80a861c9a7b33ee9734d4f60566b46"
|
||||
integrity sha512-59CAAjAhTaIMCN8y9kD573vDkxbs1uhDcrFLHSgutYdPcGOU35Rf95725snvzEOy4BFB7+eLJ8djCNPmGwG67w==
|
||||
dependencies:
|
||||
app-builder-lib "26.0.0"
|
||||
builder-util "26.0.0"
|
||||
builder-util-runtime "9.3.0"
|
||||
app-builder-lib "26.0.12"
|
||||
builder-util "26.0.11"
|
||||
builder-util-runtime "9.3.1"
|
||||
fs-extra "^10.1.0"
|
||||
iconv-lite "^0.6.2"
|
||||
js-yaml "^4.1.0"
|
||||
@@ -1207,35 +1150,35 @@ ejs@^3.1.8:
|
||||
dependencies:
|
||||
jake "^10.8.5"
|
||||
|
||||
electron-builder@^26.0.0:
|
||||
version "26.0.0"
|
||||
resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-26.0.0.tgz#f5c03b049e3e9b0d3da7737f93bf1a830d1f17bb"
|
||||
integrity sha512-R1ZNTCtwjApiELkE4LTNIF6UkV+FMgyDIjILlsVvFak8Jr60cI9gu4q3lVALYzGBcFyzHKn2RPp6j0gl5kuVow==
|
||||
electron-builder@^26.0.12:
|
||||
version "26.0.12"
|
||||
resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-26.0.12.tgz#797af2e70efdd96c9ea5d8a8164b8728c90d65ff"
|
||||
integrity sha512-cD1kz5g2sgPTMFHjLxfMjUK5JABq3//J4jPswi93tOPFz6btzXYtK5NrDt717NRbukCUDOrrvmYVOWERlqoiXA==
|
||||
dependencies:
|
||||
app-builder-lib "26.0.0"
|
||||
builder-util "26.0.0"
|
||||
builder-util-runtime "9.3.0"
|
||||
app-builder-lib "26.0.12"
|
||||
builder-util "26.0.11"
|
||||
builder-util-runtime "9.3.1"
|
||||
chalk "^4.1.2"
|
||||
dmg-builder "26.0.0"
|
||||
dmg-builder "26.0.12"
|
||||
fs-extra "^10.1.0"
|
||||
is-ci "^3.0.0"
|
||||
lazy-val "^1.0.5"
|
||||
simple-update-notifier "2.0.0"
|
||||
yargs "^17.6.2"
|
||||
|
||||
electron-log@^5.3.2:
|
||||
version "5.3.2"
|
||||
resolved "https://registry.yarnpkg.com/electron-log/-/electron-log-5.3.2.tgz#76aa0091f9cbf0d304546ca6f271ebb6ad953bf4"
|
||||
integrity sha512-EFI5MFFEzFJU5gyhJNpKQhfGfrRP9IWzSu0sSxrWXasWKvVAOFgBySafX8W1pbPKa/w8/DDPu2bBBtVZJdDsnw==
|
||||
electron-log@^5.3.4:
|
||||
version "5.3.4"
|
||||
resolved "https://registry.yarnpkg.com/electron-log/-/electron-log-5.3.4.tgz#4117d9762d06dbed8e3b878cc468a92ce415a9e0"
|
||||
integrity sha512-QLj0EbsA5R5Yy4vjGlLe7m8hPNZ/Enp7c7a2WH7RUPr0hIOp0vDaC+6bJM0th6+uZKiZGGH5a2aKzvYp3eYwDQ==
|
||||
|
||||
electron-publish@26.0.0:
|
||||
version "26.0.0"
|
||||
resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-26.0.0.tgz#f37b9babe62885c2ee552af2817bf2048b566637"
|
||||
integrity sha512-0MOeYp1IRDj+jdkWluEVMer8fpc/htwWJZdGQUMbbbhgMnX8AvDdwHuR0UdaPFLDJ076E9YHd2urkeFyLm7PUQ==
|
||||
electron-publish@26.0.11:
|
||||
version "26.0.11"
|
||||
resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-26.0.11.tgz#92c9329a101af2836d9d228c82966eca1eee9a7b"
|
||||
integrity sha512-a8QRH0rAPIWH9WyyS5LbNvW9Ark6qe63/LqDB7vu2JXYpi0Gma5Q60Dh4tmTqhOBQt0xsrzD8qE7C+D7j+B24A==
|
||||
dependencies:
|
||||
"@types/fs-extra" "^9.0.11"
|
||||
builder-util "26.0.0"
|
||||
builder-util-runtime "9.3.0"
|
||||
builder-util "26.0.11"
|
||||
builder-util-runtime "9.3.1"
|
||||
chalk "^4.1.2"
|
||||
form-data "^4.0.0"
|
||||
fs-extra "^10.1.0"
|
||||
@@ -1250,12 +1193,12 @@ electron-store@^8.2.0:
|
||||
conf "^10.2.0"
|
||||
type-fest "^2.17.0"
|
||||
|
||||
electron-updater@^6.4.0:
|
||||
version "6.4.0"
|
||||
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-6.4.0.tgz#f413e5d1cb4fadde451eb7daa585ddb6332e2409"
|
||||
integrity sha512-E2fqL3GrVaXGZm2w95s4kJuPIF633pi5GhEy1/ReOHjDW9h/C0mZ1LXcLq0LsyQ4vyVj9UsdRb4E+Zy/d7RKUw==
|
||||
electron-updater@^6.6.2:
|
||||
version "6.6.2"
|
||||
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-6.6.2.tgz#3e65e044f1a99b00d61e200e24de8e709c69ce99"
|
||||
integrity sha512-Cr4GDOkbAUqRHP5/oeOmH/L2Bn6+FQPxVLZtPbcmKZC63a1F3uu5EefYOssgZXG3u/zBlubbJ5PJdITdMVggbw==
|
||||
dependencies:
|
||||
builder-util-runtime "9.3.0"
|
||||
builder-util-runtime "9.3.1"
|
||||
fs-extra "^10.1.0"
|
||||
js-yaml "^4.1.0"
|
||||
lazy-val "^1.0.5"
|
||||
@@ -1264,13 +1207,13 @@ electron-updater@^6.4.0:
|
||||
semver "^7.6.3"
|
||||
tiny-typed-emitter "^2.1.0"
|
||||
|
||||
electron@^34.3.4:
|
||||
version "34.3.4"
|
||||
resolved "https://registry.yarnpkg.com/electron/-/electron-34.3.4.tgz#3acbcb5fe1aabfa926dddce23de28da9e6023cc5"
|
||||
integrity sha512-bIsjBh5EN229K4orJpVfjLb7JEoCYkUVg3tS981E1elEjvhBITqwm+K1j9goEqMIlxqYWgogREYpSZRQ+aLWgQ==
|
||||
electron@^35.2.0:
|
||||
version "35.2.0"
|
||||
resolved "https://registry.yarnpkg.com/electron/-/electron-35.2.0.tgz#4701f455a2bc41c992cc529b42203c530223dcd8"
|
||||
integrity sha512-GHda7oCkN0pA23qzah735DEbRa06IPwlzP3uvjAmf9af8gxdj5i93JEHeQVGVmSVpd7sSb1pfecs9nz7B1q5ag==
|
||||
dependencies:
|
||||
"@electron/get" "^2.0.0"
|
||||
"@types/node" "^20.9.0"
|
||||
"@types/node" "^22.7.7"
|
||||
extract-zip "^2.0.1"
|
||||
|
||||
emoji-regex@^8.0.0:
|
||||
@@ -1342,12 +1285,7 @@ eslint-visitor-keys@^3.3.0:
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
|
||||
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
||||
|
||||
eslint-visitor-keys@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz#e3adc021aa038a2a8e0b2f8b0ce8f66b9483b1fb"
|
||||
integrity sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==
|
||||
|
||||
eslint-visitor-keys@^4.2.0:
|
||||
eslint-visitor-keys@^4.0.0, eslint-visitor-keys@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45"
|
||||
integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==
|
||||
@@ -1621,11 +1559,6 @@ fs.realpath@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
||||
|
||||
fsevents@~2.3.2:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
|
||||
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
|
||||
|
||||
function-bind@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
|
||||
@@ -1664,7 +1597,7 @@ git-hooks-list@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/git-hooks-list/-/git-hooks-list-3.1.0.tgz#386dc531dcc17474cf094743ff30987a3d3e70fc"
|
||||
integrity sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==
|
||||
|
||||
glob-parent@^5.1.2, glob-parent@~5.1.2:
|
||||
glob-parent@^5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
|
||||
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
|
||||
@@ -1942,13 +1875,6 @@ ip-address@^9.0.5:
|
||||
jsbn "1.1.0"
|
||||
sprintf-js "^1.1.3"
|
||||
|
||||
is-binary-path@~2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
|
||||
integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
|
||||
dependencies:
|
||||
binary-extensions "^2.0.0"
|
||||
|
||||
is-ci@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.1.tgz#db6ecbed1bd659c43dac0f45661e7674103d1867"
|
||||
@@ -1973,7 +1899,7 @@ is-fullwidth-code-point@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
|
||||
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
|
||||
|
||||
is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
|
||||
is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
|
||||
integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
|
||||
@@ -2185,10 +2111,10 @@ lru-cache@^10.2.0:
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119"
|
||||
integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==
|
||||
|
||||
lru-cache@^11.0.2:
|
||||
version "11.0.2"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.0.2.tgz#fbd8e7cf8211f5e7e5d91905c415a3f55755ca39"
|
||||
integrity sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==
|
||||
lru-cache@^11.1.0:
|
||||
version "11.1.0"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.1.0.tgz#afafb060607108132dbc1cf8ae661afb69486117"
|
||||
integrity sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==
|
||||
|
||||
lru-cache@^6.0.0:
|
||||
version "6.0.0"
|
||||
@@ -2459,11 +2385,6 @@ nopt@^6.0.0:
|
||||
dependencies:
|
||||
abbrev "^1.0.0"
|
||||
|
||||
normalize-path@^3.0.0, normalize-path@~3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
||||
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
|
||||
|
||||
normalize-url@^6.0.1:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a"
|
||||
@@ -2633,7 +2554,7 @@ pend@~1.2.0:
|
||||
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
|
||||
integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==
|
||||
|
||||
picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
|
||||
picomatch@^2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
|
||||
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
||||
@@ -2650,7 +2571,7 @@ pkg-up@^3.1.0:
|
||||
dependencies:
|
||||
find-up "^3.0.0"
|
||||
|
||||
plist@^3.0.4, plist@^3.0.5, plist@^3.1.0:
|
||||
plist@3.1.0, plist@^3.0.4, plist@^3.0.5, plist@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/plist/-/plist-3.1.0.tgz#797a516a93e62f5bde55e0b9cc9c967f860893c9"
|
||||
integrity sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==
|
||||
@@ -2744,12 +2665,10 @@ readable-stream@^3.0.2, readable-stream@^3.4.0:
|
||||
string_decoder "^1.1.1"
|
||||
util-deprecate "^1.0.1"
|
||||
|
||||
readdirp@~3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
|
||||
integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
|
||||
dependencies:
|
||||
picomatch "^2.2.1"
|
||||
readdirp@^4.0.1:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d"
|
||||
integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==
|
||||
|
||||
rechoir@^0.6.2:
|
||||
version "0.6.2"
|
||||
@@ -2886,6 +2805,11 @@ semver-compare@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
|
||||
integrity sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==
|
||||
|
||||
semver@^5.5.0:
|
||||
version "5.7.2"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
|
||||
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
|
||||
|
||||
semver@^6.2.0:
|
||||
version "6.3.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
||||
@@ -3133,6 +3057,13 @@ text-table@^0.2.0:
|
||||
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
|
||||
integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
|
||||
|
||||
tiny-async-pool@1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/tiny-async-pool/-/tiny-async-pool-1.3.0.tgz#c013e1b369095e7005db5595f95e646cca6ef8a5"
|
||||
integrity sha512-01EAw5EDrcVrdgyCLgoSPvqznC0sVxDSVeiOz09FUpjh71G79VCqneOr+xvt7T1r76CF6ZZfPjHorN2+d+3mqA==
|
||||
dependencies:
|
||||
semver "^5.5.0"
|
||||
|
||||
tiny-typed-emitter@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz#b3b027fdd389ff81a152c8e847ee2f5be9fad7b5"
|
||||
@@ -3209,29 +3140,24 @@ typedarray@^0.0.6:
|
||||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||
integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==
|
||||
|
||||
typescript-eslint@^8.26.1:
|
||||
version "8.26.1"
|
||||
resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.26.1.tgz#d17a638a7543bc535157b83cdf5876513c71493b"
|
||||
integrity sha512-t/oIs9mYyrwZGRpDv3g+3K6nZ5uhKEMt2oNmAPwaY4/ye0+EH4nXIPYNtkYFS6QHm+1DFg34DbglYBz5P9Xysg==
|
||||
typescript-eslint@^8.30.1:
|
||||
version "8.30.1"
|
||||
resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.30.1.tgz#c9ed49b459bd98e325fb78e2c86943dce7bb1cc0"
|
||||
integrity sha512-D7lC0kcehVH7Mb26MRQi64LMyRJsj3dToJxM1+JVTl53DQSV5/7oUGWQLcKl1C1KnoVHxMMU2FNQMffr7F3Row==
|
||||
dependencies:
|
||||
"@typescript-eslint/eslint-plugin" "8.26.1"
|
||||
"@typescript-eslint/parser" "8.26.1"
|
||||
"@typescript-eslint/utils" "8.26.1"
|
||||
"@typescript-eslint/eslint-plugin" "8.30.1"
|
||||
"@typescript-eslint/parser" "8.30.1"
|
||||
"@typescript-eslint/utils" "8.30.1"
|
||||
|
||||
typescript@^5.4.3:
|
||||
version "5.5.4"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba"
|
||||
integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==
|
||||
typescript@^5.4.3, typescript@^5.8.3:
|
||||
version "5.8.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e"
|
||||
integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==
|
||||
|
||||
typescript@^5.8.2:
|
||||
version "5.8.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.2.tgz#8170b3702f74b79db2e5a96207c15e65807999e4"
|
||||
integrity sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==
|
||||
|
||||
undici-types@~6.19.2:
|
||||
version "6.19.8"
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02"
|
||||
integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==
|
||||
undici-types@~6.21.0:
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb"
|
||||
integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==
|
||||
|
||||
unique-filename@^2.0.0:
|
||||
version "2.0.1"
|
||||
|
||||
@@ -142,6 +142,7 @@ export const sidebar = [
|
||||
text: "Video streaming",
|
||||
link: "/photos/faq/video-streaming",
|
||||
},
|
||||
{ text: "Desktop", link: "/photos/faq/desktop" },
|
||||
{ text: "Misc", link: "/photos/faq/misc" },
|
||||
],
|
||||
},
|
||||
@@ -237,56 +238,98 @@ export const sidebar = [
|
||||
items: [
|
||||
{ text: "Getting started", link: "/self-hosting/" },
|
||||
{
|
||||
text: "System requirements",
|
||||
link: "/self-hosting/guides/system-requirements",
|
||||
text: "Connect to custom server",
|
||||
link: "/self-hosting/guides/custom-server/",
|
||||
},
|
||||
{
|
||||
text: "Creating Accounts",
|
||||
link: "/self-hosting/creating-accounts",
|
||||
},
|
||||
{
|
||||
text: "Reverse Proxy",
|
||||
link: "/self-hosting/reverse-proxy",
|
||||
},
|
||||
{
|
||||
text: "Building your museum.yaml",
|
||||
link: "/self-hosting/museum",
|
||||
},
|
||||
{
|
||||
text: "Configuring S3",
|
||||
link: "/self-hosting/guides/configuring-s3",
|
||||
},
|
||||
{
|
||||
text: "Guides",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: "Introduction", link: "/self-hosting/guides/" },
|
||||
{
|
||||
text: "Connect to custom server",
|
||||
link: "/self-hosting/guides/custom-server/",
|
||||
},
|
||||
{
|
||||
text: "Hosting the web app",
|
||||
link: "/self-hosting/guides/web-app",
|
||||
},
|
||||
{
|
||||
text: "Configuring S3",
|
||||
link: "/self-hosting/guides/configuring-s3",
|
||||
},
|
||||
{
|
||||
text: "Hosting Ente with external S3 (Community)",
|
||||
link: "/self-hosting/guides/external-s3",
|
||||
},
|
||||
{
|
||||
text: "DB migration",
|
||||
link: "/self-hosting/guides/db-migration",
|
||||
text: "Hosting Ente from source",
|
||||
link: "/self-hosting/guides/from-source",
|
||||
},
|
||||
{
|
||||
text: "Hosting Ente without Docker",
|
||||
link: "/self-hosting/guides/standalone-ente",
|
||||
},
|
||||
{
|
||||
text: "Ente via Tailscale (Community)",
|
||||
link: "/self-hosting/guides/Tailscale.md",
|
||||
text: "Administering your server",
|
||||
link: "/self-hosting/guides/admin",
|
||||
},
|
||||
{
|
||||
text: "Configure CLI for Self Hosted Instance",
|
||||
link: "/self-hosting/guides/selfhost-cli",
|
||||
},
|
||||
{
|
||||
text: "Administering your server",
|
||||
link: "/self-hosting/guides/admin",
|
||||
text: "DB migration",
|
||||
link: "/self-hosting/guides/db-migration",
|
||||
},
|
||||
|
||||
{
|
||||
text: "Mobile build",
|
||||
link: "/self-hosting/guides/mobile-build",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Troubleshooting",
|
||||
items: [
|
||||
{
|
||||
text: "General",
|
||||
link: "/self-hosting/troubleshooting/misc",
|
||||
},
|
||||
{
|
||||
text: "Bucket CORS",
|
||||
link: '/self-hosting/troubleshooting/bucket-cors'
|
||||
},
|
||||
{
|
||||
text: "Uploads",
|
||||
link: "/self-hosting/troubleshooting/uploads",
|
||||
},
|
||||
{
|
||||
text: "Docker / quickstart",
|
||||
link: "/self-hosting/troubleshooting/docker",
|
||||
},
|
||||
{
|
||||
text: "Yarn",
|
||||
link: "/self-hosting/troubleshooting/yarn",
|
||||
},
|
||||
{
|
||||
text: "Ente CLI Secrets",
|
||||
link: "/self-hosting/troubleshooting/keyring",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Community Guides",
|
||||
items :[
|
||||
{
|
||||
text: "Ente via Tailscale",
|
||||
link: "/self-hosting/guides/Tailscale",
|
||||
},
|
||||
{
|
||||
text: "Ente with External S3",
|
||||
link: "/self-hosting/guides/external-s3",
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
text: "FAQ",
|
||||
items: [
|
||||
@@ -305,27 +348,6 @@ export const sidebar = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Troubleshooting",
|
||||
items: [
|
||||
{
|
||||
text: "Uploads",
|
||||
link: "/self-hosting/troubleshooting/uploads",
|
||||
},
|
||||
{
|
||||
text: "Docker",
|
||||
link: "/self-hosting/troubleshooting/docker",
|
||||
},
|
||||
{
|
||||
text: "Yarn",
|
||||
link: "/self-hosting/troubleshooting/yarn",
|
||||
},
|
||||
{
|
||||
text: "Ente CLI Secrets",
|
||||
link: "/self-hosting/troubleshooting/keyring",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -10,8 +10,8 @@ A guide written by Green, an ente.io lover
|
||||
> [!WARNING]
|
||||
>
|
||||
> Authy has dropped all support for its desktop apps. It is no longer possible
|
||||
> to export data from Authy using methods 1 and 2. You will either need a rooted
|
||||
> android phone or you will need to reconfigure 2FA for each of your accounts.
|
||||
> to export data from Authy using methods 1 and 2. You will need either an iOS device
|
||||
> and computer (method 4) or a rooted Android phone (method 3) to follow this guide.
|
||||
|
||||
---
|
||||
|
||||
@@ -202,7 +202,15 @@ This uses the tool [Aegis Authenticator](https://getaegis.app/) from
|
||||
6. Then export the codes from Aegis Authenticator to `json` or `txt` using the
|
||||
"Export to file" option in the "Import & Export" menu.
|
||||
|
||||
## Importing to Ente Authenticator (Method 1, method 2.1)
|
||||
## Method 4: Authy-iOS-MiTM
|
||||
|
||||
**Who should use this?** Technical iOS users of Authy that cannot export their tokens with methods 1 or 2 (due to those methods being patched) or method 3 (due to that method requiring a rooted Android device).
|
||||
|
||||
This method works by intercepting the data the Authy app receives while logging in for the first time, which contains your encrypted authenticator tokens. After the encrypted authenticator tokens are dumped, you can decrypt them using your backup password and convert them to an Ente token file.
|
||||
|
||||
For an up-to-date guide of how to retrieve the encrypted authenticator tokens and decrypt them, please see [Authy-iOS-MiTM](https://github.com/AlexTech01/Authy-iOS-MiTM). To convert the `decrypted_tokens.json` file from that guide into a format Ente Authenticator can recognize, use [this](https://gist.github.com/gboudreau/94bb0c11a6209c82418d01a59d958c93?permalink_comment_id=5317087#gistcomment-5317087) Python script. Once you have the `ente_auth_import.plain` file from that script, transfer it to your device and follow the instructions below to import it into Ente Authenticator.
|
||||
|
||||
## Importing to Ente Authenticator (Method 1, method 2.1, method 4)
|
||||
|
||||
1. Copy the TXT file to one of your devices with Ente Authenticator.
|
||||
2. Log in to your account (if you haven't already), or press "Use without
|
||||
|
||||
38
docs/docs/photos/faq/desktop.md
Normal file
@@ -0,0 +1,38 @@
|
||||
---
|
||||
title: Desktop app FAQ
|
||||
description: An assortment of frequently asked questions about Ente Photos desktop app
|
||||
---
|
||||
|
||||
# Desktop app FAQ
|
||||
|
||||
### App updates
|
||||
|
||||
**How do I ensure that the Ente desktop app stays up to date on my system?**
|
||||
|
||||
Ente desktop includes an auto-update feature, ensuring that whenever updates are
|
||||
deployed, the app will automatically download and install them. You don't need
|
||||
to manually update the software.
|
||||
|
||||
### Upload errors
|
||||
|
||||
**How do I identify which files experienced upload issues within the desktop app?**
|
||||
|
||||
Check the sections within the upload progress bar for "Failed Uploads," "Ignored
|
||||
Uploads," and "Unsuccessful Uploads."
|
||||
|
||||
### Icon update
|
||||
|
||||
**I updated my Linux app, but it is still showing the old icon**
|
||||
|
||||
You might need to update the icon cache of your Linux desktop environment.
|
||||
|
||||
The easiest way to fix this would be to restart your computer (or logout and
|
||||
login again into your desktop environment). It should also be possible to do
|
||||
this without restarting, but the steps for refreshing the icon cache would then
|
||||
be specific to your distro (e.g. `xdg-desktop-menu forceupdate`).
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> If you're using an AppImage and not seeing the icon, you'll need to [enable
|
||||
> AppImage desktop
|
||||
> integration](/photos/troubleshooting/desktop-install/#appimage-desktop-integration).
|
||||
@@ -7,10 +7,9 @@ description: Frequently asked questions about keeping extra backups of your data
|
||||
|
||||
## How can I backup my data in a local drive outside Ente?
|
||||
|
||||
Yes! You can use our CLI tool or our desktop app to set up exports of your data
|
||||
to your local drive. This way, you can use Ente in your day to day use, but will
|
||||
have an additional guarantee that a copy of your original photos and videos are
|
||||
always available in normal directories and files.
|
||||
You can use our CLI tool or our desktop app to set up exports of your data
|
||||
to your local drive. This way, you can use Ente in your day to day use, with an additional guarantee that a copy of your original photos and videos are
|
||||
always available on your machine.
|
||||
|
||||
- You can use [Ente's CLI](https://github.com/ente-io/ente/tree/main/cli#export)
|
||||
to export your data in a cron job to a location of your choice. The exports
|
||||
|
||||
@@ -86,23 +86,12 @@ On Ente's mobile apps, you can add photos from an album that's shared with you,
|
||||
into one of your own albums. This will create a copy of the item that you fully
|
||||
own, and will count against your storage quota.
|
||||
|
||||
## How do I ensure that the Ente desktop app stays up to date on my system?
|
||||
|
||||
Ente desktop includes an auto-update feature, ensuring that whenever updates are
|
||||
deployed, the app will automatically download and install them. You don't need
|
||||
to manually update the software.
|
||||
|
||||
## Can I sync a folder containing multiple subfolders, each representing an album?
|
||||
|
||||
Yes, when you drag and drop the folder onto the desktop app, the app will detect
|
||||
the multiple folders and prompt you to choose whether you want to create a
|
||||
single album or separate albums for each folder.
|
||||
|
||||
## How do I identify which files experienced upload issues within the desktop app?
|
||||
|
||||
Check the sections within the upload progress bar for "Failed Uploads," "Ignored
|
||||
Uploads," and "Unsuccessful Uploads."
|
||||
|
||||
## How do I keep NAS and Ente photos synced?
|
||||
|
||||
Please try using our CLI to pull data into your NAS
|
||||
@@ -137,6 +126,7 @@ To do this, open the photo, tap the (i) button, and enter your description.
|
||||
If the app finds exact duplicates, it will show them in the deduplication. When you delete a duplicate, the app keeps one copy and creates a symlink for the other duplicate. This helps save storage space.
|
||||
|
||||
### What happens if I lose access to my email address? Can I use my recovery key to bypass email verification?
|
||||
No, the recovery key does not bypass email verification. For security reasons, we do not disable or bypass email verification unless the account owner reaches out to us and successfully verifies their identity by providing details about their account.
|
||||
No, the recovery key does not bypass email verification. For security reasons, we do not disable or bypass email verification unless the account owner reaches out to us and successfully verifies their identity by providing details about their account.
|
||||
|
||||
If you lose access to your email, please contact our support team at support@ente.io
|
||||
If you lose access to your email, please contact our support team at
|
||||
support@ente.io
|
||||
|
||||