Compare commits
1399 Commits
v0.2.3
...
dependenci
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3271c96531 | ||
|
|
05fa6b9aba | ||
|
|
7edd7f27cb | ||
|
|
4a6b12eda1 | ||
|
|
a354e1a0eb | ||
|
|
c2c419522a | ||
|
|
7a3cc7d242 | ||
|
|
bd6f02f6af | ||
|
|
bd33728fd7 | ||
|
|
8400ee8a3d | ||
|
|
80ee7aef8e | ||
|
|
41762be3a5 | ||
|
|
605dda7b76 | ||
|
|
8d6e3b5a58 | ||
|
|
53920fc368 | ||
|
|
96d10423d9 | ||
|
|
42be9b5b51 | ||
|
|
0add041516 | ||
|
|
dee76cac8d | ||
|
|
9646fab22c | ||
|
|
a54e9cb244 | ||
|
|
f8339c7a9a | ||
|
|
9e2c864117 | ||
|
|
e1ccd71455 | ||
|
|
0e82426ea1 | ||
|
|
6c7afd168a | ||
|
|
e014fdf3da | ||
|
|
2074da05c8 | ||
|
|
84cd87b70a | ||
|
|
75f87044f6 | ||
|
|
f71b51e64a | ||
|
|
9d741cdd63 | ||
|
|
56be17000a | ||
|
|
f6aacbc31d | ||
|
|
ad4b57c327 | ||
|
|
3794b2f0de | ||
|
|
e0e8412728 | ||
|
|
05b8175aad | ||
|
|
339c89dd1c | ||
|
|
402299e9c8 | ||
|
|
d0e8f450fd | ||
|
|
e97b1ccd7a | ||
|
|
68691b91ef | ||
|
|
213d417481 | ||
|
|
2ec841eb61 | ||
|
|
60b5c54be1 | ||
|
|
448412a191 | ||
|
|
e06327936e | ||
|
|
5f044e1aed | ||
|
|
d90fb6fc9b | ||
|
|
1c583d2ea9 | ||
|
|
ddab131102 | ||
|
|
3b06cf8a2a | ||
|
|
c5d7c29f3d | ||
|
|
26af860eac | ||
|
|
ec9852eb98 | ||
|
|
f2b8c6d0ca | ||
|
|
2cf7a048cf | ||
|
|
3dbb71a076 | ||
|
|
ddf6760543 | ||
|
|
a6fa323f33 | ||
|
|
2df8f1acdb | ||
|
|
74a3290abc | ||
|
|
ab306d21f3 | ||
|
|
1bd7795851 | ||
|
|
302c142346 | ||
|
|
7c254c9b45 | ||
|
|
b1c458359d | ||
|
|
2d925c62f5 | ||
|
|
ef4711987f | ||
|
|
8910dfaecf | ||
|
|
e8b2e79c7d | ||
|
|
333ee1e1f7 | ||
|
|
ba013bbe96 | ||
|
|
636e66fe7a | ||
|
|
372a45e667 | ||
|
|
ab6b796ce2 | ||
|
|
71e6c02897 | ||
|
|
3edeaa7038 | ||
|
|
f2f75d4015 | ||
|
|
69adade738 | ||
|
|
1bd88828e4 | ||
|
|
977fcbe6cd | ||
|
|
aa76a5c436 | ||
|
|
ea5fad428d | ||
|
|
0e1e27b35a | ||
|
|
d41f67a156 | ||
|
|
6f10dec808 | ||
|
|
9b79da2cdf | ||
|
|
c11b8519f1 | ||
|
|
b9e23a0b59 | ||
|
|
75d41b6fe5 | ||
|
|
4256590735 | ||
|
|
462fb05ea8 | ||
|
|
812dbfd836 | ||
|
|
cfca837777 | ||
|
|
ac5fb1948a | ||
|
|
22d8b73625 | ||
|
|
edde40c298 | ||
|
|
50ade92238 | ||
|
|
b598d00aef | ||
|
|
97bee17e4e | ||
|
|
6aa5c79332 | ||
|
|
7c5ce756f9 | ||
|
|
43d53a9ffa | ||
|
|
e6589bee5b | ||
|
|
9f94cad615 | ||
|
|
7778d9f773 | ||
|
|
564bd55147 | ||
|
|
a7ff806522 | ||
|
|
ac3b074d66 | ||
|
|
da949c2604 | ||
|
|
20a9775dc6 | ||
|
|
8ec19e058f | ||
|
|
a5c4549722 | ||
|
|
c7d302aa16 | ||
|
|
77ac565ff3 | ||
|
|
2e6f834a50 | ||
|
|
5b044cca9e | ||
|
|
2ab5623809 | ||
|
|
2d07f0d77c | ||
|
|
8ba7f9f702 | ||
|
|
460ac7a86b | ||
|
|
f93a1ab3eb | ||
|
|
6b02696aa8 | ||
|
|
25f20d6a85 | ||
|
|
8387964bae | ||
|
|
926278617f | ||
|
|
1933737a0c | ||
|
|
b3e5288bde | ||
|
|
ed6e966b2f | ||
|
|
9315fe36b6 | ||
|
|
41fbf5ba36 | ||
|
|
40db481453 | ||
|
|
1b5e295744 | ||
|
|
b42a52f7f6 | ||
|
|
8268df84d0 | ||
|
|
eb6fa5f1f1 | ||
|
|
025c8856ed | ||
|
|
ed421445e9 | ||
|
|
0cda07106b | ||
|
|
f335941b62 | ||
|
|
f0719f8bde | ||
|
|
27fe28661c | ||
|
|
bb13b12de6 | ||
|
|
1117e28b2e | ||
|
|
0f48873c25 | ||
|
|
faf61b4af3 | ||
|
|
e29ce93d32 | ||
|
|
38ab68492e | ||
|
|
53b1576e5f | ||
|
|
2835e79973 | ||
|
|
8e4d7e989b | ||
|
|
603c6b826c | ||
|
|
51bcc77cb3 | ||
|
|
a30d07b924 | ||
|
|
11faa5fe39 | ||
|
|
ce8383b26f | ||
|
|
bd8f07c90a | ||
|
|
fee077bebd | ||
|
|
558f4d93ba | ||
|
|
e77d126349 | ||
|
|
cd8667d6de | ||
|
|
8a2d06d010 | ||
|
|
92741fc733 | ||
|
|
1cff162649 | ||
|
|
f59be465ea | ||
|
|
27305317ce | ||
|
|
8378320e50 | ||
|
|
86a69952db | ||
|
|
e212ebfdb9 | ||
|
|
f235125d48 | ||
|
|
8efa815eb9 | ||
|
|
e54d42576b | ||
|
|
1e18539862 | ||
|
|
673fdf4721 | ||
|
|
57d6bfba51 | ||
|
|
8fa23aecda | ||
|
|
f9c10533e8 | ||
|
|
c891c3723e | ||
|
|
a0625ef2e7 | ||
|
|
b2774abb54 | ||
|
|
fa089bbc40 | ||
|
|
8437d1763f | ||
|
|
0532b0f9df | ||
|
|
5f8eb853f0 | ||
|
|
9125a85382 | ||
|
|
5b3dc44c72 | ||
|
|
ee5147f111 | ||
|
|
f67137fd5e | ||
|
|
b67db4a896 | ||
|
|
067018828c | ||
|
|
e990530ada | ||
|
|
45f863a72a | ||
|
|
519febbeb2 | ||
|
|
854b1a4caf | ||
|
|
08eb95e73a | ||
|
|
66f8fbf08c | ||
|
|
86a30bbb29 | ||
|
|
966c453c27 | ||
|
|
c7bcaf0193 | ||
|
|
0ac91e36a0 | ||
|
|
6f1299ce9e | ||
|
|
83ca29d649 | ||
|
|
d0206044dc | ||
|
|
d4623e4175 | ||
|
|
68ef03377d | ||
|
|
d3f9d3d033 | ||
|
|
a6ccd04471 | ||
|
|
0fd8174e77 | ||
|
|
ebc63f479a | ||
|
|
570c39c20a | ||
|
|
1d57257cf5 | ||
|
|
82d7baee0b | ||
|
|
1d91e1f1f7 | ||
|
|
15e8894614 | ||
|
|
0ae96918e9 | ||
|
|
e970880059 | ||
|
|
69ae86aba8 | ||
|
|
8142e1be49 | ||
|
|
cbc7612451 | ||
|
|
09e6a7b7cc | ||
|
|
082e35668a | ||
|
|
c9e78c837b | ||
|
|
2d171db672 | ||
|
|
a8b11abec8 | ||
|
|
b08333dccd | ||
|
|
98bad48971 | ||
|
|
53375bb536 | ||
|
|
88798093e1 | ||
|
|
45a28751af | ||
|
|
1670c44464 | ||
|
|
a286ac85dc | ||
|
|
1606adc0ab | ||
|
|
b4ce557d92 | ||
|
|
2ba7fff8d4 | ||
|
|
98efc93610 | ||
|
|
2680507eae | ||
|
|
df72392ad2 | ||
|
|
a6acb15a00 | ||
|
|
ba7242a815 | ||
|
|
99740c1324 | ||
|
|
c04b20d1fa | ||
|
|
e127067878 | ||
|
|
6f03b72368 | ||
|
|
7bd3ee9340 | ||
|
|
c94db606e5 | ||
|
|
4d2474226b | ||
|
|
1ffc4f538b | ||
|
|
6702ac957b | ||
|
|
ba42b2e77d | ||
|
|
fba18ca40a | ||
|
|
3a2a7a1476 | ||
|
|
3c6d6b90bc | ||
|
|
47dc9ee304 | ||
|
|
0045bf206c | ||
|
|
669a1a6953 | ||
|
|
e28452cc7b | ||
|
|
5ceac03db1 | ||
|
|
96215e5950 | ||
|
|
7a030b9224 | ||
|
|
e743478a4d | ||
|
|
bc29c80d44 | ||
|
|
82b8a474d7 | ||
|
|
99851b297d | ||
|
|
e3a500e12c | ||
|
|
378666e3cc | ||
|
|
b65ad1ebd7 | ||
|
|
933a821b5f | ||
|
|
159337ddbd | ||
|
|
2e25a4333a | ||
|
|
64fafb0795 | ||
|
|
5927e0bb3b | ||
|
|
e21596db83 | ||
|
|
8a608c3c3e | ||
|
|
76f9db8516 | ||
|
|
90f4809b7c | ||
|
|
3ff1af9fd6 | ||
|
|
711dd520f7 | ||
|
|
99503c836a | ||
|
|
2c8bc51862 | ||
|
|
5e7aa15232 | ||
|
|
d0761869b6 | ||
|
|
bb99b89228 | ||
|
|
7b88beb0b5 | ||
|
|
82c630bd0e | ||
|
|
bb4f11e1b8 | ||
|
|
3182d20b7c | ||
|
|
a6f15e2474 | ||
|
|
0c3f03680c | ||
|
|
a66e8dfc9f | ||
|
|
556232aac4 | ||
|
|
7fcfaadd91 | ||
|
|
18d388e1e2 | ||
|
|
7de6622d74 | ||
|
|
9af1f90990 | ||
|
|
15ab43963d | ||
|
|
6b7465a4b0 | ||
|
|
d64bdf02de | ||
|
|
4a2c94993a | ||
|
|
86c318d86b | ||
|
|
bffc1ad41d | ||
|
|
2a685c116f | ||
|
|
0e271d2924 | ||
|
|
7127c4d590 | ||
|
|
a82929996b | ||
|
|
3f01f52c7b | ||
|
|
9c94494622 | ||
|
|
c8a508f35c | ||
|
|
4ec73ef1c3 | ||
|
|
3465b79e5b | ||
|
|
726a0a33ae | ||
|
|
ba05810d80 | ||
|
|
10bb53e7de | ||
|
|
dd8a083546 | ||
|
|
84131a71c9 | ||
|
|
4909a11896 | ||
|
|
4069357b81 | ||
|
|
e6e87bcc40 | ||
|
|
7ba22045e8 | ||
|
|
d4040b61c4 | ||
|
|
7534f8fc37 | ||
|
|
7ced009e92 | ||
|
|
cc13c71e40 | ||
|
|
d2f09209a7 | ||
|
|
a241b04d99 | ||
|
|
4f35d907cb | ||
|
|
9e50d144a3 | ||
|
|
8514bb48c4 | ||
|
|
3ae633a2a1 | ||
|
|
2799cb9118 | ||
|
|
d20346b6ac | ||
|
|
2f00666a68 | ||
|
|
80f4570093 | ||
|
|
3f0a2ba48f | ||
|
|
fc90094e8a | ||
|
|
20d580ade8 | ||
|
|
290a024a9e | ||
|
|
64a283c3a6 | ||
|
|
3e93f0ecbc | ||
|
|
b12bcc1c49 | ||
|
|
05d7313dcc | ||
|
|
c0b6e549f0 | ||
|
|
31f9bf219e | ||
|
|
4906ca7059 | ||
|
|
b963a7a0e5 | ||
|
|
5d6dadda76 | ||
|
|
77f69fd223 | ||
|
|
7f5052bc87 | ||
|
|
3009c1f4f6 | ||
|
|
5425872bba | ||
|
|
0759e17295 | ||
|
|
56a59d25df | ||
|
|
887f92babe | ||
|
|
197f942b3f | ||
|
|
a5be7a35e9 | ||
|
|
e347675265 | ||
|
|
02a084d571 | ||
|
|
7fbcc23d94 | ||
|
|
bda87167a3 | ||
|
|
34f53c287e | ||
|
|
9ab07f37d7 | ||
|
|
36399b39fb | ||
|
|
1e015287a1 | ||
|
|
a590aa8485 | ||
|
|
c0582fde66 | ||
|
|
d8d75b4afa | ||
|
|
9d4942723c | ||
|
|
e5b1ece5c0 | ||
|
|
1b25bfbf5a | ||
|
|
7c64d9f42a | ||
|
|
61f9f4ef58 | ||
|
|
b8eac56213 | ||
|
|
ab5fb5749b | ||
|
|
e0fb9a1b25 | ||
|
|
97e717f646 | ||
|
|
caa82ad1e6 | ||
|
|
7ec251ea6d | ||
|
|
675b0c3cca | ||
|
|
05e54d4b7f | ||
|
|
b4527c90e5 | ||
|
|
dbc626734d | ||
|
|
3f2ce3cb80 | ||
|
|
0820d6d6fb | ||
|
|
a8c74e39c2 | ||
|
|
d58c29907d | ||
|
|
2322733427 | ||
|
|
d76e8fe85a | ||
|
|
0c2e4fe34a | ||
|
|
30b6c87a49 | ||
|
|
540221467a | ||
|
|
d44d331a78 | ||
|
|
595554f18a | ||
|
|
84d3c3f7eb | ||
|
|
890f55c9dc | ||
|
|
575a14e1f3 | ||
|
|
91074bebd6 | ||
|
|
3459a16b48 | ||
|
|
88c9b6849f | ||
|
|
d87bb25baf | ||
|
|
34cb796505 | ||
|
|
1eb34e0662 | ||
|
|
01d631033f | ||
|
|
84b2c07340 | ||
|
|
a86eeb636d | ||
|
|
417a5a8214 | ||
|
|
bcf40dde8c | ||
|
|
cad87484c7 | ||
|
|
b8ad641ed6 | ||
|
|
ae8197be8b | ||
|
|
eafb0274a7 | ||
|
|
71a23a4e02 | ||
|
|
26fd90dfa3 | ||
|
|
e393ebede2 | ||
|
|
2981bb3f19 | ||
|
|
6e9f05abb1 | ||
|
|
9df1115380 | ||
|
|
f22e360cbb | ||
|
|
67769af6f4 | ||
|
|
b1a9a1d6d9 | ||
|
|
cf0606ecb7 | ||
|
|
7287edcd6f | ||
|
|
e0d26203dd | ||
|
|
7e3a85e9da | ||
|
|
5a0fed9c93 | ||
|
|
1f1e743912 | ||
|
|
b4301ed0d5 | ||
|
|
b5391560fc | ||
|
|
718989cbcf | ||
|
|
d0aee76962 | ||
|
|
fb08af96bd | ||
|
|
510a0c5e70 | ||
|
|
89bdc8ec75 | ||
|
|
ae25ade318 | ||
|
|
dd5e46a8a7 | ||
|
|
f7218aaa9e | ||
|
|
ee79bcfc44 | ||
|
|
2c2c174874 | ||
|
|
f57c49ce3a | ||
|
|
06121acfac | ||
|
|
2078ce7446 | ||
|
|
49f41abfdb | ||
|
|
70fcfe6d6c | ||
|
|
b060b4b9bf | ||
|
|
ee2135bfb3 | ||
|
|
7daa322441 | ||
|
|
74252cb66b | ||
|
|
5fe2be031f | ||
|
|
2ba3aaba47 | ||
|
|
ad8903991c | ||
|
|
3e5624c570 | ||
|
|
88d3bba300 | ||
|
|
f5ee6f3537 | ||
|
|
afc77e7adc | ||
|
|
024f42fce6 | ||
|
|
8a5f12b97c | ||
|
|
954b21cf39 | ||
|
|
74d095774d | ||
|
|
17a2722e6d | ||
|
|
c843bddbfe | ||
|
|
3f22a49755 | ||
|
|
7af2ffcebf | ||
|
|
de90c959e0 | ||
|
|
9987dc1eb4 | ||
|
|
3efd575dd2 | ||
|
|
f4c7b17a87 | ||
|
|
16d80718cb | ||
|
|
ad228d53b7 | ||
|
|
15ee1e531b | ||
|
|
1c8fb3392a | ||
|
|
8647866a32 | ||
|
|
23351c4f1c | ||
|
|
1367c304cf | ||
|
|
26d6bcb074 | ||
|
|
b0d651ece1 | ||
|
|
b6d50ba6a4 | ||
|
|
b3ab6a9166 | ||
|
|
f39a5ac9c2 | ||
|
|
38a9a9240d | ||
|
|
241b22a465 | ||
|
|
741abc0366 | ||
|
|
7854775de5 | ||
|
|
e62eaa6b4b | ||
|
|
b4cce23ef4 | ||
|
|
2bcaf90fc8 | ||
|
|
96ffbe2f84 | ||
|
|
6f5acee1c3 | ||
|
|
54e491d8bf | ||
|
|
ab6374e278 | ||
|
|
2fda4c9f67 | ||
|
|
5138a45b0f | ||
|
|
b224d4fa8a | ||
|
|
a552e44483 | ||
|
|
0cf3bba118 | ||
|
|
2c48ea3508 | ||
|
|
b9b6212b75 | ||
|
|
b978aaec21 | ||
|
|
af704681d9 | ||
|
|
1443ddfe6c | ||
|
|
54457a3e1b | ||
|
|
bf180e6a2c | ||
|
|
864a5820c9 | ||
|
|
4d3ca49c3f | ||
|
|
c49c3cf7f0 | ||
|
|
5d5ab57469 | ||
|
|
31978d8de0 | ||
|
|
e8eb68bf24 | ||
|
|
9ea08f4fed | ||
|
|
fe078a5c5b | ||
|
|
61933954f3 | ||
|
|
4c243638cb | ||
|
|
02ba04b5d8 | ||
|
|
4f158a4829 | ||
|
|
177a22df59 | ||
|
|
6b0ca2966e | ||
|
|
aadfaf7150 | ||
|
|
b307b9a66b | ||
|
|
6c1ab6002d | ||
|
|
9638eefc91 | ||
|
|
9e9c4ad587 | ||
|
|
ce231431b9 | ||
|
|
06e1e14e02 | ||
|
|
416e7884f5 | ||
|
|
d579222007 | ||
|
|
30243c84cd | ||
|
|
3557a77645 | ||
|
|
97be28638b | ||
|
|
aba0826c38 | ||
|
|
f032228d0e | ||
|
|
6cf174c5ed | ||
|
|
c2109d245f | ||
|
|
6a9745171e | ||
|
|
f9a68e8b23 | ||
|
|
6e391df5ee | ||
|
|
f5edca94d3 | ||
|
|
60046abec3 | ||
|
|
cafc2060b8 | ||
|
|
b1f45752cf | ||
|
|
ed17551170 | ||
|
|
ef5adab638 | ||
|
|
fb653ff99d | ||
|
|
78fc47a9c4 | ||
|
|
2a124cea61 | ||
|
|
4c7cc563dc | ||
|
|
6114af4f93 | ||
|
|
8c31629655 | ||
|
|
03c8a8edb2 | ||
|
|
3eeaee154f | ||
|
|
8cf8fa7c80 | ||
|
|
6b4f6fc71e | ||
|
|
30c2680b6f | ||
|
|
fb7b1800cc | ||
|
|
ff573bf377 | ||
|
|
0a33bb861e | ||
|
|
728756289b | ||
|
|
56ccd3a0ac | ||
|
|
66f3f0ba07 | ||
|
|
af5e0d589e | ||
|
|
533dc99e7d | ||
|
|
fc5ca965ba | ||
|
|
9c4a46bcdb | ||
|
|
52658886e7 | ||
|
|
8174ab7616 | ||
|
|
2b6acedae1 | ||
|
|
d00fe9c5f4 | ||
|
|
88aa270728 | ||
|
|
4ae409c7f4 | ||
|
|
9a29c9abdd | ||
|
|
66d93ea037 | ||
|
|
6c0066dbfb | ||
|
|
4fde644733 | ||
|
|
e7841c60df | ||
|
|
94f647b24a | ||
|
|
630249d22a | ||
|
|
db99b4cb54 | ||
|
|
c77db23586 | ||
|
|
daf66bcec4 | ||
|
|
8caf36349f | ||
|
|
6934de58e5 | ||
|
|
54a5007c01 | ||
|
|
e25a455698 | ||
|
|
ab429dfeb6 | ||
|
|
c5289dc0e8 | ||
|
|
d191877002 | ||
|
|
4d979160c2 | ||
|
|
d00e8f6e19 | ||
|
|
91b77e5237 | ||
|
|
5b8c246d53 | ||
|
|
b374b9b91c | ||
|
|
403717117e | ||
|
|
027295d995 | ||
|
|
c9b7eccbc1 | ||
|
|
2b6d9348cd | ||
|
|
692f8c8454 | ||
|
|
6783355c4d | ||
|
|
fb9cca1e99 | ||
|
|
eb770ede1a | ||
|
|
2643e853af | ||
|
|
b79456e91b | ||
|
|
ac66c086f8 | ||
|
|
ebccf401dd | ||
|
|
66494845b7 | ||
|
|
e6c36ad602 | ||
|
|
26379182db | ||
|
|
bba03d14d4 | ||
|
|
23b728a762 | ||
|
|
819c5207d2 | ||
|
|
311358544e | ||
|
|
4480ecc96d | ||
|
|
6c5f70a205 | ||
|
|
99adfb4a9e | ||
|
|
7909cf4067 | ||
|
|
780ab20aeb | ||
|
|
73119bb7c5 | ||
|
|
f20f0f064e | ||
|
|
1b44ae098c | ||
|
|
453c230716 | ||
|
|
439d885ee1 | ||
|
|
43dee3ef76 | ||
|
|
c71ba6ff8d | ||
|
|
fb7a36eb73 | ||
|
|
e7f294a065 | ||
|
|
d5037f180e | ||
|
|
e90158809a | ||
|
|
0cb802ed9a | ||
|
|
d0b47204f4 | ||
|
|
351cb391e5 | ||
|
|
051be927cd | ||
|
|
8bad2c2113 | ||
|
|
2bcf6fb3eb | ||
|
|
d1ba0ed2b2 | ||
|
|
6e421e60c5 | ||
|
|
8385050804 | ||
|
|
bfe4f08232 | ||
|
|
132f914b0d | ||
|
|
97d82b03ab | ||
|
|
f06fa3f9b7 | ||
|
|
6337788a22 | ||
|
|
024db4358b | ||
|
|
173f35487e | ||
|
|
74cbe82dd1 | ||
|
|
a8c30d30a9 | ||
|
|
1b7a52d5af | ||
|
|
e5109789bf | ||
|
|
4d2b35e09d | ||
|
|
5c5177ec57 | ||
|
|
d93b00cd15 | ||
|
|
39ade59174 | ||
|
|
0309c815b9 | ||
|
|
ce613098db | ||
|
|
ab34044196 | ||
|
|
17f724748f | ||
|
|
f3a917b5e7 | ||
|
|
376011ea08 | ||
|
|
2ce7624c14 | ||
|
|
c62dddd5b9 | ||
|
|
490ba9f140 | ||
|
|
f76890cc56 | ||
|
|
e1c8f1fed9 | ||
|
|
6e19a4ab8b | ||
|
|
b156523a7f | ||
|
|
d20b745ae5 | ||
|
|
c51e9e6b2c | ||
|
|
1a31fa9067 | ||
|
|
558b8499af | ||
|
|
986c162988 | ||
|
|
770d5cd11c | ||
|
|
446d2ab3af | ||
|
|
2f9bf7f063 | ||
|
|
72ff9c0964 | ||
|
|
33b1a11d85 | ||
|
|
06dabf1e4e | ||
|
|
28d3691e0b | ||
|
|
ffa21fbfd2 | ||
|
|
db028665fd | ||
|
|
6bc83d9f27 | ||
|
|
790d832155 | ||
|
|
f477cecdeb | ||
|
|
e031389021 | ||
|
|
e00f826eb8 | ||
|
|
24f4e8ab99 | ||
|
|
1550d528bd | ||
|
|
40c041031e | ||
|
|
3e555ec9f1 | ||
|
|
5098f14aab | ||
|
|
a355a9c85e | ||
|
|
e7db2a8573 | ||
|
|
9b18bd0b48 | ||
|
|
f95ddd594e | ||
|
|
fe8168784f | ||
|
|
4046f143f6 | ||
|
|
e4e16999c8 | ||
|
|
10f3ba4ff4 | ||
|
|
3cd2be5081 | ||
|
|
c9359978f9 | ||
|
|
781c67b31a | ||
|
|
020bd129fb | ||
|
|
8086b6d78c | ||
|
|
48e14b36b8 | ||
|
|
b3c1c56579 | ||
|
|
bd0e932910 | ||
|
|
525e5f88ae | ||
|
|
005eeb0e0b | ||
|
|
d21bb015e8 | ||
|
|
7338838b0e | ||
|
|
8bb4803ff9 | ||
|
|
892b919cf3 | ||
|
|
572d81ecef | ||
|
|
a4ce7a4037 | ||
|
|
6eafb15cf9 | ||
|
|
e19fe5ce1c | ||
|
|
9d2017e598 | ||
|
|
f33c419ed9 | ||
|
|
f425fbaf9d | ||
|
|
bcc5ec897a | ||
|
|
f5f2fe3472 | ||
|
|
b7c3863882 | ||
|
|
d759f48ee8 | ||
|
|
3a37075e71 | ||
|
|
58366c0b87 | ||
|
|
2667ed13f1 | ||
|
|
34daffbc96 | ||
|
|
be81cd72af | ||
|
|
4ae00714d2 | ||
|
|
f24cbb6692 | ||
|
|
5a35c5b928 | ||
|
|
1880da6351 | ||
|
|
df93cb103c | ||
|
|
63b474a32c | ||
|
|
abdbf158d1 | ||
|
|
ee68d80d0a | ||
|
|
c8e6f3a627 | ||
|
|
dc941575fe | ||
|
|
e64103e5f2 | ||
|
|
f0ab03a9fb | ||
|
|
09965f1cc6 | ||
|
|
d2852bb34a | ||
|
|
b03c52a501 | ||
|
|
fd6633f536 | ||
|
|
320ac81f48 | ||
|
|
70bcd2428f | ||
|
|
71f5ada0a3 | ||
|
|
aab5141404 | ||
|
|
ff6b119f27 | ||
|
|
7ef4b7eeb8 | ||
|
|
4668be6e24 | ||
|
|
a211fc7c97 | ||
|
|
54af0b675d | ||
|
|
8c8171e774 | ||
|
|
0bb1790206 | ||
|
|
45fc84d8be | ||
|
|
f7500f4cad | ||
|
|
0cfd718d8a | ||
|
|
5f486d0f51 | ||
|
|
6e5a2f85a1 | ||
|
|
e66a89208d | ||
|
|
7f65c501c6 | ||
|
|
22c2382765 | ||
|
|
38e1a4febf | ||
|
|
8db554b377 | ||
|
|
5f5cc55331 | ||
|
|
2f8b39186f | ||
|
|
a3a724e2e6 | ||
|
|
73235c8699 | ||
|
|
7e5999e862 | ||
|
|
afa244dcb0 | ||
|
|
4ea5bb2390 | ||
|
|
e545d552f6 | ||
|
|
56fe7b3596 | ||
|
|
eb28ec866a | ||
|
|
4649454282 | ||
|
|
a45dc6efda | ||
|
|
9e56b9fbb5 | ||
|
|
5504994cb9 | ||
|
|
acff6d0432 | ||
|
|
eea9cb7c5b | ||
|
|
c0ddddfb1f | ||
|
|
f7dab3ca56 | ||
|
|
e11b4038a3 | ||
|
|
b635e64803 | ||
|
|
20a194b49a | ||
|
|
33a5fb8837 | ||
|
|
59dae640db | ||
|
|
a6ac75e97b | ||
|
|
cc5b33a8ec | ||
|
|
6e1a627b84 | ||
|
|
62d4c65e1c | ||
|
|
600134a3ac | ||
|
|
df14af7337 | ||
|
|
2f740b570d | ||
|
|
294d980b52 | ||
|
|
c9d9909d74 | ||
|
|
90eeabae7b | ||
|
|
a32c77c5f1 | ||
|
|
910846f2ce | ||
|
|
35d0438261 | ||
|
|
515af472ce | ||
|
|
f062f7f9fe | ||
|
|
f68378041f | ||
|
|
30ef3057ac | ||
|
|
48f3a934c9 | ||
|
|
38d1fde84f | ||
|
|
dd78670a4b | ||
|
|
b8a8190a43 | ||
|
|
2d0989342f | ||
|
|
15ff9b06a1 | ||
|
|
41b19f69de | ||
|
|
f2bd6f1fce | ||
|
|
ec94218a4b | ||
|
|
c2e5c7cf38 | ||
|
|
bac5734527 | ||
|
|
bef4033d94 | ||
|
|
64216cba67 | ||
|
|
a9d6167a9f | ||
|
|
6c6b40548f | ||
|
|
a916d88e85 | ||
|
|
ab2f0548a3 | ||
|
|
e30ba07285 | ||
|
|
1b336d973d | ||
|
|
7b1866737f | ||
|
|
eedc4ab648 | ||
|
|
5e429c7a94 | ||
|
|
57d23eb043 | ||
|
|
5ebd9be89a | ||
|
|
5a743779e2 | ||
|
|
0495062110 | ||
|
|
d522191f69 | ||
|
|
bbbdc8b7a6 | ||
|
|
c00ed8aa5a | ||
|
|
0beaa94068 | ||
|
|
96e76665d6 | ||
|
|
6423a29600 | ||
|
|
8bddf30dcf | ||
|
|
a6b2db182d | ||
|
|
b9f3f9d859 | ||
|
|
6331447dcd | ||
|
|
4213ee660f | ||
|
|
3bd9287c5d | ||
|
|
b23d3f7c8b | ||
|
|
f8d9e5e027 | ||
|
|
8fa7fb3b1f | ||
|
|
63d92a0872 | ||
|
|
509d83365e | ||
|
|
d6ab73c905 | ||
|
|
5a93ba05d5 | ||
|
|
2d2fdf0b1e | ||
|
|
cf96622261 | ||
|
|
47c8ccb0e5 | ||
|
|
02fdb8778b | ||
|
|
6bed7f0e66 | ||
|
|
7597d335b9 | ||
|
|
f32c5ba244 | ||
|
|
ab53ab21e2 | ||
|
|
acfe5dbb49 | ||
|
|
f9b91fa189 | ||
|
|
2462e68ba1 | ||
|
|
019b2a1681 | ||
|
|
e94a07b677 | ||
|
|
c058c29755 | ||
|
|
9e7c7ac163 | ||
|
|
fcee41f00d | ||
|
|
ff2c1bf8ed | ||
|
|
a2cf26e7ed | ||
|
|
71e6900375 | ||
|
|
3bdc98bd12 | ||
|
|
68d2a6e951 | ||
|
|
acf47ac947 | ||
|
|
fda24e5f5a | ||
|
|
05eca8e4d8 | ||
|
|
b915f3b1a9 | ||
|
|
ab58968f4d | ||
|
|
820d1e7570 | ||
|
|
a120c8cf98 | ||
|
|
5a35ea116f | ||
|
|
e72ad1f030 | ||
|
|
a17362437a | ||
|
|
8643dc43b1 | ||
|
|
e1c869a358 | ||
|
|
2f5b8d9abe | ||
|
|
db324f54eb | ||
|
|
3242efb1a2 | ||
|
|
30f9f1a021 | ||
|
|
3f58d05aa7 | ||
|
|
c611a51575 | ||
|
|
73458dcd28 | ||
|
|
23ebeb1cc0 | ||
|
|
a7ba9f1886 | ||
|
|
d5192e2244 | ||
|
|
7eb595170f | ||
|
|
bd576ca808 | ||
|
|
2f8146b11f | ||
|
|
7f321c89cb | ||
|
|
fa65f606b8 | ||
|
|
7a3285adaf | ||
|
|
8bf78fef10 | ||
|
|
78f97ce4df | ||
|
|
66ccbf70f8 | ||
|
|
cb48600b40 | ||
|
|
33ce235713 | ||
|
|
f1a68ece01 | ||
|
|
dd563360af | ||
|
|
7f6dac4271 | ||
|
|
178fd8e828 | ||
|
|
1641e02a7d | ||
|
|
cfd04e9bb4 | ||
|
|
38effaf740 | ||
|
|
a68eb4a73e | ||
|
|
c02990ef98 | ||
|
|
5aa7d5ffe9 | ||
|
|
4942b0fca5 | ||
|
|
aed1bdff5a | ||
|
|
929c840006 | ||
|
|
57aef1d3c2 | ||
|
|
c1734a094c | ||
|
|
99c46685ac | ||
|
|
066b08040a | ||
|
|
35de2334fb | ||
|
|
5564c966a5 | ||
|
|
0891b5e7b7 | ||
|
|
f3341f201f | ||
|
|
bf0dafabe2 | ||
|
|
60f6587169 | ||
|
|
a9bf32919e | ||
|
|
7633f9f88b | ||
|
|
9b56233938 | ||
|
|
65074264b8 | ||
|
|
4f6fceb87f | ||
|
|
659fdd1d37 | ||
|
|
8bce2ce040 | ||
|
|
55cc83a5d4 | ||
|
|
6a51e93ded | ||
|
|
fcf570e96e | ||
|
|
cbc184e953 | ||
|
|
98f9063352 | ||
|
|
c278f1af00 | ||
|
|
fbb17a0ba5 | ||
|
|
8637a9823e | ||
|
|
d717fe7e8c | ||
|
|
5e8dfe7267 | ||
|
|
aaa4fbcdbd | ||
|
|
150f0cf486 | ||
|
|
711b220a05 | ||
|
|
b615c485f7 | ||
|
|
2f3b6b29ae | ||
|
|
7aecd83c4a | ||
|
|
3b460ab91f | ||
|
|
661c0eb970 | ||
|
|
f4a1f1fdc8 | ||
|
|
b5432c3728 | ||
|
|
6d0625c409 | ||
|
|
2f1ea08b8a | ||
|
|
a092da1943 | ||
|
|
43ef3cc562 | ||
|
|
047774475c | ||
|
|
91b8504df5 | ||
|
|
a4fb2dfcf8 | ||
|
|
ba16ec02e5 | ||
|
|
55b7af2623 | ||
|
|
b428eff10e | ||
|
|
35aee15b6d | ||
|
|
6f53c1bfde | ||
|
|
db0230ed75 | ||
|
|
7fa3c1e12a | ||
|
|
3b5993652f | ||
|
|
be4ad8947f | ||
|
|
2ead15e78e | ||
|
|
aa0740ff94 | ||
|
|
6d3f837820 | ||
|
|
359b82c29c | ||
|
|
b54171bc2c | ||
|
|
936b2131e0 | ||
|
|
aaef6a9e9c | ||
|
|
9327006e61 | ||
|
|
5225c841ae | ||
|
|
8464e319fd | ||
|
|
98b8bd90ea | ||
|
|
ae94993b09 | ||
|
|
72f10aaed1 | ||
|
|
4a74bae8c7 | ||
|
|
5164aec37b | ||
|
|
1581e9b1cd | ||
|
|
536e3ffb11 | ||
|
|
d6103191ba | ||
|
|
49e37a19a5 | ||
|
|
d02431e260 | ||
|
|
f24f6ead92 | ||
|
|
b7bdb7ae50 | ||
|
|
2dcf8ac96f | ||
|
|
5421c94853 | ||
|
|
10f6bc092a | ||
|
|
be9ea4ea8e | ||
|
|
f5c6fa842a | ||
|
|
e0943ce905 | ||
|
|
61e7df77a7 | ||
|
|
a5434360bc | ||
|
|
ba29c66e3b | ||
|
|
b3a72d55ae | ||
|
|
c382ad1cc8 | ||
|
|
363e28f323 | ||
|
|
d695656b8c | ||
|
|
31c6cbc0a2 | ||
|
|
b93284bc2f | ||
|
|
99c855b01b | ||
|
|
c2eaedc959 | ||
|
|
a631cd67ec | ||
|
|
66fccd3c68 | ||
|
|
9a4ebf4daa | ||
|
|
91c14211c6 | ||
|
|
1ea07c458b | ||
|
|
591add6e0c | ||
|
|
b99fff66df | ||
|
|
f54ba05b00 | ||
|
|
6596fb00c7 | ||
|
|
df0b5a80dc | ||
|
|
8cdbb31dbe | ||
|
|
0be4b1222d | ||
|
|
18a6bfd73a | ||
|
|
5e2271b237 | ||
|
|
798999d490 | ||
|
|
0e68c5e8bc | ||
|
|
9694af82f4 | ||
|
|
28a4386975 | ||
|
|
a238f7beba | ||
|
|
75ba16281b | ||
|
|
ad65a278d4 | ||
|
|
a2320b3f8d | ||
|
|
ae12853ad0 | ||
|
|
68adf6dc2f | ||
|
|
f88989bd4b | ||
|
|
77ef3847ce | ||
|
|
b8291837fc | ||
|
|
423a7f951a | ||
|
|
557f5fe364 | ||
|
|
5308970ad8 | ||
|
|
6b368953f4 | ||
|
|
2d0b63c29d | ||
|
|
34e941c8cb | ||
|
|
76cf007fff | ||
|
|
321963be83 | ||
|
|
c733bda6c3 | ||
|
|
e67b50b976 | ||
|
|
9e3c080909 | ||
|
|
cb661aaebd | ||
|
|
573571978c | ||
|
|
dc492a2a0a | ||
|
|
e47747dd0e | ||
|
|
4de944b41e | ||
|
|
5f7a1fa5cd | ||
|
|
b8ad328cde | ||
|
|
3076fd19c1 | ||
|
|
fac437b8c1 | ||
|
|
697c25015e | ||
|
|
d83b404fc3 | ||
|
|
ab7313cbc4 | ||
|
|
1b8d70322b | ||
|
|
844ffab4ed | ||
|
|
f5d0513d1f | ||
|
|
557abd4285 | ||
|
|
f4f1a0fbc6 | ||
|
|
74e10dc012 | ||
|
|
359812b7ed | ||
|
|
c2449e53c4 | ||
|
|
1a91249da2 | ||
|
|
b9162f9576 | ||
|
|
f726e8a7b3 | ||
|
|
2f284cfdc9 | ||
|
|
b74696adba | ||
|
|
c8ccba0192 | ||
|
|
41b0e05f62 | ||
|
|
847d5f1b3b | ||
|
|
0445f9dfc2 | ||
|
|
3001c780bd | ||
|
|
68ad5e2320 | ||
|
|
b5e229b19c | ||
|
|
453d798fcf | ||
|
|
451afdb660 | ||
|
|
d298bda92c | ||
|
|
fd99ba6255 | ||
|
|
6ade0b2b1a | ||
|
|
9902003da9 | ||
|
|
0ff2fcac11 | ||
|
|
e80be8e7b6 | ||
|
|
fe0ad0f5cb | ||
|
|
cb8e162f4e | ||
|
|
ae8c30fe57 | ||
|
|
ab82db9e22 | ||
|
|
cb9d3098de | ||
|
|
c927419c99 | ||
|
|
c009026961 | ||
|
|
51cf442fa5 | ||
|
|
954e3553ee | ||
|
|
cde17385b4 | ||
|
|
5b9e078061 | ||
|
|
0290d9ddfc | ||
|
|
eab671d102 | ||
|
|
f9a96ff914 | ||
|
|
3ec2b46d28 | ||
|
|
aec30b89e0 | ||
|
|
309c33e190 | ||
|
|
9c0276f97b | ||
|
|
0a3402ff43 | ||
|
|
bd82308024 | ||
|
|
db3b634e62 | ||
|
|
40bcb22977 | ||
|
|
4bd94092f1 | ||
|
|
cac1ce6895 | ||
|
|
5c3696123a | ||
|
|
4140fc86ee | ||
|
|
2ad771e7fd | ||
|
|
5a38468144 | ||
|
|
0a9c81772f | ||
|
|
c9649ac501 | ||
|
|
6ea567742b | ||
|
|
f31349eaa0 | ||
|
|
9d44668d5f | ||
|
|
a12f58c1c7 | ||
|
|
b5283eaaed | ||
|
|
4b6189af5f | ||
|
|
5d0ffbe453 | ||
|
|
502706931e | ||
|
|
57c411288f | ||
|
|
b09b7b11a1 | ||
|
|
1a7b3c7294 | ||
|
|
4678fc7dde | ||
|
|
9f492fad49 | ||
|
|
bd0a959e18 | ||
|
|
dd605e2610 | ||
|
|
9910f6b817 | ||
|
|
991897aff4 | ||
|
|
3cde019208 | ||
|
|
2f6efbed63 | ||
|
|
5cff4e299b | ||
|
|
bce33639da | ||
|
|
366c465cad | ||
|
|
acc6e05bdc | ||
|
|
4ce15577cd | ||
|
|
98fa4d5e65 | ||
|
|
7fe94076c7 | ||
|
|
b8b0c8fa63 | ||
|
|
e585e87bec | ||
|
|
6a4924bb16 | ||
|
|
ab0d516d91 | ||
|
|
b756ae39d0 | ||
|
|
c15c38ea8f | ||
|
|
743963318f | ||
|
|
ed3fc50858 | ||
|
|
5b886fe6be | ||
|
|
7074bbc405 | ||
|
|
ef314c1707 | ||
|
|
a3e7626dd9 | ||
|
|
5cb5d74eed | ||
|
|
6eee10d46d | ||
|
|
2d95f2b0d6 | ||
|
|
ec41bb9c70 | ||
|
|
2d1780b1cf | ||
|
|
d9ce99887c | ||
|
|
9b9cc90414 | ||
|
|
c1eb539a5c | ||
|
|
e1793f57ef | ||
|
|
dbd09a8743 | ||
|
|
0d189ca617 | ||
|
|
dc9bcc40ee | ||
|
|
4991f7ff39 | ||
|
|
a393b8b122 | ||
|
|
c73b354386 | ||
|
|
392ecee3ff | ||
|
|
bae721c49e | ||
|
|
4e806e21a6 | ||
|
|
ec0fdf83b2 | ||
|
|
cb94d8414f | ||
|
|
8890051c17 | ||
|
|
cf00c9476f | ||
|
|
b2a24c7abd | ||
|
|
732a1f4694 | ||
|
|
4c5aa7084e | ||
|
|
fe1fea671c | ||
|
|
04c754c0ac | ||
|
|
754c22c84e | ||
|
|
629331870b | ||
|
|
78774315cb | ||
|
|
36b9c07928 | ||
|
|
40a818630d | ||
|
|
568511a4cf | ||
|
|
109fb39e09 | ||
|
|
68450d2042 | ||
|
|
8a052bbed6 | ||
|
|
3afbb56640 | ||
|
|
c0ad84a491 | ||
|
|
c72f17605c | ||
|
|
42fbee0cdb | ||
|
|
e9b7ec735f | ||
|
|
743788135f | ||
|
|
8ea3e6fa26 | ||
|
|
f23c83e681 | ||
|
|
b615bda17e | ||
|
|
f7c7cd1d3c | ||
|
|
c7e7be4379 | ||
|
|
d63d49f246 | ||
|
|
dad94edb20 | ||
|
|
7108d5f3ab | ||
|
|
ef47a74920 | ||
|
|
a43dab8057 | ||
|
|
f44039b628 | ||
|
|
08fa5205b0 | ||
|
|
b91daebd92 | ||
|
|
9cd6c5c624 | ||
|
|
650e017b72 | ||
|
|
18f9d6dec5 | ||
|
|
4df6571ad9 | ||
|
|
0f5923a10a | ||
|
|
bcdae1169e | ||
|
|
f260d5df49 | ||
|
|
808b861dd1 | ||
|
|
17f1c487a8 | ||
|
|
8dc2c1a38f | ||
|
|
220a494692 | ||
|
|
db6bc10196 | ||
|
|
1880363aeb | ||
|
|
19c7b59883 | ||
|
|
749df89229 | ||
|
|
444f2172fa | ||
|
|
77a77c0ea7 | ||
|
|
dbf380a0d1 | ||
|
|
ade34f5217 | ||
|
|
e89607799a | ||
|
|
d05d8d6a9e | ||
|
|
b6aa50d3dc | ||
|
|
9df361935f | ||
|
|
98b8a122b6 | ||
|
|
c7232522ee | ||
|
|
5280f1d745 | ||
|
|
b52a081e7b | ||
|
|
f981a44861 | ||
|
|
d7c5ce0750 | ||
|
|
9ccc66ca1e | ||
|
|
8606af3616 | ||
|
|
f6e821ba6b | ||
|
|
e8dbcf819b | ||
|
|
bbe2ef4e8e | ||
|
|
dd15455031 | ||
|
|
12ac7bb338 | ||
|
|
46ef348f0d | ||
|
|
1a55cca8af | ||
|
|
81ee989f1f | ||
|
|
c9c06f8a3d | ||
|
|
72127979c3 | ||
|
|
1ad3ddef94 | ||
|
|
97ec5eabf7 | ||
|
|
e12e3a3f2d | ||
|
|
4ff625f23b | ||
|
|
e38dcd85ac | ||
|
|
0245baf1b6 | ||
|
|
10b55c043c | ||
|
|
457655b416 | ||
|
|
7e4506c860 | ||
|
|
794d376348 | ||
|
|
c60578f5b5 | ||
|
|
3a9a392a77 | ||
|
|
a13d4698be | ||
|
|
c046a1993e | ||
|
|
f709117cc4 | ||
|
|
30dd298fca | ||
|
|
0ff8bb8090 | ||
|
|
74bbd3c3a2 | ||
|
|
2e82eaf59a | ||
|
|
7f1df1f1bd | ||
|
|
3c79238a44 | ||
|
|
0aa2565df3 | ||
|
|
22b11db16e | ||
|
|
d0e678b5e9 | ||
|
|
e7bba968b3 | ||
|
|
4934a24293 | ||
|
|
ccb68bcda9 | ||
|
|
66bf4ba3ad | ||
|
|
78a0cfd052 | ||
|
|
8548373742 | ||
|
|
2dfd725ee0 | ||
|
|
5b779b4f14 | ||
|
|
fc48aa7155 | ||
|
|
6193a842f4 | ||
|
|
eb86b471fe | ||
|
|
2b52584547 | ||
|
|
6e3cc57f48 | ||
|
|
f2c04621a5 | ||
|
|
3ed6938d4a | ||
|
|
99fec25ed5 | ||
|
|
73758ad1fd | ||
|
|
c53fe0ed1f | ||
|
|
6082c2bcac | ||
|
|
069abed784 | ||
|
|
7d8fa4d78a | ||
|
|
76081f8d89 | ||
|
|
5ef4285558 | ||
|
|
aa7df4282e | ||
|
|
0ef1d5d0de | ||
|
|
cceb4bb81f | ||
|
|
f0f45e007d | ||
|
|
6a8ffe1642 | ||
|
|
3a73868c10 | ||
|
|
ab1b5897a6 | ||
|
|
f94734a5c8 | ||
|
|
61b86c9584 | ||
|
|
1ac1d6e903 | ||
|
|
b6c58f74c0 | ||
|
|
c88e99d87c | ||
|
|
8d7ab9d05e | ||
|
|
47155a4a29 | ||
|
|
d0b87fd7c3 | ||
|
|
d49fd37656 | ||
|
|
0bd29d71be | ||
|
|
4b5b62c8ae | ||
|
|
65fb2ca2d5 | ||
|
|
0d5bfc0997 | ||
|
|
4f02c373c2 | ||
|
|
209a5b1207 | ||
|
|
95349eacab | ||
|
|
82ba604b99 | ||
|
|
46a8dec655 | ||
|
|
b5af234524 | ||
|
|
b5c41750f7 | ||
|
|
6083824eec | ||
|
|
40977785c3 | ||
|
|
5eddf4f1aa | ||
|
|
99a8e25411 | ||
|
|
08587d8f2f | ||
|
|
3480d50f61 | ||
|
|
43af55252d | ||
|
|
9c43b31fc0 | ||
|
|
9ec7184aa1 | ||
|
|
4e2cb30db7 | ||
|
|
9ca83d3291 | ||
|
|
6b2172d873 | ||
|
|
1a5d9f7dad | ||
|
|
a8425862f0 | ||
|
|
a3a3db6abb | ||
|
|
d6c3bc57c0 | ||
|
|
59c09f90f9 | ||
|
|
d982b83e14 | ||
|
|
cc0e930d34 | ||
|
|
3c3d77fbea | ||
|
|
da7453fdbf | ||
|
|
5fcd25506e | ||
|
|
4979a472de | ||
|
|
4e8d4f4591 | ||
|
|
0f5d2b15e0 | ||
|
|
7fc9631434 | ||
|
|
df5953dd7b | ||
|
|
8f5b2b4a0e | ||
|
|
43c63ffa70 | ||
|
|
6779bc7459 | ||
|
|
664be2d0ba | ||
|
|
6113898b69 | ||
|
|
79aad6b5c2 | ||
|
|
6da7757d36 | ||
|
|
dbb3cb8cc8 | ||
|
|
579f36a1dd | ||
|
|
72c2b306cf | ||
|
|
c2673cd396 | ||
|
|
8eb152816a | ||
|
|
a0bc8a21a5 | ||
|
|
08e4d72758 | ||
|
|
66340a27fa | ||
|
|
83fe9835b6 | ||
|
|
4c1a50a3ca | ||
|
|
fe44a7b3bc | ||
|
|
e86d192db7 | ||
|
|
ea8f1c52f9 | ||
|
|
a4c1573c45 | ||
|
|
182bf49ad0 | ||
|
|
13e1ddbccd | ||
|
|
327b9a1757 | ||
|
|
18c48db7f7 | ||
|
|
b6543bd87f | ||
|
|
9ad8f71d7c | ||
|
|
e369311fc2 | ||
|
|
72ff261fe3 | ||
|
|
774c6f7e05 | ||
|
|
771af6ae08 | ||
|
|
b3cd207444 | ||
|
|
03f9fa4bc2 | ||
|
|
e32bfd9aab | ||
|
|
7e47f8f893 | ||
|
|
cb816e9653 | ||
|
|
6b3e7cbc08 | ||
|
|
db4993ae9b | ||
|
|
4dc3cf6c6b | ||
|
|
2b84bbf3a8 | ||
|
|
26ef4c9961 | ||
|
|
4f56c38599 | ||
|
|
240f4dcfb1 | ||
|
|
ac6abd81c9 | ||
|
|
14bda4f3a5 | ||
|
|
61b9670b45 | ||
|
|
01e8db317e | ||
|
|
92fc09493e | ||
|
|
d927209db7 | ||
|
|
e94007b21f | ||
|
|
18750f275a | ||
|
|
d686a853f4 |
@@ -1,5 +0,0 @@
|
|||||||
[target.aarch64-unknown-linux-gnu]
|
|
||||||
linker = "aarch64-linux-gnu-gcc"
|
|
||||||
|
|
||||||
[target.armv7-unknown-linux-gnueabihf]
|
|
||||||
linker = "arm-linux-gnueabihf-gcc"
|
|
||||||
1
.github/FUNDING.yml
vendored
@@ -1 +0,0 @@
|
|||||||
github: clash-verge-rev
|
|
||||||
34
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -2,38 +2,29 @@ name: 问题反馈 / Bug report
|
|||||||
title: "[BUG] "
|
title: "[BUG] "
|
||||||
description: 反馈你遇到的问题 / Report the issue you are experiencing
|
description: 反馈你遇到的问题 / Report the issue you are experiencing
|
||||||
labels: ["bug"]
|
labels: ["bug"]
|
||||||
type: "Bug"
|
|
||||||
|
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
value: |
|
value: |
|
||||||
## 在提交问题之前,请确认以下事项:
|
## 在提交问题之前,请确认以下事项:
|
||||||
1. 请 **确保** 您已经查阅了 [Clash Verge Rev 官方文档](https://clash-verge-rev.github.io/guide/term.html) 以及 [常见问题](https://clash-verge-rev.github.io/faq/windows.html)
|
1. 请 **确保** 您已经查阅了 [Clash Verge Rev 官方文档](https://clash-verge-rev.github.io/guide.html) 以及 [常见问题](https://clash-verge-rev.github.io/faq/install/)
|
||||||
2. 请 **确保** [已有的问题](https://github.com/clash-verge-rev/clash-verge-rev/issues?q=is%3Aissue) 中没有人提交过相似issue,否则请在已有的issue下进行讨论
|
2. 请 **确保** [已有的问题](https://github.com/clash-verge-rev/clash-verge-rev/issues?q=is%3Aissue) 中没有人提交过相似issue,否则请在已有的issue下进行讨论
|
||||||
3. 请 **务必** 给issue填写一个简洁明了的标题,以便他人快速检索
|
3. 请 **务必** 给issue填写一个简洁明了的标题,以便他人快速检索
|
||||||
4. 请 **务必** 查看 [Alpha](https://github.com/clash-verge-rev/clash-verge-rev/releases/tag/alpha) 版本更新日志
|
4. 请 **务必** 先下载 [Alpha](https://github.com/clash-verge-rev/clash-verge-rev/releases/tag/alpha) 版本测试,确保问题依然存在
|
||||||
5. 请 **务必** 尝试 [Alpha](https://github.com/clash-verge-rev/clash-verge-rev/releases/tag/alpha) 版本,确定问题是否仍然存在
|
5. 请 **务必** 按照模板规范详细描述问题,否则issue将会被关闭
|
||||||
6. 请 **务必** 按照模板规范详细描述问题以及尝试更新 Alpha 版本,否则issue将会被直接关闭
|
|
||||||
## Before submitting the issue, please make sure of the following checklist:
|
## Before submitting the issue, please make sure of the following checklist:
|
||||||
1. Please make sure you have read the [Clash Verge Rev official documentation](https://clash-verge-rev.github.io/guide/term.html) and [FAQ](https://clash-verge-rev.github.io/faq/windows.html)
|
1. Please make sure you have read the [Clash Verge Rev official documentation](https://clash-verge-rev.github.io/guide.html) and [FAQ](https://clash-verge-rev.github.io/faq/install/)
|
||||||
2. Please make sure there is no similar issue in the [existing issues](https://github.com/clash-verge-rev/clash-verge-rev/issues?q=is%3Aissue), otherwise please discuss under the existing issue
|
2. Please make sure there is no similar issue in the [existing issues](https://github.com/clash-verge-rev/clash-verge-rev/issues?q=is%3Aissue), otherwise please discuss under the existing issue
|
||||||
3. Please be sure to fill in a concise and clear title for the issue so that others can quickly search
|
3. Please be sure to fill in a concise and clear title for the issue so that others can quickly search
|
||||||
4. Please be sure to check out [Alpha](https://github.com/clash-verge-rev/clash-verge-rev/releases/tag/alpha) version update log
|
4. Please be sure to download the [Alpha](https://github.com/clash-verge-rev/clash-verge-rev/releases/tag/alpha) version for testing to ensure that the problem still exists
|
||||||
5. Please be sure to try the [Alpha](https://github.com/clash-verge-rev/clash-verge-rev/releases/tag/alpha) version to ensure that the problem still exists
|
5. Please describe the problem in detail according to the template specification, otherwise the issue will be closed
|
||||||
6. Please describe the problem in detail according to the template specification and try to update the Alpha version, otherwise the issue will be closed
|
|
||||||
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: description
|
id: description
|
||||||
attributes:
|
attributes:
|
||||||
label: 问题描述 / Describe the bug
|
label: 问题描述 / Describe the bug
|
||||||
description: 详细清晰地描述你遇到的问题,并配合截图 / Describe the problem you encountered in detail and clearly, and provide screenshots
|
description: 详细清晰地描述你遇到的问题 / A clear and concise description of what the bug is
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: 软件版本 / Verge Version
|
|
||||||
description: 请提供Verge的具体版本,如果是alpha版本,请注明下载时间(精确到小时分钟) / Please provide the specific version of Verge. If it is an alpha version, please indicate the download time (accurate to hours and minutes)
|
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
@@ -59,14 +50,7 @@ body:
|
|||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: 日志(勿上传日志文件,请粘贴日志内容) / Log (Do not upload the log file, paste the log content directly)
|
label: 日志 / Log
|
||||||
description: 请提供完整或相关部分的Debug日志(请在“软件左侧菜单”->“设置”->“日志等级”调整到debug,Verge错误请把“杂项设置”->“app日志等级”调整到debug,并重启Verge生效。日志文件在“软件左侧菜单”->“设置”->“日志目录”下) / Please provide a complete or relevant part of the Debug log (please adjust the "Log level" to debug in "Software left menu" -> "Settings" -> "Log level". If there is a Verge error, please adjust "Miscellaneous settings" -> "app log level" to debug, and restart Verge to take effect. The log file is under "Software left menu" -> "Settings" -> "Log directory")
|
description: 请提供完整或相关部分的Debug日志 / Please provide the complete or relevant part of the Debug log
|
||||||
value: |
|
|
||||||
<details><summary>日志内容 / Log Content</summary>
|
|
||||||
```log
|
|
||||||
<!-- 在此处粘贴完整日志 / Paste the full log here -->
|
|
||||||
|
|
||||||
```
|
|
||||||
</details>
|
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
16
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@@ -2,20 +2,19 @@ name: 功能请求 / Feature request
|
|||||||
title: "[Feature] "
|
title: "[Feature] "
|
||||||
description: 提出你的功能请求 / Propose your feature request
|
description: 提出你的功能请求 / Propose your feature request
|
||||||
labels: ["enhancement"]
|
labels: ["enhancement"]
|
||||||
type: "Feature"
|
|
||||||
|
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
value: |
|
value: |
|
||||||
## 在提交问题之前,请确认以下事项:
|
## 在提交问题之前,请确认以下事项:
|
||||||
1. 请 **确保** 您已经查阅了 [Clash Verge Rev 官方文档](https://clash-verge-rev.github.io/guide/term.html) 确认软件不存在类似的功能
|
1. 请 **确保** 您已经查阅了 [Clash Verge Rev 官方文档](https://clash-verge-rev.github.io/guide.html) 确认软件不存在类似的功能
|
||||||
2. 请 **确保** [已有的问题](https://github.com/clash-verge-rev/clash-verge-rev/issues?q=is%3Aissue) 中没有人提交过相似issue,否则请在已有的issue下进行讨论
|
2. 请 **确保** [已有的问题](https://github.com/clash-verge-rev/clash-verge-rev/issues?q=is%3Aissue) 中没有人提交过相似issue,否则请在已有的issue下进行讨论
|
||||||
3. 请 **务必** 给issue填写一个简洁明了的标题,以便他人快速检索
|
3. 请 **务必** 给issue填写一个简洁明了的标题,以便他人快速检索
|
||||||
4. 请 **务必** 先下载 [Alpha](https://github.com/clash-verge-rev/clash-verge-rev/releases/tag/alpha) 版本测试,确保该功能还未实现
|
4. 请 **务必** 先下载 [Alpha](https://github.com/clash-verge-rev/clash-verge-rev/releases/tag/alpha) 版本测试,确保该功能还未实现
|
||||||
5. 请 **务必** 按照模板规范详细描述问题,否则issue将会被关闭
|
5. 请 **务必** 按照模板规范详细描述问题,否则issue将会被关闭
|
||||||
## Before submitting the issue, please make sure of the following checklist:
|
## Before submitting the issue, please make sure of the following checklist:
|
||||||
1. Please make sure you have read the [Clash Verge Rev official documentation](https://clash-verge-rev.github.io/guide/term.html) to confirm that the software does not have similar functions
|
1. Please make sure you have read the [Clash Verge Rev official documentation](https://clash-verge-rev.github.io/guide.html) to confirm that the software does not have similar functions
|
||||||
2. Please make sure there is no similar issue in the [existing issues](https://github.com/clash-verge-rev/clash-verge-rev/issues?q=is%3Aissue), otherwise please discuss under the existing issue
|
2. Please make sure there is no similar issue in the [existing issues](https://github.com/clash-verge-rev/clash-verge-rev/issues?q=is%3Aissue), otherwise please discuss under the existing issue
|
||||||
3. Please be sure to fill in a concise and clear title for the issue so that others can quickly search
|
3. Please be sure to fill in a concise and clear title for the issue so that others can quickly search
|
||||||
4. Please be sure to download the [Alpha](https://github.com/clash-verge-rev/clash-verge-rev/releases/tag/alpha) version for testing to ensure that the function has not been implemented
|
4. Please be sure to download the [Alpha](https://github.com/clash-verge-rev/clash-verge-rev/releases/tag/alpha) version for testing to ensure that the function has not been implemented
|
||||||
@@ -34,14 +33,3 @@ body:
|
|||||||
description: 请描述你的功能请求的使用场景 / Please describe the use case of your feature request
|
description: 请描述你的功能请求的使用场景 / Please describe the use case of your feature request
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: checkboxes
|
|
||||||
id: os-labels
|
|
||||||
attributes:
|
|
||||||
label: 适用系统 / Target OS
|
|
||||||
description: 请选择该功能适用的操作系统(至少选择一个) / Please select the operating system(s) for this feature request (select at least one)
|
|
||||||
options:
|
|
||||||
- label: windows
|
|
||||||
- label: macos
|
|
||||||
- label: linux
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|||||||
58
.github/ISSUE_TEMPLATE/i18n_request.yml
vendored
@@ -1,58 +0,0 @@
|
|||||||
name: I18N / 多语言相关
|
|
||||||
title: "[I18N] "
|
|
||||||
description: 用于多语言翻译、国际化相关问题或建议 / For issues or suggestions related to translations and internationalization
|
|
||||||
labels: ["I18n"]
|
|
||||||
type: "Task"
|
|
||||||
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
## I18N 相关问题/建议
|
|
||||||
请用此模板提交翻译错误、缺失、建议或新增语言请求。
|
|
||||||
Please use this template for translation errors, missing translations, suggestions, or new language requests.
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: description
|
|
||||||
attributes:
|
|
||||||
label: 问题描述 / Description
|
|
||||||
description: 详细描述你的 I18N 问题或建议 / Please describe your I18N issue or suggestion in detail
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: input
|
|
||||||
id: language
|
|
||||||
attributes:
|
|
||||||
label: 相关语言 / Language
|
|
||||||
description: 例如 zh, en, jp, ru, ... / e.g. zh, en, jp, ru, ...
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: suggestion
|
|
||||||
attributes:
|
|
||||||
label: 建议或修正内容 / Suggestion or Correction
|
|
||||||
description: 如果是翻译修正或建议,请填写建议的内容 / If this is a translation correction or suggestion, please provide the suggested content
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
id: i18n-type
|
|
||||||
attributes:
|
|
||||||
label: 问题类型 / Issue Type
|
|
||||||
description: 请选择适用类型(可多选) / Please select the applicable type(s)
|
|
||||||
options:
|
|
||||||
- label: 翻译错误 / Translation error
|
|
||||||
- label: 翻译缺失 / Missing translation
|
|
||||||
- label: 建议优化 / Suggestion
|
|
||||||
- label: 新增语言 / New language
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: input
|
|
||||||
id: verge-version
|
|
||||||
attributes:
|
|
||||||
label: 软件版本 / Verge Version
|
|
||||||
description: 请提供你使用的 Verge 具体版本 / Please provide the specific version of Verge you are using
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
4
.github/build-for-linux/Dockerfile
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
FROM rust:buster
|
||||||
|
COPY entrypoint.sh /entrypoint.sh
|
||||||
|
RUN chmod a+x /entrypoint.sh
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
14
.github/build-for-linux/action.yml
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
name: "Build for Linux"
|
||||||
|
branding:
|
||||||
|
icon: user-check
|
||||||
|
color: gray-dark
|
||||||
|
inputs:
|
||||||
|
target:
|
||||||
|
required: true
|
||||||
|
description: "Rust Target"
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: "docker"
|
||||||
|
image: "Dockerfile"
|
||||||
|
args:
|
||||||
|
- ${{ inputs.target }}
|
||||||
8
.github/build-for-linux/build.sh
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
pnpm install
|
||||||
|
pnpm check $INPUT_TARGET
|
||||||
|
sed -i "s/#openssl/openssl={version=\"0.10\",features=[\"vendored\"]}/g" src-tauri/Cargo.toml
|
||||||
|
if [ "$INPUT_TARGET" = "x86_64-unknown-linux-gnu" ]; then
|
||||||
|
pnpm build --target $INPUT_TARGET
|
||||||
|
else
|
||||||
|
pnpm build --target $INPUT_TARGET -b deb
|
||||||
|
fi
|
||||||
47
.github/build-for-linux/entrypoint.sh
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
wget https://nodejs.org/dist/v20.10.0/node-v20.10.0-linux-x64.tar.xz
|
||||||
|
tar -Jxvf ./node-v20.10.0-linux-x64.tar.xz
|
||||||
|
export PATH=$(pwd)/node-v20.10.0-linux-x64/bin:$PATH
|
||||||
|
npm install pnpm -g
|
||||||
|
|
||||||
|
rustup target add "$INPUT_TARGET"
|
||||||
|
|
||||||
|
if [ "$INPUT_TARGET" = "x86_64-unknown-linux-gnu" ]; then
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev patchelf
|
||||||
|
elif [ "$INPUT_TARGET" = "aarch64-unknown-linux-gnu" ]; then
|
||||||
|
dpkg --add-architecture arm64
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y libncurses6:arm64 libtinfo6:arm64 linux-libc-dev:arm64 libncursesw6:arm64 libssl3:arm64 libcups2:arm64
|
||||||
|
apt-get install -y --no-install-recommends g++-aarch64-linux-gnu libc6-dev-arm64-cross libwebkit2gtk-4.0-dev:arm64 libgtk-3-dev:arm64 patchelf:arm64 librsvg2-dev:arm64 libayatana-appindicator3-dev:arm64
|
||||||
|
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc
|
||||||
|
export CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc
|
||||||
|
export CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++
|
||||||
|
export PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig
|
||||||
|
export PKG_CONFIG_ALLOW_CROSS=1
|
||||||
|
elif [ "$INPUT_TARGET" = "armv7-unknown-linux-gnueabihf" ]; then
|
||||||
|
dpkg --add-architecture armhf
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y libncurses6:armhf libtinfo6:armhf linux-libc-dev:armhf libncursesw6:armhf libssl3:armhf libcups2:armhf
|
||||||
|
apt-get install -y --no-install-recommends g++-arm-linux-gnueabihf libc6-dev-armhf-cross libwebkit2gtk-4.0-dev:armhf libgtk-3-dev:armhf patchelf:armhf librsvg2-dev:armhf libayatana-appindicator3-dev:armhf
|
||||||
|
export CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc
|
||||||
|
export CC_armv7_unknown_linux_gnueabihf=arm-linux-gnueabihf-gcc
|
||||||
|
export CXX_armv7_unknown_linux_gnueabihf=arm-linux-gnueabihf-g++
|
||||||
|
export PKG_CONFIG_PATH=/usr/lib/arm-linux-gnueabihf/pkgconfig
|
||||||
|
export PKG_CONFIG_ALLOW_CROSS=1
|
||||||
|
elif [ "$INPUT_TARGET" = "riscv64gc-unknown-linux-gnu" ]; then
|
||||||
|
dpkg --add-architecture riscv64
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y libncurses6:riscv64 libtinfo6:riscv64 linux-libc-dev:riscv64 libncursesw6:riscv64 libssl3:riscv64 libcups2:riscv64
|
||||||
|
apt-get install -y --no-install-recommends g++-riscv64-linux-gnu libc6-dev-riscv64-cross libwebkit2gtk-4.0-dev:riscv64 libgtk-3-dev:riscv64 patchelf:riscv64 librsvg2-dev:riscv64 libayatana-appindicator3-dev:riscv64
|
||||||
|
export CARGO_TARGET_RISCV64_UNKNOWN_LINUX_GNU_LINKER=riscv64-linux-gnu-gcc
|
||||||
|
export CC_riscv64_unknown_linux_gnu=riscv64-linux-gnu-gcc
|
||||||
|
export CXX_riscv64_unknown_linux_gnu=riscv64-linux-gnu-g++
|
||||||
|
export PKG_CONFIG_PATH=/usr/lib/riscv64-linux-gnu/pkgconfig
|
||||||
|
export PKG_CONFIG_ALLOW_CROSS=1
|
||||||
|
else
|
||||||
|
echo "Unknown target: $INPUT_TARGET" && exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
bash .github/build-for-linux/build.sh
|
||||||
565
.github/workflows/alpha.yml
vendored
@@ -1,262 +1,17 @@
|
|||||||
name: Alpha Build
|
name: Alpha Build
|
||||||
|
|
||||||
on:
|
on:
|
||||||
# 因为 alpha 不再负责频繁构建,且需要相对于 autobuild 更稳定使用环境
|
|
||||||
# 所以不再使用 workflow_dispatch 触发
|
|
||||||
# 应当通过 git tag 来触发构建
|
|
||||||
# TODO 手动控制版本号
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
# inputs:
|
push:
|
||||||
# tag_name:
|
branches: [main]
|
||||||
# description: "Alpha tag name (e.g. v1.2.3-alpha.1)"
|
tags-ignore: [updater, alpha]
|
||||||
# required: true
|
|
||||||
# type: string
|
|
||||||
|
|
||||||
# push:
|
|
||||||
# # 应当限制在 dev 分支上触发发布。
|
|
||||||
# branches:
|
|
||||||
# - dev
|
|
||||||
# # 应当限制 v*.*.*-alpha* 的 tag 来触发发布。
|
|
||||||
# tags:
|
|
||||||
# - "v*.*.*-alpha*"
|
|
||||||
permissions: write-all
|
permissions: write-all
|
||||||
env:
|
env:
|
||||||
TAG_NAME: alpha
|
|
||||||
TAG_CHANNEL: Alpha
|
|
||||||
CARGO_INCREMENTAL: 0
|
CARGO_INCREMENTAL: 0
|
||||||
RUST_BACKTRACE: short
|
RUST_BACKTRACE: short
|
||||||
concurrency:
|
|
||||||
group: "${{ github.workflow }} - ${{ github.head_ref || github.ref }}"
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check_alpha_tag:
|
alpha:
|
||||||
name: Check Alpha Tag package.json Version Consistency
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Check tag and package.json version
|
|
||||||
id: check_tag
|
|
||||||
run: |
|
|
||||||
TAG_REF="${GITHUB_REF##*/}"
|
|
||||||
echo "Current tag: $TAG_REF"
|
|
||||||
if [[ ! "$TAG_REF" =~ -alpha ]]; then
|
|
||||||
echo "Current tag is not an alpha tag."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
PKG_VERSION=$(jq -r .version package.json)
|
|
||||||
echo "package.json version: $PKG_VERSION"
|
|
||||||
if [[ "$PKG_VERSION" != *alpha* ]]; then
|
|
||||||
echo "package.json version is not an alpha version."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if [[ "$TAG_REF" != "v$PKG_VERSION" ]]; then
|
|
||||||
echo "Tag ($TAG_REF) does not match package.json version (v$PKG_VERSION)."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo "Alpha tag and package.json version are consistent."
|
|
||||||
|
|
||||||
delete_old_assets:
|
|
||||||
name: Delete Old Alpha Release Assets and Tags
|
|
||||||
needs: check_alpha_tag
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Delete Old Alpha Tags Except Latest
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
script: |
|
|
||||||
const tagPattern = /-alpha.*/; // 匹配带有 -alpha 的 tag
|
|
||||||
const owner = context.repo.owner;
|
|
||||||
const repo = context.repo.repo;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 获取所有 tag
|
|
||||||
const { data: tags } = await github.rest.repos.listTags({
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
per_page: 100 // 调整 per_page 以获取更多 tag
|
|
||||||
});
|
|
||||||
|
|
||||||
// 过滤出包含 -alpha 的 tag
|
|
||||||
const alphaTags = (await Promise.all(
|
|
||||||
tags
|
|
||||||
.filter(tag => tagPattern.test(tag.name))
|
|
||||||
.map(async tag => {
|
|
||||||
// 获取每个 tag 的 commit 信息以获得日期
|
|
||||||
const { data: commit } = await github.rest.repos.getCommit({
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
ref: tag.commit.sha
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
...tag,
|
|
||||||
commitDate: commit.committer && commit.committer.date ? commit.committer.date : commit.commit.author.date
|
|
||||||
};
|
|
||||||
})
|
|
||||||
)).sort((a, b) => {
|
|
||||||
// 按 commit 日期降序排序(最新的在前面)
|
|
||||||
return new Date(b.commitDate) - new Date(a.commitDate);
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`Found ${alphaTags.length} alpha tags`);
|
|
||||||
|
|
||||||
if (alphaTags.length === 0) {
|
|
||||||
console.log('No alpha tags found');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保留最新的 tag
|
|
||||||
const latestTag = alphaTags[0];
|
|
||||||
console.log(`Keeping latest alpha tag: ${latestTag.name}`);
|
|
||||||
|
|
||||||
// 处理其他旧的 alpha tag
|
|
||||||
for (const tag of alphaTags.slice(1)) {
|
|
||||||
console.log(`Processing tag: ${tag.name}`);
|
|
||||||
|
|
||||||
// 获取与 tag 关联的 release
|
|
||||||
try {
|
|
||||||
const { data: release } = await github.rest.repos.getReleaseByTag({
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
tag: tag.name
|
|
||||||
});
|
|
||||||
|
|
||||||
// 删除 release 下的所有资产
|
|
||||||
if (release.assets && release.assets.length > 0) {
|
|
||||||
console.log(`Deleting ${release.assets.length} assets for release ${tag.name}`);
|
|
||||||
for (const asset of release.assets) {
|
|
||||||
console.log(`Deleting asset: ${asset.name} (${asset.id})`);
|
|
||||||
await github.rest.repos.deleteReleaseAsset({
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
asset_id: asset.id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除 release
|
|
||||||
console.log(`Deleting release for tag: ${tag.name}`);
|
|
||||||
await github.rest.repos.deleteRelease({
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
release_id: release.id
|
|
||||||
});
|
|
||||||
|
|
||||||
// 删除 tag
|
|
||||||
console.log(`Deleting tag: ${tag.name}`);
|
|
||||||
await github.rest.git.deleteRef({
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
ref: `tags/${tag.name}`
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
if (error.status === 404) {
|
|
||||||
console.log(`No release found for tag ${tag.name}, deleting tag directly`);
|
|
||||||
await github.rest.git.deleteRef({
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
ref: `tags/${tag.name}`
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.error(`Error processing tag ${tag.name}:`, error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('Old alpha tags and releases deleted successfully');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
update_tag:
|
|
||||||
name: Update tag
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: delete_old_assets
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Fetch UPDATE logs
|
|
||||||
id: fetch_update_logs
|
|
||||||
run: |
|
|
||||||
if [ -f "UPDATELOG.md" ]; then
|
|
||||||
UPDATE_LOGS=$(awk '/^## v/{if(flag) exit; flag=1} flag' UPDATELOG.md)
|
|
||||||
if [ -n "$UPDATE_LOGS" ]; then
|
|
||||||
echo "Found update logs"
|
|
||||||
echo "UPDATE_LOGS<<EOF" >> $GITHUB_ENV
|
|
||||||
echo "$UPDATE_LOGS" >> $GITHUB_ENV
|
|
||||||
echo "EOF" >> $GITHUB_ENV
|
|
||||||
else
|
|
||||||
echo "No update sections found in UPDATELOG.md"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "UPDATELOG.md file not found"
|
|
||||||
fi
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Set Env
|
|
||||||
run: |
|
|
||||||
echo "BUILDTIME=$(TZ=Asia/Shanghai date)" >> $GITHUB_ENV
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- run: |
|
|
||||||
if [ -z "$UPDATE_LOGS" ]; then
|
|
||||||
echo "No update logs found, using default message"
|
|
||||||
UPDATE_LOGS="More new features are now supported. Check for detailed changelog soon."
|
|
||||||
else
|
|
||||||
echo "Using found update logs"
|
|
||||||
fi
|
|
||||||
|
|
||||||
cat > release.txt << EOF
|
|
||||||
$UPDATE_LOGS
|
|
||||||
|
|
||||||
## 我应该下载哪个版本?
|
|
||||||
|
|
||||||
### MacOS
|
|
||||||
- MacOS intel芯片: x64.dmg
|
|
||||||
- MacOS apple M芯片: aarch64.dmg
|
|
||||||
|
|
||||||
### Linux
|
|
||||||
- Linux 64位: amd64.deb/amd64.rpm
|
|
||||||
- Linux arm64 architecture: arm64.deb/aarch64.rpm
|
|
||||||
- Linux armv7架构: armhf.deb/armhfp.rpm
|
|
||||||
|
|
||||||
### Windows (不再支持Win7)
|
|
||||||
#### 正常版本(推荐)
|
|
||||||
- 64位: x64-setup.exe
|
|
||||||
- arm64架构: arm64-setup.exe
|
|
||||||
#### 便携版问题很多不再提供
|
|
||||||
#### 内置Webview2版(体积较大,仅在企业版系统或无法安装webview2时使用)
|
|
||||||
- 64位: x64_fixed_webview2-setup.exe
|
|
||||||
- arm64架构: arm64_fixed_webview2-setup.exe
|
|
||||||
|
|
||||||
### FAQ
|
|
||||||
- [常见问题](https://clash-verge-rev.github.io/faq/windows.html)
|
|
||||||
|
|
||||||
### 稳定机场VPN推荐
|
|
||||||
- [狗狗加速](https://verge.dginv.click/#/register?code=oaxsAGo6)
|
|
||||||
|
|
||||||
Created at ${{ env.BUILDTIME }}.
|
|
||||||
EOF
|
|
||||||
|
|
||||||
- name: Upload Release
|
|
||||||
uses: softprops/action-gh-release@v2
|
|
||||||
with:
|
|
||||||
tag_name: ${{ env.TAG_NAME }}
|
|
||||||
name: "Clash Verge Rev ${{ env.TAG_CHANNEL }}"
|
|
||||||
body_path: release.txt
|
|
||||||
prerelease: true
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
generate_release_notes: true
|
|
||||||
|
|
||||||
alpha-x86-windows-macos-linux:
|
|
||||||
name: Alpha x86 Windows, MacOS and Linux
|
|
||||||
needs: update_tag
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@@ -269,8 +24,7 @@ jobs:
|
|||||||
target: aarch64-apple-darwin
|
target: aarch64-apple-darwin
|
||||||
- os: macos-latest
|
- os: macos-latest
|
||||||
target: x86_64-apple-darwin
|
target: x86_64-apple-darwin
|
||||||
- os: ubuntu-22.04
|
|
||||||
target: x86_64-unknown-linux-gnu
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Repository
|
- name: Checkout Repository
|
||||||
@@ -286,166 +40,69 @@ jobs:
|
|||||||
uses: Swatinem/rust-cache@v2
|
uses: Swatinem/rust-cache@v2
|
||||||
with:
|
with:
|
||||||
workspaces: src-tauri
|
workspaces: src-tauri
|
||||||
save-if: false
|
|
||||||
|
|
||||||
- name: Install dependencies (ubuntu only)
|
|
||||||
if: matrix.os == 'ubuntu-22.04'
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y libxslt1.1 libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev patchelf
|
|
||||||
|
|
||||||
- name: Install Node
|
- name: Install Node
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: "22"
|
node-version: "20"
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v3
|
||||||
name: Install pnpm
|
name: Install pnpm
|
||||||
with:
|
with:
|
||||||
|
version: 9
|
||||||
run_install: false
|
run_install: false
|
||||||
|
|
||||||
- name: Pnpm install and check
|
- name: Pnpm install and check
|
||||||
run: |
|
run: |
|
||||||
pnpm i
|
pnpm i
|
||||||
pnpm run prebuild ${{ matrix.target }}
|
pnpm check ${{ matrix.target }}
|
||||||
|
|
||||||
# - name: Release ${{ env.TAG_CHANNEL }} Version
|
|
||||||
# run: pnpm release-version ${{ env.TAG_NAME }}
|
|
||||||
|
|
||||||
- name: Tauri build
|
- name: Tauri build
|
||||||
uses: tauri-apps/tauri-action@v0
|
uses: tauri-apps/tauri-action@v0
|
||||||
env:
|
env:
|
||||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
|
||||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
|
||||||
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
|
|
||||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
|
||||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
|
||||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
|
||||||
with:
|
with:
|
||||||
tagName: ${{ env.TAG_NAME }}
|
tagName: alpha
|
||||||
releaseName: "Clash Verge Rev ${{ env.TAG_CHANNEL }}"
|
releaseName: "Clash Verge Rev Alpha"
|
||||||
releaseBody: "More new features are now supported."
|
releaseBody: "More new features are now supported."
|
||||||
releaseDraft: false
|
releaseDraft: false
|
||||||
prerelease: true
|
prerelease: true
|
||||||
tauriScript: pnpm
|
tauriScript: pnpm
|
||||||
args: --target ${{ matrix.target }}
|
args: --target ${{ matrix.target }}
|
||||||
|
|
||||||
alpha-arm-linux:
|
- name: Portable Bundle
|
||||||
name: Alpha ARM Linux
|
if: matrix.os == 'windows-latest'
|
||||||
needs: update_tag
|
run: pnpm portable ${{ matrix.target }} --alpha
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
|
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||||
|
|
||||||
|
alpha-for-linux:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- os: ubuntu-22.04
|
- os: ubuntu-latest
|
||||||
|
target: x86_64-unknown-linux-gnu
|
||||||
|
- os: ubuntu-latest
|
||||||
target: aarch64-unknown-linux-gnu
|
target: aarch64-unknown-linux-gnu
|
||||||
arch: arm64
|
- os: ubuntu-latest
|
||||||
- os: ubuntu-22.04
|
|
||||||
target: armv7-unknown-linux-gnueabihf
|
target: armv7-unknown-linux-gnueabihf
|
||||||
arch: armhf
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Repository
|
- name: Checkout Repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install Rust Stable
|
|
||||||
uses: dtolnay/rust-toolchain@stable
|
|
||||||
|
|
||||||
- name: Add Rust Target
|
|
||||||
run: rustup target add ${{ matrix.target }}
|
|
||||||
|
|
||||||
- name: Rust Cache
|
|
||||||
uses: Swatinem/rust-cache@v2
|
|
||||||
with:
|
|
||||||
workspaces: src-tauri
|
|
||||||
save-if: false
|
|
||||||
|
|
||||||
- name: Install Node
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: "22"
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Pnpm install and check
|
|
||||||
run: |
|
|
||||||
pnpm i
|
|
||||||
pnpm run prebuild ${{ matrix.target }}
|
|
||||||
|
|
||||||
# - name: Release ${{ env.TAG_CHANNEL }} Version
|
|
||||||
# run: pnpm release-version ${{ env.TAG_NAME }}
|
|
||||||
|
|
||||||
- name: Setup for linux
|
|
||||||
run: |
|
|
||||||
sudo ls -lR /etc/apt/
|
|
||||||
|
|
||||||
cat > /tmp/sources.list << EOF
|
|
||||||
deb [arch=amd64,i386] http://archive.ubuntu.com/ubuntu jammy main multiverse universe restricted
|
|
||||||
deb [arch=amd64,i386] http://archive.ubuntu.com/ubuntu jammy-security main multiverse universe restricted
|
|
||||||
deb [arch=amd64,i386] http://archive.ubuntu.com/ubuntu jammy-updates main multiverse universe restricted
|
|
||||||
deb [arch=amd64,i386] http://archive.ubuntu.com/ubuntu jammy-backports main multiverse universe restricted
|
|
||||||
|
|
||||||
deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy main multiverse universe restricted
|
|
||||||
deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security main multiverse universe restricted
|
|
||||||
deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates main multiverse universe restricted
|
|
||||||
deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-backports main multiverse universe restricted
|
|
||||||
EOF
|
|
||||||
|
|
||||||
sudo mv /etc/apt/sources.list /etc/apt/sources.list.default
|
|
||||||
sudo mv /tmp/sources.list /etc/apt/sources.list
|
|
||||||
|
|
||||||
sudo dpkg --add-architecture ${{ matrix.arch }}
|
|
||||||
sudo apt-get update -y
|
|
||||||
sudo apt-get -f install -y
|
|
||||||
|
|
||||||
sudo apt-get install -y \
|
|
||||||
linux-libc-dev:${{ matrix.arch }} \
|
|
||||||
libc6-dev:${{ matrix.arch }}
|
|
||||||
|
|
||||||
sudo apt-get install -y \
|
|
||||||
libxslt1.1:${{ matrix.arch }} \
|
|
||||||
libwebkit2gtk-4.1-dev:${{ matrix.arch }} \
|
|
||||||
libayatana-appindicator3-dev:${{ matrix.arch }} \
|
|
||||||
libssl-dev:${{ matrix.arch }} \
|
|
||||||
patchelf:${{ matrix.arch }} \
|
|
||||||
librsvg2-dev:${{ matrix.arch }}
|
|
||||||
|
|
||||||
- name: Install aarch64 tools
|
|
||||||
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
|
||||||
run: |
|
|
||||||
sudo apt install -y \
|
|
||||||
gcc-aarch64-linux-gnu \
|
|
||||||
g++-aarch64-linux-gnu
|
|
||||||
|
|
||||||
- name: Install armv7 tools
|
|
||||||
if: matrix.target == 'armv7-unknown-linux-gnueabihf'
|
|
||||||
run: |
|
|
||||||
sudo apt install -y \
|
|
||||||
gcc-arm-linux-gnueabihf \
|
|
||||||
g++-arm-linux-gnueabihf
|
|
||||||
|
|
||||||
- name: Build for Linux
|
- name: Build for Linux
|
||||||
run: |
|
uses: ./.github/build-for-linux
|
||||||
export PKG_CONFIG_ALLOW_CROSS=1
|
|
||||||
if [ "${{ matrix.target }}" == "aarch64-unknown-linux-gnu" ]; then
|
|
||||||
export PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig/:$PKG_CONFIG_PATH
|
|
||||||
export PKG_CONFIG_SYSROOT_DIR=/usr/aarch64-linux-gnu/
|
|
||||||
elif [ "${{ matrix.target }}" == "armv7-unknown-linux-gnueabihf" ]; then
|
|
||||||
export PKG_CONFIG_PATH=/usr/lib/arm-linux-gnueabihf/pkgconfig/:$PKG_CONFIG_PATH
|
|
||||||
export PKG_CONFIG_SYSROOT_DIR=/usr/arm-linux-gnueabihf/
|
|
||||||
fi
|
|
||||||
pnpm build --target ${{ matrix.target }}
|
|
||||||
env:
|
env:
|
||||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
with:
|
||||||
|
target: ${{ matrix.target }}
|
||||||
|
|
||||||
- name: Get Version
|
- name: Get Version
|
||||||
run: |
|
run: |
|
||||||
@@ -454,111 +111,95 @@ jobs:
|
|||||||
echo "VERSION=$(cat package.json | jq '.version' | tr -d '"')" >> $GITHUB_ENV
|
echo "VERSION=$(cat package.json | jq '.version' | tr -d '"')" >> $GITHUB_ENV
|
||||||
echo "BUILDTIME=$(TZ=Asia/Shanghai date)" >> $GITHUB_ENV
|
echo "BUILDTIME=$(TZ=Asia/Shanghai date)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- run: |
|
||||||
|
cat > release.txt << 'EOF'
|
||||||
|
### 我应该下载哪个版本?
|
||||||
|
|
||||||
|
- Windows x86_64架构: x64-setup.exe (不支持win7)
|
||||||
|
- Windows arm64架构: arm64-setup.exe
|
||||||
|
- MacOS intel芯片: x64.dmg
|
||||||
|
- MacOS apple M芯片: aarch64.dmg (提示文件损坏看下面FAQ)
|
||||||
|
- Linux x64架构: amd64.AppImage/amd64.deb
|
||||||
|
- Linux arm64架构: arm64.deb
|
||||||
|
- Linux armv7架构: armhf.deb
|
||||||
|
- Windows 便携板 x86_64架构: x64_portable.zip (不推荐使用,无法自动更新)
|
||||||
|
- Windows 便携板 arm64架构: arm64_portable.zip (不推荐使用,无法自动更新)
|
||||||
|
|
||||||
|
### FAQ
|
||||||
|
|
||||||
|
- [FAQ](https://clash-verge-rev.github.io/faq/install/)
|
||||||
|
|
||||||
|
Created at ${{ env.BUILDTIME }}.
|
||||||
|
EOF
|
||||||
|
|
||||||
- name: Upload Release
|
- name: Upload Release
|
||||||
uses: softprops/action-gh-release@v2
|
if: startsWith(matrix.target, 'x86_64')
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
with:
|
with:
|
||||||
tag_name: ${{ env.TAG_NAME }}
|
tag_name: alpha
|
||||||
name: "Clash Verge Rev ${{ env.TAG_CHANNEL }}"
|
name: "Clash Verge Rev Alpha"
|
||||||
|
body_path: release.txt
|
||||||
prerelease: true
|
prerelease: true
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
files: |
|
files: src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage*
|
||||||
src-tauri/target/${{ matrix.target }}/release/bundle/deb/*.deb
|
|
||||||
src-tauri/target/${{ matrix.target }}/release/bundle/rpm/*.rpm
|
|
||||||
|
|
||||||
alpha-x86-arm-windows_webview2:
|
- name: Upload Release
|
||||||
name: Alpha x86 and ARM Windows with WebView2
|
uses: softprops/action-gh-release@v1
|
||||||
needs: update_tag
|
with:
|
||||||
strategy:
|
tag_name: alpha
|
||||||
fail-fast: false
|
name: "Clash Verge Rev Alpha"
|
||||||
matrix:
|
body_path: release.txt
|
||||||
include:
|
prerelease: true
|
||||||
- os: windows-latest
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
target: x86_64-pc-windows-msvc
|
files: src-tauri/target/${{ matrix.target }}/release/bundle/deb/*.deb
|
||||||
arch: x64
|
|
||||||
- os: windows-latest
|
update_tag:
|
||||||
target: aarch64-pc-windows-msvc
|
name: Update tag
|
||||||
arch: arm64
|
runs-on: ubuntu-latest
|
||||||
runs-on: ${{ matrix.os }}
|
needs: [alpha, alpha-for-linux]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Add Rust Target
|
- name: Set Env
|
||||||
run: rustup target add ${{ matrix.target }}
|
|
||||||
|
|
||||||
- name: Rust Cache
|
|
||||||
uses: Swatinem/rust-cache@v2
|
|
||||||
with:
|
|
||||||
workspaces: src-tauri
|
|
||||||
save-if: false
|
|
||||||
|
|
||||||
- name: Install Node
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: "22"
|
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v4
|
|
||||||
name: Install pnpm
|
|
||||||
with:
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Pnpm install and check
|
|
||||||
run: |
|
run: |
|
||||||
pnpm i
|
echo "BUILDTIME=$(TZ=Asia/Shanghai date)" >> $GITHUB_ENV
|
||||||
pnpm run prebuild ${{ matrix.target }}
|
shell: bash
|
||||||
|
|
||||||
# - name: Release ${{ env.TAG_CHANNEL }} Version
|
- name: Update Tag
|
||||||
# run: pnpm release-version ${{ env.TAG_NAME }}
|
uses: richardsimko/update-tag@v1
|
||||||
|
with:
|
||||||
- name: Download WebView2 Runtime
|
tag_name: alpha
|
||||||
run: |
|
|
||||||
invoke-webrequest -uri https://github.com/westinyang/WebView2RuntimeArchive/releases/download/109.0.1518.78/Microsoft.WebView2.FixedVersionRuntime.109.0.1518.78.${{ matrix.arch }}.cab -outfile Microsoft.WebView2.FixedVersionRuntime.109.0.1518.78.${{ matrix.arch }}.cab
|
|
||||||
Expand .\Microsoft.WebView2.FixedVersionRuntime.109.0.1518.78.${{ matrix.arch }}.cab -F:* ./src-tauri
|
|
||||||
Remove-Item .\src-tauri\tauri.windows.conf.json
|
|
||||||
Rename-Item .\src-tauri\webview2.${{ matrix.arch }}.json tauri.windows.conf.json
|
|
||||||
|
|
||||||
- name: Tauri build
|
|
||||||
id: build
|
|
||||||
uses: tauri-apps/tauri-action@v0
|
|
||||||
env:
|
env:
|
||||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
|
||||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
|
||||||
with:
|
|
||||||
tauriScript: pnpm
|
|
||||||
args: --target ${{ matrix.target }}
|
|
||||||
|
|
||||||
- name: Rename
|
- run: |
|
||||||
run: |
|
cat > release.txt << 'EOF'
|
||||||
$files = Get-ChildItem ".\src-tauri\target\${{ matrix.target }}\release\bundle\nsis\*-setup.exe"
|
### 我应该下载哪个版本?
|
||||||
foreach ($file in $files) {
|
|
||||||
$newName = $file.Name -replace "-setup\.exe$", "_fixed_webview2-setup.exe"
|
|
||||||
Rename-Item $file.FullName $newName
|
|
||||||
}
|
|
||||||
|
|
||||||
$files = Get-ChildItem ".\src-tauri\target\${{ matrix.target }}\release\bundle\nsis\*.nsis.zip"
|
- Windows x86_64架构: x64-setup.exe (不支持win7)
|
||||||
foreach ($file in $files) {
|
- Windows arm64架构: arm64-setup.exe
|
||||||
$newName = $file.Name -replace "-setup\.nsis\.zip$", "_fixed_webview2-setup.nsis.zip"
|
- MacOS intel芯片: x64.dmg
|
||||||
Rename-Item $file.FullName $newName
|
- MacOS apple M芯片: aarch64.dmg (提示文件损坏看下面FAQ)
|
||||||
}
|
- Linux x64架构: amd64.AppImage/amd64.deb
|
||||||
|
- Linux arm64架构: arm64.deb
|
||||||
|
- Linux armv7架构: armhf.deb
|
||||||
|
- Windows 便携板 x86_64架构: x64_portable.zip (不推荐使用,无法自动更新)
|
||||||
|
- Windows 便携板 arm64架构: arm64_portable.zip (不推荐使用,无法自动更新)
|
||||||
|
|
||||||
$files = Get-ChildItem ".\src-tauri\target\${{ matrix.target }}\release\bundle\nsis\*-setup.exe.sig"
|
### FAQ
|
||||||
foreach ($file in $files) {
|
|
||||||
$newName = $file.Name -replace "-setup\.exe\.sig$", "_fixed_webview2-setup.exe.sig"
|
- [FAQ](https://clash-verge-rev.github.io/faq/install/)
|
||||||
Rename-Item $file.FullName $newName
|
|
||||||
}
|
Created at ${{ env.BUILDTIME }}.
|
||||||
|
EOF
|
||||||
|
|
||||||
- name: Upload Release
|
- name: Upload Release
|
||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v1
|
||||||
with:
|
with:
|
||||||
tag_name: ${{ env.TAG_NAME }}
|
tag_name: alpha
|
||||||
name: "Clash Verge Rev ${{ env.TAG_CHANNEL }}"
|
name: "Clash Verge Rev Alpha"
|
||||||
|
body_path: release.txt
|
||||||
prerelease: true
|
prerelease: true
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
files: src-tauri/target/${{ matrix.target }}/release/bundle/nsis/*setup*
|
generate_release_notes: true
|
||||||
|
|
||||||
- name: Portable Bundle
|
|
||||||
run: pnpm portable-fixed-webview2 ${{ matrix.target }} --${{ env.TAG_NAME }}
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|||||||
485
.github/workflows/autobuild.yml
vendored
@@ -1,485 +0,0 @@
|
|||||||
name: Auto Build
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
# schedule:
|
|
||||||
# # UTC+8 0,6,12,18
|
|
||||||
# - cron: "0 16,22,4,10 * * *"
|
|
||||||
permissions: write-all
|
|
||||||
env:
|
|
||||||
TAG_NAME: autobuild
|
|
||||||
TAG_CHANNEL: AutoBuild
|
|
||||||
CARGO_INCREMENTAL: 0
|
|
||||||
RUST_BACKTRACE: short
|
|
||||||
concurrency:
|
|
||||||
group: "${{ github.workflow }} - ${{ github.head_ref || github.ref }}"
|
|
||||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check_commit:
|
|
||||||
name: Check Commit Needs Build
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
should_run: ${{ steps.check.outputs.should_run }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 2
|
|
||||||
|
|
||||||
- name: Check if version changed or src changed
|
|
||||||
id: check
|
|
||||||
run: |
|
|
||||||
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
|
|
||||||
echo "should_run=true" >> $GITHUB_OUTPUT
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
CURRENT_VERSION=$(cat package.json | jq -r '.version')
|
|
||||||
echo "Current version: $CURRENT_VERSION"
|
|
||||||
|
|
||||||
git checkout HEAD~1 package.json
|
|
||||||
PREVIOUS_VERSION=$(cat package.json | jq -r '.version')
|
|
||||||
echo "Previous version: $PREVIOUS_VERSION"
|
|
||||||
|
|
||||||
git checkout HEAD package.json
|
|
||||||
|
|
||||||
if [ "$CURRENT_VERSION" != "$PREVIOUS_VERSION" ]; then
|
|
||||||
echo "Version changed from $PREVIOUS_VERSION to $CURRENT_VERSION"
|
|
||||||
echo "should_run=true" >> $GITHUB_OUTPUT
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
CURRENT_SRC_HASH=$(git rev-parse HEAD:src)
|
|
||||||
PREVIOUS_SRC_HASH=$(git rev-parse HEAD~1:src 2>/dev/null || echo "")
|
|
||||||
CURRENT_TAURI_HASH=$(git rev-parse HEAD:src-tauri 2>/dev/null || echo "")
|
|
||||||
PREVIOUS_TAURI_HASH=$(git rev-parse HEAD~1:src-tauri 2>/dev/null || echo "")
|
|
||||||
|
|
||||||
echo "Current src hash: $CURRENT_SRC_HASH"
|
|
||||||
echo "Previous src hash: $PREVIOUS_SRC_HASH"
|
|
||||||
echo "Current tauri hash: $CURRENT_TAURI_HASH"
|
|
||||||
echo "Previous tauri hash: $PREVIOUS_TAURI_HASH"
|
|
||||||
|
|
||||||
if [ "$CURRENT_SRC_HASH" != "$PREVIOUS_SRC_HASH" ] || [ "$CURRENT_TAURI_HASH" != "$PREVIOUS_TAURI_HASH" ]; then
|
|
||||||
echo "Source directories changed"
|
|
||||||
echo "should_run=true" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "Version and source directories unchanged"
|
|
||||||
echo "should_run=false" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
update_tag:
|
|
||||||
name: Update tag
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: check_commit
|
|
||||||
if: ${{ needs.check_commit.outputs.should_run == 'true' }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Update git tag
|
|
||||||
run: |
|
|
||||||
git config user.name "github-actions[bot]"
|
|
||||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
||||||
git tag -f ${{ env.TAG_NAME }}
|
|
||||||
git push --force origin ${{ env.TAG_NAME }}
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Fetch UPDATE logs
|
|
||||||
id: fetch_update_logs
|
|
||||||
run: |
|
|
||||||
if [ -f "UPDATELOG.md" ]; then
|
|
||||||
UPDATE_LOGS=$(awk '/^## v/{if(flag) exit; flag=1} flag' UPDATELOG.md)
|
|
||||||
if [ -n "$UPDATE_LOGS" ]; then
|
|
||||||
echo "Found update logs"
|
|
||||||
echo "UPDATE_LOGS<<EOF" >> $GITHUB_ENV
|
|
||||||
echo "$UPDATE_LOGS" >> $GITHUB_ENV
|
|
||||||
echo "EOF" >> $GITHUB_ENV
|
|
||||||
else
|
|
||||||
echo "No update sections found in UPDATELOG.md"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "UPDATELOG.md file not found"
|
|
||||||
fi
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Set Env
|
|
||||||
run: |
|
|
||||||
echo "BUILDTIME=$(TZ=Asia/Shanghai date)" >> $GITHUB_ENV
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- run: |
|
|
||||||
if [ -z "$UPDATE_LOGS" ]; then
|
|
||||||
echo "No update logs found, using default message"
|
|
||||||
UPDATE_LOGS="More new features are now supported. Check for detailed changelog soon."
|
|
||||||
else
|
|
||||||
echo "Using found update logs"
|
|
||||||
fi
|
|
||||||
|
|
||||||
cat > release.txt << EOF
|
|
||||||
$UPDATE_LOGS
|
|
||||||
|
|
||||||
## Which version should I download?
|
|
||||||
|
|
||||||
### MacOS
|
|
||||||
- MacOS Intel Chip: x64.dmg
|
|
||||||
- MacOS Apple M Chip: aarch64.dmg
|
|
||||||
|
|
||||||
### Linux
|
|
||||||
- Linux 64-bit: amd64.deb/amd64.rpm
|
|
||||||
- Linux arm64: arm64.deb/aarch64.rpm
|
|
||||||
- Linux armv7: armhf.deb/armhfp.rpm
|
|
||||||
|
|
||||||
### Windows (Win7 is no longer supported)
|
|
||||||
#### Normal version (recommended)
|
|
||||||
- 64-bit: x64-setup.exe
|
|
||||||
- arm64: arm64-setup.exe
|
|
||||||
#### Portable version is no longer available with many problems
|
|
||||||
#### Built-in Webview version 2 (large size, only used in enterprise version of the system or can not install webview2)
|
|
||||||
- 64-bit: x64_fixed_webview2-setup.exe
|
|
||||||
- arm64: arm64_fixed_webview2-setup.exe
|
|
||||||
|
|
||||||
Created at ${{ env.BUILDTIME }}.
|
|
||||||
EOF
|
|
||||||
|
|
||||||
- name: Upload Release
|
|
||||||
uses: softprops/action-gh-release@v2
|
|
||||||
with:
|
|
||||||
tag_name: ${{ env.TAG_NAME }}
|
|
||||||
name: "Clash Verge Rev ${{ env.TAG_CHANNEL }}"
|
|
||||||
body_path: release.txt
|
|
||||||
prerelease: true
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
generate_release_notes: true
|
|
||||||
|
|
||||||
clean_old_assets:
|
|
||||||
name: Clean Old Release Assets
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: update_tag
|
|
||||||
if: ${{ needs.update_tag.result == 'success' }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Remove old assets from release
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
TAG_NAME: ${{ env.TAG_NAME }}
|
|
||||||
run: |
|
|
||||||
VERSION=$(cat package.json | jq -r '.version')
|
|
||||||
assets=$(gh release view "$TAG_NAME" --json assets -q '.assets[].name' || true)
|
|
||||||
for asset in $assets; do
|
|
||||||
if [[ "$asset" != *"$VERSION"* ]]; then
|
|
||||||
echo "Deleting old asset: $asset"
|
|
||||||
gh release delete-asset "$TAG_NAME" "$asset" -y
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
autobuild-x86-windows-macos-linux:
|
|
||||||
name: Autobuild x86 Windows, MacOS and Linux
|
|
||||||
needs: update_tag
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- os: windows-latest
|
|
||||||
target: x86_64-pc-windows-msvc
|
|
||||||
- os: windows-latest
|
|
||||||
target: aarch64-pc-windows-msvc
|
|
||||||
- os: macos-latest
|
|
||||||
target: aarch64-apple-darwin
|
|
||||||
- os: macos-latest
|
|
||||||
target: x86_64-apple-darwin
|
|
||||||
- os: ubuntu-22.04
|
|
||||||
target: x86_64-unknown-linux-gnu
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout Repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install Rust Stable
|
|
||||||
uses: dtolnay/rust-toolchain@stable
|
|
||||||
|
|
||||||
- name: Add Rust Target
|
|
||||||
run: rustup target add ${{ matrix.target }}
|
|
||||||
|
|
||||||
- name: Rust Cache
|
|
||||||
uses: Swatinem/rust-cache@v2
|
|
||||||
with:
|
|
||||||
workspaces: src-tauri
|
|
||||||
cache-all-crates: true
|
|
||||||
save-if: ${{ github.ref == 'refs/heads/dev' }}
|
|
||||||
|
|
||||||
- name: Install dependencies (ubuntu only)
|
|
||||||
if: matrix.os == 'ubuntu-22.04'
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y libxslt1.1 libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev patchelf
|
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v4
|
|
||||||
name: Install pnpm
|
|
||||||
with:
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Install Node
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: "22"
|
|
||||||
cache: "pnpm"
|
|
||||||
|
|
||||||
- name: Pnpm install and check
|
|
||||||
run: |
|
|
||||||
pnpm i
|
|
||||||
pnpm run prebuild ${{ matrix.target }}
|
|
||||||
|
|
||||||
- name: Release ${{ env.TAG_CHANNEL }} Version
|
|
||||||
run: pnpm release-version ${{ env.TAG_NAME }}
|
|
||||||
|
|
||||||
- name: Tauri build
|
|
||||||
uses: tauri-apps/tauri-action@v0
|
|
||||||
env:
|
|
||||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
|
||||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
|
||||||
with:
|
|
||||||
tagName: ${{ env.TAG_NAME }}
|
|
||||||
releaseName: "Clash Verge Rev ${{ env.TAG_CHANNEL }}"
|
|
||||||
releaseBody: "More new features are now supported."
|
|
||||||
releaseDraft: false
|
|
||||||
prerelease: true
|
|
||||||
tauriScript: pnpm
|
|
||||||
args: --target ${{ matrix.target }}
|
|
||||||
|
|
||||||
autobuild-arm-linux:
|
|
||||||
name: Autobuild ARM Linux
|
|
||||||
needs: update_tag
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- os: ubuntu-22.04
|
|
||||||
target: aarch64-unknown-linux-gnu
|
|
||||||
arch: arm64
|
|
||||||
- os: ubuntu-22.04
|
|
||||||
target: armv7-unknown-linux-gnueabihf
|
|
||||||
arch: armhf
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout Repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install Rust Stable
|
|
||||||
uses: dtolnay/rust-toolchain@stable
|
|
||||||
|
|
||||||
- name: Add Rust Target
|
|
||||||
run: rustup target add ${{ matrix.target }}
|
|
||||||
|
|
||||||
- name: Rust Cache
|
|
||||||
uses: Swatinem/rust-cache@v2
|
|
||||||
with:
|
|
||||||
workspaces: src-tauri
|
|
||||||
cache-all-crates: true
|
|
||||||
save-if: ${{ github.ref == 'refs/heads/dev' }}
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Install Node
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: "22"
|
|
||||||
cache: "pnpm"
|
|
||||||
|
|
||||||
- name: Pnpm install and check
|
|
||||||
run: |
|
|
||||||
pnpm i
|
|
||||||
pnpm run prebuild ${{ matrix.target }}
|
|
||||||
|
|
||||||
- name: Release ${{ env.TAG_CHANNEL }} Version
|
|
||||||
run: pnpm release-version ${{ env.TAG_NAME }}
|
|
||||||
|
|
||||||
- name: Setup for linux
|
|
||||||
run: |
|
|
||||||
sudo ls -lR /etc/apt/
|
|
||||||
|
|
||||||
cat > /tmp/sources.list << EOF
|
|
||||||
deb [arch=amd64,i386] http://archive.ubuntu.com/ubuntu jammy main multiverse universe restricted
|
|
||||||
deb [arch=amd64,i386] http://archive.ubuntu.com/ubuntu jammy-security main multiverse universe restricted
|
|
||||||
deb [arch=amd64,i386] http://archive.ubuntu.com/ubuntu jammy-updates main multiverse universe restricted
|
|
||||||
deb [arch=amd64,i386] http://archive.ubuntu.com/ubuntu jammy-backports main multiverse universe restricted
|
|
||||||
|
|
||||||
deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy main multiverse universe restricted
|
|
||||||
deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security main multiverse universe restricted
|
|
||||||
deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates main multiverse universe restricted
|
|
||||||
deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-backports main multiverse universe restricted
|
|
||||||
EOF
|
|
||||||
|
|
||||||
sudo mv /etc/apt/sources.list /etc/apt/sources.list.default
|
|
||||||
sudo mv /tmp/sources.list /etc/apt/sources.list
|
|
||||||
|
|
||||||
sudo dpkg --add-architecture ${{ matrix.arch }}
|
|
||||||
sudo apt-get update -y
|
|
||||||
sudo apt-get -f install -y
|
|
||||||
|
|
||||||
sudo apt-get install -y \
|
|
||||||
linux-libc-dev:${{ matrix.arch }} \
|
|
||||||
libc6-dev:${{ matrix.arch }}
|
|
||||||
|
|
||||||
sudo apt-get install -y \
|
|
||||||
libxslt1.1:${{ matrix.arch }} \
|
|
||||||
libwebkit2gtk-4.1-dev:${{ matrix.arch }} \
|
|
||||||
libayatana-appindicator3-dev:${{ matrix.arch }} \
|
|
||||||
libssl-dev:${{ matrix.arch }} \
|
|
||||||
patchelf:${{ matrix.arch }} \
|
|
||||||
librsvg2-dev:${{ matrix.arch }}
|
|
||||||
|
|
||||||
- name: Install aarch64 tools
|
|
||||||
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
|
||||||
run: |
|
|
||||||
sudo apt install -y \
|
|
||||||
gcc-aarch64-linux-gnu \
|
|
||||||
g++-aarch64-linux-gnu
|
|
||||||
|
|
||||||
- name: Install armv7 tools
|
|
||||||
if: matrix.target == 'armv7-unknown-linux-gnueabihf'
|
|
||||||
run: |
|
|
||||||
sudo apt install -y \
|
|
||||||
gcc-arm-linux-gnueabihf \
|
|
||||||
g++-arm-linux-gnueabihf
|
|
||||||
|
|
||||||
- name: Build for Linux
|
|
||||||
run: |
|
|
||||||
export PKG_CONFIG_ALLOW_CROSS=1
|
|
||||||
if [ "${{ matrix.target }}" == "aarch64-unknown-linux-gnu" ]; then
|
|
||||||
export PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig/:$PKG_CONFIG_PATH
|
|
||||||
export PKG_CONFIG_SYSROOT_DIR=/usr/aarch64-linux-gnu/
|
|
||||||
elif [ "${{ matrix.target }}" == "armv7-unknown-linux-gnueabihf" ]; then
|
|
||||||
export PKG_CONFIG_PATH=/usr/lib/arm-linux-gnueabihf/pkgconfig/:$PKG_CONFIG_PATH
|
|
||||||
export PKG_CONFIG_SYSROOT_DIR=/usr/arm-linux-gnueabihf/
|
|
||||||
fi
|
|
||||||
pnpm build --target ${{ matrix.target }}
|
|
||||||
env:
|
|
||||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
|
||||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
|
||||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
|
||||||
|
|
||||||
- name: Get Version
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install jq
|
|
||||||
echo "VERSION=$(cat package.json | jq '.version' | tr -d '"')" >> $GITHUB_ENV
|
|
||||||
echo "BUILDTIME=$(TZ=Asia/Shanghai date)" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Upload Release
|
|
||||||
uses: softprops/action-gh-release@v2
|
|
||||||
with:
|
|
||||||
tag_name: ${{ env.TAG_NAME }}
|
|
||||||
name: "Clash Verge Rev ${{ env.TAG_CHANNEL }}"
|
|
||||||
prerelease: true
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
files: |
|
|
||||||
src-tauri/target/${{ matrix.target }}/release/bundle/deb/*.deb
|
|
||||||
src-tauri/target/${{ matrix.target }}/release/bundle/rpm/*.rpm
|
|
||||||
|
|
||||||
autobuild-x86-arm-windows_webview2:
|
|
||||||
name: Autobuild x86 and ARM Windows with WebView2
|
|
||||||
needs: update_tag
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- os: windows-latest
|
|
||||||
target: x86_64-pc-windows-msvc
|
|
||||||
arch: x64
|
|
||||||
- os: windows-latest
|
|
||||||
target: aarch64-pc-windows-msvc
|
|
||||||
arch: arm64
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout Repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Add Rust Target
|
|
||||||
run: rustup target add ${{ matrix.target }}
|
|
||||||
|
|
||||||
- name: Rust Cache
|
|
||||||
uses: Swatinem/rust-cache@v2
|
|
||||||
with:
|
|
||||||
workspaces: src-tauri
|
|
||||||
cache-all-crates: true
|
|
||||||
save-if: ${{ github.ref == 'refs/heads/dev' }}
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Install Node
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: "22"
|
|
||||||
cache: "pnpm"
|
|
||||||
|
|
||||||
- name: Pnpm install and check
|
|
||||||
run: |
|
|
||||||
pnpm i
|
|
||||||
pnpm run prebuild ${{ matrix.target }}
|
|
||||||
|
|
||||||
- name: Release ${{ env.TAG_CHANNEL }} Version
|
|
||||||
run: pnpm release-version ${{ env.TAG_NAME }}
|
|
||||||
|
|
||||||
- name: Download WebView2 Runtime
|
|
||||||
run: |
|
|
||||||
invoke-webrequest -uri https://github.com/westinyang/WebView2RuntimeArchive/releases/download/109.0.1518.78/Microsoft.WebView2.FixedVersionRuntime.109.0.1518.78.${{ matrix.arch }}.cab -outfile Microsoft.WebView2.FixedVersionRuntime.109.0.1518.78.${{ matrix.arch }}.cab
|
|
||||||
Expand .\Microsoft.WebView2.FixedVersionRuntime.109.0.1518.78.${{ matrix.arch }}.cab -F:* ./src-tauri
|
|
||||||
Remove-Item .\src-tauri\tauri.windows.conf.json
|
|
||||||
Rename-Item .\src-tauri\webview2.${{ matrix.arch }}.json tauri.windows.conf.json
|
|
||||||
|
|
||||||
- name: Tauri build
|
|
||||||
id: build
|
|
||||||
uses: tauri-apps/tauri-action@v0
|
|
||||||
env:
|
|
||||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
|
||||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
|
||||||
with:
|
|
||||||
tauriScript: pnpm
|
|
||||||
args: --target ${{ matrix.target }}
|
|
||||||
|
|
||||||
- name: Rename
|
|
||||||
run: |
|
|
||||||
$files = Get-ChildItem ".\src-tauri\target\${{ matrix.target }}\release\bundle\nsis\*-setup.exe"
|
|
||||||
foreach ($file in $files) {
|
|
||||||
$newName = $file.Name -replace "-setup\.exe$", "_fixed_webview2-setup.exe"
|
|
||||||
Rename-Item $file.FullName $newName
|
|
||||||
}
|
|
||||||
|
|
||||||
$files = Get-ChildItem ".\src-tauri\target\${{ matrix.target }}\release\bundle\nsis\*.nsis.zip"
|
|
||||||
foreach ($file in $files) {
|
|
||||||
$newName = $file.Name -replace "-setup\.nsis\.zip$", "_fixed_webview2-setup.nsis.zip"
|
|
||||||
Rename-Item $file.FullName $newName
|
|
||||||
}
|
|
||||||
|
|
||||||
$files = Get-ChildItem ".\src-tauri\target\${{ matrix.target }}\release\bundle\nsis\*-setup.exe.sig"
|
|
||||||
foreach ($file in $files) {
|
|
||||||
$newName = $file.Name -replace "-setup\.exe\.sig$", "_fixed_webview2-setup.exe.sig"
|
|
||||||
Rename-Item $file.FullName $newName
|
|
||||||
}
|
|
||||||
|
|
||||||
- name: Upload Release
|
|
||||||
uses: softprops/action-gh-release@v2
|
|
||||||
with:
|
|
||||||
tag_name: ${{ env.TAG_NAME }}
|
|
||||||
name: "Clash Verge Rev ${{ env.TAG_CHANNEL }}"
|
|
||||||
prerelease: true
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
files: src-tauri/target/${{ matrix.target }}/release/bundle/nsis/*setup*
|
|
||||||
|
|
||||||
- name: Portable Bundle
|
|
||||||
run: pnpm portable-fixed-webview2 ${{ matrix.target }} --${{ env.TAG_NAME }}
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
63
.github/workflows/clippy.yml
vendored
@@ -1,63 +0,0 @@
|
|||||||
name: Clippy Lint
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
clippy:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- os: windows-latest
|
|
||||||
target: x86_64-pc-windows-msvc
|
|
||||||
- os: macos-latest
|
|
||||||
target: aarch64-apple-darwin
|
|
||||||
- os: ubuntu-22.04
|
|
||||||
target: x86_64-unknown-linux-gnu
|
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout Repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install Rust Stable
|
|
||||||
uses: dtolnay/rust-toolchain@stable
|
|
||||||
|
|
||||||
- name: Add Rust Target
|
|
||||||
run: rustup target add ${{ matrix.target }}
|
|
||||||
|
|
||||||
- name: Rust Cache
|
|
||||||
uses: Swatinem/rust-cache@v2
|
|
||||||
with:
|
|
||||||
workspaces: src-tauri
|
|
||||||
save-if: false
|
|
||||||
|
|
||||||
- name: Install dependencies (ubuntu only)
|
|
||||||
if: matrix.os == 'ubuntu-22.04'
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y libxslt1.1 libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev patchelf
|
|
||||||
|
|
||||||
- name: Install Node
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: "22"
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Pnpm install and check
|
|
||||||
run: |
|
|
||||||
pnpm i
|
|
||||||
pnpm run prebuild ${{ matrix.target }}
|
|
||||||
|
|
||||||
- name: Build Web Assets
|
|
||||||
run: pnpm run web:build
|
|
||||||
env:
|
|
||||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
|
||||||
|
|
||||||
- name: Run Clippy
|
|
||||||
run: cargo clippy --manifest-path src-tauri/Cargo.toml --all-targets --all-features -- -D warnings
|
|
||||||
64
.github/workflows/cross_check.yaml
vendored
@@ -1,64 +0,0 @@
|
|||||||
name: Cross Platform Cargo Check
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
# pull_request:
|
|
||||||
# push:
|
|
||||||
# branches: [main, dev]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
cargo-check:
|
|
||||||
# Treat all Rust compiler warnings as errors
|
|
||||||
env:
|
|
||||||
RUSTFLAGS: "-D warnings"
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- os: macos-latest
|
|
||||||
target: aarch64-apple-darwin
|
|
||||||
- os: windows-latest
|
|
||||||
target: x86_64-pc-windows-msvc
|
|
||||||
- os: ubuntu-latest
|
|
||||||
target: x86_64-unknown-linux-gnu
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout Repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install Rust Stable
|
|
||||||
uses: dtolnay/rust-toolchain@stable
|
|
||||||
with:
|
|
||||||
targets: ${{ matrix.target }}
|
|
||||||
|
|
||||||
- name: Add Rust Target
|
|
||||||
run: rustup target add ${{ matrix.target }}
|
|
||||||
|
|
||||||
- name: Install Node
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: "20"
|
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v4
|
|
||||||
name: Install pnpm
|
|
||||||
with:
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Pnpm install and check
|
|
||||||
run: |
|
|
||||||
pnpm i
|
|
||||||
pnpm run prebuild ${{ matrix.target }}
|
|
||||||
|
|
||||||
- name: Rust Cache
|
|
||||||
uses: Swatinem/rust-cache@v2
|
|
||||||
with:
|
|
||||||
workspaces: src-tauri
|
|
||||||
save-if: false
|
|
||||||
|
|
||||||
- name: Cargo Check (deny warnings)
|
|
||||||
working-directory: src-tauri
|
|
||||||
run: |
|
|
||||||
cargo check --target ${{ matrix.target }} --workspace --all-features
|
|
||||||
93
.github/workflows/dev.yml
vendored
@@ -1,93 +0,0 @@
|
|||||||
name: Development Test
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
permissions: write-all
|
|
||||||
env:
|
|
||||||
CARGO_INCREMENTAL: 0
|
|
||||||
RUST_BACKTRACE: short
|
|
||||||
concurrency:
|
|
||||||
# only allow per workflow per commit (and not pr) to run at a time
|
|
||||||
group: "${{ github.workflow }} - ${{ github.head_ref || github.ref }}"
|
|
||||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
dev:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- os: windows-latest
|
|
||||||
target: x86_64-pc-windows-msvc
|
|
||||||
bundle: nsis
|
|
||||||
- os: macos-latest
|
|
||||||
target: aarch64-apple-darwin
|
|
||||||
bundle: dmg
|
|
||||||
- os: macos-latest
|
|
||||||
target: x86_64-apple-darwin
|
|
||||||
bundle: dmg
|
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout Repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install Rust Stable
|
|
||||||
uses: dtolnay/rust-toolchain@stable
|
|
||||||
|
|
||||||
- name: Add Rust Target
|
|
||||||
run: rustup target add ${{ matrix.target }}
|
|
||||||
|
|
||||||
- name: Rust Cache
|
|
||||||
uses: Swatinem/rust-cache@v2
|
|
||||||
with:
|
|
||||||
workspaces: src-tauri
|
|
||||||
save-if: false
|
|
||||||
|
|
||||||
- name: Install Node
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: "20"
|
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v4
|
|
||||||
name: Install pnpm
|
|
||||||
with:
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Pnpm install and check
|
|
||||||
run: |
|
|
||||||
pnpm i
|
|
||||||
pnpm run prebuild ${{ matrix.target }}
|
|
||||||
|
|
||||||
- name: Tauri build
|
|
||||||
uses: tauri-apps/tauri-action@v0
|
|
||||||
env:
|
|
||||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
|
||||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
|
||||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
|
||||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
|
||||||
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
|
|
||||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
|
||||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
|
||||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
|
||||||
with:
|
|
||||||
tauriScript: pnpm
|
|
||||||
args: --target ${{ matrix.target }} -b ${{ matrix.bundle }}
|
|
||||||
|
|
||||||
- name: Upload Artifacts
|
|
||||||
if: matrix.os == 'macos-latest'
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ${{ matrix.target }}
|
|
||||||
path: src-tauri/target/${{ matrix.target }}/release/bundle/dmg/*.dmg
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
- name: Upload Artifacts
|
|
||||||
if: matrix.os == 'windows-latest'
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ${{ matrix.target }}
|
|
||||||
path: src-tauri/target/${{ matrix.target }}/release/bundle/nsis/*.exe
|
|
||||||
if-no-files-found: error
|
|
||||||
50
.github/workflows/fmt.yml
vendored
@@ -1,50 +0,0 @@
|
|||||||
# Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
# SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
name: Check Formatting
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
rustfmt:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: install Rust stable and rustfmt
|
|
||||||
uses: dtolnay/rust-toolchain@stable
|
|
||||||
with:
|
|
||||||
components: rustfmt
|
|
||||||
|
|
||||||
- name: run cargo fmt
|
|
||||||
run: cargo fmt --manifest-path ./src-tauri/Cargo.toml --all -- --check
|
|
||||||
|
|
||||||
prettier:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: "lts/*"
|
|
||||||
- run: corepack enable
|
|
||||||
- run: pnpm install --frozen-lockfile
|
|
||||||
- run: pnpm format:check
|
|
||||||
|
|
||||||
# taplo:
|
|
||||||
# name: taplo (.toml files)
|
|
||||||
# runs-on: ubuntu-latest
|
|
||||||
# steps:
|
|
||||||
# - uses: actions/checkout@v4
|
|
||||||
|
|
||||||
# - name: install Rust stable
|
|
||||||
# uses: dtolnay/rust-toolchain@stable
|
|
||||||
|
|
||||||
# - name: install taplo-cli
|
|
||||||
# uses: taiki-e/install-action@v2
|
|
||||||
# with:
|
|
||||||
# tool: taplo-cli
|
|
||||||
|
|
||||||
# - run: taplo fmt --check --diff
|
|
||||||
394
.github/workflows/release.yml
vendored
@@ -1,48 +1,14 @@
|
|||||||
name: Release Build
|
name: Release Build
|
||||||
|
|
||||||
on:
|
on:
|
||||||
# ! 为了避免重复发布版本,应当通过独特 git tag 触发。
|
workflow_dispatch:
|
||||||
# ! 不再使用 workflow_dispatch 触发。
|
|
||||||
# workflow_dispatch:
|
|
||||||
push:
|
|
||||||
# 应当限制在 main 分支上触发发布。
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
# 应当限制 v*.*.* 的 tag 触发发布。
|
|
||||||
tags:
|
|
||||||
- "v*.*.*"
|
|
||||||
permissions: write-all
|
permissions: write-all
|
||||||
env:
|
env:
|
||||||
CARGO_INCREMENTAL: 0
|
CARGO_INCREMENTAL: 0
|
||||||
RUST_BACKTRACE: short
|
RUST_BACKTRACE: short
|
||||||
concurrency:
|
|
||||||
# only allow per workflow per commit (and not pr) to run at a time
|
|
||||||
group: "${{ github.workflow }} - ${{ github.head_ref || github.ref }}"
|
|
||||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check_tag_version:
|
|
||||||
name: Check Release Tag and package.json Version Consistency
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Check tag and package.json version
|
|
||||||
run: |
|
|
||||||
TAG_REF="${GITHUB_REF##*/}"
|
|
||||||
echo "Current tag: $TAG_REF"
|
|
||||||
PKG_VERSION=$(jq -r .version package.json)
|
|
||||||
echo "package.json version: $PKG_VERSION"
|
|
||||||
if [[ "$TAG_REF" != "v$PKG_VERSION" ]]; then
|
|
||||||
echo "Tag ($TAG_REF) does not match package.json version (v$PKG_VERSION)."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo "Tag and package.json version are consistent."
|
|
||||||
|
|
||||||
release:
|
release:
|
||||||
name: Release Build
|
|
||||||
needs: check_tag_version
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@@ -55,8 +21,6 @@ jobs:
|
|||||||
target: aarch64-apple-darwin
|
target: aarch64-apple-darwin
|
||||||
- os: macos-latest
|
- os: macos-latest
|
||||||
target: x86_64-apple-darwin
|
target: x86_64-apple-darwin
|
||||||
- os: ubuntu-22.04
|
|
||||||
target: x86_64-unknown-linux-gnu
|
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
@@ -73,272 +37,111 @@ jobs:
|
|||||||
uses: Swatinem/rust-cache@v2
|
uses: Swatinem/rust-cache@v2
|
||||||
with:
|
with:
|
||||||
workspaces: src-tauri
|
workspaces: src-tauri
|
||||||
save-if: false
|
|
||||||
|
|
||||||
- name: Install dependencies (ubuntu only)
|
|
||||||
if: matrix.os == 'ubuntu-22.04'
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y libxslt1.1 libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev patchelf
|
|
||||||
|
|
||||||
- name: Install Node
|
- name: Install Node
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: "22"
|
node-version: "20"
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v3
|
||||||
name: Install pnpm
|
name: Install pnpm
|
||||||
with:
|
with:
|
||||||
|
version: 9
|
||||||
run_install: false
|
run_install: false
|
||||||
|
|
||||||
- name: Pnpm install and check
|
- name: Pnpm install and check
|
||||||
run: |
|
run: |
|
||||||
pnpm i
|
pnpm i
|
||||||
pnpm run prebuild ${{ matrix.target }}
|
pnpm check ${{ matrix.target }}
|
||||||
|
|
||||||
- name: Tauri build
|
- name: Tauri build
|
||||||
uses: tauri-apps/tauri-action@v0
|
uses: tauri-apps/tauri-action@v0
|
||||||
env:
|
env:
|
||||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||||
with:
|
with:
|
||||||
tagName: v__VERSION__
|
tagName: v__VERSION__
|
||||||
releaseName: "Clash Verge Rev Lite v__VERSION__"
|
releaseName: "Clash Verge Rev v__VERSION__"
|
||||||
|
releaseBody: "More new features are now supported."
|
||||||
|
releaseDraft: false
|
||||||
|
prerelease: false
|
||||||
tauriScript: pnpm
|
tauriScript: pnpm
|
||||||
args: --target ${{ matrix.target }}
|
args: --target ${{ matrix.target }}
|
||||||
|
|
||||||
release-for-linux-arm:
|
- name: Portable Bundle
|
||||||
name: Release Build for Linux ARM
|
if: matrix.os == 'windows-latest'
|
||||||
|
run: pnpm portable ${{ matrix.target }}
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
|
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||||
|
|
||||||
|
release-for-linux:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- os: ubuntu-22.04
|
- os: ubuntu-latest
|
||||||
|
target: x86_64-unknown-linux-gnu
|
||||||
|
- os: ubuntu-latest
|
||||||
target: aarch64-unknown-linux-gnu
|
target: aarch64-unknown-linux-gnu
|
||||||
arch: arm64
|
- os: ubuntu-latest
|
||||||
- os: ubuntu-22.04
|
|
||||||
target: armv7-unknown-linux-gnueabihf
|
target: armv7-unknown-linux-gnueabihf
|
||||||
arch: armhf
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Repository
|
- name: Checkout Repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install Rust Stable
|
|
||||||
uses: dtolnay/rust-toolchain@stable
|
|
||||||
|
|
||||||
- name: Add Rust Target
|
|
||||||
run: rustup target add ${{ matrix.target }}
|
|
||||||
|
|
||||||
- name: Rust Cache
|
|
||||||
uses: Swatinem/rust-cache@v2
|
|
||||||
with:
|
|
||||||
workspaces: src-tauri
|
|
||||||
save-if: false
|
|
||||||
|
|
||||||
- name: Install Node
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: "22"
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Pnpm install and check
|
|
||||||
run: |
|
|
||||||
pnpm i
|
|
||||||
pnpm run prebuild ${{ matrix.target }}
|
|
||||||
|
|
||||||
- name: "Setup for linux"
|
|
||||||
run: |-
|
|
||||||
sudo ls -lR /etc/apt/
|
|
||||||
|
|
||||||
cat > /tmp/sources.list << EOF
|
|
||||||
deb [arch=amd64,i386] http://archive.ubuntu.com/ubuntu jammy main multiverse universe restricted
|
|
||||||
deb [arch=amd64,i386] http://archive.ubuntu.com/ubuntu jammy-security main multiverse universe restricted
|
|
||||||
deb [arch=amd64,i386] http://archive.ubuntu.com/ubuntu jammy-updates main multiverse universe restricted
|
|
||||||
deb [arch=amd64,i386] http://archive.ubuntu.com/ubuntu jammy-backports main multiverse universe restricted
|
|
||||||
|
|
||||||
deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy main multiverse universe restricted
|
|
||||||
deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security main multiverse universe restricted
|
|
||||||
deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates main multiverse universe restricted
|
|
||||||
deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-backports main multiverse universe restricted
|
|
||||||
EOF
|
|
||||||
|
|
||||||
sudo mv /etc/apt/sources.list /etc/apt/sources.list.default
|
|
||||||
sudo mv /tmp/sources.list /etc/apt/sources.list
|
|
||||||
|
|
||||||
sudo dpkg --add-architecture ${{ matrix.arch }}
|
|
||||||
sudo apt update
|
|
||||||
|
|
||||||
sudo apt install -y \
|
|
||||||
libxslt1.1:${{ matrix.arch }} \
|
|
||||||
libwebkit2gtk-4.1-dev:${{ matrix.arch }} \
|
|
||||||
libayatana-appindicator3-dev:${{ matrix.arch }} \
|
|
||||||
libssl-dev:${{ matrix.arch }} \
|
|
||||||
patchelf:${{ matrix.arch }} \
|
|
||||||
librsvg2-dev:${{ matrix.arch }}
|
|
||||||
|
|
||||||
- name: "Install aarch64 tools"
|
|
||||||
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
|
||||||
run: |
|
|
||||||
sudo apt install -y \
|
|
||||||
gcc-aarch64-linux-gnu \
|
|
||||||
g++-aarch64-linux-gnu
|
|
||||||
|
|
||||||
- name: "Install armv7 tools"
|
|
||||||
if: matrix.target == 'armv7-unknown-linux-gnueabihf'
|
|
||||||
run: |
|
|
||||||
sudo apt install -y \
|
|
||||||
gcc-arm-linux-gnueabihf \
|
|
||||||
g++-arm-linux-gnueabihf
|
|
||||||
|
|
||||||
- name: Build for Linux
|
- name: Build for Linux
|
||||||
run: |
|
uses: ./.github/build-for-linux
|
||||||
export PKG_CONFIG_ALLOW_CROSS=1
|
|
||||||
if [ "${{ matrix.target }}" == "aarch64-unknown-linux-gnu" ]; then
|
|
||||||
export PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig/:$PKG_CONFIG_PATH
|
|
||||||
export PKG_CONFIG_SYSROOT_DIR=/usr/aarch64-linux-gnu/
|
|
||||||
elif [ "${{ matrix.target }}" == "armv7-unknown-linux-gnueabihf" ]; then
|
|
||||||
export PKG_CONFIG_PATH=/usr/lib/arm-linux-gnueabihf/pkgconfig/:$PKG_CONFIG_PATH
|
|
||||||
export PKG_CONFIG_SYSROOT_DIR=/usr/arm-linux-gnueabihf/
|
|
||||||
fi
|
|
||||||
pnpm build --target ${{ matrix.target }}
|
|
||||||
env:
|
env:
|
||||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
with:
|
||||||
|
target: ${{ matrix.target }}
|
||||||
|
|
||||||
- name: Get Version
|
- name: Get Version
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install jq
|
sudo apt-get install jq
|
||||||
echo "VERSION=$(cat package.json | jq '.version' | tr -d '"')" >> $GITHUB_ENV
|
echo "VERSION=$(cat package.json | jq '.version' | tr -d '"')" >> $GITHUB_ENV
|
||||||
echo "BUILDTIME=$(TZ=Europe/Moscow date)" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Upload Release
|
- name: Upload Release
|
||||||
uses: softprops/action-gh-release@v2
|
if: startsWith(matrix.target, 'x86_64')
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
with:
|
with:
|
||||||
tag_name: v${{env.VERSION}}
|
tag_name: v${{env.VERSION}}
|
||||||
name: "Clash Verge Rev Lite v${{env.VERSION}}"
|
name: "Clash Verge Rev v${{env.VERSION}}"
|
||||||
|
body: "More new features are now supported."
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
files: |
|
files: src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage*
|
||||||
src-tauri/target/${{ matrix.target }}/release/bundle/deb/*.deb
|
|
||||||
src-tauri/target/${{ matrix.target }}/release/bundle/rpm/*.rpm
|
|
||||||
|
|
||||||
release-for-fixed-webview2:
|
|
||||||
name: Release Build for Fixed WebView2
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- os: windows-latest
|
|
||||||
target: x86_64-pc-windows-msvc
|
|
||||||
arch: x64
|
|
||||||
- os: windows-latest
|
|
||||||
target: aarch64-pc-windows-msvc
|
|
||||||
arch: arm64
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout Repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Add Rust Target
|
|
||||||
run: rustup target add ${{ matrix.target }}
|
|
||||||
|
|
||||||
- name: Rust Cache
|
|
||||||
uses: Swatinem/rust-cache@v2
|
|
||||||
with:
|
|
||||||
workspaces: src-tauri
|
|
||||||
save-if: false
|
|
||||||
|
|
||||||
- name: Install Node
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: "22"
|
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v4
|
|
||||||
name: Install pnpm
|
|
||||||
with:
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Pnpm install and check
|
|
||||||
run: |
|
|
||||||
pnpm i
|
|
||||||
pnpm run prebuild ${{ matrix.target }}
|
|
||||||
|
|
||||||
- name: Download WebView2 Runtime
|
|
||||||
run: |
|
|
||||||
invoke-webrequest -uri https://github.com/westinyang/WebView2RuntimeArchive/releases/download/133.0.3065.92/Microsoft.WebView2.FixedVersionRuntime.133.0.3065.92.${{ matrix.arch }}.cab -outfile Microsoft.WebView2.FixedVersionRuntime.133.0.3065.92.${{ matrix.arch }}.cab
|
|
||||||
Expand .\Microsoft.WebView2.FixedVersionRuntime.133.0.3065.92.${{ matrix.arch }}.cab -F:* ./src-tauri
|
|
||||||
Remove-Item .\src-tauri\tauri.windows.conf.json
|
|
||||||
Rename-Item .\src-tauri\webview2.${{ matrix.arch }}.json tauri.windows.conf.json
|
|
||||||
|
|
||||||
- name: Tauri build
|
|
||||||
id: build
|
|
||||||
uses: tauri-apps/tauri-action@v0
|
|
||||||
env:
|
|
||||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
|
||||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
|
||||||
with:
|
|
||||||
tauriScript: pnpm
|
|
||||||
args: --target ${{ matrix.target }}
|
|
||||||
|
|
||||||
- name: Rename
|
|
||||||
run: |
|
|
||||||
$files = Get-ChildItem ".\src-tauri\target\${{ matrix.target }}\release\bundle\nsis\*-setup.exe"
|
|
||||||
foreach ($file in $files) {
|
|
||||||
$newName = $file.Name -replace "-setup\.exe$", "_fixed_webview2-setup.exe"
|
|
||||||
Rename-Item $file.FullName $newName
|
|
||||||
}
|
|
||||||
|
|
||||||
$files = Get-ChildItem ".\src-tauri\target\${{ matrix.target }}\release\bundle\nsis\*.nsis.zip"
|
|
||||||
foreach ($file in $files) {
|
|
||||||
$newName = $file.Name -replace "-setup\.nsis\.zip$", "_fixed_webview2-setup.nsis.zip"
|
|
||||||
Rename-Item $file.FullName $newName
|
|
||||||
}
|
|
||||||
|
|
||||||
$files = Get-ChildItem ".\src-tauri\target\${{ matrix.target }}\release\bundle\nsis\*-setup.exe.sig"
|
|
||||||
foreach ($file in $files) {
|
|
||||||
$newName = $file.Name -replace "-setup\.exe\.sig$", "_fixed_webview2-setup.exe.sig"
|
|
||||||
Rename-Item $file.FullName $newName
|
|
||||||
}
|
|
||||||
|
|
||||||
- name: Upload Release
|
- name: Upload Release
|
||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v1
|
||||||
with:
|
with:
|
||||||
tag_name: v${{steps.build.outputs.appVersion}}
|
tag_name: v${{env.VERSION}}
|
||||||
name: "Clash Verge Rev Lite v${{steps.build.outputs.appVersion}}"
|
name: "Clash Verge Rev v${{env.VERSION}}"
|
||||||
|
body: "More new features are now supported."
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
files: src-tauri/target/${{ matrix.target }}/release/bundle/nsis/*setup*
|
files: src-tauri/target/${{ matrix.target }}/release/bundle/deb/*.deb
|
||||||
|
|
||||||
- name: Portable Bundle
|
|
||||||
run: pnpm portable-fixed-webview2 ${{ matrix.target }}
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
release-update:
|
release-update:
|
||||||
name: Release Update
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [release, release-for-linux-arm]
|
needs: [release, release-for-linux]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Install Node
|
- name: Install Node
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: "22"
|
node-version: "20"
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v2
|
||||||
name: Install pnpm
|
name: Install pnpm
|
||||||
with:
|
with:
|
||||||
|
version: 8
|
||||||
run_install: false
|
run_install: false
|
||||||
|
|
||||||
- name: Pnpm install
|
- name: Pnpm install
|
||||||
@@ -348,110 +151,3 @@ jobs:
|
|||||||
run: pnpm updater
|
run: pnpm updater
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
release-update-for-fixed-webview2:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [release-for-fixed-webview2]
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install Node
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: "22"
|
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v4
|
|
||||||
name: Install pnpm
|
|
||||||
with:
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Pnpm install
|
|
||||||
run: pnpm i
|
|
||||||
|
|
||||||
- name: Release updater file
|
|
||||||
run: pnpm updater-fixed-webview2
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
create_release_notes:
|
|
||||||
name: Create Release Notes
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Fetch UPDATE logs
|
|
||||||
id: fetch_update_logs
|
|
||||||
run: |
|
|
||||||
if [ -f "UPDATELOG.md" ]; then
|
|
||||||
UPDATE_LOGS=$(awk '/^## v/{if(flag) exit; flag=1} flag' UPDATELOG.md)
|
|
||||||
if [ -n "$UPDATE_LOGS" ]; then
|
|
||||||
echo "Found update logs"
|
|
||||||
echo "UPDATE_LOGS<<EOF" >> $GITHUB_ENV
|
|
||||||
echo "$UPDATE_LOGS" >> $GITHUB_ENV
|
|
||||||
echo "EOF" >> $GITHUB_ENV
|
|
||||||
else
|
|
||||||
echo "No update sections found in UPDATELOG.md"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "UPDATELOG.md file not found"
|
|
||||||
fi
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Get Version
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install jq
|
|
||||||
echo "VERSION=$(cat package.json | jq '.version' | tr -d '"')" >> $GITHUB_ENV
|
|
||||||
echo "BUILDTIME=$(TZ=Europe/Moscow date)" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- run: |
|
|
||||||
if [ -z "$UPDATE_LOGS" ]; then
|
|
||||||
echo "No update logs found, using default message"
|
|
||||||
UPDATE_LOGS="More new features are now supported. Check for detailed changelog soon."
|
|
||||||
else
|
|
||||||
echo "Using found update logs"
|
|
||||||
fi
|
|
||||||
|
|
||||||
cat > release.txt << EOF
|
|
||||||
$UPDATE_LOGS
|
|
||||||
|
|
||||||
## Which version should I download?
|
|
||||||
|
|
||||||
### macOS
|
|
||||||
<a href="https://github.com/coolcoala/clash-verge-rev-lite/releases/download/v${{ env.VERSION }}/Clash.Verge.Rev.Lite_${{ env.VERSION }}_aarch64.dmg"><img src="https://img.shields.io/badge/DMG-default?style=flat&logo=apple&label=Apple%20Silicon"></a><br>
|
|
||||||
<a href="https://github.com/coolcoala/clash-verge-rev-lite/releases/download/v${{ env.VERSION }}/Clash.Verge.Rev.Lite_${{ env.VERSION }}_x64.dmg"><img src="https://img.shields.io/badge/DMG-default?style=flat&logo=apple&label=Intel"></a><br>
|
|
||||||
> :warning: **Warning**
|
|
||||||
If you get a notification that the application is corrupted when you run it on macOS, run this command:<br>
|
|
||||||
<code>sudo xattr -r -c /Applications/Clash\ Verge\ Rev\ Lite.app</code>
|
|
||||||
|
|
||||||
### Linux
|
|
||||||
<a href="https://github.com/coolcoala/clash-verge-rev-lite/releases/download/v${{ env.VERSION }}/Clash.Verge.Rev.Lite_${{ env.VERSION }}_amd64.deb"><img src="https://img.shields.io/badge/x64-default?style=flat&logo=debian&label=DEB"> </a><br>
|
|
||||||
<a href="https://github.com/coolcoala/clash-verge-rev-lite/releases/download/v${{ env.VERSION }}/Clash.Verge.Rev.Lite-${{ env.VERSION }}-1.x86_64.rpm"><img src="https://img.shields.io/badge/x64-default?style=flat&logo=fedora&label=RPM"> </a>
|
|
||||||
|
|
||||||
<a href="https://github.com/coolcoala/clash-verge-rev-lite/releases/download/v${{ env.VERSION }}/Clash.Verge.Rev.Lite_${{ env.VERSION }}_arm64.deb"><img src="https://img.shields.io/badge/arm64-default?style=flat&logo=debian&label=DEB"> </a><br>
|
|
||||||
<a href="https://github.com/coolcoala/clash-verge-rev-lite/releases/download/v${{ env.VERSION }}/Clash.Verge.Rev.Lite-${{ env.VERSION }}-1.aarch64.rpm"><img src="https://img.shields.io/badge/aarch64-default?style=flat&logo=fedora&label=RPM"> </a>
|
|
||||||
|
|
||||||
<a href="https://github.com/coolcoala/clash-verge-rev-lite/releases/download/v${{ env.VERSION }}/Clash.Verge.Rev.Lite_${{ env.VERSION }}_armhf.deb"><img src="https://img.shields.io/badge/armhf-default?style=flat&logo=debian&label=DEB"> </a><br>
|
|
||||||
<a href="https://github.com/coolcoala/clash-verge-rev-lite/releases/download/v${{ env.VERSION }}/Clash.Verge.Rev.Lite-${{ env.VERSION }}-1.armhfp.rpm"><img src="https://img.shields.io/badge/armhfp-default?style=flat&logo=fedora&label=RPM"> </a>
|
|
||||||
|
|
||||||
### Windows (Win7 is no longer supported)
|
|
||||||
#### Normal version (recommended)
|
|
||||||
<a href="https://github.com/coolcoala/clash-verge-rev-lite/releases/download/v${{ env.VERSION }}/Clash.Verge.Rev.Lite_${{ env.VERSION }}_x64-setup.exe"><img src="https://badgen.net/badge/icon/x64?icon=windows&label=exe"></a><br>
|
|
||||||
<a href="https://github.com/coolcoala/clash-verge-rev-lite/releases/download/v${{ env.VERSION }}/Clash.Verge.Rev.Lite_${{ env.VERSION }}_arm64-setup.exe"><img src="https://badgen.net/badge/icon/arm64?icon=windows&label=exe"></a>
|
|
||||||
#### Portable version is no longer available with many problems
|
|
||||||
#### Built-in Webview version 2 (large size, only used in enterprise version of the system or can not install webview2)
|
|
||||||
<a href="https://github.com/coolcoala/clash-verge-rev-lite/releases/download/v${{ env.VERSION }}/Clash.Verge.Rev.Lite_${{ env.VERSION }}_x64_fixed_webview2-setup.exe"><img src="https://badgen.net/badge/icon/x64?icon=windows&label=exe"></a><br>
|
|
||||||
<a href="https://github.com/coolcoala/clash-verge-rev-lite/releases/download/v${{ env.VERSION }}/Clash.Verge.Rev.Lite_${{ env.VERSION }}_arm64_fixed_webview2-setup.exe"><img src="https://badgen.net/badge/icon/arm64?icon=windows&label=exe"></a>
|
|
||||||
|
|
||||||
Created at ${{ env.BUILDTIME }}.
|
|
||||||
EOF
|
|
||||||
|
|
||||||
- name: Upload Release
|
|
||||||
uses: softprops/action-gh-release@v2
|
|
||||||
with:
|
|
||||||
tag_name: v${{env.VERSION}}
|
|
||||||
name: "Clash Verge Rev Lite v${{env.VERSION}}"
|
|
||||||
body_path: release.txt
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|||||||
33
.github/workflows/updater.yml
vendored
@@ -7,16 +7,17 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Install Node
|
- name: Install Node
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: "22"
|
node-version: "20"
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v2
|
||||||
name: Install pnpm
|
name: Install pnpm
|
||||||
with:
|
with:
|
||||||
|
version: 8
|
||||||
run_install: false
|
run_install: false
|
||||||
|
|
||||||
- name: Pnpm install
|
- name: Pnpm install
|
||||||
@@ -26,27 +27,3 @@ jobs:
|
|||||||
run: pnpm updater
|
run: pnpm updater
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
release-update-for-fixed-webview2:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install Node
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: "22"
|
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v4
|
|
||||||
name: Install pnpm
|
|
||||||
with:
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Pnpm install
|
|
||||||
run: pnpm i
|
|
||||||
|
|
||||||
- name: Release updater file
|
|
||||||
run: pnpm updater-fixed-webview2
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|||||||
4
.gitignore
vendored
@@ -7,6 +7,4 @@ dist-ssr
|
|||||||
update.json
|
update.json
|
||||||
scripts/_env.sh
|
scripts/_env.sh
|
||||||
.vscode
|
.vscode
|
||||||
.tool-versions
|
.tool-versions
|
||||||
.idea
|
|
||||||
.old
|
|
||||||
@@ -1,26 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/bin/sh
|
||||||
|
. "$(dirname "$0")/_/husky.sh"
|
||||||
|
|
||||||
#pnpm pretty-quick --staged
|
pnpm pretty-quick --staged
|
||||||
|
|
||||||
if git diff --cached --name-only | grep -q '^src/'; then
|
|
||||||
pnpm format:check
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo "Code format check failed in src/. Please fix formatting issues."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if git diff --cached --name-only | grep -q '^src-tauri/'; then
|
|
||||||
cd src-tauri
|
|
||||||
cargo fmt
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo "rustfmt failed to format the code. Please fix the issues and try again."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
cd ..
|
|
||||||
fi
|
|
||||||
|
|
||||||
#git add .
|
|
||||||
|
|
||||||
# 允许提交
|
|
||||||
exit 0
|
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# $1: remote name (e.g., origin)
|
|
||||||
# $2: remote url (e.g., git@github.com:clash-verge-rev/clash-verge-rev.git)
|
|
||||||
|
|
||||||
if git diff --cached --name-only | grep -q '^src-tauri/'; then
|
|
||||||
cargo clippy --manifest-path ./src-tauri/Cargo.toml
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo "Clippy found issues in src-tauri. Please fix them before pushing."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 只在 push 到 origin 并且 origin 指向目标仓库时执行格式检查
|
|
||||||
if [ "$1" = "origin" ] && echo "$2" | grep -Eq 'github\.com[:/]+clash-verge-rev/clash-verge-rev(\.git)?$'; then
|
|
||||||
echo "[pre-push] Detected push to origin (clash-verge-rev/clash-verge-rev)"
|
|
||||||
echo "[pre-push] Running pnpm format:check..."
|
|
||||||
|
|
||||||
pnpm format:check
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo "❌ Code format check failed. Please fix formatting before pushing."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "[pre-push] Not pushing to target repo. Skipping format check."
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
# README.md
|
|
||||||
# UPDATELOG.md
|
|
||||||
# CONTRIBUTING.md
|
|
||||||
|
|
||||||
pnpm-lock.yaml
|
|
||||||
|
|
||||||
src-tauri/target/
|
|
||||||
src-tauri/gen/
|
|
||||||
16
.prettierrc
@@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"printWidth": 80,
|
|
||||||
"tabWidth": 2,
|
|
||||||
"useTabs": false,
|
|
||||||
"semi": true,
|
|
||||||
"singleQuote": false,
|
|
||||||
"jsxSingleQuote": false,
|
|
||||||
"trailingComma": "all",
|
|
||||||
"bracketSpacing": true,
|
|
||||||
"bracketSameLine": false,
|
|
||||||
"arrowParens": "always",
|
|
||||||
"proseWrap": "preserve",
|
|
||||||
"htmlWhitespaceSensitivity": "css",
|
|
||||||
"endOfLine": "lf",
|
|
||||||
"embeddedLanguageFormatting": "auto"
|
|
||||||
}
|
|
||||||
@@ -17,46 +17,25 @@ If you're a Windows user, you may need to perform some additional steps:
|
|||||||
- Make sure to add Rust and Node.js to your system's PATH. This is usually done during the installation process, but you can verify and manually add them if necessary.
|
- Make sure to add Rust and Node.js to your system's PATH. This is usually done during the installation process, but you can verify and manually add them if necessary.
|
||||||
- The gnu `patch` tool should be installed
|
- The gnu `patch` tool should be installed
|
||||||
|
|
||||||
When you setup `Rust` environment, Only use toolchain with `Windows MSVC` , to change settings follow command:
|
### Install Node.js Packages
|
||||||
|
|
||||||
|
After installing Rust and Node.js, install the necessary Node.js packages:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
rustup target add x86_64-pc-windows-msvc
|
pnpm i
|
||||||
rustup set default-host x86_64-pc-windows-msvc
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Install Node.js Package
|
### Download the Clash Binary
|
||||||
|
|
||||||
After installing Rust and Node.js, install the necessary Node.js and Node Package Manager:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
npm install pnpm -g
|
|
||||||
```
|
|
||||||
|
|
||||||
### Install Dependencies
|
|
||||||
|
|
||||||
Install node packages
|
|
||||||
|
|
||||||
```shell
|
|
||||||
pnpm install
|
|
||||||
```
|
|
||||||
|
|
||||||
Install apt packages ONLY for Ubuntu
|
|
||||||
|
|
||||||
```shell
|
|
||||||
apt-get install -y libxslt1.1 libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev patchelf
|
|
||||||
```
|
|
||||||
|
|
||||||
### Download the Mihomo Core Binary
|
|
||||||
|
|
||||||
You have two options for downloading the clash binary:
|
You have two options for downloading the clash binary:
|
||||||
|
|
||||||
- Automatically download it via the provided script:
|
- Automatically download it via the provided script:
|
||||||
```shell
|
```shell
|
||||||
pnpm run prebuild
|
pnpm run check
|
||||||
# Use '--force' to force update to the latest version
|
# Use '--force' to force update to the latest version
|
||||||
# pnpm run prebuild --force
|
# pnpm run check --force
|
||||||
```
|
```
|
||||||
- Manually download it from the [Mihomo release](https://github.com/MetaCubeX/mihomo/releases). After downloading, rename the binary according to the [Tauri configuration](https://tauri.app/v1/api/config#bundleconfig.externalbin).
|
- Manually download it from the [Clash Meta release](https://github.com/MetaCubeX/Clash.Meta/releases). After downloading, rename the binary according to the [Tauri configuration](https://tauri.app/v1/api/config#bundleconfig.externalbin).
|
||||||
|
|
||||||
### Run the Development Server
|
### Run the Development Server
|
||||||
|
|
||||||
@@ -70,63 +49,14 @@ pnpm dev:diff
|
|||||||
|
|
||||||
### Build the Project
|
### Build the Project
|
||||||
|
|
||||||
To build this project:
|
If you want to build the project, use:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
pnpm build
|
pnpm build
|
||||||
```
|
```
|
||||||
|
|
||||||
For a faster build, use the following command
|
|
||||||
|
|
||||||
```shell
|
|
||||||
pnpm build:fast
|
|
||||||
```
|
|
||||||
|
|
||||||
This uses Rust's fast-release profile which significantly reduces compilation time by disabling optimization and LTO. The resulting binary will be larger and less performant than the standard build, but it's useful for testing changes quickly.
|
|
||||||
|
|
||||||
The `Artifacts` will display in the `log` in the Terminal.
|
|
||||||
|
|
||||||
### Build clean
|
|
||||||
|
|
||||||
To clean rust build:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
pnpm clean
|
|
||||||
```
|
|
||||||
|
|
||||||
### Portable Version (Windows Only)
|
|
||||||
|
|
||||||
To package portable version after the build:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
pnpm portable
|
|
||||||
```
|
|
||||||
|
|
||||||
## Contributing Your Changes
|
## Contributing Your Changes
|
||||||
|
|
||||||
#### Before commit your changes
|
|
||||||
|
|
||||||
If you changed the rust code, it's recommanded to execute code style formatting and quailty checks.
|
|
||||||
|
|
||||||
1. Code quailty checks
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# For rust backend
|
|
||||||
$ clash-verge-rev: pnpm clippy
|
|
||||||
# For frontend (not yet).
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Code style formatting
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# For rust backend
|
|
||||||
$ clash-verge-rev: cd src-tauri
|
|
||||||
$ clash-verge-rev/src-tauri: cargo fmt
|
|
||||||
# For frontend
|
|
||||||
$ clash-verge-rev: pnpm format:check
|
|
||||||
$ clash-verge-rev: pnpm format
|
|
||||||
```
|
|
||||||
|
|
||||||
Once you have made your changes:
|
Once you have made your changes:
|
||||||
|
|
||||||
1. Fork the repository.
|
1. Fork the repository.
|
||||||
|
|||||||
47
README.md
@@ -1,7 +1,7 @@
|
|||||||
<h1 align="center">
|
<h1 align="center">
|
||||||
<img src="./src-tauri/icons/icon.png" alt="Clash" width="128" />
|
<img src="./src/assets/image/logo.png" alt="Clash" width="128" />
|
||||||
<br>
|
<br>
|
||||||
Fork of <a href="https://github.com/clash-verge-rev/clash-verge-rev">Clash Verge Rev</a>
|
Continuation of <a href="https://github.com/zzzgydi/clash-verge">Clash Verge</a>
|
||||||
<br>
|
<br>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
@@ -11,26 +11,45 @@ A Clash Meta GUI based on <a href="https://github.com/tauri-apps/tauri">Tauri</a
|
|||||||
|
|
||||||
## Preview
|
## Preview
|
||||||
|
|
||||||
| Dark | Light |
|

|
||||||
| ----------------------------------- | ------------------------------------ |
|
|
||||||
|  |  |
|
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
Go to the [Release page](https://github.com/coolcoala/clash-verge-rev-lite/releases) to download the corresponding installation package<br>
|
请到发布页面下载对应的安装包:[Release page](https://github.com/clash-verge-rev/clash-verge-rev/releases)<br>
|
||||||
|
Go to the [release page](https://github.com/clash-verge-rev/clash-verge-rev/releases) to download the corresponding installation package<br>
|
||||||
Supports Windows (x64/x86), Linux (x64/arm64) and macOS 10.15+ (intel/apple).
|
Supports Windows (x64/x86), Linux (x64/arm64) and macOS 10.15+ (intel/apple).
|
||||||
|
|
||||||
### Telegram channel: ---
|
### 安装说明和常见问题,请到[文档页](https://clash-verge-rev.github.io/)查看:[Doc](https://clash-verge-rev.github.io/)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### TG Group: [@clash_verge_rev](https://t.me/clash_verge_rev)
|
||||||
|
|
||||||
|
## Promotion
|
||||||
|
|
||||||
|
[狗狗加速 —— 技术流机场 Doggygo VPN](https://狗狗加速.com)
|
||||||
|
|
||||||
|
- 高性能海外机场,免费试用,优惠套餐,解锁流媒体,全球首家支持 Hysteria 协议。
|
||||||
|
- 使用 Clash Verge 专属邀请链接注册送 3 天,每天 1G 流量免费试用:https://verge.狗狗加速.com/#/register?code=oaxsAGo6
|
||||||
|
- Clash Verge 专属 8 折优惠码: verge20 (仅有 500 份)
|
||||||
|
- 优惠套餐每月仅需 15.8 元,160G 流量,年付 8 折
|
||||||
|
- 海外团队,无跑路风险,高达 50% 返佣
|
||||||
|
- 集群负载均衡设计,高速专线(兼容老客户端),极低延迟,无视晚高峰,4K 秒开
|
||||||
|
- 全球首家 Hysteria 协议机场,现已上线更快的 `Hysteria2` 协议(Clash Verge 客户端最佳搭配)
|
||||||
|
- 解锁流媒体及 ChatGPT
|
||||||
|
- 官网:https://狗狗加速.com
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Based on the powerful Rust and Tauri 2 frameworks.
|
- Since the clash core has been removed. The project no longer maintains the clash core, but only the Clash Meta core.
|
||||||
- Built-in [Clash.Meta(mihomo)](https://github.com/MetaCubeX/mihomo) kernel with support for switching between `Alpha` versions of the kernel.
|
- Profiles management and enhancement (by yaml and Javascript). [Doc](https://clash-verge-rev.github.io)
|
||||||
- Simple and beautiful user interface with support for custom theme colors, agent group/tray icons, and `CSS Injection`.
|
- Improved UI and supports custom theme color.
|
||||||
- Configuration file management, configuration file syntax hints.
|
- Built-in support [Clash.Meta(mihomo)](https://github.com/MetaCubeX/mihomo) core.
|
||||||
- System Agent and Guard, `TUN (Virtual NIC)` mode.
|
- System proxy setting and guard.
|
||||||
- Visual node and rule editing
|
|
||||||
- WebDav configuration backup and synchronization
|
### FAQ
|
||||||
|
|
||||||
|
Refer to [Doc FAQ Page](https://clash-verge-rev.github.io/faq/install/)
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
|
|||||||
908
UPDATELOG.md
@@ -1,36 +1,888 @@
|
|||||||
## v0.2.3
|
## v1.6.1
|
||||||
|
|
||||||
- fixed problem with profile inactivation after adding via deeplink on windows
|
### Features
|
||||||
- corrected layout on the proxy page, now all cards are the same size
|
|
||||||
- corrected announe transposition by \n
|
|
||||||
- corrected side menu in compressed window
|
|
||||||
- added check at the main toggle switch, now it cannot be enabled if there are no profiles.
|
|
||||||
|
|
||||||
|
- 鼠标悬浮显示当前订阅的名称 [#938](https://github.com/clash-verge-rev/clash-verge-rev/pull/938)
|
||||||
|
- 日志过滤支持正则表达式 [#959](https://github.com/clash-verge-rev/clash-verge-rev/pull/959)
|
||||||
|
- 更新 Clash 内核到 1.18.4
|
||||||
|
|
||||||
## v0.2.1
|
### Bugs Fixes
|
||||||
|
|
||||||
- added headers "announce-url", "update-always"
|
- 修复 Linux KDE 环境下系统代理无法开启的问题
|
||||||
- added a check for the presence of a profile, if it already exists, an update will be performed
|
- 窗口最大化图标调整 [#924](https://github.com/clash-verge-rev/clash-verge-rev/pull/924)
|
||||||
- fixed processing of links for displaying telegram icon on the main page
|
- 修改 MacOS 托盘点击行为(左键菜单,右键点击事件)
|
||||||
- added profile update button on the main page
|
- 修复 MacOS 服务模式安装失败的问题
|
||||||
|
|
||||||
## v0.2
|
---
|
||||||
|
|
||||||
- added handlers for "Announe", "Support-Url", "New-Sub-Domain", "Profile-Title" headers:
|
## v1.6.0
|
||||||
- for "Announce" and "Support-Url" added output of information on the main page
|
|
||||||
- for "New-Sub-Domain" and "Profile-Title" added change of profile details when it is updated
|
|
||||||
- added mode switching for toggle switch on the main screen in settings
|
|
||||||
- now either tun mode or system proxy can be enabled, enabling one will disable the other
|
|
||||||
- fixed sticking of some modal windows to window frames
|
|
||||||
- the menu for adding a profile has been simplified, most of the settings are hidden behind the advanced settings button
|
|
||||||
- added notification that a profile needs to be added to start working
|
|
||||||
- corrected profile cards in the profiles section
|
|
||||||
- corrected display of flags in proxy names on Windows
|
|
||||||
- fixed display of proxy groups on the main page if they were not “Selector”
|
|
||||||
|
|
||||||
## v0.1
|
### Features
|
||||||
|
|
||||||
- rewritten interface from MUI to shadcn/ui
|
- Meta(mihomo)内核回退 1.18.1(当前新版内核 hy2 协议有 bug,等修复后更新)
|
||||||
- rewritten main page:
|
- 多处界面细节调整 [#724](https://github.com/clash-verge-rev/clash-verge-rev/pull/724) [#799](https://github.com/clash-verge-rev/clash-verge-rev/pull/799) [#900](https://github.com/clash-verge-rev/clash-verge-rev/pull/900) [#901](https://github.com/clash-verge-rev/clash-verge-rev/pull/901)
|
||||||
- one big power button and lists with proxy selection
|
- Linux 下新增服务模式
|
||||||
- notifications when no profiles are available or service needs to be installed
|
- 新增订阅卡片右键可以打开机场首页
|
||||||
|
- url-test 支持手动选择、节点组 fixed 节点使用角标展示 [#840](https://github.com/clash-verge-rev/clash-verge-rev/pull/840)
|
||||||
|
- Clash 配置、Merge 配置提供 JSON Schema 语法支持、连接界面调整 [#887](https://github.com/clash-verge-rev/clash-verge-rev/pull/887)
|
||||||
|
- 修改 Merge 配置文件默认内容 [#889](https://github.com/clash-verge-rev/clash-verge-rev/pull/889)
|
||||||
|
- 修改 tun 模式默认 mtu 为 1500,老版本升级,需在 tun 模式设置下“重置为默认值”。
|
||||||
|
- 使用 npm 安装 meta-json-schema [#895](https://github.com/clash-verge-rev/clash-verge-rev/pull/895)
|
||||||
|
- 更新部分翻译 [#904](https://github.com/clash-verge-rev/clash-verge-rev/pull/904)
|
||||||
|
- 支持 ico 格式的任务栏图标
|
||||||
|
|
||||||
|
### Bugs Fixes
|
||||||
|
|
||||||
|
- 修复 Linux KDE 环境下系统代理无法开启的问题
|
||||||
|
- 修复延迟检测动画问题
|
||||||
|
- 窗口最大化图标调整 [#816](https://github.com/clash-verge-rev/clash-verge-rev/pull/816)
|
||||||
|
- 修复 Windows 某些情况下无法安装服务模式 [#822](https://github.com/clash-verge-rev/clash-verge-rev/pull/822)
|
||||||
|
- UI 细节修复 [#821](https://github.com/clash-verge-rev/clash-verge-rev/pull/821)
|
||||||
|
- 修复使用默认编辑器打开配置文件
|
||||||
|
- 修复内核文件在特定目录也可以更新的问题 [#857](https://github.com/clash-verge-rev/clash-verge-rev/pull/857)
|
||||||
|
- 修复服务模式的安装目录问题
|
||||||
|
- 修复删除配置文件的“更新间隔”出现的问题 [#907](https://github.com/clash-verge-rev/clash-verge-rev/issues/907)
|
||||||
|
|
||||||
|
### 已知问题(历史遗留问题,暂未找到有效解决方案)
|
||||||
|
|
||||||
|
- MacOS M 芯片下服务模式无法安装;临时解决方案:在内核 ⚙️ 下,手动授权,再打开 tun 模式。
|
||||||
|
- MacOS 下如果删除过网络配置,会导致无法正常打开系统代理;临时解决方案:使用浏览器代理插件或手动配置系统代理。
|
||||||
|
- Window 拨号连接下无法正确识别并打开系统代理;临时解决方案:使用浏览器代理插件或使用 tun 模式。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.5.11
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- Meta(mihomo)内核更新 1.18.2
|
||||||
|
|
||||||
|
### Bugs Fixes
|
||||||
|
|
||||||
|
- 升级图标无法点击的问题
|
||||||
|
- 卸载时检查安装目录是否为空
|
||||||
|
- 代理界面图标重合的问题
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.5.10
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- 优化 Linux 托盘菜单显示
|
||||||
|
- 添加透明代理端口设置
|
||||||
|
- 删除订阅前确认
|
||||||
|
|
||||||
|
### Bugs Fixes
|
||||||
|
|
||||||
|
- 删除 MacOS 程序坞图标
|
||||||
|
- Windows 下 service 日志没有清理
|
||||||
|
- MacOS 无法开启系统代理
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.5.9
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- 缓存代理组图标
|
||||||
|
- 使用`boa_engine` 代替 `rquickjs`
|
||||||
|
- 支持 Linux armv7
|
||||||
|
|
||||||
|
### Bugs Fixes
|
||||||
|
|
||||||
|
- Windows 首次安装无法点击
|
||||||
|
- Windows 触摸屏无法拖动
|
||||||
|
- 规则列表 `REJECT-DROP` 颜色
|
||||||
|
- MacOS Dock 栏不显示图标
|
||||||
|
- MacOS 自定义字体无效
|
||||||
|
- 避免使用空 UA 拉取订阅
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.5.8
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- 优化 UI 细节
|
||||||
|
- Linux 绘制窗口圆角
|
||||||
|
- 开放 DevTools
|
||||||
|
|
||||||
|
### Bugs Fixes
|
||||||
|
|
||||||
|
- 修复 MacOS 下开启 Tun 内核崩溃的问题
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.5.7
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- 优化 UI 各种细节
|
||||||
|
- 提供菜单栏图标样式切换选项(单色/彩色/禁用)
|
||||||
|
- 添加自动检查更新开关
|
||||||
|
- MacOS 开启 Tun 模式自动修改 DNS
|
||||||
|
- 调整可拖动区域(尝试修复触摸屏无法拖动的问题)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.5.6
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- 全新专属 Verge rev UI 界面 (by @Amnesiash) 及细节调整
|
||||||
|
- 提供允许无效证书的开关
|
||||||
|
- 删除不必要的快捷键
|
||||||
|
- Provider 更新添加动画
|
||||||
|
- Merge 支持 Provider
|
||||||
|
- 更换订阅框的粘贴按钮,删除默认的"Remote File" Profile 名称
|
||||||
|
- 链接菜单添加节点显示
|
||||||
|
|
||||||
|
### Bugs Fixes
|
||||||
|
|
||||||
|
- Linux 下图片显示错误
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.5.4
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- 支持自定义托盘图标
|
||||||
|
- 支持禁用代理组图标
|
||||||
|
- 代理组显示当前代理
|
||||||
|
- 修改 `打开面板` 快捷键为`打开/关闭面板`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.5.3
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- Tun 设置添加重置按钮
|
||||||
|
|
||||||
|
### Bugs Fixes
|
||||||
|
|
||||||
|
- Tun 设置项显示错误的问题
|
||||||
|
- 修改一些默认值
|
||||||
|
- 启动时不更改启动项设置
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.5.2
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- 支持自定义延迟测试超时时间
|
||||||
|
- 优化 Tun 相关设置
|
||||||
|
|
||||||
|
### Bugs Fixes
|
||||||
|
|
||||||
|
- Merge 操作出错
|
||||||
|
- 安装后重启服务
|
||||||
|
- 修复管理员权限启动时开机启动失效的问题
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.5.1
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- 保存窗口最大化状态
|
||||||
|
- Proxy Provider 显示数量
|
||||||
|
- 不再提供 32 位安装包(因为 32 位经常出现各种奇怪问题,比如 tun 模式无法开启;现在系统也几乎没有 32 位了)
|
||||||
|
|
||||||
|
### Bugs Fixes
|
||||||
|
|
||||||
|
- 优化设置项名称
|
||||||
|
- 自定义 GLOBAL 代理组时代理组显示错误的问题
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.5.0
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- 删除 Clash 字段过滤功能
|
||||||
|
- 添加 socks 端口和 http 端口设置
|
||||||
|
- 升级内核到 1.18.1
|
||||||
|
|
||||||
|
### Bugs Fixes
|
||||||
|
|
||||||
|
- 修复 32 位版本无法显示流量信息的问题
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.4.11
|
||||||
|
|
||||||
|
### Break Changes
|
||||||
|
|
||||||
|
- 此版本更改了 Windows 安装包安装模式,需要卸载后手动安装,否则无法安装到正确位置
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- 优化了系统代理开启的代码,解决了稀有场景下代理开启卡顿的问题
|
||||||
|
- 添加 MacOS 下的 debug 日志,以便日后调试稀有场景下 MacOS 下无法开启系统代理的问题
|
||||||
|
- MacOS 关闭 GUI 时同步杀除后台 GUI [#306](https://github.com/clash-verge-rev/clash-verge-rev/issues/306)
|
||||||
|
|
||||||
|
### Bugs Fixes
|
||||||
|
|
||||||
|
- 解决自动更新时文件占用问题
|
||||||
|
- 解决稀有场景下系统代理开启失败的问题
|
||||||
|
- 删除冗余内核代码
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.4.10
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- 设置中添加退出按钮
|
||||||
|
- 支持自定义软件启动页
|
||||||
|
- 在 Proxy Provider 页面展示订阅信息
|
||||||
|
- 优化 Provider 支持
|
||||||
|
|
||||||
|
### Bugs Fixes
|
||||||
|
|
||||||
|
- 更改端口时立即重设系统代理
|
||||||
|
- 网站测试超时错误
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.4.9
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- 支持启动时运行脚本
|
||||||
|
- 支持代理组显示图标
|
||||||
|
- 新增测试页面
|
||||||
|
|
||||||
|
### Bugs Fixes
|
||||||
|
|
||||||
|
- 连接页面时间排序错误
|
||||||
|
- 连接页面表格宽度优化
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.4.8
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- 连接页面总流量显示
|
||||||
|
|
||||||
|
### Bugs Fixes
|
||||||
|
|
||||||
|
- 连接页面数据排序错误
|
||||||
|
- 新建订阅时设置更新间隔无效
|
||||||
|
- Windows 拨号网络无法设置系统代理
|
||||||
|
- Windows 开启/关闭系统代理延迟(使用注册表即可)
|
||||||
|
- 删除无效的背景模糊选项
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.4.7
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- Windows 便携版禁用应用内更新
|
||||||
|
- 支持代理组 Hidden 选项
|
||||||
|
- 支持 URL Scheme(MacOS & Linux)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.4.6
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- 更新 Clash Meta(mihomo) 内核到 v1.18.0
|
||||||
|
- 支持 URL Scheme(暂时仅支持 Windows)
|
||||||
|
- 添加窗口置顶按钮
|
||||||
|
- UI 优化调整
|
||||||
|
|
||||||
|
### Bugs Fixes
|
||||||
|
|
||||||
|
- 修复一些编译错误
|
||||||
|
- 获取订阅名称错误
|
||||||
|
- 订阅信息解析错误
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.4.5
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- 更新 MacOS 托盘图标样式(@gxx2778 贡献)
|
||||||
|
|
||||||
|
### Bugs Fixes
|
||||||
|
|
||||||
|
- Windows 下更新时无法覆盖`clash-verge-service.exe`的问题(需要卸载重装一次服务,下次更新生效)
|
||||||
|
- 窗口最大化按钮变化问题
|
||||||
|
- 窗口尺寸保存错误问题
|
||||||
|
- 复制环境变量类型无法切换问题
|
||||||
|
- 某些情况下闪退的问题
|
||||||
|
- 某些订阅无法导入的问题
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.4.4
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- 支持 Windows aarch64(arm64) 版本
|
||||||
|
- 支持一键更新 GeoData
|
||||||
|
- 支持一键更新 Alpha 内核
|
||||||
|
- MacOS 支持在系统代理时显示不同的托盘图标
|
||||||
|
- Linux 支持在系统代理时显示不同的托盘图标
|
||||||
|
- 优化复制环境变量逻辑
|
||||||
|
|
||||||
|
### Bugs Fixes
|
||||||
|
|
||||||
|
- 修改 PID 文件的路径
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
|
||||||
|
- 优化创建窗口的速度
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.4.3
|
||||||
|
|
||||||
|
### Break Changes
|
||||||
|
|
||||||
|
- 更改配置文件路径到标准目录(可以保证卸载时没有残留)
|
||||||
|
- 更改 appid 为 `io.github.clash-verge-rev.clash-verge-rev`
|
||||||
|
- 建议卸载旧版本后再安装新版本,该版本安装后不会使用旧版配置文件,你可以手动将旧版配置文件迁移到新版配置文件目录下
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- 移除页面切换动画
|
||||||
|
- 更改 Tun 模式托盘图标颜色
|
||||||
|
- Portable 版本默认使用当前目录作为配置文件目录
|
||||||
|
- 禁用 Clash 字段过滤时隐藏 Clash 字段选项
|
||||||
|
- 优化拖拽时光标样式
|
||||||
|
|
||||||
|
### Bugs Fixes
|
||||||
|
|
||||||
|
- 修复 windows 下更新时没有关闭内核导致的更新失败的问题
|
||||||
|
- 修复打开文件报错的问题
|
||||||
|
- 修复 url 导入时无法获取中文配置名称的问题
|
||||||
|
- 修复 alpha 内核无法显示内存信息的问题
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.4.2
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- update clash meta core to mihomo 1.17.0
|
||||||
|
- support both clash meta stable release and prerelease-alpha release
|
||||||
|
- fixed the problem of not being able to set the system proxy when there is a dial-up link on windows system [#833](https://github.com/zzzgydi/clash-verge/issues/833)
|
||||||
|
- support new clash field
|
||||||
|
- support random mixed port
|
||||||
|
- add windows x86 and linux armv7 support
|
||||||
|
- support disable tray click event
|
||||||
|
- add download progress for updater
|
||||||
|
- support drag to reorder the profile
|
||||||
|
- embed emoji fonts
|
||||||
|
- update depends
|
||||||
|
- improve UI style
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.4.1
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- update clash meta core to newest 虚空终端(2023.11.23)
|
||||||
|
- delete clash core UI
|
||||||
|
- improve UI
|
||||||
|
- change Logo to original
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.4.0
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- update clash meta core to newest 虚空终端
|
||||||
|
- delete clash core, no longer maintain
|
||||||
|
- merge Clash nyanpasu changes
|
||||||
|
- remove delay display different color
|
||||||
|
- use Meta Country.mmdb
|
||||||
|
- update dependencies
|
||||||
|
- small changes here and there
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.3.8
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- update clash meta core
|
||||||
|
- add default valid keys
|
||||||
|
- adjust the delay display interval and color
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- fix connections page undefined exception
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.3.7
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- update clash and clash meta core
|
||||||
|
- profiles page add paste button
|
||||||
|
- subscriptions url textfield use multi lines
|
||||||
|
- set min window size
|
||||||
|
- add check for updates buttons
|
||||||
|
- add open dashboard to the hotkey list
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- fix profiles page undefined exception
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.3.6
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- add russian translation
|
||||||
|
- support to show connection detail
|
||||||
|
- support clash meta memory usage display
|
||||||
|
- support proxy provider update ui
|
||||||
|
- update geo data file from meta repo
|
||||||
|
- adjust setting page
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- center the window when it is out of screen
|
||||||
|
- use `sudo` when `pkexec` not found (Linux)
|
||||||
|
- reconnect websocket when window focus
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
|
||||||
|
- The current version of the Linux installation package is built by Ubuntu 20.04 (Github Action).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.3.5
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- update clash core
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- fix blurry system tray icon (Windows)
|
||||||
|
- fix v1.3.4 wintun.dll not found (Windows)
|
||||||
|
- fix v1.3.4 clash core not found (macOS, Linux)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.3.4
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- update clash and clash meta core
|
||||||
|
- optimize traffic graph high CPU usage when window hidden
|
||||||
|
- use polkit to elevate permission (Linux)
|
||||||
|
- support app log level setting
|
||||||
|
- support copy environment variable
|
||||||
|
- overwrite resource file according to file modified
|
||||||
|
- save window size and position
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- remove fallback group select status
|
||||||
|
- enable context menu on editable element (Windows)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.3.3
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- update clash and clash meta core
|
||||||
|
- show tray icon variants in different system proxy status (Windows)
|
||||||
|
- close all connections when mode changed
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- encode controller secret into uri
|
||||||
|
- error boundary for each page
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.3.2
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- update clash and clash meta core
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- fix import url issue
|
||||||
|
- fix profile undefined issue
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.3.1
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- update clash and clash meta core
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- fix open url issue
|
||||||
|
- fix appimage path panic
|
||||||
|
- fix grant root permission in macOS
|
||||||
|
- fix linux system proxy default bypass
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.3.0
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- update clash and clash meta
|
||||||
|
- support opening dir on tray
|
||||||
|
- support updating all profiles with one click
|
||||||
|
- support granting root permission to clash core(Linux, macOS)
|
||||||
|
- support enable/disable clash fields filter, feel free to experience the latest features of Clash Meta
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- deb add openssl depend(Linux)
|
||||||
|
- fix the AppImage auto launch path(Linux)
|
||||||
|
- fix get the default network service(macOS)
|
||||||
|
- remove the esc key listener in macOS, cmd+w instead(macOS)
|
||||||
|
- fix infinite retry when websocket error
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.2.3
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- update clash
|
||||||
|
- adjust macOS window style
|
||||||
|
- profile supports UTF8 with BOM
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- fix selected proxy
|
||||||
|
- fix error log
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.2.2
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- update clash meta
|
||||||
|
- recover clash core after panic
|
||||||
|
- use system window decorations(Linux)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- flush system proxy settings(Windows)
|
||||||
|
- fix parse log panic
|
||||||
|
- fix ui bug
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.2.1
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- update clash version
|
||||||
|
- proxy groups support multi columns
|
||||||
|
- optimize ui
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- fix ui websocket connection
|
||||||
|
- adjust delay check concurrency
|
||||||
|
- avoid setting login item repeatedly(macOS)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.2.0
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- update clash meta version
|
||||||
|
- support to change external-controller
|
||||||
|
- support to change default latency test URL
|
||||||
|
- close all connections when proxy changed or profile changed
|
||||||
|
- check the config by using the core
|
||||||
|
- increase the robustness of the program
|
||||||
|
- optimize windows service mode (need to reinstall)
|
||||||
|
- optimize ui
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- invalid hotkey cause panic
|
||||||
|
- invalid theme setting cause panic
|
||||||
|
- fix some other glitches
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.1.2
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- the system tray follows i18n
|
||||||
|
- change the proxy group ui of global mode
|
||||||
|
- support to update profile with the system proxy/clash proxy
|
||||||
|
- check the remote profile more strictly
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- use app version as default user agent
|
||||||
|
- the clash not exit in service mode
|
||||||
|
- reset the system proxy when quit the app
|
||||||
|
- fix some other glitches
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.1.1
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- optimize clash config feedback
|
||||||
|
- hide macOS dock icon
|
||||||
|
- use clash meta compatible version (Linux)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- fix some other glitches
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.1.0
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- add rule page
|
||||||
|
- supports proxy providers delay check
|
||||||
|
- add proxy delay check loading status
|
||||||
|
- supports hotkey/shortcut management
|
||||||
|
- supports displaying connections data in table layout(refer to yacd)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- supports yaml merge key in clash config
|
||||||
|
- detect the network interface and set the system proxy(macOS)
|
||||||
|
- fix some other glitches
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.0.6
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- update clash and clash.meta
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- only script profile display console
|
||||||
|
- automatic configuration update on demand at launch
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.0.5
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- reimplement profile enhanced mode with quick-js
|
||||||
|
- optimize the runtime config generation process
|
||||||
|
- support web ui management
|
||||||
|
- support clash field management
|
||||||
|
- support viewing the runtime config
|
||||||
|
- adjust some pages style
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- fix silent start
|
||||||
|
- fix incorrectly reset system proxy on exit
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.0.4
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- update clash core and clash meta version
|
||||||
|
- support switch clash mode on system tray
|
||||||
|
- theme mode support follows system
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- config load error on first use
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.0.3
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- save some states such as URL test, filter, etc
|
||||||
|
- update clash core and clash-meta core
|
||||||
|
- new icon for macOS
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.0.2
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- supports for switching clash core
|
||||||
|
- supports release UI processes
|
||||||
|
- supports script mode setting
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- fix service mode bug (Windows)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.0.1
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- adjust default theme settings
|
||||||
|
- reduce gpu usage of traffic graph when hidden
|
||||||
|
- supports more remote profile response header setting
|
||||||
|
- check remote profile data format when imported
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- service mode install and start issue (Windows)
|
||||||
|
- fix launch panic (Some Windows)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.0.0
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- update clash core
|
||||||
|
- optimize traffic graph animation
|
||||||
|
- supports interval update profiles
|
||||||
|
- supports service mode (Windows)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- reset system proxy when exit from dock (macOS)
|
||||||
|
- adjust clash dns config process strategy
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v0.0.29
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- sort proxy node
|
||||||
|
- custom proxy test url
|
||||||
|
- logs page filter
|
||||||
|
- connections page filter
|
||||||
|
- default user agent for subscription
|
||||||
|
- system tray add tun mode toggle
|
||||||
|
- enable to change the config dir (Windows only)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v0.0.28
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- enable to use clash config fields (UI)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- remove the character
|
||||||
|
- fix some icon color
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v0.0.27
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- supports custom theme color
|
||||||
|
- tun mode setting control the final config
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- fix transition flickers (macOS)
|
||||||
|
- reduce proxy page render
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v0.0.26
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- silent start
|
||||||
|
- profile editor
|
||||||
|
- profile enhance mode supports more fields
|
||||||
|
- optimize profile enhance mode strategy
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- fix csp restriction on macOS
|
||||||
|
- window controllers on Linux
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v0.0.25
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- update clash core version
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- app updater error
|
||||||
|
- display window controllers on Linux
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
|
||||||
|
If you can't update the app properly, please consider downloading the latest version from github release.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v0.0.24
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- Connections page
|
||||||
|
- add wintun.dll (Windows)
|
||||||
|
- supports create local profile with selected file (Windows)
|
||||||
|
- system tray enable set system proxy
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- open dir error
|
||||||
|
- auto launch path (Windows)
|
||||||
|
- fix some clash config error
|
||||||
|
- reduce the impact of the enhanced mode
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v0.0.23
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- i18n supports
|
||||||
|
- Remote profile User Agent supports
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- clash config file case ignore
|
||||||
|
- clash `external-controller` only port
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://ui.shadcn.com/schema.json",
|
|
||||||
"style": "new-york",
|
|
||||||
"rsc": false,
|
|
||||||
"tsx": true,
|
|
||||||
"tailwind": {
|
|
||||||
"config": "",
|
|
||||||
"css": "src/index.css",
|
|
||||||
"baseColor": "slate",
|
|
||||||
"cssVariables": true,
|
|
||||||
"prefix": ""
|
|
||||||
},
|
|
||||||
"aliases": {
|
|
||||||
"components": "@root/src/components",
|
|
||||||
"utils": "@root/lib/utils",
|
|
||||||
"ui": "@root/src/components/ui",
|
|
||||||
"lib": "@root/lib",
|
|
||||||
"hooks": "@root/hooks"
|
|
||||||
},
|
|
||||||
"iconLibrary": "lucide"
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
files:
|
|
||||||
- source: /src/locales/en.json
|
|
||||||
translation: /src/locales
|
|
||||||
multilingual: 1
|
|
||||||
BIN
docs/preview.png
Normal file
|
After Width: | Height: | Size: 576 KiB |
|
Before Width: | Height: | Size: 712 KiB |
|
Before Width: | Height: | Size: 671 KiB |
@@ -1,19 +0,0 @@
|
|||||||
import * as React from "react"
|
|
||||||
|
|
||||||
const MOBILE_BREAKPOINT = 768
|
|
||||||
|
|
||||||
export function useIsMobile() {
|
|
||||||
const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
|
|
||||||
const onChange = () => {
|
|
||||||
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
|
||||||
}
|
|
||||||
mql.addEventListener("change", onChange)
|
|
||||||
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
|
||||||
return () => mql.removeEventListener("change", onChange)
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
return !!isMobile
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
import { clsx, type ClassValue } from "clsx";
|
|
||||||
import { twMerge } from "tailwind-merge";
|
|
||||||
|
|
||||||
export function cn(...inputs: ClassValue[]) {
|
|
||||||
return twMerge(clsx(inputs));
|
|
||||||
}
|
|
||||||
171
package.json
@@ -1,146 +1,83 @@
|
|||||||
{
|
{
|
||||||
"name": "clash-verge",
|
"name": "clash-verge",
|
||||||
"version": "0.2.3",
|
"version": "1.6.1",
|
||||||
"license": "GPL-3.0-only",
|
"license": "GPL-3.0-only",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "cross-env RUST_BACKTRACE=1 tauri dev -f verge-dev",
|
"dev": "tauri dev",
|
||||||
"dev:diff": "cross-env RUST_BACKTRACE=1 tauri dev -f verge-dev",
|
"dev:diff": "tauri dev -f verge-dev",
|
||||||
"build": "cross-env NODE_OPTIONS='--max-old-space-size=4096' tauri build",
|
"build": "tauri build",
|
||||||
"build:fast": "cross-env NODE_OPTIONS='--max-old-space-size=4096' tauri build -- --profile fast-release",
|
|
||||||
"tauri": "tauri",
|
"tauri": "tauri",
|
||||||
"web:dev": "vite",
|
"web:dev": "vite",
|
||||||
"web:build": "tsc --noEmit && vite build",
|
"web:build": "tsc && vite build",
|
||||||
"web:serve": "vite preview",
|
"web:serve": "vite preview",
|
||||||
"prebuild": "node scripts/prebuild.mjs",
|
"check": "node scripts/check.mjs",
|
||||||
"updater": "node scripts/updater.mjs",
|
"updater": "node scripts/updater.mjs",
|
||||||
"updater-fixed-webview2": "node scripts/updater-fixed-webview2.mjs",
|
|
||||||
"portable": "node scripts/portable.mjs",
|
"portable": "node scripts/portable.mjs",
|
||||||
"portable-fixed-webview2": "node scripts/portable-fixed-webview2.mjs",
|
"prepare": "husky install"
|
||||||
"fix-alpha-version": "node scripts/fix-alpha_version.mjs",
|
|
||||||
"release-version": "node scripts/release-version.mjs",
|
|
||||||
"publish-version": "node scripts/publish-version.mjs",
|
|
||||||
"fmt": "cargo fmt --manifest-path ./src-tauri/Cargo.toml",
|
|
||||||
"clippy": "cargo clippy --manifest-path ./src-tauri/Cargo.toml",
|
|
||||||
"format": "prettier --write .",
|
|
||||||
"format:check": "prettier --check ."
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@dnd-kit/core": "^6.3.1",
|
"@dnd-kit/core": "^6.1.0",
|
||||||
"@dnd-kit/sortable": "^10.0.0",
|
"@dnd-kit/sortable": "^8.0.0",
|
||||||
"@dnd-kit/utilities": "^3.2.2",
|
"@dnd-kit/utilities": "^3.2.2",
|
||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.11.4",
|
||||||
"@emotion/styled": "^11.14.0",
|
"@emotion/styled": "^11.11.5",
|
||||||
"@hookform/resolvers": "^5.1.1",
|
|
||||||
"@juggle/resize-observer": "^3.4.0",
|
"@juggle/resize-observer": "^3.4.0",
|
||||||
"@mui/icons-material": "^7.1.1",
|
"@mui/icons-material": "^5.15.15",
|
||||||
"@mui/lab": "7.0.0-beta.13",
|
"@mui/lab": "5.0.0-alpha.149",
|
||||||
"@mui/material": "^7.1.1",
|
"@mui/material": "^5.15.15",
|
||||||
"@mui/x-data-grid": "^8.5.1",
|
"@mui/x-data-grid": "^6.19.11",
|
||||||
"@radix-ui/react-alert-dialog": "^1.1.14",
|
"@tauri-apps/api": "^1.5.4",
|
||||||
"@radix-ui/react-context-menu": "^2.2.15",
|
|
||||||
"@radix-ui/react-dialog": "^1.1.14",
|
|
||||||
"@radix-ui/react-dropdown-menu": "^2.1.15",
|
|
||||||
"@radix-ui/react-icons": "^1.3.2",
|
|
||||||
"@radix-ui/react-label": "^2.1.7",
|
|
||||||
"@radix-ui/react-popover": "^1.1.14",
|
|
||||||
"@radix-ui/react-progress": "^1.1.7",
|
|
||||||
"@radix-ui/react-select": "^2.2.5",
|
|
||||||
"@radix-ui/react-separator": "^1.1.7",
|
|
||||||
"@radix-ui/react-slot": "^1.2.3",
|
|
||||||
"@radix-ui/react-switch": "^1.2.5",
|
|
||||||
"@radix-ui/react-tooltip": "^1.2.7",
|
|
||||||
"@tailwindcss/vite": "^4.1.11",
|
|
||||||
"@tanstack/react-table": "^8.21.3",
|
|
||||||
"@tauri-apps/api": "2.5.0",
|
|
||||||
"@tauri-apps/plugin-clipboard-manager": "^2.2.2",
|
|
||||||
"@tauri-apps/plugin-dialog": "^2.2.2",
|
|
||||||
"@tauri-apps/plugin-fs": "^2.3.0",
|
|
||||||
"@tauri-apps/plugin-global-shortcut": "^2.2.1",
|
|
||||||
"@tauri-apps/plugin-notification": "^2.2.2",
|
|
||||||
"@tauri-apps/plugin-process": "^2.2.1",
|
|
||||||
"@tauri-apps/plugin-shell": "2.2.1",
|
|
||||||
"@tauri-apps/plugin-updater": "2.7.1",
|
|
||||||
"@tauri-apps/plugin-window-state": "^2.2.2",
|
|
||||||
"@types/d3-shape": "^3.1.7",
|
|
||||||
"@types/json-schema": "^7.0.15",
|
"@types/json-schema": "^7.0.15",
|
||||||
"ahooks": "^3.8.5",
|
"ahooks": "^3.7.11",
|
||||||
"axios": "^1.9.0",
|
"axios": "^1.6.8",
|
||||||
"chart.js": "^4.4.9",
|
"dayjs": "1.11.5",
|
||||||
"class-variance-authority": "^0.7.1",
|
"i18next": "^23.11.2",
|
||||||
"cli-color": "^2.0.4",
|
|
||||||
"clsx": "^2.1.1",
|
|
||||||
"cmdk": "^1.1.1",
|
|
||||||
"d3-shape": "^3.2.0",
|
|
||||||
"dayjs": "1.11.13",
|
|
||||||
"foxact": "^0.2.45",
|
|
||||||
"glob": "^11.0.2",
|
|
||||||
"i18next": "^25.2.1",
|
|
||||||
"js-base64": "^3.7.7",
|
|
||||||
"js-yaml": "^4.1.0",
|
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"lucide-react": "^0.514.0",
|
"meta-json-schema": "1.18.4-beta2",
|
||||||
"monaco-editor": "^0.52.2",
|
"monaco-editor": "^0.47.0",
|
||||||
"monaco-yaml": "^5.4.0",
|
"monaco-yaml": "^5.1.1",
|
||||||
"nanoid": "^5.1.5",
|
"nanoid": "^5.0.7",
|
||||||
"next-themes": "^0.4.6",
|
"react": "^18.3.1",
|
||||||
"peggy": "^5.0.3",
|
"react-dom": "^18.3.1",
|
||||||
"react": "19.1.0",
|
"react-error-boundary": "^3.1.4",
|
||||||
"react-chartjs-2": "^5.3.0",
|
"react-hook-form": "^7.51.3",
|
||||||
"react-colorful": "^5.6.1",
|
"react-i18next": "^13.5.0",
|
||||||
"react-dom": "19.1.0",
|
"react-markdown": "^9.0.1",
|
||||||
"react-error-boundary": "6.0.0",
|
"react-router-dom": "^6.23.0",
|
||||||
"react-hook-form": "^7.57.0",
|
"react-transition-group": "^4.4.5",
|
||||||
"react-i18next": "15.5.2",
|
"react-virtuoso": "^4.7.10",
|
||||||
"react-markdown": "10.1.0",
|
"recoil": "^0.7.7",
|
||||||
"react-monaco-editor": "0.58.0",
|
"swr": "^1.3.0",
|
||||||
"react-router-dom": "7.6.2",
|
"tar": "^6.2.1"
|
||||||
"react-virtuoso": "^4.12.8",
|
|
||||||
"sockette": "^2.0.6",
|
|
||||||
"sonner": "^2.0.5",
|
|
||||||
"swr": "^2.3.3",
|
|
||||||
"tailwind-merge": "^3.3.1",
|
|
||||||
"tar": "^7.4.3",
|
|
||||||
"types-pac": "^1.0.3",
|
|
||||||
"zod": "^3.25.67",
|
|
||||||
"zustand": "^5.0.5"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@actions/github": "^6.0.1",
|
"@actions/github": "^5.1.1",
|
||||||
"@tauri-apps/cli": "2.5.0",
|
"@tauri-apps/cli": "^1.5.12",
|
||||||
|
"@types/fs-extra": "^9.0.13",
|
||||||
"@types/js-cookie": "^3.0.6",
|
"@types/js-cookie": "^3.0.6",
|
||||||
"@types/js-yaml": "^4.0.9",
|
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/node": "^24.0.0",
|
"@types/react": "^18.3.1",
|
||||||
"@types/react": "19.1.6",
|
"@types/react-dom": "^18.3.0",
|
||||||
"@types/react-dom": "19.1.6",
|
"@types/react-transition-group": "^4.4.10",
|
||||||
"@vitejs/plugin-legacy": "^6.1.1",
|
"@vitejs/plugin-react": "^4.2.1",
|
||||||
"@vitejs/plugin-react": "4.5.1",
|
"adm-zip": "^0.5.12",
|
||||||
"adm-zip": "^0.5.16",
|
|
||||||
"autoprefixer": "^10.4.21",
|
|
||||||
"commander": "^14.0.0",
|
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"https-proxy-agent": "^7.0.6",
|
"fs-extra": "^11.2.0",
|
||||||
"husky": "^9.1.7",
|
"https-proxy-agent": "^5.0.1",
|
||||||
"meta-json-schema": "^1.19.10",
|
"husky": "^7.0.4",
|
||||||
"node-fetch": "^3.3.2",
|
"node-fetch": "^3.3.2",
|
||||||
"postcss": "^8.5.4",
|
"prettier": "^2.8.8",
|
||||||
"prettier": "^3.5.3",
|
"pretty-quick": "^3.3.1",
|
||||||
"pretty-quick": "^4.2.2",
|
"sass": "^1.75.0",
|
||||||
"sass": "^1.89.1",
|
"typescript": "^5.4.5",
|
||||||
"tailwindcss": "^4.1.11",
|
"vite": "^5.2.10",
|
||||||
"terser": "^5.41.0",
|
|
||||||
"tw-animate-css": "^1.3.4",
|
|
||||||
"typescript": "^5.8.3",
|
|
||||||
"vite": "^6.3.5",
|
|
||||||
"vite-plugin-monaco-editor": "^1.1.0",
|
"vite-plugin-monaco-editor": "^1.1.0",
|
||||||
"vite-plugin-svgr": "^4.3.0"
|
"vite-plugin-svgr": "^4.2.0"
|
||||||
},
|
},
|
||||||
"prettier": {
|
"prettier": {
|
||||||
"tabWidth": 2,
|
"tabWidth": 2,
|
||||||
"semi": true,
|
"semi": true,
|
||||||
"singleQuote": false,
|
"singleQuote": false,
|
||||||
"endOfLine": "lf"
|
"endOfLine": "lf"
|
||||||
},
|
}
|
||||||
"type": "module",
|
|
||||||
"packageManager": "pnpm@9.13.2"
|
|
||||||
}
|
}
|
||||||
|
|||||||
9516
pnpm-lock.yaml
generated
@@ -1,42 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": ["config:recommended"],
|
|
||||||
"baseBranches": ["dev"],
|
|
||||||
"enabledManagers": ["cargo", "npm"],
|
|
||||||
"labels": ["dependencies"],
|
|
||||||
"ignorePaths": [
|
|
||||||
"**/node_modules/**",
|
|
||||||
"**/bower_components/**",
|
|
||||||
"**/vendor/**",
|
|
||||||
"**/__tests__/**",
|
|
||||||
"**/test/**",
|
|
||||||
"**/tests/**",
|
|
||||||
"**/__fixtures__/**",
|
|
||||||
"**/crate/**",
|
|
||||||
"shared/**"
|
|
||||||
],
|
|
||||||
"rangeStrategy": "bump",
|
|
||||||
"packageRules": [
|
|
||||||
{
|
|
||||||
"semanticCommitType": "chore",
|
|
||||||
"matchPackageNames": ["*"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "Disable node/pnpm version updates",
|
|
||||||
"matchPackageNames": ["node", "pnpm"],
|
|
||||||
"matchDepTypes": ["engines", "packageManager"],
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "Group all cargo dependencies into a single PR",
|
|
||||||
"matchManagers": ["cargo"],
|
|
||||||
"groupName": "cargo dependencies"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "Group all npm dependencies into a single PR",
|
|
||||||
"matchManagers": ["npm"],
|
|
||||||
"groupName": "npm dependencies"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"postUpdateOptions": ["pnpmDedupe"],
|
|
||||||
"ignoreDeps": ["serde_yaml"]
|
|
||||||
}
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
import fs from "fs";
|
|
||||||
import path from "path";
|
|
||||||
import { fileURLToPath } from "url";
|
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
|
||||||
const __dirname = path.dirname(__filename);
|
|
||||||
|
|
||||||
const LOCALES_DIR = path.resolve(__dirname, "../src/locales");
|
|
||||||
const SRC_DIRS = [
|
|
||||||
path.resolve(__dirname, "../src"),
|
|
||||||
path.resolve(__dirname, "../src-tauri"),
|
|
||||||
];
|
|
||||||
const exts = [".js", ".ts", ".tsx", ".jsx", ".vue", ".rs"];
|
|
||||||
|
|
||||||
// 递归获取所有文件
|
|
||||||
function getAllFiles(dir, exts) {
|
|
||||||
let files = [];
|
|
||||||
fs.readdirSync(dir).forEach((file) => {
|
|
||||||
const full = path.join(dir, file);
|
|
||||||
if (fs.statSync(full).isDirectory()) {
|
|
||||||
files = files.concat(getAllFiles(full, exts));
|
|
||||||
} else if (exts.includes(path.extname(full))) {
|
|
||||||
files.push(full);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 读取所有源码内容为一个大字符串
|
|
||||||
function getAllSourceContent() {
|
|
||||||
const files = SRC_DIRS.flatMap((dir) => getAllFiles(dir, exts));
|
|
||||||
return files.map((f) => fs.readFileSync(f, "utf8")).join("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 白名单 key,不检查这些 key 是否被使用
|
|
||||||
const WHITELIST_KEYS = [
|
|
||||||
"theme.light",
|
|
||||||
"theme.dark",
|
|
||||||
"theme.system",
|
|
||||||
"Already Using Latest Core Version",
|
|
||||||
];
|
|
||||||
|
|
||||||
// 主流程
|
|
||||||
function processI18nFile(i18nPath, lang, allSource) {
|
|
||||||
const i18n = JSON.parse(fs.readFileSync(i18nPath, "utf8"));
|
|
||||||
const keys = Object.keys(i18n);
|
|
||||||
|
|
||||||
const used = {};
|
|
||||||
const unused = [];
|
|
||||||
|
|
||||||
let checked = 0;
|
|
||||||
const total = keys.length;
|
|
||||||
keys.forEach((key) => {
|
|
||||||
if (WHITELIST_KEYS.includes(key)) {
|
|
||||||
used[key] = i18n[key];
|
|
||||||
} else {
|
|
||||||
// 只查找一次
|
|
||||||
const regex = new RegExp(`["'\`]${key}["'\`]`);
|
|
||||||
if (regex.test(allSource)) {
|
|
||||||
used[key] = i18n[key];
|
|
||||||
} else {
|
|
||||||
unused.push(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
checked++;
|
|
||||||
if (checked % 20 === 0 || checked === total) {
|
|
||||||
const percent = ((checked / total) * 100).toFixed(1);
|
|
||||||
process.stdout.write(
|
|
||||||
`\r[${lang}] Progress: ${checked}/${total} (${percent}%)`,
|
|
||||||
);
|
|
||||||
if (checked === total) process.stdout.write("\n");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 输出未使用的 key
|
|
||||||
console.log(`\n[${lang}] Unused keys:`, unused);
|
|
||||||
|
|
||||||
// 备份原文件
|
|
||||||
const oldPath = i18nPath + ".old";
|
|
||||||
fs.renameSync(i18nPath, oldPath);
|
|
||||||
|
|
||||||
// 写入精简后的 i18n 文件(保留原文件名)
|
|
||||||
fs.writeFileSync(i18nPath, JSON.stringify(used, null, 2), "utf8");
|
|
||||||
console.log(
|
|
||||||
`[${lang}] Cleaned i18n file written to src/locales/${path.basename(i18nPath)}`,
|
|
||||||
);
|
|
||||||
console.log(`[${lang}] Original file backed up as ${path.basename(oldPath)}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
function main() {
|
|
||||||
// 支持 zhtw.json、zh-tw.json、zh_CN.json 等
|
|
||||||
const files = fs
|
|
||||||
.readdirSync(LOCALES_DIR)
|
|
||||||
.filter((f) => /^[a-z0-9\-_]+\.json$/i.test(f) && !f.endsWith(".old"));
|
|
||||||
const allSource = getAllSourceContent();
|
|
||||||
files.forEach((file) => {
|
|
||||||
const lang = path.basename(file, ".json");
|
|
||||||
processI18nFile(path.join(LOCALES_DIR, file), lang, allSource);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
main();
|
|
||||||
@@ -1,14 +1,11 @@
|
|||||||
import fs from "fs";
|
import fs from "fs-extra";
|
||||||
import fsp from "fs/promises";
|
|
||||||
import zlib from "zlib";
|
import zlib from "zlib";
|
||||||
import { extract } from "tar";
|
import tar from "tar";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import AdmZip from "adm-zip";
|
import AdmZip from "adm-zip";
|
||||||
import fetch from "node-fetch";
|
import fetch from "node-fetch";
|
||||||
import { HttpsProxyAgent } from "https-proxy-agent";
|
import proxyAgent from "https-proxy-agent";
|
||||||
import { execSync } from "child_process";
|
import { execSync } from "child_process";
|
||||||
import { log_info, log_debug, log_error, log_success } from "./utils.mjs";
|
|
||||||
import { glob } from "glob";
|
|
||||||
|
|
||||||
const cwd = process.cwd();
|
const cwd = process.cwd();
|
||||||
const TEMP_DIR = path.join(cwd, "node_modules/.verge");
|
const TEMP_DIR = path.join(cwd, "node_modules/.verge");
|
||||||
@@ -64,7 +61,7 @@ const META_ALPHA_MAP = {
|
|||||||
"win32-x64": "mihomo-windows-amd64-compatible",
|
"win32-x64": "mihomo-windows-amd64-compatible",
|
||||||
"win32-ia32": "mihomo-windows-386",
|
"win32-ia32": "mihomo-windows-386",
|
||||||
"win32-arm64": "mihomo-windows-arm64",
|
"win32-arm64": "mihomo-windows-arm64",
|
||||||
"darwin-x64": "mihomo-darwin-amd64-compatible",
|
"darwin-x64": "mihomo-darwin-amd64",
|
||||||
"darwin-arm64": "mihomo-darwin-arm64",
|
"darwin-arm64": "mihomo-darwin-arm64",
|
||||||
"linux-x64": "mihomo-linux-amd64-compatible",
|
"linux-x64": "mihomo-linux-amd64-compatible",
|
||||||
"linux-ia32": "mihomo-linux-386",
|
"linux-ia32": "mihomo-linux-386",
|
||||||
@@ -85,7 +82,7 @@ async function getLatestAlphaVersion() {
|
|||||||
process.env.https_proxy;
|
process.env.https_proxy;
|
||||||
|
|
||||||
if (httpProxy) {
|
if (httpProxy) {
|
||||||
options.agent = new HttpsProxyAgent(httpProxy);
|
options.agent = proxyAgent(httpProxy);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const response = await fetch(META_ALPHA_VERSION_URL, {
|
const response = await fetch(META_ALPHA_VERSION_URL, {
|
||||||
@@ -94,9 +91,9 @@ async function getLatestAlphaVersion() {
|
|||||||
});
|
});
|
||||||
let v = await response.text();
|
let v = await response.text();
|
||||||
META_ALPHA_VERSION = v.trim(); // Trim to remove extra whitespaces
|
META_ALPHA_VERSION = v.trim(); // Trim to remove extra whitespaces
|
||||||
log_info(`Latest alpha version: ${META_ALPHA_VERSION}`);
|
console.log(`Latest alpha version: ${META_ALPHA_VERSION}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log_error("Error fetching latest alpha version:", error.message);
|
console.error("Error fetching latest alpha version:", error.message);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,7 +108,7 @@ const META_MAP = {
|
|||||||
"win32-x64": "mihomo-windows-amd64-compatible",
|
"win32-x64": "mihomo-windows-amd64-compatible",
|
||||||
"win32-ia32": "mihomo-windows-386",
|
"win32-ia32": "mihomo-windows-386",
|
||||||
"win32-arm64": "mihomo-windows-arm64",
|
"win32-arm64": "mihomo-windows-arm64",
|
||||||
"darwin-x64": "mihomo-darwin-amd64-compatible",
|
"darwin-x64": "mihomo-darwin-amd64",
|
||||||
"darwin-arm64": "mihomo-darwin-arm64",
|
"darwin-arm64": "mihomo-darwin-arm64",
|
||||||
"linux-x64": "mihomo-linux-amd64-compatible",
|
"linux-x64": "mihomo-linux-amd64-compatible",
|
||||||
"linux-ia32": "mihomo-linux-386",
|
"linux-ia32": "mihomo-linux-386",
|
||||||
@@ -132,7 +129,7 @@ async function getLatestReleaseVersion() {
|
|||||||
process.env.https_proxy;
|
process.env.https_proxy;
|
||||||
|
|
||||||
if (httpProxy) {
|
if (httpProxy) {
|
||||||
options.agent = new HttpsProxyAgent(httpProxy);
|
options.agent = proxyAgent(httpProxy);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const response = await fetch(META_VERSION_URL, {
|
const response = await fetch(META_VERSION_URL, {
|
||||||
@@ -141,9 +138,9 @@ async function getLatestReleaseVersion() {
|
|||||||
});
|
});
|
||||||
let v = await response.text();
|
let v = await response.text();
|
||||||
META_VERSION = v.trim(); // Trim to remove extra whitespaces
|
META_VERSION = v.trim(); // Trim to remove extra whitespaces
|
||||||
log_info(`Latest release version: ${META_VERSION}`);
|
console.log(`Latest release version: ${META_VERSION}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log_error("Error fetching latest release version:", error.message);
|
console.error("Error fetching latest release version:", error.message);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,13 +150,13 @@ async function getLatestReleaseVersion() {
|
|||||||
*/
|
*/
|
||||||
if (!META_MAP[`${platform}-${arch}`]) {
|
if (!META_MAP[`${platform}-${arch}`]) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`clash meta alpha unsupported platform "${platform}-${arch}"`,
|
`clash meta alpha unsupported platform "${platform}-${arch}"`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!META_ALPHA_MAP[`${platform}-${arch}`]) {
|
if (!META_ALPHA_MAP[`${platform}-${arch}`]) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`clash meta alpha unsupported platform "${platform}-${arch}"`,
|
`clash meta alpha unsupported platform "${platform}-${arch}"`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,8 +172,8 @@ function clashMetaAlpha() {
|
|||||||
const zipFile = `${name}-${META_ALPHA_VERSION}.${urlExt}`;
|
const zipFile = `${name}-${META_ALPHA_VERSION}.${urlExt}`;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: "verge-mihomo-alpha",
|
name: "clash-meta-alpha",
|
||||||
targetFile: `verge-mihomo-alpha-${SIDECAR_HOST}${isWin ? ".exe" : ""}`,
|
targetFile: `clash-meta-alpha-${SIDECAR_HOST}${isWin ? ".exe" : ""}`,
|
||||||
exeFile,
|
exeFile,
|
||||||
zipFile,
|
zipFile,
|
||||||
downloadURL,
|
downloadURL,
|
||||||
@@ -192,8 +189,8 @@ function clashMeta() {
|
|||||||
const zipFile = `${name}-${META_VERSION}.${urlExt}`;
|
const zipFile = `${name}-${META_VERSION}.${urlExt}`;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: "verge-mihomo",
|
name: "clash-meta",
|
||||||
targetFile: `verge-mihomo-${SIDECAR_HOST}${isWin ? ".exe" : ""}`,
|
targetFile: `clash-meta-${SIDECAR_HOST}${isWin ? ".exe" : ""}`,
|
||||||
exeFile,
|
exeFile,
|
||||||
zipFile,
|
zipFile,
|
||||||
downloadURL,
|
downloadURL,
|
||||||
@@ -208,44 +205,44 @@ async function resolveSidecar(binInfo) {
|
|||||||
const sidecarDir = path.join(cwd, "src-tauri", "sidecar");
|
const sidecarDir = path.join(cwd, "src-tauri", "sidecar");
|
||||||
const sidecarPath = path.join(sidecarDir, targetFile);
|
const sidecarPath = path.join(sidecarDir, targetFile);
|
||||||
|
|
||||||
await fsp.mkdir(sidecarDir, { recursive: true });
|
await fs.mkdirp(sidecarDir);
|
||||||
if (!FORCE && fs.existsSync(sidecarPath)) return;
|
if (!FORCE && (await fs.pathExists(sidecarPath))) return;
|
||||||
|
|
||||||
const tempDir = path.join(TEMP_DIR, name);
|
const tempDir = path.join(TEMP_DIR, name);
|
||||||
const tempZip = path.join(tempDir, zipFile);
|
const tempZip = path.join(tempDir, zipFile);
|
||||||
const tempExe = path.join(tempDir, exeFile);
|
const tempExe = path.join(tempDir, exeFile);
|
||||||
|
|
||||||
await fsp.mkdir(tempDir, { recursive: true });
|
await fs.mkdirp(tempDir);
|
||||||
try {
|
try {
|
||||||
if (!fs.existsSync(tempZip)) {
|
if (!(await fs.pathExists(tempZip))) {
|
||||||
await downloadFile(downloadURL, tempZip);
|
await downloadFile(downloadURL, tempZip);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zipFile.endsWith(".zip")) {
|
if (zipFile.endsWith(".zip")) {
|
||||||
const zip = new AdmZip(tempZip);
|
const zip = new AdmZip(tempZip);
|
||||||
zip.getEntries().forEach((entry) => {
|
zip.getEntries().forEach((entry) => {
|
||||||
log_debug(`"${name}" entry name`, entry.entryName);
|
console.log(`[DEBUG]: "${name}" entry name`, entry.entryName);
|
||||||
});
|
});
|
||||||
zip.extractAllTo(tempDir, true);
|
zip.extractAllTo(tempDir, true);
|
||||||
await fsp.rename(tempExe, sidecarPath);
|
await fs.rename(tempExe, sidecarPath);
|
||||||
log_success(`unzip finished: "${name}"`);
|
console.log(`[INFO]: "${name}" unzip finished`);
|
||||||
} else if (zipFile.endsWith(".tgz")) {
|
} else if (zipFile.endsWith(".tgz")) {
|
||||||
// tgz
|
// tgz
|
||||||
await fsp.mkdir(tempDir, { recursive: true });
|
await fs.mkdirp(tempDir);
|
||||||
await extract({
|
await tar.extract({
|
||||||
cwd: tempDir,
|
cwd: tempDir,
|
||||||
file: tempZip,
|
file: tempZip,
|
||||||
//strip: 1, // 可能需要根据实际的 .tgz 文件结构调整
|
//strip: 1, // 可能需要根据实际的 .tgz 文件结构调整
|
||||||
});
|
});
|
||||||
const files = await fsp.readdir(tempDir);
|
const files = await fs.readdir(tempDir);
|
||||||
log_debug(`"${name}" files in tempDir:`, files);
|
console.log(`[DEBUG]: "${name}" files in tempDir:`, files);
|
||||||
const extractedFile = files.find((file) => file.startsWith("虚空终端-"));
|
const extractedFile = files.find((file) => file.startsWith("虚空终端-"));
|
||||||
if (extractedFile) {
|
if (extractedFile) {
|
||||||
const extractedFilePath = path.join(tempDir, extractedFile);
|
const extractedFilePath = path.join(tempDir, extractedFile);
|
||||||
await fsp.rename(extractedFilePath, sidecarPath);
|
await fs.rename(extractedFilePath, sidecarPath);
|
||||||
log_success(`"${name}" file renamed to "${sidecarPath}"`);
|
console.log(`[INFO]: "${name}" file renamed to "${sidecarPath}"`);
|
||||||
execSync(`chmod 755 ${sidecarPath}`);
|
execSync(`chmod 755 ${sidecarPath}`);
|
||||||
log_success(`chmod binary finished: "${name}"`);
|
console.log(`[INFO]: "${name}" chmod binary finished`);
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Expected file not found in ${tempDir}`);
|
throw new Error(`Expected file not found in ${tempDir}`);
|
||||||
}
|
}
|
||||||
@@ -255,15 +252,16 @@ async function resolveSidecar(binInfo) {
|
|||||||
const writeStream = fs.createWriteStream(sidecarPath);
|
const writeStream = fs.createWriteStream(sidecarPath);
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
const onError = (error) => {
|
const onError = (error) => {
|
||||||
log_error(`"${name}" gz failed:`, error.message);
|
console.error(`[ERROR]: "${name}" gz failed:`, error.message);
|
||||||
reject(error);
|
reject(error);
|
||||||
};
|
};
|
||||||
readStream
|
readStream
|
||||||
.pipe(zlib.createGunzip().on("error", onError))
|
.pipe(zlib.createGunzip().on("error", onError))
|
||||||
.pipe(writeStream)
|
.pipe(writeStream)
|
||||||
.on("finish", () => {
|
.on("finish", () => {
|
||||||
|
console.log(`[INFO]: "${name}" gunzip finished`);
|
||||||
execSync(`chmod 755 ${sidecarPath}`);
|
execSync(`chmod 755 ${sidecarPath}`);
|
||||||
log_success(`chmod binary finished: "${name}"`);
|
console.log(`[INFO]: "${name}" chmod binary finished`);
|
||||||
resolve();
|
resolve();
|
||||||
})
|
})
|
||||||
.on("error", onError);
|
.on("error", onError);
|
||||||
@@ -271,58 +269,35 @@ async function resolveSidecar(binInfo) {
|
|||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// 需要删除文件
|
// 需要删除文件
|
||||||
await fsp.rm(sidecarPath, { recursive: true, force: true });
|
await fs.remove(sidecarPath);
|
||||||
throw err;
|
throw err;
|
||||||
} finally {
|
} finally {
|
||||||
// delete temp dir
|
// delete temp dir
|
||||||
await fsp.rm(tempDir, { recursive: true, force: true });
|
await fs.remove(tempDir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const resolveSetDnsScript = () =>
|
|
||||||
resolveResource({
|
|
||||||
file: "set_dns.sh",
|
|
||||||
localPath: path.join(cwd, "scripts/set_dns.sh"),
|
|
||||||
});
|
|
||||||
const resolveUnSetDnsScript = () =>
|
|
||||||
resolveResource({
|
|
||||||
file: "unset_dns.sh",
|
|
||||||
localPath: path.join(cwd, "scripts/unset_dns.sh"),
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* download the file to the resources dir
|
* download the file to the resources dir
|
||||||
*/
|
*/
|
||||||
async function resolveResource(binInfo) {
|
async function resolveResource(binInfo) {
|
||||||
const { file, downloadURL, localPath } = binInfo;
|
const { file, downloadURL } = binInfo;
|
||||||
|
|
||||||
const resDir = path.join(cwd, "src-tauri/resources");
|
const resDir = path.join(cwd, "src-tauri/resources");
|
||||||
const targetPath = path.join(resDir, file);
|
const targetPath = path.join(resDir, file);
|
||||||
|
|
||||||
if (!FORCE && fs.existsSync(targetPath)) return;
|
if (!FORCE && (await fs.pathExists(targetPath))) return;
|
||||||
|
|
||||||
if (downloadURL) {
|
await fs.mkdirp(resDir);
|
||||||
await fsp.mkdir(resDir, { recursive: true });
|
await downloadFile(downloadURL, targetPath);
|
||||||
await downloadFile(downloadURL, targetPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (localPath) {
|
console.log(`[INFO]: ${file} finished`);
|
||||||
await fs.copyFile(localPath, targetPath, (err) => {
|
|
||||||
if (err) {
|
|
||||||
console.error("Error copying file:", err);
|
|
||||||
} else {
|
|
||||||
console.log("File was copied successfully");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
log_debug(`copy file finished: "${localPath}"`);
|
|
||||||
}
|
|
||||||
|
|
||||||
log_success(`${file} finished`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* download file and save to `path`
|
* download file and save to `path`
|
||||||
*/ async function downloadFile(url, path) {
|
*/
|
||||||
|
async function downloadFile(url, path) {
|
||||||
const options = {};
|
const options = {};
|
||||||
|
|
||||||
const httpProxy =
|
const httpProxy =
|
||||||
@@ -332,7 +307,7 @@ async function resolveResource(binInfo) {
|
|||||||
process.env.https_proxy;
|
process.env.https_proxy;
|
||||||
|
|
||||||
if (httpProxy) {
|
if (httpProxy) {
|
||||||
options.agent = new HttpsProxyAgent(httpProxy);
|
options.agent = proxyAgent(httpProxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
@@ -341,9 +316,9 @@ async function resolveResource(binInfo) {
|
|||||||
headers: { "Content-Type": "application/octet-stream" },
|
headers: { "Content-Type": "application/octet-stream" },
|
||||||
});
|
});
|
||||||
const buffer = await response.arrayBuffer();
|
const buffer = await response.arrayBuffer();
|
||||||
await fsp.writeFile(path, new Uint8Array(buffer));
|
await fs.writeFile(path, new Uint8Array(buffer));
|
||||||
|
|
||||||
log_success(`download finished: ${url}`);
|
console.log(`[INFO]: download finished "${url}"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SimpleSC.dll
|
// SimpleSC.dll
|
||||||
@@ -354,111 +329,87 @@ const resolvePlugin = async () => {
|
|||||||
const tempDir = path.join(TEMP_DIR, "SimpleSC");
|
const tempDir = path.join(TEMP_DIR, "SimpleSC");
|
||||||
const tempZip = path.join(
|
const tempZip = path.join(
|
||||||
tempDir,
|
tempDir,
|
||||||
"NSIS_Simple_Service_Plugin_Unicode_1.30.zip",
|
"NSIS_Simple_Service_Plugin_Unicode_1.30.zip"
|
||||||
);
|
);
|
||||||
const tempDll = path.join(tempDir, "SimpleSC.dll");
|
const tempDll = path.join(tempDir, "SimpleSC.dll");
|
||||||
const pluginDir = path.join(process.env.APPDATA, "Local/NSIS");
|
const pluginDir = path.join(process.env.APPDATA, "Local/NSIS");
|
||||||
const pluginPath = path.join(pluginDir, "SimpleSC.dll");
|
const pluginPath = path.join(pluginDir, "SimpleSC.dll");
|
||||||
await fsp.mkdir(pluginDir, { recursive: true });
|
await fs.mkdirp(pluginDir);
|
||||||
await fsp.mkdir(tempDir, { recursive: true });
|
await fs.mkdirp(tempDir);
|
||||||
if (!FORCE && fs.existsSync(pluginPath)) return;
|
if (!FORCE && (await fs.pathExists(pluginPath))) return;
|
||||||
try {
|
try {
|
||||||
if (!fs.existsSync(tempZip)) {
|
if (!(await fs.pathExists(tempZip))) {
|
||||||
await downloadFile(url, tempZip);
|
await downloadFile(url, tempZip);
|
||||||
}
|
}
|
||||||
const zip = new AdmZip(tempZip);
|
const zip = new AdmZip(tempZip);
|
||||||
zip.getEntries().forEach((entry) => {
|
zip.getEntries().forEach((entry) => {
|
||||||
log_debug(`"SimpleSC" entry name`, entry.entryName);
|
console.log(`[DEBUG]: "SimpleSC" entry name`, entry.entryName);
|
||||||
});
|
});
|
||||||
zip.extractAllTo(tempDir, true);
|
zip.extractAllTo(tempDir, true);
|
||||||
await fsp.cp(tempDll, pluginPath, { recursive: true, force: true });
|
await fs.copyFile(tempDll, pluginPath);
|
||||||
log_success(`unzip finished: "SimpleSC"`);
|
console.log(`[INFO]: "SimpleSC" unzip finished`);
|
||||||
} finally {
|
} finally {
|
||||||
await fsp.rm(tempDir, { recursive: true, force: true });
|
await fs.remove(tempDir);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// service chmod
|
// service chmod
|
||||||
const resolveServicePermission = async () => {
|
const resolveServicePermission = async () => {
|
||||||
const serviceExecutables = [
|
const serviceExecutables = [
|
||||||
"clash-verge-service*",
|
"clash-verge-service",
|
||||||
"install-service*",
|
"install-service",
|
||||||
"uninstall-service*",
|
"uninstall-service",
|
||||||
];
|
];
|
||||||
const resDir = path.join(cwd, "src-tauri/resources");
|
const resDir = path.join(cwd, "src-tauri/resources");
|
||||||
for (let f of serviceExecutables) {
|
for (let f of serviceExecutables) {
|
||||||
// 使用glob模块来处理通配符
|
const targetPath = path.join(resDir, f);
|
||||||
const files = glob.sync(path.join(resDir, f));
|
if (await fs.pathExists(targetPath)) {
|
||||||
for (let filePath of files) {
|
execSync(`chmod 755 ${targetPath}`);
|
||||||
if (fs.existsSync(filePath)) {
|
console.log(`[INFO]: "${targetPath}" chmod finished`);
|
||||||
execSync(`chmod 755 ${filePath}`);
|
|
||||||
log_success(`chmod finished: "${filePath}"`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 在 resolveResource 函数后添加新函数
|
|
||||||
async function resolveLocales() {
|
|
||||||
const srcLocalesDir = path.join(cwd, "src/locales");
|
|
||||||
const targetLocalesDir = path.join(cwd, "src-tauri/resources/locales");
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 确保目标目录存在
|
|
||||||
await fsp.mkdir(targetLocalesDir, { recursive: true });
|
|
||||||
|
|
||||||
// 读取所有语言文件
|
|
||||||
const files = await fsp.readdir(srcLocalesDir);
|
|
||||||
|
|
||||||
// 复制每个文件
|
|
||||||
for (const file of files) {
|
|
||||||
const srcPath = path.join(srcLocalesDir, file);
|
|
||||||
const targetPath = path.join(targetLocalesDir, file);
|
|
||||||
|
|
||||||
await fsp.copyFile(srcPath, targetPath);
|
|
||||||
log_success(`Copied locale file: ${file}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
log_success("All locale files copied successfully");
|
|
||||||
} catch (err) {
|
|
||||||
log_error("Error copying locale files:", err.message);
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* main
|
* main
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const SERVICE_URL = `https://github.com/clash-verge-rev/clash-verge-service/releases/download/${SIDECAR_HOST}`;
|
const SERVICE_URL = `https://github.com/clash-verge-rev/clash-verge-service/releases/download/${SIDECAR_HOST}`;
|
||||||
|
|
||||||
const resolveService = () => {
|
const resolveService = () => {
|
||||||
let ext = platform === "win32" ? ".exe" : "";
|
let ext = platform === "win32" ? ".exe" : "";
|
||||||
let suffix = platform === "linux" ? "-" + SIDECAR_HOST : "";
|
|
||||||
resolveResource({
|
resolveResource({
|
||||||
file: "clash-verge-service" + suffix + ext,
|
file: "clash-verge-service" + ext,
|
||||||
downloadURL: `${SERVICE_URL}/clash-verge-service${ext}`,
|
downloadURL: `${SERVICE_URL}/clash-verge-service${ext}`,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const resolveInstall = () => {
|
const resolveInstall = () => {
|
||||||
let ext = platform === "win32" ? ".exe" : "";
|
let ext = platform === "win32" ? ".exe" : "";
|
||||||
let suffix = platform === "linux" ? "-" + SIDECAR_HOST : "";
|
|
||||||
resolveResource({
|
resolveResource({
|
||||||
file: "install-service" + suffix + ext,
|
file: "install-service" + ext,
|
||||||
downloadURL: `${SERVICE_URL}/install-service${ext}`,
|
downloadURL: `${SERVICE_URL}/install-service${ext}`,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const resolveUninstall = () => {
|
const resolveUninstall = () => {
|
||||||
let ext = platform === "win32" ? ".exe" : "";
|
let ext = platform === "win32" ? ".exe" : "";
|
||||||
let suffix = platform === "linux" ? "-" + SIDECAR_HOST : "";
|
|
||||||
|
|
||||||
resolveResource({
|
resolveResource({
|
||||||
file: "uninstall-service" + suffix + ext,
|
file: "uninstall-service" + ext,
|
||||||
downloadURL: `${SERVICE_URL}/uninstall-service${ext}`,
|
downloadURL: `${SERVICE_URL}/uninstall-service${ext}`,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const resolveSetDnsScript = () =>
|
||||||
|
resolveResource({
|
||||||
|
file: "set_dns.sh",
|
||||||
|
downloadURL: `https://github.com/clash-verge-rev/set-dns-script/releases/download/script/set_dns.sh`,
|
||||||
|
});
|
||||||
|
const resolveUnSetDnsScript = () =>
|
||||||
|
resolveResource({
|
||||||
|
file: "unset_dns.sh",
|
||||||
|
downloadURL: `https://github.com/clash-verge-rev/set-dns-script/releases/download/script/unset_dns.sh`,
|
||||||
|
});
|
||||||
const resolveMmdb = () =>
|
const resolveMmdb = () =>
|
||||||
resolveResource({
|
resolveResource({
|
||||||
file: "Country.mmdb",
|
file: "Country.mmdb",
|
||||||
@@ -480,22 +431,16 @@ const resolveEnableLoopback = () =>
|
|||||||
downloadURL: `https://github.com/Kuingsmile/uwp-tool/releases/download/latest/enableLoopback.exe`,
|
downloadURL: `https://github.com/Kuingsmile/uwp-tool/releases/download/latest/enableLoopback.exe`,
|
||||||
});
|
});
|
||||||
|
|
||||||
const resolveWinSysproxy = () =>
|
|
||||||
resolveResource({
|
|
||||||
file: "sysproxy.exe",
|
|
||||||
downloadURL: `https://github.com/clash-verge-rev/sysproxy/releases/download/${arch}/sysproxy.exe`,
|
|
||||||
});
|
|
||||||
|
|
||||||
const tasks = [
|
const tasks = [
|
||||||
// { name: "clash", func: resolveClash, retry: 5 },
|
// { name: "clash", func: resolveClash, retry: 5 },
|
||||||
{
|
{
|
||||||
name: "verge-mihomo-alpha",
|
name: "clash-meta-alpha",
|
||||||
func: () =>
|
func: () =>
|
||||||
getLatestAlphaVersion().then(() => resolveSidecar(clashMetaAlpha())),
|
getLatestAlphaVersion().then(() => resolveSidecar(clashMetaAlpha())),
|
||||||
retry: 5,
|
retry: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "verge-mihomo",
|
name: "clash-meta",
|
||||||
func: () =>
|
func: () =>
|
||||||
getLatestReleaseVersion().then(() => resolveSidecar(clashMeta())),
|
getLatestReleaseVersion().then(() => resolveSidecar(clashMeta())),
|
||||||
retry: 5,
|
retry: 5,
|
||||||
@@ -504,6 +449,8 @@ const tasks = [
|
|||||||
{ name: "service", func: resolveService, retry: 5 },
|
{ name: "service", func: resolveService, retry: 5 },
|
||||||
{ name: "install", func: resolveInstall, retry: 5 },
|
{ name: "install", func: resolveInstall, retry: 5 },
|
||||||
{ name: "uninstall", func: resolveUninstall, retry: 5 },
|
{ name: "uninstall", func: resolveUninstall, retry: 5 },
|
||||||
|
{ name: "set_dns_script", func: resolveSetDnsScript, retry: 5 },
|
||||||
|
{ name: "unset_dns_script", func: resolveUnSetDnsScript, retry: 5 },
|
||||||
{ name: "mmdb", func: resolveMmdb, retry: 5 },
|
{ name: "mmdb", func: resolveMmdb, retry: 5 },
|
||||||
{ name: "geosite", func: resolveGeosite, retry: 5 },
|
{ name: "geosite", func: resolveGeosite, retry: 5 },
|
||||||
{ name: "geoip", func: resolveGeoIP, retry: 5 },
|
{ name: "geoip", func: resolveGeoIP, retry: 5 },
|
||||||
@@ -516,48 +463,24 @@ const tasks = [
|
|||||||
{
|
{
|
||||||
name: "service_chmod",
|
name: "service_chmod",
|
||||||
func: resolveServicePermission,
|
func: resolveServicePermission,
|
||||||
retry: 5,
|
retry: 1,
|
||||||
unixOnly: platform === "linux" || platform === "darwin",
|
unixOnly: true,
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "windows-sysproxy",
|
|
||||||
func: resolveWinSysproxy,
|
|
||||||
retry: 5,
|
|
||||||
winOnly: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "set_dns_script",
|
|
||||||
func: resolveSetDnsScript,
|
|
||||||
retry: 5,
|
|
||||||
macosOnly: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "unset_dns_script",
|
|
||||||
func: resolveUnSetDnsScript,
|
|
||||||
retry: 5,
|
|
||||||
macosOnly: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "locales",
|
|
||||||
func: resolveLocales,
|
|
||||||
retry: 2,
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
async function runTask() {
|
async function runTask() {
|
||||||
const task = tasks.shift();
|
const task = tasks.shift();
|
||||||
if (!task) return;
|
if (!task) return;
|
||||||
if (task.unixOnly && platform === "win32") return runTask();
|
|
||||||
if (task.winOnly && platform !== "win32") return runTask();
|
if (task.winOnly && platform !== "win32") return runTask();
|
||||||
if (task.macosOnly && platform !== "darwin") return runTask();
|
|
||||||
if (task.linuxOnly && platform !== "linux") return runTask();
|
if (task.linuxOnly && platform !== "linux") return runTask();
|
||||||
|
if (task.unixOnly && platform === "win32") return runTask();
|
||||||
|
|
||||||
for (let i = 0; i < task.retry; i++) {
|
for (let i = 0; i < task.retry; i++) {
|
||||||
try {
|
try {
|
||||||
await task.func();
|
await task.func();
|
||||||
break;
|
break;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log_error(`task::${task.name} try ${i} ==`, err.message);
|
console.error(`[ERROR]: task::${task.name} try ${i} ==`, err.message);
|
||||||
if (i === task.retry - 1) throw err;
|
if (i === task.retry - 1) throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -565,3 +488,4 @@ async function runTask() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
runTask();
|
runTask();
|
||||||
|
runTask();
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
import { exec } from "child_process";
|
|
||||||
import { promisify } from "util";
|
|
||||||
import fs from "fs/promises";
|
|
||||||
import path from "path";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 为Alpha版本重命名版本号
|
|
||||||
*/
|
|
||||||
const execPromise = promisify(exec);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 标准输出HEAD hash
|
|
||||||
*/
|
|
||||||
async function getLatestCommitHash() {
|
|
||||||
try {
|
|
||||||
const { stdout } = await execPromise("git rev-parse HEAD");
|
|
||||||
const commitHash = stdout.trim();
|
|
||||||
// 格式化,只截取前7位字符
|
|
||||||
const formathash = commitHash.substring(0, 7);
|
|
||||||
console.log(`Found the latest commit hash code: ${commitHash}`);
|
|
||||||
return formathash;
|
|
||||||
} catch (error) {
|
|
||||||
console.error("pnpm run fix-alpha-version ERROR", error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string 传入格式化后的hash
|
|
||||||
* 将新的版本号写入文件 package.json
|
|
||||||
*/
|
|
||||||
async function updatePackageVersion(newVersion) {
|
|
||||||
// 获取内容根目录
|
|
||||||
const _dirname = process.cwd();
|
|
||||||
const packageJsonPath = path.join(_dirname, "package.json");
|
|
||||||
try {
|
|
||||||
// 读取文件
|
|
||||||
const data = await fs.readFile(packageJsonPath, "utf8");
|
|
||||||
const packageJson = JSON.parse(data);
|
|
||||||
// 获取键值替换
|
|
||||||
let result = packageJson.version.replace("alpha", newVersion);
|
|
||||||
// 检查当前版本号是否已经包含了 alpha- 后缀
|
|
||||||
if (!packageJson.version.includes(`alpha-`)) {
|
|
||||||
// 如果只有 alpha 而没有 alpha-,则替换为 alpha-newVersion
|
|
||||||
result = packageJson.version.replace("alpha", `alpha-${newVersion}`);
|
|
||||||
} else {
|
|
||||||
// 如果已经是 alpha-xxx 格式,则更新 xxx 部分
|
|
||||||
result = packageJson.version.replace(
|
|
||||||
/alpha-[^-]*/,
|
|
||||||
`alpha-${newVersion}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
console.log("[INFO]: Current version is: ", result);
|
|
||||||
packageJson.version = result;
|
|
||||||
// 写入版本号
|
|
||||||
await fs.writeFile(
|
|
||||||
packageJsonPath,
|
|
||||||
JSON.stringify(packageJson, null, 2),
|
|
||||||
"utf8",
|
|
||||||
);
|
|
||||||
console.log(`[INFO]: Alpha version update to: ${newVersion}`);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("pnpm run fix-alpha-version ERROR", error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const newVersion = await getLatestCommitHash();
|
|
||||||
updatePackageVersion(newVersion).catch(console.error);
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
import fs from "fs";
|
|
||||||
import fsp from "fs/promises";
|
|
||||||
import path from "path";
|
|
||||||
import AdmZip from "adm-zip";
|
|
||||||
import { createRequire } from "module";
|
|
||||||
import { getOctokit, context } from "@actions/github";
|
|
||||||
|
|
||||||
const target = process.argv.slice(2)[0];
|
|
||||||
const alpha = process.argv.slice(2)[1];
|
|
||||||
|
|
||||||
const ARCH_MAP = {
|
|
||||||
"x86_64-pc-windows-msvc": "x64",
|
|
||||||
"i686-pc-windows-msvc": "x86",
|
|
||||||
"aarch64-pc-windows-msvc": "arm64",
|
|
||||||
};
|
|
||||||
|
|
||||||
const PROCESS_MAP = {
|
|
||||||
x64: "x64",
|
|
||||||
ia32: "x86",
|
|
||||||
arm64: "arm64",
|
|
||||||
};
|
|
||||||
const arch = target ? ARCH_MAP[target] : PROCESS_MAP[process.arch];
|
|
||||||
/// Script for ci
|
|
||||||
/// 打包绿色版/便携版 (only Windows)
|
|
||||||
async function resolvePortable() {
|
|
||||||
if (process.platform !== "win32") return;
|
|
||||||
|
|
||||||
const releaseDir = target
|
|
||||||
? `./src-tauri/target/${target}/release`
|
|
||||||
: `./src-tauri/target/release`;
|
|
||||||
|
|
||||||
const configDir = path.join(releaseDir, ".config");
|
|
||||||
|
|
||||||
if (!fs.existsSync(releaseDir)) {
|
|
||||||
throw new Error("could not found the release dir");
|
|
||||||
}
|
|
||||||
|
|
||||||
await fsp.mkdir(configDir, { recursive: true });
|
|
||||||
if (!fs.existsSync(path.join(configDir, "PORTABLE"))) {
|
|
||||||
await fsp.writeFile(path.join(configDir, "PORTABLE"), "");
|
|
||||||
}
|
|
||||||
|
|
||||||
const zip = new AdmZip();
|
|
||||||
|
|
||||||
zip.addLocalFile(path.join(releaseDir, "Clash Verge.exe"));
|
|
||||||
zip.addLocalFile(path.join(releaseDir, "verge-mihomo.exe"));
|
|
||||||
zip.addLocalFile(path.join(releaseDir, "verge-mihomo-alpha.exe"));
|
|
||||||
zip.addLocalFolder(path.join(releaseDir, "resources"), "resources");
|
|
||||||
zip.addLocalFolder(
|
|
||||||
path.join(
|
|
||||||
releaseDir,
|
|
||||||
`Microsoft.WebView2.FixedVersionRuntime.133.0.3065.92.${arch}`,
|
|
||||||
),
|
|
||||||
`Microsoft.WebView2.FixedVersionRuntime.133.0.3065.92.${arch}`,
|
|
||||||
);
|
|
||||||
zip.addLocalFolder(configDir, ".config");
|
|
||||||
|
|
||||||
const require = createRequire(import.meta.url);
|
|
||||||
const packageJson = require("../package.json");
|
|
||||||
const { version } = packageJson;
|
|
||||||
|
|
||||||
const zipFile = `Clash.Verge_${version}_${arch}_fixed_webview2_portable.zip`;
|
|
||||||
zip.writeZip(zipFile);
|
|
||||||
|
|
||||||
console.log("[INFO]: create portable zip successfully");
|
|
||||||
|
|
||||||
// push release assets
|
|
||||||
if (process.env.GITHUB_TOKEN === undefined) {
|
|
||||||
throw new Error("GITHUB_TOKEN is required");
|
|
||||||
}
|
|
||||||
|
|
||||||
const options = { owner: context.repo.owner, repo: context.repo.repo };
|
|
||||||
const github = getOctokit(process.env.GITHUB_TOKEN);
|
|
||||||
const tag = alpha ? "alpha" : process.env.TAG_NAME || `v${version}`;
|
|
||||||
console.log("[INFO]: upload to ", tag);
|
|
||||||
|
|
||||||
const { data: release } = await github.rest.repos.getReleaseByTag({
|
|
||||||
...options,
|
|
||||||
tag,
|
|
||||||
});
|
|
||||||
|
|
||||||
let assets = release.assets.filter((x) => {
|
|
||||||
return x.name === zipFile;
|
|
||||||
});
|
|
||||||
if (assets.length > 0) {
|
|
||||||
let id = assets[0].id;
|
|
||||||
await github.rest.repos.deleteReleaseAsset({
|
|
||||||
...options,
|
|
||||||
asset_id: id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(release.name);
|
|
||||||
|
|
||||||
await github.rest.repos.uploadReleaseAsset({
|
|
||||||
...options,
|
|
||||||
release_id: release.id,
|
|
||||||
name: zipFile,
|
|
||||||
data: zip.toBuffer(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
resolvePortable().catch(console.error);
|
|
||||||
@@ -1,20 +1,17 @@
|
|||||||
import fs from "fs";
|
import fs from "fs-extra";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import AdmZip from "adm-zip";
|
import AdmZip from "adm-zip";
|
||||||
import { createRequire } from "module";
|
import { createRequire } from "module";
|
||||||
import fsp from "fs/promises";
|
import { getOctokit, context } from "@actions/github";
|
||||||
|
|
||||||
const target = process.argv.slice(2)[0];
|
const target = process.argv.slice(2)[0];
|
||||||
|
const alpha = process.argv.slice(2)[1];
|
||||||
|
|
||||||
const ARCH_MAP = {
|
const ARCH_MAP = {
|
||||||
"x86_64-pc-windows-msvc": "x64",
|
"x86_64-pc-windows-msvc": "x64",
|
||||||
"aarch64-pc-windows-msvc": "arm64",
|
"aarch64-pc-windows-msvc": "arm64",
|
||||||
};
|
};
|
||||||
|
|
||||||
const PROCESS_MAP = {
|
|
||||||
x64: "x64",
|
|
||||||
arm64: "arm64",
|
|
||||||
};
|
|
||||||
const arch = target ? ARCH_MAP[target] : PROCESS_MAP[process.arch];
|
|
||||||
/// Script for ci
|
/// Script for ci
|
||||||
/// 打包绿色版/便携版 (only Windows)
|
/// 打包绿色版/便携版 (only Windows)
|
||||||
async function resolvePortable() {
|
async function resolvePortable() {
|
||||||
@@ -25,28 +22,64 @@ async function resolvePortable() {
|
|||||||
: `./src-tauri/target/release`;
|
: `./src-tauri/target/release`;
|
||||||
const configDir = path.join(releaseDir, ".config");
|
const configDir = path.join(releaseDir, ".config");
|
||||||
|
|
||||||
if (!fs.existsSync(releaseDir)) {
|
if (!(await fs.pathExists(releaseDir))) {
|
||||||
throw new Error("could not found the release dir");
|
throw new Error("could not found the release dir");
|
||||||
}
|
}
|
||||||
|
|
||||||
await fsp.mkdir(configDir, { recursive: true });
|
await fs.mkdir(configDir);
|
||||||
if (!fs.existsSync(path.join(configDir, "PORTABLE"))) {
|
await fs.createFile(path.join(configDir, "PORTABLE"));
|
||||||
await fsp.writeFile(path.join(configDir, "PORTABLE"), "");
|
|
||||||
}
|
|
||||||
const zip = new AdmZip();
|
const zip = new AdmZip();
|
||||||
|
|
||||||
zip.addLocalFile(path.join(releaseDir, "clash-verge.exe"));
|
zip.addLocalFile(path.join(releaseDir, "Clash Verge.exe"));
|
||||||
zip.addLocalFile(path.join(releaseDir, "verge-mihomo.exe"));
|
zip.addLocalFile(path.join(releaseDir, "clash-meta.exe"));
|
||||||
zip.addLocalFile(path.join(releaseDir, "verge-mihomo-alpha.exe"));
|
zip.addLocalFile(path.join(releaseDir, "clash-meta-alpha.exe"));
|
||||||
zip.addLocalFolder(path.join(releaseDir, "resources"), "resources");
|
zip.addLocalFolder(path.join(releaseDir, "resources"), "resources");
|
||||||
zip.addLocalFolder(configDir, ".config");
|
zip.addLocalFolder(configDir, ".config");
|
||||||
|
|
||||||
const require = createRequire(import.meta.url);
|
const require = createRequire(import.meta.url);
|
||||||
const packageJson = require("../package.json");
|
const packageJson = require("../package.json");
|
||||||
const { version } = packageJson;
|
const { version } = packageJson;
|
||||||
const zipFile = `Clash.Verge_${version}_${arch}_portable.zip`;
|
|
||||||
|
const zipFile = `Clash.Verge_${version}_${ARCH_MAP[target]}_portable.zip`;
|
||||||
zip.writeZip(zipFile);
|
zip.writeZip(zipFile);
|
||||||
|
|
||||||
console.log("[INFO]: create portable zip successfully");
|
console.log("[INFO]: create portable zip successfully");
|
||||||
|
|
||||||
|
// push release assets
|
||||||
|
if (process.env.GITHUB_TOKEN === undefined) {
|
||||||
|
throw new Error("GITHUB_TOKEN is required");
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = { owner: context.repo.owner, repo: context.repo.repo };
|
||||||
|
const github = getOctokit(process.env.GITHUB_TOKEN);
|
||||||
|
const tag = alpha ? "alpha" : process.env.TAG_NAME || `v${version}`;
|
||||||
|
console.log("[INFO]: upload to ", tag);
|
||||||
|
|
||||||
|
const { data: release } = await github.rest.repos.getReleaseByTag({
|
||||||
|
...options,
|
||||||
|
tag,
|
||||||
|
});
|
||||||
|
|
||||||
|
let assets = release.assets.filter((x) => {
|
||||||
|
return x.name === zipFile;
|
||||||
|
});
|
||||||
|
if (assets.length > 0) {
|
||||||
|
let id = assets[0].id;
|
||||||
|
await github.rest.repos.deleteReleaseAsset({
|
||||||
|
...options,
|
||||||
|
asset_id: id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(release.name);
|
||||||
|
|
||||||
|
await github.rest.repos.uploadReleaseAsset({
|
||||||
|
...options,
|
||||||
|
release_id: release.id,
|
||||||
|
name: zipFile,
|
||||||
|
data: zip.toBuffer(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
resolvePortable().catch(console.error);
|
resolvePortable().catch(console.error);
|
||||||
|
|||||||
@@ -1,66 +0,0 @@
|
|||||||
// scripts/publish-version.mjs
|
|
||||||
import { spawn } from "child_process";
|
|
||||||
import { existsSync } from "fs";
|
|
||||||
import path from "path";
|
|
||||||
|
|
||||||
const rootDir = process.cwd();
|
|
||||||
const scriptPath = path.join(rootDir, "scripts", "release-version.mjs");
|
|
||||||
|
|
||||||
if (!existsSync(scriptPath)) {
|
|
||||||
console.error("release-version.mjs not found!");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const versionArg = process.argv[2];
|
|
||||||
if (!versionArg) {
|
|
||||||
console.error("Usage: pnpm publish-version <version>");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. 调用 release-version.mjs
|
|
||||||
const runRelease = () =>
|
|
||||||
new Promise((resolve, reject) => {
|
|
||||||
const child = spawn("node", [scriptPath, versionArg], { stdio: "inherit" });
|
|
||||||
child.on("exit", (code) => {
|
|
||||||
if (code === 0) resolve();
|
|
||||||
else reject(new Error("release-version failed"));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// 2. 判断是否需要打 tag
|
|
||||||
function isSemver(version) {
|
|
||||||
return /^v?\d+\.\d+\.\d+(-[0-9A-Za-z-.]+)?$/.test(version);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function run() {
|
|
||||||
await runRelease();
|
|
||||||
|
|
||||||
let tag = null;
|
|
||||||
if (versionArg === "alpha") {
|
|
||||||
// 读取 package.json 里的主版本
|
|
||||||
const pkg = await import(path.join(rootDir, "package.json"), {
|
|
||||||
assert: { type: "json" },
|
|
||||||
});
|
|
||||||
tag = `v${pkg.default.version}-alpha`;
|
|
||||||
} else if (isSemver(versionArg)) {
|
|
||||||
// 1.2.3 或 v1.2.3
|
|
||||||
tag = versionArg.startsWith("v") ? versionArg : `v${versionArg}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tag) {
|
|
||||||
// 打 tag 并推送
|
|
||||||
const { execSync } = await import("child_process");
|
|
||||||
try {
|
|
||||||
execSync(`git tag ${tag}`, { stdio: "inherit" });
|
|
||||||
execSync(`git push origin ${tag}`, { stdio: "inherit" });
|
|
||||||
console.log(`[INFO]: Git tag ${tag} created and pushed.`);
|
|
||||||
} catch (e) {
|
|
||||||
console.error(`[ERROR]: Failed to create or push git tag: ${tag}`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.log("[INFO]: No git tag created for this version.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
run();
|
|
||||||
@@ -1,253 +0,0 @@
|
|||||||
/**
|
|
||||||
* CLI tool to update version numbers in package.json, src-tauri/Cargo.toml, and src-tauri/tauri.conf.json.
|
|
||||||
*
|
|
||||||
* Usage:
|
|
||||||
* pnpm release-version <version>
|
|
||||||
*
|
|
||||||
* <version> can be:
|
|
||||||
* - A full semver version (e.g., 1.2.3, v1.2.3, 1.2.3-beta, v1.2.3+build)
|
|
||||||
* - A tag: "alpha", "beta", "rc", or "autobuild"
|
|
||||||
* - "alpha", "beta", "rc": Appends the tag to the current base version (e.g., 1.2.3-beta)
|
|
||||||
* - "autobuild": Appends a timestamped autobuild tag (e.g., 1.2.3+autobuild.2406101530)
|
|
||||||
*
|
|
||||||
* Examples:
|
|
||||||
* pnpm release-version 1.2.3
|
|
||||||
* pnpm release-version v1.2.3-beta
|
|
||||||
* pnpm release-version beta
|
|
||||||
* pnpm release-version autobuild
|
|
||||||
*
|
|
||||||
* The script will:
|
|
||||||
* - Validate and normalize the version argument
|
|
||||||
* - Update the version field in package.json
|
|
||||||
* - Update the version field in src-tauri/Cargo.toml
|
|
||||||
* - Update the version field in src-tauri/tauri.conf.json
|
|
||||||
*
|
|
||||||
* Errors are logged and the process exits with code 1 on failure.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import fs from "fs/promises";
|
|
||||||
import path from "path";
|
|
||||||
import { program } from "commander";
|
|
||||||
import { execSync } from "child_process";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前 git 短 commit hash
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
function getGitShortCommit() {
|
|
||||||
try {
|
|
||||||
return execSync("git rev-parse --short HEAD").toString().trim();
|
|
||||||
} catch (e) {
|
|
||||||
console.warn("[WARN]: Failed to get git short commit, fallback to 'nogit'");
|
|
||||||
return "nogit";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成短时间戳(格式:YYMMDD)或带 commit(格式:YYMMDD.cc39b27)
|
|
||||||
* @param {boolean} withCommit 是否带 commit
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
function generateShortTimestamp(withCommit = false) {
|
|
||||||
const now = new Date();
|
|
||||||
const month = String(now.getMonth() + 1).padStart(2, "0");
|
|
||||||
const day = String(now.getDate()).padStart(2, "0");
|
|
||||||
if (withCommit) {
|
|
||||||
const gitShort = getGitShortCommit();
|
|
||||||
return `${month}${day}.${gitShort}`;
|
|
||||||
}
|
|
||||||
return `${month}${day}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 验证版本号格式
|
|
||||||
* @param {string} version
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
function isValidVersion(version) {
|
|
||||||
return /^v?\d+\.\d+\.\d+(-(alpha|beta|rc)(\.\d+)?)?(\+[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*)?$/i.test(
|
|
||||||
version,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 标准化版本号
|
|
||||||
* @param {string} version
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
function normalizeVersion(version) {
|
|
||||||
return version.startsWith("v") ? version : `v${version}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 提取基础版本号(去掉所有 -tag 和 +build 部分)
|
|
||||||
* @param {string} version
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
function getBaseVersion(version) {
|
|
||||||
let base = version.replace(/-(alpha|beta|rc)(\.\d+)?/i, "");
|
|
||||||
base = base.replace(/\+[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*/g, "");
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新 package.json 版本号
|
|
||||||
* @param {string} newVersion
|
|
||||||
*/
|
|
||||||
async function updatePackageVersion(newVersion) {
|
|
||||||
const _dirname = process.cwd();
|
|
||||||
const packageJsonPath = path.join(_dirname, "package.json");
|
|
||||||
try {
|
|
||||||
const data = await fs.readFile(packageJsonPath, "utf8");
|
|
||||||
const packageJson = JSON.parse(data);
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
"[INFO]: Current package.json version is: ",
|
|
||||||
packageJson.version,
|
|
||||||
);
|
|
||||||
packageJson.version = newVersion.startsWith("v")
|
|
||||||
? newVersion.slice(1)
|
|
||||||
: newVersion;
|
|
||||||
await fs.writeFile(
|
|
||||||
packageJsonPath,
|
|
||||||
JSON.stringify(packageJson, null, 2),
|
|
||||||
"utf8",
|
|
||||||
);
|
|
||||||
console.log(
|
|
||||||
`[INFO]: package.json version updated to: ${packageJson.version}`,
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error updating package.json version:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新 Cargo.toml 版本号
|
|
||||||
* @param {string} newVersion
|
|
||||||
*/
|
|
||||||
async function updateCargoVersion(newVersion) {
|
|
||||||
const _dirname = process.cwd();
|
|
||||||
const cargoTomlPath = path.join(_dirname, "src-tauri", "Cargo.toml");
|
|
||||||
try {
|
|
||||||
const data = await fs.readFile(cargoTomlPath, "utf8");
|
|
||||||
const lines = data.split("\n");
|
|
||||||
const versionWithoutV = newVersion.startsWith("v")
|
|
||||||
? newVersion.slice(1)
|
|
||||||
: newVersion;
|
|
||||||
const baseVersion = getBaseVersion(versionWithoutV);
|
|
||||||
|
|
||||||
const updatedLines = lines.map((line) => {
|
|
||||||
if (line.trim().startsWith("version =")) {
|
|
||||||
return line.replace(
|
|
||||||
/version\s*=\s*"[^"]+"/,
|
|
||||||
`version = "${baseVersion}"`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return line;
|
|
||||||
});
|
|
||||||
|
|
||||||
await fs.writeFile(cargoTomlPath, updatedLines.join("\n"), "utf8");
|
|
||||||
console.log(`[INFO]: Cargo.toml version updated to: ${baseVersion}`);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error updating Cargo.toml version:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新 tauri.conf.json 版本号
|
|
||||||
* @param {string} newVersion
|
|
||||||
*/
|
|
||||||
async function updateTauriConfigVersion(newVersion) {
|
|
||||||
const _dirname = process.cwd();
|
|
||||||
const tauriConfigPath = path.join(_dirname, "src-tauri", "tauri.conf.json");
|
|
||||||
try {
|
|
||||||
const data = await fs.readFile(tauriConfigPath, "utf8");
|
|
||||||
const tauriConfig = JSON.parse(data);
|
|
||||||
const versionWithoutV = newVersion.startsWith("v")
|
|
||||||
? newVersion.slice(1)
|
|
||||||
: newVersion;
|
|
||||||
const baseVersion = getBaseVersion(versionWithoutV);
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
"[INFO]: Current tauri.conf.json version is: ",
|
|
||||||
tauriConfig.version,
|
|
||||||
);
|
|
||||||
tauriConfig.version = baseVersion;
|
|
||||||
await fs.writeFile(
|
|
||||||
tauriConfigPath,
|
|
||||||
JSON.stringify(tauriConfig, null, 2),
|
|
||||||
"utf8",
|
|
||||||
);
|
|
||||||
console.log(`[INFO]: tauri.conf.json version updated to: ${baseVersion}`);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error updating tauri.conf.json version:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前版本号
|
|
||||||
*/
|
|
||||||
async function getCurrentVersion() {
|
|
||||||
const _dirname = process.cwd();
|
|
||||||
const packageJsonPath = path.join(_dirname, "package.json");
|
|
||||||
try {
|
|
||||||
const data = await fs.readFile(packageJsonPath, "utf8");
|
|
||||||
const packageJson = JSON.parse(data);
|
|
||||||
return packageJson.version;
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error getting current version:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 主函数
|
|
||||||
*/
|
|
||||||
async function main(versionArg) {
|
|
||||||
if (!versionArg) {
|
|
||||||
console.error("Error: Version argument is required");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
let newVersion;
|
|
||||||
const validTags = ["alpha", "beta", "rc", "autobuild"];
|
|
||||||
|
|
||||||
if (validTags.includes(versionArg.toLowerCase())) {
|
|
||||||
const currentVersion = await getCurrentVersion();
|
|
||||||
const baseVersion = getBaseVersion(currentVersion);
|
|
||||||
|
|
||||||
if (versionArg.toLowerCase() === "autobuild") {
|
|
||||||
// 格式: 2.3.0+autobuild.250613.cc39b27
|
|
||||||
newVersion = `${baseVersion}+autobuild.${generateShortTimestamp(true)}`;
|
|
||||||
} else {
|
|
||||||
newVersion = `${baseVersion}-${versionArg.toLowerCase()}`;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!isValidVersion(versionArg)) {
|
|
||||||
console.error("Error: Invalid version format");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
newVersion = normalizeVersion(versionArg);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`[INFO]: Updating versions to: ${newVersion}`);
|
|
||||||
await updatePackageVersion(newVersion);
|
|
||||||
await updateCargoVersion(newVersion);
|
|
||||||
await updateTauriConfigVersion(newVersion);
|
|
||||||
console.log("[SUCCESS]: All version updates completed successfully!");
|
|
||||||
} catch (error) {
|
|
||||||
console.error("[ERROR]: Failed to update versions:", error);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
program
|
|
||||||
.name("pnpm release-version")
|
|
||||||
.description("Update project version numbers")
|
|
||||||
.argument("<version>", "version tag or full version")
|
|
||||||
.action(main)
|
|
||||||
.parse(process.argv);
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# 验证IPv4地址格式
|
|
||||||
function is_valid_ipv4() {
|
|
||||||
local ip=$1
|
|
||||||
local IFS='.'
|
|
||||||
local -a octets
|
|
||||||
|
|
||||||
[[ ! $ip =~ ^([0-9]+\.){3}[0-9]+$ ]] && return 1
|
|
||||||
read -r -a octets <<<"$ip"
|
|
||||||
[ "${#octets[@]}" -ne 4 ] && return 1
|
|
||||||
|
|
||||||
for octet in "${octets[@]}"; do
|
|
||||||
if ! [[ "$octet" =~ ^[0-9]+$ ]] || ((octet < 0 || octet > 255)); then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# 验证IPv6地址格式
|
|
||||||
function is_valid_ipv6() {
|
|
||||||
local ip=$1
|
|
||||||
if [[ ! $ip =~ ^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}$ ]] &&
|
|
||||||
[[ ! $ip =~ ^(([0-9a-fA-F]{0,4}:){0,7}:|(:[0-9a-fA-F]{0,4}:){0,6}:[0-9a-fA-F]{0,4})$ ]]; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# 验证IP地址是否为有效的IPv4或IPv6
|
|
||||||
function is_valid_ip() {
|
|
||||||
is_valid_ipv4 "$1" || is_valid_ipv6 "$1"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 检查参数
|
|
||||||
[ $# -lt 1 ] && echo "Usage: $0 <IP address>" && exit 1
|
|
||||||
! is_valid_ip "$1" && echo "$1 is not a valid IP address." && exit 1
|
|
||||||
|
|
||||||
# 获取网络接口和硬件端口
|
|
||||||
nic=$(route -n get default | grep "interface" | awk '{print $2}')
|
|
||||||
hardware_port=$(networksetup -listallhardwareports | awk -v dev="$nic" '
|
|
||||||
/Hardware Port:/{port=$0; gsub("Hardware Port: ", "", port)}
|
|
||||||
/Device: /{if ($2 == dev) {print port; exit}}
|
|
||||||
')
|
|
||||||
|
|
||||||
# 获取当前DNS设置
|
|
||||||
original_dns=$(networksetup -getdnsservers "$hardware_port")
|
|
||||||
|
|
||||||
# 检查当前DNS设置是否有效
|
|
||||||
is_valid_dns=false
|
|
||||||
for ip in $original_dns; do
|
|
||||||
ip=$(echo "$ip" | tr -d '[:space:]')
|
|
||||||
if [ -n "$ip" ] && (is_valid_ipv4 "$ip" || is_valid_ipv6 "$ip"); then
|
|
||||||
is_valid_dns=true
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# 更新DNS设置
|
|
||||||
if [ "$is_valid_dns" = false ]; then
|
|
||||||
echo "empty" >.original_dns.txt
|
|
||||||
else
|
|
||||||
echo "$original_dns" >.original_dns.txt
|
|
||||||
fi
|
|
||||||
networksetup -setdnsservers "$hardware_port" "$1"
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
nic=$(route -n get default | grep "interface" | awk '{print $2}')
|
|
||||||
|
|
||||||
hardware_port=$(networksetup -listallhardwareports | awk -v dev="$nic" '
|
|
||||||
/Hardware Port:/{
|
|
||||||
port=$0; gsub("Hardware Port: ", "", port)
|
|
||||||
}
|
|
||||||
/Device: /{
|
|
||||||
if ($2 == dev) {
|
|
||||||
print port;
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
')
|
|
||||||
|
|
||||||
if [ -f .original_dns.txt ]; then
|
|
||||||
original_dns=$(cat .original_dns.txt)
|
|
||||||
networksetup -setdnsservers "$hardware_port" $original_dns
|
|
||||||
rm -rf .original_dns.txt
|
|
||||||
fi
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
import fs from "fs";
|
import fs from "fs-extra";
|
||||||
import fsp from "fs/promises";
|
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
|
||||||
const UPDATE_LOG = "UPDATELOG.md";
|
const UPDATE_LOG = "UPDATELOG.md";
|
||||||
@@ -13,11 +12,11 @@ export async function resolveUpdateLog(tag) {
|
|||||||
|
|
||||||
const file = path.join(cwd, UPDATE_LOG);
|
const file = path.join(cwd, UPDATE_LOG);
|
||||||
|
|
||||||
if (!fs.existsSync(file)) {
|
if (!(await fs.pathExists(file))) {
|
||||||
throw new Error("could not found UPDATELOG.md");
|
throw new Error("could not found UPDATELOG.md");
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await fsp.readFile(file, "utf-8");
|
const data = await fs.readFile(file).then((d) => d.toString("utf8"));
|
||||||
|
|
||||||
const map = {};
|
const map = {};
|
||||||
let p = "";
|
let p = "";
|
||||||
@@ -43,42 +42,3 @@ export async function resolveUpdateLog(tag) {
|
|||||||
|
|
||||||
return map[tag].join("\n").trim();
|
return map[tag].join("\n").trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function resolveUpdateLogDefault() {
|
|
||||||
const cwd = process.cwd();
|
|
||||||
const file = path.join(cwd, UPDATE_LOG);
|
|
||||||
|
|
||||||
if (!fs.existsSync(file)) {
|
|
||||||
throw new Error("could not found UPDATELOG.md");
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await fsp.readFile(file, "utf-8");
|
|
||||||
|
|
||||||
const reTitle = /^## v[\d\.]+/;
|
|
||||||
const reEnd = /^---/;
|
|
||||||
|
|
||||||
let isCapturing = false;
|
|
||||||
let content = [];
|
|
||||||
let firstTag = "";
|
|
||||||
|
|
||||||
for (const line of data.split("\n")) {
|
|
||||||
if (reTitle.test(line) && !isCapturing) {
|
|
||||||
isCapturing = true;
|
|
||||||
firstTag = line.slice(3).trim();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCapturing) {
|
|
||||||
if (reEnd.test(line)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
content.push(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!firstTag) {
|
|
||||||
throw new Error("could not found any version tag in UPDATELOG.md");
|
|
||||||
}
|
|
||||||
|
|
||||||
return content.join("\n").trim();
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,157 +0,0 @@
|
|||||||
import fetch from "node-fetch";
|
|
||||||
import { getOctokit, context } from "@actions/github";
|
|
||||||
import { resolveUpdateLog } from "./updatelog.mjs";
|
|
||||||
|
|
||||||
const UPDATE_TAG_NAME = "updater";
|
|
||||||
const UPDATE_JSON_FILE = "update-fixed-webview2.json";
|
|
||||||
const UPDATE_JSON_PROXY = "update-fixed-webview2-proxy.json";
|
|
||||||
|
|
||||||
/// generate update.json
|
|
||||||
/// upload to update tag's release asset
|
|
||||||
async function resolveUpdater() {
|
|
||||||
if (process.env.GITHUB_TOKEN === undefined) {
|
|
||||||
throw new Error("GITHUB_TOKEN is required");
|
|
||||||
}
|
|
||||||
|
|
||||||
const options = { owner: context.repo.owner, repo: context.repo.repo };
|
|
||||||
const github = getOctokit(process.env.GITHUB_TOKEN);
|
|
||||||
|
|
||||||
const { data: tags } = await github.rest.repos.listTags({
|
|
||||||
...options,
|
|
||||||
per_page: 10,
|
|
||||||
page: 1,
|
|
||||||
});
|
|
||||||
|
|
||||||
// get the latest publish tag
|
|
||||||
const tag = tags.find((t) => t.name.startsWith("v"));
|
|
||||||
|
|
||||||
console.log(tag);
|
|
||||||
console.log();
|
|
||||||
|
|
||||||
const { data: latestRelease } = await github.rest.repos.getReleaseByTag({
|
|
||||||
...options,
|
|
||||||
tag: tag.name,
|
|
||||||
});
|
|
||||||
|
|
||||||
const updateData = {
|
|
||||||
name: tag.name,
|
|
||||||
notes: await resolveUpdateLog(tag.name), // use updatelog.md
|
|
||||||
pub_date: new Date().toISOString(),
|
|
||||||
platforms: {
|
|
||||||
"windows-x86_64": { signature: "", url: "" },
|
|
||||||
"windows-aarch64": { signature: "", url: "" },
|
|
||||||
"windows-x86": { signature: "", url: "" },
|
|
||||||
"windows-i686": { signature: "", url: "" },
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const promises = latestRelease.assets.map(async (asset) => {
|
|
||||||
const { name, browser_download_url } = asset;
|
|
||||||
|
|
||||||
// win64 url
|
|
||||||
if (name.endsWith("x64_fixed_webview2-setup.nsis.zip")) {
|
|
||||||
updateData.platforms["windows-x86_64"].url = browser_download_url;
|
|
||||||
}
|
|
||||||
// win64 signature
|
|
||||||
if (name.endsWith("x64_fixed_webview2-setup.nsis.zip.sig")) {
|
|
||||||
const sig = await getSignature(browser_download_url);
|
|
||||||
updateData.platforms["windows-x86_64"].signature = sig;
|
|
||||||
}
|
|
||||||
|
|
||||||
// win32 url
|
|
||||||
if (name.endsWith("x86_fixed_webview2-setup.nsis.zip")) {
|
|
||||||
updateData.platforms["windows-x86"].url = browser_download_url;
|
|
||||||
updateData.platforms["windows-i686"].url = browser_download_url;
|
|
||||||
}
|
|
||||||
// win32 signature
|
|
||||||
if (name.endsWith("x86_fixed_webview2-setup.nsis.zip.sig")) {
|
|
||||||
const sig = await getSignature(browser_download_url);
|
|
||||||
updateData.platforms["windows-x86"].signature = sig;
|
|
||||||
updateData.platforms["windows-i686"].signature = sig;
|
|
||||||
}
|
|
||||||
|
|
||||||
// win arm url
|
|
||||||
if (name.endsWith("arm64_fixed_webview2-setup.nsis.zip")) {
|
|
||||||
updateData.platforms["windows-aarch64"].url = browser_download_url;
|
|
||||||
}
|
|
||||||
// win arm signature
|
|
||||||
if (name.endsWith("arm64_fixed_webview2-setup.nsis.zip.sig")) {
|
|
||||||
const sig = await getSignature(browser_download_url);
|
|
||||||
updateData.platforms["windows-aarch64"].signature = sig;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await Promise.allSettled(promises);
|
|
||||||
console.log(updateData);
|
|
||||||
|
|
||||||
// maybe should test the signature as well
|
|
||||||
// delete the null field
|
|
||||||
Object.entries(updateData.platforms).forEach(([key, value]) => {
|
|
||||||
if (!value.url) {
|
|
||||||
console.log(`[Error]: failed to parse release for "${key}"`);
|
|
||||||
delete updateData.platforms[key];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 生成一个代理github的更新文件
|
|
||||||
// 使用 https://hub.fastgit.xyz/ 做github资源的加速
|
|
||||||
const updateDataNew = JSON.parse(JSON.stringify(updateData));
|
|
||||||
|
|
||||||
Object.entries(updateDataNew.platforms).forEach(([key, value]) => {
|
|
||||||
if (value.url) {
|
|
||||||
updateDataNew.platforms[key].url =
|
|
||||||
"https://download.clashverge.dev/" + value.url;
|
|
||||||
} else {
|
|
||||||
console.log(`[Error]: updateDataNew.platforms.${key} is null`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// update the update.json
|
|
||||||
const { data: updateRelease } = await github.rest.repos.getReleaseByTag({
|
|
||||||
...options,
|
|
||||||
tag: UPDATE_TAG_NAME,
|
|
||||||
});
|
|
||||||
|
|
||||||
// delete the old assets
|
|
||||||
for (let asset of updateRelease.assets) {
|
|
||||||
if (asset.name === UPDATE_JSON_FILE) {
|
|
||||||
await github.rest.repos.deleteReleaseAsset({
|
|
||||||
...options,
|
|
||||||
asset_id: asset.id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (asset.name === UPDATE_JSON_PROXY) {
|
|
||||||
await github.rest.repos
|
|
||||||
.deleteReleaseAsset({ ...options, asset_id: asset.id })
|
|
||||||
.catch(console.error); // do not break the pipeline
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// upload new assets
|
|
||||||
await github.rest.repos.uploadReleaseAsset({
|
|
||||||
...options,
|
|
||||||
release_id: updateRelease.id,
|
|
||||||
name: UPDATE_JSON_FILE,
|
|
||||||
data: JSON.stringify(updateData, null, 2),
|
|
||||||
});
|
|
||||||
|
|
||||||
await github.rest.repos.uploadReleaseAsset({
|
|
||||||
...options,
|
|
||||||
release_id: updateRelease.id,
|
|
||||||
name: UPDATE_JSON_PROXY,
|
|
||||||
data: JSON.stringify(updateDataNew, null, 2),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the signature file content
|
|
||||||
async function getSignature(url) {
|
|
||||||
const response = await fetch(url, {
|
|
||||||
method: "GET",
|
|
||||||
headers: { "Content-Type": "application/octet-stream" },
|
|
||||||
});
|
|
||||||
|
|
||||||
return response.text();
|
|
||||||
}
|
|
||||||
|
|
||||||
resolveUpdater().catch(console.error);
|
|
||||||
@@ -1,15 +1,10 @@
|
|||||||
import fetch from "node-fetch";
|
import fetch from "node-fetch";
|
||||||
import { getOctokit, context } from "@actions/github";
|
import { getOctokit, context } from "@actions/github";
|
||||||
import { resolveUpdateLog, resolveUpdateLogDefault } from "./updatelog.mjs";
|
import { resolveUpdateLog } from "./updatelog.mjs";
|
||||||
|
|
||||||
// Add stable update JSON filenames
|
|
||||||
const UPDATE_TAG_NAME = "updater";
|
const UPDATE_TAG_NAME = "updater";
|
||||||
const UPDATE_JSON_FILE = "update.json";
|
const UPDATE_JSON_FILE = "update.json";
|
||||||
const UPDATE_JSON_PROXY = "update-proxy.json";
|
const UPDATE_JSON_PROXY = "update-proxy.json";
|
||||||
// Add alpha update JSON filenames
|
|
||||||
const ALPHA_TAG_NAME = "updater-alpha";
|
|
||||||
const ALPHA_UPDATE_JSON_FILE = "update.json";
|
|
||||||
const ALPHA_UPDATE_JSON_PROXY = "update-proxy.json";
|
|
||||||
|
|
||||||
/// generate update.json
|
/// generate update.json
|
||||||
/// upload to update tag's release asset
|
/// upload to update tag's release asset
|
||||||
@@ -21,293 +16,171 @@ async function resolveUpdater() {
|
|||||||
const options = { owner: context.repo.owner, repo: context.repo.repo };
|
const options = { owner: context.repo.owner, repo: context.repo.repo };
|
||||||
const github = getOctokit(process.env.GITHUB_TOKEN);
|
const github = getOctokit(process.env.GITHUB_TOKEN);
|
||||||
|
|
||||||
// Fetch all tags using pagination
|
const { data: tags } = await github.rest.repos.listTags({
|
||||||
let allTags = [];
|
...options,
|
||||||
let page = 1;
|
per_page: 10,
|
||||||
const perPage = 100;
|
page: 1,
|
||||||
|
});
|
||||||
|
|
||||||
while (true) {
|
// get the latest publish tag
|
||||||
const { data: pageTags } = await github.rest.repos.listTags({
|
const tag = tags.find((t) => t.name.startsWith("v"));
|
||||||
...options,
|
|
||||||
per_page: perPage,
|
|
||||||
page: page,
|
|
||||||
});
|
|
||||||
|
|
||||||
allTags = allTags.concat(pageTags);
|
console.log(tag);
|
||||||
|
|
||||||
// Break if we received fewer tags than requested (last page)
|
|
||||||
if (pageTags.length < perPage) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
page++;
|
|
||||||
}
|
|
||||||
|
|
||||||
const tags = allTags;
|
|
||||||
console.log(`Retrieved ${tags.length} tags in total`);
|
|
||||||
|
|
||||||
// More flexible tag detection with regex patterns
|
|
||||||
const stableTagRegex = /^v\d+\.\d+\.\d+$/; // Matches vX.Y.Z format
|
|
||||||
// const preReleaseRegex = /^v\d+\.\d+\.\d+-(alpha|beta|rc|pre)/i; // Matches vX.Y.Z-alpha/beta/rc format
|
|
||||||
const preReleaseRegex = /^(alpha|beta|rc|pre)$/i; // Matches exact alpha/beta/rc/pre tags
|
|
||||||
|
|
||||||
// Get the latest stable tag and pre-release tag
|
|
||||||
const stableTag = tags.find((t) => stableTagRegex.test(t.name));
|
|
||||||
const preReleaseTag = tags.find((t) => preReleaseRegex.test(t.name));
|
|
||||||
|
|
||||||
console.log("All tags:", tags.map((t) => t.name).join(", "));
|
|
||||||
console.log("Stable tag:", stableTag ? stableTag.name : "None found");
|
|
||||||
console.log(
|
|
||||||
"Pre-release tag:",
|
|
||||||
preReleaseTag ? preReleaseTag.name : "None found",
|
|
||||||
);
|
|
||||||
console.log();
|
console.log();
|
||||||
|
|
||||||
// Process stable release
|
const { data: latestRelease } = await github.rest.repos.getReleaseByTag({
|
||||||
if (stableTag) {
|
...options,
|
||||||
await processRelease(github, options, stableTag, false);
|
tag: tag.name,
|
||||||
}
|
});
|
||||||
|
|
||||||
// Process pre-release if found
|
const updateData = {
|
||||||
if (preReleaseTag) {
|
name: tag.name,
|
||||||
await processRelease(github, options, preReleaseTag, true);
|
notes: await resolveUpdateLog(tag.name), // use updatelog.md
|
||||||
}
|
pub_date: new Date().toISOString(),
|
||||||
}
|
platforms: {
|
||||||
|
win64: { signature: "", url: "" }, // compatible with older formats
|
||||||
|
linux: { signature: "", url: "" }, // compatible with older formats
|
||||||
|
darwin: { signature: "", url: "" }, // compatible with older formats
|
||||||
|
"darwin-aarch64": { signature: "", url: "" },
|
||||||
|
"darwin-intel": { signature: "", url: "" },
|
||||||
|
"darwin-x86_64": { signature: "", url: "" },
|
||||||
|
"linux-x86_64": { signature: "", url: "" },
|
||||||
|
"linux-aarch64": { signature: "", url: "" },
|
||||||
|
"linux-armv7": { signature: "", url: "" },
|
||||||
|
"windows-x86_64": { signature: "", url: "" },
|
||||||
|
"windows-aarch64": { signature: "", url: "" },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
// Process a release (stable or alpha) and generate update files
|
const promises = latestRelease.assets.map(async (asset) => {
|
||||||
async function processRelease(github, options, tag, isAlpha) {
|
const { name, browser_download_url } = asset;
|
||||||
if (!tag) return;
|
|
||||||
|
|
||||||
try {
|
// win64 url
|
||||||
const { data: release } = await github.rest.repos.getReleaseByTag({
|
if (name.endsWith("x64-setup.nsis.zip")) {
|
||||||
...options,
|
updateData.platforms.win64.url = browser_download_url;
|
||||||
tag: tag.name,
|
updateData.platforms["windows-x86_64"].url = browser_download_url;
|
||||||
});
|
|
||||||
|
|
||||||
const updateData = {
|
|
||||||
name: tag.name,
|
|
||||||
notes: await resolveUpdateLog(tag.name).catch(() =>
|
|
||||||
resolveUpdateLogDefault().catch(() => "No changelog available"),
|
|
||||||
),
|
|
||||||
pub_date: new Date().toISOString(),
|
|
||||||
platforms: {
|
|
||||||
win64: { signature: "", url: "" }, // compatible with older formats
|
|
||||||
linux: { signature: "", url: "" }, // compatible with older formats
|
|
||||||
darwin: { signature: "", url: "" }, // compatible with older formats
|
|
||||||
"darwin-aarch64": { signature: "", url: "" },
|
|
||||||
"darwin-intel": { signature: "", url: "" },
|
|
||||||
"darwin-x86_64": { signature: "", url: "" },
|
|
||||||
"linux-x86_64": { signature: "", url: "" },
|
|
||||||
"linux-x86": { signature: "", url: "" },
|
|
||||||
"linux-i686": { signature: "", url: "" },
|
|
||||||
"linux-aarch64": { signature: "", url: "" },
|
|
||||||
"linux-armv7": { signature: "", url: "" },
|
|
||||||
"windows-x86_64": { signature: "", url: "" },
|
|
||||||
"windows-aarch64": { signature: "", url: "" },
|
|
||||||
"windows-x86": { signature: "", url: "" },
|
|
||||||
"windows-i686": { signature: "", url: "" },
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const promises = release.assets.map(async (asset) => {
|
|
||||||
const { name, browser_download_url } = asset;
|
|
||||||
|
|
||||||
// Process all the platform URL and signature data
|
|
||||||
// win64 url
|
|
||||||
if (name.endsWith("x64-setup.exe")) {
|
|
||||||
updateData.platforms.win64.url = browser_download_url;
|
|
||||||
updateData.platforms["windows-x86_64"].url = browser_download_url;
|
|
||||||
}
|
|
||||||
// win64 signature
|
|
||||||
if (name.endsWith("x64-setup.exe.sig")) {
|
|
||||||
const sig = await getSignature(browser_download_url);
|
|
||||||
updateData.platforms.win64.signature = sig;
|
|
||||||
updateData.platforms["windows-x86_64"].signature = sig;
|
|
||||||
}
|
|
||||||
|
|
||||||
// win32 url
|
|
||||||
if (name.endsWith("x86-setup.exe")) {
|
|
||||||
updateData.platforms["windows-x86"].url = browser_download_url;
|
|
||||||
updateData.platforms["windows-i686"].url = browser_download_url;
|
|
||||||
}
|
|
||||||
// win32 signature
|
|
||||||
if (name.endsWith("x86-setup.exe.sig")) {
|
|
||||||
const sig = await getSignature(browser_download_url);
|
|
||||||
updateData.platforms["windows-x86"].signature = sig;
|
|
||||||
updateData.platforms["windows-i686"].signature = sig;
|
|
||||||
}
|
|
||||||
|
|
||||||
// win arm url
|
|
||||||
if (name.endsWith("arm64-setup.exe")) {
|
|
||||||
updateData.platforms["windows-aarch64"].url = browser_download_url;
|
|
||||||
}
|
|
||||||
// win arm signature
|
|
||||||
if (name.endsWith("arm64-setup.exe.sig")) {
|
|
||||||
const sig = await getSignature(browser_download_url);
|
|
||||||
updateData.platforms["windows-aarch64"].signature = sig;
|
|
||||||
}
|
|
||||||
|
|
||||||
// darwin url (intel)
|
|
||||||
if (name.endsWith(".app.tar.gz") && !name.includes("aarch")) {
|
|
||||||
updateData.platforms.darwin.url = browser_download_url;
|
|
||||||
updateData.platforms["darwin-intel"].url = browser_download_url;
|
|
||||||
updateData.platforms["darwin-x86_64"].url = browser_download_url;
|
|
||||||
}
|
|
||||||
// darwin signature (intel)
|
|
||||||
if (name.endsWith(".app.tar.gz.sig") && !name.includes("aarch")) {
|
|
||||||
const sig = await getSignature(browser_download_url);
|
|
||||||
updateData.platforms.darwin.signature = sig;
|
|
||||||
updateData.platforms["darwin-intel"].signature = sig;
|
|
||||||
updateData.platforms["darwin-x86_64"].signature = sig;
|
|
||||||
}
|
|
||||||
|
|
||||||
// darwin url (aarch)
|
|
||||||
if (name.endsWith("aarch64.app.tar.gz")) {
|
|
||||||
updateData.platforms["darwin-aarch64"].url = browser_download_url;
|
|
||||||
// 使linux可以检查更新
|
|
||||||
updateData.platforms.linux.url = browser_download_url;
|
|
||||||
updateData.platforms["linux-x86_64"].url = browser_download_url;
|
|
||||||
updateData.platforms["linux-x86"].url = browser_download_url;
|
|
||||||
updateData.platforms["linux-i686"].url = browser_download_url;
|
|
||||||
updateData.platforms["linux-aarch64"].url = browser_download_url;
|
|
||||||
updateData.platforms["linux-armv7"].url = browser_download_url;
|
|
||||||
}
|
|
||||||
// darwin signature (aarch)
|
|
||||||
if (name.endsWith("aarch64.app.tar.gz.sig")) {
|
|
||||||
const sig = await getSignature(browser_download_url);
|
|
||||||
updateData.platforms["darwin-aarch64"].signature = sig;
|
|
||||||
updateData.platforms.linux.signature = sig;
|
|
||||||
updateData.platforms["linux-x86_64"].signature = sig;
|
|
||||||
updateData.platforms["linux-x86"].url = browser_download_url;
|
|
||||||
updateData.platforms["linux-i686"].url = browser_download_url;
|
|
||||||
updateData.platforms["linux-aarch64"].signature = sig;
|
|
||||||
updateData.platforms["linux-armv7"].signature = sig;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await Promise.allSettled(promises);
|
|
||||||
console.log(updateData);
|
|
||||||
|
|
||||||
// maybe should test the signature as well
|
|
||||||
// delete the null field
|
|
||||||
Object.entries(updateData.platforms).forEach(([key, value]) => {
|
|
||||||
if (!value.url) {
|
|
||||||
console.log(`[Error]: failed to parse release for "${key}"`);
|
|
||||||
delete updateData.platforms[key];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Generate a proxy update file for accelerated GitHub resources
|
|
||||||
const updateDataNew = JSON.parse(JSON.stringify(updateData));
|
|
||||||
|
|
||||||
Object.entries(updateDataNew.platforms).forEach(([key, value]) => {
|
|
||||||
if (value.url) {
|
|
||||||
updateDataNew.platforms[key].url =
|
|
||||||
"https://download.clashverge.dev/" + value.url;
|
|
||||||
} else {
|
|
||||||
console.log(`[Error]: updateDataNew.platforms.${key} is null`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get the appropriate updater release based on isAlpha flag
|
|
||||||
const releaseTag = isAlpha ? ALPHA_TAG_NAME : UPDATE_TAG_NAME;
|
|
||||||
console.log(
|
|
||||||
`Processing ${isAlpha ? "alpha" : "stable"} release:`,
|
|
||||||
releaseTag,
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
let updateRelease;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Try to get the existing release
|
|
||||||
const response = await github.rest.repos.getReleaseByTag({
|
|
||||||
...options,
|
|
||||||
tag: releaseTag,
|
|
||||||
});
|
|
||||||
updateRelease = response.data;
|
|
||||||
console.log(
|
|
||||||
`Found existing ${releaseTag} release with ID: ${updateRelease.id}`,
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
// If release doesn't exist, create it
|
|
||||||
if (error.status === 404) {
|
|
||||||
console.log(
|
|
||||||
`Release with tag ${releaseTag} not found, creating new release...`,
|
|
||||||
);
|
|
||||||
const createResponse = await github.rest.repos.createRelease({
|
|
||||||
...options,
|
|
||||||
tag_name: releaseTag,
|
|
||||||
name: isAlpha
|
|
||||||
? "Auto-update Alpha Channel"
|
|
||||||
: "Auto-update Stable Channel",
|
|
||||||
body: `This release contains the update information for ${isAlpha ? "alpha" : "stable"} channel.`,
|
|
||||||
prerelease: isAlpha,
|
|
||||||
});
|
|
||||||
updateRelease = createResponse.data;
|
|
||||||
console.log(
|
|
||||||
`Created new ${releaseTag} release with ID: ${updateRelease.id}`,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// If it's another error, throw it
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// File names based on release type
|
|
||||||
const jsonFile = isAlpha ? ALPHA_UPDATE_JSON_FILE : UPDATE_JSON_FILE;
|
|
||||||
const proxyFile = isAlpha ? ALPHA_UPDATE_JSON_PROXY : UPDATE_JSON_PROXY;
|
|
||||||
|
|
||||||
// Delete existing assets with these names
|
|
||||||
for (let asset of updateRelease.assets) {
|
|
||||||
if (asset.name === jsonFile) {
|
|
||||||
await github.rest.repos.deleteReleaseAsset({
|
|
||||||
...options,
|
|
||||||
asset_id: asset.id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (asset.name === proxyFile) {
|
|
||||||
await github.rest.repos
|
|
||||||
.deleteReleaseAsset({ ...options, asset_id: asset.id })
|
|
||||||
.catch(console.error); // do not break the pipeline
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Upload new assets
|
|
||||||
await github.rest.repos.uploadReleaseAsset({
|
|
||||||
...options,
|
|
||||||
release_id: updateRelease.id,
|
|
||||||
name: jsonFile,
|
|
||||||
data: JSON.stringify(updateData, null, 2),
|
|
||||||
});
|
|
||||||
|
|
||||||
await github.rest.repos.uploadReleaseAsset({
|
|
||||||
...options,
|
|
||||||
release_id: updateRelease.id,
|
|
||||||
name: proxyFile,
|
|
||||||
data: JSON.stringify(updateDataNew, null, 2),
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`Successfully uploaded ${isAlpha ? "alpha" : "stable"} update files to ${releaseTag}`,
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(
|
|
||||||
`Failed to process ${isAlpha ? "alpha" : "stable"} release:`,
|
|
||||||
error.message,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
// win64 signature
|
||||||
if (error.status === 404) {
|
if (name.endsWith("x64-setup.nsis.zip.sig")) {
|
||||||
console.log(`Release not found for tag: ${tag.name}, skipping...`);
|
const sig = await getSignature(browser_download_url);
|
||||||
|
updateData.platforms.win64.signature = sig;
|
||||||
|
updateData.platforms["windows-x86_64"].signature = sig;
|
||||||
|
}
|
||||||
|
|
||||||
|
// win arm url
|
||||||
|
if (name.endsWith("arm64-setup.nsis.zip")) {
|
||||||
|
updateData.platforms["windows-aarch64"].url = browser_download_url;
|
||||||
|
}
|
||||||
|
// win arm signature
|
||||||
|
if (name.endsWith("arm64-setup.nsis.zip.sig")) {
|
||||||
|
const sig = await getSignature(browser_download_url);
|
||||||
|
updateData.platforms["windows-aarch64"].signature = sig;
|
||||||
|
}
|
||||||
|
|
||||||
|
// darwin url (intel)
|
||||||
|
if (name.endsWith(".app.tar.gz") && !name.includes("aarch")) {
|
||||||
|
updateData.platforms.darwin.url = browser_download_url;
|
||||||
|
updateData.platforms["darwin-intel"].url = browser_download_url;
|
||||||
|
updateData.platforms["darwin-x86_64"].url = browser_download_url;
|
||||||
|
}
|
||||||
|
// darwin signature (intel)
|
||||||
|
if (name.endsWith(".app.tar.gz.sig") && !name.includes("aarch")) {
|
||||||
|
const sig = await getSignature(browser_download_url);
|
||||||
|
updateData.platforms.darwin.signature = sig;
|
||||||
|
updateData.platforms["darwin-intel"].signature = sig;
|
||||||
|
updateData.platforms["darwin-x86_64"].signature = sig;
|
||||||
|
}
|
||||||
|
|
||||||
|
// darwin url (aarch)
|
||||||
|
if (name.endsWith("aarch64.app.tar.gz")) {
|
||||||
|
updateData.platforms["darwin-aarch64"].url = browser_download_url;
|
||||||
|
}
|
||||||
|
// darwin signature (aarch)
|
||||||
|
if (name.endsWith("aarch64.app.tar.gz.sig")) {
|
||||||
|
const sig = await getSignature(browser_download_url);
|
||||||
|
updateData.platforms["darwin-aarch64"].signature = sig;
|
||||||
|
}
|
||||||
|
|
||||||
|
// linux x64 url
|
||||||
|
if (name.endsWith("amd64.AppImage.tar.gz")) {
|
||||||
|
updateData.platforms.linux.url = browser_download_url;
|
||||||
|
updateData.platforms["linux-x86_64"].url = browser_download_url;
|
||||||
|
// 暂时使用x64版本的url和sig,使得可以检查更新,但aarch64版本还不支持构建appimage
|
||||||
|
updateData.platforms["linux-aarch64"].url = browser_download_url;
|
||||||
|
updateData.platforms["linux-armv7"].url = browser_download_url;
|
||||||
|
}
|
||||||
|
// linux x64 signature
|
||||||
|
if (name.endsWith("amd64.AppImage.tar.gz.sig")) {
|
||||||
|
const sig = await getSignature(browser_download_url);
|
||||||
|
updateData.platforms.linux.signature = sig;
|
||||||
|
updateData.platforms["linux-x86_64"].signature = sig;
|
||||||
|
// 暂时使用x64版本的url和sig,使得可以检查更新,但aarch64版本还不支持构建appimage
|
||||||
|
updateData.platforms["linux-aarch64"].signature = sig;
|
||||||
|
updateData.platforms["linux-armv7"].signature = sig;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.allSettled(promises);
|
||||||
|
console.log(updateData);
|
||||||
|
|
||||||
|
// maybe should test the signature as well
|
||||||
|
// delete the null field
|
||||||
|
Object.entries(updateData.platforms).forEach(([key, value]) => {
|
||||||
|
if (!value.url) {
|
||||||
|
console.log(`[Error]: failed to parse release for "${key}"`);
|
||||||
|
delete updateData.platforms[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 生成一个代理github的更新文件
|
||||||
|
// 使用 https://hub.fastgit.xyz/ 做github资源的加速
|
||||||
|
const updateDataNew = JSON.parse(JSON.stringify(updateData));
|
||||||
|
|
||||||
|
Object.entries(updateDataNew.platforms).forEach(([key, value]) => {
|
||||||
|
if (value.url) {
|
||||||
|
updateDataNew.platforms[key].url =
|
||||||
|
"https://mirror.ghproxy.com/" + value.url;
|
||||||
} else {
|
} else {
|
||||||
console.error(
|
console.log(`[Error]: updateDataNew.platforms.${key} is null`);
|
||||||
`Failed to get release for tag: ${tag.name}`,
|
}
|
||||||
error.message,
|
});
|
||||||
);
|
|
||||||
|
// update the update.json
|
||||||
|
const { data: updateRelease } = await github.rest.repos.getReleaseByTag({
|
||||||
|
...options,
|
||||||
|
tag: UPDATE_TAG_NAME,
|
||||||
|
});
|
||||||
|
|
||||||
|
// delete the old assets
|
||||||
|
for (let asset of updateRelease.assets) {
|
||||||
|
if (asset.name === UPDATE_JSON_FILE) {
|
||||||
|
await github.rest.repos.deleteReleaseAsset({
|
||||||
|
...options,
|
||||||
|
asset_id: asset.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (asset.name === UPDATE_JSON_PROXY) {
|
||||||
|
await github.rest.repos
|
||||||
|
.deleteReleaseAsset({ ...options, asset_id: asset.id })
|
||||||
|
.catch(console.error); // do not break the pipeline
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// upload new assets
|
||||||
|
await github.rest.repos.uploadReleaseAsset({
|
||||||
|
...options,
|
||||||
|
release_id: updateRelease.id,
|
||||||
|
name: UPDATE_JSON_FILE,
|
||||||
|
data: JSON.stringify(updateData, null, 2),
|
||||||
|
});
|
||||||
|
|
||||||
|
await github.rest.repos.uploadReleaseAsset({
|
||||||
|
...options,
|
||||||
|
release_id: updateRelease.id,
|
||||||
|
name: UPDATE_JSON_PROXY,
|
||||||
|
data: JSON.stringify(updateDataNew, null, 2),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the signature file content
|
// get the signature file content
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
import clc from "cli-color";
|
|
||||||
|
|
||||||
export const log_success = (msg, ...optionalParams) =>
|
|
||||||
console.log(clc.green(msg), ...optionalParams);
|
|
||||||
export const log_error = (msg, ...optionalParams) =>
|
|
||||||
console.log(clc.red(msg), ...optionalParams);
|
|
||||||
export const log_info = (msg, ...optionalParams) =>
|
|
||||||
console.log(clc.bgBlue(msg), ...optionalParams);
|
|
||||||
var debugMsg = clc.xterm(245);
|
|
||||||
export const log_debug = (msg, ...optionalParams) =>
|
|
||||||
console.log(debugMsg(msg), ...optionalParams);
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
avoid-breaking-exported-api = true
|
|
||||||
2
src-tauri/.gitignore
vendored
@@ -1,8 +1,6 @@
|
|||||||
# Generated by Cargo
|
# Generated by Cargo
|
||||||
# will have compiled files and executables
|
# will have compiled files and executables
|
||||||
/target/
|
/target/
|
||||||
gen/
|
|
||||||
WixTools
|
WixTools
|
||||||
resources
|
resources
|
||||||
sidecar
|
sidecar
|
||||||
|
|
||||||
|
|||||||
6524
src-tauri/Cargo.lock
generated
152
src-tauri/Cargo.toml
Executable file → Normal file
@@ -1,116 +1,52 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "clash-verge"
|
name = "clash-verge"
|
||||||
version = "0.2.3"
|
version = "1.6.1"
|
||||||
description = "clash verge"
|
description = "clash verge"
|
||||||
authors = ["zzzgydi", "wonfen", "MystiPanda", "coolcoala"]
|
authors = ["zzzgydi", "wonfen", "MystiPanda"]
|
||||||
license = "GPL-3.0-only"
|
license = "GPL-3.0-only"
|
||||||
repository = "https://github.com/coolcoala/clash-verge-rev-lite.git"
|
repository = "https://github.com/clash-verge-rev/clash-verge-rev.git"
|
||||||
default-run = "clash-verge"
|
default-run = "clash-verge"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
[package.metadata.bundle]
|
|
||||||
identifier = "io.github.clash-verge-rev.clash-verge-rev"
|
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
tauri-build = { version = "2.3.0", features = [] }
|
tauri-build = { version = "1", features = [] }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
url = "2.5.4"
|
warp = "0.3"
|
||||||
os_info = "3.0"
|
anyhow = "1.0"
|
||||||
machine-uid = "0.2"
|
dirs = "5.0"
|
||||||
warp = "0.3.7"
|
open = "5.0"
|
||||||
anyhow = "1.0.98"
|
log = "0.4"
|
||||||
dirs = "6.0"
|
dunce = "1.0"
|
||||||
open = "5.3.2"
|
log4rs = "1"
|
||||||
log = "0.4.27"
|
|
||||||
dunce = "1.0.5"
|
|
||||||
log4rs = "1.3.0"
|
|
||||||
nanoid = "0.4"
|
nanoid = "0.4"
|
||||||
chrono = "0.4.41"
|
chrono = "0.4"
|
||||||
sysinfo = "0.35.2"
|
sysinfo = "0.30"
|
||||||
boa_engine = "0.20.0"
|
boa_engine = "0.18"
|
||||||
serde_json = "1.0.140"
|
serde_json = "1.0"
|
||||||
serde_yaml = "0.9.34-deprecated"
|
serde_yaml = "0.9"
|
||||||
once_cell = "1.21.3"
|
once_cell = "1.18"
|
||||||
lazy_static = "1.5.0"
|
|
||||||
port_scanner = "0.1.5"
|
port_scanner = "0.1.5"
|
||||||
delay_timer = "0.11.6"
|
delay_timer = "0.11.5"
|
||||||
parking_lot = "0.12.4"
|
parking_lot = "0.12"
|
||||||
percent-encoding = "2.3.1"
|
percent-encoding = "2.3.1"
|
||||||
tokio = { version = "1.45.1", features = [
|
window-shadows = { version = "0.2" }
|
||||||
"rt-multi-thread",
|
tokio = { version = "1", features = ["full"] }
|
||||||
"macros",
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
"time",
|
reqwest = { version = "0.12", features = ["json", "rustls-tls"] }
|
||||||
"sync",
|
sysproxy = { git="https://github.com/zzzgydi/sysproxy-rs", branch = "main" }
|
||||||
] }
|
auto-launch = { git="https://github.com/zzzgydi/auto-launch", branch = "main" }
|
||||||
serde = { version = "1.0.219", features = ["derive"] }
|
tauri = { version = "1.6", features = [ "fs-read-file", "fs-exists", "path-all", "protocol-asset", "dialog-open", "notification-all", "icon-png", "icon-ico", "clipboard-all", "global-shortcut-all", "process-all", "shell-all", "system-tray", "updater", "window-all", "devtools"] }
|
||||||
reqwest = { version = "0.12.20", features = ["json", "rustls-tls", "cookies"] }
|
|
||||||
regex = "1.11.1"
|
|
||||||
sysproxy = { git = "https://github.com/clash-verge-rev/sysproxy-rs" }
|
|
||||||
image = "0.25.6"
|
|
||||||
imageproc = "0.25.0"
|
|
||||||
tauri = { version = "2.6.2", features = [
|
|
||||||
"protocol-asset",
|
|
||||||
"devtools",
|
|
||||||
"tray-icon",
|
|
||||||
"image-ico",
|
|
||||||
"image-png",
|
|
||||||
] }
|
|
||||||
network-interface = { version = "2.0.1", features = ["serde"] }
|
|
||||||
tauri-plugin-shell = "2.3.0"
|
|
||||||
tauri-plugin-dialog = "2.3.0"
|
|
||||||
tauri-plugin-fs = "2.4.0"
|
|
||||||
tauri-plugin-process = "2.3.0"
|
|
||||||
tauri-plugin-clipboard-manager = "2.3.0"
|
|
||||||
tauri-plugin-deep-link = "2.4.0"
|
|
||||||
tauri-plugin-devtools = "2.0.0"
|
|
||||||
tauri-plugin-window-state = "2.3.0"
|
|
||||||
zip = "4.2.0"
|
|
||||||
reqwest_dav = "0.2.1"
|
|
||||||
aes-gcm = { version = "0.10.3", features = ["std"] }
|
|
||||||
base64 = "0.22.1"
|
|
||||||
getrandom = "0.3.3"
|
|
||||||
tokio-tungstenite = "0.27.0"
|
|
||||||
futures = "0.3.31"
|
|
||||||
sys-locale = "0.3.2"
|
|
||||||
async-trait = "0.1.88"
|
|
||||||
mihomo_api = { path = "src_crates/crate_mihomo_api" }
|
|
||||||
ab_glyph = "0.2.29"
|
|
||||||
tungstenite = "0.27.0"
|
|
||||||
libc = "0.2.174"
|
|
||||||
gethostname = "1.0.2"
|
|
||||||
hmac = "0.12.1"
|
|
||||||
sha2 = "0.10.9"
|
|
||||||
hex = "0.4.3"
|
|
||||||
scopeguard = "1.2.0"
|
|
||||||
tauri-plugin-notification = "2.3.0"
|
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
runas = "=1.2.0"
|
runas = "=1.2.0"
|
||||||
deelevate = "0.2.0"
|
deelevate = "0.2.0"
|
||||||
winreg = "0.55.0"
|
winreg = "0.52.0"
|
||||||
winapi = { version = "0.3.9", features = [
|
|
||||||
"winbase",
|
|
||||||
"fileapi",
|
|
||||||
"winnt",
|
|
||||||
"handleapi",
|
|
||||||
"errhandlingapi",
|
|
||||||
"minwindef",
|
|
||||||
"winerror",
|
|
||||||
"tlhelp32",
|
|
||||||
"processthreadsapi",
|
|
||||||
"winhttp",
|
|
||||||
"winreg",
|
|
||||||
] }
|
|
||||||
|
|
||||||
[target.'cfg(target_os = "linux")'.dependencies]
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
users = "0.11.0"
|
users = "0.11.0"
|
||||||
|
#openssl
|
||||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
|
||||||
tauri-plugin-autostart = "2.5.0"
|
|
||||||
tauri-plugin-global-shortcut = "2.3.0"
|
|
||||||
tauri-plugin-updater = "2.9.0"
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["custom-protocol"]
|
default = ["custom-protocol"]
|
||||||
@@ -122,35 +58,3 @@ panic = "abort"
|
|||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
lto = true
|
lto = true
|
||||||
opt-level = "s"
|
opt-level = "s"
|
||||||
strip = true
|
|
||||||
|
|
||||||
[profile.dev]
|
|
||||||
incremental = true
|
|
||||||
codegen-units = 256 # 增加编译单元,提升编译速度
|
|
||||||
opt-level = 0 # 禁用优化,进一步提升编译速度
|
|
||||||
debug = true # 保留调试信息
|
|
||||||
strip = false # 不剥离符号,保留调试信息
|
|
||||||
|
|
||||||
[profile.fast-release]
|
|
||||||
inherits = "release" # 继承 release 的配置
|
|
||||||
panic = "abort" # 与 release 相同
|
|
||||||
codegen-units = 256 # 增加编译单元,提升编译速度
|
|
||||||
lto = false # 禁用 LTO,提升编译速度
|
|
||||||
opt-level = 0 # 禁用优化,大幅提升编译速度
|
|
||||||
debug = true # 保留调试信息
|
|
||||||
strip = false # 不剥离符号,保留调试信息
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
name = "app_lib"
|
|
||||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
tempfile = "3.20.0"
|
|
||||||
|
|
||||||
[workspace]
|
|
||||||
members = ["src_crates/crate_mihomo_api"]
|
|
||||||
|
|
||||||
# [patch.crates-io]
|
|
||||||
# bitflags = { git = "https://github.com/bitflags/bitflags", rev = "2.9.0" }
|
|
||||||
# zerocopy = { git = "https://github.com/google/zerocopy", rev = "v0.8.24" }
|
|
||||||
# tungstenite = { git = "https://github.com/snapview/tungstenite-rs", rev = "v0.26.2" }
|
|
||||||
|
|||||||
17
src-tauri/Info.plist
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleURLTypes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleURLName</key>
|
||||||
|
<string>Clash Verge</string>
|
||||||
|
<key>CFBundleURLSchemes</key>
|
||||||
|
<array>
|
||||||
|
<string>clash</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"identifier": "desktop-windows-capability",
|
|
||||||
"description": "permissions for desktop windows applications",
|
|
||||||
"windows": ["main"],
|
|
||||||
"permissions": [
|
|
||||||
"core:webview:allow-create-webview",
|
|
||||||
"core:webview:allow-create-webview-window"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
{
|
|
||||||
"identifier": "desktop-capability",
|
|
||||||
"platforms": ["macOS", "windows", "linux"],
|
|
||||||
"webviews": ["main"],
|
|
||||||
"windows": ["main"],
|
|
||||||
"permissions": [
|
|
||||||
"global-shortcut:default",
|
|
||||||
"updater:default",
|
|
||||||
"dialog:default",
|
|
||||||
"dialog:allow-ask",
|
|
||||||
"dialog:allow-message",
|
|
||||||
"updater:default",
|
|
||||||
"updater:allow-check",
|
|
||||||
"updater:allow-download-and-install",
|
|
||||||
"process:allow-restart",
|
|
||||||
"deep-link:default",
|
|
||||||
"autostart:allow-enable",
|
|
||||||
"autostart:allow-disable",
|
|
||||||
"autostart:allow-is-enabled",
|
|
||||||
"core:window:allow-set-theme",
|
|
||||||
"notification:default"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
{
|
|
||||||
"identifier": "migrated",
|
|
||||||
"description": "permissions that were migrated from v1",
|
|
||||||
"local": true,
|
|
||||||
"windows": ["main"],
|
|
||||||
"permissions": [
|
|
||||||
"core:default",
|
|
||||||
"fs:allow-read-file",
|
|
||||||
"fs:allow-exists",
|
|
||||||
{
|
|
||||||
"identifier": "fs:scope",
|
|
||||||
"allow": ["$APPDATA/**", "$RESOURCE/../**", "**"]
|
|
||||||
},
|
|
||||||
"fs:allow-write-file",
|
|
||||||
{
|
|
||||||
"identifier": "fs:scope",
|
|
||||||
"allow": ["$APPDATA/**", "$RESOURCE/../**", "**"]
|
|
||||||
},
|
|
||||||
"fs:allow-app-read",
|
|
||||||
"fs:allow-app-read-recursive",
|
|
||||||
"fs:allow-appcache-read",
|
|
||||||
"fs:allow-appcache-read-recursive",
|
|
||||||
"fs:allow-appconfig-read",
|
|
||||||
"fs:allow-appconfig-read-recursive",
|
|
||||||
"core:window:allow-create",
|
|
||||||
"core:window:allow-center",
|
|
||||||
"core:window:allow-request-user-attention",
|
|
||||||
"core:window:allow-set-resizable",
|
|
||||||
"core:window:allow-set-maximizable",
|
|
||||||
"core:window:allow-set-minimizable",
|
|
||||||
"core:window:allow-set-closable",
|
|
||||||
"core:window:allow-set-title",
|
|
||||||
"core:window:allow-maximize",
|
|
||||||
"core:window:allow-unmaximize",
|
|
||||||
"core:window:allow-minimize",
|
|
||||||
"core:window:allow-unminimize",
|
|
||||||
"core:window:allow-show",
|
|
||||||
"core:window:allow-hide",
|
|
||||||
"core:window:allow-close",
|
|
||||||
"core:window:allow-set-decorations",
|
|
||||||
"core:window:allow-set-always-on-top",
|
|
||||||
"core:window:allow-set-content-protected",
|
|
||||||
"core:window:allow-set-size",
|
|
||||||
"core:window:allow-set-min-size",
|
|
||||||
"core:window:allow-set-max-size",
|
|
||||||
"core:window:allow-set-position",
|
|
||||||
"core:window:allow-set-fullscreen",
|
|
||||||
"core:window:allow-set-focus",
|
|
||||||
"core:window:allow-set-icon",
|
|
||||||
"core:window:allow-set-skip-taskbar",
|
|
||||||
"core:window:allow-set-cursor-grab",
|
|
||||||
"core:window:allow-set-cursor-visible",
|
|
||||||
"core:window:allow-set-cursor-icon",
|
|
||||||
"core:window:allow-set-cursor-position",
|
|
||||||
"core:window:allow-set-ignore-cursor-events",
|
|
||||||
"core:window:allow-start-dragging",
|
|
||||||
"core:window:allow-maximize",
|
|
||||||
"core:window:allow-toggle-maximize",
|
|
||||||
"core:window:allow-unmaximize",
|
|
||||||
"core:window:allow-minimize",
|
|
||||||
"core:window:allow-unminimize",
|
|
||||||
"core:window:allow-set-maximizable",
|
|
||||||
"core:window:allow-set-minimizable",
|
|
||||||
"core:webview:allow-print",
|
|
||||||
"shell:allow-execute",
|
|
||||||
"shell:allow-open",
|
|
||||||
"shell:allow-kill",
|
|
||||||
"shell:allow-spawn",
|
|
||||||
"shell:allow-stdin-write",
|
|
||||||
"dialog:allow-open",
|
|
||||||
"global-shortcut:allow-is-registered",
|
|
||||||
"global-shortcut:allow-register",
|
|
||||||
"global-shortcut:allow-register-all",
|
|
||||||
"global-shortcut:allow-unregister",
|
|
||||||
"global-shortcut:allow-unregister-all",
|
|
||||||
"process:allow-restart",
|
|
||||||
"process:allow-exit",
|
|
||||||
"clipboard-manager:allow-read-text",
|
|
||||||
"clipboard-manager:allow-write-text",
|
|
||||||
"shell:default",
|
|
||||||
"dialog:default"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,236 +0,0 @@
|
|||||||
# This template contains all of the possible sections and their default values
|
|
||||||
|
|
||||||
# Note that all fields that take a lint level have these possible values:
|
|
||||||
# * deny - An error will be produced and the check will fail
|
|
||||||
# * warn - A warning will be produced, but the check will not fail
|
|
||||||
# * allow - No warning or error will be produced, though in some cases a note
|
|
||||||
# will be
|
|
||||||
|
|
||||||
# The values provided in this template are the default values that will be used
|
|
||||||
# when any section or field is not specified in your own configuration
|
|
||||||
|
|
||||||
# Root options
|
|
||||||
|
|
||||||
# The graph table configures how the dependency graph is constructed and thus
|
|
||||||
# which crates the checks are performed against
|
|
||||||
[graph]
|
|
||||||
# If 1 or more target triples (and optionally, target_features) are specified,
|
|
||||||
# only the specified targets will be checked when running `cargo deny check`.
|
|
||||||
# This means, if a particular package is only ever used as a target specific
|
|
||||||
# dependency, such as, for example, the `nix` crate only being used via the
|
|
||||||
# `target_family = "unix"` configuration, that only having windows targets in
|
|
||||||
# this list would mean the nix crate, as well as any of its exclusive
|
|
||||||
# dependencies not shared by any other crates, would be ignored, as the target
|
|
||||||
# list here is effectively saying which targets you are building for.
|
|
||||||
targets = [
|
|
||||||
# The triple can be any string, but only the target triples built in to
|
|
||||||
# rustc (as of 1.40) can be checked against actual config expressions
|
|
||||||
#"x86_64-unknown-linux-musl",
|
|
||||||
# You can also specify which target_features you promise are enabled for a
|
|
||||||
# particular target. target_features are currently not validated against
|
|
||||||
# the actual valid features supported by the target architecture.
|
|
||||||
#{ triple = "wasm32-unknown-unknown", features = ["atomics"] },
|
|
||||||
]
|
|
||||||
# When creating the dependency graph used as the source of truth when checks are
|
|
||||||
# executed, this field can be used to prune crates from the graph, removing them
|
|
||||||
# from the view of cargo-deny. This is an extremely heavy hammer, as if a crate
|
|
||||||
# is pruned from the graph, all of its dependencies will also be pruned unless
|
|
||||||
# they are connected to another crate in the graph that hasn't been pruned,
|
|
||||||
# so it should be used with care. The identifiers are [Package ID Specifications]
|
|
||||||
# (https://doc.rust-lang.org/cargo/reference/pkgid-spec.html)
|
|
||||||
#exclude = []
|
|
||||||
# If true, metadata will be collected with `--all-features`. Note that this can't
|
|
||||||
# be toggled off if true, if you want to conditionally enable `--all-features` it
|
|
||||||
# is recommended to pass `--all-features` on the cmd line instead
|
|
||||||
all-features = false
|
|
||||||
# If true, metadata will be collected with `--no-default-features`. The same
|
|
||||||
# caveat with `all-features` applies
|
|
||||||
no-default-features = false
|
|
||||||
# If set, these feature will be enabled when collecting metadata. If `--features`
|
|
||||||
# is specified on the cmd line they will take precedence over this option.
|
|
||||||
#features = []
|
|
||||||
|
|
||||||
# The output table provides options for how/if diagnostics are outputted
|
|
||||||
[output]
|
|
||||||
# When outputting inclusion graphs in diagnostics that include features, this
|
|
||||||
# option can be used to specify the depth at which feature edges will be added.
|
|
||||||
# This option is included since the graphs can be quite large and the addition
|
|
||||||
# of features from the crate(s) to all of the graph roots can be far too verbose.
|
|
||||||
# This option can be overridden via `--feature-depth` on the cmd line
|
|
||||||
feature-depth = 1
|
|
||||||
|
|
||||||
# This section is considered when running `cargo deny check advisories`
|
|
||||||
# More documentation for the advisories section can be found here:
|
|
||||||
# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html
|
|
||||||
[advisories]
|
|
||||||
# The path where the advisory databases are cloned/fetched into
|
|
||||||
#db-path = "$CARGO_HOME/advisory-dbs"
|
|
||||||
# The url(s) of the advisory databases to use
|
|
||||||
#db-urls = ["https://github.com/rustsec/advisory-db"]
|
|
||||||
# A list of advisory IDs to ignore. Note that ignored advisories will still
|
|
||||||
# output a note when they are encountered.
|
|
||||||
ignore = [
|
|
||||||
#"RUSTSEC-0000-0000",
|
|
||||||
#{ id = "RUSTSEC-0000-0000", reason = "you can specify a reason the advisory is ignored" },
|
|
||||||
#"a-crate-that-is-yanked@0.1.1", # you can also ignore yanked crate versions if you wish
|
|
||||||
#{ crate = "a-crate-that-is-yanked@0.1.1", reason = "you can specify why you are ignoring the yanked crate" },
|
|
||||||
"RUSTSEC-2024-0415",
|
|
||||||
]
|
|
||||||
# If this is true, then cargo deny will use the git executable to fetch advisory database.
|
|
||||||
# If this is false, then it uses a built-in git library.
|
|
||||||
# Setting this to true can be helpful if you have special authentication requirements that cargo-deny does not support.
|
|
||||||
# See Git Authentication for more information about setting up git authentication.
|
|
||||||
#git-fetch-with-cli = true
|
|
||||||
|
|
||||||
# This section is considered when running `cargo deny check licenses`
|
|
||||||
# More documentation for the licenses section can be found here:
|
|
||||||
# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html
|
|
||||||
[licenses]
|
|
||||||
# List of explicitly allowed licenses
|
|
||||||
# See https://spdx.org/licenses/ for list of possible licenses
|
|
||||||
# [possible values: any SPDX 3.11 short identifier (+ optional exception)].
|
|
||||||
allow = [
|
|
||||||
#"MIT",
|
|
||||||
#"Apache-2.0",
|
|
||||||
#"Apache-2.0 WITH LLVM-exception",
|
|
||||||
]
|
|
||||||
# The confidence threshold for detecting a license from license text.
|
|
||||||
# The higher the value, the more closely the license text must be to the
|
|
||||||
# canonical license text of a valid SPDX license file.
|
|
||||||
# [possible values: any between 0.0 and 1.0].
|
|
||||||
confidence-threshold = 0.85
|
|
||||||
# Allow 1 or more licenses on a per-crate basis, so that particular licenses
|
|
||||||
# aren't accepted for every possible crate as with the normal allow list
|
|
||||||
exceptions = [
|
|
||||||
# Each entry is the crate and version constraint, and its specific allow
|
|
||||||
# list
|
|
||||||
#{ allow = ["Zlib"], crate = "adler32" },
|
|
||||||
]
|
|
||||||
|
|
||||||
# Some crates don't have (easily) machine readable licensing information,
|
|
||||||
# adding a clarification entry for it allows you to manually specify the
|
|
||||||
# licensing information
|
|
||||||
#[[licenses.clarify]]
|
|
||||||
# The package spec the clarification applies to
|
|
||||||
#crate = "ring"
|
|
||||||
# The SPDX expression for the license requirements of the crate
|
|
||||||
#expression = "MIT AND ISC AND OpenSSL"
|
|
||||||
# One or more files in the crate's source used as the "source of truth" for
|
|
||||||
# the license expression. If the contents match, the clarification will be used
|
|
||||||
# when running the license check, otherwise the clarification will be ignored
|
|
||||||
# and the crate will be checked normally, which may produce warnings or errors
|
|
||||||
# depending on the rest of your configuration
|
|
||||||
#license-files = [
|
|
||||||
# Each entry is a crate relative path, and the (opaque) hash of its contents
|
|
||||||
#{ path = "LICENSE", hash = 0xbd0eed23 }
|
|
||||||
#]
|
|
||||||
|
|
||||||
[licenses.private]
|
|
||||||
# If true, ignores workspace crates that aren't published, or are only
|
|
||||||
# published to private registries.
|
|
||||||
# To see how to mark a crate as unpublished (to the official registry),
|
|
||||||
# visit https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field.
|
|
||||||
ignore = false
|
|
||||||
# One or more private registries that you might publish crates to, if a crate
|
|
||||||
# is only published to private registries, and ignore is true, the crate will
|
|
||||||
# not have its license(s) checked
|
|
||||||
registries = [
|
|
||||||
#"https://sekretz.com/registry
|
|
||||||
]
|
|
||||||
|
|
||||||
# This section is considered when running `cargo deny check bans`.
|
|
||||||
# More documentation about the 'bans' section can be found here:
|
|
||||||
# https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html
|
|
||||||
[bans]
|
|
||||||
# Lint level for when multiple versions of the same crate are detected
|
|
||||||
multiple-versions = "warn"
|
|
||||||
# Lint level for when a crate version requirement is `*`
|
|
||||||
wildcards = "allow"
|
|
||||||
# The graph highlighting used when creating dotgraphs for crates
|
|
||||||
# with multiple versions
|
|
||||||
# * lowest-version - The path to the lowest versioned duplicate is highlighted
|
|
||||||
# * simplest-path - The path to the version with the fewest edges is highlighted
|
|
||||||
# * all - Both lowest-version and simplest-path are used
|
|
||||||
highlight = "all"
|
|
||||||
# The default lint level for `default` features for crates that are members of
|
|
||||||
# the workspace that is being checked. This can be overridden by allowing/denying
|
|
||||||
# `default` on a crate-by-crate basis if desired.
|
|
||||||
workspace-default-features = "allow"
|
|
||||||
# The default lint level for `default` features for external crates that are not
|
|
||||||
# members of the workspace. This can be overridden by allowing/denying `default`
|
|
||||||
# on a crate-by-crate basis if desired.
|
|
||||||
external-default-features = "allow"
|
|
||||||
# List of crates that are allowed. Use with care!
|
|
||||||
allow = [
|
|
||||||
#"ansi_term@0.11.0",
|
|
||||||
#{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is allowed" },
|
|
||||||
]
|
|
||||||
# List of crates to deny
|
|
||||||
deny = [
|
|
||||||
#"ansi_term@0.11.0",
|
|
||||||
#{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is banned" },
|
|
||||||
# Wrapper crates can optionally be specified to allow the crate when it
|
|
||||||
# is a direct dependency of the otherwise banned crate
|
|
||||||
#{ crate = "ansi_term@0.11.0", wrappers = ["this-crate-directly-depends-on-ansi_term"] },
|
|
||||||
]
|
|
||||||
|
|
||||||
# List of features to allow/deny
|
|
||||||
# Each entry the name of a crate and a version range. If version is
|
|
||||||
# not specified, all versions will be matched.
|
|
||||||
#[[bans.features]]
|
|
||||||
#crate = "reqwest"
|
|
||||||
# Features to not allow
|
|
||||||
#deny = ["json"]
|
|
||||||
# Features to allow
|
|
||||||
#allow = [
|
|
||||||
# "rustls",
|
|
||||||
# "__rustls",
|
|
||||||
# "__tls",
|
|
||||||
# "hyper-rustls",
|
|
||||||
# "rustls",
|
|
||||||
# "rustls-pemfile",
|
|
||||||
# "rustls-tls-webpki-roots",
|
|
||||||
# "tokio-rustls",
|
|
||||||
# "webpki-roots",
|
|
||||||
#]
|
|
||||||
# If true, the allowed features must exactly match the enabled feature set. If
|
|
||||||
# this is set there is no point setting `deny`
|
|
||||||
#exact = true
|
|
||||||
|
|
||||||
# Certain crates/versions that will be skipped when doing duplicate detection.
|
|
||||||
skip = [
|
|
||||||
#"ansi_term@0.11.0",
|
|
||||||
#{ crate = "ansi_term@0.11.0", reason = "you can specify a reason why it can't be updated/removed" },
|
|
||||||
]
|
|
||||||
# Similarly to `skip` allows you to skip certain crates during duplicate
|
|
||||||
# detection. Unlike skip, it also includes the entire tree of transitive
|
|
||||||
# dependencies starting at the specified crate, up to a certain depth, which is
|
|
||||||
# by default infinite.
|
|
||||||
skip-tree = [
|
|
||||||
#"ansi_term@0.11.0", # will be skipped along with _all_ of its direct and transitive dependencies
|
|
||||||
#{ crate = "ansi_term@0.11.0", depth = 20 },
|
|
||||||
]
|
|
||||||
|
|
||||||
# This section is considered when running `cargo deny check sources`.
|
|
||||||
# More documentation about the 'sources' section can be found here:
|
|
||||||
# https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html
|
|
||||||
[sources]
|
|
||||||
# Lint level for what to happen when a crate from a crate registry that is not
|
|
||||||
# in the allow list is encountered
|
|
||||||
unknown-registry = "warn"
|
|
||||||
# Lint level for what to happen when a crate from a git repository that is not
|
|
||||||
# in the allow list is encountered
|
|
||||||
unknown-git = "warn"
|
|
||||||
# List of URLs for allowed crate registries. Defaults to the crates.io index
|
|
||||||
# if not specified. If it is specified but empty, no registries are allowed.
|
|
||||||
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
|
|
||||||
# List of URLs for allowed Git repositories
|
|
||||||
allow-git = []
|
|
||||||
|
|
||||||
[sources.allow-org]
|
|
||||||
# github.com organizations to allow git sources for
|
|
||||||
github = []
|
|
||||||
# gitlab.com organizations to allow git sources for
|
|
||||||
gitlab = []
|
|
||||||
# bitbucket.org organizations to allow git sources for
|
|
||||||
bitbucket = []
|
|
||||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 1.8 KiB |
BIN
src-tauri/icons/Square107x107Logo.png
Normal file
|
After Width: | Height: | Size: 9.0 KiB |
BIN
src-tauri/icons/Square142x142Logo.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
src-tauri/icons/Square150x150Logo.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src-tauri/icons/Square284x284Logo.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
src-tauri/icons/Square30x30Logo.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
src-tauri/icons/Square310x310Logo.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
src-tauri/icons/Square44x44Logo.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
src-tauri/icons/Square71x71Logo.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
src-tauri/icons/Square89x89Logo.png
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
BIN
src-tauri/icons/StoreLogo.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
src-tauri/icons/icon-new.icns
Normal file
BIN
src-tauri/icons/icon-shrink.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 65 KiB |
BIN
src-tauri/icons/mac-tray-icon-sys.png
Normal file
|
After Width: | Height: | Size: 8.7 KiB |
BIN
src-tauri/icons/mac-tray-icon-tun.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
src-tauri/icons/mac-tray-icon.png
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 47 KiB |
BIN
src-tauri/icons/tray-icon-sys.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 107 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 54 KiB |
BIN
src-tauri/icons/tray-icon-tun.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 4.2 KiB |
BIN
src-tauri/icons/tray-icon.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 22 KiB |
@@ -1,4 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
chmod +x /usr/bin/install-service
|
|
||||||
chmod +x /usr/bin/uninstall-service
|
|
||||||
chmod +x /usr/bin/clash-verge-service
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
/usr/bin/uninstall-service
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>com.apple.security.app-sandbox</key>
|
|
||||||
<false/>
|
|
||||||
<key>com.apple.security.application-groups</key>
|
|
||||||
<array>
|
|
||||||
<string>io.github.clash-verge-rev.clash-verge-rev</string>
|
|
||||||
</array>
|
|
||||||
<key>com.apple.security.inherit</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
@@ -11,3 +11,4 @@ merge_derives = true
|
|||||||
use_try_shorthand = false
|
use_try_shorthand = false
|
||||||
use_field_init_shorthand = false
|
use_field_init_shorthand = false
|
||||||
force_explicit_abi = true
|
force_explicit_abi = true
|
||||||
|
imports_granularity = "Crate"
|
||||||
|
|||||||
@@ -1,246 +0,0 @@
|
|||||||
use super::CmdResult;
|
|
||||||
use crate::{
|
|
||||||
feat, logging,
|
|
||||||
utils::{dirs, logging::Type},
|
|
||||||
wrap_err,
|
|
||||||
};
|
|
||||||
use tauri::Manager;
|
|
||||||
|
|
||||||
/// 打开应用程序所在目录
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn open_app_dir() -> CmdResult<()> {
|
|
||||||
let app_dir = wrap_err!(dirs::app_home_dir())?;
|
|
||||||
wrap_err!(open::that(app_dir))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 打开核心所在目录
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn open_core_dir() -> CmdResult<()> {
|
|
||||||
let core_dir = wrap_err!(tauri::utils::platform::current_exe())?;
|
|
||||||
let core_dir = core_dir.parent().ok_or("failed to get core dir")?;
|
|
||||||
wrap_err!(open::that(core_dir))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 打开日志目录
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn open_logs_dir() -> CmdResult<()> {
|
|
||||||
let log_dir = wrap_err!(dirs::app_logs_dir())?;
|
|
||||||
wrap_err!(open::that(log_dir))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 打开网页链接
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn open_web_url(url: String) -> CmdResult<()> {
|
|
||||||
wrap_err!(open::that(url))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 打开/关闭开发者工具
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn open_devtools(app_handle: tauri::AppHandle) {
|
|
||||||
if let Some(window) = app_handle.get_webview_window("main") {
|
|
||||||
if !window.is_devtools_open() {
|
|
||||||
window.open_devtools();
|
|
||||||
} else {
|
|
||||||
window.close_devtools();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 退出应用
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn exit_app() {
|
|
||||||
feat::quit();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 重启应用
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn restart_app() -> CmdResult<()> {
|
|
||||||
feat::restart_app();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 获取便携版标识
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn get_portable_flag() -> CmdResult<bool> {
|
|
||||||
Ok(*dirs::PORTABLE_FLAG.get().unwrap_or(&false))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 获取应用目录
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn get_app_dir() -> CmdResult<String> {
|
|
||||||
let app_home_dir = wrap_err!(dirs::app_home_dir())?
|
|
||||||
.to_string_lossy()
|
|
||||||
.to_string();
|
|
||||||
Ok(app_home_dir)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 获取当前自启动状态
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn get_auto_launch_status() -> CmdResult<bool> {
|
|
||||||
use crate::core::sysopt::Sysopt;
|
|
||||||
wrap_err!(Sysopt::global().get_launch_status())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 下载图标缓存
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn download_icon_cache(url: String, name: String) -> CmdResult<String> {
|
|
||||||
let icon_cache_dir = wrap_err!(dirs::app_home_dir())?.join("icons").join("cache");
|
|
||||||
let icon_path = icon_cache_dir.join(&name);
|
|
||||||
|
|
||||||
if icon_path.exists() {
|
|
||||||
return Ok(icon_path.to_string_lossy().to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
if !icon_cache_dir.exists() {
|
|
||||||
let _ = std::fs::create_dir_all(&icon_cache_dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
let temp_path = icon_cache_dir.join(format!("{}.downloading", &name));
|
|
||||||
|
|
||||||
let response = wrap_err!(reqwest::get(&url).await)?;
|
|
||||||
|
|
||||||
let content_type = response
|
|
||||||
.headers()
|
|
||||||
.get(reqwest::header::CONTENT_TYPE)
|
|
||||||
.and_then(|v| v.to_str().ok())
|
|
||||||
.unwrap_or("");
|
|
||||||
|
|
||||||
let is_image = content_type.starts_with("image/");
|
|
||||||
|
|
||||||
let content = wrap_err!(response.bytes().await)?;
|
|
||||||
|
|
||||||
let is_html = content.len() > 15
|
|
||||||
&& (content.starts_with(b"<!DOCTYPE html")
|
|
||||||
|| content.starts_with(b"<html")
|
|
||||||
|| content.starts_with(b"<?xml"));
|
|
||||||
|
|
||||||
if is_image && !is_html {
|
|
||||||
{
|
|
||||||
let mut file = match std::fs::File::create(&temp_path) {
|
|
||||||
Ok(file) => file,
|
|
||||||
Err(_) => {
|
|
||||||
if icon_path.exists() {
|
|
||||||
return Ok(icon_path.to_string_lossy().to_string());
|
|
||||||
} else {
|
|
||||||
return Err("Failed to create temporary file".into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
wrap_err!(std::io::copy(&mut content.as_ref(), &mut file))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if !icon_path.exists() {
|
|
||||||
match std::fs::rename(&temp_path, &icon_path) {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(_) => {
|
|
||||||
let _ = std::fs::remove_file(&temp_path);
|
|
||||||
if icon_path.exists() {
|
|
||||||
return Ok(icon_path.to_string_lossy().to_string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let _ = std::fs::remove_file(&temp_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(icon_path.to_string_lossy().to_string())
|
|
||||||
} else {
|
|
||||||
let _ = std::fs::remove_file(&temp_path);
|
|
||||||
Err(format!("下载的内容不是有效图片: {url}"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
|
||||||
pub struct IconInfo {
|
|
||||||
name: String,
|
|
||||||
previous_t: String,
|
|
||||||
current_t: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 复制图标文件
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn copy_icon_file(path: String, icon_info: IconInfo) -> CmdResult<String> {
|
|
||||||
use std::{fs, path::Path};
|
|
||||||
|
|
||||||
let file_path = Path::new(&path);
|
|
||||||
|
|
||||||
let icon_dir = wrap_err!(dirs::app_home_dir())?.join("icons");
|
|
||||||
if !icon_dir.exists() {
|
|
||||||
let _ = fs::create_dir_all(&icon_dir);
|
|
||||||
}
|
|
||||||
let ext = match file_path.extension() {
|
|
||||||
Some(e) => e.to_string_lossy().to_string(),
|
|
||||||
None => "ico".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let dest_path = icon_dir.join(format!(
|
|
||||||
"{0}-{1}.{ext}",
|
|
||||||
icon_info.name, icon_info.current_t
|
|
||||||
));
|
|
||||||
if file_path.exists() {
|
|
||||||
if icon_info.previous_t.trim() != "" {
|
|
||||||
fs::remove_file(
|
|
||||||
icon_dir.join(format!("{0}-{1}.png", icon_info.name, icon_info.previous_t)),
|
|
||||||
)
|
|
||||||
.unwrap_or_default();
|
|
||||||
fs::remove_file(
|
|
||||||
icon_dir.join(format!("{0}-{1}.ico", icon_info.name, icon_info.previous_t)),
|
|
||||||
)
|
|
||||||
.unwrap_or_default();
|
|
||||||
}
|
|
||||||
logging!(
|
|
||||||
info,
|
|
||||||
Type::Cmd,
|
|
||||||
true,
|
|
||||||
"Copying icon file path: {:?} -> file dist: {:?}",
|
|
||||||
path,
|
|
||||||
dest_path
|
|
||||||
);
|
|
||||||
match fs::copy(file_path, &dest_path) {
|
|
||||||
Ok(_) => Ok(dest_path.to_string_lossy().to_string()),
|
|
||||||
Err(err) => Err(err.to_string()),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Err("file not found".to_string())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 通知UI已准备就绪
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn notify_ui_ready() -> CmdResult<()> {
|
|
||||||
log::info!(target: "app", "前端UI已准备就绪");
|
|
||||||
crate::utils::resolve::mark_ui_ready();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// UI加载阶段
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn update_ui_stage(stage: String) -> CmdResult<()> {
|
|
||||||
log::info!(target: "app", "UI加载阶段更新: {stage}");
|
|
||||||
|
|
||||||
use crate::utils::resolve::UiReadyStage;
|
|
||||||
|
|
||||||
let stage_enum = match stage.as_str() {
|
|
||||||
"NotStarted" => UiReadyStage::NotStarted,
|
|
||||||
"Loading" => UiReadyStage::Loading,
|
|
||||||
"DomReady" => UiReadyStage::DomReady,
|
|
||||||
"ResourcesLoaded" => UiReadyStage::ResourcesLoaded,
|
|
||||||
"Ready" => UiReadyStage::Ready,
|
|
||||||
_ => {
|
|
||||||
log::warn!(target: "app", "未知的UI加载阶段: {stage}");
|
|
||||||
return Err(format!("未知的UI加载阶段: {stage}"));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
crate::utils::resolve::update_ui_ready_stage(stage_enum);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 重置UI就绪状态
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn reset_ui_ready_state() -> CmdResult<()> {
|
|
||||||
log::info!(target: "app", "重置UI就绪状态");
|
|
||||||
crate::utils::resolve::reset_ui_ready();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
@@ -1,269 +0,0 @@
|
|||||||
use super::CmdResult;
|
|
||||||
use crate::{
|
|
||||||
config::*, core::*, feat, module::mihomo::MihomoManager, process::AsyncHandler, wrap_err,
|
|
||||||
};
|
|
||||||
use serde_yaml::Mapping;
|
|
||||||
|
|
||||||
/// 复制Clash环境变量
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn copy_clash_env() -> CmdResult {
|
|
||||||
feat::copy_clash_env();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 获取Clash信息
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn get_clash_info() -> CmdResult<ClashInfo> {
|
|
||||||
Ok(Config::clash().latest().get_client_info())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 修改Clash配置
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn patch_clash_config(payload: Mapping) -> CmdResult {
|
|
||||||
wrap_err!(feat::patch_clash(payload).await)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 修改Clash模式
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn patch_clash_mode(payload: String) -> CmdResult {
|
|
||||||
feat::change_clash_mode(payload);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 切换Clash核心
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn change_clash_core(clash_core: String) -> CmdResult<Option<String>> {
|
|
||||||
log::info!(target: "app", "changing core to {clash_core}");
|
|
||||||
|
|
||||||
match CoreManager::global()
|
|
||||||
.change_core(Some(clash_core.clone()))
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(_) => {
|
|
||||||
// 切换内核后重启内核
|
|
||||||
match CoreManager::global().restart_core().await {
|
|
||||||
Ok(_) => {
|
|
||||||
log::info!(target: "app", "core changed and restarted to {clash_core}");
|
|
||||||
handle::Handle::notice_message("config_core::change_success", &clash_core);
|
|
||||||
handle::Handle::refresh_clash();
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
let error_msg = format!("Core changed but failed to restart: {err}");
|
|
||||||
log::error!(target: "app", "{error_msg}");
|
|
||||||
handle::Handle::notice_message("config_core::change_error", &error_msg);
|
|
||||||
Ok(Some(error_msg))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
let error_msg = err.to_string();
|
|
||||||
log::error!(target: "app", "failed to change core: {error_msg}");
|
|
||||||
handle::Handle::notice_message("config_core::change_error", &error_msg);
|
|
||||||
Ok(Some(error_msg))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 启动核心
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn start_core() -> CmdResult {
|
|
||||||
wrap_err!(CoreManager::global().start_core().await)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 关闭核心
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn stop_core() -> CmdResult {
|
|
||||||
wrap_err!(CoreManager::global().stop_core().await)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 重启核心
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn restart_core() -> CmdResult {
|
|
||||||
wrap_err!(CoreManager::global().restart_core().await)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 获取代理延迟
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn clash_api_get_proxy_delay(
|
|
||||||
name: String,
|
|
||||||
url: Option<String>,
|
|
||||||
timeout: i32,
|
|
||||||
) -> CmdResult<serde_json::Value> {
|
|
||||||
MihomoManager::global()
|
|
||||||
.test_proxy_delay(&name, url, timeout)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 测试URL延迟
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn test_delay(url: String) -> CmdResult<u32> {
|
|
||||||
Ok(feat::test_delay(url).await.unwrap_or(10000u32))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 保存DNS配置到单独文件
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn save_dns_config(dns_config: Mapping) -> CmdResult {
|
|
||||||
use crate::utils::dirs;
|
|
||||||
use serde_yaml;
|
|
||||||
use std::fs;
|
|
||||||
|
|
||||||
// 获取DNS配置文件路径
|
|
||||||
let dns_path = dirs::app_home_dir()
|
|
||||||
.map_err(|e| e.to_string())?
|
|
||||||
.join("dns_config.yaml");
|
|
||||||
|
|
||||||
// 保存DNS配置到文件
|
|
||||||
let yaml_str = serde_yaml::to_string(&dns_config).map_err(|e| e.to_string())?;
|
|
||||||
fs::write(&dns_path, yaml_str).map_err(|e| e.to_string())?;
|
|
||||||
log::info!(target: "app", "DNS config saved to {dns_path:?}");
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 应用或撤销DNS配置
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn apply_dns_config(apply: bool) -> CmdResult {
|
|
||||||
use crate::{
|
|
||||||
config::Config,
|
|
||||||
core::{handle, CoreManager},
|
|
||||||
utils::dirs,
|
|
||||||
};
|
|
||||||
|
|
||||||
// 使用spawn来处理异步操作
|
|
||||||
AsyncHandler::spawn(move || async move {
|
|
||||||
if apply {
|
|
||||||
// 读取DNS配置文件
|
|
||||||
let dns_path = match dirs::app_home_dir() {
|
|
||||||
Ok(path) => path.join("dns_config.yaml"),
|
|
||||||
Err(e) => {
|
|
||||||
log::error!(target: "app", "Failed to get home dir: {e}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if !dns_path.exists() {
|
|
||||||
log::warn!(target: "app", "DNS config file not found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let dns_yaml = match std::fs::read_to_string(&dns_path) {
|
|
||||||
Ok(content) => content,
|
|
||||||
Err(e) => {
|
|
||||||
log::error!(target: "app", "Failed to read DNS config: {e}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 解析DNS配置并创建patch
|
|
||||||
let patch_config = match serde_yaml::from_str::<serde_yaml::Mapping>(&dns_yaml) {
|
|
||||||
Ok(config) => {
|
|
||||||
let mut patch = serde_yaml::Mapping::new();
|
|
||||||
patch.insert("dns".into(), config.into());
|
|
||||||
patch
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
log::error!(target: "app", "Failed to parse DNS config: {e}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
log::info!(target: "app", "Applying DNS config from file");
|
|
||||||
|
|
||||||
// 重新生成配置,确保DNS配置被正确应用
|
|
||||||
// 这里不调用patch_clash以避免将DNS配置写入config.yaml
|
|
||||||
Config::runtime()
|
|
||||||
.latest()
|
|
||||||
.patch_config(patch_config.clone());
|
|
||||||
|
|
||||||
// 首先重新生成配置
|
|
||||||
if let Err(err) = Config::generate().await {
|
|
||||||
log::error!(target: "app", "Failed to regenerate config with DNS: {err}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 然后应用新配置
|
|
||||||
if let Err(err) = CoreManager::global().update_config().await {
|
|
||||||
log::error!(target: "app", "Failed to apply config with DNS: {err}");
|
|
||||||
} else {
|
|
||||||
log::info!(target: "app", "DNS config successfully applied");
|
|
||||||
handle::Handle::refresh_clash();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 当关闭DNS设置时,不需要对配置进行任何修改
|
|
||||||
// 直接重新生成配置,让enhance函数自动跳过DNS配置的加载
|
|
||||||
log::info!(target: "app", "DNS settings disabled, regenerating config");
|
|
||||||
|
|
||||||
// 重新生成配置
|
|
||||||
if let Err(err) = Config::generate().await {
|
|
||||||
log::error!(target: "app", "Failed to regenerate config: {err}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 应用新配置
|
|
||||||
match CoreManager::global().update_config().await {
|
|
||||||
Ok(_) => {
|
|
||||||
log::info!(target: "app", "Config regenerated successfully");
|
|
||||||
handle::Handle::refresh_clash();
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
log::error!(target: "app", "Failed to apply regenerated config: {err}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 检查DNS配置文件是否存在
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn check_dns_config_exists() -> CmdResult<bool> {
|
|
||||||
use crate::utils::dirs;
|
|
||||||
|
|
||||||
let dns_path = dirs::app_home_dir()
|
|
||||||
.map_err(|e| e.to_string())?
|
|
||||||
.join("dns_config.yaml");
|
|
||||||
|
|
||||||
Ok(dns_path.exists())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 获取DNS配置文件内容
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn get_dns_config_content() -> CmdResult<String> {
|
|
||||||
use crate::utils::dirs;
|
|
||||||
use std::fs;
|
|
||||||
|
|
||||||
let dns_path = dirs::app_home_dir()
|
|
||||||
.map_err(|e| e.to_string())?
|
|
||||||
.join("dns_config.yaml");
|
|
||||||
|
|
||||||
if !dns_path.exists() {
|
|
||||||
return Err("DNS config file not found".into());
|
|
||||||
}
|
|
||||||
|
|
||||||
let content = fs::read_to_string(&dns_path).map_err(|e| e.to_string())?;
|
|
||||||
Ok(content)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 验证DNS配置文件
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn validate_dns_config() -> CmdResult<(bool, String)> {
|
|
||||||
use crate::{core::CoreManager, utils::dirs};
|
|
||||||
|
|
||||||
let app_dir = dirs::app_home_dir().map_err(|e| e.to_string())?;
|
|
||||||
let dns_path = app_dir.join("dns_config.yaml");
|
|
||||||
let dns_path_str = dns_path.to_str().unwrap_or_default();
|
|
||||||
|
|
||||||
if !dns_path.exists() {
|
|
||||||
return Ok((false, "DNS config file not found".to_string()));
|
|
||||||
}
|
|
||||||
|
|
||||||
match CoreManager::global()
|
|
||||||
.validate_config_file(dns_path_str, None)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(result) => Ok(result),
|
|
||||||
Err(e) => Err(e.to_string()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
use crate::module::lightweight;
|
|
||||||
|
|
||||||
use super::CmdResult;
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn entry_lightweight_mode() -> CmdResult {
|
|
||||||
lightweight::entry_lightweight_mode();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn exit_lightweight_mode() -> CmdResult {
|
|
||||||
lightweight::exit_lightweight_mode();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
use anyhow::Result;
|
|
||||||
|
|
||||||
// Common result type used by command functions
|
|
||||||
pub type CmdResult<T = ()> = Result<T, String>;
|
|
||||||
|
|
||||||
// Command modules
|
|
||||||
pub mod app;
|
|
||||||
pub mod clash;
|
|
||||||
pub mod lightweight;
|
|
||||||
pub mod media_unlock_checker;
|
|
||||||
pub mod network;
|
|
||||||
pub mod profile;
|
|
||||||
pub mod proxy;
|
|
||||||
pub mod runtime;
|
|
||||||
pub mod save_profile;
|
|
||||||
pub mod service;
|
|
||||||
pub mod system;
|
|
||||||
pub mod uwp;
|
|
||||||
pub mod validate;
|
|
||||||
pub mod verge;
|
|
||||||
pub mod webdav;
|
|
||||||
|
|
||||||
// Re-export all command functions for backwards compatibility
|
|
||||||
pub use app::*;
|
|
||||||
pub use clash::*;
|
|
||||||
pub use lightweight::*;
|
|
||||||
pub use media_unlock_checker::*;
|
|
||||||
pub use network::*;
|
|
||||||
pub use profile::*;
|
|
||||||
pub use proxy::*;
|
|
||||||
pub use runtime::*;
|
|
||||||
pub use save_profile::*;
|
|
||||||
pub use service::*;
|
|
||||||
pub use system::*;
|
|
||||||
pub use uwp::*;
|
|
||||||
pub use validate::*;
|
|
||||||
pub use verge::*;
|
|
||||||
pub use webdav::*;
|
|
||||||