Compare commits
890 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d6b207833 | ||
|
|
3371a42822 | ||
|
|
fe712318b8 | ||
|
|
593d8327b2 | ||
|
|
d5c54b770f | ||
|
|
32a9a21be1 | ||
|
|
e0735f8928 | ||
|
|
c6dc962134 | ||
|
|
e068103e4d | ||
|
|
6eb5ade9ea | ||
|
|
c40168cacd | ||
|
|
a546b75986 | ||
|
|
8686ecfa54 | ||
|
|
270c48a1dd | ||
|
|
fdbec2cbac | ||
|
|
46049fd15c | ||
|
|
a81fe6ff7f | ||
|
|
fd4e8ecb01 | ||
|
|
8142e5e79e | ||
|
|
0c71772953 | ||
|
|
d54bc21441 | ||
|
|
be4bca2c15 | ||
|
|
2bd54673de | ||
|
|
4a3359f773 | ||
|
|
c35095f90e | ||
|
|
32abccd8c2 | ||
|
|
5d68ca3e18 | ||
|
|
8efa5335b0 | ||
|
|
4710bb16d8 | ||
|
|
db4f3e4e1b | ||
|
|
e18272a6d7 | ||
|
|
85aed9ce9d | ||
|
|
d03f93166f | ||
|
|
a3b1a433c6 | ||
|
|
608f63bc9c | ||
|
|
a4c118648a | ||
|
|
42866b8e4f | ||
|
|
0b7455b74f | ||
|
|
eab7bc3f5f | ||
|
|
af2623d16c | ||
|
|
e683034e77 | ||
|
|
ffa979ddc8 | ||
|
|
8a8c8a5699 | ||
|
|
2aea956fd0 | ||
|
|
1803517943 | ||
|
|
49c8081f68 | ||
|
|
3d64ca37e7 | ||
|
|
ccc88745a6 | ||
|
|
0bf6dbd402 | ||
|
|
b9abb4ce47 | ||
|
|
ad0c0f37c9 | ||
|
|
4c6257c145 | ||
|
|
6c5231dbff | ||
|
|
0454bb9b3c | ||
|
|
021f89da29 | ||
|
|
2ccca633ed | ||
|
|
fe15e025aa | ||
|
|
9e0c416db5 | ||
|
|
fa9b84a9c9 | ||
|
|
b3b1bd7bc8 | ||
|
|
91e806a619 | ||
|
|
6df6eefd3d | ||
|
|
ae35d05649 | ||
|
|
72939db2df | ||
|
|
b6f5770dc2 | ||
|
|
c1e7faa7bf | ||
|
|
37a18eae9c | ||
|
|
010bc5e328 | ||
|
|
a166051781 | ||
|
|
c2341d6697 | ||
|
|
03bba4259e | ||
|
|
80844580df | ||
|
|
a8790b9835 | ||
|
|
36262ff166 | ||
|
|
98d67be9d9 | ||
|
|
131f077c3f | ||
|
|
2c428ef099 | ||
|
|
08887cd6ed | ||
|
|
f786a29b70 | ||
|
|
d3f1d7f378 | ||
|
|
c48a31fd63 | ||
|
|
1217f06324 | ||
|
|
4cc3197be8 | ||
|
|
eb940d5968 | ||
|
|
6381389cac | ||
|
|
ab939e859a | ||
|
|
9bdc71c487 | ||
|
|
56a4abfaff | ||
|
|
769bc7f109 | ||
|
|
a587847e41 | ||
|
|
bda4650de8 | ||
|
|
4f0af93b72 | ||
|
|
4a656268b8 | ||
|
|
2ad9d5990f | ||
|
|
32585bc453 | ||
|
|
66307d4545 | ||
|
|
8b9ae2734f | ||
|
|
96f9e12d93 | ||
|
|
43c4e13c11 | ||
|
|
27f6168a29 | ||
|
|
70dbbc93f4 | ||
|
|
92c9808bfb | ||
|
|
1f8df84b87 | ||
|
|
271c1bcd51 | ||
|
|
f830b1199a | ||
|
|
b80d48aa91 | ||
|
|
691d835d16 | ||
|
|
3ac6d0ff5f | ||
|
|
68b32a20a4 | ||
|
|
88e4df4388 | ||
|
|
3e13980870 | ||
|
|
dd23af7051 | ||
|
|
7d5fc6de12 | ||
|
|
28233fbe58 | ||
|
|
32a35c6706 | ||
|
|
228ddace91 | ||
|
|
f9ffdbbce7 | ||
|
|
9b233683a2 | ||
|
|
ff78fb6b30 | ||
|
|
8efda6478c | ||
|
|
851c7871e3 | ||
|
|
a78c78f3e5 | ||
|
|
05e8442ff1 | ||
|
|
977b842df3 | ||
|
|
5bde54aac1 | ||
|
|
0f27e3ea42 | ||
|
|
d170725f0c | ||
|
|
a26fcf0cd8 | ||
|
|
18a4455511 | ||
|
|
2ab3286d0e | ||
|
|
d4a411ab4a | ||
|
|
c7facb38b1 | ||
|
|
b7434e9eaf | ||
|
|
4a174c0084 | ||
|
|
db8ad1e8eb | ||
|
|
1feaac003a | ||
|
|
c42b2fb34c | ||
|
|
5d48fa93ba | ||
|
|
527ac04c4e | ||
|
|
9644163dc5 | ||
|
|
d0090abd01 | ||
|
|
918d2ad156 | ||
|
|
b028fb955f | ||
|
|
ba33d5a39b | ||
|
|
fd0b9c55fc | ||
|
|
b28fb5c9b4 | ||
|
|
77ecd4be9b | ||
|
|
6f74003e14 | ||
|
|
63b2c2fb2f | ||
|
|
08da7a37e6 | ||
|
|
6b87a8d91b | ||
|
|
0f1364a8d7 | ||
|
|
9dbf70780d | ||
|
|
58e5592c2b | ||
|
|
02cc842cc8 | ||
|
|
e962e866b3 | ||
|
|
af3b30096d | ||
|
|
aa7ab86b62 | ||
|
|
7f864a9e35 | ||
|
|
609d345443 | ||
|
|
426815fa50 | ||
|
|
5d1b1e48d7 | ||
|
|
28d0412adc | ||
|
|
9d070b3671 | ||
|
|
cd423752d1 | ||
|
|
1f8a0eaf67 | ||
|
|
42d9fcd8b0 | ||
|
|
4e1510c840 | ||
|
|
7ebfd43f65 | ||
|
|
41d6157116 | ||
|
|
f9f8297fd6 | ||
|
|
dfbe3f665a | ||
|
|
b36df472e5 | ||
|
|
0b147f708d | ||
|
|
4e3bdbcc74 | ||
|
|
0345419ef3 | ||
|
|
9237dbbc18 | ||
|
|
68ac1b7641 | ||
|
|
2cfe4d29ba | ||
|
|
b436497555 | ||
|
|
7ac638c52c | ||
|
|
f21d2bc7c7 | ||
|
|
550917bd16 | ||
|
|
c1c0311586 | ||
|
|
489bbb6902 | ||
|
|
86af25bde3 | ||
|
|
a599e0716f | ||
|
|
30fc818771 | ||
|
|
df08f677bd | ||
|
|
7247bcad1b | ||
|
|
c0bcac25ea | ||
|
|
ae06019bdb | ||
|
|
432861780a | ||
|
|
111ee88833 | ||
|
|
487ee7015e | ||
|
|
061cc16c27 | ||
|
|
af8d9dff2d | ||
|
|
cb16bd0324 | ||
|
|
acf8171617 | ||
|
|
da7429f03e | ||
|
|
4a121db39d | ||
|
|
0e8e287fe2 | ||
|
|
cf942121dd | ||
|
|
77c2e962ec | ||
|
|
05f5cc4fe8 | ||
|
|
684f09feaf | ||
|
|
38bea3ced1 | ||
|
|
6a6f9a53bd | ||
|
|
584c12e60f | ||
|
|
bb5b667613 | ||
|
|
0628d3533f | ||
|
|
e1bd4c9a0a | ||
|
|
85c9ec38db | ||
|
|
6ff7cfde11 | ||
|
|
c52034f992 | ||
|
|
b982dd90e4 | ||
|
|
80e36688e8 | ||
|
|
c6c1071d2d | ||
|
|
481817c607 | ||
|
|
2e5739f042 | ||
|
|
0bb9f5ece5 | ||
|
|
d454f51993 | ||
|
|
7f3ab31ad5 | ||
|
|
98fe433819 | ||
|
|
4b01326420 | ||
|
|
3a4acd2693 | ||
|
|
b8e9937083 | ||
|
|
72d44ec783 | ||
|
|
680b60cb07 | ||
|
|
45527b320d | ||
|
|
0acc9a553e | ||
|
|
19f81cf379 | ||
|
|
96ddbdf0f0 | ||
|
|
9eb87911a6 | ||
|
|
b0881726fa | ||
|
|
308248d8ec | ||
|
|
de5ea4f0aa | ||
|
|
305ce6ff11 | ||
|
|
bd4dbb55e4 | ||
|
|
1fefb2bcaf | ||
|
|
e094e80ecf | ||
|
|
9715db1229 | ||
|
|
3c0daa2bf1 | ||
|
|
435fec2f1c | ||
|
|
69ba619f24 | ||
|
|
b7bb21f091 | ||
|
|
77f51a3e9f | ||
|
|
7799e511e8 | ||
|
|
416f4a4dee | ||
|
|
2fd5158839 | ||
|
|
b8287acff3 | ||
|
|
53b470ed09 | ||
|
|
8a20b773fb | ||
|
|
aa576fe7db | ||
|
|
582321c1ae | ||
|
|
541f5041fb | ||
|
|
d16babefbe | ||
|
|
4ac6768b7a | ||
|
|
97d3d3c616 | ||
|
|
2ee7572634 | ||
|
|
8e7fd1ecef | ||
|
|
6b4e6533f5 | ||
|
|
b680a89033 | ||
|
|
ee6a6f4b94 | ||
|
|
6933baafca | ||
|
|
0f3a6782b8 | ||
|
|
f99cc021f8 | ||
|
|
e4de4b8c1b | ||
|
|
793b5a679c | ||
|
|
1b75cf822d | ||
|
|
60604020c7 | ||
|
|
09780d02e3 | ||
|
|
4760f79ab5 | ||
|
|
05363a0d22 | ||
|
|
49797f891c | ||
|
|
9d38fe6764 | ||
|
|
f340b18408 | ||
|
|
358c449b17 | ||
|
|
1f6a6bbb39 | ||
|
|
10028cf500 | ||
|
|
a977458881 | ||
|
|
dc811d8b84 | ||
|
|
5bc119bd9d | ||
|
|
9016796497 | ||
|
|
32f47aaa34 | ||
|
|
c54b38a068 | ||
|
|
a9a708d0f6 | ||
|
|
ab3f118588 | ||
|
|
87852acb14 | ||
|
|
65ab26365d | ||
|
|
e7630e98d9 | ||
|
|
9779c1ebee | ||
|
|
9cef7e3370 | ||
|
|
b6bc545e7d | ||
|
|
85326be7bb | ||
|
|
75750ad38d | ||
|
|
0522114c5d | ||
|
|
6300236cdb | ||
|
|
1dbb950b3c | ||
|
|
bfd2ecd26c | ||
|
|
e60c2f5f19 | ||
|
|
274f71615f | ||
|
|
cd7d5ed665 | ||
|
|
703327ed41 | ||
|
|
a7ce24c84b | ||
|
|
c3c42e33ee | ||
|
|
530ace6b81 | ||
|
|
5345b001e8 | ||
|
|
07c9e2f675 | ||
|
|
7a08cb5ddd | ||
|
|
9c0ae12959 | ||
|
|
1e03791e82 | ||
|
|
d92e34949c | ||
|
|
c8423c0b4f | ||
|
|
2c1b4acfcc | ||
|
|
b14883c9af | ||
|
|
53245e9e4f | ||
|
|
45fc8c77b6 | ||
|
|
9d8fe4be06 | ||
|
|
03781ea692 | ||
|
|
3c28c4861b | ||
|
|
0c986ee68c | ||
|
|
17d45d7406 | ||
|
|
07ed408129 | ||
|
|
c001803d71 | ||
|
|
4ce54ea395 | ||
|
|
2039431735 | ||
|
|
15c9207542 | ||
|
|
79d8d79b9d | ||
|
|
806925333f | ||
|
|
2e196656ba | ||
|
|
55204df130 | ||
|
|
627c50910c | ||
|
|
959e11b77c | ||
|
|
6cc9da338b | ||
|
|
1cd93344dd | ||
|
|
7893814da4 | ||
|
|
da2d3237b6 | ||
|
|
431b04a011 | ||
|
|
f13c6f0153 | ||
|
|
160693f608 | ||
|
|
b127a1e98c | ||
|
|
b0a9cd70ac | ||
|
|
5955831809 | ||
|
|
b13f10d624 | ||
|
|
47635c95e1 | ||
|
|
c238d49584 | ||
|
|
2ff6455231 | ||
|
|
110db561a9 | ||
|
|
61013e9d2d | ||
|
|
2de6d1c5f1 | ||
|
|
991e453881 | ||
|
|
edcf501a22 | ||
|
|
1fc5cf0aa5 | ||
|
|
ce072ae9d3 | ||
|
|
a811b1da1a | ||
|
|
1de087eac7 | ||
|
|
2337a3e8a3 | ||
|
|
1637ae4d17 | ||
|
|
f46a08fe89 | ||
|
|
2c0d2c4497 | ||
|
|
f75eeb07be | ||
|
|
965a1d03ba | ||
|
|
12f947ed2e | ||
|
|
97d684fde1 | ||
|
|
75c1069251 | ||
|
|
050b641d79 | ||
|
|
e9539b5c5c | ||
|
|
6fc5a47970 | ||
|
|
11317154f6 | ||
|
|
98b4abfa19 | ||
|
|
f40f019d2e | ||
|
|
42109ce000 | ||
|
|
a38df1280b | ||
|
|
e19002caca | ||
|
|
b67d99e5a5 | ||
|
|
15942a7b96 | ||
|
|
cac2d0e050 | ||
|
|
7d504f9231 | ||
|
|
c0f78b023f | ||
|
|
3803ab045c | ||
|
|
bee2790af3 | ||
|
|
182a3076fc | ||
|
|
a9bcb71afe | ||
|
|
4f5baa1ac8 | ||
|
|
323743e426 | ||
|
|
3ba51fd6fe | ||
|
|
ff98e06afa | ||
|
|
6f22c73d99 | ||
|
|
87bd27f814 | ||
|
|
3e7db5617b | ||
|
|
1712e466d5 | ||
|
|
abf49529d6 | ||
|
|
3e31a78af1 | ||
|
|
41fc46c8b5 | ||
|
|
db8cfec7ad | ||
|
|
66376daad4 | ||
|
|
182f08d221 | ||
|
|
887cf39321 | ||
|
|
e2f6ec308c | ||
|
|
b1f2a27eac | ||
|
|
0c6cedf879 | ||
|
|
1ff6a00653 | ||
|
|
016821a8ce | ||
|
|
a786ae24e9 | ||
|
|
799b768367 | ||
|
|
24610f9c0a | ||
|
|
172307d53b | ||
|
|
d7816729d0 | ||
|
|
ac7daa70f7 | ||
|
|
0372f0647b | ||
|
|
60f98ac438 | ||
|
|
6d76814aed | ||
|
|
2cf5bb689f | ||
|
|
e18c295ca6 | ||
|
|
58346d6fc9 | ||
|
|
5364b7a09b | ||
|
|
52630aa735 | ||
|
|
89255a8c84 | ||
|
|
6d5cc38235 | ||
|
|
c4234ddcff | ||
|
|
7a9872d42f | ||
|
|
f5165d517c | ||
|
|
0b125e29b5 | ||
|
|
aabd6d8985 | ||
|
|
94dccae48a | ||
|
|
74ef112d57 | ||
|
|
0da63c6ef0 | ||
|
|
3c145c7dd7 | ||
|
|
63590119bb | ||
|
|
7845d65119 | ||
|
|
2454738224 | ||
|
|
3685cb8868 | ||
|
|
fcffcb5b59 | ||
|
|
19049fb890 | ||
|
|
50950cc9d2 | ||
|
|
b1f9e525ab | ||
|
|
fc03cd77fc | ||
|
|
9a3434b02e | ||
|
|
eab5e51f66 | ||
|
|
ff6b7cbec2 | ||
|
|
abe62d84ed | ||
|
|
1aa9627e4a | ||
|
|
8bbe549b0c | ||
|
|
baf69e397a | ||
|
|
3ca8f09971 | ||
|
|
3381ad0e0e | ||
|
|
150342f699 | ||
|
|
44830752f7 | ||
|
|
5e7ef691ae | ||
|
|
ed858bafdc | ||
|
|
2fff8652ca | ||
|
|
358142c1cc | ||
|
|
903ca18b75 | ||
|
|
6a91d3eec2 | ||
|
|
0d5e880fb2 | ||
|
|
03f322f92a | ||
|
|
5cf2acfff2 | ||
|
|
7d17423e4b | ||
|
|
5d877d81e3 | ||
|
|
a968410431 | ||
|
|
c6f4bfa875 | ||
|
|
71b84fb10d | ||
|
|
0d76c9ccb4 | ||
|
|
70815e276e | ||
|
|
72fe8f3af1 | ||
|
|
53bc50d05c | ||
|
|
99eb2856f7 | ||
|
|
616135ac14 | ||
|
|
5ca490d233 | ||
|
|
1c159f59bb | ||
|
|
4ad9c81381 | ||
|
|
d11eaec7d5 | ||
|
|
a02748d518 | ||
|
|
0ab2940347 | ||
|
|
fc2585eb95 | ||
|
|
c2789312ba | ||
|
|
e1646a3127 | ||
|
|
0fc1de9f29 | ||
|
|
7c5969e580 | ||
|
|
e719999d8a | ||
|
|
59ea4e4b44 | ||
|
|
df52e8ede9 | ||
|
|
028bf5919d | ||
|
|
31e16a7ed7 | ||
|
|
aa6696dfcc | ||
|
|
838355a5e9 | ||
|
|
f87962f1a0 | ||
|
|
8e4158d11d | ||
|
|
60f8f10bb5 | ||
|
|
de5e1d7274 | ||
|
|
cfe78fc387 | ||
|
|
2a8bfac2c5 | ||
|
|
3c5c684641 | ||
|
|
c757ac8517 | ||
|
|
2597ab4ea1 | ||
|
|
783799b2a4 | ||
|
|
87aec33833 | ||
|
|
06087cd853 | ||
|
|
afaef43017 | ||
|
|
e7f3f27104 | ||
|
|
6c0e11eebc | ||
|
|
809752e4ec | ||
|
|
54f6255fe4 | ||
|
|
d97a27307c | ||
|
|
6423066cb2 | ||
|
|
e8d8feb042 | ||
|
|
816caa6415 | ||
|
|
a11d123815 | ||
|
|
c24d1d1e41 | ||
|
|
1b2daef90c | ||
|
|
6284fd8024 | ||
|
|
763874ac55 | ||
|
|
4defaa103e | ||
|
|
181ac937d2 | ||
|
|
f6884524e2 | ||
|
|
23f118fb1a | ||
|
|
a3b8f31b1e | ||
|
|
c6fb2232d0 | ||
|
|
ef411ddb47 | ||
|
|
7aed2828bb | ||
|
|
560445a518 | ||
|
|
3549ed2da0 | ||
|
|
ec9f86c450 | ||
|
|
c6e829be4f | ||
|
|
5ef84916bb | ||
|
|
94403be9a8 | ||
|
|
6403b8ce38 | ||
|
|
3f34fa26bf | ||
|
|
b1a6c6b59c | ||
|
|
76981a59d4 | ||
|
|
d93fbd699d | ||
|
|
fd2dca0769 | ||
|
|
5097102ca1 | ||
|
|
fa3fd8d8a4 | ||
|
|
5582e78315 | ||
|
|
b7fd32067f | ||
|
|
2a2fdc57bd | ||
|
|
025739e35c | ||
|
|
c8f6153831 | ||
|
|
3c02e3dddc | ||
|
|
40997c34ff | ||
|
|
677c3f16e4 | ||
|
|
0adb4f5ae5 | ||
|
|
cbbcf914ad | ||
|
|
d68a29a5a2 | ||
|
|
368eeed0d0 | ||
|
|
a522b78496 | ||
|
|
dab81116e9 | ||
|
|
b7f355bd1a | ||
|
|
dbeaebaee3 | ||
|
|
fe94a1eac9 | ||
|
|
bd5107bbaf | ||
|
|
8018d9b418 | ||
|
|
0454d300ec | ||
|
|
1e5c9ebc91 | ||
|
|
5c7e9728e6 | ||
|
|
da4be33a04 | ||
|
|
47e2a5a460 | ||
|
|
04337ef4b8 | ||
|
|
df58c8eb80 | ||
|
|
b0bf1bf4be | ||
|
|
1a3d84d4c4 | ||
|
|
735f629ca1 | ||
|
|
9dc927b50b | ||
|
|
47a336eb64 | ||
|
|
33b66aaea0 | ||
|
|
7b9eefdf2d | ||
|
|
ea5e8b56dd | ||
|
|
e52fff4d0e | ||
|
|
8d108509c9 | ||
|
|
d3cc630501 | ||
|
|
e74f297f9e | ||
|
|
8be9c75734 | ||
|
|
851851a7e6 | ||
|
|
1cbe46dc3b | ||
|
|
675a943d59 | ||
|
|
908815def3 | ||
|
|
200ca1eeda | ||
|
|
b81cc139b3 | ||
|
|
f8ae906326 | ||
|
|
e6f55804f4 | ||
|
|
1432a19d7d | ||
|
|
74fbfb130c | ||
|
|
3cf45f602f | ||
|
|
7a9dcc71fd | ||
|
|
fb5249a979 | ||
|
|
3f694b75f8 | ||
|
|
0e1ee66dd6 | ||
|
|
920e002247 | ||
|
|
ab0b352d36 | ||
|
|
aa4b08a156 | ||
|
|
66514908d2 | ||
|
|
60f0801a7c | ||
|
|
7149d0d43f | ||
|
|
d970687ebe | ||
|
|
d0425fc0d6 | ||
|
|
bdd5b46708 | ||
|
|
6d949d7e4d | ||
|
|
5d72d092fc | ||
|
|
667fc8c8a6 | ||
|
|
f7a2d9fd06 | ||
|
|
85946efd0b | ||
|
|
f6a853bfe9 | ||
|
|
4bfbdeb9a5 | ||
|
|
1e53508d67 | ||
|
|
b8fca59cbb | ||
|
|
9ada6fe4a7 | ||
|
|
b1593a2053 | ||
|
|
22a5125a11 | ||
|
|
dfd9a0019b | ||
|
|
e1d81c199b | ||
|
|
e8f574ee9c | ||
|
|
472af1bca6 | ||
|
|
671346bcdd | ||
|
|
9132abb3fe | ||
|
|
1c681e9f82 | ||
|
|
19286ef99d | ||
|
|
37ad2f522a | ||
|
|
1e1aa65fc0 | ||
|
|
ec6e067938 | ||
|
|
ea515fdd85 | ||
|
|
c11c202248 | ||
|
|
1cfee31483 | ||
|
|
00a5aa01c7 | ||
|
|
fc61cf16ed | ||
|
|
0684e29098 | ||
|
|
66d29293cd | ||
|
|
e9fd657852 | ||
|
|
bd7f51358c | ||
|
|
371b8fad05 | ||
|
|
fe259747dc | ||
|
|
d4d94ddbee | ||
|
|
f62d773246 | ||
|
|
20294233e6 | ||
|
|
cb4ab411f9 | ||
|
|
7f008d1f9c | ||
|
|
fe0487c3f9 | ||
|
|
a54e810af1 | ||
|
|
5cc1f20fac | ||
|
|
da804e1f69 | ||
|
|
3399333360 | ||
|
|
e75ab3a7d7 | ||
|
|
3b70acc3ca | ||
|
|
b42092884e | ||
|
|
fea2db0e29 | ||
|
|
fe7bc924da | ||
|
|
60b357e6f9 | ||
|
|
5544a469c4 | ||
|
|
067ca91c4d | ||
|
|
afd8d692fd | ||
|
|
a9a8fa2857 | ||
|
|
4b3a624ed9 | ||
|
|
549ea19c26 | ||
|
|
c0515c9c4f | ||
|
|
e81d594d01 | ||
|
|
3d469a4986 | ||
|
|
b91bd7ede0 | ||
|
|
6048af99bc | ||
|
|
ef9427122e | ||
|
|
02402f5207 | ||
|
|
80197ee18c | ||
|
|
8989b05a69 | ||
|
|
f809782559 | ||
|
|
9522e975a0 | ||
|
|
8854fb69d8 | ||
|
|
10bd75ea7b | ||
|
|
f33ffb55a7 | ||
|
|
3bff44da0c | ||
|
|
cf960e3695 | ||
|
|
c8eac2690f | ||
|
|
8af458e61a | ||
|
|
07899327f1 | ||
|
|
dd5bffe071 | ||
|
|
83000b75ca | ||
|
|
e6c3815493 | ||
|
|
32626ef773 | ||
|
|
ab1d18debe | ||
|
|
62330571a3 | ||
|
|
a8827c361c | ||
|
|
4635481c77 | ||
|
|
c6f9e421c1 | ||
|
|
448e1cd0c3 | ||
|
|
5ee7c5a319 | ||
|
|
89625188f1 | ||
|
|
fdd19068a8 | ||
|
|
ef7033cac0 | ||
|
|
65840e45cd | ||
|
|
6075f413dc | ||
|
|
ba3b2f613a | ||
|
|
165832e703 | ||
|
|
7e27ec488b | ||
|
|
4e3356ccb2 | ||
|
|
6b69cdf12f | ||
|
|
c24b29a42c | ||
|
|
c013d19530 | ||
|
|
5a1e1864d9 | ||
|
|
7c56b2fce2 | ||
|
|
7266352ca0 | ||
|
|
c1cff1e3c2 | ||
|
|
c003efe1e9 | ||
|
|
68d847aca5 | ||
|
|
82bea640c4 | ||
|
|
4fa88dd7a0 | ||
|
|
900bdd3afe | ||
|
|
8dff457422 | ||
|
|
850a429243 | ||
|
|
d3c8f16aed | ||
|
|
a43e127dd0 | ||
|
|
84e52f5525 | ||
|
|
1dce2c1f7a | ||
|
|
1c802ad5f5 | ||
|
|
db38db9256 | ||
|
|
cb9fa62dac | ||
|
|
9cc36e2a6a | ||
|
|
bf310adc12 | ||
|
|
7273b6ad67 | ||
|
|
a02f9e1151 | ||
|
|
6ef8015179 | ||
|
|
db38b27e52 | ||
|
|
cccb5b191d | ||
|
|
3c589743b1 | ||
|
|
65270e02da | ||
|
|
27c1bf8eb6 | ||
|
|
1db54195f5 | ||
|
|
399208429d | ||
|
|
b40e57f191 | ||
|
|
be350e49f0 | ||
|
|
bae732016c | ||
|
|
e50a67f0e4 | ||
|
|
26e8e0a1b1 | ||
|
|
c8210e0516 | ||
|
|
95590dd07f | ||
|
|
7e94e96bcc | ||
|
|
5009494e89 | ||
|
|
e58c2f86aa | ||
|
|
fcea542def | ||
|
|
44407585fa | ||
|
|
3d93d88bf0 | ||
|
|
8a49e32d2a | ||
|
|
8bbc4a3c4a | ||
|
|
3a9dbbb577 | ||
|
|
5f11fa65b4 | ||
|
|
6f4129d317 | ||
|
|
e2a1d7b99d | ||
|
|
18b6f73008 | ||
|
|
c16de232ad | ||
|
|
6ff1d683a5 | ||
|
|
a7c2857808 | ||
|
|
4cea16c326 | ||
|
|
a8228159b7 | ||
|
|
4594f2fd1f | ||
|
|
9c7661d1ae | ||
|
|
dd2416b5ae | ||
|
|
54ddb7473b | ||
|
|
cc7ad7c71f | ||
|
|
bfc07b2a97 | ||
|
|
2aad2c6b8a | ||
|
|
959df65e0a | ||
|
|
76d32c1cb4 | ||
|
|
da59164664 | ||
|
|
01c3a7d687 | ||
|
|
9a57118300 | ||
|
|
8ecd6e6f54 | ||
|
|
b9ac754c07 | ||
|
|
3bd48e547d | ||
|
|
92c77332a0 | ||
|
|
5c7652afe8 | ||
|
|
c2dd35790f | ||
|
|
5dae561b70 | ||
|
|
b3600bef34 | ||
|
|
c6087f577d | ||
|
|
c695c00e76 | ||
|
|
0d10d1f95b | ||
|
|
f80d03ed15 | ||
|
|
f2b023193c | ||
|
|
e467b92bb9 | ||
|
|
ae467cd515 | ||
|
|
9e51a55d45 | ||
|
|
67a3ab164a | ||
|
|
77ea6d3748 | ||
|
|
5e9b3a16fa | ||
|
|
bdeab55d3c | ||
|
|
bb10474cbb | ||
|
|
d7a8e3dc51 | ||
|
|
2d5e336f0f | ||
|
|
2aa4ff8422 | ||
|
|
8f7523dd95 | ||
|
|
f5cdd99fe6 | ||
|
|
2459b4c64c | ||
|
|
54ea4c03d6 | ||
|
|
59061a0672 | ||
|
|
03b73e89b3 | ||
|
|
3bc6fc97a2 | ||
|
|
82176a831d | ||
|
|
9920e5ef99 | ||
|
|
f3852b20ca | ||
|
|
b20886f08a | ||
|
|
ec2b802912 | ||
|
|
3b5832eceb | ||
|
|
589e373bd8 | ||
|
|
a6fd41900f | ||
|
|
7daa626d55 | ||
|
|
72da89235a | ||
|
|
8a14fe7985 | ||
|
|
1e1c0515d1 | ||
|
|
95a398da23 | ||
|
|
ff8a8d860f | ||
|
|
928cf264b0 | ||
|
|
7139682bc7 | ||
|
|
b5ad039980 | ||
|
|
ab37817d26 | ||
|
|
e79f8b357c | ||
|
|
bdb9f9b949 | ||
|
|
07708c7a56 | ||
|
|
05e9c07aa1 | ||
|
|
3486cfaab7 | ||
|
|
313eba409c | ||
|
|
88cae5d8e9 | ||
|
|
52c4a77934 | ||
|
|
e526c244f3 | ||
|
|
54b5517222 | ||
|
|
70a691bc68 | ||
|
|
55d22e424d | ||
|
|
69ea40abc0 | ||
|
|
953fc94cb0 | ||
|
|
4b22518532 | ||
|
|
b60c438694 | ||
|
|
d1d9d65a06 | ||
|
|
b1ee4d10d7 | ||
|
|
908ef635fa | ||
|
|
6b2cf5df2f | ||
|
|
1105a9f31c | ||
|
|
689724db6c | ||
|
|
3530a95738 | ||
|
|
c9d8bbe874 | ||
|
|
8d87990793 | ||
|
|
5c4590d507 | ||
|
|
11d3754c08 | ||
|
|
209bf9e0aa | ||
|
|
9eaf072e8f | ||
|
|
065bbef781 | ||
|
|
beb5589a4a | ||
|
|
d88d5e7818 | ||
|
|
12336148d9 | ||
|
|
9bec54c454 | ||
|
|
303d712860 | ||
|
|
9e6bfaada4 | ||
|
|
3f8c47100d | ||
|
|
716120ea61 | ||
|
|
2003c5a0c9 | ||
|
|
07898cdfd6 | ||
|
|
72418194e9 | ||
|
|
358b93fb70 | ||
|
|
3e9a111643 | ||
|
|
8841951fe3 | ||
|
|
e45cee6596 | ||
|
|
66b965d9f7 | ||
|
|
f4285ae106 | ||
|
|
657e65bc6a | ||
|
|
41fc8d2e2e | ||
|
|
25ca781d76 | ||
|
|
41f4130e5d | ||
|
|
8e19f3fc0b | ||
|
|
c4b8ac8b0b | ||
|
|
0ac2df1297 | ||
|
|
251450fd50 | ||
|
|
85c5595f43 | ||
|
|
ca3188c930 | ||
|
|
2f47f82b0f | ||
|
|
0e09598b10 | ||
|
|
a705420528 | ||
|
|
4089887514 | ||
|
|
a3d02e5f39 | ||
|
|
6e09363832 | ||
|
|
1c58a64847 | ||
|
|
2a716e4d5a | ||
|
|
a2c613d380 | ||
|
|
aa4b09436c | ||
|
|
9521bba4ba | ||
|
|
55d10021f8 | ||
|
|
7fe35748d0 | ||
|
|
ff9efbd4ea | ||
|
|
23b8c325f4 | ||
|
|
ecfccb4c40 | ||
|
|
2472574cde | ||
|
|
bf81c8facc | ||
|
|
9bf0d69ab6 | ||
|
|
cf9d98d434 | ||
|
|
da8e67d4e5 |
3
.babelrc
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"presets": [
|
||||
"@babel/preset-typescript",
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
@@ -20,6 +21,6 @@
|
||||
"@babel/plugin-syntax-dynamic-import",
|
||||
"@babel/plugin-transform-modules-umd",
|
||||
"@babel/plugin-transform-runtime",
|
||||
"@babel/plugin-proposal-class-properties"
|
||||
"@babel/plugin-transform-class-properties"
|
||||
]
|
||||
}
|
||||
|
||||
34
.eslintrc
@@ -1,34 +0,0 @@
|
||||
{
|
||||
"extends": [
|
||||
// "plugin:vue/vue3-recommended",
|
||||
"standard"
|
||||
],
|
||||
"plugins": [
|
||||
"html"
|
||||
],
|
||||
"parser": "@babel/eslint-parser",
|
||||
"parserOptions": {
|
||||
"requireConfigFile": false
|
||||
},
|
||||
"rules": {
|
||||
"no-new": "off",
|
||||
"camelcase": "off",
|
||||
"no-return-assign": "off",
|
||||
"space-before-function-paren": ["error", "never"],
|
||||
"no-var": "error",
|
||||
"no-fallthrough": "off",
|
||||
"prefer-promise-reject-errors": "off",
|
||||
"eqeqeq": "off",
|
||||
"no-multiple-empty-lines": [1, {"max": 2}],
|
||||
"comma-dangle": [2, "always-multiline"],
|
||||
"standard/no-callback-literal": "off",
|
||||
"prefer-const": "off",
|
||||
"no-labels": "off",
|
||||
"node/no-callback-literal": "off",
|
||||
"vue/multi-word-component-names": "off"
|
||||
},
|
||||
"settings": {
|
||||
"html/html-extensions": [".html", ".vue"]
|
||||
},
|
||||
"ignorePatterns": ["vendors", "*.min.js"]
|
||||
}
|
||||
98
.eslintrc.base.cjs
Normal file
@@ -0,0 +1,98 @@
|
||||
const baseRule = {
|
||||
'no-new': 'off',
|
||||
camelcase: 'off',
|
||||
'no-return-assign': 'off',
|
||||
'space-before-function-paren': ['error', 'never'],
|
||||
'no-var': 'error',
|
||||
'no-fallthrough': 'off',
|
||||
eqeqeq: 'off',
|
||||
'require-atomic-updates': ['error', { allowProperties: true }],
|
||||
'no-multiple-empty-lines': [1, { max: 2 }],
|
||||
'comma-dangle': [2, 'always-multiline'],
|
||||
'standard/no-callback-literal': 'off',
|
||||
'prefer-const': 'off',
|
||||
'no-labels': 'off',
|
||||
'node/no-callback-literal': 'off',
|
||||
'multiline-ternary': 'off',
|
||||
}
|
||||
const typescriptRule = {
|
||||
...baseRule,
|
||||
'@typescript-eslint/strict-boolean-expressions': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/space-before-function-paren': 'off',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
'@typescript-eslint/restrict-template-expressions': [1, {
|
||||
allowBoolean: true,
|
||||
allowAny: true,
|
||||
}],
|
||||
'@typescript-eslint/restrict-plus-operands': [1, {
|
||||
allowBoolean: true,
|
||||
allowAny: true,
|
||||
}],
|
||||
'@typescript-eslint/no-misused-promises': [
|
||||
'error',
|
||||
{
|
||||
checksVoidReturn: {
|
||||
arguments: false,
|
||||
attributes: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/naming-convention': 'off',
|
||||
'@typescript-eslint/return-await': 'off',
|
||||
'@typescript-eslint/ban-ts-comment': 'off',
|
||||
'@typescript-eslint/comma-dangle': 'off',
|
||||
'@typescript-eslint/no-unsafe-argument': 'off',
|
||||
}
|
||||
const vueRule = {
|
||||
...typescriptRule,
|
||||
'vue/multi-word-component-names': 'off',
|
||||
'vue/max-attributes-per-line': 'off',
|
||||
'vue/singleline-html-element-content-newline': 'off',
|
||||
'vue/use-v-on-exact': 'off',
|
||||
}
|
||||
|
||||
exports.base = {
|
||||
extends: ['standard'],
|
||||
rules: baseRule,
|
||||
parser: '@babel/eslint-parser',
|
||||
}
|
||||
|
||||
exports.html = {
|
||||
files: ['*.html'],
|
||||
plugins: ['html'],
|
||||
}
|
||||
|
||||
exports.typescript = {
|
||||
files: ['*.ts'],
|
||||
rules: typescriptRule,
|
||||
parser: '@typescript-eslint/parser',
|
||||
extends: [
|
||||
'standard-with-typescript',
|
||||
],
|
||||
}
|
||||
|
||||
exports.vue = {
|
||||
files: ['*.vue'],
|
||||
rules: vueRule,
|
||||
parser: 'vue-eslint-parser',
|
||||
extends: [
|
||||
// 'plugin:vue/vue3-essential',
|
||||
'plugin:vue/base',
|
||||
'plugin:vue/vue3-recommended',
|
||||
'plugin:vue-pug/vue3-recommended',
|
||||
// "plugin:vue/strongly-recommended"
|
||||
'standard-with-typescript',
|
||||
],
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
parser: {
|
||||
// Script parser for `<script>`
|
||||
js: '@typescript-eslint/parser',
|
||||
|
||||
// Script parser for `<script lang="ts">`
|
||||
ts: '@typescript-eslint/parser',
|
||||
},
|
||||
extraFileExtensions: ['.vue'],
|
||||
},
|
||||
}
|
||||
20
.eslintrc.cjs
Normal file
@@ -0,0 +1,20 @@
|
||||
const { base, typescript } = require('./.eslintrc.base.cjs')
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
...base,
|
||||
overrides: [
|
||||
{
|
||||
...typescript,
|
||||
parserOptions: {
|
||||
project: './tsconfig.json',
|
||||
},
|
||||
},
|
||||
],
|
||||
ignorePatterns: [
|
||||
'node_modules',
|
||||
'*.min.js',
|
||||
'dist',
|
||||
'build',
|
||||
],
|
||||
}
|
||||
55
.github/ISSUE_TEMPLATE/--bug.yml
vendored
@@ -1,55 +0,0 @@
|
||||
name: 🐞报告Bug
|
||||
description: 报告bug,请先查看常见问题及搜索issue列表中有无你要提的问题
|
||||
title: "[Bug]: "
|
||||
body:
|
||||
- type: checkboxes
|
||||
id: check-answer
|
||||
attributes:
|
||||
label: 解决方案检查
|
||||
description: 请确保你已完成以下所有操作
|
||||
options:
|
||||
- label: 我已阅读常见问题(<https://lyswhut.github.io/lx-music-doc/desktop/faq>),并没有找到解决方案
|
||||
required: true
|
||||
- label: 我已搜索issue列表(<https://github.com/lyswhut/lx-music-desktop/issues?utf8=✓&q=>),并没有发现类似的问题
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected-behavior
|
||||
attributes:
|
||||
label: 预期行为
|
||||
description: 对期望发生的事情的清晰简明描述
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: actual-behavior
|
||||
attributes:
|
||||
label: 实际行为
|
||||
description: 对实际发生的事情的清晰简明描述
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Lx Music 版本
|
||||
description: 你使用什么版本的LX Music?
|
||||
placeholder: 1.15.0
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: last-known-working-version
|
||||
attributes:
|
||||
label: 最后正常的版本
|
||||
description: 如果有,请在此处填写最后正常的版本是多少?
|
||||
placeholder: 1.15.0
|
||||
- type: input
|
||||
id: operating-system-version
|
||||
attributes:
|
||||
label: 操作系统版本
|
||||
description: 您使用的是什么操作系统版本?在 Windows 上,单击开始按钮 > 设置 > 系统 > 关于;在 macOS 上,单击 Apple 菜单 > 关于本机;在 Linux 上,使用 lsb_release 或 uname -a
|
||||
placeholder: "例如 Windows 10 版本 1909、macOS Catalina 10.15.7 或 Ubuntu 20.04"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: additional-information
|
||||
attributes:
|
||||
label: 附加信息
|
||||
description: 如果你的问题需要进一步解释,或者你所遇到的问题不容易重现,请在此处添加更多信息。(直接把图片、视频拖到编辑框即可添加图片或视频)
|
||||
59
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
name: 🐞 报告错误
|
||||
description: 报告一个错误(Bug),请先查看常见问题及搜索 Issue 列表中有无你要提的问题。
|
||||
title: "[Bug]: "
|
||||
body:
|
||||
- type: checkboxes
|
||||
id: check-answer
|
||||
attributes:
|
||||
label: 解决方案检查
|
||||
description: 请确保你已完成以下所有操作。
|
||||
options:
|
||||
- label: 我已阅读 [常见问题](https://lyswhut.github.io/lx-music-doc/desktop/faq),并没有找到解决方案。
|
||||
required: true
|
||||
- label: 我已搜索 [Issue 列表](https://github.com/lyswhut/lx-music-desktop/issues?q=is%3Aissue+),并没有发现类似的问题。
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected-behavior
|
||||
attributes:
|
||||
label: 预期行为
|
||||
description: 对期望发生的事情的清晰简明描述。
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: actual-behavior
|
||||
attributes:
|
||||
label: 实际行为
|
||||
description: 对实际发生的事情的清晰简明描述。
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: LX Music 版本
|
||||
description: 你使用什么版本的 LX Music?
|
||||
placeholder: 例如 2.9.0
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: last-known-working-version
|
||||
attributes:
|
||||
label: 最后正常的版本
|
||||
description: 如果有,请在此处填写最后正常的版本。
|
||||
placeholder: 例如 2.8.0
|
||||
- type: input
|
||||
id: operating-system-version
|
||||
attributes:
|
||||
label: 操作系统版本
|
||||
description: |
|
||||
你使用什么版本的操作系统?
|
||||
在 macOS 上,单击「Apple 菜单 > 关于本机」;
|
||||
在 Linux 上,执行 `lsb_release` 或 `uname -a` 命令;
|
||||
在 Windows 上,单击「开始按钮 > 设置 > 系统 > 关于」。
|
||||
placeholder: "例如 Windows 11 版本 24H2、macOS Sequoia 15.1.1 或 Ubuntu 24.10"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: additional-information
|
||||
attributes:
|
||||
label: 附加信息
|
||||
description: 如果你的问题需要进一步解释,或者你所遇到的问题不容易重现,请在此处添加更多信息。(直接把图片/视频拖到编辑框即可添加图片/视频)
|
||||
@@ -1,40 +1,38 @@
|
||||
name: ✨功能请求
|
||||
description: 为这个项目提出一个想法,请先查看常见问题及搜索issue列表中有无你要提的问题
|
||||
name: ✨ 功能请求
|
||||
description: 为这个项目提出一个想法,请先查看常见问题及搜索 Issue 列表中有无你要提的问题。
|
||||
title: "[Feature]: "
|
||||
body:
|
||||
- type: checkboxes
|
||||
id: check-answer
|
||||
attributes:
|
||||
label: 解决方案检查
|
||||
description: 请确保你已完成以下所有操作
|
||||
description: 请确保你已完成以下所有操作。
|
||||
options:
|
||||
- label: 我已阅读常见问题(<https://lyswhut.github.io/lx-music-doc/desktop/faq>),但没有找到解决方案
|
||||
- label: 我已阅读 [常见问题](https://lyswhut.github.io/lx-music-doc/desktop/faq),但没有找到解决方案。
|
||||
required: true
|
||||
- label: 我已搜索issue列表(<https://github.com/lyswhut/lx-music-desktop/issues?utf8=✓&q=>),但没有发现类似的问题
|
||||
- label: 我已搜索 [Issue 列表](https://github.com/lyswhut/lx-music-desktop/issues?q=is%3Aissue+),但没有发现类似的问题。
|
||||
required: true
|
||||
- type: textarea
|
||||
id: problem-description
|
||||
attributes:
|
||||
label: 问题描述
|
||||
description: 请添加清晰简洁的描述,说明你希望通过此功能请求解决的问题
|
||||
description: 请添加清晰简洁的描述,说明你希望通过此功能请求解决的问题。
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: proposed-solution
|
||||
attributes:
|
||||
label: 描述你想要的解决方案
|
||||
description: 简洁明了地描述你要发生的事情
|
||||
description: 简洁明了地描述你要发生的事情。
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: alternatives-considered
|
||||
attributes:
|
||||
label: 描述你考虑过的替代方案
|
||||
description: 对你考虑过的所有替代解决方案或功能的简洁明了的描述
|
||||
validations:
|
||||
required: false
|
||||
description: 对你考虑过的所有替代解决方案或功能的简洁明了的描述。
|
||||
- type: textarea
|
||||
id: additional-information
|
||||
attributes:
|
||||
label: 附加信息
|
||||
description: 如果你的问题需要进一步解释,或者想要表达其他内容,请在此处添加更多信息。(直接把图片、视频拖到编辑框即可添加图片或视频)
|
||||
description: 如果你的问题需要进一步解释,或者想要表达其他内容,请在此处添加更多信息。(直接把图片/视频拖到编辑框即可添加图片/视频)
|
||||
28
.github/actions/setup/action.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: Setup
|
||||
description: Setup Node Env
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22'
|
||||
|
||||
# - name: Get npm cache directory
|
||||
# run: node -p -e '`NPM_CACHE_DIR=${require("child_process").execSync("npm config get cache").toString()}`' >> $GITHUB_ENV
|
||||
# run: echo "NPM_CACHE_DIR=$(npm config get cache)" >> $GITHUB_ENV
|
||||
|
||||
# https://docs.npmjs.com/cli/v10/configuring-npm/folders#cache
|
||||
- name: Cache node modules
|
||||
id: cache-npm
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ env.NPM_CACHE }}
|
||||
key: ${{ runner.os }}-npm-cache-${{ hashFiles('package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-npm-cache-
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
shell: bash
|
||||
297
.github/workflows/beta-pack.yml
vendored
@@ -5,94 +5,159 @@ on:
|
||||
branches:
|
||||
- beta
|
||||
|
||||
env:
|
||||
IS_CI: 'true'
|
||||
|
||||
jobs:
|
||||
# CheckCode:
|
||||
# name: Lint Code
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - name: Check out git repository
|
||||
# uses: actions/checkout@v4
|
||||
|
||||
# - name: Install Node.js
|
||||
# uses: actions/setup-node@v4
|
||||
# with:
|
||||
# node-version: 20
|
||||
|
||||
# - name: Cache file
|
||||
# uses: actions/cache@v4
|
||||
# with:
|
||||
# path: |
|
||||
# node_modules
|
||||
# $HOME/.cache/electron
|
||||
# $HOME/.cache/electron-builder
|
||||
# $HOME/.npm/_prebuilds
|
||||
# key: ${{ runner.os }}-build-caches-${{ hashFiles('**/package-lock.json') }}
|
||||
# restore-keys: |
|
||||
# ${{ runner.os }}-build-
|
||||
|
||||
# - name: Install Dependencies
|
||||
# run: |
|
||||
# npm ci
|
||||
|
||||
# - name: Lint src code
|
||||
# run: npm run lint
|
||||
|
||||
Windows:
|
||||
name: Windows
|
||||
runs-on: windows-latest
|
||||
# needs: CheckCode
|
||||
steps:
|
||||
- name: Check out git repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '16'
|
||||
- name: Get npm cache directory
|
||||
shell: pwsh
|
||||
run: echo "NPM_CACHE=$(npm config get cache)" >> $env:GITHUB_ENV
|
||||
|
||||
- name: Cache file
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
node_modules
|
||||
%APPDATA%\npm-cache
|
||||
%LOCALAPPDATA%\electron\Cache
|
||||
%LOCALAPPDATA%\electron-builder\Cache
|
||||
key: ${{ runner.os }}-build-caches-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
npm install npm@8.5 -g
|
||||
npm install
|
||||
- name: Setup Node Env
|
||||
env:
|
||||
NPM_CACHE: ${{ env.NPM_CACHE }}
|
||||
uses: ./.github/actions/setup
|
||||
|
||||
- name: Build src code
|
||||
run: npm run build:src
|
||||
run: |
|
||||
git status --porcelain
|
||||
npm run build
|
||||
|
||||
- name: Build Package Setup x64
|
||||
run: npm run pack:win:setup:x64
|
||||
- name: Upload Artifact Setup x64
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: lx-music-desktop-x64-Setup
|
||||
path: build/* x64 Setup.exe
|
||||
|
||||
- name: Build Package Setup x86
|
||||
run: npm run pack:win:setup:x86
|
||||
- name: Upload Artifact Setup x86
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: lx-music-desktop-x86-Setup
|
||||
path: build/* x86 Setup.exe
|
||||
|
||||
- name: Build Package Setup arm64
|
||||
run: npm run pack:win:setup:arm64
|
||||
- name: Upload Artifact Setup arm64
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: lx-music-desktop-arm64-Setup
|
||||
path: build/* arm64 Setup.exe
|
||||
|
||||
- name: Build Package Setup x86_64
|
||||
run: npm run pack:win:setup:x86_64
|
||||
- name: Upload Artifact Setup x86_64
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: lx-music-desktop-x86_64-Setup
|
||||
path: build/*x86_64 Setup.exe
|
||||
path: build/*-x64-Setup.exe
|
||||
|
||||
- name: Build Package 7z x64
|
||||
run: npm run pack:win:7z:x64
|
||||
- name: Upload Artifact 7z x64
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: lx-music-desktop-win_x64-green
|
||||
path: build/*win_x64 green.7z
|
||||
path: build/*win_x64-green.7z
|
||||
|
||||
- name: Build Package 7z x86
|
||||
run: npm run pack:win:7z:x86
|
||||
- name: Upload Artifact 7z x86
|
||||
uses: actions/upload-artifact@v2
|
||||
- name: Build Package Setup arm64
|
||||
run: npm run pack:win:setup:arm64
|
||||
- name: Upload Artifact Setup arm64
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: lx-music-desktop-win_x86-green
|
||||
path: build/*win_x86 green.7z
|
||||
name: lx-music-desktop-arm64-Setup
|
||||
path: build/*-arm64-Setup.exe
|
||||
|
||||
- name: Build Package 7z arm64
|
||||
run: npm run pack:win:7z:arm64
|
||||
- name: Upload Artifact 7z arm64
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: lx-music-desktop-win_arm64-green
|
||||
path: build/*win_arm64 green.7z
|
||||
path: build/*win_arm64-green.7z
|
||||
|
||||
- name: Generate file MD5
|
||||
run: |
|
||||
cd build
|
||||
Get-FileHash *.exe,*.7z -Algorithm MD5 | Format-List
|
||||
|
||||
Windows_7:
|
||||
name: Windows_7
|
||||
runs-on: windows-latest
|
||||
env:
|
||||
BUILD_WIN7: true
|
||||
# needs: CheckCode
|
||||
steps:
|
||||
- name: Check out git repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Get npm cache directory
|
||||
shell: pwsh
|
||||
run: echo "NPM_CACHE=$(npm config get cache)" >> $env:GITHUB_ENV
|
||||
|
||||
- name: Setup Node Env
|
||||
env:
|
||||
NPM_CACHE: ${{ env.NPM_CACHE }}
|
||||
uses: ./.github/actions/setup
|
||||
|
||||
- name: Prepare win7 undici env
|
||||
run: |
|
||||
npm install undici@5
|
||||
Set-Content -Path .\src\common\utils\request.ts -Value "export * from './request_node16'"
|
||||
|
||||
- name: Build src code
|
||||
env:
|
||||
BUILD_WIN7: true
|
||||
run: |
|
||||
git status --porcelain
|
||||
npm run build
|
||||
|
||||
- name: Prepare win7 electron env
|
||||
run: |
|
||||
npm install electron@22
|
||||
pip.exe install setuptools
|
||||
|
||||
- name: Build Package win7 Setup x64
|
||||
run: npm run pack:win7:setup:x64
|
||||
- name: Upload Artifact win7 Setup x64
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: lx-music-desktop-win7_x64-Setup
|
||||
path: build/*win7_x64-Setup.exe
|
||||
|
||||
- name: Build Package win7 7z x64
|
||||
run: npm run pack:win7:7z:x64
|
||||
- name: Upload Artifact win7 7z x64
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: lx-music-desktop-win7_x64-green
|
||||
path: build/*win7_x64-green.7z
|
||||
|
||||
- name: Build Package win7 7z x86
|
||||
run: npm run pack:win7:7z:x86
|
||||
- name: Upload Artifact win7 7z x86
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: lx-music-desktop-win7_x86-green
|
||||
path: build/*win7_x86-green.7z
|
||||
|
||||
- name: Generate file MD5
|
||||
run: |
|
||||
@@ -102,52 +167,42 @@ jobs:
|
||||
Mac:
|
||||
name: Mac
|
||||
runs-on: macos-latest
|
||||
# needs: CheckCode
|
||||
steps:
|
||||
- name: Check out git repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '16'
|
||||
- name: Install python setuptools
|
||||
run: brew install python-setuptools
|
||||
|
||||
- name: Cache file
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
node_modules
|
||||
$HOME/.cache/electron
|
||||
$HOME/.cache/electron-builder
|
||||
$HOME/.npm/_prebuilds
|
||||
key: ${{ runner.os }}-build-caches-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-
|
||||
- name: Get npm cache directory
|
||||
shell: bash
|
||||
run: echo "NPM_CACHE=$(npm config get cache)" >> $GITHUB_ENV
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
npm install npm@8.5 -g
|
||||
npm install
|
||||
- name: Setup Node Env
|
||||
env:
|
||||
NPM_CACHE: ${{ env.NPM_CACHE }}
|
||||
uses: ./.github/actions/setup
|
||||
|
||||
- name: Build src code
|
||||
run: npm run build:src
|
||||
run: |
|
||||
git status --porcelain
|
||||
npm run build
|
||||
|
||||
- name: Build Package dmg
|
||||
run: |
|
||||
npm run pack:mac:dmg
|
||||
npm run pack:mac:dmg:arm64
|
||||
env:
|
||||
ELECTRON_CACHE: $HOME/.cache/electron
|
||||
ELECTRON_BUILDERCACHE: $HOME/.cache/electron-builder
|
||||
|
||||
- name: Upload Artifact dmg
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: lx-music-desktop-mac-dmg
|
||||
path: |
|
||||
build/*.dmg
|
||||
!build/*-arm64.dmg
|
||||
- name: Upload Artifact dmg
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: lx-music-desktop-mac-dmg-arm64
|
||||
path: build/*-arm64.dmg
|
||||
@@ -160,93 +215,75 @@ jobs:
|
||||
Linux:
|
||||
name: Linux
|
||||
runs-on: ubuntu-latest
|
||||
# needs: CheckCode
|
||||
steps:
|
||||
- name: Install package
|
||||
run: sudo apt-get update && sudo apt-get install -y rpm libarchive-tools
|
||||
|
||||
- name: Check out git repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '16'
|
||||
- name: Get npm cache directory
|
||||
shell: bash
|
||||
run: echo "NPM_CACHE=$(npm config get cache)" >> $GITHUB_ENV
|
||||
|
||||
- name: Cache file
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
node_modules
|
||||
$HOME/.cache/electron
|
||||
$HOME/.cache/electron-builder
|
||||
$HOME/.npm/_prebuilds
|
||||
key: ${{ runner.os }}-build-caches-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
npm install npm@8.5 -g
|
||||
npm install
|
||||
- name: Setup Node Env
|
||||
env:
|
||||
NPM_CACHE: ${{ env.NPM_CACHE }}
|
||||
uses: ./.github/actions/setup
|
||||
|
||||
- name: Build src code
|
||||
run: npm run build:src
|
||||
run: |
|
||||
git status --porcelain
|
||||
npm run build
|
||||
|
||||
- name: Build Package deb x64
|
||||
run: npm run pack:linux:deb:x64
|
||||
- name: Upload Artifact deb x64
|
||||
uses: actions/upload-artifact@v2
|
||||
- name: Build Package deb amd64
|
||||
run: npm run pack:linux:deb:amd64
|
||||
- name: Upload Artifact deb amd64
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: lx-music-desktop-deb-x64
|
||||
path: build/* x64.deb
|
||||
|
||||
- name: Build Package deb x86
|
||||
run: npm run pack:linux:deb:x86
|
||||
- name: Upload Artifact deb x86
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: lx-music-desktop-deb-x86
|
||||
path: build/* x86.deb
|
||||
name: lx-music-desktop-deb-amd64
|
||||
path: build/*_amd64.deb
|
||||
|
||||
- name: Build Package deb arm64
|
||||
run: npm run pack:linux:deb:arm64
|
||||
- name: Upload Artifact deb arm64
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: lx-music-desktop-deb-arm64
|
||||
path: build/* arm64.deb
|
||||
path: build/*_arm64.deb
|
||||
|
||||
- name: Build Package deb armv7l
|
||||
run: npm run pack:linux:deb:armv7l
|
||||
- name: Upload Artifact deb armv7l
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: lx-music-desktop-deb-armv7l
|
||||
path: build/* armv7l.deb
|
||||
path: build/*_armv7l.deb
|
||||
|
||||
- name: Build Package x64 appImage
|
||||
run: npm run pack:linux:appImage
|
||||
- name: Upload Artifact x64 appImage
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: lx-music-desktop-x64-appImage
|
||||
path: build/* x64.AppImage
|
||||
path: build/*_x64.AppImage
|
||||
|
||||
- name: Build Package x64 rpm
|
||||
run: npm run pack:linux:rpm
|
||||
- name: Upload Artifact x64 rpm
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: lx-music-desktop-x64-rpm
|
||||
path: build/* x64.rpm
|
||||
path: build/*.x64.rpm
|
||||
|
||||
- name: Build Package x64 pacman
|
||||
run: npm run pack:linux:pacman
|
||||
- name: Upload Artifact x64 pacman
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: lx-music-desktop-x64-pacman
|
||||
path: build/* x64.pacman
|
||||
path: build/*_x64.pacman
|
||||
|
||||
- name: Generate file MD5
|
||||
run: |
|
||||
|
||||
28
.github/workflows/build-test.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: Run build test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- dev
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out git repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
- name: Install Dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Eslint check
|
||||
run: npm run lint
|
||||
|
||||
- name: Test Build
|
||||
run: npm run build
|
||||
16
.github/workflows/publish-version-info.yml
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
name: Publish NPM Version Info
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
dispatch:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Repository Dispatch
|
||||
uses: peter-evans/repository-dispatch@v2
|
||||
with:
|
||||
token: ${{ secrets.PAT }}
|
||||
repository: lyswhut/lx-music-desktop-version-info
|
||||
event-type: npm-release
|
||||
205
.github/workflows/release.yml
vendored
@@ -5,48 +5,121 @@ on:
|
||||
branches:
|
||||
- master
|
||||
|
||||
env:
|
||||
IS_CI: 'true'
|
||||
|
||||
jobs:
|
||||
# CheckCode:
|
||||
# name: Lint Code
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - name: Check out git repository
|
||||
# uses: actions/checkout@v4
|
||||
|
||||
# - name: Install Node.js
|
||||
# uses: actions/setup-node@v4
|
||||
# with:
|
||||
# node-version: 20
|
||||
|
||||
# - name: Cache file
|
||||
# uses: actions/cache@v4
|
||||
# with:
|
||||
# path: |
|
||||
# node_modules
|
||||
# $HOME/.cache/electron
|
||||
# $HOME/.cache/electron-builder
|
||||
# $HOME/.npm/_prebuilds
|
||||
# key: ${{ runner.os }}-build-caches-${{ hashFiles('**/package-lock.json') }}
|
||||
# restore-keys: |
|
||||
# ${{ runner.os }}-build-
|
||||
|
||||
# - name: Install Dependencies
|
||||
# run: |
|
||||
# npm ci
|
||||
|
||||
# - name: Lint src code
|
||||
# run: npm run lint
|
||||
|
||||
Windows:
|
||||
name: Windows
|
||||
runs-on: windows-latest
|
||||
# needs: CheckCode
|
||||
steps:
|
||||
- name: Check out git repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '16'
|
||||
- name: Get npm cache directory
|
||||
shell: pwsh
|
||||
run: echo "NPM_CACHE=$(npm config get cache)" >> $env:GITHUB_ENV
|
||||
|
||||
- name: Cache file
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
node_modules
|
||||
%APPDATA%\npm-cache
|
||||
%LOCALAPPDATA%\electron\Cache
|
||||
%LOCALAPPDATA%\electron-builder\Cache
|
||||
key: ${{ runner.os }}-build-caches-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-
|
||||
- name: Show Env
|
||||
run: echo "${{ env.NPM_CACHE }}"
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
npm install npm@8.5 -g
|
||||
npm install
|
||||
- name: Setup Node Env
|
||||
env:
|
||||
NPM_CACHE: ${{ env.NPM_CACHE }}
|
||||
uses: ./.github/actions/setup
|
||||
|
||||
- name: Build src code
|
||||
run: npm run build:src
|
||||
run: |
|
||||
git status --porcelain
|
||||
npm run build
|
||||
|
||||
- name: Release package
|
||||
run: |
|
||||
npm run publish:win:setup:x64:always
|
||||
npm run publish:win:setup:x86
|
||||
npm run publish:win:setup:arm64
|
||||
npm run publish:win:setup:x86_64
|
||||
npm run publish:win:7z:x64
|
||||
npm run publish:win:7z:x86
|
||||
npm run publish:win:7z:arm64
|
||||
npm run publish:win:setup:arm64
|
||||
npm run publish:win:setup:x64
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
BT_TOKEN: ${{ secrets.BT_TOKEN }}
|
||||
|
||||
- name: Generate file MD5
|
||||
run: |
|
||||
cd build
|
||||
Get-FileHash *.exe,*.7z -Algorithm MD5 | Format-List
|
||||
|
||||
|
||||
Windows_7:
|
||||
name: Windows_7
|
||||
runs-on: windows-latest
|
||||
# needs: CheckCode
|
||||
steps:
|
||||
- name: Check out git repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Get npm cache directory
|
||||
shell: pwsh
|
||||
run: echo "NPM_CACHE=$(npm config get cache)" >> $env:GITHUB_ENV
|
||||
|
||||
- name: Setup Node Env
|
||||
env:
|
||||
NPM_CACHE: ${{ env.NPM_CACHE }}
|
||||
uses: ./.github/actions/setup
|
||||
|
||||
- name: Prepare win7 undici env
|
||||
run: |
|
||||
npm install undici@5
|
||||
Set-Content -Path .\src\common\utils\request.ts -Value "export * from './request_node16'"
|
||||
|
||||
- name: Build src code
|
||||
env:
|
||||
BUILD_WIN7: true
|
||||
run: |
|
||||
git status --porcelain
|
||||
npm run build
|
||||
|
||||
- name: Prepare win7 electron env
|
||||
run: |
|
||||
npm install electron@22
|
||||
pip.exe install setuptools
|
||||
|
||||
- name: Release win7 package
|
||||
run: |
|
||||
npm run publish:win7:setup:x64
|
||||
npm run publish:win7:7z:x64
|
||||
npm run publish:win7:7z:x86
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
BT_TOKEN: ${{ secrets.BT_TOKEN }}
|
||||
@@ -59,42 +132,35 @@ jobs:
|
||||
Mac:
|
||||
name: Mac
|
||||
runs-on: macos-latest
|
||||
# needs: CheckCode
|
||||
steps:
|
||||
- name: Check out git repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '16'
|
||||
- name: Install python3 setuptools
|
||||
run: brew install python-setuptools
|
||||
|
||||
- name: Cache file
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
node_modules
|
||||
$HOME/.cache/electron
|
||||
$HOME/.cache/electron-builder
|
||||
$HOME/.npm/_prebuilds
|
||||
key: ${{ runner.os }}-build-caches-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-
|
||||
- name: Get npm cache directory
|
||||
shell: bash
|
||||
run: echo "NPM_CACHE=$(npm config get cache)" >> $GITHUB_ENV
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
npm install npm@8.5 -g
|
||||
npm install
|
||||
- name: Show Env
|
||||
run: echo "${{ env.NPM_CACHE }}"
|
||||
- name: Setup Node Env
|
||||
env:
|
||||
NPM_CACHE: ${{ env.NPM_CACHE }}
|
||||
uses: ./.github/actions/setup
|
||||
|
||||
- name: Build src code
|
||||
run: npm run build:src
|
||||
run: |
|
||||
git status --porcelain
|
||||
npm run build
|
||||
|
||||
- name: Release package
|
||||
run: |
|
||||
npm run publish:mac:dmg:always
|
||||
npm run publish:mac:dmg
|
||||
npm run publish:mac:dmg:arm64
|
||||
env:
|
||||
ELECTRON_CACHE: $HOME/.cache/electron
|
||||
ELECTRON_BUILDERCACHE: $HOME/.cache/electron-builder
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
BT_TOKEN: ${{ secrets.BT_TOKEN }}
|
||||
|
||||
@@ -106,42 +172,33 @@ jobs:
|
||||
Linux:
|
||||
name: Linux
|
||||
runs-on: ubuntu-latest
|
||||
# needs: CheckCode
|
||||
steps:
|
||||
- name: Install package
|
||||
run: sudo apt-get update && sudo apt-get install -y rpm libarchive-tools
|
||||
|
||||
- name: Check out git repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '16'
|
||||
- name: Get npm cache directory
|
||||
shell: bash
|
||||
run: echo "NPM_CACHE=$(npm config get cache)" >> $GITHUB_ENV
|
||||
|
||||
- name: Cache file
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
node_modules
|
||||
$HOME/.cache/electron
|
||||
$HOME/.cache/electron-builder
|
||||
$HOME/.npm/_prebuilds
|
||||
key: ${{ runner.os }}-build-caches-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
npm install npm@8.5 -g
|
||||
npm install
|
||||
- name: Show Env
|
||||
run: echo "${{ env.NPM_CACHE }}"
|
||||
- name: Setup Node Env
|
||||
env:
|
||||
NPM_CACHE: ${{ env.NPM_CACHE }}
|
||||
uses: ./.github/actions/setup
|
||||
|
||||
- name: Build src code
|
||||
run: npm run build:src
|
||||
run: |
|
||||
git status --porcelain
|
||||
npm run build
|
||||
|
||||
- name: Release package
|
||||
run: |
|
||||
npm run publish:linux:deb:x64:always
|
||||
npm run publish:linux:deb:x86
|
||||
npm run publish:linux:deb:amd64
|
||||
npm run publish:linux:deb:arm64
|
||||
npm run publish:linux:deb:armv7l
|
||||
npm run publish:linux:appImage
|
||||
|
||||
36
.ncurc.js
@@ -3,11 +3,45 @@ module.exports = {
|
||||
reject: [
|
||||
'electron',
|
||||
'chalk',
|
||||
'del',
|
||||
'comlink',
|
||||
'vue',
|
||||
'vue-router',
|
||||
'image-size',
|
||||
'message2call',
|
||||
'@types/ws',
|
||||
'eslint',
|
||||
'@types/node',
|
||||
'electron-debug',
|
||||
'eslint-webpack-plugin',
|
||||
|
||||
'eslint-plugin-vue',
|
||||
'vue-eslint-parser',
|
||||
// 'eslint-config-standard-with-typescript',
|
||||
],
|
||||
|
||||
// target: 'newest',
|
||||
// filter: [
|
||||
// /^vue/,
|
||||
// 'electron-builder',
|
||||
// 'electron-updater',
|
||||
// ],
|
||||
|
||||
// target: 'patch',
|
||||
// filter: [
|
||||
// 'electron',
|
||||
// 'vue',
|
||||
// 'vue-router',
|
||||
// ],
|
||||
|
||||
// target: 'minor',
|
||||
// filter: [
|
||||
// // 'electron',
|
||||
// 'eslint',
|
||||
// 'eslint-webpack-plugin',
|
||||
// 'electron-debug',
|
||||
// '@types/node',
|
||||
|
||||
// 'eslint-plugin-vue',
|
||||
// 'vue-eslint-parser',
|
||||
// ],
|
||||
}
|
||||
|
||||
29
.vscode/i18n-ally-custom-framework.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
# .vscode/i18n-ally-custom-framework.yml
|
||||
|
||||
# An array of strings which contain Language Ids defined by VS Code
|
||||
# You can check avaliable language ids here: https://code.visualstudio.com/docs/languages/overview#_language-id
|
||||
languageIds:
|
||||
- javascript
|
||||
- typescript
|
||||
- vue
|
||||
|
||||
# An array of RegExes to find the key usage. **The key should be captured in the first match group**.
|
||||
# You should unescape RegEx strings in order to fit in the YAML file
|
||||
# To help with this, you can use https://www.freeformatter.com/json-escape.html
|
||||
usageMatchRegex:
|
||||
# The following example shows how to detect `t("your.i18n.keys")`
|
||||
# the `{key}` will be placed by a proper keypath matching regex,
|
||||
# you can ignore it and use your own matching rules as well
|
||||
- "[^\\w\\d]t\\(['\"`]({key})['\"`]"
|
||||
|
||||
|
||||
# An array of strings containing refactor templates.
|
||||
# The "$1" will be replaced by the keypath specified.
|
||||
# Optional: uncomment the following two lines to use
|
||||
|
||||
# refactorTemplates:
|
||||
# - i18n.get("$1")
|
||||
|
||||
|
||||
# If set to true, only enables this custom framework (will disable all built-in frameworks)
|
||||
monopoly: true
|
||||
37
.vscode/javascript.code-snippets
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
// Place your lx-music-desktop-new 工作区 snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
|
||||
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
|
||||
// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
|
||||
// used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
|
||||
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
|
||||
// Placeholders with the same ids are connected.
|
||||
// Example:
|
||||
// "Print to console": {
|
||||
// "scope": "javascript,typescript",
|
||||
// "prefix": "log",
|
||||
// "body": [
|
||||
// "console.log('$1');",
|
||||
// "$2"
|
||||
// ],
|
||||
// "description": "Log output to console"
|
||||
// }
|
||||
"use i18n": {
|
||||
"prefix": "ui18n",
|
||||
"body": [
|
||||
"import { useI18n } from '@renderer/plugins/i18n'",
|
||||
"${1:const t = useI18n()}"
|
||||
]
|
||||
},
|
||||
"list action": {
|
||||
"prefix": "listacion",
|
||||
"body": [
|
||||
"import { $1 } from '@renderer/store/list/action'",
|
||||
]
|
||||
},
|
||||
"import vue tools": {
|
||||
"prefix": "imvt",
|
||||
"body": [
|
||||
"import { $1 } from '@common/utils/vueTools'",
|
||||
]
|
||||
}
|
||||
}
|
||||
5
.vscode/settings.json
vendored
@@ -10,5 +10,8 @@
|
||||
"google-cn",
|
||||
"google"
|
||||
],
|
||||
"i18n-ally.sortKeys": true
|
||||
"i18n-ally.sortKeys": true,
|
||||
"javascript.preferences.importModuleSpecifier": "non-relative",
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"vue.codeActions.enabled": false
|
||||
}
|
||||
|
||||
31
.vscode/typescript.code-snippets
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
// Place your lx-music-desktop-new 工作区 snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
|
||||
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
|
||||
// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
|
||||
// used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
|
||||
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
|
||||
// Placeholders with the same ids are connected.
|
||||
// Example:
|
||||
// "Print to console": {
|
||||
// "scope": "javascript,typescript",
|
||||
// "prefix": "log",
|
||||
// "body": [
|
||||
// "console.log('$1');",
|
||||
// "$2"
|
||||
// ],
|
||||
// "description": "Log output to console"
|
||||
// }
|
||||
"use i18n": {
|
||||
"prefix": "ui18n",
|
||||
"body": [
|
||||
"import { useI18n } from '@renderer/plugins/i18n'",
|
||||
"${1:const t = useI18n()}"
|
||||
]
|
||||
},
|
||||
"import vue tools": {
|
||||
"prefix": "imvt",
|
||||
"body": [
|
||||
"import { $1 } from '@common/utils/vueTools'",
|
||||
]
|
||||
}
|
||||
}
|
||||
731
CHANGELOG.md
@@ -6,6 +6,737 @@ Project versioning adheres to [Semantic Versioning](http://semver.org/).
|
||||
Commit convention is based on [Conventional Commits](http://conventionalcommits.org).
|
||||
Change log format is based on [Keep a Changelog](http://keepachangelog.com/).
|
||||
|
||||
## [2.12.1](https://github.com/lyswhut/lx-music-desktop/compare/v2.12.0...v2.12.1) - 2026-02-16
|
||||
|
||||
我们很高兴地宣布新项目 Any Listen 的桌面版已发布,目前已支持列表跟随本地文件自动更新、加载并播放WebDAV上的歌曲等功能,更多功能仍在积极开发中,桌面版与Web版将同步更新。
|
||||
对于有播放本地音乐或播放服务器上音乐需求的人可以试试,若遇到任何问题可以发 issue 反馈。
|
||||
|
||||
### 优化
|
||||
|
||||
- 优化托盘图标行为:在非 Windows 系统中,点击托盘图标时不再显示主窗口
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复音量条在调整音量时实际音量与显示的数值不一致的问题(#2606)
|
||||
- 修复某些情况下搜索框的搜索按钮布局错位的问题(#2622)
|
||||
|
||||
## [2.12.0](https://github.com/lyswhut/lx-music-desktop/compare/v2.11.0...v2.12.0) - 2025-11-29
|
||||
|
||||
我们很高兴地宣布新项目 Any Listen 的桌面版已发布,目前已支持列表跟随本地文件自动更新、加载并播放WebDAV上的歌曲等功能,更多功能仍在积极开发中,桌面版与Web版将同步更新。
|
||||
对于有播放本地音乐或播放服务器上音乐需求的人可以试试,若遇到任何问题可以发 issue 反馈。
|
||||
|
||||
### 新增
|
||||
|
||||
- 新增「设置 → 其他设置 → 主窗口使用软件内置的圆角及阴影」选项 (#2360)
|
||||
*默认启用,关闭后将使用系统原生的窗口样式,该选项重启软件后生效*
|
||||
- 开放 API 新增播放器声音大小、静音、播放进度控制、完整歌词获取,详情看接入文档 (#2386)
|
||||
- 新增「设置 → 播放设置 → 调换歌词翻译与歌词罗马音位置」选项,默认关闭 (#2451)
|
||||
- 新增启动参数 `-hidden`,在启动时将软件最小化到系统托盘 (#2459)
|
||||
- 新增 Any Listen 歌词(用于支持已下载歌曲的歌词逐字播放)标签数据读取与播放 (#2485)
|
||||
- 新增 Any Listen 歌词(包含逐字歌词、翻译、罗马音歌词,如果有)嵌入与下载,默认启用
|
||||
- 下载列表菜单新增歌曲添加弹窗,允许将所选歌曲的在线版本添加到收藏列表 (#2537)
|
||||
|
||||
### 修复
|
||||
|
||||
- 尝试修复进度为0时仍然显示下载完成的问题 (#2471)
|
||||
- 修复TX源搜索失败 (#2575 @Folltoshe)
|
||||
- 修复MG源歌单加载失败
|
||||
- 修复MG源评论加载失败
|
||||
|
||||
### 变更
|
||||
|
||||
- 调换「歌词翻译」与「歌词罗马音」的位置,现在歌词罗马音在歌词翻译的上方展示
|
||||
*若你想要恢复以前的行为,可以开启「调换歌词翻译与歌词罗马音位置」选项*
|
||||
- 更新代理配置规则,现在不启用代理时,图片、音频加载将不再走系统代理 (#2382 @Folltoshe)
|
||||
- 字体设置可以最多设置两种字体([any-listen#82](https://github.com/any-listen/any-listen/issues/82))
|
||||
|
||||
### 其他
|
||||
|
||||
- 更新 Electron 到 37.6.0
|
||||
|
||||
## [2.11.0](https://github.com/lyswhut/lx-music-desktop/compare/v2.10.0...v2.11.0) - 2025-05-01
|
||||
|
||||
### 新增
|
||||
|
||||
- 新增「快进/快退5秒」自定义快捷键设置(#2289)
|
||||
- 新增「设置 → 桌面歌词设置 → 暂停时提高歌词透明度」设置,默认启用(#2294)
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复 Windows 下桌面歌词最小高度与宽度设置问题(#2244)
|
||||
- 修复 Windows 下界面缩放后移动桌面歌词会改变歌词窗口大小的问题(#2244)
|
||||
- 修复 tx 歌单搜索名字、描述出现乱码的问题(#2250)
|
||||
- 修复本地 FLAC 文件内嵌歌词无法读取的问题
|
||||
- 修复潜在播放暂停的问题
|
||||
- 修复 kw 歌单详情出现打开失败的问题(#2317)
|
||||
- 修复 kg 热门评论无法获取的问题
|
||||
- 修复桌面歌词被遮挡时会被暂停的问题(#2320)
|
||||
- 修复 kg 歌单打开失败的问题(thanks @Folltoshe)
|
||||
|
||||
### 优化
|
||||
|
||||
- 允许更小的桌面歌词窗口宽度
|
||||
- 允许拖动桌面歌词控制栏空白处移动歌词窗口(#2280)
|
||||
- 优化「自定义源管理」对话框在小窗口下的布局(#2247, @3gf8jv4dv)
|
||||
- 优化软件文案编排(#2259, #2266, #2269, #2296, @3gf8jv4dv)
|
||||
|
||||
### 变更
|
||||
|
||||
- 我的列表-歌曲菜单中的 歌曲换源 功能从之前的类似软连接的形式改成替换歌曲的形式,也就是说,现在该功能相当于快速在线搜索歌曲,确认换源后将自动将原来的歌曲删除再将选择的歌曲插入被删除歌曲的位置。
|
||||
|
||||
### 其他
|
||||
|
||||
- 更新项目文档(@3gf8jv4dv)
|
||||
- 更新 Electron 到 35.2.2
|
||||
|
||||
## [2.10.0](https://github.com/lyswhut/lx-music-desktop/compare/v2.9.0...v2.10.0) - 2025-01-27
|
||||
|
||||
落雪祝大家新年快乐!
|
||||
|
||||
### 关于之前提到的新项目
|
||||
|
||||
新项目我取名叫 Any Listen,希望它能像它的名字一样让我们能到处任意听歌。
|
||||
经过一年多的开发,因各种原因,实际进度比预期的慢,但还是赶在年前发布了第一个web服务预览版,第一个版本仅支持播放服务器上的歌曲,扩展功能暂时未能开放,但已趋于完成,一两个月内可以搞定。
|
||||
目前的版本仅是“能用”的状态,因时间关系,部分UI未能重新设计,但后面会继续完善。
|
||||
该项目目前的目标用户是拥有自己服务器且上面存储有歌曲的人使用。
|
||||
|
||||
项目刚发布,文档未能完善,遇到使用问题或有任何建议欢迎提 issue 交流,
|
||||
项目地址: https://github.com/any-listen/any-listen
|
||||
|
||||
---
|
||||
|
||||
*感谢 @3gf8jv4dv 对 LX 系列项目翻译、文档等文案的大幅修订优化。*
|
||||
|
||||
### 不兼容性变更
|
||||
|
||||
Linux 系统至少需要 `GLIBC_2.29` 版本才能运行。
|
||||
|
||||
由于将 Electron 升级到 v32.x,原生库的编译被限制到不低于 C++ 20,试了几次无法在 docker 镜像 `node:16` 安装 gcc-10,最终将构建使用镜像更新到 `node:18`。
|
||||
|
||||
### 新增
|
||||
|
||||
- 新增下载的歌曲按列表名分组的功能,默认关闭,可以通过「设置 → 下载设置 → 将文件保存到以对应列表命名的子目录中」启用(#2145)
|
||||
- 新增托盘图标样式「跟随系统亮暗模式」设置,可以在「设置 → 其他」里启用 (#2016)
|
||||
- 支持本地同名 `.krc` 格式歌词文件的读取(#2053)
|
||||
- 开放 API 新增播放器播放/暂停、切歌、收藏当前播放歌曲等接口调用,详情看文档「开放 API 服务」部分(#2077, @14Kay)
|
||||
|
||||
### 优化
|
||||
|
||||
- 优化正常播放结束时的下一首歌曲播放衔接度,在歌曲即将结束播放时将预获取下一首歌曲的播放链接,减少自动切歌时的等待时间(#2126)
|
||||
- 优化歌曲换源机制,提升换源正确率
|
||||
- 优化 Windows 平台上桌面歌词窗口大小调整机制,改用原生的窗口调整方式(#2137)
|
||||
- 修正搜索歌曲提示框文案(#2050)
|
||||
- 优化播放详情页 UI,修复「歌曲名」「艺术家」等文字过长时被截断的问题(#2049)
|
||||
- Scheme URL 的播放歌曲允许更长的专辑名称
|
||||
- 播放本地歌曲时,将优先尝试读取本地同名 `.jpg` 或 `.png` 图片作为播放封面显示,若文件不存在则从音频文件内读取,最后再尝试使用在线图片(#2096)
|
||||
- 客户端模式的同步服务连接允许重定向 5 次(#2109)
|
||||
- 更新软件默认使用的字体,修复 macOS Sequoia (15) 上界面出现乱码的问题(#2076)
|
||||
- 优化简体、繁体中文文案编排,大幅修订英语文案编排(#2159, #2166, #2174 等, @3gf8jv4dv)
|
||||
- 优化排序歌曲、主题名称、添加/编辑主题、列表更新管理等对话框布局及长文本显示效果(#2176, #2188, #2189, #2198 等, @3gf8jv4dv)
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复歌单详情页内歌单名字过长时的 UI 显示问题(#2028)
|
||||
- 修复获取自定义环境音效预设列表逻辑问题
|
||||
- 修复 `.m4a` 文件内嵌歌词无法读取的问题(#2090)
|
||||
- 修复 Windows 任务管理器中的进程名显示为软件描述的问题(#2147)
|
||||
- 修复本地歌曲同名歌词文件调整偏移时间后,下次再播放时调整的设置未被应用的问题(#2139)
|
||||
- 修复首次打开软件后直接创建并删除列表时的报错问题(#2175, @14Kay)
|
||||
|
||||
### 变更
|
||||
|
||||
- 不再长期缓存换源歌曲信息
|
||||
- 更新软件默认使用的字体,现在软件尽量使用系统自带的默认字体
|
||||
- Linux 系统至少需要 `GLIBC_2.29` 版本才能运行
|
||||
|
||||
### 其他
|
||||
|
||||
- 更新 Readme 文档,优化文案编排(#2146, Thanks @3gf8jv4dv)
|
||||
- 更新 Issue 模板(#2153, @3gf8jv4dv)
|
||||
- 更新项目文档(@3gf8jv4dv)
|
||||
- 修订项目协议文件(#2146, #2152, @3gf8jv4dv)
|
||||
- 更新 Electron 到 v32.3.0
|
||||
|
||||
## [2.9.0](https://github.com/lyswhut/lx-music-desktop/compare/v2.8.0...v2.9.0) - 2024-08-24
|
||||
|
||||
### 新增
|
||||
|
||||
- 新增 设置-播放设置-是否将歌词显示在状态栏 设置,默认关闭,该功能只在 MacOS 下可用(#1940)
|
||||
- 新增设置-播放详情页设置-延迟歌词滚动设置(#1985)
|
||||
- 新增鼠标在音量按钮使用滚轮时可以调整音量大小的功能(#2000)
|
||||
- 新增设置-下载设置-同时下载任务数设置(#1498)
|
||||
- 新增 我的列表-歌曲右击菜单-歌曲换源 功能,换源后下次再播放该列表的该歌曲时将优先尝试播放所选源的歌曲,该功能允许你手动指定来源以解决自动换源失败或者换源不准确的问题
|
||||
|
||||
### 优化
|
||||
|
||||
- 优化侧栏图标显示,修复图标可能被裁切的问题(#1960)
|
||||
- 托盘图标添加当前播放歌曲名字显示
|
||||
- 优化本地歌曲内嵌封面过大时的加载方式
|
||||
- 将下载歌曲的歌手信息中的分隔符从 `、` 替换为 `;` 以确保音乐元数据在写入时的兼容性和一致性(#1989 @qnnp-me)
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复 MacOS 下点击 dock 右键菜单的退出按钮时,程序没有退出的问题(#1923)
|
||||
- 修复 OpenAPI 的 `lyricLineAllText` 在切换到无歌词的音乐时内容没有更新的问题(#1925)
|
||||
- 修复切换音源时可能出现切换死循环的问题
|
||||
- 尝试修复某些情况下播放音频时,处于播放状态但是进度条不走的问题
|
||||
- 修复程序目录路径存在 `#` 或 `%` 时,自定义源、托盘等图标异常的问题(#1997)
|
||||
|
||||
### 变更
|
||||
|
||||
- 简化了应用退出行为,据测试,现在 linux 下,若启用了托盘,dock 右键菜单的 退出、关闭所有 之类的功能将不再退出程序,需改用托盘的退出按钮退出程序
|
||||
- 现在如果在设置或者启动参数配置了代理服务,那么应用内的图片、音频加载,歌曲下载也将走代理
|
||||
|
||||
### 其他
|
||||
|
||||
- 更新 electron 到 v30.4.0
|
||||
|
||||
## [2.8.0](https://github.com/lyswhut/lx-music-desktop/compare/v2.7.0...v2.8.0) - 2024-06-01
|
||||
|
||||
我们发布了关于 LX Music 项目发展调整与新项目计划的说明,
|
||||
详情看: https://github.com/lyswhut/lx-music-desktop/issues/1912
|
||||
|
||||
### 新增
|
||||
|
||||
- 新增 设置-播放设置-使用设备能处理的最大声道数输出音频 设置(未启用时固定为2声道输出),由于这用到高级音频API,考虑到在某些设备上的兼容问题,默认禁用(#1873)
|
||||
- 允许添加 `m4a`、`oga` 格式的本地歌曲到列表中(#1864)
|
||||
- 开放API支持跨域请求(#1872 @Ceale)
|
||||
- Scheme URL API新增 `music/searchPlay` 支持,用于搜索并播放指定的歌曲名字,详细入参请阅读 Scheme URL 支持文档(#1886)
|
||||
|
||||
### 优化
|
||||
|
||||
- 优化白色托盘图标显示,修复windows下托盘图标不清晰的问题(#1842)
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复存在多级弹窗时的背景显示问题
|
||||
- 增大在线导入自定义源文件的大小限制问题(#1857)
|
||||
- 修复Mac下窗口出现残留阴影的问题,这解决了Mac下桌面歌词出现残留阴影的远古bug,感谢 @zclorne (#1869, Thanks @zclorne)
|
||||
- 增大在线导入自定义源文件的大小限制,解决某些音源无法导入的问题(#1857)
|
||||
- 修复Mac下即使开启了托盘, `cmd+w` 仍会中断播放的问题(#1844)
|
||||
- 修复播放详情页的歌词无法使用触碰拖动的问题(#1865)
|
||||
- 修复与优化繁体中文、英语翻译显示(#1845)
|
||||
- 修复歌曲时文件名过长导致歌曲无法下载的问题(#1877)
|
||||
- 修复文本提示气泡在内容过长时,文本未被换行而被截断的问题
|
||||
- 修复翻页按钮栏切页按钮只显示前几页的问题
|
||||
|
||||
### 变更
|
||||
|
||||
- 设置-播放设置-优先播放320k音质选项改为“优先播放的音质”,允许选择更高优先播放的音质,如果歌曲及音源支持的话(#1839)
|
||||
|
||||
### 开放API变更
|
||||
|
||||
- `/status` 的入参现在与 `/subscribe-player-status` 保持一致
|
||||
- `/status` 新增 `filter` 入参用于过滤返回的字段,并内置了默认值,与之前相比默认不再返回 `picUrl`
|
||||
- `/status` 及 `/subscribe-player-status` 的可用字段名添加了 `lyricLineAllText`,它对应的值是当前句歌词及扩展歌词文本(扩展歌词包含翻译、罗马音等,按换行符分割)
|
||||
|
||||
详情看开放API接入文档
|
||||
|
||||
### 其他
|
||||
|
||||
- 更新 electron 到 v28.3.3
|
||||
|
||||
## [2.7.0](https://github.com/lyswhut/lx-music-desktop/compare/v2.6.0...v2.7.0) - 2024-04-14
|
||||
|
||||
### 新增
|
||||
|
||||
- 主题编辑器添加“深色字体”选项,启用后将减少字体颜色梯度,各类字体(正文、标签字体等)颜色将更接近,这有助于解决创建全透明主题时可能出现的字体配色问题(#1799)
|
||||
- 新增在线自定义源导入功能,允许通过http/https链接导入自定义源
|
||||
- 新增HTTP开放API服务,默认关闭,该服务可以为第三方软件提供调用LX的能力,可用API看[说明文档](https://lyswhut.github.io/lx-music-doc/desktop/open-api)(#1824)
|
||||
- 托盘菜单新增播放、切歌、收藏控制
|
||||
- 添加当前软件版本所对应的代码提交版本、提交时间的显示,可到设置-版本更新查看
|
||||
|
||||
### 优化
|
||||
|
||||
- 主题设置默认折叠其他主题以优化进入设置界面时的性能
|
||||
- 不再丢弃kg源逐行歌词(@helloplhm-qwq)
|
||||
- 支持kw源排行榜显示大小(revert @Folltoshe #1460)
|
||||
- 托盘菜单添加多语言支持(#1802)
|
||||
- 优化本地歌曲换源匹配机制
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复某些情况下歌曲加载时间过长时不会自动跳到下一首的问题
|
||||
- 修复mg歌词在某些情况下获取失败的问题(#1783)
|
||||
- 修复mg歌单搜索(@helloplhm-qwq)
|
||||
- 修复kg最新评论无法获取的问题(@helloplhm-qwq)
|
||||
- 修复更新超时弹窗在非更新阶段意外弹出的问题(#1797)
|
||||
- 修复网络代理设置没有对自定义源的网络请求生效的问题(#1814)
|
||||
|
||||
### 移除
|
||||
|
||||
- 移除未使用的网络代理设置用户名、密码设置,实际上在 v1.20.0 起这两个设置就没有在被内部使用
|
||||
|
||||
### 其他
|
||||
|
||||
- 更新 electron 到 v28.3.0
|
||||
|
||||
## [2.6.0](https://github.com/lyswhut/lx-music-desktop/compare/v2.5.0...v2.6.0) - 2024-02-01
|
||||
|
||||
提交祝大家新年快乐!
|
||||
|
||||
更新前需要注意:
|
||||
由于自定义源的调用方式变更,可能会导致某些第三方源停止工作,如果出现这种情况,你需要将LX回退到 v2.5.0
|
||||
|
||||
### 新增
|
||||
|
||||
- 若自定义源初始化失败,将会出现弹窗提示初始化失败的详情
|
||||
- 添加win7_x64架构的安装版安装包构建
|
||||
- 新增播放歌曲时阻止电脑休眠,默认启用,可到设置-播放设置关闭(#1563)
|
||||
|
||||
### 优化
|
||||
|
||||
- 更新zh-tw翻译
|
||||
- 自定义源列显示源版本号、作者名字
|
||||
- 优化列表全选机制,修复列表未获得焦点时仍然可以全选的问题
|
||||
- 优化搜索框交互逻辑,防止鼠标操作时意外搜索候选列表的内容
|
||||
- 添加对wy源某些歌曲有问题的歌词进行修复
|
||||
- 改进本地音乐在线信息的匹配机制
|
||||
- 优化任务下载状态显示,现在下载时若数据传输完成但数据写入未完成时会显示相应的状态
|
||||
- 添加对下载歌曲时封面图片大小的控制处理(#1609)
|
||||
- 添加创建同名列表时的二次确认(#1621)
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复备份文件无法导入json格式的问题
|
||||
- Windows、MacOS平台下的字体列表取消使用原生方式获取以修复某些字体应用后无效的问题(#1596)
|
||||
- 修复亮暗主题自动切换功能无效的问题(#1697)
|
||||
- 修复 MacOS 平台在 Finder 打开文件或目录时应用卡死的问题(#1684)
|
||||
- 修复下载模块在数据写入速度较慢的情况下出现任务及文件异常的问题
|
||||
- 修复临时列表变更会意外触发同步的问题
|
||||
- 修复最小化后再隐藏窗口时,托盘菜单的显示主界面功能异常的问题
|
||||
|
||||
### 变更
|
||||
|
||||
- 播放歌曲时默认会阻止系统进入休眠状态,若你不行软件阻止系统休眠,可以到设置-播放设置取消勾选“播放歌曲时阻止电脑休眠”设置
|
||||
|
||||
### 其他
|
||||
|
||||
- 移除所有内置源,由于收到腾讯投诉要求停止提供软件内置的连接到他们平台的在线播放及下载服务,所以从即日(2023年10月18日)起LX本身不再提供上述服务
|
||||
- 更新 electron 到 v25.9.8
|
||||
- 更新许可协议的排版,使其看起来更加清晰明了,更新数据来源原理说明
|
||||
|
||||
### 自定义源的不兼容变更与新增内容(源开发者需要看)
|
||||
|
||||
自定义源的调用方式已改变:
|
||||
|
||||
- 为了与移动端的调用方式统一,不再推荐使用 `window.lx` 对象(移动端无`window`对象),改用 `globalThis.lx`
|
||||
- `inited` 事件不再需要传递 `status` 属性,脚本运行过程中,在成功调用 `inited` 事件之前的任何首次未捕获的错误都将视为初始化失败,所以现在若想人为让脚本初始化失败,直接抛出一个错误即可
|
||||
- 新增 `globalThis.lx.env` 属性,桌面端环境固定为 `desktop`,移动端环境固定为 `mobile`
|
||||
- 新增 `globalThis.lx.currentScriptInfo` 对象,可以从这里获取解析后的脚本头部注释信息及脚本原始内容,具体可用属性看文档说明
|
||||
- `globalThis.lx.version` 属性更新到 `2.0.0`
|
||||
- 自定义源不再使用`script`标签的形式执行,若要获取脚本原始代码字符串需从 `globalThis.lx.currentScriptInfo.rawScript` 属性获取
|
||||
- 自定义源新增支持`local`源的`musicUrl`、`pic`、`lyric`的获取操作详情看自定义源文档说明
|
||||
|
||||
## [2.5.0](https://github.com/lyswhut/lx-music-desktop/compare/v2.4.1...v2.5.0) - 2023-09-28
|
||||
|
||||
落雪提前祝大家中秋快乐~🥮😘!
|
||||
|
||||
### 不兼容性变更
|
||||
|
||||
- 由于微软及Electron即将结束对 Windows 7、Windows 8 的支持,所以从这个版本起,LX的默认 Windows 版也不再支持这些版本的系统,但考虑到仍然有许多人使用 Windows 7,我们特别构建了能在 Windows 7 上使用的免安装版(文件名带win7),需要注意的是这个版本将缺乏安全更新,若非必要情况,不要使用该版本
|
||||
- 由于微软在 Windows 10 2004版本已删除对32位的OEM支持,所以在这个版本起,LX的默认 Windows 版已不再提供32位的支持
|
||||
- 更改构建的文件名格式,主要修改linux下deb、rpm文件命名格式
|
||||
|
||||
### 新增
|
||||
|
||||
- 新增Scheme URL对播放器的控制操作,新增的操作包含 播放、暂停、下一首、上一首等,详情看Scheme URL文档
|
||||
|
||||
### 优化
|
||||
|
||||
- 通过歌曲菜单添加不喜欢歌曲时需要二次确认防止手抖
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复音频输出设备设置在重启软件后被重置的问题(#1568)
|
||||
- 修复更换语言设置后源名称未更新的问题
|
||||
- 修复点击搜索、排行榜等在线列表歌曲右键菜单歌曲详情页会意外将该歌曲添加不喜欢的问题
|
||||
|
||||
### 其他
|
||||
|
||||
- 更新 electron 到 v25.8.3
|
||||
|
||||
## [2.4.1](https://github.com/lyswhut/lx-music-desktop/compare/v2.4.0...v2.4.1) - 2023-09-09
|
||||
|
||||
目前本项目的原始发布地址只有 **GitHub** 及 **蓝奏网盘** ,其他渠道均为第三方转载发布,可信度请自行鉴别。
|
||||
本项目无微信公众号之类的官方账号,谨防被骗。
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复 v2.4.0 的默认数据库版本号不对导致首次安装该版本的用户无法再次启动软件的问题
|
||||
|
||||
## [2.4.0](https://github.com/lyswhut/lx-music-desktop/compare/v2.3.0...v2.4.0) - 2023-09-09
|
||||
|
||||
目前本项目的原始发布地址只有 **GitHub** 及 **蓝奏网盘** ,其他渠道均为第三方转载发布,可信度请自行鉴别。
|
||||
本项目无微信公众号之类的官方账号,谨防被骗。
|
||||
|
||||
### 不兼容性变更
|
||||
|
||||
该版本修改了同步协议逻辑,同步功能至少需要PC端v2.4.0或移动端v1.1.0版本或同步服务v2.0.0才能连接使用。
|
||||
|
||||
### 新增
|
||||
|
||||
- 新增我的列表名右键菜单-排序歌曲-随机乱序功能,使用它可以对选中列表内歌曲进行随机重排(#1440)
|
||||
- 新增数据同步服务端模式已认证设备列表管理,该功能位置:设置-数据同步-服务端模式-已认证设备列表
|
||||
- 新增“不喜欢歌曲”功能,可以在我的列表或者在线列表内歌曲的右击菜单使用,还可以去“设置-其他”手动编辑不喜欢规则,注:“上一曲”、“下一曲”功能将跳过符合“不喜欢歌曲”规则的歌曲,但你仍可以手动播放这些歌曲
|
||||
- 新增同步功能对“不喜欢歌曲”列表的同步
|
||||
- 新增软件内快捷键“不喜欢该歌曲”设置,全局快捷键“收藏歌曲”、“取消收藏”、“不喜欢该歌曲”设置
|
||||
- 新增设置-播放设置-点击相同列表内的歌曲切歌时是否清空已播放列表(随机模式下列表内所有歌曲会重新参与随机)选项,默认关闭
|
||||
|
||||
### 优化
|
||||
|
||||
- 优化音效设置-环境音效启用、禁用时的操作效果显示,修复禁用环境音效时仍然可以调整增益、新增预设的问题
|
||||
- 过滤翻译歌词或罗马音歌词中只有“//”的行(#1499)
|
||||
- 点击打开歌单弹窗背景将不再自动关闭弹窗,防止选择输入框里的内容时意外关闭弹窗
|
||||
- 优化数据传输逻辑,列表同步指令使用队列机制,保证列表同步操作的顺序
|
||||
- 优化桌面歌词在开启 缩放当前播放的歌词 并关闭 延迟歌词滚动 时的歌词滚动位置计算问题,现在歌词滚动应该可以正确滚动到目标位置了
|
||||
- 优化歌词在短时间内快速播放时的滚动效果,现在遇到这种情况时滚动将更平滑
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复字体设置某些字体无法应用的问题
|
||||
- 修复搜索提示功能失效的问题(#1452, @Folltoshe)
|
||||
- 修复我的列表名右键菜单-排序歌曲按专辑名排序无效的问题(#1440)
|
||||
- 修复若路径存在 # 字符时,软件无法启动的问题
|
||||
- 修复搜索框在某些情况下输入内容后搜索时会自动清空的问题(#1472)
|
||||
- 修复某些tx源歌词因数据异常解析失败的问题
|
||||
- 修复windows平台下隐藏窗口后再显示时任务栏按钮丢失的问题
|
||||
- 修复首句歌词被提前播放的问题
|
||||
- 修复潜在导致列表数据不同步的问题
|
||||
- 修复kg无评论时的加载处理问题
|
||||
|
||||
### 变更
|
||||
|
||||
- 播放模式应该只适用于列表内的歌曲,所以单曲循环模式不应对“稍后播放”的歌曲有效,该行为现在与移动端一致
|
||||
- 随机模式下,通过点击与播放列表相同的列表切歌时,将不再清空已播放列表,即已播放的歌曲不再重新参与随机,若想恢复之前的行为可以去设置-播放设置启用清空已播放列表选项
|
||||
|
||||
### 其他
|
||||
|
||||
- 更新 electron 到 v22.3.23
|
||||
- 重构同步服务端功能部分代码,使其更易扩展新功能
|
||||
|
||||
## [2.3.0](https://github.com/lyswhut/lx-music-desktop/compare/v2.2.2...v2.3.0) - 2023-06-29
|
||||
|
||||
### 新增
|
||||
|
||||
- 新增音效设置(实验性功能),支持10段均衡器设置、内置的一些环境混响音效、音调升降调节、3D立体环绕音效(由于升降调需要实时处理音频数据,这会导致额外的CPU占用,已知问题:如果CPU资源不够时将处理导致任务堆积而出现声音异常,这时需要暂停播放一段时间等堆积的任务处理完毕再播放)
|
||||
- 播放速率设置面板新增是否音调补偿设置,在调整播放速率后,可以选择是否启用音调补偿,默认启用
|
||||
|
||||
### 优化
|
||||
|
||||
- Windows、MacOS平台下的字体列表改用原生方式获取,现在Windows平台下能显示当前已安装的更多类型字体了(注:MacOS平台未测,可用性未知)
|
||||
- 移除桌面歌词窗口透明边距,在Linux下的桌面歌词可以完全拖到贴合屏幕边缘了
|
||||
- 过滤嵌入、下载的翻译、罗马音歌词时间标签,与主歌词时间不匹配的歌词将被丢弃,防止出现原歌词与翻译歌词顺序错乱的问题(#1358)
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复列表名翻译显示
|
||||
- 修复因插入数字类型的ID导致其意外在末尾追加 .0 导致列表数据异常的问题,同时也可能导致同步数据丢失的问题(要完全修复这个问题还需要同时将移动端、同步服务更新到最新版本)
|
||||
- 修复下载时出现302错误的问题
|
||||
- 修复播放某些在线音频会没有声音的问题
|
||||
- 修复改变播放速率时会导致歌词报错的问题
|
||||
- 修复tx热门评论昵称被错误切割的问题 (#1397, By: @helloplhm-qwq, @Folltoshe)
|
||||
- 修复wy源热搜词失效的问题(#1401, @Folltoshe)
|
||||
- 修复Deepin 20下启用桌面歌词时可能会导致桌面卡死的问题(#1288)
|
||||
- 修复添加单首歌曲弹窗列表创建按钮无法取消的问题
|
||||
- 修复mg歌单搜索歌单播放数量显示问题
|
||||
- 修复tx翻译歌词解析丢失的问题(更新版本后需手动清理一次歌词缓存)
|
||||
|
||||
### 其他
|
||||
|
||||
- 更新 electron 到 v22.3.15
|
||||
|
||||
## [2.2.2](https://github.com/lyswhut/lx-music-desktop/compare/v2.2.1...v2.2.2) - 2023-05-01
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复在低版本Linux amd64系统上无法启动的问题(glibc版本要求过高导致的,采用内置预编译二进制文件的方式解决)
|
||||
- 修复添加歌曲弹窗默认列表名字显示问题
|
||||
|
||||
## [2.2.1](https://github.com/lyswhut/lx-music-desktop/compare/v2.2.0...v2.2.1) - 2023-05-01
|
||||
|
||||
### 优化
|
||||
|
||||
- 优化对系统Media Session的支持,现在切歌不会再会导致信息丢失的问题了
|
||||
- 启用桌面歌词时,取消对歌词窗口的聚焦
|
||||
- 增加kg歌单歌曲flac24bit显示(@helloplhm-qwq)
|
||||
- 增加tx源热门评论图片显示(@Folltoshe)
|
||||
- 优化更新弹窗弹出时机
|
||||
- 优化搜索框背景配色,使其适应高透明主题
|
||||
- 支持wy热门评论翻页
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复启用全局快捷键时与Media Session注册冲突的问题,启用全局快捷键时,不再注册媒体控制快捷键
|
||||
- 修复mg搜索不显示时长的问题(@Folltoshe)
|
||||
- 修复mg评论加载失败的问题(@Folltoshe)
|
||||
- 修复对存在错误时间标签的歌词的解析
|
||||
|
||||
### 其他
|
||||
|
||||
- 自定义源API utils对象新增`zlib.inflate`与`zlib.deflate`方法,API版本更新到 v1.3.0
|
||||
- 更新kg、tx、wy等平台排行榜列表
|
||||
- 更新 electron 到 v22.3.7
|
||||
|
||||
## [2.2.0](https://github.com/lyswhut/lx-music-desktop/compare/v2.1.2...v2.2.0) - 2023-03-26
|
||||
|
||||
从v2.2.0起,我们发布了一个独立版的[数据同步服务](https://github.com/lyswhut/lx-music-sync-server#readme),如果你有服务器,可以将其部署到服务器上作为私人多端同步服务使用,详情看该项目说明
|
||||
|
||||
### 不兼容性变更说明
|
||||
|
||||
- 同步功能,从这个版本起,数据同步功能至少需要移动端v1.0.0的版本才能连接,连接的地址格式也略有改变,详情看[文档说明](https://lyswhut.github.io/lx-music-doc/desktop/faq/sync)
|
||||
|
||||
### 新增
|
||||
|
||||
- 重构数据同步功能,新增客户端模式
|
||||
- 新增全屏时自动关闭歌词设置,默认开启,可以去设置-桌面歌词设置更改
|
||||
- 新增设置-桌面歌词设置-重置窗口设置功能,点击时会重置桌面歌词窗口大小及位置
|
||||
- 新增设置-其他-列表数据清理功能,点击时会清空已创建的所有列表及所有收藏的歌曲
|
||||
|
||||
### 优化
|
||||
|
||||
- 支持wy源flac hires歌曲类型的显示
|
||||
- 快捷键调整音量时每次加减2%音量改为4%(#1220)
|
||||
- 音量、播放模式等设置弹出式按钮在鼠标移到按钮上时将自动弹出设置内容,保留点击切换显示/隐藏
|
||||
- 支持kg源搜索列表、排行榜flac hires歌曲类型的显示(#1231, #1238 By @helloplhm-qwq, @Folltoshe)
|
||||
- 播放速率的粒度调整为0.01,范围0.6-2.0x
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复同步连接的处理问题
|
||||
- 修复记住播放进度的情况下,使用Scheme URL打开应用播放的歌曲进度没有被重置的问题
|
||||
- 修复使用酷狗码无法打开某些类型的歌单的问题
|
||||
- 修复tx源某些歌单因为歌曲信息缺失导致打开失败的问题
|
||||
- 修复连续选择时的初始选择歌曲位置被意外改变的问题
|
||||
|
||||
### 其他
|
||||
|
||||
- 更新 Electron 到v22.3.4
|
||||
|
||||
## [2.1.2](https://github.com/lyswhut/lx-music-desktop/compare/v2.1.1...v2.1.2) - 2023-02-18
|
||||
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复处于最新版本时更新弹窗日志内容显示异常的问题
|
||||
- 修复更新到最新版本后的首次启动时的更新日志未显示的问题
|
||||
|
||||
## [2.1.1](https://github.com/lyswhut/lx-music-desktop/compare/v2.1.0...v2.1.1) - 2023-02-18
|
||||
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复检查更新日志地址不正确的问题
|
||||
|
||||
## [2.1.0](https://github.com/lyswhut/lx-music-desktop/compare/v2.0.5...v2.1.0) - 2023-02-18
|
||||
|
||||
由于软件内功能在设计时只考虑简单便捷性,是否对新手友好并不是我们考虑的重点,功能的新增、变更会在更新日志中注明,不会在软件内做指引提示,
|
||||
因此为了更愉快地使用本软件,我们建议在使用新版本时阅读一遍更新日志以了解软件的变更情况,同时若遇到问题可以去阅读常见问题找解决方案
|
||||
|
||||
### 新增
|
||||
|
||||
- 新增桌面歌词设置字体加粗设置,可以到设置-桌面歌词设置-加粗字体修改
|
||||
- 新增是否自动下载更新设置,默认开启,可以去设置-软件更新更改
|
||||
- 新增当前版本更新日志显示弹窗(建议大家阅读更新日志以了解当前版本的变化),在更新版本后将自动弹出
|
||||
- 新增是否在更新版本的首次启动时显示更新日志弹窗设置,默认开启,可以去设置-软件更新更改
|
||||
- 新增播放速率调整功能,可以去播放详情页的控制按钮调整,范围限制为x0.5至x2之间(#13)
|
||||
- 添加wy、tx源(感谢某位不愿透露姓名的大佬提供的C++算法源码,但由于作者不希望公开,所以将会以预构建二进制文件的形式加入代码仓库中)逐字歌词的支持
|
||||
- 新增设置-下载设置-是否嵌入翻译歌词、罗马音歌词设置,默认关闭
|
||||
- 添加启动时的数据库表及表结构完整性校验,若未通过校验,则会显示弹窗提示后将该数据库重命名添加`.bak`后缀后重建数据库启动。对于某些人遇到更新到v2.0.0后出现之前收藏的歌曲全部丢失或者歌曲无法添加到列表的问题,可以通过此特性自动重建数据库并重新迁移数据,不再需要手动去数据目录删除数据库
|
||||
|
||||
### 优化
|
||||
|
||||
- 微调了桌面歌词逐行字体阴影,使其看起来更匀称
|
||||
- 调整了桌面歌词在启用滚动到顶部时的距离,现在滚动到顶部的歌词更靠边,不再受字体大小、歌词间距影响
|
||||
- 优化更新弹窗内容的显示,添加了自动更新失败时的更新指引
|
||||
- 为所有文本输入框添加右键快速粘贴的功能,右击输入框可以自动粘贴剪贴板的文字,若选中文字时将粘贴并替换选中文字
|
||||
- 防止桌面歌词窗口在屏幕分辨率变小时,窗口位置跟随分辨率变化的问题,现在若屏幕分辨率变小后窗口位置仍会在原始分辨率的位置(添加这个机制是为了解决屏幕分辨率被临时调整时的位置更新问题,如运行某些低分辨率的全屏游戏、高分辨率外接屏幕休眠时),但若你的分辨率调整不是临时的,因窗口在原始位置导致看不到窗口可以开关桌面歌词即可重新自动调节回屏幕内
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复播放下载列表的歌曲时,调整歌词偏移时间功能异常的问题
|
||||
- 修复较旧Linux arm64系统下无法启动软件的问题(将预构建模块的所需glibc版本降级到2.28)(#1161)
|
||||
- 修改列表响应式更新机制,尝试修复偶现的删除歌曲列表未更新的问题
|
||||
- 修复某些kg歌单链接无法打开的问题
|
||||
- 修复将桌面歌词放到屏幕边缘时,偶现的开启桌面歌词后出现歌词窗口位置出现少许偏移的问题,以及将歌词窗口调整到全屏大小后,重开桌面歌词窗口被缩小出现边距的问题
|
||||
|
||||
### 其他
|
||||
|
||||
- 更新Electron到v22.3.0
|
||||
|
||||
## [2.0.5](https://github.com/lyswhut/lx-music-desktop/compare/v2.0.4...v2.0.5) - 2023-01-18
|
||||
|
||||
这应该是LX今年的最后一个版本,提前祝大家新年快乐~😘
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复声音输出设备更改时后的自动暂停播放设置无效的问题
|
||||
- 重写桌面歌词窗口坐标的计算逻辑,修复桌面歌词移动到最边缘时,某些情况下在启用歌词后会出现窗口偏移的问题(远古bug了)
|
||||
- 修复随机播放模式下使用稍后播放功能播放我的列表的歌曲时,切换下一曲永远是当前歌曲的问题(#1147)
|
||||
- 修复macOS下的软件系统菜单中的退出功能不会完全退出软件的问题(#1148)
|
||||
|
||||
## [2.0.4](https://github.com/lyswhut/lx-music-desktop/compare/v2.0.3...v2.0.4) - 2023-01-15
|
||||
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复备份文件导入指引无法识别v2配置的问题
|
||||
- 修复从搜索界面进入歌单详情后,若启用强迫症设置的清空功能会导致意外清空搜索框、搜索列表的问题
|
||||
- 修复桌面歌词在启用卡拉OK歌词后字体边缘可能被截断的问题(特别是纵向歌词某些字的边角被截断导致后面的阴影露出来或阴影不均匀的问题)
|
||||
- 修复桌面歌词启用歌词缩放后的阴影显示问题
|
||||
- 修复Linux armv7l系统(如树莓派)下无法启动的问题(与修复Linux arm64的方法一样采用内置预编译模块的方式修复)
|
||||
- 修复备份与恢复的列表导入列表信息设置逻辑问题与潜在导入问题
|
||||
|
||||
## [2.0.3](https://github.com/lyswhut/lx-music-desktop/compare/v2.0.2...v2.0.3) - 2023-01-08
|
||||
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复初始设置的桌面歌词窗口没有完全居右下角的问题
|
||||
- 修复Linux arm64系统下无法启动的问题(#1102)
|
||||
- 修复桌面歌词使用斜体出现截断的问题(#1106)
|
||||
- 修复某些情况下歌词的滚动问题
|
||||
- 修复禁用切歌时歌曲播放完毕后的歌曲信息显示问题
|
||||
- 修复修改播放设置-音频输出设置后,所做的更改没有被保存的问题
|
||||
|
||||
### 优化
|
||||
|
||||
- 点击打开歌单弹窗背景可以关闭弹窗(#1096)
|
||||
|
||||
## [2.0.2](https://github.com/lyswhut/lx-music-desktop/compare/v2.0.1...v2.0.2) - 2023-01-02
|
||||
|
||||
若你更新v2.0.0后,出现之前收藏的歌曲全部丢失或者歌曲无法添加到列表播放的问题,可以按以下方式解决:
|
||||
|
||||
1. 根据你的平台类型,进入软件数据目录
|
||||
- Windows:`%APPDATA%/lx-music-desktop`
|
||||
- Linux:`$XDG_CONFIG_HOME/lx-music-desktop` 或 `~/.config/lx-music-desktop`
|
||||
- macOS:`~/Library/Application Support/lx-music-desktop`
|
||||
|
||||
2. 进入`LxDatas`目录,退出LX,删除`lx.data.db`文件,再启动软件即可
|
||||
|
||||
若以上操作仍然不行,可以加交流群或者在GitHub开issue反馈
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复无效的歌曲信息导致我的列表数据迁移失败的问题
|
||||
|
||||
## [2.0.1](https://github.com/lyswhut/lx-music-desktop/compare/v2.0.0...v2.0.1) - 2023-01-02
|
||||
|
||||
若你更新v2.0.0后,出现之前收藏的歌曲全部丢失或者歌曲无法添加到列表播放的问题,可以按以下方式解决:
|
||||
|
||||
1. 根据你的平台类型,进入软件数据目录
|
||||
- Windows:`%APPDATA%/lx-music-desktop`
|
||||
- Linux:`$XDG_CONFIG_HOME/lx-music-desktop` 或 `~/.config/lx-music-desktop`
|
||||
- macOS:`~/Library/Application Support/lx-music-desktop`
|
||||
|
||||
2. 进入`LxDatas`目录,退出LX,删除`lx.data.db`文件,再启动软件即可
|
||||
|
||||
若以上操作仍然不行,可以加交流群或者在GitHub开issue反馈
|
||||
|
||||
### 优化
|
||||
|
||||
- 单次执行所有sql语句,尝试解决某些情况下某些表没有成功创建的问题
|
||||
|
||||
## [2.0.0](https://github.com/lyswhut/lx-music-desktop/compare/v1.22.3...v2.0.0) - 2023-01-01
|
||||
|
||||
|
||||
### 不兼容性变更说明
|
||||
|
||||
- 数据迁移,升级此版本时,会使用旧版本的我的列表、下载设置、快捷键设置、自定义源等数据会自动迁移到新的数据格式版本,旧的数据仍然会保留,但下载列表的数据不做迁移
|
||||
- 备份文件,v2.0.0及以后版本导出的列表、配置不支持导入v2.0.0之前版本,但v2.0.0之前版本导出的列表、配置支持导入v2.0.0以及以后版本(移动端需v0.15.0起才支持导入PC端v2生成的备份数据)
|
||||
- 同步功能,该功能不支持与移动端v1.0.0之前版本的使用,需等待后面的新版移动端,目前移动端v1的开发工作已在进行中
|
||||
|
||||
### 新增
|
||||
|
||||
- 新增自定义主题功能
|
||||
- 新增歌单搜索功能
|
||||
- 新增将本地歌曲添加到我的列表的支持,此功能可以在列表的右击菜单中使用(本地歌曲的歌词优先尝试读取相同路径下的同名歌词文件,若文件不存在则尝试读取歌曲文件内的歌词,若还是找不到歌词则尝试利用换源功能获取在线歌词,歌曲封面则是尝试读取歌曲文件内的封面,若不存在则利用换源功能获取在线封面)
|
||||
- 启动软件时自动回到上次的界面,例如上次退出软件时在我的列表,下次启动软件时会自动进入我的列表
|
||||
- 新增启动软件时自动播放音乐设置,默认关闭,可去设置-播放设置开启
|
||||
- 新增“蛋雅深藍”、“近墨者黑”皮肤
|
||||
- 新增下载歌词时是否同时下载歌词翻译、罗马音设置,默认关闭,可以去设置-下载设置开启(#344)
|
||||
- 新增下载时,若目录存在同名的文件时是否跳过下载此任务的设置(默认跳过,可以去设置-下载设置更改)
|
||||
- 新增界面字体大小设置
|
||||
- 桌面歌词新增竖排歌词显示功能(#971)
|
||||
- 桌面歌词新增歌词对齐方式、是否不允许歌词换行、歌词颜色、滚动对齐方式、歌词间距设置
|
||||
- 桌面歌词新增歌曲频谱显示(得益于主窗口与桌面歌词进程通信的改进,可以将此功能以CPU使用率“相对较低”的方式带到桌面歌词中)
|
||||
- 桌面歌词新增在任务栏显示歌词进程设置(此设置用于在录屏软件无法捕获歌词窗口时的变通解决方法)(#1063)
|
||||
- 添加kg源罗马音歌词的支持(感谢@helloplhm-qwq)
|
||||
- 支持打开波点音乐歌单(需在酷我源打开)
|
||||
- 新增设置-基本设置-播放栏进度条样式设置(此版本默认使用迷你进度条样式,对于某些不喜欢该样式的人可以将其换成其他样式)
|
||||
- 添加kg源评论图片展示(感谢@helloplhm-qwq)
|
||||
|
||||
### 优化(界面/交互/功能)
|
||||
|
||||
- 调整软件界面及配色,使其更加清爽
|
||||
- 处于单曲循环、顺序播放、禁用切歌模式时,手动切歌将会按列表循环模式的逻辑处理切歌(#864)
|
||||
- 歌单右键菜单的“重复歌曲”扫描功能现在会将歌曲名字内的括号内容移除再对比,这可以有效找出歌曲的变体,例如:`突然的自我`、`突然的自我(Live)`、`突然的自我(女生版)`、`突然的自我(DJ版)`等都会被找出来(#987)
|
||||
- 允许更小的桌面歌词窗口高度,可以取消“不允许拖动到主屏幕之外”设置后,再启用“不允许歌词换行”、“置顶歌词”与“自动刷新置顶”等设置,把它拖动到任务栏上,当做任务栏歌词使用(具体可以按你想要的显示方式使用这些设置组合去调)
|
||||
|
||||
### 优化(程序)
|
||||
|
||||
- 优化程序启动性能,优化与程序交互的流畅度
|
||||
- 重构整个程序,重新梳理了程序逻辑,使其更容易扩展及维护,将大部分代码从JavaScript迁移到TypeScript
|
||||
- 重写配置管理、列表管理功能,列表、歌词数据从json文件迁移到sqlite3存储,这应该能解决因为意外的字符编码导致的数据文件损坏问题
|
||||
|
||||
### 变更
|
||||
|
||||
- 列表右侧的操作按钮栏默认不再显示,歌曲的操作可以使用右键菜单代替,若想恢复它们的显示,可以去设置-列表设置-启用操作按钮栏开启
|
||||
- 窗口大小设置时不再自动调整字体大小,想要调整字体大小可以使用新增的字体大小设置调整
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复Linux、macOS下若程序路径存在百分号时会导致软件无法启动的问题(#963)
|
||||
- 支持单行多时间标签歌词解析,修复某些歌词会出现时间标签的问题
|
||||
|
||||
### 移除
|
||||
|
||||
- 移除“信口雌黄”皮肤(由于该皮肤的配色有点刺眼),若你正在使用该皮肤,可以使用自定义主题功能恢复它
|
||||
- 移除Linux deb x86包构建,Electron/Chromium已不再支持 32-bit Linux(electron/electron#34787)
|
||||
- 移除桌面歌词主题设置,改用桌面歌词字体颜色设置功能代替
|
||||
|
||||
### 其他
|
||||
|
||||
- 更新Electron到v19.1.9
|
||||
|
||||
## [1.22.3](https://github.com/lyswhut/lx-music-desktop/compare/v1.22.2...v1.22.3) - 2022-09-03
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复因音源的域名到期导致的音源失效的问题
|
||||
|
||||
## [1.22.2](https://github.com/lyswhut/lx-music-desktop/compare/v1.22.1...v1.22.2) - 2022-08-18
|
||||
|
||||
### 优化
|
||||
|
||||
- 为tx、kw源添加 Flac 24bit 音质显示,注:由于之前没有记录此音质,所以之前收藏的歌曲信息中不包含它
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复无法批量排序歌曲的问题
|
||||
- 修复某些缺失的繁体中文翻译
|
||||
- 修复企鹅音乐搜索失效的问题
|
||||
|
||||
### 其他
|
||||
|
||||
- 降级electron到v15.5.7
|
||||
|
||||
## [1.22.1](https://github.com/lyswhut/lx-music-desktop/compare/v1.22.0...v1.22.1) - 2022-07-09
|
||||
|
||||
### 优化
|
||||
|
||||
- 歌单列表添加歌单内歌曲数量显示,注:目前只有kw、mg、wy、tx(部分)源支持显示
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复处于不支持的源时,歌单、排行榜的右键下载菜单没有禁用的问题
|
||||
- 修复若桌面歌词窗口与主窗口重叠时,鼠标划过重叠区域鼠标会闪烁的问题,注:此修复只对未启用“鼠标移入歌词区域时降低歌词透明度”时有效
|
||||
- 修复tx源搜索失效的问题
|
||||
|
||||
### 其他
|
||||
|
||||
- 升级Electron到 v17.4.10
|
||||
|
||||
## [1.22.0](https://github.com/lyswhut/lx-music-desktop/compare/v1.21.0...v1.22.0) - 2022-06-19
|
||||
|
||||
### 新增
|
||||
|
||||
34
FAQ.md
@@ -1,7 +1,8 @@
|
||||
# lx-music-desktop 常见问题
|
||||
|
||||
本文档已迁移到:<https://lyswhut.github.io/lx-music-doc/desktop/faq>
|
||||
本文档已迁移至:<https://lyswhut.github.io/lx-music-doc/desktop/faq>
|
||||
|
||||
<!--
|
||||
在阅读本常见问题后,仍然无法解决你的问题,请提交issue或者加企鹅群`830125506`反馈(无事勿加,入群先看群公告),反馈时请**注明**已阅读常见问题!
|
||||
|
||||
## ~~软件为什么没有桌面歌词与自定义列表功能~~
|
||||
@@ -49,7 +50,7 @@
|
||||
|
||||
### 提示 `getaddrinfo EAI_AGAIN ...` 或 `无法连接到服务器`
|
||||
|
||||
尝试在在浏览器打开这个地址`http://ts.tempmusic.tk`,浏览器显示404是正常的,如果不是404那就证明所在网络无法访问接口服务器。
|
||||
尝试在在浏览器打开这个地址`http://ts.tempmusics.tk`,浏览器显示404是正常的,如果不是404那就证明所在网络无法访问接口服务器。
|
||||
若网页无法打开或打开来不是404,则可能是DNS的问题,可以尝试以下办法:
|
||||
|
||||
1. 将DNS改成自动获取试试(注:改完可能需要清理下系统DNS缓存才生效)
|
||||
@@ -68,7 +69,7 @@
|
||||
5. 若还不行请到这个链接查看详情:<https://github.com/lyswhut/lx-music-desktop/issues/5>
|
||||
6. 若没有在第5条链接中的第一条评论中看到接口无法使用的说明,则应该是你网络无法访问接口服务器的问题,如果接口有问题我会在那里说明。
|
||||
|
||||
想要知道是不是自己网络的问题可以看看`http://ts.tempmusic.tk`能不能在浏览器打开,浏览器显示404是正常的,如果不是404那就证明所在网络无法访问接口服务器。
|
||||
想要知道是不是自己网络的问题可以看看`http://ts.tempmusics.tk`能不能在浏览器打开,浏览器显示404是正常的,如果不是404那就证明所在网络无法访问接口服务器。
|
||||
若网页无法打开或打来不是404,则应该是DNS的问题,可以尝试以下办法:
|
||||
|
||||
1. 将DNS改成自动获取试试
|
||||
@@ -178,6 +179,23 @@
|
||||
|
||||
## 界面异常(界面显示不完整)
|
||||
|
||||
### Windows 10、11界面异常、界面无法显示
|
||||
|
||||
尝试添加运行参数 `--disable-gpu-sandbox` 启动,例如:`.\lx-music-desktop.exe --disable-gpu-sandbox`,添加方法可自行百度“给快捷方式加参数”。
|
||||
|
||||
若以上方法无效,则尝试将 `--disable-gpu-sandbox` 逐个换成以下参数启动,直到恢复正常为止:
|
||||
|
||||
- `--no-sandbox`
|
||||
- `-dha`
|
||||
- `--disable-gpu`
|
||||
|
||||
:::caution
|
||||
这些参数会禁用程序的某些安全特性或降低程序性能,没有遇到问题不要使用它们!
|
||||
:::
|
||||
|
||||
对于界面无法显示,任务栏里也没看到图标,但是任务管理器里面看到进程的问题,还可尝试更换软件安装目录(对于安装版需要先卸载再换目录安装,绿色版直接剪切移动即可,只要目录换了就行),<br />
|
||||
此方法的相关讨论看:<https://github.com/lyswhut/lx-music-desktop/issues/943#issuecomment-1217832186>
|
||||
|
||||
### Windows 7 下界面异常
|
||||
|
||||
由于软件默认使用了透明窗口,根据Electron官方文档的[说明](https://www.electronjs.org/docs/latest/tutorial/window-customization#limitations):
|
||||
@@ -352,7 +370,7 @@ Windows 7 未开启 Aero 效果时桌面歌词会有问题,详情看上面的
|
||||
|
||||
- URL统一以`lxmusic://`开头
|
||||
- 若无特别说明,源的可用值为:`kw/kg/tx/wy/mg`
|
||||
- 若无特别说明,音质的可用值为:`128k/320k/flac/flac32bit`
|
||||
- 若无特别说明,音质的可用值为:`128k/320k/flac/flac24bit`
|
||||
|
||||
目前支持两种传参方式:
|
||||
|
||||
@@ -447,7 +465,7 @@ send(EVENT_NAMES.inited, {
|
||||
name: '酷我音乐',
|
||||
type: 'music', // 目前固定为 music
|
||||
actions: ['musicUrl'], // 目前固定为 ['musicUrl']
|
||||
qualitys: ['128k', '320k', 'flac'], // 当前脚本的该源所支持获取的Url音质,有效的值有:['128k', '320k', 'flac']
|
||||
qualitys: ['128k', '320k', 'flac', 'flac24bit'], // 当前脚本的该源所支持获取的Url音质,有效的值有:['128k', '320k', 'flac', 'flac24bit']
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -489,8 +507,8 @@ send(EVENT_NAMES.inited, {
|
||||
|
||||
| 事件名 | 描述
|
||||
| --- | ---
|
||||
| `inited` | 脚本初始化完成后发送给应用的事件名,发送该事件时需要传入以下信息:`{status, sources, openDevTools}`<br>`status`:初始化结果(`true`成功,`false`失败)<br>`openDevTools`:是否打开DevTools,此选项可用于开发脚本时的调试<br>`sources`:支持的源信息对象,<br>`sources[kw/kg/tx/wy/mg].name`:源的名字(目前非必须)<br>`sources[kw/kg/tx/wy/mg].type`:源类型,目前固定值需为`music`<br>`sources[kw/kg/tx/wy/mg].actions`:支持的actions,由于目前只支持`musicUrl`,所以固定传`['musicUrl']`即可<br>`sources[kw/kg/tx/wy/mg].qualitys`:该源支持的音质列表,有效的值为`['128k', '320k', 'flac']`,该字段用于控制应用可用的音质类型
|
||||
| `request` | 应用API请求事件名,回调入参:`handler({ source, action, info})`,回调必须返回`Promise`对象<br>`source`:音乐源,可能的值取决于初始化时传入的`sources`对象的源key值<br>`info`:请求附加信息,内容根据`action`变化<br>`action`:请求操作类型,目前只有`musicUrl`,即获取音乐URL链接,需要在 Promise 返回歌曲 url,`info`的结构:`{type, musicInfo}`,`info.type`:音乐质量,可能的值有`128k` / `320k` / `flac`(取决于初始化时对应源传入的`qualitys`值中的一个),`info.musicInfo`:音乐信息对象,里面有音乐ID、名字等信息
|
||||
| `inited` | 脚本初始化完成后发送给应用的事件名,发送该事件时需要传入以下信息:`{status, sources, openDevTools}`<br>`status`:初始化结果(`true`成功,`false`失败)<br>`openDevTools`:是否打开DevTools,此选项可用于开发脚本时的调试<br>`sources`:支持的源信息对象,<br>`sources[kw/kg/tx/wy/mg].name`:源的名字(目前非必须)<br>`sources[kw/kg/tx/wy/mg].type`:源类型,目前固定值需为`music`<br>`sources[kw/kg/tx/wy/mg].actions`:支持的actions,由于目前只支持`musicUrl`,所以固定传`['musicUrl']`即可<br>`sources[kw/kg/tx/wy/mg].qualitys`:该源支持的音质列表,有效的值为`['128k', '320k', 'flac', 'flac24bit']`,该字段用于控制应用可用的音质类型
|
||||
| `request` | 应用API请求事件名,回调入参:`handler({ source, action, info})`,回调必须返回`Promise`对象<br>`source`:音乐源,可能的值取决于初始化时传入的`sources`对象的源key值<br>`info`:请求附加信息,内容根据`action`变化<br>`action`:请求操作类型,目前只有`musicUrl`,即获取音乐URL链接,需要在 Promise 返回歌曲 url,`info`的结构:`{type, musicInfo}`,`info.type`:音乐质量,可能的值有`128k` / `320k` / `flac` / `flac24bit`(取决于初始化时对应源传入的`qualitys`值中的一个),`info.musicInfo`:音乐信息对象,里面有音乐ID、名字等信息
|
||||
| `updateAlert` | 显示源更新弹窗,发送该事件时的参数:`{log, updateUrl}`<br>`log`:更新日志,必传,字符串类型,内容可以使用`\n`换行,最大长度1024,超过此长度后将被截取超出的部分<br>`updateUrl`:更新地址,用于引导用户去该地址更新源,选传,需为http协议的url地址,最大长度1024<br>此事件每次运行脚本只能调用一次(源版本v1.2.0新增)<br>例子:`lx.send(lx.EVENT_NAMES.updateAlert, { log: 'hello world', updateUrl: 'https://xxx.com' })`
|
||||
|
||||
|
||||
@@ -545,4 +563,4 @@ const cancelHttp = window.lx.request(url, options, callback)
|
||||
- `window.lx.utils.crypto.randomBytes`:生成随机字符串 `randomBytes(size)`
|
||||
- `window.lx.utils.crypto.rsaEncrypt`:RSA加密 `rsaEncrypt(buffer, key)`
|
||||
|
||||
目前仅提供以上工具方法,如果需要其他方法可以开issue讨论。
|
||||
目前仅提供以上工具方法,如果需要其他方法可以开issue讨论。 -->
|
||||
|
||||
153
README.md
@@ -1,5 +1,7 @@
|
||||
<p align="center"><a href="https://github.com/lyswhut/lx-music-desktop"><img width="200" src="https://github.com/lyswhut/lx-music-desktop/blob/master/doc/images/icon.png" alt="lx-music logo"></a></p>
|
||||
|
||||
<h1 align="center">LX Music 桌面版</h1>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/lyswhut/lx-music-desktop/releases"><img src="https://img.shields.io/github/release/lyswhut/lx-music-desktop" alt="Release version"></a>
|
||||
<a href="https://github.com/lyswhut/lx-music-desktop/actions/workflows/release.yml"><img src="https://github.com/lyswhut/lx-music-desktop/workflows/Build/badge.svg" alt="Build status"></a>
|
||||
@@ -28,104 +30,133 @@
|
||||
[9]: https://img.shields.io/github/license/lyswhut/lx-music-desktop
|
||||
[10]: https://github.com/lyswhut/lx-music-desktop/blob/master/LICENSE -->
|
||||
|
||||
<h2 align="center">洛雪音乐助手桌面版</h2>
|
||||
<p align="center">一个基于 Electron & Vue 开发的音乐软件</p>
|
||||
|
||||
### 说明
|
||||
|
||||
一个基于 Electron + Vue 开发的音乐软件。
|
||||
## 说明
|
||||
|
||||
所用技术栈:
|
||||
|
||||
- Electron 17
|
||||
- Electron 30+
|
||||
- Vue 3
|
||||
|
||||
已支持的平台:
|
||||
|
||||
- Windows 7 及以上
|
||||
- Mac OS
|
||||
- Linux
|
||||
- macOS
|
||||
- Windows 7 及以上
|
||||
|
||||
软件变化请查看:[更新日志](https://github.com/lyswhut/lx-music-desktop/blob/master/CHANGELOG.md)<br>
|
||||
软件下载请转到:[发布页面](https://github.com/lyswhut/lx-music-desktop/releases)<br>
|
||||
或者到网盘下载(网盘内有MAC、windows版):`https://www.lanzoui.com/b0bf2cfa/` 密码:`glqw`(若链接无法打开请百度:蓝奏云链接打不开)<br>
|
||||
使用常见问题请转至:[常见问题](https://lyswhut.github.io/lx-music-doc/desktop/faq)<br>
|
||||
移动版项目地址:<https://github.com/lyswhut/lx-music-mobile>
|
||||
*移动版项目地址:https://github.com/lyswhut/lx-music-mobile*
|
||||
|
||||
#### Scheme URL支持
|
||||
*LX Music 项目发展调整与新项目计划:https://github.com/lyswhut/lx-music-desktop/issues/1912*
|
||||
|
||||
从v1.17.0起支持 Scheme URL,可以使用此功能从浏览器等场景下调用LX Music,我们开发了一个[油猴脚本](https://github.com/lyswhut/lx-music-script#readme)配套使用,<br>
|
||||
脚本安装地址:<https://greasyfork.org/zh-CN/scripts/438148><br>
|
||||
软件变化请查看[更新日志](https://github.com/lyswhut/lx-music-desktop/blob/master/CHANGELOG.md)。
|
||||
|
||||
若你想自己调用LX Music,可以看[Scheme URL支持](https://lyswhut.github.io/lx-music-doc/desktop/scheme-url)
|
||||
软件下载请查看 [GitHub Releases](https://github.com/lyswhut/lx-music-desktop/releases)。
|
||||
|
||||
#### 启动参数
|
||||
使用常见问题请参阅[桌面版常见问题](https://lyswhut.github.io/lx-music-doc/desktop/faq)。
|
||||
|
||||
目前软件已支持的启动参数如下:
|
||||
目前本项目的原始发布地址只有 [**GitHub**](https://github.com/lyswhut/lx-music-desktop/releases),其他渠道均为第三方转载发布,与本项目无关!
|
||||
|
||||
- `-proxy-server` 设置代理服务器,代理应用的所有流量
|
||||
- `-proxy-bypass-list` 以分号分隔的主机列表绕过代理服务器
|
||||
- `-play` 启动时播放指定列表的音乐
|
||||
- `-search` 启动软件时自动在搜索框搜索指定的内容
|
||||
- `-dha` 禁用硬件加速启动(Disable Hardware Acceleration)
|
||||
- `-dt` 以非透明模式启动(Disable Transparent)
|
||||
- `-dhmkh` 禁用硬件媒体密钥处理(Disable Hardware Media Key Handling)
|
||||
为了提高使用门槛,本软件内的默认设置、UI 操作不以新手友好为目标,所以使用前建议先根据你的喜好浏览调整一遍软件设置,阅读一遍[音乐播放列表机制](https://lyswhut.github.io/lx-music-doc/desktop/faq/playlist)及[可用的鼠标、键盘快捷操作](https://lyswhut.github.io/lx-music-doc/desktop/faq/hotkey)。
|
||||
|
||||
启动参数的详细说明请看[启动参数说明](https://lyswhut.github.io/lx-music-doc/desktop/run-params)
|
||||
### Scheme URL 支持
|
||||
|
||||
#### 数据存储路径
|
||||
从 v1.17.0 起支持 Scheme URL,可以使用此功能在浏览器等场景下调用 LX Music,我们开发了一个[油猴脚本](https://github.com/lyswhut/lx-music-script#readme)配套使用。
|
||||
|
||||
脚本安装地址:[LX Music 辅助脚本](https://greasyfork.org/zh-CN/scripts/438148)。
|
||||
|
||||
若你想自己调用 LX Music,可以参考文档「[Scheme URL 支持](https://lyswhut.github.io/lx-music-doc/desktop/scheme-url)」部分。
|
||||
|
||||
### 数据同步服务
|
||||
|
||||
从 v2.2.0 起,我们发布了一个独立的[数据同步服务](https://github.com/lyswhut/lx-music-sync-server#readme)。如果你有服务器,可以将其部署到服务器上作为私人多端同步服务使用,详情看该项目说明。
|
||||
|
||||
### 开放 API 支持
|
||||
|
||||
从 v2.7.0 起支持开放 API 服务。启用该功能后,将会在本地启动一个 HTTP 服务,提供播放器相关的接口供第三方软件调用,详情看文档「[开放 API 服务](https://lyswhut.github.io/lx-music-doc/desktop/open-api)」部分。
|
||||
|
||||
### 数据存储目录
|
||||
|
||||
默认情况下,软件的数据存储在:
|
||||
|
||||
- Windows:`%APPDATA%/lx-music-desktop`
|
||||
- Linux:`$XDG_CONFIG_HOME/lx-music-desktop` 或 `~/.config/lx-music-desktop`
|
||||
- macOS:`~/Library/Application Support/lx-music-desktop`
|
||||
- Windows:`%APPDATA%/lx-music-desktop`
|
||||
|
||||
在Windows平台下,若程序目录下存在`portable`目录,则自动使用此目录作为数据存储目录(v1.17.0新增)。
|
||||
在 Windows 平台上,若程序文件夹中存在 `portable` 文件夹,则自动使用此文件夹作为数据存储文件夹(适用于 v1.17.0 及以上版本)。
|
||||
|
||||
### 源码使用方法
|
||||
## 用户界面
|
||||
|
||||
环境要求:Node.js 16+
|
||||
<p><img width="100%" src="./doc/images/app.png" alt="lx-music desktop UI"></p>
|
||||
|
||||
```bash
|
||||
# 开发模式
|
||||
npm run dev
|
||||
## 贡献代码
|
||||
|
||||
# 构建免安装版
|
||||
npm run pack:dir
|
||||
本项目欢迎 PR,但为了 PR 能顺利合并,需要注意以下几点:
|
||||
|
||||
# 构建安装包(Windows版)
|
||||
npm run pack:win
|
||||
- 对于添加新功能的 PR,建议在提交 PR 前先创建 Issue 进行说明,以确认该功能是否确实需要。
|
||||
- 对于修复 bug 的 PR,请提供修复前后的说明及重现方式。
|
||||
- 对于其他类型的 PR,则适当附上说明。
|
||||
|
||||
# 构建安装包(Mac版)
|
||||
npm run pack:mac
|
||||
贡献代码步骤:
|
||||
|
||||
# 构建安装包(Linux版)
|
||||
npm run pack:linux
|
||||
1. 参照[源码使用方法](https://lyswhut.github.io/lx-music-doc/desktop/use-source-code)设置开发环境;
|
||||
2. 克隆本仓库代码并切换至 `dev` 分支进行开发;
|
||||
3. 提交 PR 至 `dev` 分支。
|
||||
|
||||
```
|
||||
## 源码使用方法
|
||||
|
||||
### UI界面
|
||||
请参阅:<https://lyswhut.github.io/lx-music-doc/desktop/use-source-code>
|
||||
|
||||
<p><a href="https://github.com/lyswhut/lx-music-desktop"><img width="100%" src="https://github.com/lyswhut/lx-music-desktop/blob/master/doc/images/app.png" alt="lx-music UI"></a></p>
|
||||
|
||||
### 常见问题
|
||||
|
||||
常见问题已移至:<https://lyswhut.github.io/lx-music-doc/desktop/faq>
|
||||
|
||||
### 项目协议
|
||||
## 项目协议
|
||||
|
||||
本项目基于 [Apache License 2.0](https://github.com/lyswhut/lx-music-desktop/blob/master/LICENSE) 许可证发行,以下协议是对于 Apache License 2.0 的补充,如有冲突,以以下协议为准。
|
||||
|
||||
词语约定:本协议中的“本项目”指洛雪音乐桌面版项目;“使用者”指签署本协议的使用者;“官方音乐平台”指对本项目内置的包括酷我、酷狗、咪咕等音乐源的官方平台统称;“版权数据”指包括但不限于图像、音频、名字等在内的他人拥有所属版权的数据。
|
||||
---
|
||||
|
||||
1. 本项目的数据来源原理是从各官方音乐平台的公开服务器中拉取数据,经过对数据简单地筛选与合并后进行展示,因此本项目不对数据的准确性负责。
|
||||
2. 使用本项目的过程中可能会产生版权数据,对于这些版权数据,本项目不拥有它们的所有权,为了避免造成侵权,使用者务必在**24小时**内清除使用本项目的过程中所产生的版权数据。
|
||||
3. 本项目内的官方音乐平台别名为本项目内对官方音乐平台的一个称呼,不包含恶意,如果官方音乐平台觉得不妥,可联系本项目更改或移除。
|
||||
4. 本项目内使用的部分包括但不限于字体、图片等资源来源于互联网,如果出现侵权可联系本项目移除。
|
||||
5. 由于使用本项目产生的包括由于本协议或由于使用或无法使用本项目而引起的任何性质的任何直接、间接、特殊、偶然或结果性损害(包括但不限于因商誉损失、停工、计算机故障或故障引起的损害赔偿,或任何及所有其他商业损害或损失)由使用者负责。
|
||||
6. 本项目完全免费,且开源发布于 GitHub 面向全世界人用作对技术的学习交流,本项目不对项目内的技术可能存在违反当地法律法规的行为作保证,**禁止在违反当地法律法规的情况下使用本项目**,对于使用者在明知或不知当地法律法规不允许的情况下使用本项目所造成的任何违法违规行为由使用者承担,本项目不承担由此造成的任何直接、间接、特殊、偶然或结果性责任。
|
||||
*词语约定:本协议中的“本项目”指 LX Music(洛雪音乐助手)桌面版项目;“使用者”指签署本协议的使用者;“官方音乐平台”指对本项目内置的包括酷我、酷狗、咪咕等音乐源的官方平台统称;“版权数据”指包括但不限于图像、音频、名字等在内的他人拥有所属版权的数据。*
|
||||
|
||||
若你使用了本项目,将代表你接受以上协议。
|
||||
### 一、数据来源
|
||||
|
||||
音乐平台不易,请尊重版权,支持正版。<br>
|
||||
若对此有疑问请 mail to: lyswhut+qq.com (请将`+`替换成`@`)
|
||||
1.1 本项目的各官方平台在线数据来源原理是从其公开服务器中拉取数据(与未登录状态在官方平台 APP 获取的数据相同),经过对数据简单地筛选与合并后进行展示,因此本项目不对数据的合法性、准确性负责。
|
||||
|
||||
1.2 本项目本身没有获取某个音频数据的能力,本项目使用的在线音频数据来源来自软件设置内“自定义源”设置所选择的“源”返回的在线链接。例如播放某首歌,本项目所做的只是将希望播放的歌曲名、艺术家等信息传递给“源”,若“源”返回了一个链接,则本项目将认为这就是该歌曲的音频数据而进行使用,至于这是不是正确的音频数据本项目无法校验其准确性,所以使用本项目的过程中可能会出现希望播放的音频与实际播放的音频不对应或者无法播放的问题。
|
||||
|
||||
1.3 本项目的非官方平台数据(例如“我的列表”内列表)来自使用者本地系统或者使用者连接的同步服务,本项目不对这些数据的合法性、准确性负责。
|
||||
|
||||
### 二、版权数据
|
||||
|
||||
2.1 使用本项目的过程中可能会产生版权数据。对于这些版权数据,本项目不拥有它们的所有权。为了避免侵权,使用者务必在 **24 小时内** 清除使用本项目的过程中所产生的版权数据。
|
||||
|
||||
### 三、音乐平台别名
|
||||
|
||||
3.1 本项目内的官方音乐平台别名为本项目内对官方音乐平台的一个称呼,不包含恶意。如果官方音乐平台觉得不妥,可联系本项目更改或移除。
|
||||
|
||||
### 四、资源使用
|
||||
|
||||
4.1 本项目内使用的部分包括但不限于字体、图片等资源来源于互联网。如果出现侵权可联系本项目移除。
|
||||
|
||||
### 五、免责声明
|
||||
|
||||
5.1 由于使用本项目产生的包括由于本协议或由于使用或无法使用本项目而引起的任何性质的任何直接、间接、特殊、偶然或结果性损害(包括但不限于因商誉损失、停工、计算机故障或故障引起的损害赔偿,或任何及所有其他商业损害或损失)由使用者负责。
|
||||
|
||||
### 六、使用限制
|
||||
|
||||
6.1 本项目完全免费,且开源发布于 GitHub 面向全世界人用作对技术的学习交流。本项目不对项目内的技术可能存在违反当地法律法规的行为作保证。
|
||||
|
||||
6.2 **禁止在违反当地法律法规的情况下使用本项目。** 对于使用者在明知或不知当地法律法规不允许的情况下使用本项目所造成的任何违法违规行为由使用者承担,本项目不承担由此造成的任何直接、间接、特殊、偶然或结果性责任。
|
||||
|
||||
### 七、版权保护
|
||||
|
||||
7.1 音乐平台不易,请尊重版权,支持正版。
|
||||
|
||||
### 八、非商业性质
|
||||
|
||||
8.1 本项目仅用于对技术可行性的探索及研究,不接受任何商业(包括但不限于广告等)合作及捐赠。
|
||||
|
||||
### 九、接受协议
|
||||
|
||||
9.1 若你使用了本项目,即代表你接受本协议。
|
||||
|
||||
---
|
||||
|
||||
若对此有疑问请 mail to: lyswhut+qq.com (请将 `+` 替换为 `@`)
|
||||
|
||||
25
build-config/build-after-pack.js
Normal file
@@ -0,0 +1,25 @@
|
||||
const fs = require('fs').promises
|
||||
|
||||
// https://github.com/electron-userland/electron-builder/issues/4630
|
||||
// https://github.com/electron-userland/electron-builder/issues/4630#issuecomment-782020139
|
||||
|
||||
module.exports = async(context) => {
|
||||
const { electronPlatformName, appOutDir } = context
|
||||
if (electronPlatformName !== 'darwin') return
|
||||
const {
|
||||
productFilename,
|
||||
info: {
|
||||
_metadata: { macLanguagesInfoPlistStrings },
|
||||
},
|
||||
} = context.packager.appInfo
|
||||
|
||||
const resPath = `${appOutDir}/${productFilename}.app/Contents/Resources`
|
||||
|
||||
// 创建APP语言包文件
|
||||
return Promise.all(
|
||||
Object.entries(macLanguagesInfoPlistStrings).map(([lang, config]) => {
|
||||
let infos = Object.entries(config).map(([k, v]) => `"${k}" = "${v}";`).join('\n')
|
||||
return fs.writeFile(`${resPath}/${lang}.lproj/InfoPlist.strings`, infos)
|
||||
}),
|
||||
)
|
||||
}
|
||||
79
build-config/build-before-pack.js
Normal file
@@ -0,0 +1,79 @@
|
||||
const fs = require('fs')
|
||||
const fsPromises = require('fs').promises
|
||||
const path = require('path')
|
||||
const { Arch } = require('electron-builder')
|
||||
const nodeAbi = require('node-abi')
|
||||
|
||||
const better_sqlite3_fileNameMap = {
|
||||
[Arch.x64]: 'linux-x64',
|
||||
[Arch.arm64]: 'linux-arm64',
|
||||
[Arch.armv7l]: 'linux-arm',
|
||||
}
|
||||
|
||||
const qrc_decode_fileNameMap = {
|
||||
win32: {
|
||||
[Arch.x64]: 'win32-x64',
|
||||
[Arch.ia32]: 'win32-ia32',
|
||||
[Arch.arm64]: 'win32-arm64',
|
||||
},
|
||||
linux: {
|
||||
[Arch.x64]: 'linux-x64',
|
||||
[Arch.arm64]: 'linux-arm64',
|
||||
[Arch.armv7l]: 'linux-arm',
|
||||
},
|
||||
darwin: {
|
||||
[Arch.x64]: 'darwin-x64',
|
||||
[Arch.arm64]: 'darwin-arm64',
|
||||
},
|
||||
}
|
||||
|
||||
const replaceSqliteLib = async(electronNodeAbi, arch) => {
|
||||
// console.log(await fs.readdir(path.join(context.appOutDir, './resources/')))
|
||||
// if (context.electronPlatformName != 'linux' || context.arch != Arch.arm64) return
|
||||
// https://github.com/lyswhut/lx-music-desktop/issues/1102
|
||||
// https://github.com/lyswhut/lx-music-desktop/issues/1161
|
||||
console.log('replace sqlite lib...')
|
||||
const filePath = path.join(__dirname, `./lib/better_sqlite3_electron-v${electronNodeAbi}-${better_sqlite3_fileNameMap[arch]}.node`)
|
||||
console.log(filePath)
|
||||
const targetPath = path.join(__dirname, '../node_modules/better-sqlite3/build/Release/better_sqlite3.node')
|
||||
await fsPromises.unlink(targetPath).catch(_ => _)
|
||||
await fsPromises.copyFile(filePath, targetPath)
|
||||
}
|
||||
|
||||
const replaceQrcDecodeLib = async(electronNodeAbi, platform, arch) => {
|
||||
console.log('replace qrc_decode lib...', platform, electronNodeAbi, qrc_decode_fileNameMap[platform][arch])
|
||||
const filePath = path.join(__dirname, `./lib/qrc_decode_electron-v${electronNodeAbi}-${qrc_decode_fileNameMap[platform][arch]}.node`)
|
||||
const targetPath = path.join(__dirname, '../build/Release/qrc_decode.node')
|
||||
const targetDir = path.dirname(targetPath)
|
||||
if (fs.existsSync(targetDir)) await fsPromises.unlink(targetPath).catch(_ => _)
|
||||
else await fsPromises.mkdir(targetDir, { recursive: true })
|
||||
await fsPromises.copyFile(filePath, targetPath)
|
||||
}
|
||||
|
||||
|
||||
module.exports = async(context) => {
|
||||
const { electronPlatformName, arch } = context
|
||||
const electronVersion = context.packager?.info?._framework?.version ?? require('../package.json').devDependencies.electron.replace(/^[^\d]*?(\d+)/, '$1')
|
||||
const electronNodeAbi = nodeAbi.getAbi(electronVersion, 'electron')
|
||||
await replaceQrcDecodeLib(electronNodeAbi, electronPlatformName, arch)
|
||||
if (electronPlatformName !== 'linux' || process.env.FORCE) return
|
||||
const bindingFilePath = path.join(__dirname, '../node_modules/better-sqlite3/binding.gyp')
|
||||
const bindingBakFilePath = path.join(__dirname, '../node_modules/better-sqlite3/binding.gyp.bak')
|
||||
switch (arch) {
|
||||
case Arch.x64:
|
||||
case Arch.arm64:
|
||||
case Arch.armv7l:
|
||||
if (fs.existsSync(bindingFilePath)) {
|
||||
// console.log('rename binding file...')
|
||||
await fsPromises.rename(bindingFilePath, bindingBakFilePath)
|
||||
}
|
||||
await replaceSqliteLib(electronNodeAbi, arch)
|
||||
break
|
||||
|
||||
default:
|
||||
if (fs.existsSync(bindingFilePath)) return
|
||||
// console.log('restore binding file...')
|
||||
await fsPromises.rename(bindingBakFilePath, bindingFilePath)
|
||||
break
|
||||
}
|
||||
}
|
||||
309
build-config/build-pack.js
Normal file
@@ -0,0 +1,309 @@
|
||||
/* eslint-disable no-template-curly-in-string */
|
||||
|
||||
const builder = require('electron-builder')
|
||||
const beforePack = require('./build-before-pack')
|
||||
const afterPack = require('./build-after-pack')
|
||||
|
||||
/**
|
||||
* @type {import('electron-builder').Configuration}
|
||||
* @see https://www.electron.build/configuration/configuration
|
||||
*/
|
||||
const options = {
|
||||
appId: 'cn.toside.music.desktop',
|
||||
productName: 'lx-music-desktop',
|
||||
beforePack,
|
||||
afterPack,
|
||||
protocols: {
|
||||
name: 'lx-music-protocol',
|
||||
schemes: [
|
||||
'lxmusic',
|
||||
],
|
||||
},
|
||||
directories: {
|
||||
buildResources: './resources',
|
||||
output: './build',
|
||||
},
|
||||
files: [
|
||||
'!node_modules/**/*',
|
||||
'node_modules/font-list',
|
||||
'node_modules/better-sqlite3/lib',
|
||||
'node_modules/better-sqlite3/package.json',
|
||||
'node_modules/better-sqlite3/build/Release/better_sqlite3.node',
|
||||
'node_modules/electron-font-manager/index.js',
|
||||
'node_modules/electron-font-manager/package.json',
|
||||
'node_modules/electron-font-manager/build/Release/font_manager.node',
|
||||
'node_modules/node-gyp-build',
|
||||
'node_modules/bufferutil',
|
||||
'node_modules/utf-8-validate',
|
||||
'build/Release/qrc_decode.node',
|
||||
'dist/**/*',
|
||||
],
|
||||
asar: {
|
||||
smartUnpack: false,
|
||||
},
|
||||
extraResources: [
|
||||
'./licenses',
|
||||
],
|
||||
publish: [
|
||||
{
|
||||
provider: 'github',
|
||||
owner: 'lyswhut',
|
||||
repo: 'lx-music-desktop',
|
||||
},
|
||||
],
|
||||
}
|
||||
/**
|
||||
* @type {import('electron-builder').Configuration}
|
||||
* @see https://www.electron.build/configuration/configuration
|
||||
*/
|
||||
const winOptions = {
|
||||
win: {
|
||||
icon: './resources/icons/icon.ico',
|
||||
legalTrademarks: 'lyswhut',
|
||||
// artifactName: '${productName}-v${version}-${env.ARCH}-${env.TARGET}.${ext}',
|
||||
},
|
||||
nsis: {
|
||||
oneClick: false,
|
||||
language: '2052',
|
||||
allowToChangeInstallationDirectory: true,
|
||||
// differentialPackage: true,
|
||||
license: './licenses/license.rtf',
|
||||
shortcutName: 'LX Music',
|
||||
},
|
||||
}
|
||||
/**
|
||||
* @type {import('electron-builder').Configuration}
|
||||
* @see https://www.electron.build/configuration/configuration
|
||||
*/
|
||||
const linuxOptions = {
|
||||
linux: {
|
||||
maintainer: 'lyswhut <lyswhut@qq.com>',
|
||||
// artifactName: '${productName}-${version}.${env.ARCH}.${ext}',
|
||||
icon: './resources/icons',
|
||||
category: 'Utility;AudioVideo;Audio;Player;Music;',
|
||||
desktop: {
|
||||
// https://www.electron.build/app-builder-lib.interface.linuxdesktopfile
|
||||
// https://www.electronjs.org/docs/latest/tutorial/linux-desktop-actions
|
||||
// https://specifications.freedesktop.org/desktop-entry-spec/latest/example.html
|
||||
// https://developer.gnome.org/documentation/guidelines/maintainer/integrating.html#desktop-files
|
||||
entry: {
|
||||
Name: 'LX Music',
|
||||
'Name[zh_CN]': 'LX Music',
|
||||
'Name[zh_TW]': 'LX Music',
|
||||
Encoding: 'UTF-8',
|
||||
MimeType: 'x-scheme-handler/lxmusic',
|
||||
StartupNotify: 'false',
|
||||
},
|
||||
},
|
||||
},
|
||||
appImage: {
|
||||
license: './licenses/license_zh.txt',
|
||||
category: 'Utility;AudioVideo;Audio;Player;Music;',
|
||||
},
|
||||
}
|
||||
/**
|
||||
* @type {import('electron-builder').Configuration}
|
||||
* @see https://www.electron.build/configuration/configuration
|
||||
*/
|
||||
const macOptions = {
|
||||
mac: {
|
||||
icon: './resources/icons/icon.icns',
|
||||
category: 'public.app-category.music',
|
||||
// artifactName: '${productName}-${version}.${ext}',
|
||||
},
|
||||
dmg: {
|
||||
window: {
|
||||
width: 530,
|
||||
height: 380,
|
||||
},
|
||||
contents: [
|
||||
{
|
||||
x: 140,
|
||||
y: 200,
|
||||
},
|
||||
{
|
||||
x: 390,
|
||||
y: 200,
|
||||
type: 'link',
|
||||
path: '/Applications',
|
||||
},
|
||||
],
|
||||
title: 'LX Music v${version}',
|
||||
},
|
||||
}
|
||||
|
||||
// win: {
|
||||
// tagret: {
|
||||
// setup: ['nsis', '${productName}-v${version}-${env.ARCH}-Setup.${ext}'],
|
||||
// green: ['7z', '${productName}-v${version}-${env.ARCH}-green.${ext}'],
|
||||
// portable: ['portable', '${productName}-v${version}-${env.ARCH}-portable.${ext}'],
|
||||
// },
|
||||
// },
|
||||
// linux: {
|
||||
// platform: Platform.WINDOWS,
|
||||
// arch: {
|
||||
// x64: builder.Arch.x64,
|
||||
// arm64: builder.Arch.arm64,
|
||||
// armv7l: builder.Arch.armv7l,
|
||||
// },
|
||||
// tagret: {
|
||||
// deb: ['deb', '${productName}_${version}_${env.ARCH}.${ext}'],
|
||||
// appImage: ['AppImage', '${productName}_${version}_${env.ARCH}.${ext}'],
|
||||
// pacman: ['pacman', '${productName}_${version}_${env.ARCH}.${ext}'],
|
||||
// rpm: ['rpm', '${productName}-${version}.${env.ARCH}.${ext}'],
|
||||
// },
|
||||
// },
|
||||
// mac: {
|
||||
// arch: {
|
||||
// x64: builder.Arch.x64,
|
||||
// x86: builder.Arch.ia32,
|
||||
// arm64: builder.Arch.arm64,
|
||||
// },
|
||||
// tagret: {
|
||||
// dmg: ['dmg', '${productName}-${version}-${env.ARCH}.${ext}'],
|
||||
// },
|
||||
// },
|
||||
|
||||
const createTarget = {
|
||||
/**
|
||||
*
|
||||
* @param {*} arch
|
||||
* @param {*} packageType
|
||||
* @returns {{ buildOptions: import('electron-builder').CliOptions, options: import('electron-builder').Configuration }}
|
||||
*/
|
||||
win(arch, packageType) {
|
||||
switch (packageType) {
|
||||
case 'setup':
|
||||
winOptions.artifactName = `\${productName}-v\${version}-${arch}-Setup.\${ext}`
|
||||
return {
|
||||
buildOptions: { win: ['nsis'] },
|
||||
options: winOptions,
|
||||
}
|
||||
case 'green':
|
||||
winOptions.artifactName = `\${productName}-v\${version}-win_${arch}-green.\${ext}`
|
||||
return {
|
||||
buildOptions: { win: ['7z'] },
|
||||
options: winOptions,
|
||||
}
|
||||
case 'win7_setup':
|
||||
winOptions.artifactName = `\${productName}-v\${version}-win7_${arch}-Setup.\${ext}`
|
||||
return {
|
||||
buildOptions: { win: ['nsis'] },
|
||||
options: winOptions,
|
||||
}
|
||||
case 'win7_green':
|
||||
winOptions.artifactName = `\${productName}-v\${version}-win7_${arch}-green.\${ext}`
|
||||
return {
|
||||
buildOptions: { win: ['7z'] },
|
||||
options: winOptions,
|
||||
}
|
||||
case 'portable':
|
||||
winOptions.artifactName = `\${productName}-v\${version}-${arch}-portable.\${ext}`
|
||||
return {
|
||||
buildOptions: { win: ['portable'] },
|
||||
options: winOptions,
|
||||
}
|
||||
default: throw new Error('Unknown package type: ' + packageType)
|
||||
}
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {*} arch
|
||||
* @param {*} packageType
|
||||
* @returns {{ buildOptions: import('electron-builder').CliOptions, options: import('electron-builder').Configuration }}
|
||||
*/
|
||||
linux(arch, packageType) {
|
||||
switch (packageType) {
|
||||
case 'deb':
|
||||
linuxOptions.artifactName = `\${productName}_\${version}_${arch == 'x64' ? 'amd64' : arch}.\${ext}`
|
||||
return {
|
||||
buildOptions: { linux: ['deb'] },
|
||||
options: linuxOptions,
|
||||
}
|
||||
case 'appImage':
|
||||
linuxOptions.artifactName = `\${productName}_\${version}_${arch}.\${ext}`
|
||||
return {
|
||||
buildOptions: { linux: ['AppImage'] },
|
||||
options: linuxOptions,
|
||||
}
|
||||
case 'pacman':
|
||||
linuxOptions.artifactName = `\${productName}_\${version}_${arch}.\${ext}`
|
||||
return {
|
||||
buildOptions: { linux: ['pacman'] },
|
||||
options: linuxOptions,
|
||||
}
|
||||
case 'rpm':
|
||||
linuxOptions.artifactName = `\${productName}-\${version}.${arch}.\${ext}`
|
||||
return {
|
||||
buildOptions: { linux: ['rpm'] },
|
||||
options: linuxOptions,
|
||||
}
|
||||
default: throw new Error('Unknown package type: ' + packageType)
|
||||
}
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {*} arch
|
||||
* @param {*} packageType
|
||||
* @returns {{ buildOptions: import('electron-builder').CliOptions, options: import('electron-builder').Configuration }}
|
||||
*/
|
||||
mac(arch, packageType) {
|
||||
switch (packageType) {
|
||||
case 'dmg':
|
||||
macOptions.artifactName = `\${productName}-\${version}-${arch}.\${ext}`
|
||||
return {
|
||||
buildOptions: { mac: ['dmg'] },
|
||||
options: macOptions,
|
||||
}
|
||||
default: throw new Error('Unknown package type: ' + packageType)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {'win' | 'mac' | 'linux' | 'dir'} target 构建目标平台
|
||||
* @param {'x86_64' | 'x64' | 'x86' | 'arm64' | 'armv7l'} arch 包架构
|
||||
* @param {*} packageType 包类型
|
||||
* @param {'onTagOrDraft' | 'always' | 'never'} publishType 发布类型
|
||||
*/
|
||||
const build = async(target, arch, packageType, publishType) => {
|
||||
if (target == 'dir') {
|
||||
await builder.build({
|
||||
dir: true,
|
||||
config: { ...options, ...winOptions, ...linuxOptions, ...macOptions },
|
||||
})
|
||||
return
|
||||
}
|
||||
const targetInfo = createTarget[target](arch, packageType)
|
||||
// Promise is returned
|
||||
await builder.build({
|
||||
...targetInfo.buildOptions,
|
||||
publish: publishType ?? 'never',
|
||||
x64: arch == 'x64' || arch == 'x86_64',
|
||||
ia32: arch == 'x86' || arch == 'x86_64',
|
||||
arm64: arch == 'arm64',
|
||||
armv7l: arch == 'armv7l',
|
||||
config: { ...options, ...targetInfo.options },
|
||||
})
|
||||
// .then((result) => {
|
||||
// console.log(JSON.stringify(result))
|
||||
// })
|
||||
// .catch((error) => {
|
||||
// console.error(error)
|
||||
// })
|
||||
}
|
||||
|
||||
const params = {}
|
||||
|
||||
for (const param of process.argv.slice(2)) {
|
||||
const [name, value] = param.split('=')
|
||||
params[name] = value
|
||||
}
|
||||
|
||||
if (params.target == null) throw new Error('Missing target')
|
||||
if (params.target != 'dir' && params.arch == null) throw new Error('Missing arch')
|
||||
if (params.target != 'dir' && params.type == null) throw new Error('Missing type')
|
||||
|
||||
console.log(params.target, params.arch, params.type, params.publish ?? '')
|
||||
build(params.target, params.arch, params.type, params.publish)
|
||||
@@ -4,6 +4,7 @@ module.exports = {
|
||||
modules: {
|
||||
localIdentName: isDev ? '[path][name]__[local]--[hash:base64:5]' : '[hash:base64:5]',
|
||||
exportLocalsConvention: 'camelCase',
|
||||
namedExport: false,
|
||||
},
|
||||
sourceMap: isDev,
|
||||
}
|
||||
|
||||
38
build-config/dependencies-patch.js
Normal file
@@ -0,0 +1,38 @@
|
||||
// 修补依赖源码以使vite构建的依赖恢复正常工作
|
||||
|
||||
const fs = require('node:fs')
|
||||
const path = require('node:path')
|
||||
|
||||
const rootPath = path.join(__dirname, '../')
|
||||
|
||||
const patchs = [
|
||||
[
|
||||
path.join(rootPath, './node_modules/ws/package.json'),
|
||||
'\n "browser": "./browser.js",',
|
||||
'',
|
||||
],
|
||||
[
|
||||
path.join(rootPath, './node_modules/music-metadata/package.json'),
|
||||
'"default": "./lib/core.js"',
|
||||
'"default": "./lib/index.js"',
|
||||
],
|
||||
[
|
||||
path.join(rootPath, './node_modules/strtok3/package.json'),
|
||||
'"default": "./lib/core.js"',
|
||||
'"default": "./lib/index.js"',
|
||||
],
|
||||
]
|
||||
|
||||
;(async() => {
|
||||
for (const [filePath, fromStr, toStr] of patchs) {
|
||||
console.log(`Patching ${filePath.replace(rootPath, '')}`)
|
||||
try {
|
||||
const file = (await fs.promises.readFile(filePath)).toString()
|
||||
await fs.promises.writeFile(filePath, file.replace(fromStr, toStr))
|
||||
} catch (err) {
|
||||
console.error(`Patch ${filePath.replace(rootPath, '')} failed: ${err.message}`)
|
||||
}
|
||||
}
|
||||
console.log('\nDependencies patch finished.\n')
|
||||
})()
|
||||
|
||||
53
build-config/lib-update.js
Normal file
@@ -0,0 +1,53 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const tar = require('tar')
|
||||
|
||||
const libDir = path.join(__dirname, 'lib')
|
||||
|
||||
const getGzipFiles = async() => {
|
||||
const names = await fs.promises.readdir(libDir)
|
||||
// for (const name of names) {
|
||||
// if (name.endsWith('.node')) await fs.promises.unlink(path.join(libDir, name))
|
||||
// }
|
||||
return names.filter(name => name.endsWith('.gz'))
|
||||
}
|
||||
|
||||
const unzip = async(filePath) => {
|
||||
const targetDir = filePath.replace('.tar.gz', '')
|
||||
if (fs.existsSync(targetDir)) await fs.promises.rm(targetDir, { recursive: true })
|
||||
await fs.promises.mkdir(targetDir)
|
||||
await tar.x({
|
||||
file: filePath,
|
||||
strip: 1,
|
||||
C: targetDir,
|
||||
})
|
||||
return targetDir
|
||||
}
|
||||
|
||||
const files = [
|
||||
'qrc_decode',
|
||||
'better_sqlite3',
|
||||
]
|
||||
const moveFile = async(filePath) => {
|
||||
const name = 'electron-' + path.basename(filePath).split('-electron-')[1]
|
||||
for (const fileName of files) {
|
||||
if (fileName == 'better_sqlite3' && !name.includes('linux')) continue
|
||||
const targetPath = path.join(libDir, `${fileName}_${name}.node`)
|
||||
if (fs.existsSync(targetPath)) await fs.promises.unlink(targetPath)
|
||||
await fs.promises.rename(path.join(filePath, 'Release', fileName + '.node'), targetPath)
|
||||
}
|
||||
await fs.promises.rm(filePath, { recursive: true })
|
||||
}
|
||||
|
||||
const run = async() => {
|
||||
const files = await getGzipFiles()
|
||||
for (const name of files) {
|
||||
await moveFile(await unzip(path.join(libDir, name)))
|
||||
}
|
||||
for (const name of files) {
|
||||
await fs.promises.unlink(path.join(libDir, name))
|
||||
}
|
||||
}
|
||||
|
||||
run()
|
||||
|
||||
BIN
build-config/lib/better_sqlite3_electron-v136-linux-arm.node
Normal file
BIN
build-config/lib/better_sqlite3_electron-v136-linux-arm64.node
Normal file
BIN
build-config/lib/better_sqlite3_electron-v136-linux-x64.node
Normal file
BIN
build-config/lib/qrc_decode_electron-v110-win32-arm64.node
Normal file
BIN
build-config/lib/qrc_decode_electron-v110-win32-ia32.node
Normal file
BIN
build-config/lib/qrc_decode_electron-v110-win32-x64.node
Normal file
BIN
build-config/lib/qrc_decode_electron-v136-darwin-arm64.node
Normal file
BIN
build-config/lib/qrc_decode_electron-v136-darwin-x64.node
Normal file
BIN
build-config/lib/qrc_decode_electron-v136-linux-arm.node
Normal file
BIN
build-config/lib/qrc_decode_electron-v136-linux-arm64.node
Normal file
BIN
build-config/lib/qrc_decode_electron-v136-linux-x64.node
Normal file
BIN
build-config/lib/qrc_decode_electron-v136-win32-arm64.node
Normal file
BIN
build-config/lib/qrc_decode_electron-v136-win32-ia32.node
Normal file
BIN
build-config/lib/qrc_decode_electron-v136-win32-x64.node
Normal file
@@ -1,13 +1,25 @@
|
||||
const path = require('path')
|
||||
const ESLintPlugin = require('eslint-webpack-plugin')
|
||||
|
||||
const isDev = process.env.NODE_ENV === 'development'
|
||||
|
||||
module.exports = {
|
||||
target: 'electron-main',
|
||||
output: {
|
||||
filename: '[name].js',
|
||||
libraryTarget: 'commonjs2',
|
||||
library: {
|
||||
type: 'commonjs2',
|
||||
},
|
||||
path: path.join(__dirname, '../../dist'),
|
||||
},
|
||||
externals: {
|
||||
'font-list': 'font-list',
|
||||
'better-sqlite3': 'better-sqlite3',
|
||||
'electron-font-manager': 'electron-font-manager',
|
||||
bufferutil: 'bufferutil',
|
||||
'utf-8-validate': 'utf-8-validate',
|
||||
'qrc_decode.node': isDev ? path.join(__dirname, '../../build/Release/qrc_decode.node') : path.join('../build/Release/qrc_decode.node'),
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@main': path.join(__dirname, '../../src/main'),
|
||||
@@ -15,7 +27,7 @@ module.exports = {
|
||||
'@lyric': path.join(__dirname, '../../src/renderer-lyric'),
|
||||
'@common': path.join(__dirname, '../../src/common'),
|
||||
},
|
||||
extensions: ['*', '.js', '.json', '.node'],
|
||||
extensions: ['.tsx', '.ts', '.js', '.mjs', '.json', '.node'],
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
@@ -23,6 +35,11 @@ module.exports = {
|
||||
test: /\.node$/,
|
||||
use: 'node-loader',
|
||||
},
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
use: 'ts-loader',
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
|
||||
@@ -8,15 +8,17 @@ const baseConfig = require('./webpack.config.base')
|
||||
module.exports = merge(baseConfig, {
|
||||
mode: 'development',
|
||||
entry: {
|
||||
main: path.join(__dirname, '../../src/main/index.dev.js'),
|
||||
main: path.join(__dirname, '../../src/main/index-dev.ts'),
|
||||
// 'dbService.worker': path.join(__dirname, '../../src/main/worker/dbService/index.ts'),
|
||||
},
|
||||
devtool: 'eval-source-map',
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
NODE_ENV: '"development"',
|
||||
},
|
||||
__static: `"${path.join(__dirname, '../../src/static').replace(/\\/g, '\\\\')}"`,
|
||||
__userApi: `"${path.join(__dirname, '../../src/main/modules/userApi').replace(/\\/g, '\\\\')}"`,
|
||||
webpackStaticPath: `"${path.join(__dirname, '../../src/static').replace(/\\/g, '\\\\')}"`,
|
||||
webpackUserApiPath: `"${path.join(__dirname, '../../src/main/modules/userApi').replace(/\\/g, '\\\\')}"`,
|
||||
}),
|
||||
],
|
||||
performance: {
|
||||
|
||||
@@ -5,18 +5,18 @@ const CopyWebpackPlugin = require('copy-webpack-plugin')
|
||||
|
||||
const baseConfig = require('./webpack.config.base')
|
||||
|
||||
const { dependencies } = require('../../package.json')
|
||||
// const { dependencies } = require('../../package.json')
|
||||
|
||||
// const buildConfig = require('../webpack-build-config')
|
||||
|
||||
|
||||
module.exports = merge(baseConfig, {
|
||||
mode: 'production',
|
||||
devtool: false,
|
||||
entry: {
|
||||
main: path.join(__dirname, '../../src/main/index.js'),
|
||||
main: path.join(__dirname, '../../src/main/index.ts'),
|
||||
// 'dbService.worker': path.join(__dirname, '../../src/main/worker/dbService/index.ts'),
|
||||
},
|
||||
externals: [
|
||||
...Object.keys(dependencies || {}),
|
||||
// 'font-list',
|
||||
],
|
||||
node: {
|
||||
__dirname: false,
|
||||
__filename: false,
|
||||
@@ -25,12 +25,12 @@ module.exports = merge(baseConfig, {
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
{
|
||||
from: path.join(__dirname, '../../src/main/modules/userApi/renderer'),
|
||||
to: path.join(__dirname, '../../dist/userApi/renderer'),
|
||||
from: path.join(__dirname, '../../src/main/modules/userApi/renderer/user-api.html'),
|
||||
to: path.join(__dirname, '../../dist/userApi/renderer/user-api.html'),
|
||||
},
|
||||
{
|
||||
from: path.join(__dirname, '../../src/main/modules/userApi/rendererEvent/name.js'),
|
||||
to: path.join(__dirname, '../../dist/userApi/rendererEvent/name.js'),
|
||||
from: path.join(__dirname, '../../src/common/theme/images/*').replace(/\\/g, '/'),
|
||||
to: path.join(__dirname, '../../dist/theme_images/[name][ext]'),
|
||||
},
|
||||
],
|
||||
}),
|
||||
|
||||
@@ -5,21 +5,26 @@ const del = require('del')
|
||||
const webpack = require('webpack')
|
||||
const Spinnies = require('spinnies')
|
||||
|
||||
const mainConfig = require('./main/webpack.config.prod')
|
||||
const rendererConfig = require('./renderer/webpack.config.prod')
|
||||
const rendererLyricConfig = require('./renderer-lyric/webpack.config.prod')
|
||||
const mainConfig = './main/webpack.config.prod'
|
||||
const rendererConfig = './renderer/webpack.config.prod'
|
||||
const rendererLyricConfig = './renderer-lyric/webpack.config.prod'
|
||||
const rendererScriptConfig = './renderer-scripts/webpack.config.prod'
|
||||
|
||||
const errorLog = chalk.bgRed.white(' ERROR ') + ' '
|
||||
const okayLog = chalk.bgGreen.white(' OKAY ') + ' '
|
||||
|
||||
const { Worker, isMainThread, parentPort } = require('worker_threads')
|
||||
|
||||
|
||||
function build() {
|
||||
console.time('build')
|
||||
del.sync(['dist/**', 'build/**'])
|
||||
|
||||
const spinners = new Spinnies({ color: 'blue' })
|
||||
spinners.add('main', { text: 'main building' })
|
||||
spinners.add('renderer', { text: 'renderer building' })
|
||||
spinners.add('renderer-lyric', { text: 'renderer-lyric building' })
|
||||
spinners.add('renderer-scripts', { text: 'renderer-scripts building' })
|
||||
let results = ''
|
||||
|
||||
// m.on('success', () => {
|
||||
@@ -32,6 +37,7 @@ function build() {
|
||||
process.stdout.write('\x1B[2J\x1B[0f')
|
||||
console.log(`\n\n${results}`)
|
||||
console.log(`${okayLog}take it away ${chalk.yellow('`electron-builder`')}\n`)
|
||||
console.timeEnd('build')
|
||||
process.exit()
|
||||
}
|
||||
|
||||
@@ -63,11 +69,35 @@ function build() {
|
||||
console.error(`\n${err}\n`)
|
||||
process.exit(1)
|
||||
}),
|
||||
pack(rendererScriptConfig).then(result => {
|
||||
results += result + '\n\n'
|
||||
spinners.succeed('renderer-scripts', { text: 'renderer-scripts build success!' })
|
||||
}).catch(err => {
|
||||
spinners.fail('renderer-scripts', { text: 'renderer-scripts build fail :(' })
|
||||
console.log(`\n ${errorLog}failed to build renderer-scripts process`)
|
||||
console.error(`\n${err}\n`)
|
||||
process.exit(1)
|
||||
}),
|
||||
]).then(handleSuccess)
|
||||
}
|
||||
|
||||
function pack(config) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const worker = new Worker(__filename)
|
||||
const subChannel = new MessageChannel()
|
||||
worker.postMessage({ port: subChannel.port1, config }, [subChannel.port1])
|
||||
subChannel.port2.on('message', ({ status, message }) => {
|
||||
switch (status) {
|
||||
case 'success': return resolve(message)
|
||||
case 'error': return reject(message)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function runPack(config) {
|
||||
return new Promise((resolve, reject) => {
|
||||
config = require(config)
|
||||
config.mode = 'production'
|
||||
webpack(config, (err, stats) => {
|
||||
if (err) reject(err.stack || err)
|
||||
@@ -95,5 +125,22 @@ function pack(config) {
|
||||
})
|
||||
}
|
||||
|
||||
build()
|
||||
|
||||
if (isMainThread) build()
|
||||
else {
|
||||
parentPort.once('message', ({ port, config }) => {
|
||||
// assert(port instanceof MessagePort)
|
||||
runPack(config).then((result) => {
|
||||
port.postMessage({
|
||||
status: 'success',
|
||||
message: result,
|
||||
})
|
||||
}).catch((err) => {
|
||||
port.postMessage({
|
||||
status: 'error',
|
||||
message: err,
|
||||
})
|
||||
}).finally(() => {
|
||||
port.close()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
2
build-config/post-install.js
Normal file
@@ -0,0 +1,2 @@
|
||||
const { Arch } = require('electron-builder')
|
||||
require('./build-before-pack')({ electronPlatformName: process.platform, arch: Arch[process.arch] })
|
||||
@@ -12,27 +12,39 @@ const isDev = process.env.NODE_ENV === 'development'
|
||||
module.exports = {
|
||||
target: 'electron-renderer',
|
||||
entry: {
|
||||
'renderer-lyric': path.join(__dirname, '../../src/renderer-lyric/main.js'),
|
||||
'renderer-lyric': path.join(__dirname, '../../src/renderer-lyric/main.ts'),
|
||||
},
|
||||
output: {
|
||||
filename: '[name].js',
|
||||
libraryTarget: 'commonjs2',
|
||||
library: {
|
||||
type: 'commonjs2',
|
||||
},
|
||||
path: path.join(__dirname, '../../dist'),
|
||||
publicPath: 'auto',
|
||||
publicPath: '',
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': path.join(__dirname, '../../src'),
|
||||
'@root': path.join(__dirname, '../../src'),
|
||||
'@main': path.join(__dirname, '../../src/main'),
|
||||
'@renderer': path.join(__dirname, '../../src/renderer'),
|
||||
'@lyric': path.join(__dirname, '../../src/renderer-lyric'),
|
||||
'@static': path.join(__dirname, '../../src/static'),
|
||||
'@common': path.join(__dirname, '../../src/common'),
|
||||
},
|
||||
extensions: ['*', '.js', '.json', '.vue', '.node'],
|
||||
extensions: ['.tsx', '.ts', '.js', '.json', '.node'],
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: 'ts-loader',
|
||||
options: {
|
||||
appendTsSuffixTo: [/\.vue$/],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.node$/,
|
||||
use: 'node-loader',
|
||||
@@ -43,9 +55,8 @@ module.exports = {
|
||||
options: vueLoaderConfig,
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
exclude: /node_modules/,
|
||||
test: /\.pug$/,
|
||||
loader: 'pug-plain-loader',
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
@@ -60,20 +71,6 @@ module.exports = {
|
||||
},
|
||||
}),
|
||||
},
|
||||
{
|
||||
test: /\.pug$/,
|
||||
oneOf: [
|
||||
// Use pug-plain-loader handle .vue file
|
||||
{
|
||||
resourceQuery: /vue/,
|
||||
use: ['pug-plain-loader'],
|
||||
},
|
||||
// Use pug-loader handle .pug file
|
||||
{
|
||||
use: ['pug-loader'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
|
||||
exclude: path.join(__dirname, '../../src/renderer/assets/svgs'),
|
||||
@@ -130,7 +127,7 @@ module.exports = {
|
||||
plugins: [
|
||||
new HTMLPlugin({
|
||||
filename: 'lyric.html',
|
||||
template: path.join(__dirname, '../../src/renderer-lyric/index.pug'),
|
||||
template: path.join(__dirname, '../../src/renderer-lyric/index.html'),
|
||||
isProd: process.env.NODE_ENV == 'production',
|
||||
browser: process.browser,
|
||||
__dirname,
|
||||
|
||||
@@ -16,7 +16,8 @@ module.exports = merge(baseConfig, {
|
||||
},
|
||||
__VUE_OPTIONS_API__: 'true',
|
||||
__VUE_PROD_DEVTOOLS__: 'false',
|
||||
__static: `"${path.join(__dirname, '../../src/static').replace(/\\/g, '\\\\')}"`,
|
||||
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: 'false',
|
||||
staticPath: `"${path.join(__dirname, '../../src/static').replace(/\\/g, '\\\\')}"`,
|
||||
}),
|
||||
],
|
||||
performance: {
|
||||
|
||||
@@ -5,19 +5,29 @@ const TerserPlugin = require('terser-webpack-plugin')
|
||||
const { merge } = require('webpack-merge')
|
||||
|
||||
const baseConfig = require('./webpack.config.base')
|
||||
const buildConfig = require('../webpack-build-config')
|
||||
|
||||
const { dependencies } = require('../../package.json')
|
||||
// const { dependencies } = require('../../package.json')
|
||||
|
||||
// let whiteListedModules = ['vue']
|
||||
let whiteListedModules = ['vue', 'vue-router', 'vuex', 'vue-i18n']
|
||||
// let whiteListedModules = ['vue', 'vue-router', 'vuex', 'vue-i18n']
|
||||
|
||||
|
||||
module.exports = merge(baseConfig, {
|
||||
mode: 'production',
|
||||
devtool: false,
|
||||
devtool: 'source-map',
|
||||
externals: [
|
||||
...Object.keys(dependencies || {}).filter(d => !whiteListedModules.includes(d)),
|
||||
// ...Object.keys(dependencies || {}).filter(d => !whiteListedModules.includes(d)),
|
||||
],
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
@@ -25,10 +35,11 @@ module.exports = merge(baseConfig, {
|
||||
},
|
||||
__VUE_OPTIONS_API__: 'true',
|
||||
__VUE_PROD_DEVTOOLS__: 'false',
|
||||
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: 'false',
|
||||
}),
|
||||
],
|
||||
optimization: {
|
||||
minimize: false,
|
||||
minimize: buildConfig.minimize,
|
||||
minimizer: [
|
||||
new TerserPlugin(),
|
||||
new CssMinimizerPlugin(),
|
||||
|
||||
52
build-config/renderer-scripts/webpack.config.base.js
Normal file
@@ -0,0 +1,52 @@
|
||||
const path = require('path')
|
||||
const ESLintPlugin = require('eslint-webpack-plugin')
|
||||
|
||||
module.exports = {
|
||||
target: 'electron-renderer',
|
||||
entry: {
|
||||
'user-api-preload': path.join(__dirname, '../../src/main/modules/userApi/renderer/preload.js'),
|
||||
},
|
||||
output: {
|
||||
filename: '[name].js',
|
||||
library: {
|
||||
type: 'commonjs2',
|
||||
},
|
||||
path: path.join(__dirname, '../../dist'),
|
||||
publicPath: '',
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@root': path.join(__dirname, '../../src'),
|
||||
'@main': path.join(__dirname, '../../src/main'),
|
||||
'@renderer': path.join(__dirname, '../../src/renderer'),
|
||||
'@lyric': path.join(__dirname, '../../src/renderer-lyric'),
|
||||
'@static': path.join(__dirname, '../../src/static'),
|
||||
'@common': path.join(__dirname, '../../src/common'),
|
||||
},
|
||||
extensions: ['.tsx', '.ts', '.js', '.json', '.node'],
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: 'ts-loader',
|
||||
options: {
|
||||
appendTsSuffixTo: [/\.vue$/],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.node$/,
|
||||
use: 'node-loader',
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new ESLintPlugin({
|
||||
extensions: ['js'],
|
||||
formatter: require('eslint-formatter-friendly'),
|
||||
}),
|
||||
],
|
||||
}
|
||||
24
build-config/renderer-scripts/webpack.config.dev.js
Normal file
@@ -0,0 +1,24 @@
|
||||
const path = require('path')
|
||||
const webpack = require('webpack')
|
||||
|
||||
const { merge } = require('webpack-merge')
|
||||
|
||||
const baseConfig = require('./webpack.config.base')
|
||||
|
||||
module.exports = merge(baseConfig, {
|
||||
mode: 'development',
|
||||
devtool: 'eval-source-map',
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
NODE_ENV: '"development"',
|
||||
ELECTRON_DISABLE_SECURITY_WARNINGS: 'true',
|
||||
},
|
||||
staticPath: `"${path.join(__dirname, '../../src/static').replace(/\\/g, '\\\\')}"`,
|
||||
}),
|
||||
],
|
||||
performance: {
|
||||
hints: false,
|
||||
},
|
||||
})
|
||||
|
||||
54
build-config/renderer-scripts/webpack.config.prod.js
Normal file
@@ -0,0 +1,54 @@
|
||||
// const path = require('path')
|
||||
const webpack = require('webpack')
|
||||
const TerserPlugin = require('terser-webpack-plugin')
|
||||
const { merge } = require('webpack-merge')
|
||||
|
||||
const baseConfig = require('./webpack.config.base')
|
||||
const buildConfig = require('../webpack-build-config')
|
||||
|
||||
// const { dependencies } = require('../../package.json')
|
||||
|
||||
// let whiteListedModules = ['vue']
|
||||
// let whiteListedModules = ['vue', 'vue-router', 'vuex', 'vue-i18n']
|
||||
|
||||
|
||||
module.exports = merge(baseConfig, {
|
||||
mode: 'production',
|
||||
devtool: 'source-map',
|
||||
externals: [
|
||||
// ...Object.keys(dependencies || {}).filter(d => !whiteListedModules.includes(d)),
|
||||
],
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
NODE_ENV: '"production"',
|
||||
},
|
||||
}),
|
||||
],
|
||||
optimization: {
|
||||
minimize: buildConfig.minimize,
|
||||
minimizer: [
|
||||
new TerserPlugin(),
|
||||
],
|
||||
},
|
||||
performance: {
|
||||
maxEntrypointSize: 1024 * 1024 * 10,
|
||||
maxAssetSize: 1024 * 1024 * 20,
|
||||
hints: 'warning',
|
||||
},
|
||||
node: {
|
||||
__dirname: false,
|
||||
__filename: false,
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -12,27 +12,45 @@ const isDev = process.env.NODE_ENV === 'development'
|
||||
module.exports = {
|
||||
target: 'electron-renderer',
|
||||
entry: {
|
||||
renderer: path.join(__dirname, '../../src/renderer/main.js'),
|
||||
renderer: path.join(__dirname, '../../src/renderer/main.ts'),
|
||||
},
|
||||
output: {
|
||||
filename: '[name].js',
|
||||
libraryTarget: 'commonjs2',
|
||||
library: {
|
||||
type: 'commonjs2',
|
||||
},
|
||||
path: path.join(__dirname, '../../dist'),
|
||||
publicPath: 'auto',
|
||||
publicPath: '',
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': path.join(__dirname, '../../src'),
|
||||
'@root': path.join(__dirname, '../../src'),
|
||||
'@main': path.join(__dirname, '../../src/main'),
|
||||
'@renderer': path.join(__dirname, '../../src/renderer'),
|
||||
'@lyric': path.join(__dirname, '../../src/renderer-lyric'),
|
||||
'@static': path.join(__dirname, '../../src/static'),
|
||||
'@common': path.join(__dirname, '../../src/common'),
|
||||
},
|
||||
extensions: ['*', '.js', '.json', '.vue', '.node'],
|
||||
extensions: ['.tsx', '.ts', '.js', '.json', '.node'],
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: 'ts-loader',
|
||||
options: {
|
||||
appendTsSuffixTo: [/\.vue$/],
|
||||
},
|
||||
},
|
||||
parser: {
|
||||
worker: [
|
||||
'*audioContext.audioWorklet.addModule()',
|
||||
'...',
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.node$/,
|
||||
use: 'node-loader',
|
||||
@@ -43,9 +61,8 @@ module.exports = {
|
||||
options: vueLoaderConfig,
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
exclude: /node_modules/,
|
||||
test: /\.pug$/,
|
||||
loader: 'pug-plain-loader',
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
@@ -60,20 +77,6 @@ module.exports = {
|
||||
},
|
||||
}),
|
||||
},
|
||||
{
|
||||
test: /\.pug$/,
|
||||
oneOf: [
|
||||
// Use pug-plain-loader handle .vue file
|
||||
{
|
||||
resourceQuery: /vue/,
|
||||
use: ['pug-plain-loader'],
|
||||
},
|
||||
// Use pug-loader handle .pug file
|
||||
{
|
||||
use: ['pug-loader'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
|
||||
exclude: path.join(__dirname, '../../src/renderer/assets/svgs'),
|
||||
@@ -102,7 +105,7 @@ module.exports = {
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
|
||||
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)$/,
|
||||
type: 'asset',
|
||||
parser: {
|
||||
dataUrlCondition: {
|
||||
|
||||
@@ -5,6 +5,11 @@ const { merge } = require('webpack-merge')
|
||||
|
||||
const baseConfig = require('./webpack.config.base')
|
||||
|
||||
const gitInfo = {
|
||||
commit_id: '',
|
||||
commit_date: '',
|
||||
}
|
||||
|
||||
module.exports = merge(baseConfig, {
|
||||
mode: 'development',
|
||||
devtool: 'eval-source-map',
|
||||
@@ -14,10 +19,13 @@ module.exports = merge(baseConfig, {
|
||||
NODE_ENV: '"development"',
|
||||
ELECTRON_DISABLE_SECURITY_WARNINGS: 'true',
|
||||
},
|
||||
ENVIRONMENT: 'process.env',
|
||||
// ENVIRONMENT: 'process.env',
|
||||
__VUE_OPTIONS_API__: 'true',
|
||||
__VUE_PROD_DEVTOOLS__: 'false',
|
||||
__static: `"${path.join(__dirname, '../../src/static').replace(/\\/g, '\\\\')}"`,
|
||||
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: 'false',
|
||||
COMMIT_ID: `"${gitInfo.commit_id}"`,
|
||||
COMMIT_DATE: `"${gitInfo.commit_date}"`,
|
||||
staticPath: `"${path.join(__dirname, '../../src/static').replace(/\\/g, '\\\\')}"`,
|
||||
}),
|
||||
],
|
||||
performance: {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const path = require('path')
|
||||
const { execSync } = require('child_process')
|
||||
const webpack = require('webpack')
|
||||
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
|
||||
const TerserPlugin = require('terser-webpack-plugin')
|
||||
@@ -6,18 +7,47 @@ const CopyWebpackPlugin = require('copy-webpack-plugin')
|
||||
const { merge } = require('webpack-merge')
|
||||
|
||||
const baseConfig = require('./webpack.config.base')
|
||||
const buildConfig = require('../webpack-build-config')
|
||||
|
||||
const { dependencies } = require('../../package.json')
|
||||
// const { dependencies } = require('../../package.json')
|
||||
|
||||
let whiteListedModules = ['vue', 'vue-router', 'vuex', 'vue-i18n']
|
||||
// let whiteListedModules = ['vue', 'vue-router', 'vuex', 'vue-i18n']
|
||||
|
||||
const gitInfo = {
|
||||
commit_id: '',
|
||||
commit_date: '',
|
||||
}
|
||||
|
||||
try {
|
||||
let isClean = !execSync('git status --porcelain').toString().trim()
|
||||
if (process.env.BUILD_WIN7) {
|
||||
console.warn('BUILD_WIN7 is set, skipping git status check.')
|
||||
console.log('Workspace status:', execSync('git status --porcelain').toString().trim())
|
||||
isClean = true
|
||||
}
|
||||
if (isClean) {
|
||||
gitInfo.commit_id = execSync('git log -1 --pretty=format:"%H"').toString().trim()
|
||||
gitInfo.commit_date = execSync('git log -1 --pretty=format:"%ad" --date=iso-strict').toString().trim()
|
||||
} else if (process.env.IS_CI) {
|
||||
throw new Error('Working directory is not clean')
|
||||
}
|
||||
} catch {}
|
||||
|
||||
module.exports = merge(baseConfig, {
|
||||
mode: 'production',
|
||||
devtool: false,
|
||||
devtool: 'source-map',
|
||||
externals: [
|
||||
...Object.keys(dependencies || {}).filter(d => !whiteListedModules.includes(d)),
|
||||
// ...Object.keys(dependencies || {}).filter(d => !whiteListedModules.includes(d)),
|
||||
],
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
@@ -31,17 +61,24 @@ module.exports = merge(baseConfig, {
|
||||
'process.env': {
|
||||
NODE_ENV: '"production"',
|
||||
},
|
||||
ENVIRONMENT: 'process.env',
|
||||
// ENVIRONMENT: 'process.env',
|
||||
__VUE_OPTIONS_API__: 'true',
|
||||
__VUE_PROD_DEVTOOLS__: 'false',
|
||||
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: 'false',
|
||||
COMMIT_ID: `"${gitInfo.commit_id}"`,
|
||||
COMMIT_DATE: `"${gitInfo.commit_date}"`,
|
||||
}),
|
||||
],
|
||||
optimization: {
|
||||
minimize: false,
|
||||
minimize: buildConfig.minimize,
|
||||
minimizer: [
|
||||
new TerserPlugin(),
|
||||
new CssMinimizerPlugin(),
|
||||
],
|
||||
splitChunks: {
|
||||
chunks: 'initial',
|
||||
minChunks: 2,
|
||||
},
|
||||
},
|
||||
performance: {
|
||||
maxEntrypointSize: 1024 * 1024 * 10,
|
||||
|
||||
@@ -13,9 +13,13 @@ const webpackHotMiddleware = require('webpack-hot-middleware')
|
||||
const mainConfig = require('./main/webpack.config.dev')
|
||||
const rendererConfig = require('./renderer/webpack.config.dev')
|
||||
const rendererLyricConfig = require('./renderer-lyric/webpack.config.dev')
|
||||
const rendererScriptConfig = require('./renderer-scripts/webpack.config.dev')
|
||||
const { Arch } = require('electron-builder')
|
||||
const replaceLib = require('./build-before-pack')
|
||||
const treeKill = require('tree-kill')
|
||||
const { debounce } = require('./utils')
|
||||
|
||||
let electronProcess = null
|
||||
let manualRestart = false
|
||||
let hotMiddlewareRenderer
|
||||
let hotMiddlewareRendererLyric
|
||||
|
||||
@@ -47,16 +51,19 @@ function startRenderer() {
|
||||
port: 9080,
|
||||
hot: true,
|
||||
historyApiFallback: true,
|
||||
// static: {
|
||||
// directory: path.join(__dirname, '../'),
|
||||
// },
|
||||
static: {
|
||||
directory: path.join(__dirname, '../src/common/theme/images'),
|
||||
publicPath: '/theme_images',
|
||||
},
|
||||
client: {
|
||||
logging: 'warn',
|
||||
overlay: true,
|
||||
},
|
||||
setupMiddlewares(middlewares, devServer) {
|
||||
devServer.app.use(hotMiddlewareRenderer)
|
||||
devServer.middleware.waitUntilValid(resolve)
|
||||
setImmediate(() => {
|
||||
devServer.middleware.waitUntilValid(resolve)
|
||||
})
|
||||
|
||||
return middlewares
|
||||
},
|
||||
@@ -102,7 +109,9 @@ function startRendererLyric() {
|
||||
},
|
||||
setupMiddlewares(middlewares, devServer) {
|
||||
devServer.app.use(hotMiddlewareRenderer)
|
||||
devServer.middleware.waitUntilValid(resolve)
|
||||
setImmediate(() => {
|
||||
devServer.middleware.waitUntilValid(resolve)
|
||||
})
|
||||
return middlewares
|
||||
},
|
||||
}, compiler)
|
||||
@@ -111,10 +120,28 @@ function startRendererLyric() {
|
||||
})
|
||||
}
|
||||
|
||||
function startMain() {
|
||||
function startRendererScripts() {
|
||||
return new Promise((resolve, reject) => {
|
||||
// mainConfig.entry.main = [path.join(__dirname, '../src/main/index.dev.js')].concat(mainConfig.entry.main)
|
||||
// mainConfig.mode = 'development'
|
||||
const compiler = webpack(rendererScriptConfig)
|
||||
|
||||
compiler.watch({}, (err, stats) => {
|
||||
if (err) {
|
||||
console.log(err)
|
||||
return
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function startMain() {
|
||||
let firstRun = true
|
||||
return new Promise((resolve, reject) => {
|
||||
// mainConfig.entry.main = [path.join(__dirname, '../src/main/index.dev.js')].concat(mainConfig.entry.main)
|
||||
// mainConfig.mode = 'development'
|
||||
const runElectronDelay = debounce(startElectron, 200)
|
||||
const compiler = webpack(mainConfig)
|
||||
|
||||
compiler.hooks.watchRun.tapAsync('watch-run', (compilation, done) => {
|
||||
@@ -126,23 +153,19 @@ function startMain() {
|
||||
compiler.watch({}, (err, stats) => {
|
||||
if (err) {
|
||||
console.log(err)
|
||||
reject(err)
|
||||
return
|
||||
}
|
||||
|
||||
// logStats('Main', stats)
|
||||
|
||||
if (electronProcess && electronProcess.kill) {
|
||||
manualRestart = true
|
||||
process.kill(electronProcess.pid)
|
||||
electronProcess = null
|
||||
startElectron()
|
||||
|
||||
setTimeout(() => {
|
||||
manualRestart = false
|
||||
}, 5000)
|
||||
if (electronProcess) {
|
||||
electronProcess.removeAllListeners()
|
||||
treeKill(electronProcess.pid)
|
||||
}
|
||||
|
||||
resolve()
|
||||
if (firstRun) {
|
||||
firstRun = false
|
||||
resolve()
|
||||
} else runElectronDelay()
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -171,15 +194,23 @@ function startElectron() {
|
||||
})
|
||||
|
||||
electronProcess.on('close', () => {
|
||||
if (!manualRestart) process.exit()
|
||||
process.exit()
|
||||
})
|
||||
}
|
||||
|
||||
const logs = [
|
||||
'Manifest version 2 is deprecated, and support will be removed in 2023',
|
||||
'"Extension server error: Operation failed: Permission denied", source: devtools://devtools/bundled',
|
||||
|
||||
// https://github.com/electron/electron/issues/32133
|
||||
'"Electron sandbox_bundle.js script failed to run"',
|
||||
'"TypeError: object null is not iterable (cannot read property Symbol(Symbol.iterator))",',
|
||||
]
|
||||
function electronLog(data, color) {
|
||||
let log = data.toString()
|
||||
if (/[0-9A-z]+/.test(log)) {
|
||||
// 抑制 user api 窗口使用 data url 加载页面时 vue扩展 的报错日志刷屏的问题
|
||||
if (color == 'red' && typeof log === 'string' && log.includes('"Extension server error: Operation failed: Permission denied", source: devtools://devtools/bundled/extensions/extensions.js')) return
|
||||
// 抑制某些无关的报错日志
|
||||
if (color == 'red' && typeof log === 'string' && logs.some(l => log.includes(l))) return
|
||||
|
||||
console.log(chalk[color](log))
|
||||
}
|
||||
@@ -191,12 +222,14 @@ function init() {
|
||||
spinners.add('main', { text: 'main compiling' })
|
||||
spinners.add('renderer', { text: 'renderer compiling' })
|
||||
spinners.add('renderer-lyric', { text: 'renderer-lyric compiling' })
|
||||
spinners.add('renderer-scripts', { text: 'renderer-scripts compiling' })
|
||||
function handleSuccess(name) {
|
||||
spinners.succeed(name, { text: name + ' compile success!' })
|
||||
}
|
||||
function handleFail(name) {
|
||||
spinners.fail(name, { text: name + ' compile fail!' })
|
||||
}
|
||||
replaceLib({ electronPlatformName: process.platform, arch: Arch[process.arch] })
|
||||
|
||||
Promise.all([
|
||||
startRenderer().then(() => handleSuccess('renderer')).catch((err) => {
|
||||
@@ -207,6 +240,10 @@ function init() {
|
||||
console.error(err.message)
|
||||
return handleFail('renderer-lyric')
|
||||
}),
|
||||
startRendererScripts().then(() => handleSuccess('renderer-scripts')).catch((err) => {
|
||||
console.error(err.message)
|
||||
return handleFail('renderer-scripts')
|
||||
}),
|
||||
startMain().then(() => handleSuccess('main')).catch(() => handleFail('main')),
|
||||
]).then(startElectron).catch(err => {
|
||||
console.error(err)
|
||||
|
||||
@@ -31,7 +31,12 @@ exports.mergeCSSLoader = beforeLoader => {
|
||||
esModule: false,
|
||||
},
|
||||
},
|
||||
'css-loader',
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
esModule: false,
|
||||
},
|
||||
},
|
||||
'postcss-loader',
|
||||
],
|
||||
},
|
||||
@@ -63,3 +68,15 @@ exports.logStats = (proc, data) => {
|
||||
console.log(log)
|
||||
}
|
||||
|
||||
exports.debounce = (fn, delay = 100) => {
|
||||
let timer = null
|
||||
let _args
|
||||
return (...args) => {
|
||||
_args = args
|
||||
if (timer) clearTimeout(timer)
|
||||
timer = setTimeout(() => {
|
||||
timer = null
|
||||
fn(..._args)
|
||||
}, delay)
|
||||
}
|
||||
}
|
||||
|
||||
3
build-config/webpack-build-config.js
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
minimize: true,
|
||||
}
|
||||
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 487 KiB |
@@ -9,5 +9,10 @@
|
||||
"@common/*": ["src/common/*"],
|
||||
}
|
||||
},
|
||||
"vueCompilerOptions": {
|
||||
"plugins": [
|
||||
"@vue/language-plugin-pug"
|
||||
]
|
||||
},
|
||||
"exclude": ["node_modules", "build", "dist"]
|
||||
}
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
{\rtf1\adeflang1025\ansi\ansicpg936\uc2\adeff0\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi0\deflang1033\deflangfe2052\themelang1033\themelangfe2052\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f2\fbidi \fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;}
|
||||
{\f13\fbidi \fnil\fcharset134\fprq2{\*\panose 02010600030101010101}\'cb\'ce\'cc\'e5{\*\falt SimSun};}{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;}
|
||||
{\f44\fbidi \fnil\fcharset134\fprq2{\*\panose 00000000000000000000}@\'cb\'ce\'cc\'e5;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
|
||||
{\f36\fbidi \fnil\fcharset134\fprq2{\*\panose 02010600030101010101}\'b5\'c8\'cf\'df{\*\falt DengXian};}{\f44\fbidi \fnil\fcharset134\fprq2{\*\panose 00000000000000000000}@\'cb\'ce\'cc\'e5;}
|
||||
{\f45\fbidi \fnil\fcharset134\fprq2{\*\panose 00000000000000000000}@\'b5\'c8\'cf\'df;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
|
||||
{\fdbmajor\f31501\fbidi \fnil\fcharset134\fprq2{\*\panose 02010600030101010101}\'b5\'c8\'cf\'df Light;}{\fhimajor\f31502\fbidi \fnil\fcharset134\fprq2{\*\panose 02010600030101010101}\'b5\'c8\'cf\'df Light;}
|
||||
{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
|
||||
{\fdbminor\f31505\fbidi \fnil\fcharset134\fprq2{\*\panose 02010600030101010101}\'b5\'c8\'cf\'df{\*\falt DengXian};}{\fhiminor\f31506\fbidi \fnil\fcharset134\fprq2{\*\panose 02010600030101010101}\'b5\'c8\'cf\'df{\*\falt DengXian};}
|
||||
{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f45\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f46\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
|
||||
{\f48\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f49\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f50\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f51\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
|
||||
{\f52\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f53\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f65\fbidi \fmodern\fcharset238\fprq1 Courier New CE;}{\f66\fbidi \fmodern\fcharset204\fprq1 Courier New Cyr;}
|
||||
{\f68\fbidi \fmodern\fcharset161\fprq1 Courier New Greek;}{\f69\fbidi \fmodern\fcharset162\fprq1 Courier New Tur;}{\f70\fbidi \fmodern\fcharset177\fprq1 Courier New (Hebrew);}{\f71\fbidi \fmodern\fcharset178\fprq1 Courier New (Arabic);}
|
||||
{\f72\fbidi \fmodern\fcharset186\fprq1 Courier New Baltic;}{\f73\fbidi \fmodern\fcharset163\fprq1 Courier New (Vietnamese);}{\f177\fbidi \fnil\fcharset0\fprq2 SimSun Western{\*\falt SimSun};}{\f385\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}
|
||||
{\f386\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;}{\f388\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f389\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f392\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}
|
||||
{\f393\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);}{\f487\fbidi \fnil\fcharset0\fprq2 @SimSun Western;}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
|
||||
{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f46\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f47\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
|
||||
{\f49\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f50\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f51\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f52\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
|
||||
{\f53\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f54\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f66\fbidi \fmodern\fcharset238\fprq1 Courier New CE;}{\f67\fbidi \fmodern\fcharset204\fprq1 Courier New Cyr;}
|
||||
{\f69\fbidi \fmodern\fcharset161\fprq1 Courier New Greek;}{\f70\fbidi \fmodern\fcharset162\fprq1 Courier New Tur;}{\f71\fbidi \fmodern\fcharset177\fprq1 Courier New (Hebrew);}{\f72\fbidi \fmodern\fcharset178\fprq1 Courier New (Arabic);}
|
||||
{\f73\fbidi \fmodern\fcharset186\fprq1 Courier New Baltic;}{\f74\fbidi \fmodern\fcharset163\fprq1 Courier New (Vietnamese);}{\f178\fbidi \fnil\fcharset0\fprq2 SimSun Western{\*\falt SimSun};}{\f386\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}
|
||||
{\f387\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;}{\f389\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f390\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f393\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}
|
||||
{\f394\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);}{\f408\fbidi \fnil\fcharset0\fprq2 DengXian Western{\*\falt DengXian};}{\f406\fbidi \fnil\fcharset238\fprq2 DengXian CE{\*\falt DengXian};}
|
||||
{\f407\fbidi \fnil\fcharset204\fprq2 DengXian Cyr{\*\falt DengXian};}{\f409\fbidi \fnil\fcharset161\fprq2 DengXian Greek{\*\falt DengXian};}{\f488\fbidi \fnil\fcharset0\fprq2 @SimSun Western;}{\f498\fbidi \fnil\fcharset0\fprq2 @DengXian Western;}
|
||||
{\f496\fbidi \fnil\fcharset238\fprq2 @DengXian CE;}{\f497\fbidi \fnil\fcharset204\fprq2 @DengXian Cyr;}{\f499\fbidi \fnil\fcharset161\fprq2 @DengXian Greek;}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
|
||||
{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
|
||||
{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
|
||||
{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31520\fbidi \fnil\fcharset0\fprq2 DengXian Light Western;}{\fdbmajor\f31518\fbidi \fnil\fcharset238\fprq2 DengXian Light CE;}
|
||||
@@ -38,12 +41,12 @@
|
||||
\fs21\lang1033\langfe2052\kerning2\loch\f31505\hich\af2\dbch\af31505\cgrid\langnp1033\langfenp2052 \sbasedon0 \snext15 \slink16 \sunhideused Plain Text;}{\*\cs16 \additive \rtlch\fcs1 \af2 \ltrch\fcs0 \loch\f31505\hich\af2 \sbasedon10 \slink15 \slocked
|
||||
\'b4\'bf\'ce\'c4\'b1\'be \'d7\'d6\'b7\'fb;}{\*\cs17 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf19 \sbasedon10 \sunhideused \styrsid9533173 Hyperlink;}{\*\cs18 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \cf20\chshdng0\chcfpat0\chcbpat21
|
||||
\sbasedon10 \ssemihidden \sunhideused \styrsid9533173 Unresolved Mention;}{\*\cs19 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf22 \sbasedon10 \ssemihidden \sunhideused \styrsid9533173 FollowedHyperlink;}}{\*\pgptbl {\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}}
|
||||
{\*\rsidtbl \rsid927107\rsid1398824\rsid2109456\rsid3950508\rsid4133944\rsid4355753\rsid9533173\rsid10447395\rsid11081282\rsid12910709\rsid13643782\rsid14384001\rsid15226681}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0
|
||||
\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\author lysyw}{\operator lysyw}{\creatim\yr2019\mo8\dy17\hr10\min22}{\revtim\yr2020\mo4\dy28\hr13\min46}{\version8}{\edmins3}{\nofpages1}{\nofwords135}{\nofchars772}{\nofcharsws906}{\vern1}}
|
||||
{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw11906\paperh16838\margl2253\margr2253\margt1440\margb1440\gutter0\ltrsect
|
||||
{\*\rsidtbl \rsid927107\rsid1398824\rsid2109456\rsid2766548\rsid3758332\rsid3950508\rsid4133944\rsid4355753\rsid9533173\rsid10447395\rsid11081282\rsid12910709\rsid13643782\rsid14384001\rsid14511311\rsid15225067\rsid15226681}{\mmathPr\mmathFont34\mbrkBin0
|
||||
\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\author lysyw}{\operator lysyw}{\creatim\yr2019\mo8\dy17\hr10\min22}{\revtim\yr2025\mo2\dy22\hr15\min34}{\version12}{\edmins5}{\nofpages2}
|
||||
{\nofwords195}{\nofchars1117}{\nofcharsws1310}{\vern77}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw11906\paperh16838\margl2253\margr2253\margt1440\margb1440\gutter0\ltrsect
|
||||
\deftab420\ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors1\formshade\horzdoc\dgmargin\dghspace180\dgvspace156
|
||||
\dghorigin2253\dgvorigin1440\dghshow0\dgvshow2\jcompress\lnongrid
|
||||
\viewkind1\viewscale120\splytwnine\ftnlytwnine\htmautsp\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct\asianbrkrule\rsidroot3950508\newtblstyruls
|
||||
\viewkind1\viewscale100\splytwnine\ftnlytwnine\htmautsp\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct\asianbrkrule\rsidroot3950508\newtblstyruls
|
||||
\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat {\upr{\*\fchars
|
||||
!%),.:\'3b>?]\'7d\'a1\'e9\'a1\'a7\'a1\'e3\'a1\'a4\'a1\'a6\'a1\'a5\'a8\'44\'a1\'ac\'a1\'af\'a1\'b1\'a1\'ad\'a1\'eb\'a1\'e4\'a1\'e5?\'a1\'e6\'a1\'c3\'a1\'a2\'a1\'a3\'a1\'a8\'a1\'b5\'a1\'b7\'a1\'b9\'a1\'bb\'a1\'bf\'a1\'b3\'a1\'bd\'a8\'95\'a6\'e1\'a6\'e3\'a6\'e7\'a6\'e5\'a6\'eb\'a9\'77\'a9\'79\'a9\'7b\'a3\'a1\'a3\'a2\'a3\'a5\'a3\'a7\'a3\'a9\'a3\'ac\'a3\'ae\'a3\'ba\'a3\'bb\'a3\'bf\'a3\'dd\'a3\'e0\'a3\'fc\'a3\'fd\'a1\'ab\'a1\'e9
|
||||
}{\*\ud\uc0{\*\fchars
|
||||
@@ -53,66 +56,128 @@ $([\'7b{\uc2\u163 \'a1\'ea\u165 \'a3\'a4\'a1\'a4\'a1\'ae\'a1\'b0\'a1\'b4\'a1\'b6
|
||||
\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\headery851\footery992\colsx425\endnhere\sectlinegrid312\sectspecifyl\sectrsid2109456\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta \dbch .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang
|
||||
{\pntxta \dbch .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta \dbch .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta \dbch )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb \dbch (}{\pntxta \dbch )}}{\*\pnseclvl6
|
||||
\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb \dbch (}{\pntxta \dbch )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb \dbch (}{\pntxta \dbch )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb \dbch (}{\pntxta \dbch )}}{\*\pnseclvl9
|
||||
\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb \dbch (}{\pntxta \dbch )}}\pard\plain \ltrpar\s15\qj \li0\ri0\nowidctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid1398824 \rtlch\fcs1 \af2\afs22\alang1025 \ltrch\fcs0
|
||||
\fs21\lang1033\langfe2052\kerning2\loch\af31505\hich\af2\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824 \loch\af13\hich\af13\dbch\f13 \'b1\'be\'cf\'ee\'c4\'bf\'a3\'a8
|
||||
\'c8\'ed\'bc\'fe\'a3\'a9\'bb\'f9\'d3\'da}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid4133944 \hich\af13\dbch\af13\loch\f13 Apache License 2.0}{\rtlch\fcs1 \af13 \ltrch\fcs0
|
||||
\loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824 \hich\af13\dbch\af13\loch\f13 }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824 \loch\af13\hich\af13\dbch\f13 \'d0\'ed\'bf\'c9\'d6\'a4\'b7\'a2
|
||||
\'d0\'d0\'a3\'ac\'d4\'da\'ca\'b9\'d3\'c3\'b1\'be\'c8\'ed\'bc\'fe\'c7\'b0\'a3\'ac\'c4\'e3\'a3\'a8\'ca\'b9\'d3\'c3\'d5\'df\'a3\'a9\'d0\'e8\'c7\'a9\'ca\'f0\'b1\'be\'d0\'ad\'d2\'e9\'b2\'c5\'bf\'c9\'bc\'cc\'d0\'f8\'ca\'b9\'d3\'c3\'a3\'ac\'d2\'d4\'cf\'c2
|
||||
\'d0\'ad\'d2\'e9\'ca\'c7\'b6\'d4\'d3\'da}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824 \hich\af13\dbch\af13\loch\f13 Apache Li\hich\af13\dbch\af13\loch\f13 cense 2.0 }{\rtlch\fcs1 \af13 \ltrch\fcs0
|
||||
\loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824 \loch\af13\hich\af13\dbch\f13 \'b5\'c4\'b2\'b9\'b3\'e4\'a3\'ac\'c8\'e7\'d3\'d0\'b3\'e5\'cd\'bb\'a3\'ac\'d2\'d4\'d2\'d4\'cf\'c2\'d0\'ad\'d2\'e9\'ce\'aa\'d7\'bc\'a1\'a3}{\rtlch\fcs1 \af13
|
||||
\ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824
|
||||
\par }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid15226681
|
||||
\par }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid10447395\charrsid1398824
|
||||
\par }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824 \loch\af13\hich\af13\dbch\f13 \'b4\'ca\'d3\'ef\'d4\'bc\'b6\'a8\'a3\'ba\'b1\'be\'d0\'ad\'d2\'e9\'d6\'d0\'b5\'c4\'a1\'b0\'b1\'be\'c8\'ed\'bc\'fe\'a1\'b1\'d6\'b8
|
||||
\'c2\'e5\'d1\'a9\'d2\'f4\'c0\'d6\'d7\'c0\'c3\'e6\'b0\'e6\'cf\'ee\'c4\'bf\'a3\'bb\'a1\'b0\'ca\'b9\'d3\'c3\'d5\'df\'a1\'b1\'d6\'b8\'c7\'a9\'ca\'f0\'b1\'be\'d0\'ad\'d2\'e9\'b5\'c4\'ca\'b9\'d3\'c3\'d5\'df\'a3\'bb\'a1\'b0\'b9\'d9\'b7\'bd\'d2\'f4\'c0\'d6
|
||||
\'c6\'bd\'cc\'a8\'a1\'b1\'d6\'b8\'b6\'d4\'b1\'be\'c8\'ed\'bc\'fe\'c4\'da\'d6\'c3\'b5\'c4\'b0\'fc\'c0\'a8\'bf\'e1\'ce\'d2\'a1\'a2\'bf\'e1\'b9\'b7\'a1\'a2\'df\'e4\'b9\'be\'b5\'c8\'d2\'f4\'c0\'d6\'d4\'b4\'b5\'c4\'b9\'d9\'b7\'bd\'c6\'bd\'cc\'a8\'cd\'b3
|
||||
\'b3\'c6\'a3\'bb\'a1\'b0\'b0\'e6\'c8\'a8\'ca\'fd\'be\'dd\'a1\'b1\'d6\'b8\'b0\'fc\'c0\'a8\'b5\'ab\'b2\'bb\'cf\'de\'d3\'da\'cd\'bc\'cf\'f1\'a1\'a2\'d2\'f4\'c6\'b5\'a1\'a2\'c3\'fb\'d7\'d6\'b5\'c8\'d4\'da\'c4\'da\'b5\'c4\'cb\'fb\'c8\'cb\'d3\'b5\'d3\'d0
|
||||
\'cb\'f9\'ca\'f4\'b0\'e6\'c8\'a8\'b5\'c4\'ca\'fd\'be\'dd\'a1\'a3}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824
|
||||
\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb \dbch (}{\pntxta \dbch )}}\pard\plain \ltrpar\qj \li0\ri0\nowidctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid2766548 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0
|
||||
\fs21\lang1033\langfe2052\kerning2\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'b1\'be\'cf\'ee\'c4\'bf
|
||||
\'bb\'f9\'d3\'da}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \hich\af13\dbch\af13\loch\f13 Apache License 2.0 }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\loch\af13\hich\af13\dbch\f13 \'d0\'ed\'bf\'c9\'d6\'a4\'b7\'a2\'d0\'d0\'a3\'ac\'d2\'d4\'cf\'c2\'d0\'ad\'d2\'e9\'ca\'c7\'b6\'d4\'d3\'da}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\hich\af13\dbch\af13\loch\f13 Apache License 2.0 }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'b5\'c4\'b2\'b9\'b3\'e4\'a3\'ac\'c8\'e7\'d3\'d0\'b3\'e5\'cd\'bb\'a3\'ac\'d2\'d4
|
||||
\'d2\'d4\'cf\'c2\'d0\'ad\'d2\'e9\'ce\'aa\'d7\'bc\'a1\'a3}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\par
|
||||
\par \hich\af13\dbch\af13\loch\f13 1}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824 \loch\af13\hich\af13\dbch\f13 \'a1\'a2\'b1\'be\'c8\'ed\'bc\'fe\'b5\'c4\'ca\'fd\'be\'dd\'c0\'b4\'d4\'b4\'d4\'ad\'c0\'ed\'ca\'c7
|
||||
\'b4\'d3\'b8\'f7\'b9\'d9\'b7\'bd\'d2\'f4\'c0\'d6\'c6\'bd\'cc\'a8\'b5\'c4\'b9\'ab\'bf\'aa\'b7\'fe\'ce\'f1\'c6\'f7\'d6\'d0\'c0\'ad\'c8\'a1\'ca\'fd\'be\'dd\'a3\'ac\'be\'ad\'b9\'fd\'b6\'d4\'ca\'fd\'be\'dd\'bc\'f2\'b5\'a5\'b5\'d8\'c9\'b8\'d1\'a1\'d3\'eb
|
||||
\'ba\'cf\'b2\'a2\'ba\'f3\'bd\'f8\'d0\'d0\'d5\'b9\'ca\'be\'a3\'ac\'d2\'f2\'b4\'cb\'b1\'be\'c8\'ed\'bc\'fe\'b2\'bb\'b6\'d4\'ca\'fd\'be\'dd\'b5\'c4\'d7\'bc\'c8\'b7\'d0\'d4\'b8\'ba\'d4\'f0\'a1\'a3}{\rtlch\fcs1 \af13 \ltrch\fcs0
|
||||
\loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824
|
||||
\par \hich\af13\dbch\af13\loch\f13 2}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824 \loch\af13\hich\af13\dbch\f13 \'a1\'a2\'ca\'b9\'d3\'c3\'b1\'be\'c8\'ed\'bc\'fe\'b5\'c4\'b9\'fd\'b3\'cc\'d6\'d0\'bf\'c9\'c4\'dc
|
||||
\'bb\'e1\'b2\'fa\'c9\'fa\'b0\'e6\'c8\'a8\'ca\'fd\'be\'dd\'a3\'ac\'b6\'d4\'d3\'da\'d5\'e2\'d0\'a9\'b0\'e6\'c8\'a8\'ca\'fd\'be\'dd\'a3\'ac\'b1\'be\'c8\'ed\'bc\'fe\'b2\'bb\'d3\'b5\'d3\'d0\'cb\'fc\loch\af13\hich\af13\dbch\f13 \'c3\'c7\'b5\'c4\'cb\'f9\'d3\'d0
|
||||
\'c8\'a8\'a3\'ac\'ce\'aa\'c1\'cb\'b1\'dc\'c3\'e2\'d4\'ec\'b3\'c9\'c7\'d6\'c8\'a8\'a3\'ac\'ca\'b9\'d3\'c3\'d5\'df\'ce\'f1\'b1\'d8\'d4\'da}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824
|
||||
\hich\af13\dbch\af13\loch\f13 24}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824 \loch\af13\hich\af13\dbch\f13 \'d0\'a1\'ca\'b1\'c4\'da\'c7\'e5\'b3\'fd\'ca\'b9\'d3\'c3\'b1\'be\'c8\'ed\'bc\'fe\'b5\'c4\'b9\'fd
|
||||
\'b3\'cc\'d6\'d0\'cb\'f9\'b2\'fa\'c9\'fa\'b5\'c4\'b0\'e6\'c8\'a8\'ca\'fd\'be\'dd\'a1\'a3}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824
|
||||
\par \hich\af13\dbch\af13\loch\f13 3}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824 \loch\af13\hich\af13\dbch\f13 \'a1\'a2\'b1\'be\'c8\'ed\'bc\'fe\'c4\'da\'b5\'c4\'b9\'d9\'b7\'bd\'d2\'f4\'c0\'d6\'c6\'bd\'cc\'a8
|
||||
\'b1\'f0\'c3\'fb\'ce\'aa\'b1\'be\'c8\'ed\'bc\'fe\'c4\'da\'b6\'d4\'b9\'d9\'b7\'bd\'d2\'f4\'c0\'d6\'c6\'bd\'cc\'a8\'b5\'c4\'d2\'bb\'b8\'f6\'b3\'c6\'ba\'f4\'a3\'ac\'b2\'bb\'b0\'fc\'ba\'ac\'b6\'f1\'d2\'e2\'a3\'ac\'c8\'e7\'b9\'fb\'b9\'d9\'b7\'bd\'d2\'f4
|
||||
\'c0\'d6\'c6\'bd\'cc\'a8\'be\'f5\'b5\'c3\'b2\'bb\'cd\'d7\'a3\'ac\'bf\'c9\'c1\'aa\'cf\'b5\'b1\'be\'c8\'ed\'bc\'fe\'b8\'fc\'b8\'c4\'bb\'f2\'d2\'c6\'b3\'fd\'a1\'a3}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824
|
||||
|
||||
\par \hich\af13\dbch\af13\loch\f13 4}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824 \loch\af13\hich\af13\dbch\f13 \'a1\'a2\'b1\'be\'c8\'ed\'bc\'fe\'c4\'da\'ca\'b9\'d3\'c3\'b5\'c4\'b2\'bf\'b7\'d6\'b0\'fc\'c0\'a8
|
||||
\'b5\'ab\'b2\'bb\'cf\'de\'d3\'da\'d7\'d6\'cc\'e5\'a1\'a2\'cd\'bc\'c6\'ac\'b5\'c8\'d7\'ca\'d4\'b4\'c0\'b4\'d4\'b4\'d3\'da\'bb\'a5\'c1\'aa\'cd\'f8\'a3\'ac\'c8\'e7\'b9\'fb\'b3\'f6\'cf\'d6\'c7\'d6\'c8\'a8\'bf\'c9\'c1\'aa\'cf\'b5\'b1\'be\'c8\'ed\'bc\'fe
|
||||
\'d2\'c6\'b3\'fd\'a1\'a3}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824
|
||||
\par \hich\af13\dbch\af13\loch\f13 5}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824 \loch\af13\hich\af13\dbch\f13 \'a1\'a2\'d3\'c9\'d3\'da\'ca\'b9\'d3\'c3\'b1\'be\'c8\'ed\'bc\'fe\'b2\'fa\'c9\'fa\'b5\'c4\'b0\'fc
|
||||
\'c0\'a8\'d3\'c9\'d3\'da\'b1\'be\'d0\'ad\'d2\'e9\'bb\'f2\'d3\'c9\'d3\'da\'ca\'b9\'d3\'c3\'bb\'f2\'ce\'de\'b7\'a8\'ca\'b9\'d3\'c3\'b1\'be\'c8\'ed\'bc\'fe\'b6\'f8\'d2\'fd\'c6\'f0\'b5\'c4\'c8\'ce\'ba\'ce\'d0\'d4\'d6\'ca\'b5\'c4\'c8\'ce\'ba\'ce\'d6\'b1
|
||||
\'bd\'d3\'a1\'a2\'bc\'e4\'bd\'d3\'a1\'a2\'cc\'d8\'ca\'e2\'a1\'a2\'c5\'bc\'c8\'bb\'bb\'f2\'bd\'e1\'b9\'fb\'d0\'d4\'cb\'f0\'ba\'a6\'a3\'a8\'b0\'fc\'c0\'a8\'b5\'ab\'b2\'bb\'cf\'de\'d3\'da\'d2\'f2\'c9\'cc\'d3\'fe\'cb\'f0\'ca\'a7\'a1\'a2\'cd\'a3\'b9\'a4
|
||||
\'a1\'a2\'bc\'c6\'cb\'e3\'bb\'fa\'b9\'ca\'d5\'cf\'bb\'f2\'b9\'ca\'d5\'cf\'d2\'fd\'c6\'f0\'b5\'c4\'cb\'f0\'ba\'a6\'c5\'e2\'b3\'a5\'a3\'ac\'bb\'f2\'c8\'ce\'ba\'ce\'bc\'b0\loch\af13\hich\af13\dbch\f13 \'cb\'f9\'d3\'d0\'c6\'e4\'cb\'fb\'c9\'cc\'d2\'b5\'cb\'f0
|
||||
\'ba\'a6\'bb\'f2\'cb\'f0\'ca\'a7\'a3\'a9\'d3\'c9\'ca\'b9\'d3\'c3\'d5\'df\'b8\'ba\'d4\'f0\'a1\'a3}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824
|
||||
\par \hich\af13\dbch\af13\loch\f13 6}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824 \loch\af13\hich\af13\dbch\f13 \'a1\'a2\'b1\'be\'cf\'ee\'c4\'bf\'cd\'ea\'c8\'ab\'c3\'e2\'b7\'d1\'a3\'ac\'c7\'d2\'bf\'aa\'d4\'b4
|
||||
\'b7\'a2\'b2\'bc\'d3\'da}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824 \hich\af13\dbch\af13\loch\f13 GitHub }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824
|
||||
\loch\af13\hich\af13\dbch\f13 \'c3\'e6\'cf\'f2\'c8\'ab\'ca\'c0\'bd\'e7\'c8\'cb\'d3\'c3\'d7\'f7\'b6\'d4\'bc\'bc\'ca\'f5\'b5\'c4\'d1\'a7\'cf\'b0\'bd\'bb\'c1\'f7\'a3\'ac\'b1\'be\'c8\'ed\'bc\'fe\'b2\'bb\'b6\'d4\'cf\'ee\'c4\'bf\'c4\'da\'b5\'c4\'bc\'bc\'ca\'f5
|
||||
\'bf\'c9\'c4\'dc\'b4\'e6\'d4\'da\'ce\'a5\'b7\'b4\'b5\'b1\'b5\'d8\'b7\'a8\'c2\'c9\'b7\'a8\'b9\'e6\'b5\'c4\'d0\'d0\'ce\'aa\'d7\'f7\'b1\'a3\'d6\'a4\'a3\'ac\'bd\'fb\'d6\'b9\'d4\'da\'ce\'a5\'b7\'b4\'b5\'b1\'b5\'d8\'b7\'a8\'c2\'c9\'b7\'a8\'b9\'e6\'b5\'c4
|
||||
\'c7\'e9\'bf\'f6\'cf\'c2\'ca\'b9\'d3\'c3\'b1\'be\'c8\'ed\'bc\'fe\'a3\'ac\'b6\'d4\'d3\'da\'ca\'b9\'d3\'c3\'d5\'df\'d4\'da\'c3\'f7\'d6\'aa\'bb\'f2\'b2\'bb\'d6\'aa\'b5\'b1\'b5\'d8\'b7\'a8\'c2\'c9\'b7\'a8\'b9\'e6\'b2\'bb\'d4\'ca\'d0\'ed\'b5\'c4\'c7\'e9
|
||||
\'bf\'f6\'cf\'c2\'ca\'b9\'d3\'c3\'b1\'be\'c8\'ed\'bc\'fe\'cb\'f9\'d4\'ec\'b3\'c9\'b5\'c4\'c8\'ce\'ba\'ce\'ce\'a5\'b7\'a8\'ce\'a5\'b9\'e6\'d0\'d0\'ce\'aa\'d3\'c9\'ca\'b9\'d3\'c3\'d5\'df\'b3\'d0\'b5\'a3\'a3\'ac\'b1\'be\'c8\'ed\'bc\'fe\'b2\'bb\'b3\'d0
|
||||
\'b5\'a3\'d3\'c9\'b4\'cb\'d4\'ec\'b3\'c9\'b5\'c4\'c8\'ce\'ba\'ce\'d6\'b1\'bd\'d3\'a1\'a2\'bc\'e4\'bd\'d3\'a1\'a2\'cc\'d8\'ca\'e2\'a1\'a2\'c5\'bc\'c8\'bb\'bb\'f2\'bd\'e1\'b9\'fb\'d0\'d4\'d4\'f0\'c8\'ce\'a1\'a3}{\rtlch\fcs1 \af13 \ltrch\fcs0
|
||||
\loch\af13\hich\af13\dbch\af13\insrsid1398824
|
||||
\par }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid15226681
|
||||
\par }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid10447395\charrsid1398824
|
||||
\par }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824 \hich\af13\dbch\af13\loch\f13 * }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824 \loch\af13\hich\af13\dbch\f13
|
||||
\'c8\'f4\'d0\'ad\'d2\'e9\'b8\'fc\'d0\'c2\'a3\'ac\'cb\'a1\'b2\'bb\'c1\'ed\'d0\'d0\'cd\'a8\'d6\'aa\'a3\'ac\'bf\'c9\'b5\'bd\'bf\'aa\'d4\'b4\'b5\'d8\'d6\'b7\'b2\'e9\'bf\'b4\'a1\'a3}{\rtlch\fcs1 \af13 \ltrch\fcs0
|
||||
\loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid15226681
|
||||
\par }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824 \hich\af13\dbch\af13\loch\f13 * }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824 \loch\af13\hich\af13\dbch\f13
|
||||
\'b1\'be\'c8\'ed\'bc\'fe\'b5\'c4\'b3\'f5\'d6\'d4\'ca\'c7\'b0\'ef\'d6\'fa\'b9\'d9\'b7\'bd\'d2\'f4\'c0\'d6\'c6\'bd\'cc\'a8\'bc\'f2\'bb\'af\'ca\'fd\'be\'dd\'ba\'f3\'b4\'fa\'ce\'aa\'d5\'b9\'ca\'be\'a3\'ac\'b0\'ef\'d6\'fa\'ca\'b9\'d3\'c3\'d5\'df\'b8\'f9
|
||||
\'be\'dd\'b8\'e8\'c7\'fa\loch\af13\hich\af13\dbch\f13 \'c3\'fb\'a1\'a2\'d2\'d5\'ca\'f5\'bc\'d2\'b5\'c8\'b9\'d8\'bc\'fc\'d7\'d6\'bf\'ec\'cb\'d9\'b5\'d8\'b6\'a8\'ce\'bb\'cb\'f9\'d0\'e8\'c4\'da\'c8\'dd\'cb\'f9\'d4\'da\'b5\'c4\'d2\'f4\'c0\'d6\'c6\'bd\'cc\'a8
|
||||
\'a1\'a3}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid15226681
|
||||
\par }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824 \hich\af13\dbch\af13\loch\f13 * }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid1398824\charrsid1398824 \loch\af13\hich\af13\dbch\f13
|
||||
\'d2\'f4\'c0\'d6\'c6\'bd\'cc\'a8\'b2\'bb\'d2\'d7\'a3\'ac\'bd\'a8\'d2\'e9\'b5\'bd\'b6\'d4\'d3\'a6\'d2\'f4\'c0\'d6\'c6\'bd\'cc\'a8\'d6\'a7\'b3\'d6\'d5\'fd\'b0\'e6\'d7\'ca\'d4\'b4\'a1\'a3}{\rtlch\fcs1 \af13 \ltrch\fcs0
|
||||
\loch\af13\hich\af13\dbch\af13\insrsid12910709
|
||||
\par }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid9533173\charrsid15226681
|
||||
\par }\pard \ltrpar\s15\qj \li0\ri0\nowidctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12910709 {\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid12910709\charrsid12910709 \hich\af13\dbch\af13\loch\f13 By: }{
|
||||
\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid12910709\charrsid12910709 \loch\af13\hich\af13\dbch\f13 \'c2\'e4\'d1\'a9\'ce\'de\'ba\'db}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid12910709\charrsid12910709
|
||||
\par }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'b4\'ca\'d3\'ef\'d4\'bc\'b6\'a8\'a3\'ba\'b1\'be\'d0\'ad\'d2\'e9\'d6\'d0\'b5\'c4\'a1\'b0\'b1\'be\'cf\'ee\'c4\'bf\'a1\'b1\'d6\'b8}{
|
||||
\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \hich\af13\dbch\af13\loch\f13 LX Music }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\loch\af13\hich\af13\dbch\f13 \'d7\'c0\'c3\'e6\'b0\'e6\'cf\'ee\'c4\'bf\'a3\'bb}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \u8220\'a1\'b0}{\rtlch\fcs1 \af13 \ltrch\fcs0
|
||||
\loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'ca\'b9\'d3\'c3\'d5\'df}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \u8221\'a1\'b1}{\rtlch\fcs1 \af13
|
||||
\ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'d6\'b8\'c7\'a9\'ca\'f0\'b1\'be\'d0\'ad\'d2\'e9\'b5\'c4\'ca\'b9\'d3\'c3\'d5\'df\'a3\'bb}{\rtlch\fcs1 \af13 \ltrch\fcs0
|
||||
\loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \u8220\'a1\'b0}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'b9\'d9\'b7\'bd\'d2\'f4\'c0\'d6\'c6\'bd\'cc\'a8}{
|
||||
\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \u8221\'a1\'b1}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'d6\'b8\'b6\'d4\'b1\'be
|
||||
\'cf\'ee\'c4\'bf\'c4\'da\'d6\'c3\'b5\'c4\'b0\'fc\'c0\'a8\'bf\'e1\'ce\'d2\'a1\'a2\'bf\'e1\'b9\'b7\'a1\'a2\'df\'e4\'b9\'be\'b5\'c8\'d2\'f4\'c0\'d6\'d4\'b4\'b5\'c4\'b9\'d9\'b7\'bd\'c6\'bd\'cc\'a8\'cd\'b3\'b3\'c6\'a3\'bb}{\rtlch\fcs1 \af13 \ltrch\fcs0
|
||||
\loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \u8220\'a1\'b0}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'b0\'e6\'c8\'a8\'ca\'fd\'be\'dd}{\rtlch\fcs1 \af13
|
||||
\ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \u8221\'a1\'b1}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'d6\'b8\'b0\'fc\'c0\'a8\'b5\'ab\'b2\'bb
|
||||
\'cf\'de\'d3\'da\'cd\'bc\'cf\'f1\'a1\'a2\'d2\'f4\'c6\'b5\'a1\'a2\'c3\'fb\'d7\'d6\'b5\'c8\'d4\'da\'c4\'da\'b5\'c4\'cb\'fb\'c8\'cb\'d3\'b5\'d3\'d0\'cb\'f9\'ca\'f4\'b0\'e6\'c8\'a8\'b5\'c4\'ca\'fd\'be\'dd\'a1\'a3}{\rtlch\fcs1 \af13 \ltrch\fcs0
|
||||
\loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\par
|
||||
\par }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'d2\'bb\'a1\'a2\'ca\'fd\'be\'dd\'c0\'b4\'d4\'b4}{\rtlch\fcs1 \af13 \ltrch\fcs0
|
||||
\loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\par
|
||||
\par \hich\af13\dbch\af13\loch\f13 1.1 }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'b1\'be\'cf\'ee\'c4\'bf\'b5\'c4\'b8\'f7\'b9\'d9\'b7\'bd\'c6\'bd\'cc\'a8\'d4\'da\'cf\'df\'ca\'fd
|
||||
\'be\'dd\'c0\'b4\'d4\'b4\'d4\'ad\'c0\'ed\'ca\'c7\'b4\'d3\'c6\'e4\'b9\'ab\'bf\'aa\'b7\'fe\'ce\'f1\'c6\'f7\'d6\'d0\'c0\'ad\'c8\'a1\'ca\'fd\'be\'dd\'a3\'a8\'d3\'eb\'ce\'b4\'b5\'c7\'c2\'bc\'d7\'b4\'cc\'ac\'d4\'da\'b9\'d9\'b7\'bd\'c6\'bd\'cc\'a8}{\rtlch\fcs1
|
||||
\af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \hich\af13\dbch\af13\loch\f13 APP }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'bb\'f1\'c8\'a1
|
||||
\'b5\'c4\'ca\'fd\'be\'dd\'cf\'e0\'cd\'ac\'a3\'a9\'a3\'ac\'be\'ad\'b9\'fd\'b6\'d4\'ca\'fd\'be\'dd\'bc\'f2\'b5\'a5\'b5\'d8\'c9\'b8\'d1\'a1\'d3\'eb\'ba\'cf\'b2\'a2\'ba\'f3\'bd\'f8\'d0\'d0\'d5\'b9\'ca\'be\'a3\'ac\'d2\'f2\'b4\'cb\'b1\'be\'cf\'ee\'c4\'bf
|
||||
\'b2\'bb\'b6\'d4\'ca\'fd\'be\'dd\'b5\'c4\'ba\'cf\'b7\'a8\'d0\'d4\'a1\'a2\'d7\'bc\'c8\'b7\'d0\'d4\'b8\'ba\'d4\'f0\'a1\'a3}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\par
|
||||
\par \hich\af13\dbch\af13\loch\f13 1.2 }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'b1\'be\'cf\'ee\'c4\'bf\'b1\'be\'c9\'ed\'c3\'bb\'d3\'d0\'bb\'f1\'c8\'a1\'c4\'b3\'b8\'f6\'d2\'f4
|
||||
\'c6\'b5\'ca\'fd\'be\'dd\'b5\'c4\'c4\'dc\'c1\'a6\'a3\'ac\'b1\'be\'cf\'ee\'c4\'bf\'ca\'b9\'d3\'c3\'b5\'c4\'d4\'da\'cf\'df\'d2\'f4\'c6\'b5\'ca\'fd\'be\'dd\'c0\'b4\'d4\'b4\'c0\'b4\'d7\'d4\'c8\'ed\'bc\'fe\'c9\'e8\'d6\'c3\'c4\'da}{\rtlch\fcs1 \af13
|
||||
\ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \u8220\'a1\'b0}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'d7\'d4\'b6\'a8\'d2\'e5\'d4\'b4}{
|
||||
\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \u8221\'a1\'b1}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'c9\'e8\'d6\'c3\'cb\'f9
|
||||
\'d1\'a1\'d4\'f1\'b5\'c4}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \u8220\'a1\'b0}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\loch\af13\hich\af13\dbch\f13 \'d4\'b4}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \u8221\'a1\'b1}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\loch\af13\hich\af13\dbch\f13 \'b7\'b5\'bb\'d8\'b5\'c4\'d4\'da\'cf\'df\'c1\'b4\'bd\'d3\'a1\'a3\'c0\'fd\'c8\'e7\'b2\'a5\'b7\'c5\'c4\'b3\'ca\'d7\'b8\'e8\'a3\'ac\'b1\'be\'cf\'ee\'c4\'bf\'cb\'f9\'d7\'f6\'b5\'c4\'d6\'bb\'ca\'c7\'bd\'ab\'cf\'a3\'cd\'fb\'b2\'a5
|
||||
\'b7\'c5\'b5\'c4\'b8\'e8\'c7\'fa\'c3\'fb\'a1\'a2\'d2\'d5\'ca\'f5\'bc\'d2\'b5\'c8\'d0\'c5\'cf\'a2\'b4\'ab\'b5\'dd\'b8\'f8}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \u8220\'a1\'b0}{\rtlch\fcs1 \af13
|
||||
\ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'d4\'b4}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \u8221\'a1\'b1}{\rtlch\fcs1 \af13 \ltrch\fcs0
|
||||
\loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'a3\'ac\'c8\'f4}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \u8220\'a1\'b0}{\rtlch\fcs1 \af13 \ltrch\fcs0
|
||||
\loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'d4\'b4}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \u8221\'a1\'b1}{\rtlch\fcs1 \af13 \ltrch\fcs0
|
||||
\loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'b7\'b5\'bb\'d8\'c1\'cb\'d2\'bb\'b8\'f6\'c1\'b4\'bd\'d3\'a3\'ac\'d4\'f2\'b1\'be\'cf\'ee\'c4\'bf\'bd\'ab\'c8\'cf\'ce\'aa\'d5\'e2\'be\'cd\'ca\'c7\'b8\'c3\'b8\'e8
|
||||
\'c7\'fa\'b5\'c4\'d2\'f4\'c6\'b5\'ca\'fd\'be\'dd\'b6\'f8\'bd\'f8\'d0\'d0\'ca\'b9\'d3\'c3\'a3\'ac\'d6\'c1\'d3\'da\'d5\'e2\'ca\'c7\'b2\'bb\'ca\'c7\'d5\'fd\'c8\'b7\'b5\'c4\'d2\'f4\'c6\'b5\'ca\'fd\'be\'dd\'b1\'be\'cf\'ee\'c4\'bf\'ce\'de\'b7\'a8\'d0\'a3
|
||||
\'d1\'e9\'c6\'e4\'d7\'bc\'c8\'b7\'d0\'d4\'a3\'ac\'cb\'f9\'d2\'d4\'ca\'b9\'d3\'c3\'b1\'be\'cf\'ee\'c4\'bf\'b5\'c4\'b9\'fd\'b3\'cc\'d6\'d0\'bf\'c9\'c4\'dc\'bb\'e1\'b3\'f6\'cf\'d6\'cf\'a3\'cd\'fb\'b2\'a5\'b7\'c5\'b5\'c4\'d2\'f4\'c6\'b5\'d3\'eb\'ca\'b5
|
||||
\'bc\'ca\'b2\'a5\'b7\'c5\'b5\'c4\'d2\'f4\'c6\'b5\'b2\'bb\'b6\'d4\'d3\'a6\'bb\'f2\'d5\'df\'ce\'de\'b7\'a8\'b2\'a5\'b7\'c5\'b5\'c4\'ce\'ca\'cc\'e2\'a1\'a3}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\par
|
||||
\par \hich\af13\dbch\af13\loch\f13 1.3 }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'b1\'be\'cf\'ee\'c4\'bf\'b5\'c4\'b7\'c7\'b9\'d9\'b7\'bd\'c6\'bd\'cc\'a8\'ca\'fd\'be\'dd\'a3\'a8
|
||||
\'c0\'fd\'c8\'e7}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \u8220\'a1\'b0}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13
|
||||
\'ce\'d2\'b5\'c4\'c1\'d0\'b1\'ed}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \u8221\'a1\'b1}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\loch\af13\hich\af13\dbch\f13 \'c4\'da\'c1\'d0\'b1\'ed\'a3\'a9\'c0\'b4\'d7\'d4\'ca\'b9\'d3\'c3\'d5\'df\'b1\'be\'b5\'d8\'cf\'b5\'cd\'b3\'bb\'f2\'d5\'df\'ca\'b9\'d3\'c3\'d5\'df\'c1\'ac\'bd\'d3\'b5\'c4\'cd\'ac\'b2\'bd\'b7\'fe\'ce\'f1\'a3\'ac\'b1\'be\'cf\'ee
|
||||
\'c4\'bf\'b2\'bb\'b6\'d4\'d5\'e2\'d0\'a9\'ca\'fd\'be\'dd\'b5\'c4\'ba\'cf\'b7\'a8\'d0\'d4\'a1\'a2\'d7\'bc\'c8\'b7\'d0\'d4\'b8\'ba\'d4\'f0\'a1\'a3}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\par
|
||||
\par }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'b6\'fe\'a1\'a2\'b0\'e6\'c8\'a8\'ca\'fd\'be\'dd}{\rtlch\fcs1 \af13 \ltrch\fcs0
|
||||
\loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\par
|
||||
\par \hich\af13\dbch\af13\loch\f13 2\hich\af13\dbch\af13\loch\f13 .1 }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'ca\'b9\'d3\'c3\'b1\'be\'cf\'ee\'c4\'bf\'b5\'c4\'b9\'fd\'b3\'cc
|
||||
\'d6\'d0\'bf\'c9\'c4\'dc\'bb\'e1\'b2\'fa\'c9\'fa\'b0\'e6\'c8\'a8\'ca\'fd\'be\'dd\'a1\'a3\'b6\'d4\'d3\'da\'d5\'e2\'d0\'a9\'b0\'e6\'c8\'a8\'ca\'fd\'be\'dd\'a3\'ac\'b1\'be\'cf\'ee\'c4\'bf\'b2\'bb\'d3\'b5\'d3\'d0\'cb\'fc\'c3\'c7\'b5\'c4\'cb\'f9\'d3\'d0
|
||||
\'c8\'a8\'a1\'a3\'ce\'aa\'c1\'cb\'b1\'dc\'c3\'e2\'c7\'d6\'c8\'a8\'a3\'ac\'ca\'b9\'d3\'c3\'d5\'df\'ce\'f1\'b1\'d8\'d4\'da}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \hich\af13\dbch\af13\loch\f13 **24 }{
|
||||
\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'d0\'a1\'ca\'b1\'c4\'da}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\hich\af13\dbch\af13\loch\f13 ** }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'c7\'e5\'b3\'fd\'ca\'b9\'d3\'c3\'b1\'be\'cf\'ee\'c4\'bf\'b5\'c4\'b9\'fd\'b3\'cc\'d6\'d0\'cb\'f9
|
||||
\'b2\'fa\'c9\'fa\'b5\'c4\'b0\'e6\'c8\'a8\'ca\'fd\'be\'dd\'a1\'a3}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\par
|
||||
\par }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'c8\'fd\'a1\'a2\'d2\'f4\'c0\'d6\'c6\'bd\'cc\'a8\'b1\'f0\'c3\'fb}{\rtlch\fcs1 \af13 \ltrch\fcs0
|
||||
\loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\par
|
||||
\par \hich\af13\dbch\af13\loch\f13 3.1 }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'b1\'be\'cf\'ee\'c4\'bf\'c4\'da\'b5\'c4\'b9\'d9\'b7\'bd\'d2\'f4\'c0\'d6\'c6\'bd\'cc\'a8\'b1\'f0
|
||||
\'c3\'fb\'ce\'aa\'b1\'be\'cf\'ee\'c4\'bf\'c4\'da\'b6\'d4\'b9\'d9\'b7\'bd\'d2\'f4\'c0\'d6\'c6\'bd\'cc\'a8\'b5\'c4\'d2\'bb\'b8\'f6\'b3\'c6\'ba\'f4\'a3\'ac\'b2\'bb\'b0\'fc\'ba\'ac\'b6\'f1\'d2\'e2\'a1\'a3\'c8\'e7\'b9\'fb\'b9\'d9\'b7\'bd\'d2\'f4\'c0\'d6
|
||||
\'c6\'bd\'cc\'a8\'be\'f5\'b5\'c3\'b2\'bb\'cd\'d7\'a3\'ac\'bf\'c9\'c1\'aa\'cf\'b5\'b1\'be\'cf\'ee\'c4\'bf\'b8\'fc\'b8\'c4\'bb\'f2\'d2\'c6\'b3\'fd\'a1\'a3}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\par
|
||||
\par }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'cb\'c4\'a1\'a2\'d7\'ca\'d4\'b4\'ca\'b9\'d3\'c3}{\rtlch\fcs1 \af13 \ltrch\fcs0
|
||||
\loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\par
|
||||
\par \hich\af13\dbch\af13\loch\f13 4.1 }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'b1\'be\'cf\'ee\'c4\'bf\'c4\'da\'ca\'b9\'d3\'c3\'b5\'c4\'b2\'bf\'b7\'d6\'b0\'fc\'c0\'a8\'b5\'ab
|
||||
\'b2\'bb\'cf\'de\'d3\'da\'d7\'d6\'cc\'e5\'a1\'a2\'cd\'bc\'c6\'ac\'b5\'c8\'d7\'ca\'d4\'b4\'c0\'b4\'d4\'b4\'d3\'da\'bb\'a5\'c1\'aa\'cd\'f8\'a1\'a3\'c8\'e7\'b9\'fb\'b3\'f6\'cf\'d6\'c7\'d6\'c8\'a8\'bf\'c9\'c1\'aa\'cf\'b5\'b1\'be\'cf\'ee\'c4\'bf\'d2\'c6
|
||||
\'b3\'fd\'a1\'a3}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\par
|
||||
\par }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'ce\'e5\'a1\'a2\'c3\'e2\'d4\'f0\'c9\'f9\'c3\'f7}{\rtlch\fcs1 \af13 \ltrch\fcs0
|
||||
\loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\par
|
||||
\par \hich\af13\dbch\af13\loch\f13 5.1 }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'d3\'c9\'d3\'da\'ca\'b9\'d3\'c3\'b1\'be\'cf\'ee\'c4\'bf\'b2\'fa\'c9\'fa\'b5\'c4\'b0\'fc\'c0\'a8
|
||||
\'d3\'c9\'d3\'da\'b1\'be\'d0\'ad\'d2\'e9\'bb\'f2\'d3\'c9\'d3\'da\'ca\'b9\'d3\'c3\'bb\'f2\'ce\'de\'b7\'a8\'ca\'b9\'d3\'c3\'b1\'be\'cf\'ee\'c4\'bf\'b6\'f8\'d2\'fd\'c6\'f0\'b5\'c4\'c8\'ce\'ba\'ce\'d0\'d4\'d6\'ca\'b5\'c4\'c8\'ce\'ba\'ce\'d6\'b1\'bd\'d3
|
||||
\'a1\'a2\'bc\'e4\'bd\'d3\'a1\'a2\'cc\'d8\'ca\'e2\'a1\'a2\'c5\'bc\'c8\'bb\'bb\'f2\'bd\'e1\'b9\'fb\'d0\'d4\'cb\'f0\'ba\'a6\'a3\'a8\'b0\'fc\'c0\'a8\'b5\'ab\'b2\'bb\'cf\'de\'d3\'da\'d2\'f2\'c9\'cc\'d3\'fe\'cb\'f0\'ca\'a7\'a1\'a2\'cd\'a3\'b9\'a4\'a1\'a2
|
||||
\'bc\'c6\'cb\'e3\'bb\'fa\'b9\'ca\'d5\'cf\'bb\'f2\'b9\'ca\'d5\'cf\'d2\'fd\'c6\'f0\'b5\'c4\'cb\'f0\'ba\'a6\'c5\'e2\'b3\'a5\'a3\'ac\'bb\'f2\'c8\'ce\'ba\'ce\'bc\'b0\'cb\'f9\'d3\'d0\'c6\'e4\'cb\'fb\'c9\'cc\'d2\'b5\'cb\'f0\'ba\'a6\'bb\'f2\'cb\'f0\'ca\'a7
|
||||
\'a3\'a9\'d3\'c9\'ca\'b9\'d3\'c3\'d5\'df\'b8\'ba\'d4\'f0\'a1\'a3}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\par
|
||||
\par }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'c1\'f9\'a1\'a2\'ca\'b9\'d3\'c3\'cf\'de\'d6\'c6}{\rtlch\fcs1 \af13 \ltrch\fcs0
|
||||
\loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\par
|
||||
\par \hich\af13\dbch\af13\loch\f13 6.1 }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'b1\'be\'cf\'ee\'c4\'bf\'cd\'ea\'c8\'ab\'c3\'e2\'b7\'d1\'a3\'ac\'c7\'d2\'bf\'aa\'d4\'b4\'b7\'a2
|
||||
\'b2\'bc\'d3\'da}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \hich\af13\dbch\af13\loch\f13 GitHub }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\loch\af13\hich\af13\dbch\f13 \'c3\'e6\'cf\'f2\'c8\'ab\'ca\'c0\'bd\'e7\'c8\'cb\'d3\'c3\'d7\'f7\'b6\'d4\'bc\'bc\'ca\'f5\'b5\'c4\'d1\'a7\'cf\'b0\'bd\'bb\'c1\'f7\'a1\'a3\'b1\'be\'cf\'ee\'c4\'bf\'b2\'bb\'b6\'d4\'cf\'ee\'c4\'bf\'c4\'da\'b5\'c4\'bc\'bc\'ca\'f5
|
||||
\'bf\'c9\'c4\'dc\'b4\'e6\'d4\'da\'ce\'a5\'b7\'b4\'b5\'b1\'b5\'d8\'b7\'a8\'c2\'c9\'b7\'a8\'b9\'e6\'b5\'c4\'d0\'d0\'ce\'aa\'d7\'f7\'b1\'a3\'d6\'a4\'a1\'a3}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\par
|
||||
\par \hich\af13\dbch\af13\loch\f13 6.2 **}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'bd\'fb\'d6\'b9\'d4\'da\'ce\'a5\'b7\'b4\'b5\'b1\'b5\'d8\'b7\'a8\'c2\'c9\'b7\'a8\'b9\'e6
|
||||
\'b5\'c4\'c7\'e9\'bf\'f6\'cf\'c2\'ca\'b9\'d3\'c3\'b1\'be\'cf\'ee\'c4\'bf\'a1\'a3}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \hich\af13\dbch\af13\loch\f13 ** }{\rtlch\fcs1 \af13 \ltrch\fcs0
|
||||
\loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'b6\'d4\'d3\'da\'ca\'b9\'d3\'c3\'d5\'df\'d4\'da\'c3\'f7\'d6\'aa\'bb\'f2\'b2\'bb\'d6\'aa\'b5\'b1\'b5\'d8\'b7\'a8\'c2\'c9\'b7\'a8\'b9\'e6\'b2\'bb\'d4\'ca\'d0\'ed
|
||||
\'b5\'c4\'c7\'e9\'bf\'f6\'cf\'c2\'ca\'b9\'d3\'c3\'b1\'be\'cf\'ee\'c4\'bf\'cb\'f9\'d4\'ec\'b3\'c9\'b5\'c4\'c8\'ce\'ba\'ce\'ce\'a5\'b7\'a8\'ce\'a5\'b9\'e6\'d0\'d0\'ce\'aa\'d3\'c9\'ca\'b9\'d3\'c3\'d5\'df\'b3\'d0\'b5\'a3\'a3\'ac\'b1\'be\'cf\'ee\'c4\'bf
|
||||
\'b2\'bb\'b3\'d0\'b5\'a3\'d3\'c9\'b4\'cb\'d4\'ec\'b3\'c9\'b5\'c4\'c8\'ce\'ba\'ce\'d6\'b1\'bd\'d3\'a1\'a2\'bc\'e4\'bd\'d3\'a1\'a2\'cc\'d8\'ca\'e2\'a1\'a2\'c5\'bc\'c8\'bb\'bb\'f2\'bd\'e1\'b9\'fb\'d0\'d4\'d4\'f0\'c8\'ce\'a1\'a3}{\rtlch\fcs1 \af13
|
||||
\ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\par
|
||||
\par }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'c6\'df\'a1\'a2\'b0\'e6\'c8\'a8\'b1\'a3\'bb\'a4}{\rtlch\fcs1 \af13 \ltrch\fcs0
|
||||
\loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\par
|
||||
\par \hich\af13\dbch\af13\loch\f13 7.1 }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'d2\'f4\'c0\'d6\'c6\'bd\'cc\'a8\'b2\'bb\'d2\'d7\'a3\'ac\'c7\'eb\'d7\'f0\'d6\'d8\'b0\'e6\'c8\'a8
|
||||
\'a3\'ac\'d6\'a7\'b3\'d6\'d5\'fd\'b0\'e6\'a1\'a3}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\par
|
||||
\par }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'b0\'cb\'a1\'a2\'b7\'c7\'c9\'cc\'d2\'b5\'d0\'d4\'d6\'ca}{\rtlch\fcs1 \af13 \ltrch\fcs0
|
||||
\loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\par
|
||||
\par \hich\af13\dbch\af13\loch\f13 8.1 }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'b1\'be\'cf\'ee\'c4\'bf\'bd\'f6\'d3\'c3\'d3\'da\'b6\'d4\'bc\'bc\'ca\'f5\'bf\'c9\'d0\'d0\'d0\'d4
|
||||
\'b5\'c4\'cc\'bd\'cb\'f7\'bc\'b0\'d1\'d0\'be\'bf\'a3\'ac\'b2\'bb\'bd\'d3\'ca\'dc\'c8\'ce\'ba\'ce\'c9\'cc\'d2\'b5\'a3\'a8\'b0\'fc\'c0\'a8\'b5\'ab\'b2\'bb\'cf\'de\'d3\'da\'b9\'e3\'b8\'e6\'b5\'c8\'a3\'a9\'ba\'cf\'d7\'f7\'bc\'b0\'be\'e8\'d4\'f9\'a1\'a3}{
|
||||
\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\par
|
||||
\par }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'be\'c5\'a1\'a2\'bd\'d3\'ca\'dc\'d0\'ad\'d2\'e9}{\rtlch\fcs1 \af13 \ltrch\fcs0
|
||||
\loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\par
|
||||
\par \hich\af13\dbch\af13\loch\f13 9.1 }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'c8\'f4\'c4\'e3\'ca\'b9\'d3\'c3\'c1\'cb\'b1\'be\'cf\'ee\'c4\'bf\'a3\'ac\'bc\'b4\'b4\'fa\'b1\'ed
|
||||
\'c4\'e3\'bd\'d3\'ca\'dc\'b1\'be\'d0\'ad\'d2\'e9\'a1\'a3}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\par
|
||||
\par \hich\af13\dbch\af13\loch\f13 * }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'c8\'f4\'d0\'ad\'d2\'e9\'b8\'fc\'d0\'c2\'a3\'ac\'cb\'a1\'b2\'bb\'c1\'ed\'d0\'d0\'cd\'a8\'d6\'aa
|
||||
\'a3\'ac\'bf\'c9\'b5\'bd\'bf\'aa\'d4\'b4\'b5\'d8\'d6\'b7\'b2\'e9\'bf\'b4\'a1\'a3}{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548
|
||||
\par
|
||||
\par \hich\af13\dbch\af13\loch\f13 By: }{\rtlch\fcs1 \af13 \ltrch\fcs0 \loch\af13\hich\af13\dbch\af13\insrsid2766548\charrsid2766548 \loch\af13\hich\af13\dbch\f13 \'c2\'e4\'d1\'a9\'ce\'de\'ba\'db}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid12910709\charrsid2766548
|
||||
|
||||
\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a
|
||||
9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad
|
||||
@@ -255,8 +320,8 @@ fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e5000000000000000000000000b026
|
||||
8d59201dd601feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000
|
||||
ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e5000000000000000000000000d096
|
||||
bf3efc84db01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000105000000000000}}
|
||||
@@ -1,18 +1,52 @@
|
||||
This project (software) is issued based on the Apache License 2.0 license. Before using this software, you (users) need to sign this agreement before you can continue to use it. The following agreement is a supplement to the Apache License 2.0. In case of conflict, use the following agreement Shall prevail.
|
||||
This project is issued based on the Apache License 2.0 license. The following agreements are supplemental to the Apache License 2.0. In the event of a conflict, the following agreements shall prevail.
|
||||
|
||||
DEFINITIONS:
|
||||
|
||||
Terms agreed: "this software" in this agreement refers to the Luo Xue Music desktop version of the project; "user" refers to the user who signed this agreement; "official music platform" refers to the built-in software including Kuwo, Kugou, Migu The official platforms of music sources, etc. are collectively referred to; "copyright data" refers to data including but not limited to images, audio, names, etc. that others own the copyright.
|
||||
"This Project" refers to the LX Music Desktop Edition (aka lx-music-desktop) project. "User" refers to the user who signed this agreement. "Official Music Streaming Service" refers to collectively the official streaming service corresponding to the music source. "Copyrighted Data" refers to data including, but not limited to, pictures, audio, names, etc., for which others own the copyright.
|
||||
|
||||
1. The principle of the data source of this software is to pull data from the public servers of each official music platform. After simply filtering and merging the data for display, this software is not responsible for the accuracy of the data.
|
||||
2. Copyright data may be generated during the use of this software. For this copyright data, the software does not own their ownership. In order to avoid infringement, users must clear the copyright generated during the use of this software within 24 hours data.
|
||||
3. The alias of the official music platform in this software is a name for the official music platform in the software. It does not contain maliciousness. If the official music platform feels inappropriate, you can contact the software to change or remove it.
|
||||
4. The parts used in this software include but are not limited to fonts, pictures and other resources from the Internet. If there is infringement, you can contact this software to remove it.
|
||||
5. Any direct, indirect, special, accidental or consequential damage of any nature arising from the use of this software, including this agreement or the use or inability to use this software (including but not limited to due to loss of goodwill, work stoppage, Compensation for computer failure or damage caused by the failure, or any and all other commercial damage or loss) is the responsibility of the user.
|
||||
6. This project is completely free, and the open source is published on GitHub. It is used by people all over the world to learn and exchange technology. This software does not guarantee that the technology in the project may violate local laws and regulations. It is prohibited to violate local laws and regulations. Using this software, the user shall be responsible for any violations caused by the user's use of the software without knowing or not permitted by local laws and regulations. The software shall not be responsible for any direct, indirect, special, accidental Or consequential responsibility.
|
||||
1. Data Source
|
||||
|
||||
1.1 The principle of the online data sources of the various official music streaming services of this project is to draw data from its open servers (the same as the data obtained in the unlogged-in state in the official music streaming service app). After simply screening and merging the data, this project is responsible for the legitimacy and accuracy of the data.
|
||||
|
||||
* If the agreement is updated without prior notice, you can check it at the open source address.
|
||||
* The original intention of this software is to help the official music platform to simplify the data generation for display, and to help users quickly locate the music platform where the desired content is based on the song title, artist and other keywords.
|
||||
* Music platform is not easy, it is recommended to support genuine resources to the corresponding music platform.
|
||||
1.2 The ability of this project itself does not obtain certain audio data. The online audio data source used in this project comes from the online link provided by the "API" selected in the software settings. For example, when playing a song, this project only transmits information such as the song title, artist, and other information to the "API". If the "API" returns a link, this project will think that this is the audio data of the song for use, but as for whether this is the correct audio data, this project cannot verify its accuracy. So, in the process of using this project, there may be a problem that the audio you want to play does not correspond to the audio you actually play, or you cannot play it.
|
||||
|
||||
1.3 Data in this project other than official music streaming service (such as lists in "Your Library") comes from the user's local system or a synchronization service that the user connected to. This project is not responsible for the legality and accuracy of this data.
|
||||
|
||||
2. Copyrighted Data
|
||||
|
||||
2.1 During the process of using this project, copyrighted data may be generated. For this copyrighted data, this project does not have their ownership. In order to avoid infringement, users must remove copyrighted data generated during the process of using this project ** within 24 hours **.
|
||||
|
||||
3. Alias of Music Streaming Service
|
||||
|
||||
3.1 The official music streaming service alias within this project is a term used within this project to refer to the official music streaming service and does not contain malicious intent. If the operator of the official music streaming service feels it is inappropriate, you can contact this project to request changes or removals.
|
||||
|
||||
4. Use of Resources
|
||||
|
||||
4.1 The parts used in this project include, but are not limited to, fonts, pictures, and other resources from the Internet. If infringement occurs, you can contact this project.
|
||||
|
||||
5. Disclaimer
|
||||
|
||||
5.1 The use of this project includes any direct, indirect, special, accidental, or result damage due to any nature caused by this agreement or use or inability to use this item (including but not limited to the loss of goodwill, stop work, computer, computer Damage compensation caused by faults or any or all other commercial damage or losses) is the responsibility of users.
|
||||
|
||||
6. Use Restrictions
|
||||
|
||||
6.1 This project is completely free and open source and is published on GitHub for the learning exchanges of technology for people all over the world. This project does not guarantee that the technology in this project may violate local laws and regulations.
|
||||
|
||||
6.2 ** This project is prohibited in violation of local laws and regulations. ** The user is solely responsible for any violation of law caused by the use of this project that the user knows or does not know is not permitted by local law and regulations.
|
||||
|
||||
7. Copyright Protection
|
||||
|
||||
7.1 The operation of a music streaming service is not an easy task. Please respect copyrights and support the genuine.
|
||||
|
||||
8. Non-commercial Nature
|
||||
|
||||
8.1 This project is only used for exploring and research on technical feasibility and does not accept any business (including but not limited to advertising, etc.) cooperation and donations.
|
||||
|
||||
9. Accepting Agreement
|
||||
|
||||
9.1 If you use this project, it will represent you accept this agreement.
|
||||
|
||||
* If the agreement is updated, you will not be notified separately. You can check it out by visiting the project address.
|
||||
* The content of this agreement is translated from the Chinese version of the agreement.
|
||||
|
||||
By: lyswhut
|
||||
|
||||
@@ -1,18 +1,49 @@
|
||||
本项目(软件)基于Apache License 2.0 许可证发行,在使用本软件前,你(使用者)需签署本协议才可继续使用,以下协议是对于 Apache License 2.0 的补充,如有冲突,以以下协议为准。
|
||||
本项目基于 Apache License 2.0 许可证发行,以下协议是对于 Apache License 2.0 的补充,如有冲突,以以下协议为准。
|
||||
|
||||
词语约定:本协议中的“本项目”指 LX Music 桌面版项目;“使用者”指签署本协议的使用者;“官方音乐平台”指对本项目内置的包括酷我、酷狗、咪咕等音乐源的官方平台统称;“版权数据”指包括但不限于图像、音频、名字等在内的他人拥有所属版权的数据。
|
||||
|
||||
词语约定:本协议中的“本软件”指洛雪音乐桌面版项目;“使用者”指签署本协议的使用者;“官方音乐平台”指对本软件内置的包括酷我、酷狗、咪咕等音乐源的官方平台统称;“版权数据”指包括但不限于图像、音频、名字等在内的他人拥有所属版权的数据。
|
||||
一、数据来源
|
||||
|
||||
1、本软件的数据来源原理是从各官方音乐平台的公开服务器中拉取数据,经过对数据简单地筛选与合并后进行展示,因此本软件不对数据的准确性负责。
|
||||
2、使用本软件的过程中可能会产生版权数据,对于这些版权数据,本软件不拥有它们的所有权,为了避免造成侵权,使用者务必在24小时内清除使用本软件的过程中所产生的版权数据。
|
||||
3、本软件内的官方音乐平台别名为本软件内对官方音乐平台的一个称呼,不包含恶意,如果官方音乐平台觉得不妥,可联系本软件更改或移除。
|
||||
4、本软件内使用的部分包括但不限于字体、图片等资源来源于互联网,如果出现侵权可联系本软件移除。
|
||||
5、由于使用本软件产生的包括由于本协议或由于使用或无法使用本软件而引起的任何性质的任何直接、间接、特殊、偶然或结果性损害(包括但不限于因商誉损失、停工、计算机故障或故障引起的损害赔偿,或任何及所有其他商业损害或损失)由使用者负责。
|
||||
6、本项目完全免费,且开源发布于 GitHub 面向全世界人用作对技术的学习交流,本软件不对项目内的技术可能存在违反当地法律法规的行为作保证,禁止在违反当地法律法规的情况下使用本软件,对于使用者在明知或不知当地法律法规不允许的情况下使用本软件所造成的任何违法违规行为由使用者承担,本软件不承担由此造成的任何直接、间接、特殊、偶然或结果性责任。
|
||||
1.1 本项目的各官方平台在线数据来源原理是从其公开服务器中拉取数据(与未登录状态在官方平台 APP 获取的数据相同),经过对数据简单地筛选与合并后进行展示,因此本项目不对数据的合法性、准确性负责。
|
||||
|
||||
1.2 本项目本身没有获取某个音频数据的能力,本项目使用的在线音频数据来源来自软件设置内“自定义源”设置所选择的“源”返回的在线链接。例如播放某首歌,本项目所做的只是将希望播放的歌曲名、艺术家等信息传递给“源”,若“源”返回了一个链接,则本项目将认为这就是该歌曲的音频数据而进行使用,至于这是不是正确的音频数据本项目无法校验其准确性,所以使用本项目的过程中可能会出现希望播放的音频与实际播放的音频不对应或者无法播放的问题。
|
||||
|
||||
1.3 本项目的非官方平台数据(例如“我的列表”内列表)来自使用者本地系统或者使用者连接的同步服务,本项目不对这些数据的合法性、准确性负责。
|
||||
|
||||
二、版权数据
|
||||
|
||||
2.1 使用本项目的过程中可能会产生版权数据。对于这些版权数据,本项目不拥有它们的所有权。为了避免侵权,使用者务必在 **24 小时内** 清除使用本项目的过程中所产生的版权数据。
|
||||
|
||||
三、音乐平台别名
|
||||
|
||||
3.1 本项目内的官方音乐平台别名为本项目内对官方音乐平台的一个称呼,不包含恶意。如果官方音乐平台觉得不妥,可联系本项目更改或移除。
|
||||
|
||||
四、资源使用
|
||||
|
||||
4.1 本项目内使用的部分包括但不限于字体、图片等资源来源于互联网。如果出现侵权可联系本项目移除。
|
||||
|
||||
五、免责声明
|
||||
|
||||
5.1 由于使用本项目产生的包括由于本协议或由于使用或无法使用本项目而引起的任何性质的任何直接、间接、特殊、偶然或结果性损害(包括但不限于因商誉损失、停工、计算机故障或故障引起的损害赔偿,或任何及所有其他商业损害或损失)由使用者负责。
|
||||
|
||||
六、使用限制
|
||||
|
||||
6.1 本项目完全免费,且开源发布于 GitHub 面向全世界人用作对技术的学习交流。本项目不对项目内的技术可能存在违反当地法律法规的行为作保证。
|
||||
|
||||
6.2 **禁止在违反当地法律法规的情况下使用本项目。** 对于使用者在明知或不知当地法律法规不允许的情况下使用本项目所造成的任何违法违规行为由使用者承担,本项目不承担由此造成的任何直接、间接、特殊、偶然或结果性责任。
|
||||
|
||||
七、版权保护
|
||||
|
||||
7.1 音乐平台不易,请尊重版权,支持正版。
|
||||
|
||||
八、非商业性质
|
||||
|
||||
8.1 本项目仅用于对技术可行性的探索及研究,不接受任何商业(包括但不限于广告等)合作及捐赠。
|
||||
|
||||
九、接受协议
|
||||
|
||||
9.1 若你使用了本项目,即代表你接受本协议。
|
||||
|
||||
* 若协议更新,恕不另行通知,可到开源地址查看。
|
||||
* 本软件的初衷是帮助官方音乐平台简化数据后代为展示,帮助使用者根据歌曲名、艺术家等关键字快速地定位所需内容所在的音乐平台。
|
||||
* 音乐平台不易,建议到对应音乐平台支持正版资源。
|
||||
|
||||
By: 落雪无痕
|
||||
|
||||
33149
package-lock.json
generated
381
package.json
@@ -1,163 +1,92 @@
|
||||
{
|
||||
"name": "lx-music-desktop",
|
||||
"version": "1.22.0",
|
||||
"version": "2.12.1",
|
||||
"description": "一个免费的音乐查找助手",
|
||||
"main": "./dist/main.js",
|
||||
"productName": "lx-music-desktop",
|
||||
"scripts": {
|
||||
"pack": "node build-config/pack.js && npm run pack:win:setup:x64",
|
||||
"pack:win": "node build-config/pack.js && npm run pack:win:setup:x64 && npm run pack:win:setup:x86 && npm run pack:win:setup:arm64 && npm run pack:win:setup:x86_64 && npm run pack:win:7z",
|
||||
"pack:win:setup:x86_64": "cross-env TARGET=Setup ARCH=x86_64 electron-builder -w=nsis --x64 --ia32 -p never",
|
||||
"pack:win:setup:x64": "cross-env TARGET=Setup ARCH=x64 electron-builder -w=nsis --x64 -p never",
|
||||
"pack:win:setup:x86": "cross-env TARGET=Setup ARCH=x86 electron-builder -w=nsis --ia32 -p never",
|
||||
"pack:win:setup:arm64": "cross-env TARGET=Setup ARCH=arm64 electron-builder -w=nsis --arm64 -p never",
|
||||
"pack:win:setup:x86_64": "node build-config/build-pack.js target=win arch=x86_64 type=setup",
|
||||
"pack:win:setup:x64": "node build-config/build-pack.js target=win arch=x64 type=setup",
|
||||
"pack:win:setup:x86": "node build-config/build-pack.js target=win arch=x86 type=setup",
|
||||
"pack:win:setup:arm64": "node build-config/build-pack.js target=win arch=arm64 type=setup",
|
||||
"pack:win:portable": "npm run pack:win:portable:x86_64 && npm run pack:win:portable:x64 && npm run pack:win:portable:x86",
|
||||
"pack:win:portable:x86_64": "cross-env TARGET=portable ARCH=x86_64 electron-builder -w=portable --x64 --ia32 -p never",
|
||||
"pack:win:portable:x64": "cross-env TARGET=portable ARCH=x64 electron-builder -w=portable --x64 -p never",
|
||||
"pack:win:portable:x86": "cross-env TARGET=portable ARCH=x86 electron-builder -w=portable --ia32 -p never",
|
||||
"pack:win:7z": "npm run pack:win:7z:x64 && npm run pack:win:7z:x86",
|
||||
"pack:win:7z:x64": "cross-env TARGET=green ARCH=win_x64 electron-builder -w=7z --x64 -p never",
|
||||
"pack:win:7z:x86": "cross-env TARGET=green ARCH=win_x86 electron-builder -w=7z --ia32 -p never",
|
||||
"pack:win:7z:arm64": "cross-env TARGET=green ARCH=win_arm64 electron-builder -w=7z --arm64 -p never",
|
||||
"pack:win:portable:x86_64": "node build-config/build-pack.js target=win arch=x86_64 type=portable",
|
||||
"pack:win:portable:x64": "node build-config/build-pack.js target=win arch=x64 type=portable",
|
||||
"pack:win:portable:x86": "node build-config/build-pack.js target=win arch=x86 type=portable",
|
||||
"pack:win:7z": "npm run pack:win:7z:x64",
|
||||
"pack:win:7z:x64": "node build-config/build-pack.js target=win arch=x64 type=green",
|
||||
"pack:win:7z:arm64": "node build-config/build-pack.js target=win arch=arm64 type=green",
|
||||
"pack:win7:setup:x64": "node build-config/build-pack.js target=win arch=x64 type=win7_setup",
|
||||
"pack:win7:7z:x64": "node build-config/build-pack.js target=win arch=x64 type=win7_green",
|
||||
"pack:win7:7z:x86": "node build-config/build-pack.js target=win arch=x86 type=win7_green",
|
||||
"pack:linux": "node build-config/pack.js && npm run pack:linux:deb && npm run pack:linux:appImage && npm run pack:linux:rpm && npm run pack:linux:pacman",
|
||||
"pack:linux:appImage": "cross-env ARCH=x64 electron-builder -l=AppImage -p never",
|
||||
"pack:linux:deb": "npm run pack:linux:deb:x64 && npm run pack:linux:deb:x86 && npm run pack:linux:deb:arm64 && npm run pack:linux:deb:armv7l",
|
||||
"pack:linux:deb:x64": "cross-env ARCH=x64 electron-builder -l=deb --x64 -p never",
|
||||
"pack:linux:deb:x86": "cross-env ARCH=x86 electron-builder -l=deb --ia32 -p never",
|
||||
"pack:linux:deb:arm64": "cross-env ARCH=arm64 electron-builder -l=deb --arm64 -p never",
|
||||
"pack:linux:deb:armv7l": "cross-env ARCH=armv7l electron-builder -l=deb --armv7l -p never",
|
||||
"pack:linux:rpm": "cross-env ARCH=x64 electron-builder -l=rpm --x64 -p never",
|
||||
"pack:linux:pacman": "cross-env ARCH=x64 electron-builder -l=pacman --x64 -p never",
|
||||
"pack:linux:appImage": "node build-config/build-pack.js target=linux arch=x64 type=appImage",
|
||||
"pack:linux:deb": "npm run pack:linux:deb:amd64 && npm run pack:linux:deb:arm64 && npm run pack:linux:deb:armv7l",
|
||||
"pack:linux:deb:amd64": "node build-config/build-pack.js target=linux arch=x64 type=deb",
|
||||
"pack:linux:deb:arm64": "node build-config/build-pack.js target=linux arch=arm64 type=deb",
|
||||
"pack:linux:deb:armv7l": "node build-config/build-pack.js target=linux arch=armv7l type=deb",
|
||||
"pack:linux:rpm": "node build-config/build-pack.js target=linux arch=x64 type=rpm",
|
||||
"pack:linux:pacman": "node build-config/build-pack.js target=linux arch=x64 type=pacman",
|
||||
"pack:mac": "node build-config/pack.js && npm run pack:mac:dmg && npm run pack:mac:dmg:arm64",
|
||||
"pack:mac:dmg": "cross-env electron-builder -m=dmg -p never",
|
||||
"pack:mac:dmg:arm64": "cross-env electron-builder -m=dmg --arm64 -p never",
|
||||
"pack:dir": "node build-config/pack.js && electron-builder --dir",
|
||||
"pack:mac:dmg": "node build-config/build-pack.js target=mac arch=x64 type=dmg",
|
||||
"pack:mac:dmg:arm64": "node build-config/build-pack.js target=mac arch=arm64 type=dmg",
|
||||
"pack:dir": "node build-config/pack.js && node build-config/build-pack.js target=dir",
|
||||
"publish": "node publish",
|
||||
"publish:win:setup:x64:always": "cross-env TARGET=Setup ARCH=x64 electron-builder -w=nsis --x64 -p always",
|
||||
"publish:win:setup:x64": "cross-env TARGET=Setup ARCH=x64 electron-builder -w=nsis --x64 -p always",
|
||||
"publish:win:setup:x86": "cross-env TARGET=Setup ARCH=x86 electron-builder -w=nsis --ia32 -p onTagOrDraft",
|
||||
"publish:win:setup:arm64": "cross-env TARGET=Setup ARCH=arm64 electron-builder -w=nsis --arm64 -p onTagOrDraft",
|
||||
"publish:win:setup:x86_64": "cross-env TARGET=Setup ARCH=x86_64 electron-builder -w=nsis --x64 --ia32 -p onTagOrDraft",
|
||||
"publish:win:setup:x64": "node build-config/build-pack.js target=win arch=x64 type=setup publish=always",
|
||||
"publish:win:setup:x86": "node build-config/build-pack.js target=win arch=x86 type=setup publish=always",
|
||||
"publish:win:setup:arm64": "node build-config/build-pack.js target=win arch=arm64 type=setup publish=always",
|
||||
"publish:win:setup:x86_64": "node build-config/build-pack.js target=win arch=x86_64 type=setup publish=always",
|
||||
"publish:win:portable": "npm run publish:win:portable:x86_64 && npm run publish:win:portable:x64 && npm run publish:win:portable:x86",
|
||||
"publish:win:portable:x86_64": "cross-env TARGET=portable ARCH=x86_64 electron-builder -w=portable --x64 --ia32 -p onTagOrDraft",
|
||||
"publish:win:portable:x64": "cross-env TARGET=portable ARCH=x64 electron-builder -w=portable --x64 -p onTagOrDraft",
|
||||
"publish:win:portable:x86": "cross-env TARGET=portable ARCH=x86 electron-builder -w=portable --ia32 -p onTagOrDraft",
|
||||
"publish:win:7z:x64": "cross-env TARGET=green ARCH=win_x64 electron-builder -w=7z --x64 -p onTagOrDraft",
|
||||
"publish:win:7z:x86": "cross-env TARGET=green ARCH=win_x86 electron-builder -w=7z --ia32 -p onTagOrDraft",
|
||||
"publish:win:7z:arm64": "cross-env TARGET=green ARCH=win_arm64 electron-builder -w=7z --arm64 -p onTagOrDraft",
|
||||
"publish:mac:dmg:always": "electron-builder -m=dmg -p always",
|
||||
"publish:mac:dmg": "electron-builder -m=dmg -p onTagOrDraft",
|
||||
"publish:mac:dmg:arm64": "electron-builder -m=dmg --arm64 -p onTagOrDraft",
|
||||
"publish:linux:deb:x64:always": "cross-env ARCH=x64 electron-builder -l=deb --x64 -p always",
|
||||
"publish:linux:deb:x64": "cross-env ARCH=x64 electron-builder -l=deb --x64 -p onTagOrDraft",
|
||||
"publish:linux:deb:x86": "cross-env ARCH=x86 electron-builder -l=deb --ia32 -p onTagOrDraft",
|
||||
"publish:linux:deb:arm64": "cross-env ARCH=arm64 electron-builder -l=deb --arm64 -p onTagOrDraft",
|
||||
"publish:linux:deb:armv7l": "cross-env ARCH=armv7l electron-builder -l=deb --armv7l -p onTagOrDraft",
|
||||
"publish:linux:appImage": "cross-env ARCH=x64 electron-builder -l=AppImage -p onTagOrDraft",
|
||||
"publish:linux:rpm": "cross-env ARCH=x64 electron-builder -l=rpm --x64 -p onTagOrDraft",
|
||||
"publish:linux:pacman": "cross-env ARCH=x64 electron-builder -l=pacman --x64 -p onTagOrDraft",
|
||||
"dev": "node build-config/runner-dev.js",
|
||||
"clean:electron": "rimraf dist",
|
||||
"clean": "rimraf dist && rimraf build",
|
||||
"build:src": "node build-config/pack.js",
|
||||
"publish:win:portable:x86_64": "node build-config/build-pack.js target=win arch=x86_64 type=portable publish=always",
|
||||
"publish:win:portable:x64": "node build-config/build-pack.js target=win arch=x64 type=portable publish=always",
|
||||
"publish:win:portable:x86": "node build-config/build-pack.js target=win arch=x86 type=portable publish=always",
|
||||
"publish:win:7z:x64": "node build-config/build-pack.js target=win arch=x64 type=green publish=always",
|
||||
"publish:win:7z:arm64": "node build-config/build-pack.js target=win arch=arm64 type=green publish=always",
|
||||
"publish:win7:setup:x64": "node build-config/build-pack.js target=win arch=x64 type=win7_setup publish=always",
|
||||
"publish:win7:7z:x64": "node build-config/build-pack.js target=win arch=x64 type=win7_green publish=always",
|
||||
"publish:win7:7z:x86": "node build-config/build-pack.js target=win arch=x86 type=win7_green publish=always",
|
||||
"publish:mac:dmg": "node build-config/build-pack.js target=mac arch=x64 type=dmg publish=always",
|
||||
"publish:mac:dmg:arm64": "node build-config/build-pack.js target=mac arch=arm64 type=dmg publish=always",
|
||||
"publish:linux:deb:amd64": "node build-config/build-pack.js target=linux arch=x64 type=deb publish=always",
|
||||
"publish:linux:deb:arm64": "node build-config/build-pack.js target=linux arch=arm64 type=deb publish=always",
|
||||
"publish:linux:deb:armv7l": "node build-config/build-pack.js target=linux arch=armv7l type=deb publish=always",
|
||||
"publish:linux:appImage": "node build-config/build-pack.js target=linux arch=x64 type=appImage publish=always",
|
||||
"publish:linux:rpm": "node build-config/build-pack.js target=linux arch=x64 type=rpm publish=always",
|
||||
"publish:linux:pacman": "node build-config/build-pack.js target=linux arch=x64 type=pacman publish=always",
|
||||
"dev": "cross-env NODE_OPTIONS=--max-http-header-size=200000 node build-config/runner-dev.js",
|
||||
"build:theme": "node src/common/theme/createThemes.js",
|
||||
"build": "node build-config/pack.js",
|
||||
"build:main": "cross-env NODE_ENV=production webpack --config build-config/main/webpack.config.prod.js --progress",
|
||||
"build:renderer": "cross-env NODE_ENV=production webpack --config build-config/renderer/webpack.config.prod.js --progress",
|
||||
"build:renderer-lyric": "cross-env NODE_ENV=production webpack --config build-config/renderer-lyric/webpack.config.prod.js --progress",
|
||||
"build": "npm run clean:electron && npm run build:main && npm run build:renderer && npm run build:renderer-lyric",
|
||||
"lint": "eslint --ext .js,.vue -f node_modules/eslint-formatter-friendly src",
|
||||
"lint:fix": "eslint --ext .js,.vue -f node_modules/eslint-formatter-friendly --fix src",
|
||||
"dp": "cross-env ELECTRON_GET_USE_PROXY=true GLOBAL_AGENT_HTTPS_PROXY=http://localhost:1081 npm run pack",
|
||||
"up": "cross-env ELECTRON_GET_USE_PROXY=true GLOBAL_AGENT_HTTPS_PROXY=http://localhost:1081 npm i"
|
||||
"build:renderer-scripts": "cross-env NODE_ENV=production webpack --config build-config/renderer-scripts/webpack.config.prod.js --progress",
|
||||
"lint": "eslint --ext .ts,.js,.vue -f node_modules/eslint-formatter-friendly src",
|
||||
"lint:fix": "eslint --ext .ts,.js,.vue -f node_modules/eslint-formatter-friendly --fix src",
|
||||
"postinstall": "electron-builder install-app-deps",
|
||||
"dp": "cross-env ELECTRON_GET_USE_PROXY=true GLOBAL_AGENT_HTTPS_PROXY=http://127.0.0.1:2081 npm run pack",
|
||||
"up": "cross-env ELECTRON_GET_USE_PROXY=true GLOBAL_AGENT_HTTPS_PROXY=http://127.0.0.1:2081 npm i"
|
||||
},
|
||||
"browserslist": [
|
||||
"Electron 17.4.7"
|
||||
"Electron 22.3.0"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 16",
|
||||
"node": ">= 22",
|
||||
"npm": ">=8.5.2"
|
||||
},
|
||||
"build": {
|
||||
"appId": "cn.toside.music.desktop",
|
||||
"protocols": {
|
||||
"name": "lx-music-protocol",
|
||||
"schemes": [
|
||||
"lxmusic"
|
||||
]
|
||||
"macLanguagesInfoPlistStrings": {
|
||||
"en": {
|
||||
"CFBundleDisplayName": "LX Music",
|
||||
"CFBundleName": "LX Music"
|
||||
},
|
||||
"directories": {
|
||||
"buildResources": "./resources",
|
||||
"output": "./build"
|
||||
"zh_CN": {
|
||||
"CFBundleDisplayName": "LX Music",
|
||||
"CFBundleName": "LX Music"
|
||||
},
|
||||
"files": [
|
||||
"dist/**/*"
|
||||
],
|
||||
"asar": {
|
||||
"smartUnpack": false
|
||||
},
|
||||
"extraResources": [
|
||||
"./licenses"
|
||||
],
|
||||
"win": {
|
||||
"icon": "./resources/icons/icon.ico",
|
||||
"legalTrademarks": "lyswhut",
|
||||
"artifactName": "${productName} v${version} ${env.ARCH} ${env.TARGET}.${ext}"
|
||||
},
|
||||
"mac": {
|
||||
"icon": "./resources/icons/icon.icns",
|
||||
"category": "public.app-category.music",
|
||||
"extendInfo": {
|
||||
"CFBundleName": "lx-music-desktop",
|
||||
"CFBundleDisplayName": "LX Music"
|
||||
}
|
||||
},
|
||||
"linux": {
|
||||
"maintainer": "lyswhut <lyswhut@qq.com>",
|
||||
"artifactName": "${productName} v${version} ${env.ARCH}.${ext}",
|
||||
"icon": "./resources/icons",
|
||||
"category": "Utility;AudioVideo;Audio;Player;Music;",
|
||||
"desktop": {
|
||||
"Name[zh_CN]": "洛雪音乐助手"
|
||||
}
|
||||
},
|
||||
"nsis": {
|
||||
"oneClick": false,
|
||||
"language": "2052",
|
||||
"allowToChangeInstallationDirectory": true,
|
||||
"differentialPackage": true,
|
||||
"license": "./licenses/license.rtf",
|
||||
"shortcutName": "LX Music"
|
||||
},
|
||||
"dmg": {
|
||||
"window": {
|
||||
"width": 600,
|
||||
"height": 400
|
||||
},
|
||||
"contents": [
|
||||
{
|
||||
"x": 106,
|
||||
"y": 252,
|
||||
"name": "LX Music"
|
||||
},
|
||||
{
|
||||
"x": 490,
|
||||
"y": 252,
|
||||
"type": "link",
|
||||
"path": "/Applications"
|
||||
}
|
||||
],
|
||||
"title": "洛雪音乐助手 v${version}"
|
||||
},
|
||||
"appImage": {
|
||||
"license": "./licenses/license_zh.txt",
|
||||
"category": "Utility;AudioVideo;Audio;Player;Music;"
|
||||
},
|
||||
"publish": [
|
||||
{
|
||||
"provider": "github",
|
||||
"owner": "lyswhut",
|
||||
"repo": "lx-music-desktop"
|
||||
}
|
||||
]
|
||||
"zh_TW": {
|
||||
"CFBundleDisplayName": "LX Music",
|
||||
"CFBundleName": "LX Music"
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -166,7 +95,7 @@
|
||||
"keywords": [
|
||||
"music-player",
|
||||
"electron-app",
|
||||
"vuejs2"
|
||||
"vuejs3"
|
||||
],
|
||||
"author": {
|
||||
"name": "lyswhut",
|
||||
@@ -178,96 +107,116 @@
|
||||
},
|
||||
"homepage": "https://github.com/lyswhut/lx-music-desktop#readme",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.18.5",
|
||||
"@babel/eslint-parser": "^7.18.2",
|
||||
"@babel/plugin-proposal-class-properties": "^7.17.12",
|
||||
"@babel/core": "^7.29.0",
|
||||
"@babel/eslint-parser": "^7.28.6",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||
"@babel/plugin-transform-modules-umd": "^7.18.0",
|
||||
"@babel/plugin-transform-runtime": "^7.18.5",
|
||||
"@babel/polyfill": "^7.12.1",
|
||||
"@babel/preset-env": "^7.18.2",
|
||||
"babel-loader": "^8.2.5",
|
||||
"babel-preset-minify": "^0.5.2",
|
||||
"browserslist": "^4.20.4",
|
||||
"@babel/plugin-transform-class-properties": "^7.28.6",
|
||||
"@babel/plugin-transform-modules-umd": "^7.27.1",
|
||||
"@babel/plugin-transform-runtime": "^7.29.0",
|
||||
"@babel/preset-env": "^7.29.0",
|
||||
"@babel/preset-typescript": "^7.28.5",
|
||||
"@babel/runtime": "^7.28.6",
|
||||
"@tsconfig/recommended": "^1.0.13",
|
||||
"@types/better-sqlite3": "^7.6.13",
|
||||
"@types/needle": "^3.3.0",
|
||||
"@types/node": "^20.19.33",
|
||||
"@types/tunnel": "^0.0.7",
|
||||
"@types/ws": "8.5.4",
|
||||
"@vue/language-plugin-pug": "^3.2.4",
|
||||
"babel-loader": "^10.0.0",
|
||||
"browserslist": "^4.28.1",
|
||||
"chalk": "^4.1.2",
|
||||
"changelog-parser": "^2.8.1",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"core-js": "^3.23.1",
|
||||
"cross-env": "^7.0.3",
|
||||
"css-loader": "^6.7.1",
|
||||
"css-minimizer-webpack-plugin": "^4.0.0",
|
||||
"changelog-parser": "^3.0.1",
|
||||
"copy-webpack-plugin": "^13.0.1",
|
||||
"core-js": "^3.48.0",
|
||||
"cross-env": "^10.1.0",
|
||||
"css-loader": "^7.1.3",
|
||||
"css-minimizer-webpack-plugin": "^7.0.4",
|
||||
"del": "^6.1.1",
|
||||
"electron": "^17.4.7",
|
||||
"electron-builder": "^23.1.0",
|
||||
"electron": "37.6.1",
|
||||
"electron-builder": "^26.8.0",
|
||||
"electron-debug": "^3.2.0",
|
||||
"electron-devtools-installer": "^3.2.0",
|
||||
"electron-to-chromium": "^1.4.161",
|
||||
"electron-updater": "^5.0.5",
|
||||
"eslint": "^8.18.0",
|
||||
"eslint-config-standard": "^17.0.0",
|
||||
"eslint-formatter-friendly": "git+https://github.com/lyswhut/eslint-friendly-formatter.git#2170d1320e2fad13615a9dcf229669f0bb473a53",
|
||||
"eslint-plugin-html": "^6.2.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^6.0.0",
|
||||
"eslint-plugin-standard": "^4.1.0",
|
||||
"eslint-webpack-plugin": "^3.1.1",
|
||||
"file-loader": "^6.2.0",
|
||||
"html-webpack-plugin": "^5.5.0",
|
||||
"less": "^4.1.3",
|
||||
"less-loader": "^11.0.0",
|
||||
"mini-css-extract-plugin": "^2.6.1",
|
||||
"node-loader": "^2.0.0",
|
||||
"postcss": "^8.4.14",
|
||||
"postcss-loader": "^7.0.0",
|
||||
"postcss-pxtorem": "^6.0.0",
|
||||
"pug": "^3.0.2",
|
||||
"pug-loader": "^2.4.0",
|
||||
"electron-devtools-installer": "github:lyswhut/electron-devtools-installer#64596d615c1fc891eefd8aef1dfcb2c87aaadf03",
|
||||
"electron-to-chromium": "^1.5.286",
|
||||
"electron-updater": "6.8.3",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-config-standard": "^17.1.0",
|
||||
"eslint-config-standard-with-typescript": "^43.0.1",
|
||||
"eslint-formatter-friendly": "github:lyswhut/eslint-friendly-formatter#2170d1320e2fad13615a9dcf229669f0bb473a53",
|
||||
"eslint-plugin-html": "^8.1.4",
|
||||
"eslint-plugin-vue": "^9.33.0",
|
||||
"eslint-plugin-vue-pug": "^0.6.2",
|
||||
"eslint-webpack-plugin": "^4.2.0",
|
||||
"html-webpack-plugin": "^5.6.6",
|
||||
"less": "^4.5.1",
|
||||
"less-loader": "^12.3.1",
|
||||
"mini-css-extract-plugin": "^2.10.0",
|
||||
"node-loader": "^2.1.0",
|
||||
"postcss": "^8.5.6",
|
||||
"postcss-loader": "^8.2.1",
|
||||
"postcss-pxtorem": "^6.1.0",
|
||||
"pug": "^3.0.3",
|
||||
"pug-plain-loader": "^1.1.0",
|
||||
"raw-loader": "^4.0.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"spinnies": "git+https://github.com/lyswhut/spinnies.git#233305c58694aa3b053e3ab9af9049993f918b9d",
|
||||
"rimraf": "^6.1.3",
|
||||
"spinnies": "github:lyswhut/spinnies#233305c58694aa3b053e3ab9af9049993f918b9d",
|
||||
"svg-sprite-loader": "^6.0.11",
|
||||
"svg-transform-loader": "^2.0.13",
|
||||
"svgo-loader": "^3.0.1",
|
||||
"terser-webpack-plugin": "^5.3.3",
|
||||
"url-loader": "^4.1.1",
|
||||
"vue-loader": "^17.0.0",
|
||||
"vue-template-compiler": "^2.7.0-beta.2",
|
||||
"webpack": "^5.73.0",
|
||||
"webpack-cli": "^4.10.0",
|
||||
"webpack-dev-server": "^4.9.2",
|
||||
"webpack-hot-middleware": "git+https://github.com/lyswhut/webpack-hot-middleware.git#329c4375134b89d39da23a56a94db651247c74a1",
|
||||
"webpack-merge": "^5.8.0"
|
||||
"svgo-loader": "^4.0.0",
|
||||
"terser": "^5.46.0",
|
||||
"terser-webpack-plugin": "^5.3.16",
|
||||
"tree-kill": "^1.2.2",
|
||||
"ts-loader": "^9.5.4",
|
||||
"typescript": "5.9.3",
|
||||
"vue-eslint-parser": "^9.4.3",
|
||||
"vue-loader": "^17.4.2",
|
||||
"webpack": "^5.105.2",
|
||||
"webpack-cli": "^6.0.1",
|
||||
"webpack-dev-server": "5.2.3",
|
||||
"webpack-hot-middleware": "github:lyswhut/webpack-hot-middleware#329c4375134b89d39da23a56a94db651247c74a1",
|
||||
"webpack-merge": "^6.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"bufferutil": "^4.0.6",
|
||||
"crypto-js": "^4.1.1",
|
||||
"electron-log": "^4.4.7",
|
||||
"electron-store": "^8.0.2",
|
||||
"font-list": "git+https://github.com/lyswhut/node-font-list.git#4edbb1933b49a9bac1eedd63a31da16b487fe57d",
|
||||
"http-terminator": "^3.2.0",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"image-size": "^1.0.1",
|
||||
"koa": "^2.13.4",
|
||||
"long": "^5.2.0",
|
||||
"mitt": "^3.0.0",
|
||||
"needle": "^3.1.0",
|
||||
"node-id3": "^0.2.3",
|
||||
"request": "^2.88.2",
|
||||
"socket.io": "^4.5.1",
|
||||
"sortablejs": "^1.15.0",
|
||||
"@simonwep/pickr": "^1.9.1",
|
||||
"better-sqlite3": "^12.6.2",
|
||||
"bufferutil": "^4.1.0",
|
||||
"comlink": "~4.3.1",
|
||||
"crypto-js": "^4.2.0",
|
||||
"electron-log": "^5.4.3",
|
||||
"font-list": "^2.0.2",
|
||||
"iconv-lite": "^0.7.2",
|
||||
"image-size": "^1.1.0",
|
||||
"jschardet": "^3.1.4",
|
||||
"long": "^5.3.2",
|
||||
"message2call": "^0.1.3",
|
||||
"music-metadata": "^11.12.0",
|
||||
"needle": "github:lyswhut/needle#93299ac841b7e9a9f82ca7279b88aaaeda404060",
|
||||
"node-id3": "^0.2.9",
|
||||
"sortablejs": "^1.15.7",
|
||||
"tunnel": "^0.0.6",
|
||||
"utf-8-validate": "^5.0.9",
|
||||
"vue": "^3.2.37",
|
||||
"vue-i18n": "^9.2.0-beta.36",
|
||||
"vue-router": "^4.1.0-aabe509",
|
||||
"vuex": "^4.0.2"
|
||||
"undici": "^7.22.0",
|
||||
"utf-8-validate": "^6.0.6",
|
||||
"vue": "~3.3.13",
|
||||
"vue-router": "~4.5.1",
|
||||
"ws": "^8.19.0"
|
||||
},
|
||||
"overrides": {
|
||||
"async": "^2.3.0",
|
||||
"got": "^11",
|
||||
"json5": "latest",
|
||||
"node-abi": "latest",
|
||||
"minimatch": "latest",
|
||||
"semver": "latest",
|
||||
"svg-transform-loader": {
|
||||
"postcss": "^8"
|
||||
},
|
||||
"svg-sprite-loader": {
|
||||
"postcss": "8.2.13"
|
||||
}
|
||||
"postcss": "^8"
|
||||
},
|
||||
"svg-baker": {
|
||||
"postcss": "^8"
|
||||
},
|
||||
"braces": "latest",
|
||||
"node-gyp-build": "latest",
|
||||
"micromatch": "latest",
|
||||
"http-cache-semantics": "latest"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,12 @@
|
||||
### 新增
|
||||
|
||||
- 新增设置-以全屏模式启动设置
|
||||
- 新增设置-桌面歌词设置-鼠标移入歌词区域时降低歌词透明度(#883),默认关闭,此设置不支持linux,注:此功能存在兼容性问题,若鼠标移出后无法恢复到正常透明度,可尝试再移入移出即可恢复
|
||||
我们很高兴地宣布新项目 Any Listen 的桌面版已发布,目前已支持列表跟随本地文件自动更新、加载并播放WebDAV上的歌曲等功能,更多功能仍在积极开发中,桌面版与Web版将同步更新。
|
||||
对于有播放本地音乐或播放服务器上音乐需求的人可以试试,若遇到任何问题可以发 issue 反馈。
|
||||
|
||||
### 优化
|
||||
|
||||
- 添加歌曲到“我的列表”时,若按住`ctrl`键(Mac对应`Command`),则不会自动关闭添加窗口,这对想要将同一首(一批)歌曲添加到多个列表时会很有用
|
||||
- 支持mg源逐字歌词的播放,感谢 @mozbugbox 提供的帮助
|
||||
- 添加歌曲列表更新操作的二次确认
|
||||
- 添加导入文件错误时的指引提示
|
||||
- 优化托盘图标行为:在非 Windows 系统中,点击托盘图标时不再显示主窗口
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复若配置了`http_proxy`环境变量时,会意外使用此代理配置的问题
|
||||
- 修复多选后切换列表后不会清空多选内容的问题
|
||||
- 修复设置快捷键时的处理逻辑问题
|
||||
- 修复在新建歌单输入框、歌单内歌曲搜索输入框会意外触发设置的全局快捷键的问题(#879)
|
||||
|
||||
### 文档
|
||||
|
||||
桌面版文档已迁移到:<https://lyswhut.github.io/lx-music-doc/desktop>
|
||||
|
||||
### 其他
|
||||
|
||||
- 更新 Electron 到 v17.4.7
|
||||
- 修复音量条在调整音量时实际音量与显示的数值不一致的问题(#2606)
|
||||
- 修复某些情况下搜索框的搜索按钮布局错位的问题(#2622)
|
||||
- 修复 wyy 部分歌曲无法被搜索的问题(#2666, @ikun0014)
|
||||
|
||||
40
publish/utils/parseChangelog.js
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
*
|
||||
* @param {string} text
|
||||
* @returns
|
||||
*/
|
||||
export const parseChangelog = async(text) => {
|
||||
const versions = []
|
||||
const lines = text.split(/\r\n|\r|\n/)
|
||||
let currentVersion = null
|
||||
let currentDate = null
|
||||
let currentDesc = ''
|
||||
|
||||
for (const line of lines) {
|
||||
const versionMatch = line.match(/^\s*##\s+\[?(\d+\.\d+\.\d+)\]?.*?-\s+(\d{4}-\d{2}-\d{2})$/)
|
||||
if (versionMatch) {
|
||||
if (currentVersion) {
|
||||
versions.push({
|
||||
version: currentVersion,
|
||||
date: currentDate,
|
||||
desc: currentDesc.trim(),
|
||||
})
|
||||
}
|
||||
currentVersion = versionMatch[1]
|
||||
currentDate = versionMatch[3]
|
||||
currentDesc = ''
|
||||
} else {
|
||||
currentDesc += `${line}\n`
|
||||
}
|
||||
}
|
||||
|
||||
if (currentVersion) {
|
||||
versions.push({
|
||||
version: currentVersion,
|
||||
date: currentDate,
|
||||
desc: currentDesc.trim(),
|
||||
})
|
||||
}
|
||||
|
||||
return versions
|
||||
}
|
||||
@@ -6,8 +6,8 @@ const version = require('../version.json')
|
||||
const chalk = require('chalk')
|
||||
const pkg_bak = JSON.stringify(pkg, null, 2)
|
||||
const version_bak = JSON.stringify(version, null, 2)
|
||||
const parseChangelog = require('changelog-parser')
|
||||
const changelogPath = jp('../../CHANGELOG.md')
|
||||
const { parseChangelog } = require('./parseChangelog')
|
||||
|
||||
// const md_renderer = markdownStr => new (require('markdown-it'))({
|
||||
// html: true,
|
||||
@@ -16,27 +16,23 @@ const changelogPath = jp('../../CHANGELOG.md')
|
||||
// breaks: true,
|
||||
// }).render(markdownStr)
|
||||
|
||||
const getPrevVer = () => parseChangelog(changelogPath).then(res => {
|
||||
if (!res.versions.length) throw new Error('CHANGELOG 无法解析到版本号')
|
||||
return res.versions[0].version
|
||||
const getPrevVer = () => parseChangelog(fs.readFileSync(changelogPath, 'utf-8').toString()).then(versions => {
|
||||
if (!versions.length) throw new Error('CHANGELOG 无法解析到版本号')
|
||||
return versions[0].version
|
||||
})
|
||||
|
||||
const updateChangeLog = async(newVerNum, newChangeLog) => {
|
||||
let changeLog = fs.readFileSync(changelogPath, 'utf-8')
|
||||
const prevVer = await getPrevVer()
|
||||
const log = `## [${newVerNum}](${pkg.repository.url.replace(/^git\+(http.+)\.git$/, '$1')}/compare/v${prevVer}...v${newVerNum}) - ${formatTime()}\n\n${newChangeLog}`
|
||||
fs.writeFileSync(changelogPath, changeLog.replace(new RegExp('(## [?0.1.1]?)'), log + '\n$1'), 'utf-8')
|
||||
fs.writeFileSync(changelogPath, changeLog.replace(/(## \[(?:\d+\.))/, log + '\n$1'), 'utf-8')
|
||||
}
|
||||
|
||||
// const renderChangeLog = md => md_renderer(md)
|
||||
|
||||
|
||||
module.exports = async newVerNum => {
|
||||
if (!newVerNum) {
|
||||
let verArr = pkg.version.split('.')
|
||||
verArr[verArr.length - 1] = parseInt(verArr[verArr.length - 1]) + 1
|
||||
newVerNum = verArr.join('.')
|
||||
}
|
||||
if (!newVerNum) newVerNum = pkg.version
|
||||
const newMDChangeLog = fs.readFileSync(jp('../changeLog.md'), 'utf-8')
|
||||
// const newChangeLog = renderChangeLog(newMDChangeLog)
|
||||
version.history.unshift({
|
||||
|
||||
15
src/common/.eslintrc.cjs
Normal file
@@ -0,0 +1,15 @@
|
||||
/* eslint-env node */
|
||||
const { base, typescript } = require('../../.eslintrc.base.cjs')
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
...base,
|
||||
overrides: [
|
||||
{
|
||||
...typescript,
|
||||
parserOptions: {
|
||||
project: './tsconfig.json',
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
module.exports = {
|
||||
windowSizeList: [
|
||||
{
|
||||
id: 0,
|
||||
name: 'smaller',
|
||||
width: 828,
|
||||
height: 530,
|
||||
fontSize: '14px',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: 'small',
|
||||
width: 920,
|
||||
height: 590,
|
||||
fontSize: '16px',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'medium',
|
||||
width: 1018,
|
||||
height: 650,
|
||||
fontSize: '16px',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'big',
|
||||
width: 1114,
|
||||
height: 708,
|
||||
fontSize: '17px',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'larger',
|
||||
width: 1202,
|
||||
height: 766,
|
||||
fontSize: '17px',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: 'oversized',
|
||||
width: 1382,
|
||||
height: 886,
|
||||
fontSize: '18px',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: 'huge',
|
||||
width: 1686,
|
||||
height: 1062,
|
||||
fontSize: '19px',
|
||||
},
|
||||
],
|
||||
navigationUrlWhiteList: [
|
||||
|
||||
],
|
||||
themes: [
|
||||
{
|
||||
id: 0,
|
||||
name: '绿意盎然',
|
||||
className: 'green',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '蓝田生玉',
|
||||
className: 'blue',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '信口雌黄',
|
||||
className: 'yellow',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '橙黄橘绿',
|
||||
className: 'orange',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '热情似火',
|
||||
className: 'red',
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: '粉装玉琢',
|
||||
className: 'pink',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: '重斤球紫',
|
||||
className: 'purple',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: '灰常美丽',
|
||||
className: 'grey',
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
name: '青出于黑',
|
||||
className: 'ming',
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
name: '青出于黑',
|
||||
className: 'blue2',
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
name: '黑灯瞎火',
|
||||
className: 'black',
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: '月里嫦娥',
|
||||
className: 'mid_autumn',
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: '木叶之村',
|
||||
className: 'naruto',
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
name: '新年快乐',
|
||||
className: 'happy_new_year',
|
||||
},
|
||||
],
|
||||
themeLights: [0, 1, 2, 3, 4, 10, 5, 6, 11, 12, 7, 8, 9],
|
||||
themeDarks: [13, 7],
|
||||
}
|
||||
86
src/common/config.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
export interface WindowSize {
|
||||
id: number
|
||||
name: string
|
||||
width: number
|
||||
height: number
|
||||
}
|
||||
|
||||
export const windowSizeList: WindowSize[] = [
|
||||
{
|
||||
id: 0,
|
||||
name: 'smaller',
|
||||
width: 828,
|
||||
height: 540,
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: 'small',
|
||||
width: 920,
|
||||
height: 600,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'medium',
|
||||
width: 1020,
|
||||
height: 660,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'big',
|
||||
width: 1114,
|
||||
height: 718,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'larger',
|
||||
width: 1202,
|
||||
height: 776,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: 'oversized',
|
||||
width: 1385,
|
||||
height: 896,
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: 'huge',
|
||||
width: 1700,
|
||||
height: 1070,
|
||||
},
|
||||
]
|
||||
|
||||
export const navigationUrlWhiteList: RegExp[] = []
|
||||
|
||||
// 基础黑白色
|
||||
// export const commonColorNames = [
|
||||
// '--color-000', '--color-050', '--color-100', '--color-200', '--color-300', '--color-400',
|
||||
// '--color-500', '--color-600', '--color-700', '--color-800', '--color-900',
|
||||
// ] as const
|
||||
// export const commonLightColorValues = [
|
||||
// 'rgb(255, 255, 255)',
|
||||
// 'rgb(217,217,217)',
|
||||
// 'rgb(184,184,184)',
|
||||
// 'rgb(156,156,156)',
|
||||
// 'rgb(133,133,133)',
|
||||
// 'rgb(113,113,113)',
|
||||
// 'rgb(96,96,96)',
|
||||
// 'rgb(82,82,82)',
|
||||
// 'rgb(70,70,70)',
|
||||
// 'rgb(60,60,60)',
|
||||
// 'rgb(51,51,51)',
|
||||
// ] as const
|
||||
// export const commonDarkColorValues = [
|
||||
// 'rgb(11, 11, 11)',
|
||||
// 'rgb(60,60,60)',
|
||||
// 'rgb(99,99,99)',
|
||||
// 'rgb(130,130,130)',
|
||||
// 'rgb(155,155,155)',
|
||||
// 'rgb(175,175,175)',
|
||||
// 'rgb(191,191,191)',
|
||||
// 'rgb(204,204,204)',
|
||||
// 'rgb(214,214,214)',
|
||||
// 'rgb(222,222,222)',
|
||||
// 'rgb(229,229,229)',
|
||||
// ] as const
|
||||
|
||||
84
src/common/constants.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
export const URL_SCHEME_RXP = /^lxmusic:\/\//
|
||||
|
||||
export const SPLIT_CHAR = {
|
||||
DISLIKE_NAME: '@',
|
||||
DISLIKE_NAME_ALIAS: '#',
|
||||
} as const
|
||||
|
||||
export const STORE_NAMES = {
|
||||
APP_SETTINGS: 'config_v2',
|
||||
DATA: 'data',
|
||||
SYNC: 'sync',
|
||||
HOTKEY: 'hot_key',
|
||||
USER_API: 'user_api',
|
||||
LRC_RAW: 'lyrics',
|
||||
LRC_EDITED: 'lyrics_edited',
|
||||
THEME: 'theme',
|
||||
SOUND_EFFECT: 'sound_effect',
|
||||
} as const
|
||||
|
||||
export const APP_EVENT_NAMES = {
|
||||
winMainName: 'win_main',
|
||||
winLyricName: 'win_lyric',
|
||||
trayName: 'tray',
|
||||
} as const
|
||||
|
||||
export const LIST_IDS = {
|
||||
DEFAULT: 'default',
|
||||
LOVE: 'love',
|
||||
TEMP: 'temp',
|
||||
DOWNLOAD: 'download',
|
||||
PLAY_LATER: null,
|
||||
} as const
|
||||
|
||||
export const DATA_KEYS = {
|
||||
viewPrevState: 'viewPrevState',
|
||||
playInfo: 'playInfo',
|
||||
searchHistoryList: 'searchHistoryList',
|
||||
listScrollPosition: 'listScrollPosition',
|
||||
listPrevSelectId: 'listPrevSelectId',
|
||||
listUpdateInfo: 'listUpdateInfo',
|
||||
ignoreVersion: 'ignoreVersion',
|
||||
|
||||
leaderboardSetting: 'leaderboardSetting',
|
||||
songListSetting: 'songListSetting',
|
||||
searchSetting: 'searchSetting',
|
||||
|
||||
lastStartInfo: 'lastStartInfo',
|
||||
} as const
|
||||
|
||||
export const DEFAULT_SETTING = {
|
||||
leaderboard: {
|
||||
source: 'kw',
|
||||
boardId: 'kw__16',
|
||||
},
|
||||
|
||||
songList: {
|
||||
source: 'kw',
|
||||
sortId: 'new',
|
||||
tagId: '',
|
||||
},
|
||||
|
||||
search: {
|
||||
temp_source: 'kw',
|
||||
source: 'all',
|
||||
type: 'music',
|
||||
},
|
||||
|
||||
viewPrevState: {
|
||||
url: '/search',
|
||||
query: {},
|
||||
},
|
||||
}
|
||||
|
||||
export const DOWNLOAD_STATUS = {
|
||||
RUN: 'run',
|
||||
WAITING: 'waiting',
|
||||
PAUSE: 'pause',
|
||||
ERROR: 'error',
|
||||
COMPLETED: 'completed',
|
||||
} as const
|
||||
|
||||
export const QUALITYS = ['flac24bit', 'flac', 'wav', 'ape', '320k', '192k', '128k'] as const
|
||||
|
||||
export const TRAY_AUTO_ID = -1
|
||||
74
src/common/constants_sync.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
export const ENV_PARAMS = [
|
||||
'PORT',
|
||||
'BIND_IP',
|
||||
'CONFIG_PATH',
|
||||
'LOG_PATH',
|
||||
'DATA_PATH',
|
||||
'PROXY_HEADER',
|
||||
'MAX_SNAPSHOT_NUM',
|
||||
'LIST_ADD_MUSIC_LOCATION_TYPE',
|
||||
'LX_USER_',
|
||||
] as const
|
||||
|
||||
|
||||
export const LIST_IDS = {
|
||||
DEFAULT: 'default',
|
||||
LOVE: 'love',
|
||||
TEMP: 'temp',
|
||||
DOWNLOAD: 'download',
|
||||
PLAY_LATER: null,
|
||||
} as const
|
||||
|
||||
export const SYNC_CODE = {
|
||||
helloMsg: 'Hello~::^-^::~v4~',
|
||||
idPrefix: 'OjppZDo6',
|
||||
authMsg: 'lx-music auth::',
|
||||
msgAuthFailed: 'Auth failed',
|
||||
msgBlockedIp: 'Blocked IP',
|
||||
msgConnect: 'lx-music connect',
|
||||
|
||||
|
||||
authFailed: 'Auth failed',
|
||||
missingAuthCode: 'Missing auth code',
|
||||
getServiceIdFailed: 'Get service id failed',
|
||||
connectServiceFailed: 'Connect service failed',
|
||||
connecting: 'Connecting...',
|
||||
unknownServiceAddress: 'Unknown service address',
|
||||
} as const
|
||||
|
||||
export const SYNC_CLOSE_CODE = {
|
||||
normal: 1000,
|
||||
failed: 4100,
|
||||
} as const
|
||||
|
||||
export const TRANS_MODE: Readonly<Record<LX.Sync.List.SyncMode, LX.Sync.List.SyncMode>> = {
|
||||
merge_local_remote: 'merge_remote_local',
|
||||
merge_remote_local: 'merge_local_remote',
|
||||
overwrite_local_remote: 'overwrite_remote_local',
|
||||
overwrite_remote_local: 'overwrite_local_remote',
|
||||
overwrite_local_remote_full: 'overwrite_remote_local_full',
|
||||
overwrite_remote_local_full: 'overwrite_local_remote_full',
|
||||
cancel: 'cancel',
|
||||
} as const
|
||||
|
||||
export const File = {
|
||||
serverDataPath: 'sync/server',
|
||||
clientDataPath: 'sync/client',
|
||||
|
||||
serverInfoJSON: 'serverInfo.json',
|
||||
userDir: 'users',
|
||||
userDevicesJSON: 'devices.json',
|
||||
listDir: 'list',
|
||||
listSnapshotDir: 'snapshot',
|
||||
listSnapshotInfoJSON: 'snapshotInfo.json',
|
||||
dislikeDir: 'dislike',
|
||||
dislikeSnapshotDir: 'snapshot',
|
||||
dislikeSnapshotInfoJSON: 'snapshotInfo.json',
|
||||
|
||||
syncAuthKeysJSON: 'syncAuthKey.json',
|
||||
} as const
|
||||
|
||||
export const FeaturesList = [
|
||||
'list',
|
||||
'dislike',
|
||||
] as const
|
||||
@@ -1,89 +0,0 @@
|
||||
const { player: hotKeyPlayer, common: hotKeyCommon, desktop_lyric: hotKeyDesktopLyric } = require('./hotKey')
|
||||
|
||||
module.exports = {
|
||||
local: {
|
||||
enable: true,
|
||||
keys: {
|
||||
'mod+f5': {
|
||||
type: hotKeyPlayer.toggle_play.type,
|
||||
name: hotKeyPlayer.toggle_play.name,
|
||||
action: hotKeyPlayer.toggle_play.action,
|
||||
},
|
||||
'mod+arrowleft': {
|
||||
type: hotKeyPlayer.prev.type,
|
||||
name: hotKeyPlayer.prev.name,
|
||||
action: hotKeyPlayer.prev.action,
|
||||
},
|
||||
'mod+arrowright': {
|
||||
type: hotKeyPlayer.next.type,
|
||||
name: hotKeyPlayer.next.name,
|
||||
action: hotKeyPlayer.next.action,
|
||||
},
|
||||
f1: {
|
||||
type: hotKeyCommon.focusSearchInput.type,
|
||||
name: hotKeyCommon.focusSearchInput.name,
|
||||
action: hotKeyCommon.focusSearchInput.action,
|
||||
},
|
||||
},
|
||||
},
|
||||
global: {
|
||||
enable: false,
|
||||
keys: {
|
||||
MediaPlayPause: {
|
||||
type: hotKeyPlayer.toggle_play.type,
|
||||
name: null,
|
||||
action: hotKeyPlayer.toggle_play.action,
|
||||
},
|
||||
MediaPreviousTrack: {
|
||||
type: hotKeyPlayer.prev.type,
|
||||
name: null,
|
||||
action: hotKeyPlayer.prev.action,
|
||||
},
|
||||
MediaNextTrack: {
|
||||
type: hotKeyPlayer.next.type,
|
||||
name: null,
|
||||
action: hotKeyPlayer.next.action,
|
||||
},
|
||||
'mod+alt+f5': {
|
||||
type: hotKeyPlayer.toggle_play.type,
|
||||
name: hotKeyPlayer.toggle_play.name,
|
||||
action: hotKeyPlayer.toggle_play.action,
|
||||
},
|
||||
'mod+alt+arrowleft': {
|
||||
type: hotKeyPlayer.prev.type,
|
||||
name: hotKeyPlayer.prev.name,
|
||||
action: hotKeyPlayer.prev.action,
|
||||
},
|
||||
'mod+alt+arrowright': {
|
||||
type: hotKeyPlayer.next.type,
|
||||
name: hotKeyPlayer.next.name,
|
||||
action: hotKeyPlayer.next.action,
|
||||
},
|
||||
'mod+alt+arrowup': {
|
||||
type: hotKeyPlayer.volume_up.type,
|
||||
name: hotKeyPlayer.volume_up.name,
|
||||
action: hotKeyPlayer.volume_up.action,
|
||||
},
|
||||
'mod+alt+arrowdown': {
|
||||
type: hotKeyPlayer.volume_down.type,
|
||||
name: hotKeyPlayer.volume_down.name,
|
||||
action: hotKeyPlayer.volume_down.action,
|
||||
},
|
||||
'mod+alt+0': {
|
||||
type: hotKeyDesktopLyric.toggle_visible.type,
|
||||
name: hotKeyDesktopLyric.toggle_visible.name,
|
||||
action: hotKeyDesktopLyric.toggle_visible.action,
|
||||
},
|
||||
'mod+alt+-': {
|
||||
type: hotKeyDesktopLyric.toggle_lock.type,
|
||||
name: hotKeyDesktopLyric.toggle_lock.name,
|
||||
action: hotKeyDesktopLyric.toggle_lock.action,
|
||||
},
|
||||
'mod+alt+=': {
|
||||
type: hotKeyDesktopLyric.toggle_always_top.type,
|
||||
name: hotKeyDesktopLyric.toggle_always_top.name,
|
||||
action: hotKeyDesktopLyric.toggle_always_top.action,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
93
src/common/defaultHotKey.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import { HOTKEY_PLAYER, HOTKEY_COMMON, HOTKEY_DESKTOP_LYRIC } from './hotKey'
|
||||
|
||||
const local: LX.HotKeyConfig = {
|
||||
enable: true,
|
||||
keys: {
|
||||
'mod+f5': {
|
||||
type: HOTKEY_PLAYER.toggle_play.type,
|
||||
name: HOTKEY_PLAYER.toggle_play.name,
|
||||
action: HOTKEY_PLAYER.toggle_play.action,
|
||||
},
|
||||
'mod+arrowleft': {
|
||||
type: HOTKEY_PLAYER.prev.type,
|
||||
name: HOTKEY_PLAYER.prev.name,
|
||||
action: HOTKEY_PLAYER.prev.action,
|
||||
},
|
||||
'mod+arrowright': {
|
||||
type: HOTKEY_PLAYER.next.type,
|
||||
name: HOTKEY_PLAYER.next.name,
|
||||
action: HOTKEY_PLAYER.next.action,
|
||||
},
|
||||
f1: {
|
||||
type: HOTKEY_COMMON.focusSearchInput.type,
|
||||
name: HOTKEY_COMMON.focusSearchInput.name,
|
||||
action: HOTKEY_COMMON.focusSearchInput.action,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const global: LX.HotKeyConfig = {
|
||||
enable: false,
|
||||
keys: {
|
||||
// MediaPlayPause: {
|
||||
// type: HOTKEY_PLAYER.toggle_play.type,
|
||||
// name: '',
|
||||
// action: HOTKEY_PLAYER.toggle_play.action,
|
||||
// },
|
||||
// MediaPreviousTrack: {
|
||||
// type: HOTKEY_PLAYER.prev.type,
|
||||
// name: '',
|
||||
// action: HOTKEY_PLAYER.prev.action,
|
||||
// },
|
||||
// MediaNextTrack: {
|
||||
// type: HOTKEY_PLAYER.next.type,
|
||||
// name: '',
|
||||
// action: HOTKEY_PLAYER.next.action,
|
||||
// },
|
||||
'mod+alt+f5': {
|
||||
type: HOTKEY_PLAYER.toggle_play.type,
|
||||
name: HOTKEY_PLAYER.toggle_play.name,
|
||||
action: HOTKEY_PLAYER.toggle_play.action,
|
||||
},
|
||||
'mod+alt+arrowleft': {
|
||||
type: HOTKEY_PLAYER.prev.type,
|
||||
name: HOTKEY_PLAYER.prev.name,
|
||||
action: HOTKEY_PLAYER.prev.action,
|
||||
},
|
||||
'mod+alt+arrowright': {
|
||||
type: HOTKEY_PLAYER.next.type,
|
||||
name: HOTKEY_PLAYER.next.name,
|
||||
action: HOTKEY_PLAYER.next.action,
|
||||
},
|
||||
'mod+alt+arrowup': {
|
||||
type: HOTKEY_PLAYER.volume_up.type,
|
||||
name: HOTKEY_PLAYER.volume_up.name,
|
||||
action: HOTKEY_PLAYER.volume_up.action,
|
||||
},
|
||||
'mod+alt+arrowdown': {
|
||||
type: HOTKEY_PLAYER.volume_down.type,
|
||||
name: HOTKEY_PLAYER.volume_down.name,
|
||||
action: HOTKEY_PLAYER.volume_down.action,
|
||||
},
|
||||
'mod+alt+0': {
|
||||
type: HOTKEY_DESKTOP_LYRIC.toggle_visible.type,
|
||||
name: HOTKEY_DESKTOP_LYRIC.toggle_visible.name,
|
||||
action: HOTKEY_DESKTOP_LYRIC.toggle_visible.action,
|
||||
},
|
||||
'mod+alt+-': {
|
||||
type: HOTKEY_DESKTOP_LYRIC.toggle_lock.type,
|
||||
name: HOTKEY_DESKTOP_LYRIC.toggle_lock.name,
|
||||
action: HOTKEY_DESKTOP_LYRIC.toggle_lock.action,
|
||||
},
|
||||
'mod+alt+=': {
|
||||
type: HOTKEY_DESKTOP_LYRIC.toggle_always_top.type,
|
||||
name: HOTKEY_DESKTOP_LYRIC.toggle_always_top.name,
|
||||
action: HOTKEY_DESKTOP_LYRIC.toggle_always_top.action,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export default {
|
||||
local,
|
||||
global,
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
const path = require('path')
|
||||
const os = require('os')
|
||||
|
||||
const defaultSetting = {
|
||||
version: '1.0.59',
|
||||
player: {
|
||||
togglePlayMethod: 'listLoop',
|
||||
highQuality: false,
|
||||
isShowTaskProgess: true,
|
||||
volume: 1,
|
||||
isMute: false,
|
||||
mediaDeviceId: 'default',
|
||||
isMediaDeviceRemovedStopPlay: false,
|
||||
isShowLyricTranslation: false,
|
||||
isShowLyricRoma: false,
|
||||
isS2t: false, // 是否将歌词从简体转换为繁体
|
||||
isPlayLxlrc: true,
|
||||
isSavePlayTime: false,
|
||||
audioVisualization: false,
|
||||
waitPlayEndStop: true,
|
||||
waitPlayEndStopTime: '',
|
||||
autoSkipOnError: true,
|
||||
},
|
||||
playDetail: {
|
||||
isZoomActiveLrc: true,
|
||||
isShowLyricProgressSetting: false,
|
||||
style: {
|
||||
fontSize: 100,
|
||||
align: 'center',
|
||||
},
|
||||
},
|
||||
desktopLyric: {
|
||||
enable: false,
|
||||
isLock: false,
|
||||
isAlwaysOnTop: false,
|
||||
isAlwaysOnTopLoop: false,
|
||||
width: 380,
|
||||
height: 420,
|
||||
x: null,
|
||||
y: null,
|
||||
theme: 0,
|
||||
isLockScreen: true,
|
||||
isDelayScroll: true,
|
||||
isHoverHide: false,
|
||||
style: {
|
||||
font: '',
|
||||
fontSize: 120,
|
||||
opacity: 95,
|
||||
isZoomActiveLrc: true,
|
||||
},
|
||||
},
|
||||
list: {
|
||||
isClickPlayList: false,
|
||||
isShowAlbumName: true,
|
||||
isShowSource: true,
|
||||
isSaveScrollLocation: true,
|
||||
addMusicLocationType: 'top',
|
||||
},
|
||||
download: {
|
||||
enable: false,
|
||||
savePath: path.join(os.homedir(), 'Desktop'),
|
||||
fileName: '歌名 - 歌手',
|
||||
maxDownloadNum: 3,
|
||||
isDownloadLrc: false,
|
||||
lrcFormat: 'utf8',
|
||||
isEmbedPic: true,
|
||||
isEmbedLyric: false,
|
||||
isUseOtherSource: false,
|
||||
},
|
||||
leaderboard: {
|
||||
source: 'kw',
|
||||
tabId: 'kw__16',
|
||||
},
|
||||
songList: {
|
||||
source: 'kg',
|
||||
sortId: '5',
|
||||
tagInfo: {
|
||||
name: '默认',
|
||||
id: null,
|
||||
},
|
||||
},
|
||||
odc: {
|
||||
isAutoClearSearchInput: false,
|
||||
isAutoClearSearchList: false,
|
||||
},
|
||||
search: {
|
||||
searchSource: 'all',
|
||||
tempSearchSource: 'kw',
|
||||
isShowHotSearch: false,
|
||||
isShowHistorySearch: false,
|
||||
isFocusSearchBox: false,
|
||||
},
|
||||
network: {
|
||||
proxy: {
|
||||
enable: false,
|
||||
host: '',
|
||||
port: '',
|
||||
username: '',
|
||||
password: '',
|
||||
},
|
||||
},
|
||||
tray: {
|
||||
isShow: false,
|
||||
isToTray: false,
|
||||
themeId: 0,
|
||||
},
|
||||
sync: {
|
||||
enable: false,
|
||||
port: '23332',
|
||||
},
|
||||
windowSizeId: 2,
|
||||
startInFullscreen: false,
|
||||
theme: {
|
||||
id: 0,
|
||||
lightId: 0,
|
||||
darkId: 13,
|
||||
},
|
||||
langId: null,
|
||||
sourceId: 'kw',
|
||||
apiSource: 'temp',
|
||||
sourceNameType: 'alias',
|
||||
font: '',
|
||||
isShowAnimation: true,
|
||||
randomAnimate: true,
|
||||
ignoreVersion: null,
|
||||
isAgreePact: false,
|
||||
controlBtnPosition: process.platform === 'darwin' ? 'left' : 'right',
|
||||
}
|
||||
|
||||
const overwriteSetting = {
|
||||
|
||||
}
|
||||
|
||||
// 使用新年皮肤
|
||||
if (new Date().getMonth() < 2) {
|
||||
defaultSetting.theme.id = 9
|
||||
defaultSetting.desktopLyric.theme = 3
|
||||
}
|
||||
|
||||
|
||||
exports.defaultSetting = defaultSetting
|
||||
exports.overwriteSetting = overwriteSetting
|
||||
171
src/common/defaultSetting.ts
Normal file
@@ -0,0 +1,171 @@
|
||||
import path from 'node:path'
|
||||
import os from 'node:os'
|
||||
|
||||
const isMac = process.platform == 'darwin'
|
||||
const isWin = process.platform == 'win32'
|
||||
|
||||
const defaultSetting: LX.AppSetting = {
|
||||
version: '2.1.0',
|
||||
|
||||
'common.windowSizeId': 3,
|
||||
'common.fontSize': 16,
|
||||
'common.startInFullscreen': false,
|
||||
'common.langId': null,
|
||||
'common.apiSource': 'temp',
|
||||
'common.sourceNameType': 'alias',
|
||||
'common.font': '',
|
||||
'common.isShowAnimation': true,
|
||||
'common.randomAnimate': true,
|
||||
'common.isAgreePact': false,
|
||||
'common.controlBtnPosition': isMac ? 'left' : 'right',
|
||||
'common.playBarProgressStyle': 'mini',
|
||||
'common.transparentWindow': !isMac,
|
||||
'common.tryAutoUpdate': true,
|
||||
'common.showChangeLog': true,
|
||||
|
||||
'player.startupAutoPlay': false,
|
||||
'player.togglePlayMethod': 'listLoop',
|
||||
'player.playQuality': '128k',
|
||||
'player.isShowTaskProgess': true,
|
||||
'player.isShowStatusBarLyric': false,
|
||||
'player.volume': 1,
|
||||
'player.powerSaveBlocker': true,
|
||||
'player.isMute': false,
|
||||
'player.playbackRate': 1,
|
||||
'player.preservesPitch': true,
|
||||
'player.isMaxOutputChannelCount': false,
|
||||
'player.mediaDeviceId': 'default',
|
||||
'player.isMediaDeviceRemovedStopPlay': false,
|
||||
'player.isShowLyricTranslation': false,
|
||||
'player.isShowLyricRoma': false,
|
||||
'player.isSwapLyricTranslationAndRoma': false,
|
||||
'player.isS2t': false,
|
||||
'player.isPlayLxlrc': !isMac,
|
||||
'player.isSavePlayTime': false,
|
||||
'player.audioVisualization': false,
|
||||
'player.waitPlayEndStop': true,
|
||||
'player.waitPlayEndStopTime': '',
|
||||
'player.autoSkipOnError': true,
|
||||
'player.isAutoCleanPlayedList': false,
|
||||
'player.soundEffect.convolution.fileName': '',
|
||||
'player.soundEffect.convolution.mainGain': 10,
|
||||
'player.soundEffect.convolution.sendGain': 0,
|
||||
'player.soundEffect.biquadFilter.hz31': 0,
|
||||
'player.soundEffect.biquadFilter.hz62': 0,
|
||||
'player.soundEffect.biquadFilter.hz125': 0,
|
||||
'player.soundEffect.biquadFilter.hz250': 0,
|
||||
'player.soundEffect.biquadFilter.hz500': 0,
|
||||
'player.soundEffect.biquadFilter.hz1000': 0,
|
||||
'player.soundEffect.biquadFilter.hz2000': 0,
|
||||
'player.soundEffect.biquadFilter.hz4000': 0,
|
||||
'player.soundEffect.biquadFilter.hz8000': 0,
|
||||
'player.soundEffect.biquadFilter.hz16000': 0,
|
||||
'player.soundEffect.panner.enable': false,
|
||||
'player.soundEffect.panner.soundR': 5,
|
||||
'player.soundEffect.panner.speed': 25,
|
||||
'player.soundEffect.pitchShifter.playbackRate': 1,
|
||||
|
||||
'playDetail.isZoomActiveLrc': false,
|
||||
'playDetail.isShowLyricProgressSetting': false,
|
||||
'playDetail.style.fontSize': 140,
|
||||
'playDetail.style.align': 'center',
|
||||
'playDetail.isDelayScroll': true,
|
||||
|
||||
'desktopLyric.enable': false,
|
||||
'desktopLyric.isLock': false,
|
||||
'desktopLyric.isAlwaysOnTop': false,
|
||||
'desktopLyric.isAlwaysOnTopLoop': false,
|
||||
'desktopLyric.isShowTaskbar': false,
|
||||
'desktopLyric.audioVisualization': false,
|
||||
'desktopLyric.fullscreenHide': true,
|
||||
'desktopLyric.pauseHide': true,
|
||||
'desktopLyric.width': 450,
|
||||
'desktopLyric.height': 300,
|
||||
'desktopLyric.x': null,
|
||||
'desktopLyric.y': null,
|
||||
'desktopLyric.isLockScreen': isWin,
|
||||
'desktopLyric.isDelayScroll': true,
|
||||
'desktopLyric.scrollAlign': 'center',
|
||||
'desktopLyric.isHoverHide': false,
|
||||
'desktopLyric.direction': 'horizontal',
|
||||
'desktopLyric.style.align': 'center',
|
||||
'desktopLyric.style.font': '',
|
||||
'desktopLyric.style.fontSize': 20,
|
||||
'desktopLyric.style.lineGap': 15,
|
||||
'desktopLyric.style.lyricUnplayColor': 'rgba(255, 255, 255, 1)',
|
||||
'desktopLyric.style.lyricPlayedColor': 'rgba(7, 197, 86, 1)',
|
||||
'desktopLyric.style.lyricShadowColor': 'rgba(0, 0, 0, 0.18)',
|
||||
// 'desktopLyric.style.fontWeight': false,
|
||||
'desktopLyric.style.opacity': 95,
|
||||
'desktopLyric.style.ellipsis': false,
|
||||
'desktopLyric.style.isZoomActiveLrc': false,
|
||||
'desktopLyric.style.isFontWeightFont': true,
|
||||
'desktopLyric.style.isFontWeightLine': true,
|
||||
'desktopLyric.style.isFontWeightExtended': true,
|
||||
|
||||
'list.isClickPlayList': false,
|
||||
'list.isShowSource': true,
|
||||
'list.isSaveScrollLocation': true,
|
||||
'list.addMusicLocationType': 'top',
|
||||
'list.actionButtonsVisible': false,
|
||||
|
||||
'download.enable': false,
|
||||
'download.isSavePathGroupByListName': false,
|
||||
'download.savePath': path.join(os.homedir(), 'Desktop'),
|
||||
'download.fileName': '歌名 - 歌手',
|
||||
'download.maxDownloadNum': 3,
|
||||
'download.skipExistFile': true,
|
||||
'download.isDownloadLrc': false,
|
||||
'download.isDownloadLxLrc': true,
|
||||
'download.isDownloadTLrc': false,
|
||||
'download.isDownloadRLrc': false,
|
||||
'download.lrcFormat': 'utf8',
|
||||
'download.isEmbedPic': true,
|
||||
'download.isEmbedLyric': false,
|
||||
'download.isEmbedLyricLx': true,
|
||||
'download.isEmbedLyricT': false,
|
||||
'download.isEmbedLyricR': false,
|
||||
'download.isUseOtherSource': false,
|
||||
|
||||
'search.isShowHotSearch': false,
|
||||
'search.isShowHistorySearch': false,
|
||||
'search.isFocusSearchBox': false,
|
||||
|
||||
'network.proxy.enable': false,
|
||||
'network.proxy.host': '',
|
||||
'network.proxy.port': '',
|
||||
|
||||
'tray.enable': false,
|
||||
// 'tray.isToTray': false,
|
||||
'tray.themeId': 0,
|
||||
|
||||
'sync.mode': 'server',
|
||||
'sync.enable': false,
|
||||
'sync.server.port': '23332',
|
||||
'sync.server.maxSsnapshotNum': 5,
|
||||
'sync.client.host': '',
|
||||
|
||||
'openAPI.enable': false,
|
||||
'openAPI.port': '23330',
|
||||
'openAPI.bindLan': false,
|
||||
|
||||
// 'theme.id': 'blue_plus',
|
||||
'theme.id': 'green',
|
||||
'theme.lightId': 'green',
|
||||
'theme.darkId': 'black',
|
||||
|
||||
'odc.isAutoClearSearchInput': false,
|
||||
'odc.isAutoClearSearchList': false,
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 使用新年皮肤
|
||||
if (new Date().getMonth() < 2) {
|
||||
defaultSetting['theme.id'] = 'happy_new_year'
|
||||
defaultSetting['desktopLyric.style.lyricPlayedColor'] = 'rgba(255, 57, 71, 1)'
|
||||
}
|
||||
|
||||
|
||||
export default defaultSetting
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
const { log } = require('./utils')
|
||||
import { log } from './utils'
|
||||
|
||||
process.on('uncaughtException', function(err) {
|
||||
const ignoreErrorMessage = [
|
||||
'Possible side-effect in debug-evaluate',
|
||||
'Unexpected end of input',
|
||||
]
|
||||
|
||||
process.on('uncaughtException', err => {
|
||||
if (ignoreErrorMessage.includes(err?.message)) return
|
||||
console.error('An uncaught error occurred!')
|
||||
console.error(err)
|
||||
log.error(err)
|
||||
@@ -1,83 +0,0 @@
|
||||
const names = require('@main/events/_name')
|
||||
const hotKey = {
|
||||
common: {
|
||||
min: {
|
||||
name: 'min',
|
||||
action: 'min',
|
||||
},
|
||||
min_toggle: {
|
||||
name: 'toggle_min',
|
||||
action: 'toggle_min',
|
||||
},
|
||||
hide_toggle: {
|
||||
name: 'toggle_hide',
|
||||
action: 'toggle_hide',
|
||||
},
|
||||
close: {
|
||||
name: 'toggle_close',
|
||||
action: 'toggle_close',
|
||||
},
|
||||
focusSearchInput: {
|
||||
name: 'focus_search_input',
|
||||
action: 'focus_search_input',
|
||||
},
|
||||
},
|
||||
player: {
|
||||
toggle_play: {
|
||||
name: 'toggle_play',
|
||||
action: 'toggle_play',
|
||||
},
|
||||
next: {
|
||||
name: 'next',
|
||||
action: 'next',
|
||||
},
|
||||
prev: {
|
||||
name: 'prev',
|
||||
action: 'prev',
|
||||
},
|
||||
volume_up: {
|
||||
name: 'volume_up',
|
||||
action: 'volume_up',
|
||||
},
|
||||
volume_down: {
|
||||
name: 'volume_down',
|
||||
action: 'volume_down',
|
||||
},
|
||||
volume_mute: {
|
||||
name: 'volume_mute',
|
||||
action: 'volume_mute',
|
||||
},
|
||||
},
|
||||
desktop_lyric: {
|
||||
toggle_visible: {
|
||||
name: 'toggle_visible',
|
||||
action: 'toggle_visible',
|
||||
},
|
||||
toggle_lock: {
|
||||
name: 'toggle_lock',
|
||||
action: 'toggle_lock',
|
||||
},
|
||||
toggle_always_top: {
|
||||
name: 'toggle_always_top',
|
||||
action: 'toggle_always_top',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const keyName = {
|
||||
player: names.mainWindow.name,
|
||||
desktop_lyric: names.winLyric.name,
|
||||
}
|
||||
|
||||
for (const type of Object.keys(hotKey)) {
|
||||
let item = hotKey[type]
|
||||
for (const key of Object.keys(item)) {
|
||||
item[key].action = `${type}_${item[key].action}`
|
||||
item[key].name = `${type}_${item[key].name}`
|
||||
item[key].type = keyName[type]
|
||||
}
|
||||
}
|
||||
|
||||
exports.common = hotKey.common
|
||||
exports.player = hotKey.player
|
||||
exports.desktop_lyric = hotKey.desktop_lyric
|
||||
126
src/common/hotKey.ts
Normal file
@@ -0,0 +1,126 @@
|
||||
import { APP_EVENT_NAMES } from './constants'
|
||||
|
||||
|
||||
const keyName = {
|
||||
common: APP_EVENT_NAMES.winMainName,
|
||||
player: APP_EVENT_NAMES.winMainName,
|
||||
desktop_lyric: APP_EVENT_NAMES.winLyricName,
|
||||
}
|
||||
|
||||
const hotKey = {
|
||||
common: {
|
||||
min: {
|
||||
name: 'min',
|
||||
action: 'min',
|
||||
type: '',
|
||||
},
|
||||
min_toggle: {
|
||||
name: 'toggle_min',
|
||||
action: 'toggle_min',
|
||||
type: '',
|
||||
},
|
||||
hide_toggle: {
|
||||
name: 'toggle_hide',
|
||||
action: 'toggle_hide',
|
||||
type: '',
|
||||
},
|
||||
close: {
|
||||
name: 'toggle_close',
|
||||
action: 'toggle_close',
|
||||
type: '',
|
||||
},
|
||||
focusSearchInput: {
|
||||
name: 'focus_search_input',
|
||||
action: 'focus_search_input',
|
||||
type: '',
|
||||
},
|
||||
},
|
||||
player: {
|
||||
toggle_play: {
|
||||
name: 'toggle_play',
|
||||
action: 'toggle_play',
|
||||
type: '',
|
||||
},
|
||||
next: {
|
||||
name: 'next',
|
||||
action: 'next',
|
||||
type: '',
|
||||
},
|
||||
prev: {
|
||||
name: 'prev',
|
||||
action: 'prev',
|
||||
type: '',
|
||||
},
|
||||
seekbackward: {
|
||||
name: 'seekbackward',
|
||||
action: 'seekbackward',
|
||||
type: '',
|
||||
},
|
||||
seekforward: {
|
||||
name: 'seekforward',
|
||||
action: 'seekforward',
|
||||
type: '',
|
||||
},
|
||||
volume_up: {
|
||||
name: 'volume_up',
|
||||
action: 'volume_up',
|
||||
type: '',
|
||||
},
|
||||
volume_down: {
|
||||
name: 'volume_down',
|
||||
action: 'volume_down',
|
||||
type: '',
|
||||
},
|
||||
volume_mute: {
|
||||
name: 'volume_mute',
|
||||
action: 'volume_mute',
|
||||
type: '',
|
||||
},
|
||||
music_love: {
|
||||
name: 'music_love',
|
||||
action: 'music_love',
|
||||
type: '',
|
||||
},
|
||||
music_unlove: {
|
||||
name: 'music_unlove',
|
||||
action: 'music_unlove',
|
||||
type: '',
|
||||
},
|
||||
music_dislike: {
|
||||
name: 'music_dislike',
|
||||
action: 'music_dislike',
|
||||
type: '',
|
||||
},
|
||||
},
|
||||
desktop_lyric: {
|
||||
toggle_visible: {
|
||||
name: 'toggle_visible',
|
||||
action: 'toggle_visible',
|
||||
type: '',
|
||||
},
|
||||
toggle_lock: {
|
||||
name: 'toggle_lock',
|
||||
action: 'toggle_lock',
|
||||
type: '',
|
||||
},
|
||||
toggle_always_top: {
|
||||
name: 'toggle_always_top',
|
||||
action: 'toggle_always_top',
|
||||
type: '',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for (const type of Object.keys(hotKey) as Array<keyof typeof hotKey>) {
|
||||
let keys = hotKey[type]
|
||||
for (const key of Object.keys(keys) as Array<keyof typeof keys>) {
|
||||
const keyInfo: LX.HotKey = keys[key]
|
||||
keyInfo.action = `${type}_${keyInfo.action}`
|
||||
keyInfo.name = `${type}_${keyInfo.name}`
|
||||
keyInfo.type = keyName[type] as keyof typeof hotKey
|
||||
}
|
||||
}
|
||||
|
||||
export const HOTKEY_COMMON = hotKey.common
|
||||
export const HOTKEY_PLAYER = hotKey.player
|
||||
export const HOTKEY_DESKTOP_LYRIC = hotKey.desktop_lyric
|
||||
@@ -1,52 +0,0 @@
|
||||
const { ipcMain, ipcRenderer } = require('electron')
|
||||
const names = require('./ipcNames')
|
||||
|
||||
|
||||
exports.mainOn = (name, callback) => {
|
||||
ipcMain.on(name, callback)
|
||||
}
|
||||
exports.mainOnce = (name, callback) => {
|
||||
ipcMain.once(name, callback)
|
||||
}
|
||||
exports.mainOff = (name, callback) => {
|
||||
ipcMain.removeListener(name, callback)
|
||||
}
|
||||
exports.mainOffAll = name => {
|
||||
ipcMain.removeAllListeners(name)
|
||||
}
|
||||
|
||||
exports.mainHandle = (name, callback) => {
|
||||
ipcMain.handle(name, callback)
|
||||
}
|
||||
exports.mainHandleOnce = (name, callback) => {
|
||||
ipcMain.handleOnce(name, callback)
|
||||
}
|
||||
exports.mainHandleRemove = name => {
|
||||
ipcMain.removeListener(name)
|
||||
}
|
||||
|
||||
exports.mainSend = (window, name, params) => {
|
||||
window.webContents.send(name, params)
|
||||
}
|
||||
|
||||
exports.rendererSend = (name, params) => {
|
||||
ipcRenderer.send(name, params)
|
||||
}
|
||||
exports.rendererSendSync = (name, params) => ipcRenderer.sendSync(name, params)
|
||||
|
||||
exports.rendererInvoke = (name, params) => ipcRenderer.invoke(name, params)
|
||||
|
||||
exports.rendererOn = (name, callback) => {
|
||||
ipcRenderer.on(name, callback)
|
||||
}
|
||||
exports.rendererOnce = (name, callback) => {
|
||||
ipcRenderer.once(name, callback)
|
||||
}
|
||||
exports.rendererOff = (name, callback) => {
|
||||
ipcRenderer.removeListener(name, callback)
|
||||
}
|
||||
exports.rendererOffAll = name => {
|
||||
ipcRenderer.removeAllListeners(name)
|
||||
}
|
||||
|
||||
exports.NAMES = names
|
||||
@@ -1,126 +0,0 @@
|
||||
const names = {
|
||||
mainWindow: {
|
||||
focus: 'focus',
|
||||
close: 'close',
|
||||
min: 'min',
|
||||
max: 'max',
|
||||
fullscreen: 'fullscreen',
|
||||
set_app_name: 'set_app_name',
|
||||
clear_cache: 'clear_cache',
|
||||
get_cache_size: 'get_cache_size',
|
||||
get_env_params: 'get_env_params',
|
||||
clear_env_params_deeplink: 'clear_env_params_deeplink',
|
||||
wait: 'wait',
|
||||
wait_cancel: 'wait_cancel',
|
||||
interval: 'interval',
|
||||
interval_callback: 'interval_callback',
|
||||
interval_cancel: 'interval_cancel',
|
||||
open_dev_tools: 'open_dev_tools',
|
||||
system_theme_change: 'system_theme_change',
|
||||
|
||||
set_music_meta: 'set_music_meta',
|
||||
progress: 'progress',
|
||||
change_tray: 'change_tray',
|
||||
quit_update: 'quit_update',
|
||||
update_available: 'update_available',
|
||||
update_error: 'update_error',
|
||||
update_progress: 'update_progress',
|
||||
update_downloaded: 'update_downloaded',
|
||||
update_not_available: 'update_not_available',
|
||||
set_ignore_mouse_events: 'set_ignore_mouse_events',
|
||||
set_app_setting: 'set_app_setting',
|
||||
set_window_size: 'set_window_size',
|
||||
show_save_dialog: 'show_save_dialog',
|
||||
get_system_fonts: 'get_system_fonts',
|
||||
|
||||
handle_request: 'handle_request',
|
||||
cancel_request: 'cancel_request',
|
||||
|
||||
handle_xm_verify_open: 'handle_xm_verify_open',
|
||||
handle_xm_verify_close: 'handle_xm_verify_close',
|
||||
select_dir: 'select_dir',
|
||||
|
||||
restart_window: 'restart_window',
|
||||
|
||||
lang_s2t: 'lang_s2t',
|
||||
|
||||
handle_kw_decode_lyric: 'handle_kw_decode_lyric',
|
||||
get_lyric_info: 'get_lyric_info',
|
||||
set_lyric_info: 'set_lyric_info',
|
||||
set_config: 'set_config',
|
||||
set_hot_key_config: 'set_hot_key_config',
|
||||
key_down: 'key_down',
|
||||
quit: 'quit',
|
||||
min_toggle: 'min_toggle',
|
||||
hide_toggle: 'hide_toggle',
|
||||
get_data_path: 'get_data_path',
|
||||
show_dialog: 'show_dialog',
|
||||
|
||||
get_setting: 'get_setting',
|
||||
get_playlist: 'get_playlist',
|
||||
save_playlist: 'save_playlist',
|
||||
get_data: 'get_data',
|
||||
save_data: 'save_data',
|
||||
get_hot_key: 'get_hot_key',
|
||||
|
||||
import_user_api: 'import_user_api',
|
||||
remove_user_api: 'remove_user_api',
|
||||
set_user_api: 'set_user_api',
|
||||
get_user_api_list: 'get_user_api_list',
|
||||
request_user_api: 'request_user_api',
|
||||
request_user_api_cancel: 'request_user_api_cancel',
|
||||
get_user_api_status: 'get_user_api_status',
|
||||
user_api_status: 'user_api_status',
|
||||
user_api_show_update_alert: 'user_api_show_update_alert',
|
||||
user_api_set_allow_update_alert: 'user_api_set_allow_update_alert',
|
||||
|
||||
get_lyric: 'get_lyric',
|
||||
save_lyric: 'save_lyric',
|
||||
clear_lyric: 'clear_lyric',
|
||||
get_lyric_raw: 'get_lyric_raw',
|
||||
save_lyric_raw: 'save_lyric_raw',
|
||||
clear_lyric_raw: 'clear_lyric_raw',
|
||||
get_lyric_edited: 'get_lyric_edited',
|
||||
save_lyric_edited: 'save_lyric_edited',
|
||||
remove_lyric_edited: 'remove_lyric_edited',
|
||||
get_music_url: 'get_music_url',
|
||||
save_music_url: 'save_music_url',
|
||||
clear_music_url: 'clear_music_url',
|
||||
|
||||
sync_enable: 'sync_enable',
|
||||
sync_status: 'sync_status',
|
||||
sync_get_status: 'sync_get_status',
|
||||
sync_generate_code: 'sync_generate_code',
|
||||
sync_action_list: 'sync_action_list',
|
||||
sync_list: 'sync_list',
|
||||
|
||||
taskbar_set_thumbar_buttons: 'taskbar_set_thumbar_buttons',
|
||||
taskbar_set_thumbnail_clip: 'taskbar_set_thumbnail_clip',
|
||||
taskbar_on_thumbar_button_click: 'taskbar_on_thumbar_button_click',
|
||||
},
|
||||
winLyric: {
|
||||
close: 'close',
|
||||
set_lyric_info: 'set_lyric_info',
|
||||
get_lyric_info: 'get_lyric_info',
|
||||
set_lyric_config: 'set_lyric_config',
|
||||
get_lyric_config: 'get_lyric_config',
|
||||
set_win_bounds: 'set_win_bounds',
|
||||
key_down: 'key_down',
|
||||
},
|
||||
hotKey: {
|
||||
enable: 'enable',
|
||||
status: 'status',
|
||||
set_config: 'set_config',
|
||||
},
|
||||
}
|
||||
|
||||
for (const item of Object.keys(names)) {
|
||||
let name = names[item]
|
||||
for (const key of Object.keys(name)) {
|
||||
name[key] = `${item}_${name[key]}`
|
||||
}
|
||||
}
|
||||
|
||||
exports.mainWindow = names.mainWindow
|
||||
exports.winLyric = names.winLyric
|
||||
exports.hotKey = names.hotKey
|
||||
198
src/common/ipcNames.ts
Normal file
@@ -0,0 +1,198 @@
|
||||
const modules = {
|
||||
common: {
|
||||
get_env_params: 'get_env_params',
|
||||
deeplink: 'deeplink',
|
||||
clear_env_params_deeplink: 'clear_env_params_deeplink',
|
||||
system_theme_change: 'system_theme_change',
|
||||
theme_change: 'theme_change',
|
||||
get_system_fonts: 'get_system_fonts',
|
||||
get_app_setting: 'get_app_setting',
|
||||
set_app_setting: 'set_app_setting',
|
||||
},
|
||||
player: {
|
||||
invoke_play_music: 'play_music',
|
||||
invoke_play_next: 'play_next',
|
||||
invoke_play_prev: 'play_prev',
|
||||
invoke_toggle_play: 'toggle_play',
|
||||
player_play: 'player_play',
|
||||
player_pause: 'player_pause',
|
||||
player_stop: 'player_stop',
|
||||
player_error: 'player_error',
|
||||
|
||||
list_data_overwire: 'list_data_overwire',
|
||||
list_get: 'list_get',
|
||||
list_add: 'list_add',
|
||||
list_remove: 'list_remove',
|
||||
list_update: 'list_update',
|
||||
list_update_position: 'list_update_position',
|
||||
list_music_get: 'list_music_get',
|
||||
list_music_add: 'list_music_add',
|
||||
list_music_move: 'list_music_move',
|
||||
list_music_remove: 'list_music_remove',
|
||||
list_music_update: 'list_music_update',
|
||||
list_music_update_position: 'list_music_update_position',
|
||||
list_music_overwrite: 'list_music_overwrite',
|
||||
list_music_clear: 'list_music_clear',
|
||||
list_music_check_exist: 'list_music_check_exist',
|
||||
list_music_get_list_ids: 'list_music_get_list_ids',
|
||||
},
|
||||
dislike: {
|
||||
get_dislike_music_infos: 'get_dislike_music_infos',
|
||||
add_dislike_music_infos: 'add_dislike_music_infos',
|
||||
overwrite_dislike_music_infos: 'overwrite_dislike_music_infos',
|
||||
clear_dislike_music_infos: 'clear_dislike_music_infos',
|
||||
},
|
||||
winMain: {
|
||||
focus: 'focus',
|
||||
close: 'close',
|
||||
min: 'min',
|
||||
max: 'max',
|
||||
fullscreen: 'fullscreen',
|
||||
set_app_name: 'set_app_name',
|
||||
clear_cache: 'clear_cache',
|
||||
get_cache_size: 'get_cache_size',
|
||||
inited: 'inited',
|
||||
show_save_dialog: 'show_save_dialog',
|
||||
show_select_dialog: 'show_select_dialog',
|
||||
show_dialog: 'show_dialog',
|
||||
open_dir_in_explorer: 'open_dir_in_explorer',
|
||||
open_dev_tools: 'open_dev_tools',
|
||||
set_power_save_blocker: 'set_power_save_blocker',
|
||||
|
||||
player_status: 'player_status',
|
||||
change_tray: 'change_tray',
|
||||
quit_update: 'quit_update',
|
||||
update_check: 'update_check',
|
||||
update_download_update: 'update_download_update',
|
||||
update_available: 'update_available',
|
||||
update_error: 'update_error',
|
||||
update_progress: 'update_progress',
|
||||
update_downloaded: 'update_downloaded',
|
||||
update_not_available: 'update_not_available',
|
||||
set_ignore_mouse_events: 'set_ignore_mouse_events',
|
||||
set_window_size: 'set_window_size',
|
||||
|
||||
handle_request: 'handle_request',
|
||||
cancel_request: 'cancel_request',
|
||||
|
||||
|
||||
restart_window: 'restart_window',
|
||||
|
||||
// lang_s2t: 'lang_s2t',
|
||||
|
||||
handle_kw_decode_lyric: 'handle_kw_decode_lyric',
|
||||
handle_tx_decode_lyric: 'handle_tx_decode_lyric',
|
||||
get_lyric_info: 'get_lyric_info',
|
||||
set_lyric_info: 'set_lyric_info',
|
||||
set_config: 'set_config',
|
||||
set_hot_key_config: 'set_hot_key_config',
|
||||
on_config_change: 'on_config_change',
|
||||
key_down: 'key_down',
|
||||
quit: 'quit',
|
||||
min_toggle: 'min_toggle',
|
||||
hide_toggle: 'hide_toggle',
|
||||
|
||||
get_other_source: 'get_other_source',
|
||||
save_other_source: 'save_other_source',
|
||||
clear_other_source: 'clear_other_source',
|
||||
get_other_source_count: 'get_other_source_count',
|
||||
get_data: 'get_data',
|
||||
save_data: 'save_data',
|
||||
get_sound_effect_eq_preset: 'get_sound_effect_eq_preset',
|
||||
save_sound_effect_eq_preset: 'save_sound_effect_eq_preset',
|
||||
get_sound_effect_convolution_preset: 'get_sound_effect_convolution_preset',
|
||||
save_sound_effect_convolution_preset: 'save_sound_effect_convolution_preset',
|
||||
// get_sound_effect_pitch_shifter_preset: 'get_sound_effect_pitch_shifter_preset',
|
||||
// save_sound_effect_pitch_shifter_preset: 'save_sound_effect_pitch_shifter_preset',
|
||||
get_hot_key: 'get_hot_key',
|
||||
|
||||
import_user_api: 'import_user_api',
|
||||
remove_user_api: 'remove_user_api',
|
||||
set_user_api: 'set_user_api',
|
||||
get_user_api_list: 'get_user_api_list',
|
||||
request_user_api: 'request_user_api',
|
||||
request_user_api_cancel: 'request_user_api_cancel',
|
||||
get_user_api_status: 'get_user_api_status',
|
||||
user_api_status: 'user_api_status',
|
||||
user_api_show_update_alert: 'user_api_show_update_alert',
|
||||
user_api_set_allow_update_alert: 'user_api_set_allow_update_alert',
|
||||
|
||||
get_palyer_lyric: 'get_lyric',
|
||||
// save_lyric: 'save_lyric',
|
||||
// clear_lyric: 'clear_lyric',
|
||||
get_lyric_raw: 'get_lyric_raw',
|
||||
save_lyric_raw: 'save_lyric_raw',
|
||||
clear_lyric_raw: 'clear_lyric_raw',
|
||||
get_lyric_raw_count: 'get_lyric_raw_count',
|
||||
get_lyric_edited: 'get_lyric_edited',
|
||||
save_lyric_edited: 'save_lyric_edited',
|
||||
remove_lyric_edited: 'remove_lyric_edited',
|
||||
clear_lyric_edited: 'clear_lyric_edited',
|
||||
get_lyric_edited_count: 'get_lyric_edited_count',
|
||||
get_music_url: 'get_music_url',
|
||||
save_music_url: 'save_music_url',
|
||||
clear_music_url: 'clear_music_url',
|
||||
get_music_url_count: 'get_music_url_count',
|
||||
|
||||
open_api_action: 'open_api_action',
|
||||
sync_action: 'sync_action',
|
||||
sync_get_server_devices: 'sync_get_server_devices',
|
||||
sync_remove_server_device: 'sync_remove_server_device',
|
||||
|
||||
process_new_desktop_lyric_client: 'process_new_desktop_lyric_client',
|
||||
|
||||
player_action_set_buttons: 'player_action_set_buttons',
|
||||
// player_action_set_thumbnail_clip: 'player_action_set_thumbnail_clip',
|
||||
player_action_on_button_click: 'player_action_on_button_click',
|
||||
|
||||
get_themes: 'get_themes',
|
||||
save_theme: 'save_theme',
|
||||
remove_theme: 'remove_theme',
|
||||
|
||||
download_list_get: 'download_list_get',
|
||||
download_list_add: 'download_list_add',
|
||||
download_list_update: 'download_list_update',
|
||||
download_list_remove: 'download_list_remove',
|
||||
download_list_clear: 'download_list_clear',
|
||||
},
|
||||
winLyric: {
|
||||
close: 'close',
|
||||
set_config: 'set_config',
|
||||
get_config: 'get_config',
|
||||
on_config_change: 'on_config_change',
|
||||
main_window_inited: 'main_window_inited',
|
||||
set_win_bounds: 'set_win_bounds',
|
||||
set_win_resizeable: 'set_win_resizeable',
|
||||
key_down: 'key_down',
|
||||
request_main_window_channel: 'request_main_window_channel',
|
||||
provide_main_window_channel: 'provide_main_window_channel',
|
||||
},
|
||||
hotKey: {
|
||||
enable: 'enable',
|
||||
status: 'status',
|
||||
set_config: 'set_config',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
for (const moduleName of Object.keys(modules) as Array<keyof typeof modules>) {
|
||||
let eventNames = modules[moduleName]
|
||||
for (const eventName of Object.keys(eventNames) as Array<keyof typeof eventNames>) {
|
||||
eventNames[eventName] = `${moduleName}_${eventName as string}` as never
|
||||
}
|
||||
}
|
||||
|
||||
// for (const moduleName of Object.keys(modules) as Array<keyof typeof modules>) {
|
||||
// let eventNames = modules[moduleName]
|
||||
// for (const eventName of Object.keys(eventNames)) {
|
||||
// eventNames[eventName] = `${moduleName}_${eventName}`
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
export const CMMON_EVENT_NAME = modules.common
|
||||
export const PLAYER_EVENT_NAME = modules.player
|
||||
export const DISLIKE_EVENT_NAME = modules.dislike
|
||||
export const WIN_MAIN_RENDERER_EVENT_NAME = modules.winMain
|
||||
export const WIN_LYRIC_RENDERER_EVENT_NAME = modules.winLyric
|
||||
export const HOTKEY_RENDERER_EVENT_NAME = modules.hotKey
|
||||
54
src/common/mainIpc.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { ipcMain } from 'electron'
|
||||
|
||||
export function mainOn(name: string, listener: LX.IpcMainEventListener): void
|
||||
export function mainOn<T>(name: string, listener: LX.IpcMainEventListenerParams<T>): void
|
||||
export function mainOn<T>(name: string, listener: LX.IpcMainEventListenerParams<T>): void {
|
||||
ipcMain.on(name, (event, params) => {
|
||||
listener({ event, params })
|
||||
})
|
||||
}
|
||||
|
||||
export function mainOnce(name: string, listener: LX.IpcMainEventListener): void
|
||||
export function mainOnce<T>(name: string, listener: LX.IpcMainEventListenerParams<T>): void
|
||||
export function mainOnce<T>(name: string, listener: LX.IpcMainEventListenerParams<T>): void {
|
||||
ipcMain.once(name, (event, params) => {
|
||||
listener({ event, params })
|
||||
})
|
||||
}
|
||||
|
||||
export const mainOff = (name: string, listener: (...args: any[]) => void) => {
|
||||
ipcMain.removeListener(name, listener)
|
||||
}
|
||||
|
||||
export const mainOffAll = (name: string) => {
|
||||
ipcMain.removeAllListeners(name)
|
||||
}
|
||||
|
||||
export function mainHandle(name: string, listener: LX.IpcMainInvokeEventListener): void
|
||||
export function mainHandle<T>(name: string, listener: LX.IpcMainInvokeEventListenerParams<T>): void
|
||||
export function mainHandle<V>(name: string, listener: LX.IpcMainInvokeEventListenerValue<V>): void
|
||||
export function mainHandle<T, V>(name: string, listener: LX.IpcMainInvokeEventListenerParamsValue<T, V>): void
|
||||
export function mainHandle<T, V>(name: string, listener: LX.IpcMainInvokeEventListenerParamsValue<T, V>): void {
|
||||
ipcMain.handle(name, async(event, params) => {
|
||||
return listener({ event, params })
|
||||
})
|
||||
}
|
||||
|
||||
export function mainHandleOnce(name: string, listener: LX.IpcMainInvokeEventListener): void
|
||||
export function mainHandleOnce<T>(name: string, listener: LX.IpcMainInvokeEventListenerParams<T>): void
|
||||
export function mainHandleOnce<V>(name: string, listener: LX.IpcMainInvokeEventListenerValue<V>): void
|
||||
export function mainHandleOnce<T, V>(name: string, listener: LX.IpcMainInvokeEventListenerParamsValue<T, V>): void
|
||||
export function mainHandleOnce<T, V>(name: string, listener: LX.IpcMainInvokeEventListenerParamsValue<T, V>): void {
|
||||
ipcMain.handleOnce(name, async(event, params) => {
|
||||
return listener({ event, params })
|
||||
})
|
||||
}
|
||||
export const mainHandleRemove = (name: string) => {
|
||||
ipcMain.removeHandler(name)
|
||||
}
|
||||
|
||||
export function mainSend(window: Electron.BrowserWindow, name: string): void
|
||||
export function mainSend<T>(window: Electron.BrowserWindow, name: string, params: T): void
|
||||
export function mainSend<T>(window: Electron.BrowserWindow, name: string, params?: T): void {
|
||||
window.webContents.send(name, params)
|
||||
}
|
||||
45
src/common/rendererIpc.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { ipcRenderer } from 'electron'
|
||||
|
||||
export function rendererSend(name: string): void
|
||||
export function rendererSend<T>(name: string, params: T): void
|
||||
export function rendererSend<T>(name: string, params?: T): void {
|
||||
ipcRenderer.send(name, params)
|
||||
}
|
||||
|
||||
export function rendererSendSync(name: string): void
|
||||
export function rendererSendSync<T>(name: string, params: T): void
|
||||
export function rendererSendSync<T>(name: string, params?: T): void {
|
||||
ipcRenderer.sendSync(name, params)
|
||||
}
|
||||
|
||||
export async function rendererInvoke(name: string): Promise<void>
|
||||
export async function rendererInvoke<V>(name: string): Promise<V>
|
||||
export async function rendererInvoke<T>(name: string, params: T): Promise<void>
|
||||
export async function rendererInvoke<T, V>(name: string, params: T): Promise<V>
|
||||
export async function rendererInvoke <T, V>(name: string, params?: T): Promise<V> {
|
||||
return ipcRenderer.invoke(name, params)
|
||||
}
|
||||
|
||||
export function rendererOn(name: string, listener: LX.IpcRendererEventListener): void
|
||||
export function rendererOn<T>(name: string, listener: LX.IpcRendererEventListenerParams<T>): void
|
||||
export function rendererOn<T>(name: string, listener: LX.IpcRendererEventListenerParams<T>): void {
|
||||
ipcRenderer.on(name, (event, params) => {
|
||||
listener({ event, params })
|
||||
})
|
||||
}
|
||||
|
||||
export function rendererOnce(name: string, listener: LX.IpcRendererEventListener): void
|
||||
export function rendererOnce<T>(name: string, listener: LX.IpcRendererEventListenerParams<T>): void
|
||||
export function rendererOnce<T>(name: string, listener: LX.IpcRendererEventListenerParams<T>): void {
|
||||
ipcRenderer.once(name, (event, params) => {
|
||||
listener({ event, params })
|
||||
})
|
||||
}
|
||||
|
||||
export const rendererOff = (name: string, listener: (...args: any[]) => any) => {
|
||||
ipcRenderer.removeListener(name, listener)
|
||||
}
|
||||
|
||||
export const rendererOffAll = (name: string) => {
|
||||
ipcRenderer.removeAllListeners(name)
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
const Store = require('electron-store')
|
||||
const { dialog, app, shell } = require('electron')
|
||||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
const log = require('electron-log')
|
||||
|
||||
const stores = {}
|
||||
|
||||
/**
|
||||
* 获取 Store 对象
|
||||
* @param {*} name store 名
|
||||
* @param {*} isIgnoredError 是否忽略错误
|
||||
* @param {*} isShowErrorAlert 是否显示错误弹窗
|
||||
* @returns Store
|
||||
*/
|
||||
module.exports = (name, isIgnoredError = true, isShowErrorAlert = true) => {
|
||||
if (stores[name]) return stores[name]
|
||||
let store
|
||||
try {
|
||||
store = stores[name] = new Store({ name, clearInvalidConfig: false })
|
||||
} catch (error) {
|
||||
log.error(error)
|
||||
|
||||
if (!isIgnoredError) throw error
|
||||
|
||||
|
||||
const backPath = path.join(app.getPath('userData'), name + '.json.bak')
|
||||
fs.copyFileSync(path.join(app.getPath('userData'), name + '.json'), backPath)
|
||||
if (isShowErrorAlert) {
|
||||
dialog.showMessageBoxSync({
|
||||
type: 'error',
|
||||
message: name + ' data load error',
|
||||
detail: `We have helped you back up the old ${name} file to: ${backPath}\nYou can try to repair and restore it manually\n\nError detail: ${error.message}`,
|
||||
})
|
||||
shell.showItemInFolder(backPath)
|
||||
}
|
||||
|
||||
|
||||
store = new Store({ name, clearInvalidConfig: true })
|
||||
}
|
||||
return store
|
||||
}
|
||||
73
src/common/theme/colorUtils.js
Normal file
@@ -0,0 +1,73 @@
|
||||
/* eslint-disable */
|
||||
// https://github.com/PimpTrizkit/PJs/wiki/12.-Shade,-Blend-and-Convert-a-Web-Color-(pSBC.js)#micro-functions-version-4
|
||||
|
||||
/**
|
||||
* Blend color (Lighten or Darken)
|
||||
* @param {number} p 混合百分比 范围 0.0 - 1.0
|
||||
* @param {string} c0 rgb(a) color1
|
||||
* @param {string} c1 rgb(a) color2
|
||||
* @returns color
|
||||
*/
|
||||
exports.RGB_Linear_Blend=(p,c0,c1)=>{
|
||||
var i=parseInt,r=Math.round,P=1-p,[a,b,c,d]=c0.split(","),[e,f,g,h]=c1.split(","),x=d||h,j=x?","+(!d?h:!h?d:r((parseFloat(d)*P+parseFloat(h)*p)*1000)/1000+")"):")";
|
||||
return"rgb"+(x?"a(":"(")+r(i(a[3]=="a"?a.slice(5):a.slice(4))*P+i(e[3]=="a"?e.slice(5):e.slice(4))*p)+","+r(i(b)*P+i(f)*p)+","+r(i(c)*P+i(g)*p)+j;
|
||||
}
|
||||
|
||||
/**
|
||||
* Blend color (Lighten or Darken)
|
||||
* @param {number} p 混合百分比 范围 0.0 - 1.0
|
||||
* @param {string} c0 rgb(a) color1
|
||||
* @param {string} c1 rgb(a) color2
|
||||
* @returns color
|
||||
*/
|
||||
exports.RGB_Log_Blend=(p,c0,c1)=>{
|
||||
var i=parseInt,r=Math.round,P=1-p,[a,b,c,d]=c0.split(","),[e,f,g,h]=c1.split(","),x=d||h,j=x?","+(!d?h:!h?d:r((parseFloat(d)*P+parseFloat(h)*p)*1000)/1000+")"):")";
|
||||
return"rgb"+(x?"a(":"(")+r((P*i(a[3]=="a"?a.slice(5):a.slice(4))**2+p*i(e[3]=="a"?e.slice(5):e.slice(4))**2)**0.5)+","+r((P*i(b)**2+p*i(f)**2)**0.5)+","+r((P*i(c)**2+p*i(g)**2)**0.5)+j;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Shade color (Lighten or Darken)
|
||||
* @param {number} p Shade 百分比范围为 -1.0 - 1.0 负为黑色,正为白色
|
||||
* @param {string} c0 rgb(a) color
|
||||
* @returns color
|
||||
*/
|
||||
exports.RGB_Linear_Shade=(p,c0)=>{
|
||||
var i=parseInt,r=Math.round,[a,b,c,d]=c0.split(","),n=p<0,t=n?0:255*p,P=n?1+p:1-p;
|
||||
return"rgb"+(d?"a(":"(")+r(i(a[3]=="a"?a.slice(5):a.slice(4))*P+t)+","+r(i(b)*P+t)+","+r(i(c)*P+t)+(d?","+d:")");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Shade color (Lighten or Darken)
|
||||
* @param {number} p Shade 百分比范围为 -1.0 - 1.0 负为黑色,正为白色
|
||||
* @param {string} c0 rgb(a) color
|
||||
* @returns color
|
||||
*/
|
||||
exports.RGB_Log_Shade=(p,c0)=>{
|
||||
var i=parseInt,r=Math.round,[a,b,c,d]=c0.split(","),n=p<0,t=n?0:p*255**2,P=n?1+p:1-p;
|
||||
return"rgb"+(d?"a(":"(")+r((P*i(a[3]=="a"?a.slice(5):a.slice(4))**2+t)**0.5)+","+r((P*i(b)**2+t)**0.5)+","+r((P*i(c)**2+t)**0.5)+(d?","+d:")");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 修改透明度
|
||||
* @param {number} p 透明度 -1.0 - 1.0
|
||||
* @param {string} color
|
||||
* @returns color
|
||||
*/
|
||||
exports.RGB_Alpha_Shade = (p, color) => {
|
||||
var i = parseInt
|
||||
var n = p < 0
|
||||
var [r, g, b, a] = color.split(",")
|
||||
r = r[3] == 'a' ? r.slice(5) : r.slice(4)
|
||||
if (a) {
|
||||
a = parseFloat(a)
|
||||
a = a - (n ? (1 - a) * p : a * p)
|
||||
a = n ? Math.max(0, a) : Math.min(1, a)
|
||||
} else {
|
||||
a = 1 - p
|
||||
a = Math.min(1, a)
|
||||
}
|
||||
return `rgba(${i(r)}, ${i(g)}, ${i(b)}, ${a.toFixed(2)})`
|
||||
}
|
||||
384
src/common/theme/createThemes.js
Normal file
@@ -0,0 +1,384 @@
|
||||
//! 更新默认主题配置后,需要执行 npm run build:theme 重新构建index.json
|
||||
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const { createThemeColors } = require('./utils')
|
||||
|
||||
const defaultThemes = [
|
||||
{
|
||||
id: 'green',
|
||||
name: '绿意盎然',
|
||||
isDark: false,
|
||||
isDarkFont: false,
|
||||
config: {
|
||||
primary: 'rgb(77, 175, 124)',
|
||||
font: 'rgb(33, 33, 33)',
|
||||
'--color-app-background': 'var(--color-primary-light-600-alpha-700)',
|
||||
'--color-main-background': 'rgba(255, 255, 255, 1)',
|
||||
'--color-nav-font': 'var(--color-primary)',
|
||||
'--background-image': 'none',
|
||||
'--background-image-position': 'center',
|
||||
'--background-image-size': 'cover',
|
||||
|
||||
'--color-btn-hide': '#3bc2b2',
|
||||
'--color-btn-min': '#85c43b',
|
||||
'--color-btn-close': '#fab4a0',
|
||||
|
||||
'--color-badge-primary': 'var(--color-primary)',
|
||||
'--color-badge-secondary': '#4baed5',
|
||||
'--color-badge-tertiary': '#e7aa36',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'blue',
|
||||
name: '蓝田生玉',
|
||||
isDark: false,
|
||||
isDarkFont: false,
|
||||
config: {
|
||||
primary: 'rgb(52, 152, 219)',
|
||||
font: 'rgb(33, 33, 33)',
|
||||
'--color-app-background': 'var(--color-primary-light-600-alpha-700)',
|
||||
'--color-main-background': 'rgba(255, 255, 255, 1)',
|
||||
'--color-nav-font': 'var(--color-primary)',
|
||||
'--background-image': 'none',
|
||||
'--background-image-position': 'center',
|
||||
'--background-image-size': 'cover',
|
||||
|
||||
'--color-btn-hide': '#3bc2b2',
|
||||
'--color-btn-min': '#85c43b',
|
||||
'--color-btn-close': '#fab4a0',
|
||||
|
||||
'--color-badge-primary': 'var(--color-primary)',
|
||||
'--color-badge-secondary': '#5cbf9b',
|
||||
'--color-badge-tertiary': '#5cbf9b',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'blue_plus',
|
||||
name: '蛋雅深蓝',
|
||||
isDark: false,
|
||||
isDarkFont: false,
|
||||
config: {
|
||||
primary: 'rgb(77, 131, 175)',
|
||||
font: 'rgb(33, 33, 33)',
|
||||
'--color-app-background': 'var(--color-primary-light-600-alpha-600)',
|
||||
'--color-main-background': 'rgba(255, 255, 255, 1)',
|
||||
'--color-nav-font': 'var(--color-primary)',
|
||||
'--background-image': 'none',
|
||||
'--background-image-position': 'center',
|
||||
'--background-image-size': 'cover',
|
||||
|
||||
'--color-btn-hide': '#3bc2b2',
|
||||
'--color-btn-min': '#85c43b',
|
||||
'--color-btn-close': '#fab4a0',
|
||||
|
||||
'--color-badge-primary': 'var(--color-primary)',
|
||||
'--color-badge-secondary': 'rgba(66.6, 150.7, 171, 1)',
|
||||
'--color-badge-tertiary': 'rgba(54, 196, 231, 1)',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'orange',
|
||||
name: '橙黄橘绿',
|
||||
isDark: false,
|
||||
isDarkFont: false,
|
||||
config: {
|
||||
primary: 'rgb(245, 171, 53)',
|
||||
font: 'rgb(33, 33, 33)',
|
||||
'--color-app-background': 'var(--color-primary-light-600-alpha-700)',
|
||||
'--color-main-background': 'rgba(255, 255, 255, 1)',
|
||||
'--color-nav-font': 'var(--color-primary)',
|
||||
'--background-image': 'none',
|
||||
'--background-image-position': 'center',
|
||||
'--background-image-size': 'cover',
|
||||
|
||||
'--color-btn-hide': '#3bc2b2',
|
||||
'--color-btn-min': '#85c43b',
|
||||
'--color-btn-close': '#fab4a0',
|
||||
|
||||
'--color-badge-primary': 'var(--color-primary)',
|
||||
'--color-badge-secondary': '#9ed458',
|
||||
'--color-badge-tertiary': '#9ed458',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'red',
|
||||
name: '热情似火',
|
||||
isDark: false,
|
||||
isDarkFont: false,
|
||||
config: {
|
||||
primary: 'rgb(214, 69, 65)',
|
||||
font: 'rgb(33, 33, 33)',
|
||||
'--color-app-background': 'var(--color-primary-light-600-alpha-700)',
|
||||
'--color-main-background': 'rgba(255, 255, 255, 1)',
|
||||
'--color-nav-font': 'var(--color-primary)',
|
||||
'--background-image': 'none',
|
||||
'--background-image-position': 'center',
|
||||
'--background-image-size': 'cover',
|
||||
|
||||
'--color-btn-hide': '#3bc2b2',
|
||||
'--color-btn-min': '#85c43b',
|
||||
'--color-btn-close': '#fab4a0',
|
||||
|
||||
'--color-badge-primary': 'var(--color-primary)',
|
||||
'--color-badge-secondary': '#dfbb6b',
|
||||
'--color-badge-tertiary': '#dfbb6b',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'pink',
|
||||
name: '粉装玉琢',
|
||||
isDark: false,
|
||||
isDarkFont: false,
|
||||
config: {
|
||||
primary: 'rgb(241, 130, 141)',
|
||||
font: 'rgb(33, 33, 33)',
|
||||
'--color-app-background': 'var(--color-primary-light-600-alpha-700)',
|
||||
'--color-main-background': 'rgba(255, 255, 255, 1)',
|
||||
'--color-nav-font': 'var(--color-primary)',
|
||||
'--background-image': 'none',
|
||||
'--background-image-position': 'center',
|
||||
'--background-image-size': 'cover',
|
||||
|
||||
'--color-btn-hide': '#3bc2b2',
|
||||
'--color-btn-min': '#85c43b',
|
||||
'--color-btn-close': '#fab4a0',
|
||||
|
||||
'--color-badge-primary': 'var(--color-primary)',
|
||||
'--color-badge-secondary': '#f5b684',
|
||||
'--color-badge-tertiary': '#f5b684',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'purple',
|
||||
name: '重斤球紫',
|
||||
isDark: false,
|
||||
isDarkFont: false,
|
||||
config: {
|
||||
primary: 'rgb(155, 89, 182)',
|
||||
font: 'rgb(33, 33, 33)',
|
||||
'--color-app-background': 'var(--color-primary-light-600-alpha-700)',
|
||||
'--color-main-background': 'rgba(255, 255, 255, 1)',
|
||||
'--color-nav-font': 'var(--color-primary)',
|
||||
'--background-image': 'none',
|
||||
'--background-image-position': 'center',
|
||||
'--background-image-size': 'cover',
|
||||
|
||||
'--color-btn-hide': '#3bc2b2',
|
||||
'--color-btn-min': '#85c43b',
|
||||
'--color-btn-close': '#fab4a0',
|
||||
|
||||
'--color-badge-primary': 'var(--color-primary)',
|
||||
'--color-badge-secondary': '#e5a39f',
|
||||
'--color-badge-tertiary': '#e5a39f',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'grey',
|
||||
name: '灰常美丽',
|
||||
isDark: false,
|
||||
isDarkFont: false,
|
||||
config: {
|
||||
primary: 'rgb(108, 122, 137)',
|
||||
font: 'rgb(33, 33, 33)',
|
||||
'--color-app-background': 'var(--color-primary-light-600-alpha-700)',
|
||||
'--color-main-background': 'rgba(255, 255, 255, 1)',
|
||||
'--color-nav-font': 'var(--color-primary)',
|
||||
'--background-image': 'none',
|
||||
'--background-image-position': 'center',
|
||||
'--background-image-size': 'cover',
|
||||
|
||||
'--color-btn-hide': '#3bc2b2',
|
||||
'--color-btn-min': '#85c43b',
|
||||
'--color-btn-close': '#fab4a0',
|
||||
|
||||
'--color-badge-primary': 'var(--color-primary)',
|
||||
'--color-badge-secondary': '#b19b9f',
|
||||
'--color-badge-tertiary': '#b19b9f',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'ming',
|
||||
name: '青出于黑',
|
||||
isDark: false,
|
||||
isDarkFont: false,
|
||||
config: {
|
||||
primary: 'rgb(51, 110, 123)',
|
||||
font: 'rgb(33, 33, 33)',
|
||||
'--color-app-background': 'var(--color-primary-light-600-alpha-700)',
|
||||
'--color-main-background': 'rgba(255, 255, 255, 1)',
|
||||
'--color-nav-font': 'var(--color-primary)',
|
||||
'--background-image': 'none',
|
||||
'--background-image-position': 'center',
|
||||
'--background-image-size': 'cover',
|
||||
|
||||
'--color-btn-hide': '#3bc2b2',
|
||||
'--color-btn-min': '#85c43b',
|
||||
'--color-btn-close': '#fab4a0',
|
||||
|
||||
'--color-badge-primary': 'var(--color-primary)',
|
||||
'--color-badge-secondary': '#6376a2',
|
||||
'--color-badge-tertiary': '#6376a2',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'blue2',
|
||||
name: '清热板蓝',
|
||||
isDark: false,
|
||||
isDarkFont: false,
|
||||
config: {
|
||||
primary: 'rgb(79, 98, 208)',
|
||||
font: 'rgb(33, 33, 33)',
|
||||
'--color-app-background': 'var(--color-primary-light-600-alpha-700)',
|
||||
'--color-main-background': 'rgba(255, 255, 255, 1)',
|
||||
'--color-nav-font': 'var(--color-primary)',
|
||||
'--background-image': 'none',
|
||||
'--background-image-position': 'center',
|
||||
'--background-image-size': 'cover',
|
||||
|
||||
'--color-btn-hide': '#3bc2b2',
|
||||
'--color-btn-min': '#85c43b',
|
||||
'--color-btn-close': '#fab4a0',
|
||||
|
||||
'--color-badge-primary': 'var(--color-primary)',
|
||||
'--color-badge-secondary': '#b080db',
|
||||
'--color-badge-tertiary': '#b080db',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'black',
|
||||
name: '黑灯瞎火',
|
||||
isDark: true,
|
||||
isDarkFont: false,
|
||||
config: {
|
||||
primary: 'rgb(150, 150, 150)',
|
||||
font: 'rgb(229, 229, 229)',
|
||||
'--color-app-background': 'rgba(0, 0, 0, 0)',
|
||||
'--color-main-background': 'rgba(19, 19, 19, 0.9)',
|
||||
'--color-nav-font': 'var(--color-primary)',
|
||||
'--background-image': 'url(./theme_images/landingMoon.png)',
|
||||
'--background-image-position': 'center',
|
||||
'--background-image-size': 'cover',
|
||||
|
||||
'--color-btn-hide': '#3bc2b2',
|
||||
'--color-btn-min': '#85c43b',
|
||||
'--color-btn-close': '#fab4a0',
|
||||
|
||||
'--color-badge-primary': 'var(--color-primary-dark-200)',
|
||||
'--color-badge-secondary': 'var(--color-primary)',
|
||||
'--color-badge-tertiary': 'var(--color-primary-dark-300)',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'mid_autumn',
|
||||
name: '月里嫦娥',
|
||||
isDark: false,
|
||||
isDarkFont: false,
|
||||
config: {
|
||||
primary: 'rgb(74, 55, 82)',
|
||||
font: 'rgb(33, 33, 33)',
|
||||
'--color-app-background': 'rgba(255, 255, 255, 0)',
|
||||
'--color-main-background': 'rgba(255, 255, 255, 0.9)',
|
||||
'--color-nav-font': 'var(--color-primary-light-600)',
|
||||
'--background-image': 'url(./theme_images/jqbg.jpg)',
|
||||
'--background-image-position': 'center',
|
||||
'--background-image-size': 'cover',
|
||||
|
||||
|
||||
'--color-btn-hide': '#3bc2b2',
|
||||
'--color-btn-min': '#85c43b',
|
||||
'--color-btn-close': '#fab4a0',
|
||||
|
||||
'--color-badge-primary': 'var(--color-primary)',
|
||||
'--color-badge-secondary': '#af9479',
|
||||
'--color-badge-tertiary': '#af9479',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'naruto',
|
||||
name: '木叶之村',
|
||||
isDark: false,
|
||||
isDarkFont: false,
|
||||
config: {
|
||||
primary: 'rgb(87, 144, 167)',
|
||||
font: 'rgb(33, 33, 33)',
|
||||
'--color-app-background': 'rgba(255, 255, 255, 0.15)',
|
||||
'--color-main-background': 'rgba(255, 255, 255, 0.8)',
|
||||
'--color-nav-font': 'var(--color-primary)',
|
||||
'--background-image': 'url(./theme_images/myzcbg.jpg)',
|
||||
'--background-image-position': 'center',
|
||||
'--background-image-size': 'cover',
|
||||
|
||||
'--color-btn-hide': '#3bc2b2',
|
||||
'--color-btn-min': '#85c43b',
|
||||
'--color-btn-close': '#fab4a0',
|
||||
|
||||
'--color-badge-primary': 'var(--color-primary)',
|
||||
'--color-badge-secondary': 'var(--color-primary-light-100)',
|
||||
'--color-badge-tertiary': 'var(--color-primary-light-100)',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'china_ink',
|
||||
name: '近墨者黑',
|
||||
isDark: false,
|
||||
isDarkFont: false,
|
||||
config: {
|
||||
primary: 'rgba(47, 47, 47, 1)',
|
||||
font: 'rgb(33, 33, 33)',
|
||||
'--color-app-background': 'rgba(255, 255, 255, 0)',
|
||||
'--color-main-background': 'rgba(255, 255, 255, 0.8)',
|
||||
'--color-nav-font': 'var(--color-primary)',
|
||||
'--background-image': 'url(./theme_images/china_ink.jpg)',
|
||||
'--background-image-position': 'center',
|
||||
'--background-image-size': 'cover',
|
||||
|
||||
|
||||
'--color-btn-hide': 'rgba(183, 212, 208, 1)',
|
||||
'--color-btn-min': 'rgba(200, 214, 183, 1)',
|
||||
'--color-btn-close': 'rgba(218, 195, 188, 1)',
|
||||
|
||||
'--color-badge-primary': 'rgba(137, 70, 70, 1)',
|
||||
'--color-badge-secondary': 'rgba(67, 139, 65, 1)',
|
||||
'--color-badge-tertiary': 'rgba(132, 135, 65, 1)',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'happy_new_year',
|
||||
name: '新年快乐',
|
||||
isDark: false,
|
||||
isDarkFont: false,
|
||||
config: {
|
||||
primary: 'rgb(192, 57, 43)',
|
||||
font: 'rgb(33, 33, 33)',
|
||||
'--color-app-background': 'rgba(255, 255, 255, 0.15)',
|
||||
'--color-main-background': 'rgba(255, 255, 255, 0.8)',
|
||||
'--color-nav-font': 'var(--color-primary)',
|
||||
'--background-image': 'url(./theme_images/xnkl.png)',
|
||||
'--background-image-position': 'center',
|
||||
'--background-image-size': 'cover',
|
||||
|
||||
'--color-btn-hide': '#3bc2b2',
|
||||
'--color-btn-min': '#85c43b',
|
||||
'--color-btn-close': '#fab4a0',
|
||||
|
||||
'--color-badge-primary': '#7fb575',
|
||||
'--color-badge-secondary': '#dfbb6b',
|
||||
'--color-badge-tertiary': 'var(--color-primary-light-100)',
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
const themes = defaultThemes.map(({ config: { primary, font, ...extInfo }, ...themeInfo }) => {
|
||||
return {
|
||||
...themeInfo,
|
||||
isCustom: false,
|
||||
config: {
|
||||
themeColors: createThemeColors(primary, font, themeInfo.isDark),
|
||||
extInfo,
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
fs.writeFileSync(path.join(__dirname, 'index.json'), JSON.stringify(themes, null, 2))
|
||||
|
||||
BIN
src/common/theme/images/china_ink.jpg
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 353 KiB After Width: | Height: | Size: 353 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 997 KiB After Width: | Height: | Size: 997 KiB |
3857
src/common/theme/index.json
Normal file
75
src/common/theme/utils.js
Normal file
@@ -0,0 +1,75 @@
|
||||
const { RGB_Linear_Shade, RGB_Alpha_Shade } = require('./colorUtils')
|
||||
|
||||
exports.createThemeColors = (rgbaColor, fontRgbaColor, isDark, isDarkFont) => {
|
||||
const colors = {
|
||||
'--color-primary': rgbaColor,
|
||||
}
|
||||
|
||||
let preColor = rgbaColor
|
||||
for (let i = 1; i < 11; i += 1) {
|
||||
preColor = RGB_Linear_Shade(isDark ? 0.2 : -0.1, preColor)
|
||||
colors[`--color-primary-dark-${i * 100}`] = preColor
|
||||
for (let j = 1; j < 10; j += 1) {
|
||||
colors[`--color-primary-dark-${i * 100}-alpha-${j * 100}`] = RGB_Alpha_Shade(0.1 * j, preColor)
|
||||
colors[`--color-primary-alpha-${j * 100}`] = RGB_Alpha_Shade(0.1 * j, rgbaColor)
|
||||
}
|
||||
}
|
||||
preColor = rgbaColor
|
||||
for (let i = 1; i < 10; i += 1) {
|
||||
preColor = RGB_Linear_Shade(isDark ? -0.1 : 0.2, preColor)
|
||||
colors[`--color-primary-light-${i * 100}`] = preColor
|
||||
for (let j = 1; j < 10; j += 1) {
|
||||
colors[`--color-primary-light-${i * 100}-alpha-${j * 100}`] = RGB_Alpha_Shade(0.1 * j, preColor)
|
||||
}
|
||||
}
|
||||
preColor = RGB_Linear_Shade(isDark ? -0.35 : 1, preColor)
|
||||
colors[`--color-primary-light-${1000}`] = preColor
|
||||
for (let j = 1; j < 10; j += 1) {
|
||||
colors[`--color-primary-light-${1000}-alpha-${j * 100}`] = RGB_Alpha_Shade(0.1 * j, preColor)
|
||||
}
|
||||
|
||||
colors['--color-theme'] = isDark ? colors['--color-primary-light-900'] : rgbaColor
|
||||
|
||||
return { ...colors, ...createFontColors(fontRgbaColor, isDark, isDarkFont) }
|
||||
}
|
||||
|
||||
const createFontColors = (rgbaColor, isDark, isDarkFont) => {
|
||||
// rgb(238, 238, 238)
|
||||
// let prec = 'rgb(255, 255, 255)'
|
||||
rgbaColor ??= isDark ? 'rgb(229, 229, 229)' : 'rgb(33, 33, 33)'
|
||||
if (isDark) return createFontDarkColors(rgbaColor, isDarkFont)
|
||||
|
||||
let colors = {
|
||||
'--color-1000': rgbaColor,
|
||||
}
|
||||
let step = (isDarkFont ? 0.02 : 0.05) * (isDark ? -1 : 1)
|
||||
for (let i = 1; i < 21; i += 1) {
|
||||
colors[`--color-${String(1000 - 50 * i).padStart(3, '0')}`] = RGB_Linear_Shade(step * i, rgbaColor)
|
||||
}
|
||||
// console.log(colors)
|
||||
return colors
|
||||
}
|
||||
|
||||
const createFontDarkColors = (rgbaColor, isDarkFont) => {
|
||||
// rgb(238, 238, 238)
|
||||
// let prec = 'rgb(255, 255, 255)'
|
||||
|
||||
let colors = {
|
||||
'--color-1000': rgbaColor,
|
||||
}
|
||||
const step = isDarkFont ? -0.015 : -0.05
|
||||
let preColor = rgbaColor
|
||||
for (let i = 1; i < 21; i += 1) {
|
||||
preColor = RGB_Linear_Shade(step, preColor)
|
||||
colors[`--color-${String(1000 - 50 * i).padStart(3, '0')}`] = preColor
|
||||
}
|
||||
|
||||
// console.log(colors)
|
||||
return colors
|
||||
}
|
||||
|
||||
// console.log(createFontColors('rgb(33, 33, 33)', false))
|
||||
// console.log(createFontColors('rgb(255, 255, 255)', true))
|
||||
|
||||
// console.log(createFontDarkColors('rgb(255, 255, 255)'))
|
||||
|
||||
11
src/common/tsconfig.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"typeRoots": [
|
||||
"./types"
|
||||
],
|
||||
"paths": { /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||
"@common/*": ["common/*"],
|
||||
},
|
||||
},
|
||||
}
|
||||
696
src/common/types/app_setting.d.ts
vendored
Normal file
@@ -0,0 +1,696 @@
|
||||
import type { I18n } from '../../lang/i18n'
|
||||
|
||||
declare global {
|
||||
|
||||
declare namespace LX {
|
||||
type AddMusicLocationType = 'top' | 'bottom'
|
||||
|
||||
interface AppSetting {
|
||||
version: string
|
||||
|
||||
/**
|
||||
* 窗口大小id
|
||||
*/
|
||||
'common.windowSizeId': number
|
||||
|
||||
/**
|
||||
* 窗口大小id
|
||||
*/
|
||||
'common.fontSize': number
|
||||
|
||||
/**
|
||||
* 是否以全屏启动
|
||||
*/
|
||||
'common.startInFullscreen': boolean
|
||||
|
||||
/**
|
||||
* 语言id
|
||||
*/
|
||||
'common.langId': I18n['locale'] | null
|
||||
|
||||
/**
|
||||
* api id
|
||||
*/
|
||||
'common.apiSource': string
|
||||
|
||||
/**
|
||||
* 音源名称类型,原名、别名
|
||||
*/
|
||||
'common.sourceNameType': 'alias' | 'real'
|
||||
|
||||
/**
|
||||
* 显示的字体
|
||||
*/
|
||||
'common.font': string
|
||||
|
||||
/**
|
||||
* 是否启用动画
|
||||
*/
|
||||
'common.isShowAnimation': boolean
|
||||
|
||||
/**
|
||||
* 是否启用随机弹窗动画
|
||||
*/
|
||||
'common.randomAnimate': boolean
|
||||
|
||||
/**
|
||||
* 是否同意软件协议
|
||||
*/
|
||||
'common.isAgreePact': boolean
|
||||
|
||||
/**
|
||||
* 控制按钮位置,左边、右边
|
||||
*/
|
||||
'common.controlBtnPosition': 'left' | 'right'
|
||||
|
||||
/**
|
||||
* 播放栏进度条样式
|
||||
*/
|
||||
'common.playBarProgressStyle': 'mini' | 'full' | 'middle'
|
||||
|
||||
/**
|
||||
* 启用透明窗口
|
||||
*/
|
||||
'common.transparentWindow': boolean
|
||||
|
||||
/**
|
||||
* 尝试自动更新
|
||||
*/
|
||||
'common.tryAutoUpdate': boolean
|
||||
|
||||
/**
|
||||
* 更新版本后是否显示变更日志
|
||||
*/
|
||||
'common.showChangeLog': boolean
|
||||
|
||||
/**
|
||||
* 启动时自动播放歌曲
|
||||
*/
|
||||
'player.startupAutoPlay': boolean
|
||||
|
||||
/**
|
||||
* 切歌模式
|
||||
*/
|
||||
'player.togglePlayMethod': 'listLoop' | 'random' | 'list' | 'singleLoop' | 'none'
|
||||
|
||||
/**
|
||||
* 优先播放的音质
|
||||
*/
|
||||
'player.playQuality': LX.Quality
|
||||
|
||||
/**
|
||||
* 是否显示任务栏进度条
|
||||
*/
|
||||
'player.isShowTaskProgess': boolean
|
||||
|
||||
|
||||
/**
|
||||
* 是否将歌词显示在状态栏
|
||||
*/
|
||||
'player.isShowStatusBarLyric': boolean
|
||||
|
||||
/**
|
||||
* 音量大小
|
||||
*/
|
||||
'player.volume': number
|
||||
|
||||
/**
|
||||
* 播放歌曲时是否阻止电脑休眠
|
||||
*/
|
||||
'player.powerSaveBlocker': boolean
|
||||
|
||||
/**
|
||||
* 是否静音
|
||||
*/
|
||||
'player.isMute': boolean
|
||||
|
||||
/**
|
||||
* 播放速率
|
||||
*/
|
||||
'player.playbackRate': number
|
||||
|
||||
/**
|
||||
* 是否自动调整音频的音高以补偿对播放速率设置所做的更改
|
||||
*/
|
||||
'player.preservesPitch': boolean
|
||||
|
||||
/**
|
||||
* 使用设备能处理的最大声道数输出音频
|
||||
*/
|
||||
'player.isMaxOutputChannelCount': boolean
|
||||
|
||||
/**
|
||||
* 音频输出设备id
|
||||
*/
|
||||
'player.mediaDeviceId': string
|
||||
|
||||
/**
|
||||
* 是否在音频输出设备更改时暂停播放
|
||||
*/
|
||||
'player.isMediaDeviceRemovedStopPlay': boolean
|
||||
|
||||
/**
|
||||
* 是否显示歌词翻译
|
||||
*/
|
||||
'player.isShowLyricTranslation': boolean
|
||||
|
||||
/**
|
||||
* 是否显示歌词罗马音
|
||||
*/
|
||||
'player.isShowLyricRoma': boolean
|
||||
|
||||
/**
|
||||
* 是否调换翻译歌词与罗马音歌词位置
|
||||
*/
|
||||
'player.isSwapLyricTranslationAndRoma': boolean
|
||||
|
||||
/**
|
||||
* 是否将歌词从简体转换为繁体
|
||||
*/
|
||||
'player.isS2t': boolean
|
||||
|
||||
/**
|
||||
* 是否播放卡拉OK歌词
|
||||
*/
|
||||
'player.isPlayLxlrc': boolean
|
||||
|
||||
/**
|
||||
* 启动软件时是否恢复上次播放进度
|
||||
*/
|
||||
'player.isSavePlayTime': boolean
|
||||
|
||||
/**
|
||||
* 是否启用音频可视化
|
||||
*/
|
||||
'player.audioVisualization': boolean
|
||||
|
||||
/**
|
||||
* 定时暂停播放-是否等待歌曲播放完毕再暂停
|
||||
*/
|
||||
'player.waitPlayEndStop': boolean
|
||||
|
||||
/**
|
||||
* 定时暂停播放-倒计时时间
|
||||
*/
|
||||
'player.waitPlayEndStopTime': string
|
||||
|
||||
/**
|
||||
* 环境音效文件名
|
||||
*/
|
||||
'player.soundEffect.convolution.fileName': string | null
|
||||
|
||||
/**
|
||||
* 环境音效原始输出增益
|
||||
*/
|
||||
'player.soundEffect.convolution.mainGain': number
|
||||
|
||||
/**
|
||||
* 环境音效输出增益
|
||||
*/
|
||||
'player.soundEffect.convolution.sendGain': number
|
||||
|
||||
/**
|
||||
* 均衡器 31hz 值
|
||||
*/
|
||||
'player.soundEffect.biquadFilter.hz31': number
|
||||
|
||||
/**
|
||||
* 均衡器 62hz 值
|
||||
*/
|
||||
'player.soundEffect.biquadFilter.hz62': number
|
||||
|
||||
/**
|
||||
* 均衡器 125hz 值
|
||||
*/
|
||||
'player.soundEffect.biquadFilter.hz125': number
|
||||
|
||||
/**
|
||||
* 均衡器 250hz 值
|
||||
*/
|
||||
'player.soundEffect.biquadFilter.hz250': number
|
||||
|
||||
/**
|
||||
* 均衡器 500hz 值
|
||||
*/
|
||||
'player.soundEffect.biquadFilter.hz500': number
|
||||
|
||||
/**
|
||||
* 均衡器 1000hz 值
|
||||
*/
|
||||
'player.soundEffect.biquadFilter.hz1000': number
|
||||
|
||||
/**
|
||||
* 均衡器 2000hz 值
|
||||
*/
|
||||
'player.soundEffect.biquadFilter.hz2000': number
|
||||
|
||||
/**
|
||||
* 均衡器 4000hz 值
|
||||
*/
|
||||
'player.soundEffect.biquadFilter.hz4000': number
|
||||
|
||||
/**
|
||||
* 均衡器 8000hz 值
|
||||
*/
|
||||
'player.soundEffect.biquadFilter.hz8000': number
|
||||
|
||||
/**
|
||||
* 均衡器 16000hz 值
|
||||
*/
|
||||
'player.soundEffect.biquadFilter.hz16000': number
|
||||
|
||||
/**
|
||||
* 3D立体环绕是否启用
|
||||
*/
|
||||
'player.soundEffect.panner.enable': boolean
|
||||
|
||||
/**
|
||||
* 3D立体环绕声音距离
|
||||
*/
|
||||
'player.soundEffect.panner.soundR': number
|
||||
|
||||
/**
|
||||
* 3D立体环绕速度
|
||||
*/
|
||||
'player.soundEffect.panner.speed': number
|
||||
|
||||
/**
|
||||
* 升降声调
|
||||
*/
|
||||
'player.soundEffect.pitchShifter.playbackRate': number
|
||||
|
||||
/**
|
||||
* 是否启用音频加载失败时自动切歌
|
||||
*/
|
||||
'player.autoSkipOnError': boolean
|
||||
|
||||
/**
|
||||
* 点击相同列表内的歌曲切歌时是否清空已播放列表(随机模式下列表内所有歌曲会重新参与随机)
|
||||
*/
|
||||
'player.isAutoCleanPlayedList': boolean
|
||||
|
||||
/**
|
||||
* 播放详情页-是否缩放当前播放的歌词行
|
||||
*/
|
||||
'playDetail.isZoomActiveLrc': boolean
|
||||
|
||||
/**
|
||||
* 播放详情页-是否允许通过歌词调整播放进度
|
||||
*/
|
||||
'playDetail.isShowLyricProgressSetting': boolean
|
||||
|
||||
/**
|
||||
* 播放详情页-歌词字体大小
|
||||
*/
|
||||
'playDetail.style.fontSize': number
|
||||
|
||||
/**
|
||||
* 播放详情页-歌词对齐方式
|
||||
*/
|
||||
'playDetail.style.align': 'center' | 'left' | 'right'
|
||||
|
||||
/**
|
||||
* 播放详情页-是否延迟桌面歌词滚动
|
||||
*/
|
||||
'playDetail.isDelayScroll': boolean
|
||||
|
||||
|
||||
/**
|
||||
* 是否启用桌面歌词
|
||||
*/
|
||||
'desktopLyric.enable': boolean
|
||||
|
||||
/**
|
||||
* 是否锁定桌面歌词
|
||||
*/
|
||||
'desktopLyric.isLock': boolean
|
||||
|
||||
/**
|
||||
* 是在置顶桌面
|
||||
*/
|
||||
'desktopLyric.isAlwaysOnTop': boolean
|
||||
|
||||
/**
|
||||
* 是否自动刷新歌词置顶
|
||||
*/
|
||||
'desktopLyric.isAlwaysOnTopLoop': boolean
|
||||
|
||||
/**
|
||||
* 是否将歌词进程显示在任务栏
|
||||
*/
|
||||
'desktopLyric.isShowTaskbar': boolean
|
||||
|
||||
/**
|
||||
* 是否启用音频可视化
|
||||
*/
|
||||
'desktopLyric.audioVisualization': boolean
|
||||
|
||||
/**
|
||||
* 是否在全屏时隐藏歌词
|
||||
*/
|
||||
'desktopLyric.fullscreenHide': boolean
|
||||
|
||||
/**
|
||||
* 是否在暂停时隐藏歌词
|
||||
*/
|
||||
'desktopLyric.pauseHide': boolean
|
||||
|
||||
/**
|
||||
* 桌面歌词窗口宽度
|
||||
*/
|
||||
'desktopLyric.width': number
|
||||
|
||||
/**
|
||||
* 桌面歌词窗口高度
|
||||
*/
|
||||
'desktopLyric.height': number
|
||||
|
||||
/**
|
||||
* 桌面歌词窗口x坐标
|
||||
*/
|
||||
'desktopLyric.x': number | null
|
||||
|
||||
/**
|
||||
* 桌面歌词窗口y坐标
|
||||
*/
|
||||
'desktopLyric.y': number | null
|
||||
|
||||
/**
|
||||
* 是否允许桌面歌词窗口拖出主屏幕之外
|
||||
*/
|
||||
'desktopLyric.isLockScreen': boolean
|
||||
|
||||
/**
|
||||
* 是否延迟桌面歌词滚动
|
||||
*/
|
||||
'desktopLyric.isDelayScroll': boolean
|
||||
|
||||
/**
|
||||
* 歌词滚动位置
|
||||
*/
|
||||
'desktopLyric.scrollAlign': 'top' | 'center'
|
||||
|
||||
/**
|
||||
* 是否在鼠标划过桌面歌词窗口时降低歌词透明度
|
||||
*/
|
||||
'desktopLyric.isHoverHide': boolean
|
||||
|
||||
/**
|
||||
* 歌词方向
|
||||
*/
|
||||
'desktopLyric.direction': 'horizontal' | 'vertical'
|
||||
|
||||
/**
|
||||
* 歌词对齐方式
|
||||
*/
|
||||
'desktopLyric.style.align': 'center' | 'left' | 'right'
|
||||
|
||||
/**
|
||||
* 桌面歌词字体
|
||||
*/
|
||||
'desktopLyric.style.font': string
|
||||
|
||||
/**
|
||||
* 桌面歌词字体大小
|
||||
*/
|
||||
'desktopLyric.style.fontSize': number
|
||||
|
||||
/**
|
||||
* 歌词间距大小
|
||||
*/
|
||||
'desktopLyric.style.lineGap': number
|
||||
|
||||
/**
|
||||
* 桌面歌词未播放字体颜色
|
||||
*/
|
||||
'desktopLyric.style.lyricUnplayColor': string
|
||||
|
||||
/**
|
||||
* 桌面歌词已播放字体颜色
|
||||
*/
|
||||
'desktopLyric.style.lyricPlayedColor': string
|
||||
|
||||
/**
|
||||
* 桌面歌词字体阴影颜色
|
||||
*/
|
||||
'desktopLyric.style.lyricShadowColor': string
|
||||
|
||||
/**
|
||||
* 桌面歌词加粗字体
|
||||
*/
|
||||
// 'desktopLyric.style.fontWeight': boolean
|
||||
|
||||
/**
|
||||
* 桌面歌词字体透明度
|
||||
*/
|
||||
'desktopLyric.style.opacity': number
|
||||
|
||||
/**
|
||||
* 桌面歌词是否允许换行
|
||||
*/
|
||||
'desktopLyric.style.ellipsis': boolean
|
||||
|
||||
/**
|
||||
* 是否缩放当前正在播放的桌面歌词
|
||||
*/
|
||||
'desktopLyric.style.isZoomActiveLrc': boolean
|
||||
|
||||
/**
|
||||
* 是否加粗逐字歌词字体
|
||||
*/
|
||||
'desktopLyric.style.isFontWeightFont': boolean
|
||||
|
||||
/**
|
||||
* 是否加粗逐行歌词字体
|
||||
*/
|
||||
'desktopLyric.style.isFontWeightLine': boolean
|
||||
|
||||
/**
|
||||
* 是否加粗翻译、罗马音字体
|
||||
*/
|
||||
'desktopLyric.style.isFontWeightExtended': boolean
|
||||
|
||||
/**
|
||||
* 是否启用双击列表里的歌曲时自动切换到当前列表播放(仅对歌单、排行榜有效)
|
||||
*/
|
||||
'list.isClickPlayList': boolean
|
||||
|
||||
/**
|
||||
* 是否显示歌曲来源(仅对我的列表有效)
|
||||
*/
|
||||
'list.isShowSource': boolean
|
||||
|
||||
/**
|
||||
* 是否自动恢复列表滚动位置(仅对我的列表有效)
|
||||
*/
|
||||
'list.isSaveScrollLocation': boolean
|
||||
|
||||
/**
|
||||
* 添加歌曲到我的列表时的方式
|
||||
*/
|
||||
'list.addMusicLocationType': LX.AddMusicLocationType
|
||||
|
||||
/**
|
||||
* 是否显示列表操作按钮列
|
||||
*/
|
||||
'list.actionButtonsVisible': boolean
|
||||
|
||||
/**
|
||||
* 是否启用下载功能
|
||||
*/
|
||||
'download.enable': boolean
|
||||
|
||||
/**
|
||||
* 按列表名分组保存
|
||||
*/
|
||||
'download.isSavePathGroupByListName': boolean
|
||||
|
||||
/**
|
||||
* 下载路径
|
||||
*/
|
||||
'download.savePath': string
|
||||
|
||||
/**
|
||||
* 文件命名方式
|
||||
*/
|
||||
'download.fileName': '歌名 - 歌手' | '歌手 - 歌名' | '歌名'
|
||||
|
||||
/**
|
||||
* 最大并发下载数
|
||||
*/
|
||||
'download.maxDownloadNum': number
|
||||
|
||||
/**
|
||||
* 存在同名文件时跳过下载
|
||||
*/
|
||||
'download.skipExistFile': boolean
|
||||
|
||||
/**
|
||||
* 是否下载lrc文件
|
||||
*/
|
||||
'download.isDownloadLrc': boolean
|
||||
|
||||
/**
|
||||
* 是否在下载 lx 歌词
|
||||
*/
|
||||
'download.isDownloadLxLrc': boolean
|
||||
|
||||
/**
|
||||
* 是否下载翻译歌词文件
|
||||
*/
|
||||
'download.isDownloadTLrc': boolean
|
||||
|
||||
/**
|
||||
* 是否下载罗马音歌词文件
|
||||
*/
|
||||
'download.isDownloadRLrc': boolean
|
||||
|
||||
/**
|
||||
* 保存lrc时的文本编码格式
|
||||
*/
|
||||
'download.lrcFormat': 'utf8' | 'gbk'
|
||||
|
||||
/**
|
||||
* 是否在音频文件中嵌入歌曲封面
|
||||
*/
|
||||
'download.isEmbedPic': boolean
|
||||
|
||||
/**
|
||||
* 是否在音频文件中嵌入 lx 歌词
|
||||
*/
|
||||
'download.isEmbedLyricLx': boolean
|
||||
|
||||
/**
|
||||
* 是否在音频文件中嵌入歌词
|
||||
*/
|
||||
'download.isEmbedLyric': boolean
|
||||
|
||||
/**
|
||||
* 是否在音频文件中嵌入翻译歌词
|
||||
*/
|
||||
'download.isEmbedLyricT': boolean
|
||||
|
||||
/**
|
||||
* 是否在音频文件中嵌入罗马音歌词
|
||||
*/
|
||||
'download.isEmbedLyricR': boolean
|
||||
|
||||
/**
|
||||
* 歌曲源不可用时,是否启用换源下载
|
||||
*/
|
||||
'download.isUseOtherSource': boolean
|
||||
|
||||
/**
|
||||
* 主题id
|
||||
*/
|
||||
'theme.id': string
|
||||
|
||||
/**
|
||||
* 亮色主题id
|
||||
*/
|
||||
'theme.lightId': string
|
||||
|
||||
/**
|
||||
* 暗色主题id
|
||||
*/
|
||||
'theme.darkId': string
|
||||
|
||||
/**
|
||||
* 是否显示热门搜索
|
||||
*/
|
||||
'search.isShowHotSearch': boolean
|
||||
|
||||
/**
|
||||
* 是否显示搜索历史
|
||||
*/
|
||||
'search.isShowHistorySearch': boolean
|
||||
|
||||
/**
|
||||
* 软件启动时是否自动聚焦搜索框
|
||||
*/
|
||||
'search.isFocusSearchBox': boolean
|
||||
|
||||
/**
|
||||
* 是否启用代理
|
||||
*/
|
||||
'network.proxy.enable': boolean
|
||||
|
||||
/**
|
||||
* 代理服务器地址
|
||||
*/
|
||||
'network.proxy.host': string
|
||||
|
||||
/**
|
||||
* 代理服务器端口号
|
||||
*/
|
||||
'network.proxy.port': string
|
||||
|
||||
/**
|
||||
* 是否启用托盘
|
||||
*/
|
||||
'tray.enable': boolean
|
||||
|
||||
/**
|
||||
* 是否关闭时是否最小化到托盘
|
||||
*/
|
||||
// 'tray.isToTray': boolean
|
||||
|
||||
/**
|
||||
* 托盘主题id
|
||||
*/
|
||||
'tray.themeId': number
|
||||
|
||||
/**
|
||||
* 同步服务模式
|
||||
*/
|
||||
'sync.mode': 'server' | 'client'
|
||||
|
||||
/**
|
||||
* 是否启用同步服务
|
||||
*/
|
||||
'sync.enable': boolean
|
||||
|
||||
/**
|
||||
* 同步服务端口号
|
||||
*/
|
||||
'sync.server.port': '23332' | string
|
||||
|
||||
/**
|
||||
* 最大备份快照数
|
||||
*/
|
||||
'sync.server.maxSsnapshotNum': number
|
||||
|
||||
/**
|
||||
* 同步服务地址
|
||||
*/
|
||||
'sync.client.host': string
|
||||
|
||||
|
||||
/**
|
||||
* 是否启用开放API服务
|
||||
*/
|
||||
'openAPI.enable': boolean
|
||||
|
||||
/**
|
||||
* API服务端口号
|
||||
*/
|
||||
'openAPI.port': '23330' | string
|
||||
|
||||
/**
|
||||
* 是否绑定到局域网
|
||||
*/
|
||||
'openAPI.bindLan': boolean
|
||||
|
||||
/**
|
||||
* 是否在离开搜索界面时自动清空搜索框
|
||||
*/
|
||||
'odc.isAutoClearSearchInput': boolean
|
||||
|
||||
/**
|
||||
* 是否在离开搜索界面时自动清空搜索结果列表
|
||||
*/
|
||||
'odc.isAutoClearSearchList': boolean
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
115
src/common/types/common.d.ts
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
// import './app_setting'
|
||||
|
||||
declare namespace LX {
|
||||
interface CmdParams {
|
||||
/**
|
||||
* 搜索,启动软件时自动在搜索框搜索指定的内容,例如:-search="突然的自我 - 伍佰"
|
||||
*/
|
||||
search?: string
|
||||
|
||||
/**
|
||||
* 禁用硬件加速启动
|
||||
*/
|
||||
dha?: boolean
|
||||
|
||||
/**
|
||||
* 以非透明模式启动
|
||||
*/
|
||||
dt?: boolean
|
||||
|
||||
/**
|
||||
* 禁用硬件媒体密钥处理
|
||||
*/
|
||||
dhmkh?: boolean
|
||||
|
||||
/**
|
||||
* 设置代理服务器,代理应用的所有流量,例:-proxy-server="127.0.0.1:1081"(不支持设置账号密码,v1.17.0起新增)。注:应用内“设置-网络-代理设置”仅代理接口请求的流量,优先级更高
|
||||
*/
|
||||
'proxy-server'?: string
|
||||
|
||||
/**
|
||||
* 以分号分隔的主机列表绕过代理服务器,例:-proxy-bypass-list="<local>;*.google.com;*foo.com;1.2.3.4:5678"(与-proxy-server一起使用才有效,v1.17.0起新增)。注:此设置对应用内接口请求无效
|
||||
*/
|
||||
'proxy-bypass-list'?: string
|
||||
|
||||
/**
|
||||
* 启动时播放指定列表的音乐
|
||||
*/
|
||||
play?: string
|
||||
|
||||
/**
|
||||
* 启动后最小化到系统托盘
|
||||
*/
|
||||
hidden?: boolean
|
||||
|
||||
[key: string]: boolean | number | string
|
||||
}
|
||||
|
||||
type OnlineSource = 'kw' | 'kg' | 'tx' | 'wy' | 'mg'
|
||||
type Source = OnlineSource | 'local'
|
||||
type Quality = '128k' | '320k' | 'flac' | 'flac24bit' | '192k' | 'ape' | 'wav'
|
||||
|
||||
type QualityList = Partial<Record<LX.Source, LX.Quality[]>>
|
||||
|
||||
interface EnvParams {
|
||||
deeplink?: string | null
|
||||
cmdParams: CmdParams
|
||||
workAreaSize?: Electron.Size
|
||||
}
|
||||
|
||||
interface HotKey {
|
||||
name: string
|
||||
action: string
|
||||
type: keyof typeof keyName
|
||||
}
|
||||
|
||||
interface HotKeyDownInfo {
|
||||
type: 'local' | 'global'
|
||||
key: string
|
||||
}
|
||||
|
||||
interface HotKeyConfig {
|
||||
enable: boolean
|
||||
keys: Record<string, HotKey>
|
||||
}
|
||||
interface HotKeyConfigAll {
|
||||
local: HotKeyConfig
|
||||
global: HotKeyConfig
|
||||
}
|
||||
interface RegisterKeyInfo {
|
||||
key: string
|
||||
info: HotKey
|
||||
}
|
||||
type HotKeyState = Map<string, {
|
||||
status: boolean
|
||||
info: HotKey
|
||||
}>
|
||||
interface HotKeyActionWrap<T, D> {
|
||||
action: T
|
||||
data: D
|
||||
source?: string
|
||||
}
|
||||
type HotKeyActions = HotKeyActionWrap<'config', HotKeyConfigAll>
|
||||
| HotKeyActionWrap<'enable', boolean>
|
||||
| HotKeyActionWrap<'register', RegisterKeyInfo>
|
||||
| HotKeyActionWrap<'unregister', string>
|
||||
|
||||
interface HotKeyEvent {
|
||||
type: string
|
||||
key: string
|
||||
}
|
||||
|
||||
interface TaskBarButtonFlags {
|
||||
empty: boolean
|
||||
collect: boolean
|
||||
play: boolean
|
||||
next: boolean
|
||||
prev: boolean
|
||||
}
|
||||
|
||||
type UpdateStatus = 'downloaded' | 'downloading' | 'error' | 'checking' | 'idle'
|
||||
interface VersionInfo {
|
||||
version: string
|
||||
desc: string
|
||||
}
|
||||
}
|
||||
9
src/common/types/config_files.d.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
declare namespace LX {
|
||||
namespace ConfigFile {
|
||||
interface MyListInfoPart {
|
||||
type: 'playListPart_v2'
|
||||
data: LX.List.MyDefaultListInfoFull | LX.List.MyLoveListInfoFull | LX.List.UserListInfoFull
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
92
src/common/types/desktop_lyric.d.ts
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
declare namespace LX {
|
||||
namespace DesktopLyric {
|
||||
interface Config {
|
||||
'desktopLyric.enable': LX.AppSetting['desktopLyric.enable']
|
||||
'desktopLyric.isLock': LX.AppSetting['desktopLyric.isLock']
|
||||
'desktopLyric.isAlwaysOnTop': LX.AppSetting['desktopLyric.isAlwaysOnTop']
|
||||
'desktopLyric.isAlwaysOnTopLoop': LX.AppSetting['desktopLyric.isAlwaysOnTopLoop']
|
||||
'desktopLyric.isShowTaskbar': LX.AppSetting['desktopLyric.isShowTaskbar']
|
||||
'desktopLyric.pauseHide': LX.AppSetting['desktopLyric.pauseHide']
|
||||
'desktopLyric.audioVisualization': LX.AppSetting['desktopLyric.audioVisualization']
|
||||
'desktopLyric.width': LX.AppSetting['desktopLyric.width']
|
||||
'desktopLyric.height': LX.AppSetting['desktopLyric.height']
|
||||
'desktopLyric.x': LX.AppSetting['desktopLyric.x']
|
||||
'desktopLyric.y': LX.AppSetting['desktopLyric.y']
|
||||
'desktopLyric.isLockScreen': LX.AppSetting['desktopLyric.isLockScreen']
|
||||
'desktopLyric.isDelayScroll': LX.AppSetting['desktopLyric.isDelayScroll']
|
||||
'desktopLyric.scrollAlign': LX.AppSetting['desktopLyric.scrollAlign']
|
||||
'desktopLyric.isHoverHide': LX.AppSetting['desktopLyric.isHoverHide']
|
||||
'desktopLyric.direction': LX.AppSetting['desktopLyric.direction']
|
||||
'desktopLyric.style.align': LX.AppSetting['desktopLyric.style.align']
|
||||
'desktopLyric.style.font': LX.AppSetting['desktopLyric.style.font']
|
||||
'desktopLyric.style.fontSize': LX.AppSetting['desktopLyric.style.fontSize']
|
||||
'desktopLyric.style.lineGap': LX.AppSetting['desktopLyric.style.lineGap']
|
||||
'desktopLyric.style.lyricUnplayColor': LX.AppSetting['desktopLyric.style.lyricUnplayColor']
|
||||
'desktopLyric.style.lyricPlayedColor': LX.AppSetting['desktopLyric.style.lyricPlayedColor']
|
||||
'desktopLyric.style.lyricShadowColor': LX.AppSetting['desktopLyric.style.lyricShadowColor']
|
||||
// 'desktopLyric.style.fontWeight': LX.AppSetting['desktopLyric.style.fontWeight']
|
||||
'desktopLyric.style.opacity': LX.AppSetting['desktopLyric.style.opacity']
|
||||
'desktopLyric.style.ellipsis': LX.AppSetting['desktopLyric.style.ellipsis']
|
||||
'desktopLyric.style.isFontWeightFont': LX.AppSetting['desktopLyric.style.isFontWeightFont']
|
||||
'desktopLyric.style.isFontWeightLine': LX.AppSetting['desktopLyric.style.isFontWeightLine']
|
||||
'desktopLyric.style.isFontWeightExtended': LX.AppSetting['desktopLyric.style.isFontWeightExtended']
|
||||
'desktopLyric.style.isZoomActiveLrc': LX.AppSetting['desktopLyric.style.isZoomActiveLrc']
|
||||
'common.langId': LX.AppSetting['common.langId']
|
||||
'player.isShowLyricTranslation': LX.AppSetting['player.isShowLyricTranslation']
|
||||
'player.isShowLyricRoma': LX.AppSetting['player.isShowLyricRoma']
|
||||
'player.isSwapLyricTranslationAndRoma': LX.AppSetting['player.isSwapLyricTranslationAndRoma']
|
||||
'player.isPlayLxlrc': LX.AppSetting['player.isPlayLxlrc']
|
||||
'player.playbackRate': LX.AppSetting['player.playbackRate']
|
||||
}
|
||||
|
||||
type WinMainActions = 'get_info' | 'get_status' | 'get_analyser_data_array'
|
||||
|
||||
interface LyricActionBase <A> {
|
||||
action: A
|
||||
}
|
||||
interface LyricActionData<A, D> extends LyricActionBase<A> {
|
||||
data: D
|
||||
}
|
||||
type LyricAction<A, D = undefined> = D extends undefined ? LyricActionBase<A> : LyricActionData<A, D>
|
||||
|
||||
type LyricActions = LyricAction<'set_info', {
|
||||
id: string | null
|
||||
singer: string
|
||||
name: string
|
||||
album: string
|
||||
lrc: string | null
|
||||
tlrc: string | null
|
||||
rlrc: string | null
|
||||
lxlrc: string | null
|
||||
// pic: string | null
|
||||
isPlay: boolean
|
||||
line: number
|
||||
played_time: number
|
||||
}>
|
||||
| LyricAction<'set_status', {
|
||||
isPlay: boolean
|
||||
line: number
|
||||
played_time: number
|
||||
}>
|
||||
| LyricAction<'set_lyric', {
|
||||
lrc: string | null
|
||||
tlrc: string | null
|
||||
rlrc: string | null
|
||||
lxlrc: string | null
|
||||
}>
|
||||
| LyricAction<'set_offset', number>
|
||||
| LyricAction<'set_playbackRate', number>
|
||||
| LyricAction<'set_play', number>
|
||||
| LyricAction<'set_pause'>
|
||||
| LyricAction<'set_stop'>
|
||||
| LyricAction<'send_analyser_data_array', Uint8Array>
|
||||
|
||||
|
||||
interface NewBounds {
|
||||
x: number
|
||||
y: number
|
||||
w: number
|
||||
h: number
|
||||
}
|
||||
}
|
||||
}
|
||||