Compare commits
835 commits
main
...
immediate-
Author | SHA1 | Date | |
---|---|---|---|
|
7e30481969 | ||
|
67264cc73f | ||
|
d23a33ebb1 | ||
|
4540251601 | ||
|
7534cc570f | ||
|
3a314bf94c | ||
|
8e453e5fec | ||
|
b37b0d54b4 | ||
|
1defaaceb1 | ||
|
dabe8b9e7f | ||
|
9239afdab9 | ||
|
87e66354df | ||
|
2ec5a92801 | ||
|
4760f137a3 | ||
|
b952830b0f | ||
|
ced26f2dd6 | ||
|
10e854513b | ||
|
2595bc6716 | ||
|
f61b5ae058 | ||
|
517f751850 | ||
|
a9db3e477d | ||
|
5ba21bdf36 | ||
|
cf1b7e2025 | ||
|
bece919c41 | ||
|
6c1a220c88 | ||
|
e3c29c335f | ||
|
adf9eee45a | ||
|
d5c77c8591 | ||
|
08400692b6 | ||
|
4dd26270ae | ||
|
2ee098988f | ||
|
3778a401e6 | ||
|
3335ec1ac5 | ||
|
ba593581b7 | ||
|
53cd82c7f2 | ||
|
72ff429d5a | ||
|
10188ead07 | ||
|
bbf924d16b | ||
|
c2b211e1a0 | ||
|
29f56b1a27 | ||
|
efcd4cab77 | ||
|
f7dfc18157 | ||
|
00c9aa96aa | ||
|
19c87b6a7a | ||
|
ddeca192b7 | ||
|
07a9279682 | ||
|
a0a1aaf0ed | ||
|
356586d68f | ||
|
adf7bd0dcc | ||
|
a6971289ad | ||
|
0953ba89ed | ||
|
272209069a | ||
|
f9ef683191 | ||
|
b1f3925361 | ||
|
5dbe81e459 | ||
|
a493d56487 | ||
|
4722851172 | ||
|
67175b5b55 | ||
|
15b7982228 | ||
|
126f2df811 | ||
|
7eeaa32473 | ||
|
dc7b3dbd1e | ||
|
a6976a868b | ||
|
8dc2133ddd | ||
|
bebb98d1c7 | ||
|
bae9f8cbe6 | ||
|
3e00d52fc7 | ||
|
96054261df | ||
|
926ae50a8f | ||
|
1758eab93b | ||
|
d56328cae3 | ||
|
8b2e8d19ba | ||
|
af1bbe81c4 | ||
|
3338b38aaa | ||
|
b7f20044df | ||
|
845bfef84c | ||
|
d922f38719 | ||
|
db1a1b67c8 | ||
|
b5a271e54d | ||
|
e810944963 | ||
|
294f73fc8b | ||
|
68d3aa9af4 | ||
|
4320e60a5a | ||
|
0a09ee1dc6 | ||
|
4ae693b2fb | ||
|
20b7a81bdb | ||
|
7238d969e9 | ||
|
0f277bcfa5 | ||
|
687c3f8f3d | ||
|
42238c7aa4 | ||
|
96b8c4d4a5 | ||
|
7fcd9c3f06 | ||
|
8bfacc139a | ||
|
a9a8c338a6 | ||
|
262319a97c | ||
|
0379beb0ba | ||
|
13ada86934 | ||
|
fae5f9bfab | ||
|
7d4fc5e8e1 | ||
|
26a71caced | ||
|
b1ad0a0d58 | ||
|
4a9f258e34 | ||
|
301b0e7dfc | ||
|
2f806dde95 | ||
|
30ef53403b | ||
|
ade9a523ac | ||
|
464dddff13 | ||
|
e8965866e6 | ||
|
e3d9b2001f | ||
|
e4bc7f2add | ||
|
edc87ac75e | ||
|
5c7773c7bb | ||
|
3546632bbf | ||
|
9a48454a9f | ||
|
0e2c0b9bfb | ||
|
84c78a4262 | ||
|
cfbe4affc0 | ||
|
e8f017b15e | ||
|
22a81ab142 | ||
|
93d450a600 | ||
|
50bb6d867b | ||
|
6cc2f53501 | ||
|
f9776ce1ae | ||
|
18c5ca216c | ||
|
3f0d915c75 | ||
|
a8f77a12df | ||
|
44785d3498 | ||
|
473109b1d9 | ||
|
f398a1c871 | ||
|
9871e16e28 | ||
|
b22d4622ed | ||
|
f05d462a73 | ||
|
c183018fb1 | ||
|
f9c11a1149 | ||
|
45a876a0d5 | ||
|
4d88a13f5e | ||
|
eeb4d26812 | ||
|
2429c283aa | ||
|
1f1e3e8456 | ||
|
64e1f294e6 | ||
|
e801c71fdf | ||
|
4677ac779a | ||
|
ed32b7964d | ||
|
76f8b0e38e | ||
|
e24bdc2b6f | ||
|
4bcefb744d | ||
|
4d03a695aa | ||
|
ca3768ca5d | ||
|
6bdd0ba4a9 | ||
|
633a84581d | ||
|
4a590d3d0a | ||
|
1905aa0ae8 | ||
|
026e716710 | ||
|
9e6f24cc92 | ||
|
75a8098590 | ||
|
1f20074d4e | ||
|
fb394c6e1a | ||
|
465dd15e2c | ||
|
f676613173 | ||
|
be6209ee44 | ||
|
15a3694533 | ||
|
9fd16825e2 | ||
|
129b770ffa | ||
|
42353373db | ||
|
5f7c44f478 | ||
|
2df13a2e17 | ||
|
dc116fc3b1 | ||
|
cd3534f6fc | ||
|
01bd41413d | ||
|
654a271eae | ||
|
efd48e0364 | ||
|
09447d562e | ||
|
e57c99399d | ||
|
a3612dd4ee | ||
|
e9328cadea | ||
|
8fa19656ae | ||
|
d58d8aea71 | ||
|
5462bb1438 | ||
|
9dadde6884 | ||
|
81a1822e70 | ||
|
974953ba01 | ||
|
27fd143318 | ||
|
3bc71c688a | ||
|
d869b2ddbb | ||
|
fb3ae98419 | ||
|
70df451e64 | ||
|
2fb616ebf1 | ||
|
bd25e0cd75 | ||
|
62d4add6c1 | ||
|
3f5491d379 | ||
|
e35d0f680f | ||
|
187ece1905 | ||
|
2b99f4ece3 | ||
|
8bf98be472 | ||
|
0506505449 | ||
|
3edc36d5e0 | ||
|
6ffa969955 | ||
|
6213fca9ed | ||
|
56477d4e96 | ||
|
104f193a76 | ||
|
293b90a6d2 | ||
|
8159937827 | ||
|
aa35602827 | ||
|
42c4845261 | ||
|
710f627016 | ||
|
4389b78410 | ||
|
fde823fabf | ||
|
cce8f14d72 | ||
|
c8356570a3 | ||
|
021baa54d3 | ||
|
ddd5d9e0c3 | ||
|
920fb20d8e | ||
|
438b3e0598 | ||
|
763b24aa92 | ||
|
65013f0149 | ||
|
24795ba9f8 | ||
|
aa29e479b9 | ||
|
dd25044afd | ||
|
8c1979481e | ||
|
2a1684d902 | ||
|
b377cad1e6 | ||
|
4e09e347e2 | ||
|
ea6fccb54e | ||
|
c784bc5dbd | ||
|
edba931afe | ||
|
208882e8ec | ||
|
e0cb7242d6 | ||
|
b3ab32180c | ||
|
2506ba1b2e | ||
|
0d0c63f596 | ||
|
8abb68c553 | ||
|
f6147c6c13 | ||
|
b5fdb43cbf | ||
|
30057985c4 | ||
|
a95037d80a | ||
|
99e21ad284 | ||
|
d90bcdb063 | ||
|
771d51bcc3 | ||
|
c7e49672f5 | ||
|
3331ed2155 | ||
|
bc34d72b57 | ||
|
b333deb731 | ||
|
614cbc1146 | ||
|
a985286c88 | ||
|
1297408171 | ||
|
cc536bdbf4 | ||
|
ea859f59b0 | ||
|
a04ccd0d11 | ||
|
c1b4eb5b04 | ||
|
3f059e17be | ||
|
48442aee1d | ||
|
9ca13d1250 | ||
|
2c3be4533e | ||
|
7bf2152353 | ||
|
a6f4622837 | ||
|
2f55c7b126 | ||
|
14d1a2d1ea | ||
|
332f3e532b | ||
|
28a7fbb309 | ||
|
4caf86b60e | ||
|
5a85d6e78e | ||
|
20cfa932a4 | ||
|
9e998db456 | ||
|
3d4a7638a4 | ||
|
ab8da19e23 | ||
|
b8335108e4 | ||
|
403276d307 | ||
|
748a456cfb | ||
|
0cd0c813f2 | ||
|
f647ff0ee9 | ||
|
c2d708a621 | ||
|
35343bd790 | ||
|
cc5d4a7b3a | ||
|
ae655111de | ||
|
b768c61ef8 | ||
|
d95367b31d | ||
|
1e4ad4db4c | ||
|
d8ba959d1e | ||
|
0742cecd41 | ||
|
ed4a797ad3 | ||
|
505246954b | ||
|
eecc21db91 | ||
|
962eaa9df7 | ||
|
0190ada1a1 | ||
|
b5a1b3a124 | ||
|
1f3b8cdfd8 | ||
|
1f2c26cdba | ||
|
3b6bef1cda | ||
|
858b0e3dd7 | ||
|
718ebd56ac | ||
|
1511260666 | ||
|
4ff7c22505 | ||
|
057ccfde11 | ||
|
edf4e75ae2 | ||
|
62d9d1310d | ||
|
e592a50d7c | ||
|
c785053b86 | ||
|
e9081d2a52 | ||
|
98c67e1165 | ||
|
6c7d4259e1 | ||
|
d8e3381fb3 | ||
|
bdb9c75c74 | ||
|
a67b7847b1 | ||
|
bab081d4a9 | ||
|
0e5099416c | ||
|
20efa661b0 | ||
|
94ba593be9 | ||
|
c9295d3a85 | ||
|
d55770797a | ||
|
b4b67a98da | ||
|
453c0b62f4 | ||
|
a3fa74735f | ||
|
a3cab94a68 | ||
|
c4e7233604 | ||
|
889eb311f9 | ||
|
03120d5a98 | ||
|
9446efadd5 | ||
|
9c21c23364 | ||
|
ba6d3c7e60 | ||
|
cb1fff8d86 | ||
|
c400db41c3 | ||
|
de4743828a | ||
|
700a442ee4 | ||
|
dd3904badd | ||
|
0d360fb7e7 | ||
|
2429231965 | ||
|
570137040c | ||
|
ad3bb91bc1 | ||
|
161be30b2b | ||
|
0a4bcd5ccd | ||
|
3a5859b815 | ||
|
1ea5f56549 | ||
|
a7b02f2f1f | ||
|
32306cc6c3 | ||
|
8cfb289dc7 | ||
|
220062acdb | ||
|
e5d5bc2d34 | ||
|
17cc81f15d | ||
|
eba42489e9 | ||
|
51dee70ced | ||
|
11561e50f9 | ||
|
2095cc8d03 | ||
|
6e61ef297c | ||
|
58e810dfbe | ||
|
b2497373f0 | ||
|
18841f4551 | ||
|
da6ceb8479 | ||
|
6b811dce55 | ||
|
8982a53b47 | ||
|
3cf702a2ba | ||
|
cd79150a84 | ||
|
343e2802c3 | ||
|
dc8b579488 | ||
|
066001c57a | ||
|
24a0f62801 | ||
|
ef512e6ea1 | ||
|
c6b2eeb86d | ||
|
e457e58b49 | ||
|
cac0398276 | ||
|
e93562b95b | ||
|
f6dbcb7709 | ||
|
a82a0636cf | ||
|
2fc814124f | ||
|
a43d5d595a | ||
|
ceaaf9ab8a | ||
|
a01ee40591 | ||
|
26c2674652 | ||
|
9595f75a9a | ||
|
2189ce407b | ||
|
7b4f97fa08 | ||
|
f208472841 | ||
|
4e4a9f806f | ||
|
afe6d9f7b3 | ||
|
2dac66d7c6 | ||
|
83b09a8073 | ||
|
13d47d91bf | ||
|
004f764c2b | ||
|
a815122e3c | ||
|
b88e7faa72 | ||
|
bb22355a57 | ||
|
591f433135 | ||
|
f726376ab8 | ||
|
74bd89b721 | ||
|
aa4c6e5496 | ||
|
e8d696c18c | ||
|
d473d52047 | ||
|
36c8058920 | ||
|
8d31f3cf62 | ||
|
5021d2e344 | ||
|
92653eaf96 | ||
|
2f6e39c0bd | ||
|
5e52ecf42e | ||
|
b2ae33344b | ||
|
b24e8cb9e6 | ||
|
73b1c7b811 | ||
|
210fada19a | ||
|
002a1cfc16 | ||
|
e9e25306eb | ||
|
5931a72de2 | ||
|
3d0ce5449d | ||
|
31c39bc761 | ||
|
1d2b8a43c0 | ||
|
6d587e6530 | ||
|
853585c0bc | ||
|
6826fe003c | ||
|
c3bbc92fa2 | ||
|
ed35c496dc | ||
|
dc8ac98a6e | ||
|
337850c33a | ||
|
08f1b6a3c9 | ||
|
c8ad68c80b | ||
|
7b056364da | ||
|
7f3cad2528 | ||
|
5d290ecd35 | ||
|
b702b31744 | ||
|
3dbe621059 | ||
|
55195676b8 | ||
|
76cb49c381 | ||
|
95c4cc09af | ||
|
a5b30e762a | ||
|
5bbf467be0 | ||
|
46c771f351 | ||
|
94ea4f8e5c | ||
|
fc8a0e4904 | ||
|
9eb77cb7fd | ||
|
e1bbd67a9a | ||
|
625b248a95 | ||
|
94c365b1c3 | ||
|
f70e9290ce | ||
|
57b011aea7 | ||
|
c8097f0f1a | ||
|
5999af76c6 | ||
|
05717d6bc3 | ||
|
53dd86fa6e | ||
|
363f2e84fb | ||
|
066ce07512 | ||
|
f5b1b65db8 | ||
|
6e6ee4db68 | ||
|
ac1c417e1c | ||
|
4e14232b5a | ||
|
eddfca06ab | ||
|
61e1eada01 | ||
|
85322f9e90 | ||
|
d329d74fec | ||
|
ac6a21374f | ||
|
b385be51d6 | ||
|
d8524b087c | ||
|
c491122937 | ||
|
13337950dc | ||
|
281ab9194b | ||
|
a1881bff3d | ||
|
c50208b019 | ||
|
a8974f01eb | ||
|
b79a0dadcb | ||
|
c4c92ed366 | ||
|
78fd37a4c6 | ||
|
9de6e67cf1 | ||
|
33d5753ca7 | ||
|
8d3feef9a1 | ||
|
8580332c82 | ||
|
4d8c56689c | ||
|
5cbb816c1c | ||
|
b6594051d9 | ||
|
50415a949d | ||
|
4b03454bce | ||
|
f1b649e996 | ||
|
db5397f41a | ||
|
c34f40e30d | ||
|
dd4d80872e | ||
|
eb381767cd | ||
|
0aff3c29bc | ||
|
e7fdb3881a | ||
|
5977ff8f6b | ||
|
dd13b96728 | ||
|
01fdeb7292 | ||
|
6a3831c437 | ||
|
c485864ee8 | ||
|
2ab7d3209e | ||
|
654b2e8398 | ||
|
3f573c9af3 | ||
|
cbd9a9312c | ||
|
2656b60347 | ||
|
fbb7ee50dd | ||
|
4187932aa7 | ||
|
a19fb71c70 | ||
|
e21a6be4b6 | ||
|
b53c78c2ba | ||
|
db63fffe18 | ||
|
41ab8da5ad | ||
|
f68effc7e2 | ||
|
f21bfb9d78 | ||
|
f4cc95da5a | ||
|
3a32490937 | ||
|
545d69aa6d | ||
|
aa5ca42676 | ||
|
5197170b3d | ||
|
47eec049fc | ||
|
022a0497c3 | ||
|
e2f936538e | ||
|
b323fbb486 | ||
|
0c4e265530 | ||
|
111a4f2aa8 | ||
|
46710bf8cb | ||
|
1f938211a8 | ||
|
8d362fc394 | ||
|
79849fd37d | ||
|
a838d587ae | ||
|
3a25da5f14 | ||
|
a1e72e78d7 | ||
|
48fb6ecd1a | ||
|
3c62e393a3 | ||
|
034ef554fb | ||
|
2da9bf8f0e | ||
|
eb5fb0df29 | ||
|
479a4069b2 | ||
|
e22575805b | ||
|
c0984db612 | ||
|
9a9c1b0487 | ||
|
072619e539 | ||
|
9084459933 | ||
|
36f9eda3a8 | ||
|
99160638df | ||
|
2574d5311d | ||
|
7816727e26 | ||
|
892de53603 | ||
|
8de1ca86a9 | ||
|
01ba87cd76 | ||
|
83222631ab | ||
|
b74581908e | ||
|
896b8970b6 | ||
|
c8602ef52b | ||
|
ac1423f90c | ||
|
d0e4ec0ad5 | ||
|
7509f203cc | ||
|
17b575070f | ||
|
4a872236e1 | ||
|
d5440349c9 | ||
|
0f9b5f2d09 | ||
|
4db6c4b88a | ||
|
6e1094a5d1 | ||
|
15df3485d1 | ||
|
ea86df7174 | ||
|
66c466c9f0 | ||
|
96d5e1b89b | ||
|
4b4caa798a | ||
|
73503945fb | ||
|
43b679d676 | ||
|
011b375d02 | ||
|
9f1f2b15a4 | ||
|
a1309ea897 | ||
|
a4073703fd | ||
|
84b9e3fec1 | ||
|
6bbd91fafc | ||
|
d78f1c8000 | ||
|
64262001e8 | ||
|
6b648f3d38 | ||
|
1eeadbcd97 | ||
|
f016d277b7 | ||
|
9c2545ab16 | ||
|
b36d3b4385 | ||
|
acbc932542 | ||
|
3590d5abff | ||
|
c9c09b95a3 | ||
|
9128eb5760 | ||
|
513d9f4209 | ||
|
06393211b1 | ||
|
ac3130d37e | ||
|
3e2952890f | ||
|
a0751a0f84 | ||
|
fa45beb8ca | ||
|
539b70cd52 | ||
|
e96458fafa | ||
|
a1542bcec5 | ||
|
e00da485e8 | ||
|
513eea8d14 | ||
|
490e9131b5 | ||
|
9ceb0ae7cb | ||
|
6d59a943da | ||
|
00d71fbeab | ||
|
4459d11a97 | ||
|
1eab0146dd | ||
|
f345484e5b | ||
|
65adaf335c | ||
|
437e4eae44 | ||
|
f7d12d209c | ||
|
8a5678bec5 | ||
|
1f99162b5a | ||
|
8c5f2c897e | ||
|
9ada9bc1a9 | ||
|
8fd22f6deb | ||
|
c1e78b4397 | ||
|
32a2c90761 | ||
|
dae3841f10 | ||
|
4d27643d39 | ||
|
c2047e5f3b | ||
|
18142ecccb | ||
|
440cb1f29c | ||
|
64b1ab1112 | ||
|
3da88100df | ||
|
3e3201ad0d | ||
|
a2bda05211 | ||
|
1ed956114f | ||
|
2e27a513ac | ||
|
a8fa685cfa | ||
|
b2036762b5 | ||
|
067a16c9dc | ||
|
265cf12d39 | ||
|
b580d6dcfb | ||
|
affd527bc1 | ||
|
7d928e53aa | ||
|
b10afebc98 | ||
|
1a8a901e0a | ||
|
d936604f35 | ||
|
4dcc265be0 | ||
|
3e6e399544 | ||
|
9af63b362d | ||
|
090a3bc0a8 | ||
|
3331723496 | ||
|
999d6c812f | ||
|
c9c1e0c6c5 | ||
|
1e55ae5327 | ||
|
5b96881177 | ||
|
daa1a35fc3 | ||
|
ef895e787a | ||
|
2f16cdf77b | ||
|
e990795783 | ||
|
8dde496757 | ||
|
35f950c6e3 | ||
|
5fbabb0b70 | ||
|
ff9cc2e9e5 | ||
|
3793acd9bb | ||
|
ebae259f5d | ||
|
3296ee1c4b | ||
|
2f87363b89 | ||
|
bacf021a28 | ||
|
1138e22f58 | ||
|
d6b5bc58ce | ||
|
bd2264c125 | ||
|
86f69e84c1 | ||
|
488f133a90 | ||
|
77d8e70059 | ||
|
f64b228cb9 | ||
|
90f37471e5 | ||
|
b192c89146 | ||
|
ae10d3667c | ||
|
f727d101fc | ||
|
9bbec66ea5 | ||
|
0146789514 | ||
|
b38ab066d9 | ||
|
37514e0720 | ||
|
aa9be97f83 | ||
|
d8c6559967 | ||
|
72b014fe67 | ||
|
8eb4eab2b0 | ||
|
07361ff6fe | ||
|
64212512ca | ||
|
5e762ddd04 | ||
|
74f36a093b | ||
|
c01a8c2f78 | ||
|
90c26432f5 | ||
|
6f25005057 | ||
|
23c8818ed2 | ||
|
16d05c8935 | ||
|
c5541d297d | ||
|
a120b35f4f | ||
|
9740d28530 | ||
|
8e9434cdd5 | ||
|
f5be78d101 | ||
|
bd95cc449f | ||
|
bdd4b0f143 | ||
|
a60c8374ed | ||
|
1013c34840 | ||
|
7b7b87316d | ||
|
6567ff7435 | ||
|
22a75c4589 | ||
|
67b5ecca51 | ||
|
cdbd9ad101 | ||
|
1e96638219 | ||
|
7371abbaec | ||
|
cfb493c593 | ||
|
ac61a0377f | ||
|
bb3f629672 | ||
|
3ab68f9296 | ||
|
01a4ac9c13 | ||
|
66e1db1fdb | ||
|
688449ed62 | ||
|
5ca4e58fad | ||
|
deb0f7b9c6 | ||
|
40a1f48267 | ||
|
bc367b1d2a | ||
|
f6a7cdc430 | ||
|
d5bcbf54f9 | ||
|
4b2734610f | ||
|
c4645f79c6 | ||
|
cf9bbfc78f | ||
|
6cc40eb095 | ||
|
95acb147d1 | ||
|
21fea87551 | ||
|
2a2124c5a0 | ||
|
1a1e5c2e1d | ||
|
c9d9d53fb1 | ||
|
dc81d1c14c | ||
|
b938bdf138 | ||
|
e74aabb988 | ||
|
ab24ce08e3 | ||
|
c2435bb9dd | ||
|
d678e68899 | ||
|
dbb6f4165b | ||
|
9a1a7b374f | ||
|
ec373069b3 | ||
|
329bc68bf5 | ||
|
2a77941dff | ||
|
d36c361b47 | ||
|
b17963169f | ||
|
118361723c | ||
|
97e2e2c1c8 | ||
|
dbee2d9ecc | ||
|
1283494b46 | ||
|
e72c732d58 | ||
|
d40dfc345f | ||
|
70f60193b0 | ||
|
9e60d4979d | ||
|
3562c8ae11 | ||
|
093de43d54 | ||
|
86ad3bd4fc | ||
|
8045d65e99 | ||
|
63a1fe2c70 | ||
|
55760bc42b | ||
|
983013446d | ||
|
569dace244 | ||
|
8e5a2f6e59 | ||
|
41a1732df2 | ||
|
487af1c789 | ||
|
5168f326a3 | ||
|
4feaa40de7 | ||
|
7f5aaada88 | ||
|
725103a77c | ||
|
a878ea0b39 | ||
|
0cc89996c6 | ||
|
c72099fc39 | ||
|
84c223d471 | ||
|
82f9e36e5a | ||
|
7c8c2ff5b8 | ||
|
dc73b89b29 | ||
|
2596bf0990 | ||
|
7169dfe61a | ||
|
5ba5eca1a1 | ||
|
4209bfd3aa | ||
|
c007fc7478 | ||
|
903fa2cf11 | ||
|
7d91dea822 | ||
|
4fc4f1cb75 | ||
|
45d2cf49e0 | ||
|
b798f31669 | ||
|
7e1524362c | ||
|
e04dd85957 | ||
|
258e1efdce | ||
|
f6e484034c | ||
|
5676f45781 | ||
|
e11d651e33 | ||
|
09a6a9bf85 | ||
|
1b64419ef1 | ||
|
5edff4a3c5 | ||
|
b043d8abb7 | ||
|
e15868d499 | ||
|
a892a507be | ||
|
33a5f30ae4 | ||
|
38b6c7fa6c | ||
|
bd88625d25 | ||
|
5fca61f581 | ||
|
cc6cef02c1 | ||
|
546c5105b2 | ||
|
f65749e2d4 | ||
|
fb8f00137c | ||
|
20b071aa2d | ||
|
b7c1b495af | ||
|
4d80c53dd0 | ||
|
035e2add0b | ||
|
f70cc5205c | ||
|
fa948e8639 | ||
|
4cc6789b5b | ||
|
4753efa33c | ||
|
283a4b23ba | ||
|
3b7f1be9a2 | ||
|
c2e12e2827 | ||
|
8b6620ca2f | ||
|
f1e2d5572a | ||
|
49fcfd74df | ||
|
511ec1b129 | ||
|
94843a77ac | ||
|
8873391496 | ||
|
b77b654df1 | ||
|
c65e1f88d2 | ||
|
9cd20e3cea | ||
|
f04bd8a7ad | ||
|
fa82939e62 | ||
|
a1fefcf27a | ||
|
65b6440024 | ||
|
6e0064c5fc | ||
|
b047f9ce28 | ||
|
d97596a16a | ||
|
5b6d0f42fd | ||
|
4a89fadedd | ||
|
886071af4d | ||
|
12c9c324a1 | ||
|
e311bd9f76 | ||
|
707c23b188 | ||
|
49e78793c5 | ||
|
8d31330d3e | ||
|
17397dbe08 | ||
|
b98544ed1f | ||
|
043675f3f8 | ||
|
3b1cb02663 | ||
|
bc68bc0312 | ||
|
b3819228ed | ||
|
c23c65733b | ||
|
cfefdbc7a7 | ||
|
70103e8111 | ||
|
240705652c | ||
|
d42c9547ab | ||
|
ac85b3508b | ||
|
9ece4dddd3 | ||
|
36f5d9acc6 | ||
|
d4956f3ec7 | ||
|
8279c8d0ba | ||
|
74e3ba42e0 | ||
|
784ae0a02d | ||
|
901d803ba9 | ||
|
bdb693302a | ||
|
f8a7d1d634 | ||
|
770078f236 | ||
|
f1dd39885b | ||
|
a29115ba78 | ||
|
cd5e0aeec1 | ||
|
75fa0ff708 |
156 changed files with 3489 additions and 2412 deletions
|
@ -90,7 +90,13 @@ export default tseslint.config(
|
||||||
"no-invalid-regexp": "error",
|
"no-invalid-regexp": "error",
|
||||||
"no-constant-condition": ["error", { "checkLoops": false }],
|
"no-constant-condition": ["error", { "checkLoops": false }],
|
||||||
"no-duplicate-imports": "error",
|
"no-duplicate-imports": "error",
|
||||||
"dot-notation": "error",
|
"@typescript-eslint/dot-notation": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"allowPrivateClassPropertyAccess": true,
|
||||||
|
"allowProtectedClassPropertyAccess": true
|
||||||
|
}
|
||||||
|
],
|
||||||
"no-useless-escape": [
|
"no-useless-escape": [
|
||||||
"error",
|
"error",
|
||||||
{
|
{
|
||||||
|
|
|
@ -312,7 +312,7 @@ export const commonOpts = {
|
||||||
logLevel: "info",
|
logLevel: "info",
|
||||||
bundle: true,
|
bundle: true,
|
||||||
watch,
|
watch,
|
||||||
minify: !watch,
|
minify: !watch && !IS_REPORTER,
|
||||||
sourcemap: watch ? "inline" : "",
|
sourcemap: watch ? "inline" : "",
|
||||||
legalComments: "linked",
|
legalComments: "linked",
|
||||||
banner,
|
banner,
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
import { readFileSync } from "fs";
|
import { readFileSync } from "fs";
|
||||||
import pup, { JSHandle } from "puppeteer-core";
|
import pup, { JSHandle } from "puppeteer-core";
|
||||||
|
|
||||||
for (const variable of ["DISCORD_TOKEN", "CHROMIUM_BIN"]) {
|
for (const variable of ["CHROMIUM_BIN"]) {
|
||||||
if (!process.env[variable]) {
|
if (!process.env[variable]) {
|
||||||
console.error(`Missing environment variable ${variable}`);
|
console.error(`Missing environment variable ${variable}`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
@ -37,7 +37,8 @@ const CANARY = process.env.USE_CANARY === "true";
|
||||||
|
|
||||||
const browser = await pup.launch({
|
const browser = await pup.launch({
|
||||||
headless: true,
|
headless: true,
|
||||||
executablePath: process.env.CHROMIUM_BIN
|
executablePath: process.env.CHROMIUM_BIN,
|
||||||
|
args: ["--no-sandbox"]
|
||||||
});
|
});
|
||||||
|
|
||||||
const page = await browser.newPage();
|
const page = await browser.newPage();
|
||||||
|
@ -214,7 +215,7 @@ page.on("console", async e => {
|
||||||
|
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case "WebpackInterceptor:":
|
case "WebpackInterceptor:":
|
||||||
const patchFailMatch = message.match(/Patch by (.+?) (had no effect|errored|found no module) \(Module id is (.+?)\): (.+)/)!;
|
const patchFailMatch = message.match(/Patch by (.+?) (had no effect|errored|found no module|took [\d.]+?ms) \(Module id is (.+?)\): (.+)/)!;
|
||||||
if (!patchFailMatch) break;
|
if (!patchFailMatch) break;
|
||||||
|
|
||||||
console.error(await getText());
|
console.error(await getText());
|
||||||
|
@ -225,7 +226,7 @@ page.on("console", async e => {
|
||||||
plugin,
|
plugin,
|
||||||
type,
|
type,
|
||||||
id,
|
id,
|
||||||
match: regex.replace(/\[A-Za-z_\$\]\[\\w\$\]\*/g, "\\i"),
|
match: regex,
|
||||||
error: await maybeGetError(e.args()[3])
|
error: await maybeGetError(e.args()[3])
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -291,7 +292,7 @@ page.on("error", e => console.error("[Error]", e.message));
|
||||||
page.on("pageerror", e => {
|
page.on("pageerror", e => {
|
||||||
if (e.message.includes("Sentry successfully disabled")) return;
|
if (e.message.includes("Sentry successfully disabled")) return;
|
||||||
|
|
||||||
if (!e.message.startsWith("Object") && !e.message.includes("Cannot find module")) {
|
if (!e.message.startsWith("Object") && !e.message.includes("Cannot find module") && !/^.{1,2}$/.test(e.message)) {
|
||||||
console.error("[Page Error]", e.message);
|
console.error("[Page Error]", e.message);
|
||||||
report.otherErrors.push(e.message);
|
report.otherErrors.push(e.message);
|
||||||
} else {
|
} else {
|
||||||
|
@ -299,20 +300,9 @@ page.on("pageerror", e => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
async function reporterRuntime(token: string) {
|
|
||||||
Vencord.Webpack.waitFor(
|
|
||||||
"loginToken",
|
|
||||||
m => {
|
|
||||||
console.log("[PUP_DEBUG]", "Logging in with token...");
|
|
||||||
m.loginToken(token);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await page.evaluateOnNewDocument(`
|
await page.evaluateOnNewDocument(`
|
||||||
if (location.host.endsWith("discord.com")) {
|
if (location.host.endsWith("discord.com")) {
|
||||||
${readFileSync("./dist/browser.js", "utf-8")};
|
${readFileSync("./dist/browser.js", "utf-8")};
|
||||||
(${reporterRuntime.toString()})(${JSON.stringify(process.env.DISCORD_TOKEN)});
|
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
|
|
@ -23,10 +23,10 @@ export * as Util from "./utils";
|
||||||
export * as QuickCss from "./utils/quickCss";
|
export * as QuickCss from "./utils/quickCss";
|
||||||
export * as Updater from "./utils/updater";
|
export * as Updater from "./utils/updater";
|
||||||
export * as Webpack from "./webpack";
|
export * as Webpack from "./webpack";
|
||||||
|
export * as WebpackPatcher from "./webpack/patchWebpack";
|
||||||
export { PlainSettings, Settings };
|
export { PlainSettings, Settings };
|
||||||
|
|
||||||
import "./utils/quickCss";
|
import "./utils/quickCss";
|
||||||
import "./webpack/patchWebpack";
|
|
||||||
|
|
||||||
import { openUpdaterModal } from "@components/VencordSettings/UpdaterTab";
|
import { openUpdaterModal } from "@components/VencordSettings/UpdaterTab";
|
||||||
import { StartAt } from "@utils/types";
|
import { StartAt } from "@utils/types";
|
||||||
|
@ -39,7 +39,7 @@ import { localStorage } from "./utils/localStorage";
|
||||||
import { relaunch } from "./utils/native";
|
import { relaunch } from "./utils/native";
|
||||||
import { getCloudSettings, putCloudSettings } from "./utils/settingsSync";
|
import { getCloudSettings, putCloudSettings } from "./utils/settingsSync";
|
||||||
import { checkForUpdates, update, UpdateLogger } from "./utils/updater";
|
import { checkForUpdates, update, UpdateLogger } from "./utils/updater";
|
||||||
import { onceReady } from "./webpack";
|
import { onceDiscordLoaded } from "./webpack";
|
||||||
import { SettingsRouter } from "./webpack/common";
|
import { SettingsRouter } from "./webpack/common";
|
||||||
|
|
||||||
if (IS_REPORTER) {
|
if (IS_REPORTER) {
|
||||||
|
@ -86,7 +86,7 @@ async function syncSettings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
await onceReady;
|
await onceDiscordLoaded;
|
||||||
startAllPlugins(StartAt.WebpackReady);
|
startAllPlugins(StartAt.WebpackReady);
|
||||||
|
|
||||||
syncSettings();
|
syncSettings();
|
||||||
|
@ -125,7 +125,7 @@ async function init() {
|
||||||
const pendingPatches = patches.filter(p => !p.all && p.predicate?.() !== false);
|
const pendingPatches = patches.filter(p => !p.all && p.predicate?.() !== false);
|
||||||
if (pendingPatches.length)
|
if (pendingPatches.length)
|
||||||
PMLogger.warn(
|
PMLogger.warn(
|
||||||
"Webpack has finished initialising, but some patches haven't been applied yet.",
|
"Webpack has finished initializing, but some patches haven't been applied yet.",
|
||||||
"This might be expected since some Modules are lazy loaded, but please verify",
|
"This might be expected since some Modules are lazy loaded, but please verify",
|
||||||
"that all plugins are working as intended.",
|
"that all plugins are working as intended.",
|
||||||
"You are seeing this warning because this is a Development build of Vencord.",
|
"You are seeing this warning because this is a Development build of Vencord.",
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { ComponentType, HTMLProps } from "react";
|
|
||||||
|
|
||||||
import Plugins from "~plugins";
|
import Plugins from "~plugins";
|
||||||
|
|
||||||
|
@ -30,7 +29,7 @@ export interface ProfileBadge {
|
||||||
/** The tooltip to show on hover. Required for image badges */
|
/** The tooltip to show on hover. Required for image badges */
|
||||||
description?: string;
|
description?: string;
|
||||||
/** Custom component for the badge (tooltip not included) */
|
/** Custom component for the badge (tooltip not included) */
|
||||||
component?: ComponentType<ProfileBadge & BadgeUserArgs>;
|
component?: React.ComponentType<ProfileBadge & BadgeUserArgs>;
|
||||||
/** The custom image to use */
|
/** The custom image to use */
|
||||||
image?: string;
|
image?: string;
|
||||||
link?: string;
|
link?: string;
|
||||||
|
@ -39,7 +38,7 @@ export interface ProfileBadge {
|
||||||
/** Should the user display this badge? */
|
/** Should the user display this badge? */
|
||||||
shouldShow?(userInfo: BadgeUserArgs): boolean;
|
shouldShow?(userInfo: BadgeUserArgs): boolean;
|
||||||
/** Optional props (e.g. style) for the badge, ignored for component badges */
|
/** Optional props (e.g. style) for the badge, ignored for component badges */
|
||||||
props?: HTMLProps<HTMLImageElement>;
|
props?: React.ComponentPropsWithoutRef<"img">;
|
||||||
/** Insert at start or end? */
|
/** Insert at start or end? */
|
||||||
position?: BadgePosition;
|
position?: BadgePosition;
|
||||||
/** The badge name to display, Discord uses this. Required for component badges */
|
/** The badge name to display, Discord uses this. Required for component badges */
|
||||||
|
|
|
@ -8,13 +8,12 @@ import "./ChatButton.css";
|
||||||
|
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
import { waitFor } from "@webpack";
|
import { findByProps } from "@webpack";
|
||||||
import { Button, ButtonLooks, ButtonWrapperClasses, Tooltip } from "@webpack/common";
|
import { Button, ButtonLooks, ButtonWrapperClasses, Tooltip } from "@webpack/common";
|
||||||
import { Channel } from "discord-types/general";
|
import { Channel } from "discord-types/general";
|
||||||
import { HTMLProps, MouseEventHandler, ReactNode } from "react";
|
import { HTMLProps, MouseEventHandler, ReactNode } from "react";
|
||||||
|
|
||||||
let ChannelTextAreaClasses: Record<"button" | "buttonContainer", string>;
|
const ChannelTextAreaClasses = findByProps<Record<"button" | "buttonContainer", string>>("buttonContainer", "channelTextArea");
|
||||||
waitFor(["buttonContainer", "channelTextArea"], m => ChannelTextAreaClasses = m);
|
|
||||||
|
|
||||||
export interface ChatBarProps {
|
export interface ChatBarProps {
|
||||||
channel: Channel;
|
channel: Channel;
|
||||||
|
|
|
@ -17,14 +17,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { mergeDefaults } from "@utils/mergeDefaults";
|
import { mergeDefaults } from "@utils/mergeDefaults";
|
||||||
import { findByCodeLazy } from "@webpack";
|
import { findByCode } from "@webpack";
|
||||||
import { MessageActions, SnowflakeUtils } from "@webpack/common";
|
import { MessageActions, SnowflakeUtils } from "@webpack/common";
|
||||||
import { Message } from "discord-types/general";
|
import { Message } from "discord-types/general";
|
||||||
import type { PartialDeep } from "type-fest";
|
import type { PartialDeep } from "type-fest";
|
||||||
|
|
||||||
import { Argument } from "./types";
|
import { Argument } from "./types";
|
||||||
|
|
||||||
const createBotMessage = findByCodeLazy('username:"Clyde"');
|
const createBotMessage = findByCode('username:"Clyde"');
|
||||||
|
|
||||||
export function generateId() {
|
export function generateId() {
|
||||||
return `-${SnowflakeUtils.fromTimestamp(Date.now())}`;
|
return `-${SnowflakeUtils.fromTimestamp(Date.now())}`;
|
||||||
|
|
|
@ -19,18 +19,17 @@
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
import { Channel, Message } from "discord-types/general";
|
import { Channel, Message } from "discord-types/general";
|
||||||
import type { ComponentType, MouseEventHandler } from "react";
|
|
||||||
|
|
||||||
const logger = new Logger("MessagePopover");
|
const logger = new Logger("MessagePopover");
|
||||||
|
|
||||||
export interface ButtonItem {
|
export interface ButtonItem {
|
||||||
key?: string,
|
key?: string,
|
||||||
label: string,
|
label: string,
|
||||||
icon: ComponentType<any>,
|
icon: React.ComponentType<AnyRecord>,
|
||||||
message: Message,
|
message: Message,
|
||||||
channel: Channel,
|
channel: Channel,
|
||||||
onClick?: MouseEventHandler<HTMLButtonElement>,
|
onClick?: React.MouseEventHandler<HTMLButtonElement>,
|
||||||
onContextMenu?: MouseEventHandler<HTMLButtonElement>;
|
onContextMenu?: React.MouseEventHandler<HTMLButtonElement>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type getButtonItem = (message: Message) => ButtonItem | null;
|
export type getButtonItem = (message: Message) => ButtonItem | null;
|
||||||
|
|
|
@ -16,23 +16,22 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { waitFor } from "@webpack";
|
import { find } from "@webpack";
|
||||||
|
|
||||||
let NoticesModule: any;
|
const Notices = find(m => m.show && m.dismiss && !m.suppressAll);
|
||||||
waitFor(m => m.show && m.dismiss && !m.suppressAll, m => NoticesModule = m);
|
|
||||||
|
|
||||||
export const noticesQueue = [] as any[];
|
export const noticesQueue = [] as any[];
|
||||||
export let currentNotice: any = null;
|
export let currentNotice: any = null;
|
||||||
|
|
||||||
export function popNotice() {
|
export function popNotice() {
|
||||||
NoticesModule.dismiss();
|
Notices.dismiss();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function nextNotice() {
|
export function nextNotice() {
|
||||||
currentNotice = noticesQueue.shift();
|
currentNotice = noticesQueue.shift();
|
||||||
|
|
||||||
if (currentNotice) {
|
if (currentNotice) {
|
||||||
NoticesModule.show(...currentNotice, "VencordNotice");
|
Notices.show(...currentNotice, "VencordNotice");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,9 +32,10 @@ export interface Settings {
|
||||||
autoUpdate: boolean;
|
autoUpdate: boolean;
|
||||||
autoUpdateNotification: boolean,
|
autoUpdateNotification: boolean,
|
||||||
useQuickCss: boolean;
|
useQuickCss: boolean;
|
||||||
enableReactDevtools: boolean;
|
|
||||||
themeLinks: string[];
|
themeLinks: string[];
|
||||||
|
eagerPatches: boolean;
|
||||||
enabledThemes: string[];
|
enabledThemes: string[];
|
||||||
|
enableReactDevtools: boolean;
|
||||||
frameless: boolean;
|
frameless: boolean;
|
||||||
transparent: boolean;
|
transparent: boolean;
|
||||||
winCtrlQ: boolean;
|
winCtrlQ: boolean;
|
||||||
|
@ -81,6 +82,7 @@ const DefaultSettings: Settings = {
|
||||||
autoUpdateNotification: true,
|
autoUpdateNotification: true,
|
||||||
useQuickCss: true,
|
useQuickCss: true,
|
||||||
themeLinks: [],
|
themeLinks: [],
|
||||||
|
eagerPatches: IS_REPORTER,
|
||||||
enabledThemes: [],
|
enabledThemes: [],
|
||||||
enableReactDevtools: false,
|
enableReactDevtools: false,
|
||||||
frameless: false,
|
frameless: false,
|
||||||
|
@ -116,7 +118,6 @@ const saveSettingsOnFrequentAction = debounce(async () => {
|
||||||
}
|
}
|
||||||
}, 60_000);
|
}, 60_000);
|
||||||
|
|
||||||
|
|
||||||
export const SettingsStore = new SettingsStoreClass(settings, {
|
export const SettingsStore = new SettingsStoreClass(settings, {
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
getDefaultValue({
|
getDefaultValue({
|
||||||
|
|
|
@ -89,8 +89,8 @@ export const isStyleEnabled = (name: string) => requireStyle(name).dom?.isConnec
|
||||||
* // -- plugin.ts --
|
* // -- plugin.ts --
|
||||||
* import pluginStyle from "./plugin.css?managed";
|
* import pluginStyle from "./plugin.css?managed";
|
||||||
* import { setStyleVars } from "@api/Styles";
|
* import { setStyleVars } from "@api/Styles";
|
||||||
* import { findByPropsLazy } from "@webpack";
|
* import { findByProps } from "@webpack";
|
||||||
* const classNames = findByPropsLazy("thin", "scrollerBase"); // { thin: "thin-31rlnD scrollerBase-_bVAAt", ... }
|
* const classNames = findByProps("thin", "scrollerBase"); // { thin: "thin-31rlnD scrollerBase-_bVAAt", ... }
|
||||||
*
|
*
|
||||||
* // Inside some plugin method like "start()"
|
* // Inside some plugin method like "start()"
|
||||||
* setStyleClassNames(pluginStyle, classNames);
|
* setStyleClassNames(pluginStyle, classNames);
|
||||||
|
|
|
@ -17,8 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { proxyLazy } from "@utils/lazy";
|
import { proxyLazy } from "@utils/lazy";
|
||||||
import { Logger } from "@utils/Logger";
|
import { findByFactoryCode } from "@webpack";
|
||||||
import { findModuleId, proxyLazyWebpack, wreq } from "@webpack";
|
|
||||||
|
|
||||||
interface UserSettingDefinition<T> {
|
interface UserSettingDefinition<T> {
|
||||||
/**
|
/**
|
||||||
|
@ -43,12 +42,7 @@ interface UserSettingDefinition<T> {
|
||||||
userSettingsAPIName: string;
|
userSettingsAPIName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const UserSettings: Record<PropertyKey, UserSettingDefinition<any>> | undefined = proxyLazyWebpack(() => {
|
export const UserSettings = findByFactoryCode<Record<PropertyKey, UserSettingDefinition<any>>>('"textAndImages","renderSpoilers"');
|
||||||
const modId = findModuleId('"textAndImages","renderSpoilers"');
|
|
||||||
if (modId == null) return new Logger("UserSettingsAPI ").error("Didn't find settings module.");
|
|
||||||
|
|
||||||
return wreq(modId as any);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the setting with the given setting group and name.
|
* Get the setting with the given setting group and name.
|
||||||
|
@ -56,7 +50,7 @@ export const UserSettings: Record<PropertyKey, UserSettingDefinition<any>> | und
|
||||||
* @param group The setting group
|
* @param group The setting group
|
||||||
* @param name The name of the setting
|
* @param name The name of the setting
|
||||||
*/
|
*/
|
||||||
export function getUserSetting<T = any>(group: string, name: string): UserSettingDefinition<T> | undefined {
|
export function getUserSetting<T = any>(group: string, name: string): UserSettingDefinition<T> {
|
||||||
if (!Vencord.Plugins.isPluginEnabled("UserSettingsAPI")) throw new Error("Cannot use UserSettingsAPI without setting as dependency.");
|
if (!Vencord.Plugins.isPluginEnabled("UserSettingsAPI")) throw new Error("Cannot use UserSettingsAPI without setting as dependency.");
|
||||||
|
|
||||||
for (const key in UserSettings) {
|
for (const key in UserSettings) {
|
||||||
|
@ -66,10 +60,12 @@ export function getUserSetting<T = any>(group: string, name: string): UserSettin
|
||||||
return userSetting;
|
return userSetting;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw new Error(`UserSettingsAPI: Setting ${group}.${name} not found.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link getUserSettingDefinition}, lazy.
|
* Lazy version of {@link getUserSetting}
|
||||||
*
|
*
|
||||||
* Get the setting with the given setting group and name.
|
* Get the setting with the given setting group and name.
|
||||||
*
|
*
|
||||||
|
|
|
@ -4,10 +4,10 @@
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findByProps } from "@webpack";
|
||||||
import { Parser } from "@webpack/common";
|
import { Parser } from "@webpack/common";
|
||||||
|
|
||||||
const CodeContainerClasses = findByPropsLazy("markup", "codeContainer");
|
const CodeContainerClasses = findByProps("markup", "codeContainer");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders code in a Discord codeblock
|
* Renders code in a Discord codeblock
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
import { LazyComponent } from "@utils/react";
|
import { LazyComponent, LazyComponentType } from "@utils/react";
|
||||||
import { React } from "@webpack/common";
|
import { React } from "@webpack/common";
|
||||||
|
|
||||||
import { ErrorCard } from "./ErrorCard";
|
import { ErrorCard } from "./ErrorCard";
|
||||||
|
@ -104,8 +104,8 @@ const ErrorBoundary = LazyComponent(() => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}) as
|
}) as
|
||||||
React.ComponentType<React.PropsWithChildren<Props>> & {
|
LazyComponentType<React.PropsWithChildren<Props>> & {
|
||||||
wrap<T extends object = any>(Component: React.ComponentType<T>, errorBoundaryProps?: Omit<Props<T>, "wrappedProps">): React.FunctionComponent<T>;
|
wrap<T extends AnyRecord>(Component: React.ComponentType<T>, errorBoundaryProps?: Omit<Props<T>, "wrappedProps">): React.FunctionComponent<T>;
|
||||||
};
|
};
|
||||||
|
|
||||||
ErrorBoundary.wrap = (Component, errorBoundaryProps) => props => (
|
ErrorBoundary.wrap = (Component, errorBoundaryProps) => props => (
|
||||||
|
|
|
@ -24,13 +24,12 @@ import { classNameFactory } from "@api/Styles";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Flex } from "@components/Flex";
|
import { Flex } from "@components/Flex";
|
||||||
import { gitRemote } from "@shared/vencordUserAgent";
|
import { gitRemote } from "@shared/vencordUserAgent";
|
||||||
import { proxyLazy } from "@utils/lazy";
|
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
import { classes, isObjectEmpty } from "@utils/misc";
|
import { classes, isObjectEmpty } from "@utils/misc";
|
||||||
import { ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
import { ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
||||||
import { OptionType, Plugin } from "@utils/types";
|
import { OptionType, Plugin } from "@utils/types";
|
||||||
import { findByPropsLazy, findComponentByCodeLazy } from "@webpack";
|
import { find, findByProps, findComponentByCode } from "@webpack";
|
||||||
import { Button, Clickable, FluxDispatcher, Forms, React, Text, Tooltip, UserStore, UserUtils } from "@webpack/common";
|
import { Button, Clickable, FluxDispatcher, Forms, React, Text, Tooltip, UserUtils } from "@webpack/common";
|
||||||
import { User } from "discord-types/general";
|
import { User } from "discord-types/general";
|
||||||
import { Constructor } from "type-fest";
|
import { Constructor } from "type-fest";
|
||||||
|
|
||||||
|
@ -50,9 +49,9 @@ import { GithubButton, WebsiteButton } from "./LinkIconButton";
|
||||||
|
|
||||||
const cl = classNameFactory("vc-plugin-modal-");
|
const cl = classNameFactory("vc-plugin-modal-");
|
||||||
|
|
||||||
const UserSummaryItem = findComponentByCodeLazy("defaultRenderUser", "showDefaultAvatarsForNullUsers");
|
const UserSummaryItem = findComponentByCode("defaultRenderUser", "showDefaultAvatarsForNullUsers");
|
||||||
const AvatarStyles = findByPropsLazy("moreUsers", "emptyUser", "avatarContainer", "clickableAvatar");
|
const AvatarStyles = findByProps("moreUsers", "emptyUser", "avatarContainer", "clickableAvatar");
|
||||||
const UserRecord: Constructor<Partial<User>> = proxyLazy(() => UserStore.getCurrentUser().constructor) as any;
|
const UserRecord = find<Constructor<Partial<User>>>(m => m?.prototype?.getAvatarURL && m?.prototype?.hasHadPremium);
|
||||||
|
|
||||||
interface PluginModalProps extends ModalProps {
|
interface PluginModalProps extends ModalProps {
|
||||||
plugin: Plugin;
|
plugin: Plugin;
|
||||||
|
|
|
@ -33,19 +33,19 @@ import { Margins } from "@utils/margins";
|
||||||
import { classes, isObjectEmpty } from "@utils/misc";
|
import { classes, isObjectEmpty } from "@utils/misc";
|
||||||
import { useAwaiter } from "@utils/react";
|
import { useAwaiter } from "@utils/react";
|
||||||
import { Plugin } from "@utils/types";
|
import { Plugin } from "@utils/types";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findByProps } from "@webpack";
|
||||||
import { Alerts, Button, Card, Forms, lodash, Parser, React, Select, Text, TextInput, Toasts, Tooltip, useMemo } from "@webpack/common";
|
import { Alerts, Button, Card, Forms, lodash, Parser, React, Select, Text, TextInput, Toasts, Tooltip, useMemo } from "@webpack/common";
|
||||||
|
|
||||||
import Plugins, { ExcludedPlugins } from "~plugins";
|
import Plugins, { ExcludedPlugins } from "~plugins";
|
||||||
|
|
||||||
// Avoid circular dependency
|
// Avoid circular dependency
|
||||||
const { startDependenciesRecursive, startPlugin, stopPlugin } = proxyLazy(() => require("../../plugins"));
|
const PluginManager = proxyLazy(() => require("../../plugins")) as typeof import("../../plugins");
|
||||||
|
|
||||||
const cl = classNameFactory("vc-plugins-");
|
const cl = classNameFactory("vc-plugins-");
|
||||||
const logger = new Logger("PluginSettings", "#a6d189");
|
const logger = new Logger("PluginSettings", "#a6d189");
|
||||||
|
|
||||||
const InputStyles = findByPropsLazy("inputWrapper", "inputDefault", "error");
|
const InputStyles = findByProps("inputWrapper", "inputDefault", "error");
|
||||||
const ButtonClasses = findByPropsLazy("button", "disabled", "enabled");
|
const ButtonClasses = findByProps("button", "disabled", "enabled");
|
||||||
|
|
||||||
|
|
||||||
function showErrorToast(message: string) {
|
function showErrorToast(message: string) {
|
||||||
|
@ -100,7 +100,7 @@ export function PluginCard({ plugin, disabled, onRestartNeeded, onMouseEnter, on
|
||||||
|
|
||||||
// If we're enabling a plugin, make sure all deps are enabled recursively.
|
// If we're enabling a plugin, make sure all deps are enabled recursively.
|
||||||
if (!wasEnabled) {
|
if (!wasEnabled) {
|
||||||
const { restartNeeded, failures } = startDependenciesRecursive(plugin);
|
const { restartNeeded, failures } = PluginManager.startDependenciesRecursive(plugin);
|
||||||
if (failures.length) {
|
if (failures.length) {
|
||||||
logger.error(`Failed to start dependencies for ${plugin.name}: ${failures.join(", ")}`);
|
logger.error(`Failed to start dependencies for ${plugin.name}: ${failures.join(", ")}`);
|
||||||
showNotice("Failed to start dependencies: " + failures.join(", "), "Close", () => null);
|
showNotice("Failed to start dependencies: " + failures.join(", "), "Close", () => null);
|
||||||
|
@ -126,7 +126,7 @@ export function PluginCard({ plugin, disabled, onRestartNeeded, onMouseEnter, on
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = wasEnabled ? stopPlugin(plugin) : startPlugin(plugin);
|
const result = wasEnabled ? PluginManager.stopPlugin(plugin) : PluginManager.startPlugin(plugin);
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
settings.enabled = false;
|
settings.enabled = false;
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
import "./Switch.css";
|
import "./Switch.css";
|
||||||
|
|
||||||
import { classes } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findByProps } from "@webpack";
|
||||||
|
|
||||||
interface SwitchProps {
|
interface SwitchProps {
|
||||||
checked: boolean;
|
checked: boolean;
|
||||||
|
@ -29,7 +29,7 @@ interface SwitchProps {
|
||||||
|
|
||||||
const SWITCH_ON = "var(--green-360)";
|
const SWITCH_ON = "var(--green-360)";
|
||||||
const SWITCH_OFF = "var(--primary-400)";
|
const SWITCH_OFF = "var(--primary-400)";
|
||||||
const SwitchClasses = findByPropsLazy("slider", "input", "container");
|
const SwitchClasses = findByProps("slider", "input", "container");
|
||||||
|
|
||||||
export function Switch({ checked, onChange, disabled }: SwitchProps) {
|
export function Switch({ checked, onChange, disabled }: SwitchProps) {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -22,7 +22,7 @@ import { Margins } from "@utils/margins";
|
||||||
import { canonicalizeMatch, canonicalizeReplace } from "@utils/patches";
|
import { canonicalizeMatch, canonicalizeReplace } from "@utils/patches";
|
||||||
import { makeCodeblock } from "@utils/text";
|
import { makeCodeblock } from "@utils/text";
|
||||||
import { Patch, ReplaceFn } from "@utils/types";
|
import { Patch, ReplaceFn } from "@utils/types";
|
||||||
import { search } from "@webpack";
|
import { searchFactories } from "@webpack";
|
||||||
import { Button, Clipboard, Forms, Parser, React, Switch, TextArea, TextInput } from "@webpack/common";
|
import { Button, Clipboard, Forms, Parser, React, Switch, TextArea, TextInput } from "@webpack/common";
|
||||||
|
|
||||||
import { SettingsTab, wrapTab } from "./shared";
|
import { SettingsTab, wrapTab } from "./shared";
|
||||||
|
@ -33,7 +33,7 @@ if (IS_DEV) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const findCandidates = debounce(function ({ find, setModule, setError }) {
|
const findCandidates = debounce(function ({ find, setModule, setError }) {
|
||||||
const candidates = search(find);
|
const candidates = searchFactories(find);
|
||||||
const keys = Object.keys(candidates);
|
const keys = Object.keys(candidates);
|
||||||
const len = keys.length;
|
const len = keys.length;
|
||||||
if (len === 0)
|
if (len === 0)
|
||||||
|
@ -56,7 +56,7 @@ function ReplacementComponent({ module, match, replacement, setReplacementError
|
||||||
const [compileResult, setCompileResult] = React.useState<[boolean, string]>();
|
const [compileResult, setCompileResult] = React.useState<[boolean, string]>();
|
||||||
|
|
||||||
const [patchedCode, matchResult, diff] = React.useMemo(() => {
|
const [patchedCode, matchResult, diff] = React.useMemo(() => {
|
||||||
const src: string = fact.toString().replaceAll("\n", "");
|
const src = String(fact).replaceAll("\n", "");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
new RegExp(match);
|
new RegExp(match);
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Settings, useSettings } from "@api/Settings";
|
import { useSettings } from "@api/Settings";
|
||||||
import { classNameFactory } from "@api/Styles";
|
import { classNameFactory } from "@api/Styles";
|
||||||
import { Flex } from "@components/Flex";
|
import { Flex } from "@components/Flex";
|
||||||
import { DeleteIcon, FolderIcon, PaintbrushIcon, PencilIcon, PlusIcon, RestartIcon } from "@components/Icons";
|
import { DeleteIcon, FolderIcon, PaintbrushIcon, PencilIcon, PlusIcon, RestartIcon } from "@components/Icons";
|
||||||
|
@ -27,9 +27,9 @@ import { openInviteModal } from "@utils/discord";
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
import { showItemInFolder } from "@utils/native";
|
import { showItemInFolder } from "@utils/native";
|
||||||
import { useAwaiter } from "@utils/react";
|
import { useAwaiter } from "@utils/react";
|
||||||
import { findLazy } from "@webpack";
|
import { findComponentByFields } from "@webpack";
|
||||||
import { Card, Forms, React, showToast, TabBar, TextArea, useEffect, useRef, useState } from "@webpack/common";
|
import { Card, Forms, React, showToast, TabBar, TextArea, useEffect, useRef, useState } from "@webpack/common";
|
||||||
import type { ComponentType, Ref, SyntheticEvent } from "react";
|
import type { Ref, SyntheticEvent } from "react";
|
||||||
|
|
||||||
import Plugins from "~plugins";
|
import Plugins from "~plugins";
|
||||||
|
|
||||||
|
@ -37,14 +37,14 @@ import { AddonCard } from "./AddonCard";
|
||||||
import { QuickAction, QuickActionCard } from "./quickActions";
|
import { QuickAction, QuickActionCard } from "./quickActions";
|
||||||
import { SettingsTab, wrapTab } from "./shared";
|
import { SettingsTab, wrapTab } from "./shared";
|
||||||
|
|
||||||
type FileInput = ComponentType<{
|
type FileInputProps = {
|
||||||
ref: Ref<HTMLInputElement>;
|
ref: Ref<HTMLInputElement>;
|
||||||
onChange: (e: SyntheticEvent<HTMLInputElement>) => void;
|
onChange: (e: SyntheticEvent<HTMLInputElement>) => void;
|
||||||
multiple?: boolean;
|
multiple?: boolean;
|
||||||
filters?: { name?: string; extensions: string[]; }[];
|
filters?: { name?: string; extensions: string[]; }[];
|
||||||
}>;
|
};
|
||||||
|
|
||||||
const FileInput: FileInput = findLazy(m => m.prototype?.activateUploadDialogue && m.prototype.setRef);
|
const FileInput = findComponentByFields<FileInputProps>("activateUploadDialogue", "setRef");
|
||||||
|
|
||||||
const cl = classNameFactory("vc-settings-theme-");
|
const cl = classNameFactory("vc-settings-theme-");
|
||||||
|
|
||||||
|
@ -257,7 +257,7 @@ function ThemesTab() {
|
||||||
Icon={PaintbrushIcon}
|
Icon={PaintbrushIcon}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{Settings.plugins.ClientTheme.enabled && (
|
{Vencord.Plugins.isPluginEnabled("ClientTheme") && (
|
||||||
<QuickAction
|
<QuickAction
|
||||||
text="Edit ClientTheme"
|
text="Edit ClientTheme"
|
||||||
action={() => openPluginModal(Plugins.ClientTheme)}
|
action={() => openPluginModal(Plugins.ClientTheme)}
|
||||||
|
|
|
@ -8,13 +8,12 @@ import "./quickActions.css";
|
||||||
|
|
||||||
import { classNameFactory } from "@api/Styles";
|
import { classNameFactory } from "@api/Styles";
|
||||||
import { Card } from "@webpack/common";
|
import { Card } from "@webpack/common";
|
||||||
import type { ComponentType, PropsWithChildren, ReactNode } from "react";
|
|
||||||
|
|
||||||
const cl = classNameFactory("vc-settings-quickActions-");
|
const cl = classNameFactory("vc-settings-quickActions-");
|
||||||
|
|
||||||
export interface QuickActionProps {
|
export interface QuickActionProps {
|
||||||
Icon: ComponentType<{ className?: string; }>;
|
Icon: React.ComponentType<{ className?: string; }>;
|
||||||
text: ReactNode;
|
text: React.ReactNode;
|
||||||
action?: () => void;
|
action?: () => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -30,7 +29,7 @@ export function QuickAction(props: QuickActionProps) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function QuickActionCard(props: PropsWithChildren) {
|
export function QuickActionCard(props: React.PropsWithChildren) {
|
||||||
return (
|
return (
|
||||||
<Card className={cl("card")}>
|
<Card className={cl("card")}>
|
||||||
{props.children}
|
{props.children}
|
||||||
|
|
|
@ -24,9 +24,8 @@ import { handleComponentFailed } from "@components/handleComponentFailed";
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
import { onlyOnce } from "@utils/onlyOnce";
|
import { onlyOnce } from "@utils/onlyOnce";
|
||||||
import { Forms, Text } from "@webpack/common";
|
import { Forms, Text } from "@webpack/common";
|
||||||
import type { ComponentType, PropsWithChildren } from "react";
|
|
||||||
|
|
||||||
export function SettingsTab({ title, children }: PropsWithChildren<{ title: string; }>) {
|
export function SettingsTab({ title, children }: React.PropsWithChildren<{ title: string; }>) {
|
||||||
return (
|
return (
|
||||||
<Forms.FormSection>
|
<Forms.FormSection>
|
||||||
<Text
|
<Text
|
||||||
|
@ -44,7 +43,7 @@ export function SettingsTab({ title, children }: PropsWithChildren<{ title: stri
|
||||||
|
|
||||||
export const handleSettingsTabError = onlyOnce(handleComponentFailed);
|
export const handleSettingsTabError = onlyOnce(handleComponentFailed);
|
||||||
|
|
||||||
export function wrapTab(component: ComponentType<any>, tab: string) {
|
export function wrapTab<P extends AnyRecord>(component: React.ComponentType<P>, tab: string) {
|
||||||
return ErrorBoundary.wrap(component, {
|
return ErrorBoundary.wrap(component, {
|
||||||
message: `Failed to render the ${tab} tab. If this issue persists, try using the installer to reinstall!`,
|
message: `Failed to render the ${tab} tab. If this issue persists, try using the installer to reinstall!`,
|
||||||
onError: handleSettingsTabError,
|
onError: handleSettingsTabError,
|
||||||
|
|
|
@ -23,35 +23,61 @@ if (IS_DEV || IS_REPORTER) {
|
||||||
var logger = new Logger("Tracer", "#FFD166");
|
var logger = new Logger("Tracer", "#FFD166");
|
||||||
}
|
}
|
||||||
|
|
||||||
const noop = function () { };
|
export const beginTrace = !(IS_DEV || IS_REPORTER) ? () => { } :
|
||||||
|
|
||||||
export const beginTrace = !(IS_DEV || IS_REPORTER) ? noop :
|
|
||||||
function beginTrace(name: string, ...args: any[]) {
|
function beginTrace(name: string, ...args: any[]) {
|
||||||
if (name in traces)
|
if (name in traces) {
|
||||||
throw new Error(`Trace ${name} already exists!`);
|
throw new Error(`Trace ${name} already exists!`);
|
||||||
|
}
|
||||||
|
|
||||||
traces[name] = [performance.now(), args];
|
traces[name] = [performance.now(), args];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const finishTrace = !(IS_DEV || IS_REPORTER) ? noop : function finishTrace(name: string) {
|
export const finishTrace = !(IS_DEV || IS_REPORTER) ? () => 0 :
|
||||||
const end = performance.now();
|
function finishTrace(name: string) {
|
||||||
|
const end = performance.now();
|
||||||
|
|
||||||
const [start, args] = traces[name];
|
const [start, args] = traces[name];
|
||||||
delete traces[name];
|
delete traces[name];
|
||||||
|
|
||||||
logger.debug(`${name} took ${end - start}ms`, args);
|
const totalTime = end - start;
|
||||||
};
|
logger.debug(`${name} took ${totalTime}ms`, args);
|
||||||
|
|
||||||
|
return totalTime;
|
||||||
|
};
|
||||||
|
|
||||||
type Func = (...args: any[]) => any;
|
type Func = (...args: any[]) => any;
|
||||||
type TraceNameMapper<F extends Func> = (...args: Parameters<F>) => string;
|
type TraceNameMapper<F extends Func> = (...args: Parameters<F>) => string;
|
||||||
|
|
||||||
const noopTracer =
|
function noopTracerWithResults<F extends Func>(name: string, f: F, mapper?: TraceNameMapper<F>) {
|
||||||
<F extends Func>(name: string, f: F, mapper?: TraceNameMapper<F>) => f;
|
return function (this: unknown, ...args: Parameters<F>): [ReturnType<F>, number] {
|
||||||
|
return [f.apply(this, args), 0];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function noopTracer<F extends Func>(name: string, f: F, mapper?: TraceNameMapper<F>) {
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const traceFunctionWithResults = !(IS_DEV || IS_REPORTER)
|
||||||
|
? noopTracerWithResults
|
||||||
|
: function traceFunctionWithResults<F extends Func>(name: string, f: F, mapper?: TraceNameMapper<F>): (this: unknown, ...args: Parameters<F>) => [ReturnType<F>, number] {
|
||||||
|
return function (this: unknown, ...args: Parameters<F>) {
|
||||||
|
const traceName = mapper?.(...args) ?? name;
|
||||||
|
|
||||||
|
beginTrace(traceName, ...arguments);
|
||||||
|
try {
|
||||||
|
return [f.apply(this, args), finishTrace(traceName)];
|
||||||
|
} catch (e) {
|
||||||
|
finishTrace(traceName);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export const traceFunction = !(IS_DEV || IS_REPORTER)
|
export const traceFunction = !(IS_DEV || IS_REPORTER)
|
||||||
? noopTracer
|
? noopTracer
|
||||||
: function traceFunction<F extends Func>(name: string, f: F, mapper?: TraceNameMapper<F>): F {
|
: function traceFunction<F extends Func>(name: string, f: F, mapper?: TraceNameMapper<F>): F {
|
||||||
return function (this: any, ...args: Parameters<F>) {
|
return function (this: unknown, ...args: Parameters<F>) {
|
||||||
const traceName = mapper?.(...args) ?? name;
|
const traceName = mapper?.(...args) ?? name;
|
||||||
|
|
||||||
beginTrace(traceName, ...arguments);
|
beginTrace(traceName, ...arguments);
|
||||||
|
|
|
@ -8,10 +8,11 @@ import { Logger } from "@utils/Logger";
|
||||||
import { canonicalizeMatch } from "@utils/patches";
|
import { canonicalizeMatch } from "@utils/patches";
|
||||||
import * as Webpack from "@webpack";
|
import * as Webpack from "@webpack";
|
||||||
import { wreq } from "@webpack";
|
import { wreq } from "@webpack";
|
||||||
|
import { AnyModuleFactory, ModuleFactory } from "webpack";
|
||||||
const LazyChunkLoaderLogger = new Logger("LazyChunkLoader");
|
|
||||||
|
|
||||||
export async function loadLazyChunks() {
|
export async function loadLazyChunks() {
|
||||||
|
const LazyChunkLoaderLogger = new Logger("LazyChunkLoader");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
LazyChunkLoaderLogger.log("Loading all chunks...");
|
LazyChunkLoaderLogger.log("Loading all chunks...");
|
||||||
|
|
||||||
|
@ -25,16 +26,12 @@ export async function loadLazyChunks() {
|
||||||
// True if resolved, false otherwise
|
// True if resolved, false otherwise
|
||||||
const chunksSearchPromises = [] as Array<() => boolean>;
|
const chunksSearchPromises = [] as Array<() => boolean>;
|
||||||
|
|
||||||
const LazyChunkRegex = canonicalizeMatch(/(?:(?:Promise\.all\(\[)?(\i\.e\("?[^)]+?"?\)[^\]]*?)(?:\]\))?)\.then\(\i\.bind\(\i,"?([^)]+?)"?\)\)/g);
|
const LazyChunkRegex = canonicalizeMatch(/(?:(?:Promise\.all\(\[)?(\i\.e\("?[^)]+?"?\)[^\]]*?)(?:\]\))?)\.then\(\i(?:\.\i)?\.bind\(\i,"?([^)]+?)"?(?:,[^)]+?)?\)\)/g);
|
||||||
|
|
||||||
async function searchAndLoadLazyChunks(factoryCode: string) {
|
async function searchAndLoadLazyChunks(factoryCode: string) {
|
||||||
const lazyChunks = factoryCode.matchAll(LazyChunkRegex);
|
const lazyChunks = factoryCode.matchAll(LazyChunkRegex);
|
||||||
const validChunkGroups = new Set<[chunkIds: number[], entryPoint: number]>();
|
const validChunkGroups = new Set<[chunkIds: number[], entryPoint: number]>();
|
||||||
|
|
||||||
// Workaround for a chunk that depends on the ChannelMessage component but may be be force loaded before
|
|
||||||
// the chunk containing the component
|
|
||||||
const shouldForceDefer = factoryCode.includes(".Messages.GUILD_FEED_UNFEATURE_BUTTON_TEXT");
|
|
||||||
|
|
||||||
await Promise.all(Array.from(lazyChunks).map(async ([, rawChunkIds, entryPoint]) => {
|
await Promise.all(Array.from(lazyChunks).map(async ([, rawChunkIds, entryPoint]) => {
|
||||||
const chunkIds = rawChunkIds ? Array.from(rawChunkIds.matchAll(Webpack.ChunkIdsRegex)).map(m => Number(m[1])) : [];
|
const chunkIds = rawChunkIds ? Array.from(rawChunkIds.matchAll(Webpack.ChunkIdsRegex)).map(m => Number(m[1])) : [];
|
||||||
|
|
||||||
|
@ -69,19 +66,14 @@ export async function loadLazyChunks() {
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
Array.from(validChunkGroups)
|
Array.from(validChunkGroups)
|
||||||
.map(([chunkIds]) =>
|
.map(([chunkIds]) =>
|
||||||
Promise.all(chunkIds.map(id => wreq.e(id as any).catch(() => { })))
|
Promise.all(chunkIds.map(id => wreq.e(id)))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Requires the entry points for all valid chunk groups
|
// Requires the entry points for all valid chunk groups
|
||||||
for (const [, entryPoint] of validChunkGroups) {
|
for (const [, entryPoint] of validChunkGroups) {
|
||||||
try {
|
try {
|
||||||
if (shouldForceDefer) {
|
if (wreq.m[entryPoint]) wreq(entryPoint);
|
||||||
deferredRequires.add(entryPoint);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wreq.m[entryPoint]) wreq(entryPoint as any);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
|
@ -109,32 +101,33 @@ export async function loadLazyChunks() {
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Webpack.factoryListeners.add(factory => {
|
function factoryListener(factory: AnyModuleFactory | ModuleFactory) {
|
||||||
let isResolved = false;
|
let isResolved = false;
|
||||||
searchAndLoadLazyChunks(factory.toString()).then(() => isResolved = true);
|
searchAndLoadLazyChunks(String(factory))
|
||||||
|
.then(() => isResolved = true)
|
||||||
chunksSearchPromises.push(() => isResolved);
|
.catch(() => isResolved = true);
|
||||||
});
|
|
||||||
|
|
||||||
for (const factoryId in wreq.m) {
|
|
||||||
let isResolved = false;
|
|
||||||
searchAndLoadLazyChunks(wreq.m[factoryId].toString()).then(() => isResolved = true);
|
|
||||||
|
|
||||||
chunksSearchPromises.push(() => isResolved);
|
chunksSearchPromises.push(() => isResolved);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Webpack.factoryListeners.add(factoryListener);
|
||||||
|
for (const factoryId in wreq.m) {
|
||||||
|
factoryListener(wreq.m[factoryId]);
|
||||||
|
}
|
||||||
|
|
||||||
await chunksSearchingDone;
|
await chunksSearchingDone;
|
||||||
|
Webpack.factoryListeners.delete(factoryListener);
|
||||||
|
|
||||||
// Require deferred entry points
|
// Require deferred entry points
|
||||||
for (const deferredRequire of deferredRequires) {
|
for (const deferredRequire of deferredRequires) {
|
||||||
wreq!(deferredRequire as any);
|
wreq(deferredRequire);
|
||||||
}
|
}
|
||||||
|
|
||||||
// All chunks Discord has mapped to asset files, even if they are not used anymore
|
// All chunks Discord has mapped to asset files, even if they are not used anymore
|
||||||
const allChunks = [] as number[];
|
const allChunks = [] as number[];
|
||||||
|
|
||||||
// Matches "id" or id:
|
// Matches "id" or id:
|
||||||
for (const currentMatch of wreq!.u.toString().matchAll(/(?:"([\deE]+?)"(?![,}]))|(?:([\deE]+?):)/g)) {
|
for (const currentMatch of String(wreq.u).matchAll(/(?:"([\deE]+?)"(?![,}]))|(?:([\deE]+?):)/g)) {
|
||||||
const id = currentMatch[1] ?? currentMatch[2];
|
const id = currentMatch[1] ?? currentMatch[2];
|
||||||
if (id == null) continue;
|
if (id == null) continue;
|
||||||
|
|
||||||
|
@ -143,7 +136,8 @@ export async function loadLazyChunks() {
|
||||||
|
|
||||||
if (allChunks.length === 0) throw new Error("Failed to get all chunks");
|
if (allChunks.length === 0) throw new Error("Failed to get all chunks");
|
||||||
|
|
||||||
// Chunks that are not loaded (not used) by Discord code anymore
|
// Chunks which our regex could not catch to load
|
||||||
|
// It will always contain WebWorker assets, and also currently contains some language packs which are loaded differently
|
||||||
const chunksLeft = allChunks.filter(id => {
|
const chunksLeft = allChunks.filter(id => {
|
||||||
return !(validChunks.has(id) || invalidChunks.has(id));
|
return !(validChunks.has(id) || invalidChunks.has(id));
|
||||||
});
|
});
|
||||||
|
@ -153,12 +147,9 @@ export async function loadLazyChunks() {
|
||||||
.then(r => r.text())
|
.then(r => r.text())
|
||||||
.then(t => t.includes("importScripts("));
|
.then(t => t.includes("importScripts("));
|
||||||
|
|
||||||
// Loads and requires a chunk
|
// Loads the chunk. Currently this only happens with the language packs which are loaded differently
|
||||||
if (!isWorkerAsset) {
|
if (!isWorkerAsset) {
|
||||||
await wreq.e(id as any);
|
await wreq.e(id);
|
||||||
// Technically, the id of the chunk does not match the entry point
|
|
||||||
// But, still try it because we have no way to get the actual entry point
|
|
||||||
if (wreq.m[id]) wreq(id as any);
|
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
|
@ -4,22 +4,39 @@
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { SYM_LAZY_COMPONENT_INNER } from "@utils/lazyReact";
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
|
import { SYM_PROXY_INNER_GET, SYM_PROXY_INNER_VALUE } from "@utils/proxyInner";
|
||||||
import * as Webpack from "@webpack";
|
import * as Webpack from "@webpack";
|
||||||
import { patches } from "plugins";
|
import { addPatch, patches } from "plugins";
|
||||||
|
|
||||||
import { loadLazyChunks } from "./loadLazyChunks";
|
import { loadLazyChunks } from "./loadLazyChunks";
|
||||||
|
|
||||||
const ReporterLogger = new Logger("Reporter");
|
|
||||||
|
|
||||||
async function runReporter() {
|
async function runReporter() {
|
||||||
|
const ReporterLogger = new Logger("Reporter");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ReporterLogger.log("Starting test...");
|
ReporterLogger.log("Starting test...");
|
||||||
|
|
||||||
let loadLazyChunksResolve: (value: void | PromiseLike<void>) => void;
|
let loadLazyChunksResolve: (value: void) => void;
|
||||||
const loadLazyChunksDone = new Promise<void>(r => loadLazyChunksResolve = r);
|
const loadLazyChunksDone = new Promise<void>(r => loadLazyChunksResolve = r);
|
||||||
|
|
||||||
Webpack.beforeInitListeners.add(() => loadLazyChunks().then((loadLazyChunksResolve)));
|
// The main patch for starting the reporter chunk loading
|
||||||
|
addPatch({
|
||||||
|
find: '"Could not find app-mount"',
|
||||||
|
replacement: {
|
||||||
|
match: /(?<="use strict";)/,
|
||||||
|
replace: "Vencord.Webpack._initReporter();"
|
||||||
|
}
|
||||||
|
}, "Vencord Reporter");
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
Vencord.Webpack._initReporter = function () {
|
||||||
|
// initReporter is called in the patched entry point of Discord
|
||||||
|
// setImmediate to only start searching for lazy chunks after Discord initialized the app
|
||||||
|
setTimeout(() => loadLazyChunks().then(loadLazyChunksResolve), 0);
|
||||||
|
};
|
||||||
|
|
||||||
await loadLazyChunksDone;
|
await loadLazyChunksDone;
|
||||||
|
|
||||||
for (const patch of patches) {
|
for (const patch of patches) {
|
||||||
|
@ -28,52 +45,158 @@ async function runReporter() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [searchType, args] of Webpack.lazyWebpackSearchHistory) {
|
for (const [plugin, moduleId, match, totalTime] of Vencord.WebpackPatcher.patchTimings) {
|
||||||
let method = searchType;
|
if (totalTime > 3) {
|
||||||
|
new Logger("WebpackInterceptor").warn(`Patch by ${plugin} took ${totalTime}ms (Module id is ${String(moduleId)}): ${match}`);
|
||||||
if (searchType === "findComponent") method = "find";
|
|
||||||
if (searchType === "findExportedComponent") method = "findByProps";
|
|
||||||
if (searchType === "waitFor" || searchType === "waitForComponent") {
|
|
||||||
if (typeof args[0] === "string") method = "findByProps";
|
|
||||||
else method = "find";
|
|
||||||
}
|
}
|
||||||
if (searchType === "waitForStore") method = "findStore";
|
}
|
||||||
|
|
||||||
let result: any;
|
await Promise.all(Webpack.webpackSearchHistory.map(async ([searchType, args]) => {
|
||||||
|
args = [...args];
|
||||||
|
|
||||||
|
let result = null as any;
|
||||||
try {
|
try {
|
||||||
if (method === "proxyLazyWebpack" || method === "LazyComponentWebpack") {
|
switch (searchType) {
|
||||||
const [factory] = args;
|
case "webpackDependantLazy":
|
||||||
result = factory();
|
case "webpackDependantLazyComponent": {
|
||||||
} else if (method === "extractAndLoadChunks") {
|
const [factory] = args;
|
||||||
const [code, matcher] = args;
|
result = factory();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "extractAndLoadChunks": {
|
||||||
|
const extractAndLoadChunks = args.shift();
|
||||||
|
|
||||||
result = await Webpack.extractAndLoadChunks(code, matcher);
|
result = await extractAndLoadChunks();
|
||||||
if (result === false) result = null;
|
if (result === false) {
|
||||||
} else if (method === "mapMangledModule") {
|
result = null;
|
||||||
const [code, mapper] = args;
|
}
|
||||||
|
|
||||||
result = Webpack.mapMangledModule(code, mapper);
|
break;
|
||||||
if (Object.keys(result).length !== Object.keys(mapper).length) throw new Error("Webpack Find Fail");
|
}
|
||||||
} else {
|
default: {
|
||||||
// @ts-ignore
|
const findResult = args.shift();
|
||||||
result = Webpack[method](...args);
|
|
||||||
|
if (findResult != null) {
|
||||||
|
if (findResult.$$vencordCallbackCalled != null && findResult.$$vencordCallbackCalled()) {
|
||||||
|
result = findResult;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (findResult[SYM_PROXY_INNER_GET] != null) {
|
||||||
|
result = findResult[SYM_PROXY_INNER_VALUE];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (findResult[SYM_LAZY_COMPONENT_INNER] != null) {
|
||||||
|
result = findResult[SYM_LAZY_COMPONENT_INNER]();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (searchType === "mapMangledModule") {
|
||||||
|
result = findResult;
|
||||||
|
|
||||||
|
for (const innerMap in result) {
|
||||||
|
if (
|
||||||
|
(result[innerMap][SYM_PROXY_INNER_GET] != null && result[innerMap][SYM_PROXY_INNER_VALUE] == null) ||
|
||||||
|
(result[innerMap][SYM_LAZY_COMPONENT_INNER] != null && result[innerMap][SYM_LAZY_COMPONENT_INNER]() == null)
|
||||||
|
) {
|
||||||
|
throw new Error("Webpack Find Fail");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This can happen if a `find` was immediately found
|
||||||
|
result = findResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == null || (result.$$vencordInternal != null && result.$$vencordInternal() == null)) throw new Error("Webpack Find Fail");
|
if (result == null) {
|
||||||
|
throw new Error("Webpack Find Fail");
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
let logMessage = searchType;
|
let logMessage = searchType;
|
||||||
if (method === "find" || method === "proxyLazyWebpack" || method === "LazyComponentWebpack") logMessage += `(${args[0].toString().slice(0, 147)}...)`;
|
|
||||||
else if (method === "extractAndLoadChunks") logMessage += `([${args[0].map(arg => `"${arg}"`).join(", ")}], ${args[1].toString()})`;
|
|
||||||
else if (method === "mapMangledModule") {
|
|
||||||
const failedMappings = Object.keys(args[1]).filter(key => result?.[key] == null);
|
|
||||||
|
|
||||||
logMessage += `("${args[0]}", {\n${failedMappings.map(mapping => `\t${mapping}: ${args[1][mapping].toString().slice(0, 147)}...`).join(",\n")}\n})`;
|
let filterName = "";
|
||||||
|
let parsedArgs = args;
|
||||||
|
|
||||||
|
if (args[0].$$vencordProps != null) {
|
||||||
|
if (["find", "findComponent", "waitFor"].includes(searchType)) {
|
||||||
|
filterName = args[0].$$vencordProps[0];
|
||||||
|
parsedArgs = args[0].$$vencordProps.slice(1);
|
||||||
|
} else {
|
||||||
|
parsedArgs = args[0].$$vencordProps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function stringifyFilter(code: Webpack.CodeFilterWithSingle) {
|
||||||
|
if (Array.isArray(code)) {
|
||||||
|
return `[${code.map(arg => arg instanceof RegExp ? String(arg) : JSON.stringify(arg)).join(", ")}]`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return code instanceof RegExp ? String(code) : JSON.stringify(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if parsedArgs is the same as args, it means vencordProps of the filter was not available (like in normal filter functions),
|
||||||
|
// so log the filter function instead
|
||||||
|
if (
|
||||||
|
parsedArgs === args &&
|
||||||
|
["waitFor", "find", "findComponent", "webpackDependantLazy", "webpackDependantLazyComponent"].includes(searchType)
|
||||||
|
) {
|
||||||
|
let filter = String(parsedArgs[0]);
|
||||||
|
if (filter.length > 150) {
|
||||||
|
filter = filter.slice(0, 147) + "...";
|
||||||
|
}
|
||||||
|
|
||||||
|
logMessage += `(${filter})`;
|
||||||
|
} else if (searchType === "extractAndLoadChunks") {
|
||||||
|
const [code, matcher] = parsedArgs;
|
||||||
|
|
||||||
|
let regexStr: string;
|
||||||
|
if (matcher === Webpack.DefaultExtractAndLoadChunksRegex) {
|
||||||
|
regexStr = "DefaultExtractAndLoadChunksRegex";
|
||||||
|
} else {
|
||||||
|
regexStr = String(matcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
logMessage += `(${stringifyFilter(code)}, ${regexStr})`;
|
||||||
|
} else if (searchType === "mapMangledModule") {
|
||||||
|
const [code, mappers] = parsedArgs;
|
||||||
|
|
||||||
|
const parsedFailedMappers = Object.entries<any>(mappers)
|
||||||
|
.filter(([key]) =>
|
||||||
|
result == null ||
|
||||||
|
(result[key]?.[SYM_PROXY_INNER_GET] != null && result[key][SYM_PROXY_INNER_VALUE] == null) ||
|
||||||
|
(result[key]?.[SYM_LAZY_COMPONENT_INNER] != null && result[key][SYM_LAZY_COMPONENT_INNER]() == null)
|
||||||
|
)
|
||||||
|
.map(([key, filter]) => {
|
||||||
|
let parsedFilter: string;
|
||||||
|
|
||||||
|
if (filter.$$vencordProps != null) {
|
||||||
|
const filterName = filter.$$vencordProps[0];
|
||||||
|
parsedFilter = `${filterName}(${filter.$$vencordProps.slice(1).map((arg: any) => arg instanceof RegExp ? String(arg) : JSON.stringify(arg)).join(", ")})`;
|
||||||
|
} else {
|
||||||
|
parsedFilter = String(filter);
|
||||||
|
if (parsedFilter.length > 150) {
|
||||||
|
parsedFilter = parsedFilter.slice(0, 147) + "...";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [key, parsedFilter];
|
||||||
|
});
|
||||||
|
|
||||||
|
logMessage += `(${stringifyFilter(code)}, {\n${parsedFailedMappers.map(([key, parsedFilter]) => `\t${key}: ${parsedFilter}`).join(",\n")}\n})`;
|
||||||
|
} else {
|
||||||
|
logMessage += `(${filterName.length ? `${filterName}(` : ""}${parsedArgs.map(stringifyFilter).join(", ")})${filterName.length ? ")" : ""}`;
|
||||||
}
|
}
|
||||||
else logMessage += `(${args.map(arg => `"${arg}"`).join(", ")})`;
|
|
||||||
|
|
||||||
ReporterLogger.log("Webpack Find Fail:", logMessage);
|
ReporterLogger.log("Webpack Find Fail:", logMessage);
|
||||||
}
|
}
|
||||||
}
|
}));
|
||||||
|
|
||||||
ReporterLogger.log("Finished test");
|
ReporterLogger.log("Finished test");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -81,4 +204,5 @@ async function runReporter() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
runReporter();
|
// Run after the Vencord object has been created
|
||||||
|
setTimeout(runReporter, 0);
|
||||||
|
|
11
src/globals.d.ts
vendored
11
src/globals.d.ts
vendored
|
@ -19,6 +19,10 @@
|
||||||
import { LoDashStatic } from "lodash";
|
import { LoDashStatic } from "lodash";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
type AnyRecord = Record<PropertyKey, any>;
|
||||||
|
type AnyComponentType<P extends AnyRecord = AnyRecord> = React.ComponentType<P & AnyRecord> & AnyRecord;
|
||||||
|
type AnyComponentTypeWithChildren<P extends AnyRecord = AnyRecord> = AnyComponentType<React.PropsWithChildren<P>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This exists only at build time, so references to it in patches should insert it
|
* This exists only at build time, so references to it in patches should insert it
|
||||||
* via String interpolation OR use different replacement code based on this
|
* via String interpolation OR use different replacement code based on this
|
||||||
|
@ -64,13 +68,8 @@ declare global {
|
||||||
export var Vesktop: any;
|
export var Vesktop: any;
|
||||||
export var VesktopNative: any;
|
export var VesktopNative: any;
|
||||||
|
|
||||||
interface Window {
|
interface Window extends AnyRecord {
|
||||||
webpackChunkdiscord_app: {
|
|
||||||
push(chunk: any): any;
|
|
||||||
pop(): any;
|
|
||||||
};
|
|
||||||
_: LoDashStatic;
|
_: LoDashStatic;
|
||||||
[k: string]: any;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ import { definePluginSettings } from "@api/Settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
import definePlugin, { OptionType, StartAt } from "@utils/types";
|
import definePlugin, { OptionType, StartAt } from "@utils/types";
|
||||||
|
import { WebpackRequire } from "webpack";
|
||||||
|
|
||||||
const settings = definePluginSettings({
|
const settings = definePluginSettings({
|
||||||
disableAnalytics: {
|
disableAnalytics: {
|
||||||
|
@ -81,9 +82,9 @@ export default definePlugin({
|
||||||
Object.defineProperty(Function.prototype, "g", {
|
Object.defineProperty(Function.prototype, "g", {
|
||||||
configurable: true,
|
configurable: true,
|
||||||
|
|
||||||
set(v: any) {
|
set(this: WebpackRequire, globalObj: WebpackRequire["g"]) {
|
||||||
Object.defineProperty(this, "g", {
|
Object.defineProperty(this, "g", {
|
||||||
value: v,
|
value: globalObj,
|
||||||
configurable: true,
|
configurable: true,
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
writable: true
|
writable: true
|
||||||
|
@ -92,11 +93,11 @@ export default definePlugin({
|
||||||
// Ensure this is most likely the Sentry WebpackInstance.
|
// Ensure this is most likely the Sentry WebpackInstance.
|
||||||
// Function.g is a very generic property and is not uncommon for another WebpackInstance (or even a React component: <g></g>) to include it
|
// Function.g is a very generic property and is not uncommon for another WebpackInstance (or even a React component: <g></g>) to include it
|
||||||
const { stack } = new Error();
|
const { stack } = new Error();
|
||||||
if (!(stack?.includes("discord.com") || stack?.includes("discordapp.com")) || !String(this).includes("exports:{}") || this.c != null) {
|
if (this.c != null || !stack?.includes("http") || !String(this).includes("exports:{}")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const assetPath = stack?.match(/\/assets\/.+?\.js/)?.[0];
|
const assetPath = stack.match(/http.+?(?=:\d+?:\d+?$)/m)?.[0];
|
||||||
if (!assetPath) {
|
if (!assetPath) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -106,7 +107,8 @@ export default definePlugin({
|
||||||
srcRequest.send();
|
srcRequest.send();
|
||||||
|
|
||||||
// Final condition to see if this is the Sentry WebpackInstance
|
// Final condition to see if this is the Sentry WebpackInstance
|
||||||
if (!srcRequest.responseText.includes("window.DiscordSentry=")) {
|
// This is matching window.DiscordSentry=, but without `window` to avoid issues on some proxies
|
||||||
|
if (!srcRequest.responseText.includes(".DiscordSentry=")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Settings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import BackupAndRestoreTab from "@components/VencordSettings/BackupAndRestoreTab";
|
import BackupAndRestoreTab from "@components/VencordSettings/BackupAndRestoreTab";
|
||||||
import CloudTab from "@components/VencordSettings/CloudTab";
|
import CloudTab from "@components/VencordSettings/CloudTab";
|
||||||
import PatchHelperTab from "@components/VencordSettings/PatchHelperTab";
|
import PatchHelperTab from "@components/VencordSettings/PatchHelperTab";
|
||||||
|
@ -33,11 +33,27 @@ import gitHash from "~git-hash";
|
||||||
type SectionType = "HEADER" | "DIVIDER" | "CUSTOM";
|
type SectionType = "HEADER" | "DIVIDER" | "CUSTOM";
|
||||||
type SectionTypes = Record<SectionType, SectionType>;
|
type SectionTypes = Record<SectionType, SectionType>;
|
||||||
|
|
||||||
|
const settings = definePluginSettings({
|
||||||
|
settingsLocation: {
|
||||||
|
type: OptionType.SELECT,
|
||||||
|
description: "Where to put the Vencord settings section",
|
||||||
|
options: [
|
||||||
|
{ label: "At the very top", value: "top" },
|
||||||
|
{ label: "Above the Nitro section", value: "aboveNitro", default: true },
|
||||||
|
{ label: "Below the Nitro section", value: "belowNitro" },
|
||||||
|
{ label: "Above Activity Settings", value: "aboveActivity" },
|
||||||
|
{ label: "Below Activity Settings", value: "belowActivity" },
|
||||||
|
{ label: "At the very bottom", value: "bottom" },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "Settings",
|
name: "Settings",
|
||||||
description: "Adds Settings UI and debug info",
|
description: "Adds Settings UI and debug info",
|
||||||
authors: [Devs.Ven, Devs.Megu],
|
authors: [Devs.Ven, Devs.Megu],
|
||||||
required: true,
|
required: true,
|
||||||
|
settings,
|
||||||
|
|
||||||
patches: [
|
patches: [
|
||||||
{
|
{
|
||||||
|
@ -136,12 +152,12 @@ export default definePlugin({
|
||||||
].filter(Boolean);
|
].filter(Boolean);
|
||||||
},
|
},
|
||||||
|
|
||||||
isRightSpot({ header, settings }: { header?: string; settings?: string[]; }) {
|
isRightSpot({ header, settingsChilds }: { header?: string; settingsChilds?: string[]; }) {
|
||||||
const firstChild = settings?.[0];
|
const firstChild = settingsChilds?.[0];
|
||||||
// lowest two elements... sanity backup
|
// lowest two elements... sanity backup
|
||||||
if (firstChild === "LOGOUT" || firstChild === "SOCIAL_LINKS") return true;
|
if (firstChild === "LOGOUT" || firstChild === "SOCIAL_LINKS") return true;
|
||||||
|
|
||||||
const { settingsLocation } = Settings.plugins.Settings;
|
const { settingsLocation } = settings.store;
|
||||||
|
|
||||||
if (settingsLocation === "bottom") return firstChild === "LOGOUT";
|
if (settingsLocation === "bottom") return firstChild === "LOGOUT";
|
||||||
if (settingsLocation === "belowActivity") return firstChild === "CHANGELOG";
|
if (settingsLocation === "belowActivity") return firstChild === "CHANGELOG";
|
||||||
|
@ -181,21 +197,6 @@ export default definePlugin({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
options: {
|
|
||||||
settingsLocation: {
|
|
||||||
type: OptionType.SELECT,
|
|
||||||
description: "Where to put the Vencord settings section",
|
|
||||||
options: [
|
|
||||||
{ label: "At the very top", value: "top" },
|
|
||||||
{ label: "Above the Nitro section", value: "aboveNitro", default: true },
|
|
||||||
{ label: "Below the Nitro section", value: "belowNitro" },
|
|
||||||
{ label: "Above Activity Settings", value: "aboveActivity" },
|
|
||||||
{ label: "Below Activity Settings", value: "belowActivity" },
|
|
||||||
{ label: "At the very bottom", value: "bottom" },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
get electronVersion() {
|
get electronVersion() {
|
||||||
return VencordNative.native.getVersions().electron || window.armcord?.electron || null;
|
return VencordNative.native.getVersions().electron || window.armcord?.electron || null;
|
||||||
},
|
},
|
||||||
|
|
|
@ -59,7 +59,7 @@ const TrustedRolesIds = [
|
||||||
|
|
||||||
const AsyncFunction = async function () { }.constructor;
|
const AsyncFunction = async function () { }.constructor;
|
||||||
|
|
||||||
const ShowCurrentGame = getUserSettingLazy<boolean>("status", "showCurrentGame")!;
|
const ShowCurrentGame = getUserSettingLazy<boolean>("status", "showCurrentGame");
|
||||||
|
|
||||||
async function forceUpdate() {
|
async function forceUpdate() {
|
||||||
const outdated = await checkForUpdates();
|
const outdated = await checkForUpdates();
|
||||||
|
|
|
@ -9,7 +9,7 @@ import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { getCurrentChannel } from "@utils/discord";
|
import { getCurrentChannel } from "@utils/discord";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByPropsLazy, findComponentByCodeLazy } from "@webpack";
|
import { findByProps, findComponentByCode } from "@webpack";
|
||||||
import { ContextMenuApi, Menu, useEffect, useRef } from "@webpack/common";
|
import { ContextMenuApi, Menu, useEffect, useRef } from "@webpack/common";
|
||||||
import { User } from "discord-types/general";
|
import { User } from "discord-types/general";
|
||||||
|
|
||||||
|
@ -19,11 +19,11 @@ interface UserProfileProps {
|
||||||
originalPopout: () => React.ReactNode;
|
originalPopout: () => React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const UserProfile = findComponentByCodeLazy("UserProfilePopoutWrapper: user cannot be undefined");
|
const UserProfile = findComponentByCode("UserProfilePopoutWrapper: user cannot be undefined");
|
||||||
const styles = findByPropsLazy("accountProfilePopoutWrapper");
|
const styles = findByProps("accountProfilePopoutWrapper");
|
||||||
|
|
||||||
let openAlternatePopout = false;
|
let openAlternatePopout = false;
|
||||||
let accountPanelRef: React.MutableRefObject<Record<PropertyKey, any> | null> = { current: null };
|
let accountPanelRef: React.MutableRefObject<AnyRecord | null> = { current: null };
|
||||||
|
|
||||||
const AccountPanelContextMenu = ErrorBoundary.wrap(() => {
|
const AccountPanelContextMenu = ErrorBoundary.wrap(() => {
|
||||||
const { prioritizeServerProfile } = settings.use(["prioritizeServerProfile"]);
|
const { prioritizeServerProfile } = settings.use(["prioritizeServerProfile"]);
|
||||||
|
|
|
@ -21,12 +21,12 @@ import { definePluginSettings } from "@api/Settings";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByCodeLazy, findByPropsLazy } from "@webpack";
|
import { findByProps, findComponentByCode } from "@webpack";
|
||||||
|
|
||||||
type AnonUpload = Upload & { anonymise?: boolean; };
|
type AnonUpload = Upload & { anonymise?: boolean; };
|
||||||
|
|
||||||
const ActionBarIcon = findByCodeLazy(".actionBarIcon)");
|
const ActionBarIcon = findComponentByCode(".actionBarIcon)");
|
||||||
const UploadDraft = findByPropsLazy("popFirstFile", "update");
|
const UploadDraft = findByProps("popFirstFile", "update");
|
||||||
|
|
||||||
const enum Methods {
|
const enum Methods {
|
||||||
Random,
|
Random,
|
||||||
|
|
|
@ -20,10 +20,10 @@ import { popNotice, showNotice } from "@api/Notices";
|
||||||
import { Link } from "@components/Link";
|
import { Link } from "@components/Link";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { ReporterTestable } from "@utils/types";
|
import definePlugin, { ReporterTestable } from "@utils/types";
|
||||||
import { findByCodeLazy } from "@webpack";
|
import { findByCode } from "@webpack";
|
||||||
import { ApplicationAssetUtils, FluxDispatcher, Forms, Toasts } from "@webpack/common";
|
import { ApplicationAssetUtils, FluxDispatcher, Forms, Toasts } from "@webpack/common";
|
||||||
|
|
||||||
const fetchApplicationsRPC = findByCodeLazy("APPLICATION_RPC(", "Client ID");
|
const fetchApplicationsRPC = findByCode("APPLICATION_RPC(", "Client ID");
|
||||||
|
|
||||||
async function lookupAsset(applicationId: string, key: string): Promise<string> {
|
async function lookupAsset(applicationId: string, key: string): Promise<string> {
|
||||||
return (await ApplicationAssetUtils.fetchAssetIds(applicationId, [key]))[0];
|
return (await ApplicationAssetUtils.fetchAssetIds(applicationId, [key]))[0];
|
||||||
|
|
|
@ -17,15 +17,15 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { findByPropsLazy, findComponentByCodeLazy, findStoreLazy } from "@webpack";
|
import { findByProps, findComponentByCode, findStore } from "@webpack";
|
||||||
import { useStateFromStores } from "@webpack/common";
|
import { useStateFromStores } from "@webpack/common";
|
||||||
import type { CSSProperties } from "react";
|
import type { CSSProperties } from "react";
|
||||||
|
|
||||||
import { ExpandedGuildFolderStore, settings } from ".";
|
import { ExpandedGuildFolderStore, settings } from ".";
|
||||||
|
|
||||||
const ChannelRTCStore = findStoreLazy("ChannelRTCStore");
|
const ChannelRTCStore = findStore("ChannelRTCStore");
|
||||||
const Animations = findByPropsLazy("a", "animated", "useTransition");
|
const Animations = findByProps("a", "animated", "useTransition");
|
||||||
const GuildsBar = findComponentByCodeLazy('("guildsnav")');
|
const GuildsBar = findComponentByCode('("guildsnav")');
|
||||||
|
|
||||||
export default ErrorBoundary.wrap(guildsBarProps => {
|
export default ErrorBoundary.wrap(guildsBarProps => {
|
||||||
const expandedFolders = useStateFromStores([ExpandedGuildFolderStore], () => ExpandedGuildFolderStore.getExpandedFolders());
|
const expandedFolders = useStateFromStores([ExpandedGuildFolderStore], () => ExpandedGuildFolderStore.getExpandedFolders());
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByPropsLazy, findLazy, findStoreLazy } from "@webpack";
|
import { find, findByProps, findStore } from "@webpack";
|
||||||
import { FluxDispatcher, i18n, useMemo } from "@webpack/common";
|
import { FluxDispatcher, i18n, useMemo } from "@webpack/common";
|
||||||
|
|
||||||
import FolderSideBar from "./FolderSideBar";
|
import FolderSideBar from "./FolderSideBar";
|
||||||
|
@ -30,10 +30,10 @@ enum FolderIconDisplay {
|
||||||
MoreThanOneFolderExpanded
|
MoreThanOneFolderExpanded
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ExpandedGuildFolderStore = findStoreLazy("ExpandedGuildFolderStore");
|
export const ExpandedGuildFolderStore = findStore("ExpandedGuildFolderStore");
|
||||||
const SortedGuildStore = findStoreLazy("SortedGuildStore");
|
const SortedGuildStore = findStore("SortedGuildStore");
|
||||||
const GuildsTree = findLazy(m => m.prototype?.moveNextTo);
|
const GuildsTree = find(m => m.prototype?.moveNextTo);
|
||||||
const FolderUtils = findByPropsLazy("move", "toggleGuildFolderExpand");
|
const FolderUtils = findByProps("move", "toggleGuildFolderExpand");
|
||||||
|
|
||||||
let lastGuildId = null as string | null;
|
let lastGuildId = null as string | null;
|
||||||
let dispatchingFoldersClose = false;
|
let dispatchingFoldersClose = false;
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { definePluginSettings, Settings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { canonicalizeMatch } from "@utils/patches";
|
import { canonicalizeMatch } from "@utils/patches";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
|
@ -31,7 +31,7 @@ const settings = definePluginSettings({
|
||||||
noSpellCheck: {
|
noSpellCheck: {
|
||||||
type: OptionType.BOOLEAN,
|
type: OptionType.BOOLEAN,
|
||||||
description: "Disable spellcheck in notes",
|
description: "Disable spellcheck in notes",
|
||||||
disabled: () => Settings.plugins.BetterNotesBox.hide,
|
disabled: () => settings.store.hide,
|
||||||
default: false
|
default: false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,12 +10,12 @@ import { ImageIcon } from "@components/Icons";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { getCurrentGuild, openImageModal } from "@utils/discord";
|
import { getCurrentGuild, openImageModal } from "@utils/discord";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findByProps } from "@webpack";
|
||||||
import { Clipboard, GuildStore, Menu, PermissionStore } from "@webpack/common";
|
import { Clipboard, GuildStore, Menu, PermissionStore } from "@webpack/common";
|
||||||
|
|
||||||
const GuildSettingsActions = findByPropsLazy("open", "selectRole", "updateGuild");
|
const GuildSettingsActions = findByProps("open", "selectRole", "updateGuild");
|
||||||
|
|
||||||
const DeveloperMode = getUserSettingLazy("appearance", "developerMode")!;
|
const DeveloperMode = getUserSettingLazy("appearance", "developerMode");
|
||||||
|
|
||||||
function PencilIcon() {
|
function PencilIcon() {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -16,16 +16,32 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Settings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { Clipboard, Toasts } from "@webpack/common";
|
import { Clipboard, Toasts } from "@webpack/common";
|
||||||
|
|
||||||
|
const settings = definePluginSettings({
|
||||||
|
bothStyles: {
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
description: "Show both role dot and coloured names",
|
||||||
|
restartNeeded: true,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
copyRoleColorInProfilePopout: {
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
description: "Allow click on role dot in profile popout to copy role color",
|
||||||
|
restartNeeded: true,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "BetterRoleDot",
|
name: "BetterRoleDot",
|
||||||
authors: [Devs.Ven, Devs.AutumnVN],
|
authors: [Devs.Ven, Devs.AutumnVN],
|
||||||
description:
|
description:
|
||||||
"Copy role colour on RoleDot (accessibility setting) click. Also allows using both RoleDot and coloured names simultaneously",
|
"Copy role colour on RoleDot (accessibility setting) click. Also allows using both RoleDot and coloured names simultaneously",
|
||||||
|
settings,
|
||||||
|
|
||||||
patches: [
|
patches: [
|
||||||
{
|
{
|
||||||
|
@ -39,7 +55,7 @@ export default definePlugin({
|
||||||
find: '"dot"===',
|
find: '"dot"===',
|
||||||
all: true,
|
all: true,
|
||||||
noWarn: true,
|
noWarn: true,
|
||||||
predicate: () => Settings.plugins.BetterRoleDot.bothStyles,
|
predicate: () => settings.store.bothStyles,
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /"(?:username|dot)"===\i(?!\.\i)/g,
|
match: /"(?:username|dot)"===\i(?!\.\i)/g,
|
||||||
replace: "true",
|
replace: "true",
|
||||||
|
@ -49,7 +65,7 @@ export default definePlugin({
|
||||||
{
|
{
|
||||||
find: ".ADD_ROLE_A11Y_LABEL",
|
find: ".ADD_ROLE_A11Y_LABEL",
|
||||||
all: true,
|
all: true,
|
||||||
predicate: () => Settings.plugins.BetterRoleDot.copyRoleColorInProfilePopout && !Settings.plugins.BetterRoleDot.bothStyles,
|
predicate: () => settings.store.copyRoleColorInProfilePopout && !settings.store.bothStyles,
|
||||||
noWarn: true,
|
noWarn: true,
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /"dot"===\i/,
|
match: /"dot"===\i/,
|
||||||
|
@ -59,7 +75,7 @@ export default definePlugin({
|
||||||
{
|
{
|
||||||
find: ".roleVerifiedIcon",
|
find: ".roleVerifiedIcon",
|
||||||
all: true,
|
all: true,
|
||||||
predicate: () => Settings.plugins.BetterRoleDot.copyRoleColorInProfilePopout && !Settings.plugins.BetterRoleDot.bothStyles,
|
predicate: () => settings.store.copyRoleColorInProfilePopout && !settings.store.bothStyles,
|
||||||
noWarn: true,
|
noWarn: true,
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /"dot"===\i/,
|
match: /"dot"===\i/,
|
||||||
|
@ -68,21 +84,6 @@ export default definePlugin({
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
options: {
|
|
||||||
bothStyles: {
|
|
||||||
type: OptionType.BOOLEAN,
|
|
||||||
description: "Show both role dot and coloured names",
|
|
||||||
restartNeeded: true,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
copyRoleColorInProfilePopout: {
|
|
||||||
type: OptionType.BOOLEAN,
|
|
||||||
description: "Allow click on role dot in profile popout to copy role color",
|
|
||||||
restartNeeded: true,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
copyToClipBoard(color: string) {
|
copyToClipBoard(color: string) {
|
||||||
Clipboard.copy(color);
|
Clipboard.copy(color);
|
||||||
Toasts.show({
|
Toasts.show({
|
||||||
|
|
|
@ -21,20 +21,20 @@ import { definePluginSettings } from "@api/Settings";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByPropsLazy, findExportedComponentLazy, findStoreLazy } from "@webpack";
|
import { findByProps, findExportedComponent, findStore } from "@webpack";
|
||||||
import { Constants, React, RestAPI, Tooltip } from "@webpack/common";
|
import { Constants, React, RestAPI, Tooltip } from "@webpack/common";
|
||||||
|
|
||||||
import { RenameButton } from "./components/RenameButton";
|
import { RenameButton } from "./components/RenameButton";
|
||||||
import { Session, SessionInfo } from "./types";
|
import { Session, SessionInfo } from "./types";
|
||||||
import { fetchNamesFromDataStore, getDefaultName, GetOsColor, GetPlatformIcon, savedSessionsCache, saveSessionsToDataStore } from "./utils";
|
import { fetchNamesFromDataStore, getDefaultName, GetOsColor, GetPlatformIcon, savedSessionsCache, saveSessionsToDataStore } from "./utils";
|
||||||
|
|
||||||
const AuthSessionsStore = findStoreLazy("AuthSessionsStore");
|
const AuthSessionsStore = findStore("AuthSessionsStore");
|
||||||
const UserSettingsModal = findByPropsLazy("saveAccountChanges", "open");
|
const UserSettingsModal = findByProps("saveAccountChanges", "open");
|
||||||
|
|
||||||
const TimestampClasses = findByPropsLazy("timestampTooltip", "blockquoteContainer");
|
const TimestampClasses = findByProps("timestampTooltip", "blockquoteContainer");
|
||||||
const SessionIconClasses = findByPropsLazy("sessionIcon");
|
const SessionIconClasses = findByProps("sessionIcon");
|
||||||
|
|
||||||
const BlobMask = findExportedComponentLazy("BlobMask");
|
const BlobMask = findExportedComponent("BlobMask");
|
||||||
|
|
||||||
const settings = definePluginSettings({
|
const settings = definePluginSettings({
|
||||||
backgroundCheck: {
|
backgroundCheck: {
|
||||||
|
|
|
@ -8,8 +8,10 @@ import { definePluginSettings } from "@api/Settings";
|
||||||
import { classNameFactory } from "@api/Styles";
|
import { classNameFactory } from "@api/Styles";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
|
import { SYM_PROXY_INNER_VALUE } from "@utils/proxyInner";
|
||||||
|
import { NoopComponent } from "@utils/react";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { waitFor } from "@webpack";
|
import { findByProps } from "@webpack";
|
||||||
import { ComponentDispatch, FocusLock, i18n, Menu, useEffect, useRef } from "@webpack/common";
|
import { ComponentDispatch, FocusLock, i18n, Menu, useEffect, useRef } from "@webpack/common";
|
||||||
import type { HTMLAttributes, ReactElement } from "react";
|
import type { HTMLAttributes, ReactElement } from "react";
|
||||||
|
|
||||||
|
@ -18,8 +20,7 @@ import PluginsSubmenu from "./PluginsSubmenu";
|
||||||
type SettingsEntry = { section: string, label: string; };
|
type SettingsEntry = { section: string, label: string; };
|
||||||
|
|
||||||
const cl = classNameFactory("");
|
const cl = classNameFactory("");
|
||||||
let Classes: Record<string, string>;
|
const Classes = findByProps("animating", "baseLayer", "bg", "layer", "layers");
|
||||||
waitFor(["animating", "baseLayer", "bg", "layer", "layers"], m => Classes = m);
|
|
||||||
|
|
||||||
const settings = definePluginSettings({
|
const settings = definePluginSettings({
|
||||||
disableFade: {
|
disableFade: {
|
||||||
|
@ -142,7 +143,7 @@ export default definePlugin({
|
||||||
// try catch will only catch errors in the Layer function (hence why it's called as a plain function rather than a component), but
|
// try catch will only catch errors in the Layer function (hence why it's called as a plain function rather than a component), but
|
||||||
// not in children
|
// not in children
|
||||||
Layer(props: LayerProps) {
|
Layer(props: LayerProps) {
|
||||||
if (!FocusLock || !ComponentDispatch || !Classes) {
|
if (FocusLock === NoopComponent || ComponentDispatch[SYM_PROXY_INNER_VALUE] == null || Classes[SYM_PROXY_INNER_VALUE] == null) {
|
||||||
new Logger("BetterSettings").error("Failed to find some components");
|
new Logger("BetterSettings").error("Failed to find some components");
|
||||||
return props.children;
|
return props.children;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { findStoreLazy } from "@webpack";
|
import { findStore } from "@webpack";
|
||||||
|
|
||||||
import * as t from "./types/stores";
|
import * as t from "./types/stores";
|
||||||
|
|
||||||
export const ApplicationStreamPreviewStore: t.ApplicationStreamPreviewStore = findStoreLazy("ApplicationStreamPreviewStore");
|
export const ApplicationStreamPreviewStore: t.ApplicationStreamPreviewStore = findStore("ApplicationStreamPreviewStore");
|
||||||
export const ApplicationStreamingStore: t.ApplicationStreamingStore = findStoreLazy("ApplicationStreamingStore");
|
export const ApplicationStreamingStore: t.ApplicationStreamingStore = findStore("ApplicationStreamingStore");
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Settings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ function setCss() {
|
||||||
style.textContent = `
|
style.textContent = `
|
||||||
.vc-nsfw-img [class^=imageWrapper] img,
|
.vc-nsfw-img [class^=imageWrapper] img,
|
||||||
.vc-nsfw-img [class^=wrapperPaused] video {
|
.vc-nsfw-img [class^=wrapperPaused] video {
|
||||||
filter: blur(${Settings.plugins.BlurNSFW.blurAmount}px);
|
filter: blur(${settings.store.blurAmount}px);
|
||||||
transition: filter 0.2s;
|
transition: filter 0.2s;
|
||||||
}
|
}
|
||||||
.vc-nsfw-img [class^=imageWrapper]:hover img,
|
.vc-nsfw-img [class^=imageWrapper]:hover img,
|
||||||
|
@ -36,10 +36,20 @@ function setCss() {
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const settings = definePluginSettings({
|
||||||
|
blurAmount: {
|
||||||
|
type: OptionType.NUMBER,
|
||||||
|
description: "Blur Amount",
|
||||||
|
default: 10,
|
||||||
|
onChange: setCss
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "BlurNSFW",
|
name: "BlurNSFW",
|
||||||
description: "Blur attachments in NSFW channels until hovered",
|
description: "Blur attachments in NSFW channels until hovered",
|
||||||
authors: [Devs.Ven],
|
authors: [Devs.Ven],
|
||||||
|
settings,
|
||||||
|
|
||||||
patches: [
|
patches: [
|
||||||
{
|
{
|
||||||
|
@ -51,15 +61,6 @@ export default definePlugin({
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
options: {
|
|
||||||
blurAmount: {
|
|
||||||
type: OptionType.NUMBER,
|
|
||||||
description: "Blur Amount",
|
|
||||||
default: 10,
|
|
||||||
onChange: setCss
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
style = document.createElement("style");
|
style = document.createElement("style");
|
||||||
style.id = "VcBlurNsfw";
|
style.id = "VcBlurNsfw";
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Settings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { useTimer } from "@utils/react";
|
import { useTimer } from "@utils/react";
|
||||||
|
@ -25,7 +25,7 @@ import { React } from "@webpack/common";
|
||||||
|
|
||||||
function formatDuration(ms: number) {
|
function formatDuration(ms: number) {
|
||||||
// here be dragons (moment fucking sucks)
|
// here be dragons (moment fucking sucks)
|
||||||
const human = Settings.plugins.CallTimer.format === "human";
|
const human = settings.store.format === "human";
|
||||||
|
|
||||||
const format = (n: number) => human ? n : n.toString().padStart(2, "0");
|
const format = (n: number) => human ? n : n.toString().padStart(2, "0");
|
||||||
const unit = (s: string) => human ? s : "";
|
const unit = (s: string) => human ? s : "";
|
||||||
|
@ -46,32 +46,33 @@ function formatDuration(ms: number) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const settings = definePluginSettings({
|
||||||
|
format: {
|
||||||
|
type: OptionType.SELECT,
|
||||||
|
description: "The timer format. This can be any valid moment.js format",
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: "30d 23:00:42",
|
||||||
|
value: "stopwatch",
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "30d 23h 00m 42s",
|
||||||
|
value: "human"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "CallTimer",
|
name: "CallTimer",
|
||||||
description: "Adds a timer to vcs",
|
description: "Adds a timer to vcs",
|
||||||
authors: [Devs.Ven],
|
authors: [Devs.Ven],
|
||||||
|
settings,
|
||||||
|
|
||||||
startTime: 0,
|
startTime: 0,
|
||||||
interval: void 0 as NodeJS.Timeout | undefined,
|
interval: void 0 as NodeJS.Timeout | undefined,
|
||||||
|
|
||||||
options: {
|
|
||||||
format: {
|
|
||||||
type: OptionType.SELECT,
|
|
||||||
description: "The timer format. This can be any valid moment.js format",
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
label: "30d 23:00:42",
|
|
||||||
value: "stopwatch",
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "30d 23h 00m 42s",
|
|
||||||
value: "human"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
patches: [{
|
patches: [{
|
||||||
find: "renderConnectionStatus(){",
|
find: "renderConnectionStatus(){",
|
||||||
replacement: {
|
replacement: {
|
||||||
|
|
|
@ -11,10 +11,10 @@ import { Devs } from "@utils/constants";
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
import { classes } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import definePlugin, { OptionType, StartAt } from "@utils/types";
|
import definePlugin, { OptionType, StartAt } from "@utils/types";
|
||||||
import { findByCodeLazy, findComponentByCodeLazy, findStoreLazy } from "@webpack";
|
import { findByCode, findComponentByCode, findStore } from "@webpack";
|
||||||
import { Button, Forms, ThemeStore, useStateFromStores } from "@webpack/common";
|
import { Button, Forms, ThemeStore, useStateFromStores } from "@webpack/common";
|
||||||
|
|
||||||
const ColorPicker = findComponentByCodeLazy(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR", ".BACKGROUND_PRIMARY)");
|
const ColorPicker = findComponentByCode(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR", ".BACKGROUND_PRIMARY)");
|
||||||
|
|
||||||
const colorPresets = [
|
const colorPresets = [
|
||||||
"#1E1514", "#172019", "#13171B", "#1C1C28", "#402D2D",
|
"#1E1514", "#172019", "#13171B", "#1C1C28", "#402D2D",
|
||||||
|
@ -30,20 +30,20 @@ function onPickColor(color: number) {
|
||||||
updateColorVars(hexColor);
|
updateColorVars(hexColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
const saveClientTheme = findByCodeLazy('type:"UNSYNCED_USER_SETTINGS_UPDATE', '"system"===');
|
const saveClientTheme = findByCode('type:"UNSYNCED_USER_SETTINGS_UPDATE', '"system"===');
|
||||||
|
|
||||||
function setTheme(theme: string) {
|
function setTheme(theme: string) {
|
||||||
saveClientTheme({ theme });
|
saveClientTheme({ theme });
|
||||||
}
|
}
|
||||||
|
|
||||||
const NitroThemeStore = findStoreLazy("ClientThemesBackgroundStore");
|
const ClientThemesBackgroundStore = findStore("ClientThemesBackgroundStore");
|
||||||
|
|
||||||
function ThemeSettings() {
|
function ThemeSettings() {
|
||||||
const theme = useStateFromStores([ThemeStore], () => ThemeStore.theme);
|
const theme = useStateFromStores([ThemeStore], () => ThemeStore.theme);
|
||||||
const isLightTheme = theme === "light";
|
const isLightTheme = theme === "light";
|
||||||
const oppositeTheme = isLightTheme ? "dark" : "light";
|
const oppositeTheme = isLightTheme ? "dark" : "light";
|
||||||
|
|
||||||
const nitroTheme = useStateFromStores([NitroThemeStore], () => NitroThemeStore.gradientPreset);
|
const nitroTheme = useStateFromStores([ClientThemesBackgroundStore], () => ClientThemesBackgroundStore.gradientPreset);
|
||||||
const nitroThemeEnabled = nitroTheme !== undefined;
|
const nitroThemeEnabled = nitroTheme !== undefined;
|
||||||
|
|
||||||
const selectedLuminance = relativeLuminance(settings.store.color);
|
const selectedLuminance = relativeLuminance(settings.store.color);
|
||||||
|
|
|
@ -19,40 +19,43 @@
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { getCurrentChannel, getCurrentGuild } from "@utils/discord";
|
import { getCurrentChannel, getCurrentGuild } from "@utils/discord";
|
||||||
import { SYM_LAZY_CACHED, SYM_LAZY_GET } from "@utils/lazy";
|
import { SYM_LAZY_CACHED, SYM_LAZY_GET } from "@utils/lazy";
|
||||||
|
import { SYM_LAZY_COMPONENT_INNER } from "@utils/lazyReact";
|
||||||
import { relaunch } from "@utils/native";
|
import { relaunch } from "@utils/native";
|
||||||
import { canonicalizeMatch, canonicalizeReplace, canonicalizeReplacement } from "@utils/patches";
|
import { canonicalizeMatch, canonicalizeReplace, canonicalizeReplacement } from "@utils/patches";
|
||||||
|
import { SYM_PROXY_INNER_GET, SYM_PROXY_INNER_VALUE } from "@utils/proxyInner";
|
||||||
import definePlugin, { PluginNative, StartAt } from "@utils/types";
|
import definePlugin, { PluginNative, StartAt } from "@utils/types";
|
||||||
import * as Webpack from "@webpack";
|
import * as Webpack from "@webpack";
|
||||||
import { extract, filters, findAll, findModuleId, search } from "@webpack";
|
import { cacheFindAll, cacheFindModuleId, extract, filters, searchFactories } from "@webpack";
|
||||||
import * as Common from "@webpack/common";
|
import * as Common from "@webpack/common";
|
||||||
import { loadLazyChunks } from "debug/loadLazyChunks";
|
import { loadLazyChunks } from "debug/loadLazyChunks";
|
||||||
import type { ComponentType } from "react";
|
|
||||||
|
|
||||||
const DESKTOP_ONLY = (f: string) => () => {
|
const DESKTOP_ONLY = (f: string) => () => {
|
||||||
throw new Error(`'${f}' is Discord Desktop only.`);
|
throw new Error(`'${f}' is Discord Desktop only.`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const define: typeof Object.defineProperty =
|
|
||||||
(obj, prop, desc) => {
|
|
||||||
if (Object.hasOwn(desc, "value"))
|
|
||||||
desc.writable = true;
|
|
||||||
|
|
||||||
return Object.defineProperty(obj, prop, {
|
type Define = typeof Object.defineProperty;
|
||||||
configurable: true,
|
const define: Define = (target, p, attributes) => {
|
||||||
enumerable: true,
|
if (Object.hasOwn(attributes, "value")) {
|
||||||
...desc
|
attributes.writable = true;
|
||||||
});
|
}
|
||||||
};
|
|
||||||
|
return Object.defineProperty(target, p, {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
...attributes
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
function makeShortcuts() {
|
function makeShortcuts() {
|
||||||
function newFindWrapper(filterFactory: (...props: any[]) => Webpack.FilterFn) {
|
function newFindWrapper(filterFactory: (...props: any[]) => Webpack.FilterFn, shouldReturnFactory = false) {
|
||||||
const cache = new Map<string, unknown>();
|
const cache = new Map<string, unknown>();
|
||||||
|
|
||||||
return function (...filterProps: unknown[]) {
|
return function (...filterProps: unknown[]) {
|
||||||
const cacheKey = String(filterProps);
|
const cacheKey = String(filterProps);
|
||||||
if (cache.has(cacheKey)) return cache.get(cacheKey);
|
if (cache.has(cacheKey)) return cache.get(cacheKey);
|
||||||
|
|
||||||
const matches = findAll(filterFactory(...filterProps));
|
const matches = cacheFindAll(filterFactory(...filterProps), shouldReturnFactory);
|
||||||
|
|
||||||
const result = (() => {
|
const result = (() => {
|
||||||
switch (matches.length) {
|
switch (matches.length) {
|
||||||
|
@ -60,51 +63,72 @@ function makeShortcuts() {
|
||||||
case 1: return matches[0];
|
case 1: return matches[0];
|
||||||
default:
|
default:
|
||||||
const uniqueMatches = [...new Set(matches)];
|
const uniqueMatches = [...new Set(matches)];
|
||||||
if (uniqueMatches.length > 1)
|
if (uniqueMatches.length > 1) {
|
||||||
console.warn(`Warning: This filter matches ${matches.length} modules. Make it more specific!\n`, uniqueMatches);
|
console.warn(`Warning: This filter matches ${matches.length} modules. Make it more specific!\n`, uniqueMatches);
|
||||||
|
}
|
||||||
|
|
||||||
return matches[0];
|
return uniqueMatches[0];
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
if (result && cacheKey) cache.set(cacheKey, result);
|
if (result && cacheKey) cache.set(cacheKey, result);
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let fakeRenderWin: WeakRef<Window> | undefined;
|
let fakeRenderWin: WeakRef<Window> | undefined;
|
||||||
|
|
||||||
const find = newFindWrapper(f => f);
|
const find = newFindWrapper(f => f);
|
||||||
const findByProps = newFindWrapper(filters.byProps);
|
const findByProps = newFindWrapper(filters.byProps);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...Object.fromEntries(Object.keys(Common).map(key => [key, { getter: () => Common[key] }])),
|
|
||||||
wp: Webpack,
|
wp: Webpack,
|
||||||
wpc: { getter: () => Webpack.cache },
|
wpc: { getter: () => Webpack.cache },
|
||||||
wreq: { getter: () => Webpack.wreq },
|
wreq: { getter: () => Webpack.wreq },
|
||||||
wpsearch: search,
|
|
||||||
wpex: extract,
|
WebpackInstances: { getter: () => Vencord.WebpackPatcher.allWebpackInstances },
|
||||||
wpexs: (code: string) => extract(findModuleId(code)!),
|
|
||||||
loadLazyChunks: IS_DEV ? loadLazyChunks : () => { throw new Error("loadLazyChunks is dev only."); },
|
loadLazyChunks: IS_DEV ? loadLazyChunks : () => { throw new Error("loadLazyChunks is dev only."); },
|
||||||
|
|
||||||
|
wpsearch: searchFactories,
|
||||||
|
wpex: extract,
|
||||||
|
wpexs: (...code: Webpack.CodeFilter) => extract(cacheFindModuleId(...code)!),
|
||||||
|
|
||||||
|
filters,
|
||||||
find,
|
find,
|
||||||
findAll: findAll,
|
findAll: cacheFindAll,
|
||||||
findByProps,
|
findComponent: find,
|
||||||
findAllByProps: (...props: string[]) => findAll(filters.byProps(...props)),
|
findAllComponents: cacheFindAll,
|
||||||
findByCode: newFindWrapper(filters.byCode),
|
findExportedComponent: (...props: Webpack.PropsFilter) => findByProps(...props)[props[0]],
|
||||||
findAllByCode: (code: string) => findAll(filters.byCode(code)),
|
|
||||||
findComponentByCode: newFindWrapper(filters.componentByCode),
|
findComponentByCode: newFindWrapper(filters.componentByCode),
|
||||||
findAllComponentsByCode: (...code: string[]) => findAll(filters.componentByCode(...code)),
|
findAllComponentsByCode: (...code: Webpack.PropsFilter) => cacheFindAll(filters.componentByCode(...code)),
|
||||||
findExportedComponent: (...props: string[]) => findByProps(...props)[props[0]],
|
findComponentByFields: newFindWrapper(filters.componentByFields),
|
||||||
|
findAllComponentsByFields: (...fields: Webpack.PropsFilter) => cacheFindAll(filters.componentByFields(...fields)),
|
||||||
|
findByProps,
|
||||||
|
findAllByProps: (...props: Webpack.PropsFilter) => cacheFindAll(filters.byProps(...props)),
|
||||||
|
findProp: (...props: Webpack.PropsFilter) => findByProps(...props)[props[0]],
|
||||||
|
findByCode: newFindWrapper(filters.byCode),
|
||||||
|
findAllByCode: (code: Webpack.CodeFilter) => cacheFindAll(filters.byCode(...code)),
|
||||||
findStore: newFindWrapper(filters.byStoreName),
|
findStore: newFindWrapper(filters.byStoreName),
|
||||||
PluginsApi: { getter: () => Vencord.Plugins },
|
findByFactoryCode: newFindWrapper(filters.byFactoryCode),
|
||||||
|
findAllByFactoryCode: (...code: Webpack.CodeFilter) => cacheFindAll(filters.byFactoryCode(...code)),
|
||||||
|
findModuleFactory: newFindWrapper(filters.byFactoryCode, true),
|
||||||
|
findAllModuleFactories: (...code: Webpack.CodeFilter) => cacheFindAll(filters.byFactoryCode(...code), true),
|
||||||
|
|
||||||
plugins: { getter: () => Vencord.Plugins.plugins },
|
plugins: { getter: () => Vencord.Plugins.plugins },
|
||||||
|
PluginsApi: { getter: () => Vencord.Plugins },
|
||||||
Settings: { getter: () => Vencord.Settings },
|
Settings: { getter: () => Vencord.Settings },
|
||||||
Api: { getter: () => Vencord.Api },
|
Api: { getter: () => Vencord.Api },
|
||||||
Util: { getter: () => Vencord.Util },
|
Util: { getter: () => Vencord.Util },
|
||||||
|
|
||||||
reload: () => location.reload(),
|
reload: () => location.reload(),
|
||||||
restart: IS_WEB ? DESKTOP_ONLY("restart") : relaunch,
|
restart: IS_WEB ? DESKTOP_ONLY("restart") : relaunch,
|
||||||
|
|
||||||
canonicalizeMatch,
|
canonicalizeMatch,
|
||||||
canonicalizeReplace,
|
canonicalizeReplace,
|
||||||
canonicalizeReplacement,
|
canonicalizeReplacement,
|
||||||
fakeRender: (component: ComponentType, props: any) => {
|
|
||||||
|
preEnable: (plugin: string) => (Vencord.Settings.plugins[plugin] ??= { enabled: true }).enabled = true,
|
||||||
|
fakeRender: (component: React.ComponentType<AnyRecord>, props: any) => {
|
||||||
const prevWin = fakeRenderWin?.deref();
|
const prevWin = fakeRenderWin?.deref();
|
||||||
const win = prevWin?.closed === false
|
const win = prevWin?.closed === false
|
||||||
? prevWin
|
? prevWin
|
||||||
|
@ -133,8 +157,6 @@ function makeShortcuts() {
|
||||||
Common.ReactDOM.render(Common.React.createElement(component, props), doc.body.appendChild(document.createElement("div")));
|
Common.ReactDOM.render(Common.React.createElement(component, props), doc.body.appendChild(document.createElement("div")));
|
||||||
},
|
},
|
||||||
|
|
||||||
preEnable: (plugin: string) => (Vencord.Settings.plugins[plugin] ??= { enabled: true }).enabled = true,
|
|
||||||
|
|
||||||
channel: { getter: () => getCurrentChannel(), preload: false },
|
channel: { getter: () => getCurrentChannel(), preload: false },
|
||||||
channelId: { getter: () => Common.SelectedChannelStore.getChannelId(), preload: false },
|
channelId: { getter: () => Common.SelectedChannelStore.getChannelId(), preload: false },
|
||||||
guild: { getter: () => getCurrentGuild(), preload: false },
|
guild: { getter: () => getCurrentGuild(), preload: false },
|
||||||
|
@ -143,6 +165,7 @@ function makeShortcuts() {
|
||||||
meId: { getter: () => Common.UserStore.getCurrentUser().id, preload: false },
|
meId: { getter: () => Common.UserStore.getCurrentUser().id, preload: false },
|
||||||
messages: { getter: () => Common.MessageStore.getMessages(Common.SelectedChannelStore.getChannelId()), preload: false },
|
messages: { getter: () => Common.MessageStore.getMessages(Common.SelectedChannelStore.getChannelId()), preload: false },
|
||||||
|
|
||||||
|
...Object.fromEntries(Object.keys(Common).map(key => [key, { getter: () => Common[key] }])),
|
||||||
Stores: {
|
Stores: {
|
||||||
getter: () => Object.fromEntries(
|
getter: () => Object.fromEntries(
|
||||||
Common.Flux.Store.getAll()
|
Common.Flux.Store.getAll()
|
||||||
|
@ -157,11 +180,39 @@ function loadAndCacheShortcut(key: string, val: any, forceLoad: boolean) {
|
||||||
const currentVal = val.getter();
|
const currentVal = val.getter();
|
||||||
if (!currentVal || val.preload === false) return currentVal;
|
if (!currentVal || val.preload === false) return currentVal;
|
||||||
|
|
||||||
const value = currentVal[SYM_LAZY_GET]
|
function unwrapProxy(value: any) {
|
||||||
? forceLoad ? currentVal[SYM_LAZY_GET]() : currentVal[SYM_LAZY_CACHED]
|
if (value[SYM_LAZY_GET]) {
|
||||||
: currentVal;
|
return forceLoad ? value[SYM_LAZY_GET]() : value[SYM_LAZY_CACHED];
|
||||||
|
} else if (value[SYM_PROXY_INNER_GET]) {
|
||||||
|
return forceLoad ? value[SYM_PROXY_INNER_GET]() : value[SYM_PROXY_INNER_VALUE];
|
||||||
|
} else if (value[SYM_LAZY_COMPONENT_INNER]) {
|
||||||
|
return value[SYM_LAZY_COMPONENT_INNER]() != null ? value[SYM_LAZY_COMPONENT_INNER]() : value;
|
||||||
|
}
|
||||||
|
|
||||||
if (value) define(window.shortcutList, key, { value });
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = unwrapProxy(currentVal);
|
||||||
|
if (value != null && typeof value === "object") {
|
||||||
|
const descriptors = Object.getOwnPropertyDescriptors(value);
|
||||||
|
|
||||||
|
for (const propKey in descriptors) {
|
||||||
|
if (value[propKey] == null) continue;
|
||||||
|
|
||||||
|
const descriptor = descriptors[propKey];
|
||||||
|
if (descriptor.writable === true || descriptor.set != null) {
|
||||||
|
const currentValue = value[propKey];
|
||||||
|
const newValue = unwrapProxy(currentValue);
|
||||||
|
if (newValue != null && currentValue !== newValue) {
|
||||||
|
value[propKey] = newValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value != null) {
|
||||||
|
define(window.shortcutList, key, { value });
|
||||||
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -176,8 +227,10 @@ export default definePlugin({
|
||||||
const shortcuts = makeShortcuts();
|
const shortcuts = makeShortcuts();
|
||||||
window.shortcutList = {};
|
window.shortcutList = {};
|
||||||
|
|
||||||
for (const [key, val] of Object.entries(shortcuts)) {
|
for (const key in shortcuts) {
|
||||||
if ("getter" in val) {
|
const val = shortcuts[key];
|
||||||
|
|
||||||
|
if (Object.hasOwn(val, "getter")) {
|
||||||
define(window.shortcutList, key, {
|
define(window.shortcutList, key, {
|
||||||
get: () => loadAndCacheShortcut(key, val, true)
|
get: () => loadAndCacheShortcut(key, val, true)
|
||||||
});
|
});
|
||||||
|
@ -191,8 +244,8 @@ export default definePlugin({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unproxy loaded modules
|
// Unproxy loaded modules
|
||||||
Webpack.onceReady.then(() => {
|
Webpack.onceDiscordLoaded.then(() => {
|
||||||
setTimeout(() => this.eagerLoad(false), 1000);
|
setTimeout(() => this.eagerLoad(false), 1000);
|
||||||
|
|
||||||
if (!IS_WEB) {
|
if (!IS_WEB) {
|
||||||
|
@ -203,13 +256,13 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
|
|
||||||
async eagerLoad(forceLoad: boolean) {
|
async eagerLoad(forceLoad: boolean) {
|
||||||
await Webpack.onceReady;
|
await Webpack.onceDiscordLoaded;
|
||||||
|
|
||||||
const shortcuts = makeShortcuts();
|
const shortcuts = makeShortcuts();
|
||||||
|
for (const key in shortcuts) {
|
||||||
|
const val = shortcuts[key];
|
||||||
|
|
||||||
for (const [key, val] of Object.entries(shortcuts)) {
|
if (!Object.hasOwn(val, "getter") || val.preload === false) continue;
|
||||||
if (!Object.hasOwn(val, "getter") || (val as any).preload === false) continue;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
loadAndCacheShortcut(key, val, forceLoad);
|
loadAndCacheShortcut(key, val, forceLoad);
|
||||||
} catch { } // swallow not found errors in DEV
|
} catch { } // swallow not found errors in DEV
|
||||||
|
|
|
@ -8,10 +8,10 @@ import { definePluginSettings } from "@api/Settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { copyWithToast } from "@utils/misc";
|
import { copyWithToast } from "@utils/misc";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findProp } from "@webpack";
|
||||||
import { Menu } from "@webpack/common";
|
import { Menu } from "@webpack/common";
|
||||||
|
|
||||||
const { convertNameToSurrogate } = findByPropsLazy("convertNameToSurrogate");
|
const convertNameToSurrogate = findProp("convertNameToSurrogate");
|
||||||
|
|
||||||
interface Emoji {
|
interface Emoji {
|
||||||
type: string;
|
type: string;
|
||||||
|
@ -55,7 +55,7 @@ export default definePlugin({
|
||||||
settings,
|
settings,
|
||||||
|
|
||||||
contextMenus: {
|
contextMenus: {
|
||||||
"expression-picker"(children, { target }: { target: Target }) {
|
"expression-picker"(children, { target }: { target: Target; }) {
|
||||||
if (target.dataset.type !== "emoji") return;
|
if (target.dataset.type !== "emoji") return;
|
||||||
|
|
||||||
children.push(
|
children.push(
|
||||||
|
|
|
@ -23,22 +23,12 @@ import { Logger } from "@utils/Logger";
|
||||||
import { closeAllModals } from "@utils/modal";
|
import { closeAllModals } from "@utils/modal";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { maybePromptToUpdate } from "@utils/updater";
|
import { maybePromptToUpdate } from "@utils/updater";
|
||||||
import { filters, findBulk, proxyLazyWebpack } from "@webpack";
|
import { findByProps } from "@webpack";
|
||||||
import { DraftType, ExpressionPickerStore, FluxDispatcher, NavigationRouter, SelectedChannelStore } from "@webpack/common";
|
import { DraftType, ExpressionPickerStore, FluxDispatcher, NavigationRouter, SelectedChannelStore } from "@webpack/common";
|
||||||
|
|
||||||
const CrashHandlerLogger = new Logger("CrashHandler");
|
const CrashHandlerLogger = new Logger("CrashHandler");
|
||||||
|
const ModalStack = findByProps("pushLazy", "popAll");
|
||||||
const { ModalStack, DraftManager } = proxyLazyWebpack(() => {
|
const DraftManager = findByProps("clearDraft", "saveDraft");
|
||||||
const [ModalStack, DraftManager] = findBulk(
|
|
||||||
filters.byProps("pushLazy", "popAll"),
|
|
||||||
filters.byProps("clearDraft", "saveDraft"),
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
ModalStack,
|
|
||||||
DraftManager
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const settings = definePluginSettings({
|
const settings = definePluginSettings({
|
||||||
attemptToPreventCrashes: {
|
attemptToPreventCrashes: {
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { definePluginSettings, Settings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import { getUserSettingLazy } from "@api/UserSettings";
|
import { getUserSettingLazy } from "@api/UserSettings";
|
||||||
import { ErrorCard } from "@components/ErrorCard";
|
import { ErrorCard } from "@components/ErrorCard";
|
||||||
import { Link } from "@components/Link";
|
import { Link } from "@components/Link";
|
||||||
|
@ -26,13 +26,13 @@ import { Margins } from "@utils/margins";
|
||||||
import { classes } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import { useAwaiter } from "@utils/react";
|
import { useAwaiter } from "@utils/react";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByCodeLazy, findComponentByCodeLazy } from "@webpack";
|
import { findByCode, findComponentByCode } from "@webpack";
|
||||||
import { ApplicationAssetUtils, Button, FluxDispatcher, Forms, GuildStore, React, SelectedChannelStore, SelectedGuildStore, UserStore } from "@webpack/common";
|
import { ApplicationAssetUtils, Button, FluxDispatcher, Forms, GuildStore, React, SelectedChannelStore, SelectedGuildStore, UserStore } from "@webpack/common";
|
||||||
|
|
||||||
const useProfileThemeStyle = findByCodeLazy("profileThemeStyle:", "--profile-gradient-primary-color");
|
const useProfileThemeStyle = findByCode("profileThemeStyle:", "--profile-gradient-primary-color");
|
||||||
const ActivityComponent = findComponentByCodeLazy("onOpenGameProfile");
|
const ActivityComponent = findComponentByCode("onOpenGameProfile");
|
||||||
|
|
||||||
const ShowCurrentGame = getUserSettingLazy<boolean>("status", "showCurrentGame")!;
|
const ShowCurrentGame = getUserSettingLazy<boolean>("status", "showCurrentGame");
|
||||||
|
|
||||||
async function getApplicationAsset(key: string): Promise<string> {
|
async function getApplicationAsset(key: string): Promise<string> {
|
||||||
if (/https?:\/\/(cdn|media)\.discordapp\.(com|net)\/attachments\//.test(key)) return "mp:" + key.replace(/https?:\/\/(cdn|media)\.discordapp\.(com|net)\//, "");
|
if (/https?:\/\/(cdn|media)\.discordapp\.(com|net)\/attachments\//.test(key)) return "mp:" + key.replace(/https?:\/\/(cdn|media)\.discordapp\.(com|net)\//, "");
|
||||||
|
@ -260,7 +260,7 @@ const settings = definePluginSettings({
|
||||||
|
|
||||||
function onChange() {
|
function onChange() {
|
||||||
setRpc(true);
|
setRpc(true);
|
||||||
if (Settings.plugins.CustomRPC.enabled) setRpc();
|
if (Vencord.Plugins.isPluginEnabled("CustomRPC")) setRpc();
|
||||||
}
|
}
|
||||||
|
|
||||||
function isStreamLinkDisabled() {
|
function isStreamLinkDisabled() {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Flex } from "@components/Flex";
|
import { Flex } from "@components/Flex";
|
||||||
import { findByCodeLazy } from "@webpack";
|
import { findComponentByCode } from "@webpack";
|
||||||
import { Button, useEffect } from "@webpack/common";
|
import { Button, useEffect } from "@webpack/common";
|
||||||
|
|
||||||
import { useAuthorizationStore } from "../../lib/stores/AuthorizationStore";
|
import { useAuthorizationStore } from "../../lib/stores/AuthorizationStore";
|
||||||
|
@ -13,7 +13,7 @@ import { useCurrentUserDecorationsStore } from "../../lib/stores/CurrentUserDeco
|
||||||
import { cl } from "../";
|
import { cl } from "../";
|
||||||
import { openChangeDecorationModal } from "../modals/ChangeDecorationModal";
|
import { openChangeDecorationModal } from "../modals/ChangeDecorationModal";
|
||||||
|
|
||||||
const CustomizationSection = findByCodeLazy(".customizationSectionBackground");
|
const CustomizationSection = findComponentByCode(".customizationSectionBackground");
|
||||||
|
|
||||||
export interface DecorSectionProps {
|
export interface DecorSectionProps {
|
||||||
hideTitle?: boolean;
|
hideTitle?: boolean;
|
||||||
|
|
|
@ -5,13 +5,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { classes } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findByProps } from "@webpack";
|
||||||
import { React } from "@webpack/common";
|
import { React } from "@webpack/common";
|
||||||
|
|
||||||
import { cl } from "../";
|
import { cl } from "../";
|
||||||
import Grid, { GridProps } from "./Grid";
|
import Grid, { GridProps } from "./Grid";
|
||||||
|
|
||||||
const ScrollerClasses = findByPropsLazy("managedReactiveScroller");
|
const ScrollerClasses = findByProps("managedReactiveScroller");
|
||||||
|
|
||||||
type Section<SectionT, ItemT> = SectionT & {
|
type Section<SectionT, ItemT> = SectionT & {
|
||||||
items: Array<ItemT>;
|
items: Array<ItemT>;
|
||||||
|
|
|
@ -4,30 +4,27 @@
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { findComponentByCode, LazyComponentWebpack } from "@webpack";
|
import { NoopComponent } from "@utils/react";
|
||||||
|
import { findComponentByCode } from "@webpack";
|
||||||
import { React } from "@webpack/common";
|
import { React } from "@webpack/common";
|
||||||
import type { ComponentType, HTMLProps, PropsWithChildren } from "react";
|
|
||||||
|
|
||||||
import { AvatarDecoration } from "../..";
|
import { AvatarDecoration } from "../..";
|
||||||
|
|
||||||
type DecorationGridItemComponent = ComponentType<PropsWithChildren<HTMLProps<HTMLDivElement>> & {
|
type DecorationGridItemComponent = AnyComponentTypeWithChildren<React.ComponentPropsWithoutRef<"div"> & {
|
||||||
onSelect: () => void,
|
onSelect: () => void,
|
||||||
isSelected: boolean,
|
isSelected: boolean,
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
export let DecorationGridItem: DecorationGridItemComponent;
|
export let DecorationGridItem: DecorationGridItemComponent = NoopComponent;
|
||||||
export const setDecorationGridItem = v => DecorationGridItem = v;
|
export const setDecorationGridItem = v => DecorationGridItem = v;
|
||||||
|
|
||||||
export const AvatarDecorationModalPreview = LazyComponentWebpack(() => {
|
export const AvatarDecorationModalPreview = findComponentByCode(".shopPreviewBanner", component => React.memo(component));
|
||||||
const component = findComponentByCode(".shopPreviewBanner");
|
|
||||||
return React.memo(component);
|
|
||||||
});
|
|
||||||
|
|
||||||
type DecorationGridDecorationComponent = React.ComponentType<HTMLProps<HTMLDivElement> & {
|
type DecorationGridDecorationComponent = AnyComponentType<React.ComponentPropsWithoutRef<"div"> & {
|
||||||
avatarDecoration: AvatarDecoration;
|
avatarDecoration: AvatarDecoration;
|
||||||
onSelect: () => void,
|
onSelect: () => void,
|
||||||
isSelected: boolean,
|
isSelected: boolean,
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
export let DecorationGridDecoration: DecorationGridDecorationComponent;
|
export let DecorationGridDecoration: DecorationGridDecorationComponent = NoopComponent;
|
||||||
export const setDecorationGridDecoration = v => DecorationGridDecoration = v;
|
export const setDecorationGridDecoration = v => DecorationGridDecoration = v;
|
||||||
|
|
|
@ -5,10 +5,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { classNameFactory } from "@api/Styles";
|
import { classNameFactory } from "@api/Styles";
|
||||||
import { extractAndLoadChunksLazy, findByPropsLazy } from "@webpack";
|
import { extractAndLoadChunksLazy, findByProps } from "@webpack";
|
||||||
|
|
||||||
export const cl = classNameFactory("vc-decor-");
|
export const cl = classNameFactory("vc-decor-");
|
||||||
export const DecorationModalStyles = findByPropsLazy("modalFooterShopButton");
|
export const DecorationModalStyles = findByProps("modalFooterShopButton");
|
||||||
|
|
||||||
export const requireAvatarDecorationModal = extractAndLoadChunksLazy([".COLLECTIBLES_SHOP_FULLSCREEN&&"]);
|
export const requireAvatarDecorationModal = extractAndLoadChunksLazy(".COLLECTIBLES_SHOP_FULLSCREEN&&");
|
||||||
export const requireCreateStickerModal = extractAndLoadChunksLazy(["stickerInspected]:"]);
|
export const requireCreateStickerModal = extractAndLoadChunksLazy("stickerInspected]:");
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { openInviteModal } from "@utils/discord";
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
import { classes, copyWithToast } from "@utils/misc";
|
import { classes, copyWithToast } from "@utils/misc";
|
||||||
import { closeAllModals, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
import { closeAllModals, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
||||||
import { findComponentByCodeLazy } from "@webpack";
|
import { findComponentByCode } from "@webpack";
|
||||||
import { Alerts, Button, FluxDispatcher, Forms, GuildStore, NavigationRouter, Parser, Text, Tooltip, useEffect, UserStore, UserUtils, useState } from "@webpack/common";
|
import { Alerts, Button, FluxDispatcher, Forms, GuildStore, NavigationRouter, Parser, Text, Tooltip, useEffect, UserStore, UserUtils, useState } from "@webpack/common";
|
||||||
import { User } from "discord-types/general";
|
import { User } from "discord-types/general";
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ import SectionedGridList from "../components/SectionedGridList";
|
||||||
import { openCreateDecorationModal } from "./CreateDecorationModal";
|
import { openCreateDecorationModal } from "./CreateDecorationModal";
|
||||||
import { openGuidelinesModal } from "./GuidelinesModal";
|
import { openGuidelinesModal } from "./GuidelinesModal";
|
||||||
|
|
||||||
const UserSummaryItem = findComponentByCodeLazy("defaultRenderUser", "showDefaultAvatarsForNullUsers");
|
const UserSummaryItem = findComponentByCode("defaultRenderUser", "showDefaultAvatarsForNullUsers");
|
||||||
|
|
||||||
function usePresets() {
|
function usePresets() {
|
||||||
const [presets, setPresets] = useState<Preset[]>([]);
|
const [presets, setPresets] = useState<Preset[]>([]);
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { Link } from "@components/Link";
|
||||||
import { openInviteModal } from "@utils/discord";
|
import { openInviteModal } from "@utils/discord";
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
import { closeAllModals, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
import { closeAllModals, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
||||||
import { filters, findComponentByCodeLazy, mapMangledModuleLazy } from "@webpack";
|
import { filters, findComponentByCode, mapMangledModule } from "@webpack";
|
||||||
import { Button, FluxDispatcher, Forms, GuildStore, NavigationRouter, Text, TextInput, useEffect, useMemo, UserStore, useState } from "@webpack/common";
|
import { Button, FluxDispatcher, Forms, GuildStore, NavigationRouter, Text, TextInput, useEffect, useMemo, UserStore, useState } from "@webpack/common";
|
||||||
|
|
||||||
import { GUILD_ID, INVITE_KEY, RAW_SKU_ID } from "../../lib/constants";
|
import { GUILD_ID, INVITE_KEY, RAW_SKU_ID } from "../../lib/constants";
|
||||||
|
@ -17,11 +17,11 @@ import { useCurrentUserDecorationsStore } from "../../lib/stores/CurrentUserDeco
|
||||||
import { cl, DecorationModalStyles, requireAvatarDecorationModal, requireCreateStickerModal } from "../";
|
import { cl, DecorationModalStyles, requireAvatarDecorationModal, requireCreateStickerModal } from "../";
|
||||||
import { AvatarDecorationModalPreview } from "../components";
|
import { AvatarDecorationModalPreview } from "../components";
|
||||||
|
|
||||||
const FileUpload = findComponentByCodeLazy("fileUploadInput,");
|
const FileUpload = findComponentByCode("fileUploadInput,");
|
||||||
|
|
||||||
const { HelpMessage, HelpMessageTypes } = mapMangledModuleLazy('POSITIVE=3]="POSITIVE', {
|
const { HelpMessage, HelpMessageTypes } = mapMangledModule('POSITIVE=3]="POSITIVE', {
|
||||||
|
HelpMessage: filters.componentByCode(".iconDiv,", "messageType"),
|
||||||
HelpMessageTypes: filters.byProps("POSITIVE", "WARNING"),
|
HelpMessageTypes: filters.byProps("POSITIVE", "WARNING"),
|
||||||
HelpMessage: filters.byCode(".iconDiv")
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function useObjectURL(object: Blob | MediaSource | null) {
|
function useObjectURL(object: Blob | MediaSource | null) {
|
||||||
|
|
|
@ -22,7 +22,7 @@ import { Devs } from "@utils/constants";
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
import { canonicalizeMatch, canonicalizeReplace } from "@utils/patches";
|
import { canonicalizeMatch, canonicalizeReplace } from "@utils/patches";
|
||||||
import definePlugin, { OptionType, ReporterTestable } from "@utils/types";
|
import definePlugin, { OptionType, ReporterTestable } from "@utils/types";
|
||||||
import { filters, findAll, search } from "@webpack";
|
import { cacheFindAll, filters, searchFactories } from "@webpack";
|
||||||
|
|
||||||
const PORT = 8485;
|
const PORT = 8485;
|
||||||
const NAV_ID = "dev-companion-reconnect";
|
const NAV_ID = "dev-companion-reconnect";
|
||||||
|
@ -154,13 +154,13 @@ function initWs(isManual = false) {
|
||||||
case "testPatch": {
|
case "testPatch": {
|
||||||
const { find, replacement } = data as PatchData;
|
const { find, replacement } = data as PatchData;
|
||||||
|
|
||||||
const candidates = search(find);
|
const candidates = searchFactories(find);
|
||||||
const keys = Object.keys(candidates);
|
const keys = Object.keys(candidates);
|
||||||
if (keys.length !== 1)
|
if (keys.length !== 1)
|
||||||
return reply("Expected exactly one 'find' matches, found " + keys.length);
|
return reply("Expected exactly one 'find' matches, found " + keys.length);
|
||||||
|
|
||||||
const mod = candidates[keys[0]];
|
const mod = candidates[keys[0]];
|
||||||
let src = String(mod.original ?? mod).replaceAll("\n", "");
|
let src = String(mod).replaceAll("\n", "");
|
||||||
|
|
||||||
if (src.startsWith("function(")) {
|
if (src.startsWith("function(")) {
|
||||||
src = "0," + src;
|
src = "0," + src;
|
||||||
|
@ -201,22 +201,22 @@ function initWs(isManual = false) {
|
||||||
let results: any[];
|
let results: any[];
|
||||||
switch (type.replace("find", "").replace("Lazy", "")) {
|
switch (type.replace("find", "").replace("Lazy", "")) {
|
||||||
case "":
|
case "":
|
||||||
results = findAll(parsedArgs[0]);
|
results = cacheFindAll(parsedArgs[0]);
|
||||||
break;
|
break;
|
||||||
case "ByProps":
|
case "ByProps":
|
||||||
results = findAll(filters.byProps(...parsedArgs));
|
results = cacheFindAll(filters.byProps(...parsedArgs));
|
||||||
break;
|
break;
|
||||||
case "Store":
|
case "Store":
|
||||||
results = findAll(filters.byStoreName(parsedArgs[0]));
|
results = cacheFindAll(filters.byStoreName(parsedArgs[0]));
|
||||||
break;
|
break;
|
||||||
case "ByCode":
|
case "ByCode":
|
||||||
results = findAll(filters.byCode(...parsedArgs));
|
results = cacheFindAll(filters.byCode(...parsedArgs));
|
||||||
break;
|
break;
|
||||||
case "ModuleId":
|
case "ModuleId":
|
||||||
results = Object.keys(search(parsedArgs[0]));
|
results = Object.keys(searchFactories(parsedArgs[0]));
|
||||||
break;
|
break;
|
||||||
case "ComponentByCode":
|
case "ComponentByCode":
|
||||||
results = findAll(filters.componentByCode(...parsedArgs));
|
results = cacheFindAll(filters.componentByCode(...parsedArgs));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return reply("Unknown Find Type " + type);
|
return reply("Unknown Find Type " + type);
|
||||||
|
|
|
@ -23,12 +23,12 @@ import { Logger } from "@utils/Logger";
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
import { ModalContent, ModalHeader, ModalRoot, openModalLazy } from "@utils/modal";
|
import { ModalContent, ModalHeader, ModalRoot, openModalLazy } from "@utils/modal";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { findByCodeLazy, findStoreLazy } from "@webpack";
|
import { findByCode, findStore } from "@webpack";
|
||||||
import { Constants, EmojiStore, FluxDispatcher, Forms, GuildStore, Menu, PermissionsBits, PermissionStore, React, RestAPI, Toasts, Tooltip, UserStore } from "@webpack/common";
|
import { Constants, EmojiStore, FluxDispatcher, Forms, GuildStore, Menu, PermissionsBits, PermissionStore, React, RestAPI, Toasts, Tooltip, UserStore } from "@webpack/common";
|
||||||
import { Promisable } from "type-fest";
|
import { Promisable } from "type-fest";
|
||||||
|
|
||||||
const StickersStore = findStoreLazy("StickersStore");
|
const StickersStore = findStore("StickersStore");
|
||||||
const uploadEmoji = findByCodeLazy(".GUILD_EMOJIS(", "EMOJI_UPLOAD_START");
|
const uploadEmoji = findByCode(".GUILD_EMOJIS(", "EMOJI_UPLOAD_START");
|
||||||
|
|
||||||
interface Sticker {
|
interface Sticker {
|
||||||
t: "Sticker";
|
t: "Sticker";
|
||||||
|
|
|
@ -23,13 +23,13 @@ import { ErrorCard } from "@components/ErrorCard";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByPropsLazy, findLazy } from "@webpack";
|
import { find, findByProps } from "@webpack";
|
||||||
import { Forms, React } from "@webpack/common";
|
import { Forms, React } from "@webpack/common";
|
||||||
|
|
||||||
import hideBugReport from "./hideBugReport.css?managed";
|
import hideBugReport from "./hideBugReport.css?managed";
|
||||||
|
|
||||||
const KbdStyles = findByPropsLazy("key", "combo");
|
const KbdStyles = findByProps("key", "combo");
|
||||||
const BugReporterExperiment = findLazy(m => m?.definition?.id === "2024-09_bug_reporter");
|
const BugReporterExperiment = find(m => m?.definition?.id === "2024-09_bug_reporter");
|
||||||
|
|
||||||
const settings = definePluginSettings({
|
const settings = definePluginSettings({
|
||||||
toolbarDevMenu: {
|
toolbarDevMenu: {
|
||||||
|
|
|
@ -23,36 +23,36 @@ import { ApngBlendOp, ApngDisposeOp, importApngJs } from "@utils/dependencies";
|
||||||
import { getCurrentGuild } from "@utils/discord";
|
import { getCurrentGuild } from "@utils/discord";
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByCodeLazy, findByPropsLazy, findStoreLazy, proxyLazyWebpack } from "@webpack";
|
import { findByCode, findByProps, findStore, webpackDependantLazy } from "@webpack";
|
||||||
import { Alerts, ChannelStore, DraftType, EmojiStore, FluxDispatcher, Forms, GuildMemberStore, IconUtils, lodash, Parser, PermissionsBits, PermissionStore, UploadHandler, UserSettingsActionCreators, UserStore } from "@webpack/common";
|
import { Alerts, ChannelStore, DraftType, EmojiStore, FluxDispatcher, Forms, GuildMemberStore, IconUtils, lodash, Parser, PermissionsBits, PermissionStore, UploadHandler, UserSettingsActionCreators, UserStore } from "@webpack/common";
|
||||||
import type { Emoji } from "@webpack/types";
|
import type { Emoji } from "@webpack/types";
|
||||||
import type { Message } from "discord-types/general";
|
import type { Message } from "discord-types/general";
|
||||||
import { applyPalette, GIFEncoder, quantize } from "gifenc";
|
import { applyPalette, GIFEncoder, quantize } from "gifenc";
|
||||||
import type { ReactElement, ReactNode } from "react";
|
import type { ReactElement, ReactNode } from "react";
|
||||||
|
|
||||||
const StickerStore = findStoreLazy("StickersStore") as {
|
const StickersStore = findStore("StickersStore") as {
|
||||||
getPremiumPacks(): StickerPack[];
|
getPremiumPacks(): StickerPack[];
|
||||||
getAllGuildStickers(): Map<string, Sticker[]>;
|
getAllGuildStickers(): Map<string, Sticker[]>;
|
||||||
getStickerById(id: string): Sticker | undefined;
|
getStickerById(id: string): Sticker | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
const UserSettingsProtoStore = findStoreLazy("UserSettingsProtoStore");
|
const UserSettingsProtoStore = findStore("UserSettingsProtoStore");
|
||||||
|
|
||||||
const BINARY_READ_OPTIONS = findByPropsLazy("readerFactory");
|
const BINARY_READ_OPTIONS = findByProps("readerFactory");
|
||||||
|
|
||||||
function searchProtoClassField(localName: string, protoClass: any) {
|
function searchProtoClassField(localName: string, protoClass: any) {
|
||||||
const field = protoClass?.fields?.find((field: any) => field.localName === localName);
|
const field = protoClass?.fields?.find((field: any) => field.localName === localName);
|
||||||
if (!field) return;
|
if (!field) return;
|
||||||
|
|
||||||
const fieldGetter = Object.values(field).find(value => typeof value === "function") as any;
|
const fieldGetter = Object.values<any>(field).find(value => typeof value === "function");
|
||||||
return fieldGetter?.();
|
return fieldGetter?.();
|
||||||
}
|
}
|
||||||
|
|
||||||
const PreloadedUserSettingsActionCreators = proxyLazyWebpack(() => UserSettingsActionCreators.PreloadedUserSettingsActionCreators);
|
const PreloadedUserSettingsActionCreators = webpackDependantLazy(() => UserSettingsActionCreators.PreloadedUserSettingsActionCreators);
|
||||||
const AppearanceSettingsActionCreators = proxyLazyWebpack(() => searchProtoClassField("appearance", PreloadedUserSettingsActionCreators.ProtoClass));
|
const AppearanceSettingsActionCreators = webpackDependantLazy(() => searchProtoClassField("appearance", PreloadedUserSettingsActionCreators.ProtoClass));
|
||||||
const ClientThemeSettingsActionsCreators = proxyLazyWebpack(() => searchProtoClassField("clientThemeSettings", AppearanceSettingsActionCreators));
|
const ClientThemeSettingsActionsCreators = webpackDependantLazy(() => searchProtoClassField("clientThemeSettings", AppearanceSettingsActionCreators));
|
||||||
|
|
||||||
const isUnusableRoleSubscriptionEmoji = findByCodeLazy(".getUserIsAdmin(");
|
const isUnusableRoleSubscriptionEmoji = findByCode(".getUserIsAdmin(");
|
||||||
|
|
||||||
const enum EmojiIntentions {
|
const enum EmojiIntentions {
|
||||||
REACTION,
|
REACTION,
|
||||||
|
@ -575,8 +575,8 @@ export default definePlugin({
|
||||||
|
|
||||||
const gifMatch = child.props.href.match(fakeNitroGifStickerRegex);
|
const gifMatch = child.props.href.match(fakeNitroGifStickerRegex);
|
||||||
if (gifMatch) {
|
if (gifMatch) {
|
||||||
// There is no way to differentiate a regular gif attachment from a fake nitro animated sticker, so we check if the StickerStore contains the id of the fake sticker
|
// There is no way to differentiate a regular gif attachment from a fake nitro animated sticker, so we check if the StickersStore contains the id of the fake sticker
|
||||||
if (StickerStore.getStickerById(gifMatch[1])) return null;
|
if (StickersStore.getStickerById(gifMatch[1])) return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -664,7 +664,7 @@ export default definePlugin({
|
||||||
url = new URL(item);
|
url = new URL(item);
|
||||||
} catch { }
|
} catch { }
|
||||||
|
|
||||||
const stickerName = StickerStore.getStickerById(imgMatch[1])?.name ?? url?.searchParams.get("name") ?? "FakeNitroSticker";
|
const stickerName = StickersStore.getStickerById(imgMatch[1])?.name ?? url?.searchParams.get("name") ?? "FakeNitroSticker";
|
||||||
stickers.push({
|
stickers.push({
|
||||||
format_type: 1,
|
format_type: 1,
|
||||||
id: imgMatch[1],
|
id: imgMatch[1],
|
||||||
|
@ -677,9 +677,9 @@ export default definePlugin({
|
||||||
|
|
||||||
const gifMatch = item.match(fakeNitroGifStickerRegex);
|
const gifMatch = item.match(fakeNitroGifStickerRegex);
|
||||||
if (gifMatch) {
|
if (gifMatch) {
|
||||||
if (!StickerStore.getStickerById(gifMatch[1])) continue;
|
if (!StickersStore.getStickerById(gifMatch[1])) continue;
|
||||||
|
|
||||||
const stickerName = StickerStore.getStickerById(gifMatch[1])?.name ?? "FakeNitroSticker";
|
const stickerName = StickersStore.getStickerById(gifMatch[1])?.name ?? "FakeNitroSticker";
|
||||||
stickers.push({
|
stickers.push({
|
||||||
format_type: 2,
|
format_type: 2,
|
||||||
id: gifMatch[1],
|
id: gifMatch[1],
|
||||||
|
@ -712,8 +712,8 @@ export default definePlugin({
|
||||||
|
|
||||||
const gifMatch = embed.url!.match(fakeNitroGifStickerRegex);
|
const gifMatch = embed.url!.match(fakeNitroGifStickerRegex);
|
||||||
if (gifMatch) {
|
if (gifMatch) {
|
||||||
// There is no way to differentiate a regular gif attachment from a fake nitro animated sticker, so we check if the StickerStore contains the id of the fake sticker
|
// There is no way to differentiate a regular gif attachment from a fake nitro animated sticker, so we check if the StickersStore contains the id of the fake sticker
|
||||||
if (StickerStore.getStickerById(gifMatch[1])) return true;
|
if (StickersStore.getStickerById(gifMatch[1])) return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -730,8 +730,8 @@ export default definePlugin({
|
||||||
|
|
||||||
const match = attachment.url.match(fakeNitroGifStickerRegex);
|
const match = attachment.url.match(fakeNitroGifStickerRegex);
|
||||||
if (match) {
|
if (match) {
|
||||||
// There is no way to differentiate a regular gif attachment from a fake nitro animated sticker, so we check if the StickerStore contains the id of the fake sticker
|
// There is no way to differentiate a regular gif attachment from a fake nitro animated sticker, so we check if the StickersStore contains the id of the fake sticker
|
||||||
if (StickerStore.getStickerById(match[1])) return false;
|
if (StickersStore.getStickerById(match[1])) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -887,7 +887,7 @@ export default definePlugin({
|
||||||
if (!s.enableStickerBypass)
|
if (!s.enableStickerBypass)
|
||||||
break stickerBypass;
|
break stickerBypass;
|
||||||
|
|
||||||
const sticker = StickerStore.getStickerById(extra.stickers?.[0]!);
|
const sticker = StickersStore.getStickerById(extra.stickers?.[0]!);
|
||||||
if (!sticker)
|
if (!sticker)
|
||||||
break stickerBypass;
|
break stickerBypass;
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ import { Margins } from "@utils/margins";
|
||||||
import { classes, copyWithToast } from "@utils/misc";
|
import { classes, copyWithToast } from "@utils/misc";
|
||||||
import { useAwaiter } from "@utils/react";
|
import { useAwaiter } from "@utils/react";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { extractAndLoadChunksLazy, findComponentByCodeLazy } from "@webpack";
|
import { extractAndLoadChunksLazy, findComponentByCode } from "@webpack";
|
||||||
import { Button, Flex, Forms, React, Text, UserProfileStore, UserStore, useState } from "@webpack/common";
|
import { Button, Flex, Forms, React, Text, UserProfileStore, UserStore, useState } from "@webpack/common";
|
||||||
import { User } from "discord-types/general";
|
import { User } from "discord-types/general";
|
||||||
import virtualMerge from "virtual-merge";
|
import virtualMerge from "virtual-merge";
|
||||||
|
@ -108,10 +108,10 @@ interface ProfileModalProps {
|
||||||
isTryItOutFlow: boolean;
|
isTryItOutFlow: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ColorPicker = findComponentByCodeLazy<ColorPickerProps>(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR", ".BACKGROUND_PRIMARY)");
|
const ColorPicker = findComponentByCode<ColorPickerProps>(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR", ".BACKGROUND_PRIMARY)");
|
||||||
const ProfileModal = findComponentByCodeLazy<ProfileModalProps>("isTryItOutFlow:", "pendingThemeColors:", "pendingAvatarDecoration:", "EDIT_PROFILE_BANNER");
|
const ProfileModal = findComponentByCode<ProfileModalProps>("isTryItOutFlow:", "pendingThemeColors:", "pendingAvatarDecoration:", "EDIT_PROFILE_BANNER");
|
||||||
|
|
||||||
const requireColorPicker = extractAndLoadChunksLazy(["USER_SETTINGS_PROFILE_COLOR_DEFAULT_BUTTON.format"], /createPromise:\(\)=>\i\.\i(\("?.+?"?\)).then\(\i\.bind\(\i,"?(.+?)"?\)\)/);
|
const requireColorPicker = extractAndLoadChunksLazy("USER_SETTINGS_PROFILE_COLOR_DEFAULT_BUTTON.format");
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "FakeProfileThemes",
|
name: "FakeProfileThemes",
|
||||||
|
|
|
@ -20,7 +20,7 @@ import { definePluginSettings } from "@api/Settings";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findByProps } from "@webpack";
|
||||||
import { useCallback, useEffect, useRef, useState } from "@webpack/common";
|
import { useCallback, useEffect, useRef, useState } from "@webpack/common";
|
||||||
|
|
||||||
interface SearchBarComponentProps {
|
interface SearchBarComponentProps {
|
||||||
|
@ -35,7 +35,7 @@ interface SearchBarComponentProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
type TSearchBarComponent =
|
type TSearchBarComponent =
|
||||||
React.FC<SearchBarComponentProps> & { Sizes: Record<"SMALL" | "MEDIUM" | "LARGE", string>; };
|
React.ComponentType<SearchBarComponentProps> & { Sizes: Record<"SMALL" | "MEDIUM" | "LARGE", string>; };
|
||||||
|
|
||||||
interface Gif {
|
interface Gif {
|
||||||
format: number;
|
format: number;
|
||||||
|
@ -60,7 +60,7 @@ interface Instance {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const containerClasses: { searchBar: string; } = findByPropsLazy("searchBar", "searchBarFullRow");
|
const containerClasses: { searchBar: string; } = findByProps("searchBar", "searchBarFullRow");
|
||||||
|
|
||||||
export const settings = definePluginSettings({
|
export const settings = definePluginSettings({
|
||||||
searchOption: {
|
searchOption: {
|
||||||
|
|
|
@ -19,9 +19,9 @@
|
||||||
import { ApplicationCommandInputType, sendBotMessage } from "@api/Commands";
|
import { ApplicationCommandInputType, sendBotMessage } from "@api/Commands";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findByProps } from "@webpack";
|
||||||
|
|
||||||
const FriendInvites = findByPropsLazy("createFriendInvite");
|
const FriendInvites = findByProps("createFriendInvite");
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "FriendInvites",
|
name: "FriendInvites",
|
||||||
|
|
|
@ -8,14 +8,14 @@ import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { getCurrentChannel } from "@utils/discord";
|
import { getCurrentChannel } from "@utils/discord";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { findByCodeLazy, findByPropsLazy, findComponentByCodeLazy } from "@webpack";
|
import { findByCode, findByProps, findComponentByCode } from "@webpack";
|
||||||
import { RelationshipStore, Text } from "@webpack/common";
|
import { RelationshipStore, Text } from "@webpack/common";
|
||||||
|
|
||||||
const containerWrapper = findByPropsLazy("memberSinceWrapper");
|
const containerWrapper = findByProps("memberSinceWrapper");
|
||||||
const container = findByPropsLazy("memberSince");
|
const container = findByProps("memberSince");
|
||||||
const getCreatedAtDate = findByCodeLazy('month:"short",day:"numeric"');
|
const getCreatedAtDate = findByCode('month:"short",day:"numeric"');
|
||||||
const locale = findByPropsLazy("getLocale");
|
const locale = findByProps("getLocale");
|
||||||
const Section = findComponentByCodeLazy('"auto":"smooth"', ".section");
|
const Section = findComponentByCode('"auto":"smooth"', ".section");
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "FriendsSince",
|
name: "FriendsSince",
|
||||||
|
|
|
@ -21,11 +21,11 @@ import { migratePluginSettings } from "@api/Settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { NoopComponent } from "@utils/react";
|
import { NoopComponent } from "@utils/react";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { filters, findByPropsLazy, waitFor } from "@webpack";
|
import { filters, findProp, waitFor } from "@webpack";
|
||||||
import { ChannelStore, ContextMenuApi, i18n, UserStore } from "@webpack/common";
|
import { ChannelStore, ContextMenuApi, i18n, UserStore } from "@webpack/common";
|
||||||
import { Message } from "discord-types/general";
|
import { Message } from "discord-types/general";
|
||||||
|
|
||||||
const { useMessageMenu } = findByPropsLazy("useMessageMenu");
|
const useMessageMenu = findProp("useMessageMenu");
|
||||||
|
|
||||||
interface CopyIdMenuItemProps {
|
interface CopyIdMenuItemProps {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
|
@ -22,13 +22,13 @@ import { getUserSettingLazy } from "@api/UserSettings";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findComponentByCodeLazy } from "@webpack";
|
import { findComponentByCode } from "@webpack";
|
||||||
|
|
||||||
import style from "./style.css?managed";
|
import style from "./style.css?managed";
|
||||||
|
|
||||||
const Button = findComponentByCodeLazy("Button.Sizes.NONE,disabled:");
|
const Button = findComponentByCode("Button.Sizes.NONE,disabled:");
|
||||||
|
|
||||||
const ShowCurrentGame = getUserSettingLazy<boolean>("status", "showCurrentGame")!;
|
const ShowCurrentGame = getUserSettingLazy<boolean>("status", "showCurrentGame");
|
||||||
|
|
||||||
function makeIcon(showCurrentGame?: boolean) {
|
function makeIcon(showCurrentGame?: boolean) {
|
||||||
const { oldIcon } = settings.use(["oldIcon"]);
|
const { oldIcon } = settings.use(["oldIcon"]);
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findLazy } from "@webpack";
|
import { find } from "@webpack";
|
||||||
import { ContextMenuApi, FluxDispatcher, Menu, MessageActions } from "@webpack/common";
|
import { ContextMenuApi, FluxDispatcher, Menu, MessageActions } from "@webpack/common";
|
||||||
import { Channel, Message } from "discord-types/general";
|
import { Channel, Message } from "discord-types/general";
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ const settings = definePluginSettings({
|
||||||
unholyMultiGreetEnabled?: boolean;
|
unholyMultiGreetEnabled?: boolean;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const WELCOME_STICKERS = findLazy(m => Array.isArray(m) && m[0]?.name === "Wave");
|
const WELCOME_STICKERS = find(m => Array.isArray(m) && m[0]?.name === "Wave");
|
||||||
|
|
||||||
function greet(channel: Channel, message: Message, stickers: string[]) {
|
function greet(channel: Channel, message: Message, stickers: string[]) {
|
||||||
const options = MessageActions.getSendMessageOptionsForReply({
|
const options = MessageActions.getSendMessageOptionsForReply({
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { Flex } from "@components/Flex";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findStoreLazy } from "@webpack";
|
import { findStore } from "@webpack";
|
||||||
import { Button, Forms, showToast, TextInput, Toasts, Tooltip, useEffect, useState } from "webpack/common";
|
import { Button, Forms, showToast, TextInput, Toasts, Tooltip, useEffect, useState } from "webpack/common";
|
||||||
|
|
||||||
const enum ActivitiesTypes {
|
const enum ActivitiesTypes {
|
||||||
|
@ -31,9 +31,9 @@ const enum FilterMode {
|
||||||
Blacklist
|
Blacklist
|
||||||
}
|
}
|
||||||
|
|
||||||
const RunningGameStore = findStoreLazy("RunningGameStore");
|
const RunningGameStore = findStore("RunningGameStore");
|
||||||
|
|
||||||
const ShowCurrentGame = getUserSettingLazy("status", "showCurrentGame")!;
|
const ShowCurrentGame = getUserSettingLazy("status", "showCurrentGame");
|
||||||
|
|
||||||
function ToggleIcon(activity: IgnoredActivity, tooltipText: string, path: string, fill: string) {
|
function ToggleIcon(activity: IgnoredActivity, tooltipText: string, path: string, fill: string) {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -26,7 +26,7 @@ import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { Menu, ReactDOM } from "@webpack/common";
|
import { Menu, ReactDOM } from "@webpack/common";
|
||||||
import type { Root } from "react-dom/client";
|
import type { Root } from "react-dom/client";
|
||||||
|
|
||||||
import { Magnifier, MagnifierProps } from "./components/Magnifier";
|
import { Magnifier } from "./components/Magnifier";
|
||||||
import { ELEMENT_ID } from "./constants";
|
import { ELEMENT_ID } from "./constants";
|
||||||
import styles from "./styles.css?managed";
|
import styles from "./styles.css?managed";
|
||||||
|
|
||||||
|
@ -201,7 +201,7 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
|
|
||||||
// to stop from rendering twice /shrug
|
// to stop from rendering twice /shrug
|
||||||
currentMagnifierElement: null as React.FunctionComponentElement<MagnifierProps & JSX.IntrinsicAttributes> | null,
|
currentMagnifierElement: null as React.ReactNode,
|
||||||
element: null as HTMLDivElement | null,
|
element: null as HTMLDivElement | null,
|
||||||
|
|
||||||
Magnifier,
|
Magnifier,
|
||||||
|
|
|
@ -19,16 +19,26 @@
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findStoreLazy } from "@webpack";
|
import { findStore } from "@webpack";
|
||||||
import { ChannelStore, Constants, FluxDispatcher, GuildStore, RelationshipStore, SnowflakeUtils, UserStore } from "@webpack/common";
|
import { ChannelStore, Constants, FluxDispatcher, GuildStore, RelationshipStore, SnowflakeUtils, UserStore } from "@webpack/common";
|
||||||
import { Settings } from "Vencord";
|
|
||||||
|
|
||||||
const UserAffinitiesStore = findStoreLazy("UserAffinitiesStore");
|
const UserAffinitiesStore = findStore("UserAffinitiesStore");
|
||||||
|
|
||||||
|
const settings = definePluginSettings({
|
||||||
|
sortByAffinity: {
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
default: true,
|
||||||
|
description: "Whether to sort implicit relationships by their affinity to you.",
|
||||||
|
restartNeeded: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "ImplicitRelationships",
|
name: "ImplicitRelationships",
|
||||||
description: "Shows your implicit relationships in the Friends tab.",
|
description: "Shows your implicit relationships in the Friends tab.",
|
||||||
authors: [Devs.Dolfies],
|
authors: [Devs.Dolfies],
|
||||||
|
settings,
|
||||||
|
|
||||||
patches: [
|
patches: [
|
||||||
// Counts header
|
// Counts header
|
||||||
{
|
{
|
||||||
|
@ -75,7 +85,7 @@ export default definePlugin({
|
||||||
{
|
{
|
||||||
find: "getRelationshipCounts(){",
|
find: "getRelationshipCounts(){",
|
||||||
replacement: {
|
replacement: {
|
||||||
predicate: () => Settings.plugins.ImplicitRelationships.sortByAffinity,
|
predicate: () => settings.store.sortByAffinity,
|
||||||
match: /\}\)\.sortBy\((.+?)\)\.value\(\)/,
|
match: /\}\)\.sortBy\((.+?)\)\.value\(\)/,
|
||||||
replace: "}).sortBy(row => $self.wrapSort(($1), row)).value()"
|
replace: "}).sortBy(row => $self.wrapSort(($1), row)).value()"
|
||||||
}
|
}
|
||||||
|
@ -104,16 +114,6 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
settings: definePluginSettings(
|
|
||||||
{
|
|
||||||
sortByAffinity: {
|
|
||||||
type: OptionType.BOOLEAN,
|
|
||||||
default: true,
|
|
||||||
description: "Whether to sort implicit relationships by their affinity to you.",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
}
|
|
||||||
),
|
|
||||||
|
|
||||||
wrapSort(comparator: Function, row: any) {
|
wrapSort(comparator: Function, row: any) {
|
||||||
return row.type === 5
|
return row.type === 5
|
||||||
|
|
|
@ -20,7 +20,7 @@ import { registerCommand, unregisterCommand } from "@api/Commands";
|
||||||
import { addContextMenuPatch, removeContextMenuPatch } from "@api/ContextMenu";
|
import { addContextMenuPatch, removeContextMenuPatch } from "@api/ContextMenu";
|
||||||
import { Settings } from "@api/Settings";
|
import { Settings } from "@api/Settings";
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
import { canonicalizeFind } from "@utils/patches";
|
import { canonicalizeFind, canonicalizeReplacement } from "@utils/patches";
|
||||||
import { Patch, Plugin, ReporterTestable, StartAt } from "@utils/types";
|
import { Patch, Plugin, ReporterTestable, StartAt } from "@utils/types";
|
||||||
import { FluxDispatcher } from "@webpack/common";
|
import { FluxDispatcher } from "@webpack/common";
|
||||||
import { FluxEvents } from "@webpack/types";
|
import { FluxEvents } from "@webpack/types";
|
||||||
|
@ -66,10 +66,12 @@ export function addPatch(newPatch: Omit<Patch, "plugin">, pluginName: string) {
|
||||||
patch.replacement = [patch.replacement];
|
patch.replacement = [patch.replacement];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_REPORTER) {
|
for (const replacement of patch.replacement) {
|
||||||
patch.replacement.forEach(r => {
|
canonicalizeReplacement(replacement, pluginName);
|
||||||
delete r.predicate;
|
|
||||||
});
|
if (IS_REPORTER) {
|
||||||
|
delete replacement.predicate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
patch.replacement = patch.replacement.filter(({ predicate }) => !predicate || predicate());
|
patch.replacement = patch.replacement.filter(({ predicate }) => !predicate || predicate());
|
||||||
|
|
|
@ -21,7 +21,7 @@ import { Link } from "@components/Link";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findStore } from "@webpack";
|
||||||
import { ApplicationAssetUtils, FluxDispatcher, Forms } from "@webpack/common";
|
import { ApplicationAssetUtils, FluxDispatcher, Forms } from "@webpack/common";
|
||||||
|
|
||||||
interface ActivityAssets {
|
interface ActivityAssets {
|
||||||
|
@ -86,7 +86,7 @@ const placeholderId = "2a96cbd8b46e442fc41c2b86b821562f";
|
||||||
|
|
||||||
const logger = new Logger("LastFMRichPresence");
|
const logger = new Logger("LastFMRichPresence");
|
||||||
|
|
||||||
const presenceStore = findByPropsLazy("getLocalPresence");
|
const SelfPresenceStore = findStore("SelfPresenceStore");
|
||||||
|
|
||||||
async function getApplicationAsset(key: string): Promise<string> {
|
async function getApplicationAsset(key: string): Promise<string> {
|
||||||
return (await ApplicationAssetUtils.fetchAssetIds(applicationId, [key]))[0];
|
return (await ApplicationAssetUtils.fetchAssetIds(applicationId, [key]))[0];
|
||||||
|
@ -275,7 +275,7 @@ export default definePlugin({
|
||||||
|
|
||||||
async getActivity(): Promise<Activity | null> {
|
async getActivity(): Promise<Activity | null> {
|
||||||
if (settings.store.hideWithSpotify) {
|
if (settings.store.hideWithSpotify) {
|
||||||
for (const activity of presenceStore.getActivities()) {
|
for (const activity of SelfPresenceStore.getActivities()) {
|
||||||
if (activity.type === ActivityType.LISTENING && activity.application_id !== applicationId) {
|
if (activity.type === ActivityType.LISTENING && activity.application_id !== applicationId) {
|
||||||
// there is already music status because of Spotify or richerCider (probably more)
|
// there is already music status because of Spotify or richerCider (probably more)
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -23,20 +23,19 @@ import { classNameFactory } from "@api/Styles";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findStoreLazy } from "@webpack";
|
import { findStore } from "@webpack";
|
||||||
import { FluxStore } from "@webpack/types";
|
import { FluxStore } from "@webpack/types";
|
||||||
|
|
||||||
import { MemberCount } from "./MemberCount";
|
import { MemberCount } from "./MemberCount";
|
||||||
|
|
||||||
export const GuildMemberCountStore = findStoreLazy("GuildMemberCountStore") as FluxStore & { getMemberCount(guildId?: string): number | null; };
|
export const GuildMemberCountStore = findStore("GuildMemberCountStore") as FluxStore & { getMemberCount(guildId?: string): number | null; };
|
||||||
export const ChannelMemberStore = findStoreLazy("ChannelMemberStore") as FluxStore & {
|
export const ChannelMemberStore = findStore("ChannelMemberStore") as FluxStore & {
|
||||||
getProps(guildId?: string, channelId?: string): { groups: { count: number; id: string; }[]; };
|
getProps(guildId?: string, channelId?: string): { groups: { count: number; id: string; }[]; };
|
||||||
};
|
};
|
||||||
export const ThreadMemberListStore = findStoreLazy("ThreadMemberListStore") as FluxStore & {
|
export const ThreadMemberListStore = findStore("ThreadMemberListStore") as FluxStore & {
|
||||||
getMemberListSections(channelId?: string): { [sectionId: string]: { sectionId: string; userIds: string[]; }; };
|
getMemberListSections(channelId?: string): { [sectionId: string]: { sectionId: string; userIds: string[]; }; };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const settings = definePluginSettings({
|
const settings = definePluginSettings({
|
||||||
toolTip: {
|
toolTip: {
|
||||||
type: OptionType.BOOLEAN,
|
type: OptionType.BOOLEAN,
|
||||||
|
|
|
@ -20,11 +20,11 @@ import { addClickListener, removeClickListener } from "@api/MessageEvents";
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findByProps, findStore } from "@webpack";
|
||||||
import { FluxDispatcher, PermissionsBits, PermissionStore, UserStore } from "@webpack/common";
|
import { FluxDispatcher, PermissionsBits, PermissionStore, UserStore } from "@webpack/common";
|
||||||
|
|
||||||
const MessageActions = findByPropsLazy("deleteMessage", "startEditMessage");
|
const MessageActions = findByProps("deleteMessage", "startEditMessage");
|
||||||
const EditStore = findByPropsLazy("isEditing", "isEditingAny");
|
const EditMessageStore = findStore("EditMessageStore");
|
||||||
|
|
||||||
let isDeletePressed = false;
|
let isDeletePressed = false;
|
||||||
const keydown = (e: KeyboardEvent) => e.key === "Backspace" && (isDeletePressed = true);
|
const keydown = (e: KeyboardEvent) => e.key === "Backspace" && (isDeletePressed = true);
|
||||||
|
@ -74,7 +74,7 @@ export default definePlugin({
|
||||||
if (msg.deleted === true) return;
|
if (msg.deleted === true) return;
|
||||||
|
|
||||||
if (isMe) {
|
if (isMe) {
|
||||||
if (!settings.store.enableDoubleClickToEdit || EditStore.isEditing(channel.id, msg.id)) return;
|
if (!settings.store.enableDoubleClickToEdit || EditMessageStore.isEditing(channel.id, msg.id)) return;
|
||||||
|
|
||||||
MessageActions.startEditMessage(channel.id, msg.id, msg.content);
|
MessageActions.startEditMessage(channel.id, msg.id, msg.content);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
|
@ -9,7 +9,7 @@ import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { isNonNullish } from "@utils/guards";
|
import { isNonNullish } from "@utils/guards";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findExportedComponentLazy } from "@webpack";
|
import { findExportedComponent } from "@webpack";
|
||||||
import { SnowflakeUtils, Tooltip } from "@webpack/common";
|
import { SnowflakeUtils, Tooltip } from "@webpack/common";
|
||||||
import { Message } from "discord-types/general";
|
import { Message } from "discord-types/general";
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ interface Diff {
|
||||||
}
|
}
|
||||||
|
|
||||||
const DISCORD_KT_DELAY = 1471228928;
|
const DISCORD_KT_DELAY = 1471228928;
|
||||||
const HiddenVisually = findExportedComponentLazy("HiddenVisually");
|
const HiddenVisually = findExportedComponent("HiddenVisually");
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "MessageLatency",
|
name: "MessageLatency",
|
||||||
|
|
|
@ -25,7 +25,7 @@ import { Devs } from "@utils/constants.js";
|
||||||
import { classes } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import { Queue } from "@utils/Queue";
|
import { Queue } from "@utils/Queue";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByPropsLazy, findComponentByCodeLazy } from "@webpack";
|
import { findByProps, findComponentByCode } from "@webpack";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
ChannelStore,
|
ChannelStore,
|
||||||
|
@ -47,14 +47,14 @@ const messageCache = new Map<string, {
|
||||||
fetched: boolean;
|
fetched: boolean;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const Embed = findComponentByCodeLazy(".inlineMediaEmbed");
|
const Embed = findComponentByCode(".inlineMediaEmbed");
|
||||||
const AutoModEmbed = findComponentByCodeLazy(".withFooter]:", "childrenMessageContent:");
|
const AutoModEmbed = findComponentByCode(".withFooter]:", "childrenMessageContent:");
|
||||||
const ChannelMessage = findComponentByCodeLazy("childrenExecutedCommand:", ".hideAccessories");
|
const ChannelMessage = findComponentByCode("childrenExecutedCommand:", ".hideAccessories");
|
||||||
|
|
||||||
const SearchResultClasses = findByPropsLazy("message", "searchResult");
|
const SearchResultClasses = findByProps("message", "searchResult");
|
||||||
const EmbedClasses = findByPropsLazy("embedAuthorIcon", "embedAuthor", "embedAuthor");
|
const EmbedClasses = findByProps("embedAuthorIcon", "embedAuthor", "embedAuthor");
|
||||||
|
|
||||||
const MessageDisplayCompact = getUserSettingLazy("textAndImages", "messageDisplayCompact")!;
|
const MessageDisplayCompact = getUserSettingLazy("textAndImages", "messageDisplayCompact");
|
||||||
|
|
||||||
const messageLinkRegex = /(?<!<)https?:\/\/(?:\w+\.)?discord(?:app)?\.com\/channels\/(?:\d{17,20}|@me)\/(\d{17,20})\/(\d{17,20})/g;
|
const messageLinkRegex = /(?<!<)https?:\/\/(?:\w+\.)?discord(?:app)?\.com\/channels\/(?:\d{17,20}|@me)\/(\d{17,20})\/(\d{17,20})/g;
|
||||||
const tenorRegex = /^https:\/\/(?:www\.)?tenor\.com\//;
|
const tenorRegex = /^https:\/\/(?:www\.)?tenor\.com\//;
|
||||||
|
@ -215,10 +215,9 @@ function computeWidthAndHeight(width: number, height: number) {
|
||||||
|
|
||||||
function withEmbeddedBy(message: Message, embeddedBy: string[]) {
|
function withEmbeddedBy(message: Message, embeddedBy: string[]) {
|
||||||
return new Proxy(message, {
|
return new Proxy(message, {
|
||||||
get(_, prop) {
|
get(target, prop, receiver) {
|
||||||
if (prop === "vencordEmbeddedBy") return embeddedBy;
|
if (prop === "vencordEmbeddedBy") return embeddedBy;
|
||||||
// @ts-ignore ts so bad
|
return Reflect.get(target, prop, receiver);
|
||||||
return Reflect.get(...arguments);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,13 +9,13 @@ import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
import { classes } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import { ModalCloseButton, ModalContent, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
import { ModalCloseButton, ModalContent, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findByProps } from "@webpack";
|
||||||
import { TabBar, Text, Timestamp, TooltipContainer, useState } from "@webpack/common";
|
import { TabBar, Text, Timestamp, TooltipContainer, useState } from "@webpack/common";
|
||||||
|
|
||||||
import { parseEditContent } from ".";
|
import { parseEditContent } from ".";
|
||||||
|
|
||||||
const CodeContainerClasses = findByPropsLazy("markup", "codeContainer");
|
const CodeContainerClasses = findByProps("markup", "codeContainer");
|
||||||
const MiscClasses = findByPropsLazy("messageContent", "markupRtl");
|
const MiscClasses = findByProps("messageContent", "markupRtl");
|
||||||
|
|
||||||
const cl = classNameFactory("vc-ml-modal-");
|
const cl = classNameFactory("vc-ml-modal-");
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ import "./messageLogger.css";
|
||||||
|
|
||||||
import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
|
import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
|
||||||
import { updateMessage } from "@api/MessageUpdater";
|
import { updateMessage } from "@api/MessageUpdater";
|
||||||
import { Settings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import { disableStyle, enableStyle } from "@api/Styles";
|
import { disableStyle, enableStyle } from "@api/Styles";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
|
@ -28,7 +28,7 @@ import { proxyLazy } from "@utils/lazy";
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
import { classes } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByCodeLazy, findByPropsLazy } from "@webpack";
|
import { findByCode, findByProps } from "@webpack";
|
||||||
import { ChannelStore, FluxDispatcher, i18n, Menu, MessageStore, Parser, SelectedChannelStore, Timestamp, UserStore, useStateFromStores } from "@webpack/common";
|
import { ChannelStore, FluxDispatcher, i18n, Menu, MessageStore, Parser, SelectedChannelStore, Timestamp, UserStore, useStateFromStores } from "@webpack/common";
|
||||||
import { Message } from "discord-types/general";
|
import { Message } from "discord-types/general";
|
||||||
|
|
||||||
|
@ -42,11 +42,11 @@ interface MLMessage extends Message {
|
||||||
firstEditTimestamp?: Date;
|
firstEditTimestamp?: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = findByPropsLazy("edited", "communicationDisabled", "isSystemMessage");
|
const styles = findByProps("edited", "communicationDisabled", "isSystemMessage");
|
||||||
const getMessage = findByCodeLazy('replace(/^\\n+|\\n+$/g,"")');
|
const getMessage = findByCode('replace(/^\\n+|\\n+$/g,"")');
|
||||||
|
|
||||||
function addDeleteStyle() {
|
function addDeleteStyle() {
|
||||||
if (Settings.plugins.MessageLogger.deleteStyle === "text") {
|
if (settings.store.deleteStyle === "text") {
|
||||||
enableStyle(textStyle);
|
enableStyle(textStyle);
|
||||||
disableStyle(overlayStyle);
|
disableStyle(overlayStyle);
|
||||||
} else {
|
} else {
|
||||||
|
@ -142,11 +142,70 @@ export function parseEditContent(content: string, message: Message) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const settings = definePluginSettings({
|
||||||
|
deleteStyle: {
|
||||||
|
type: OptionType.SELECT,
|
||||||
|
description: "The style of deleted messages",
|
||||||
|
default: "text",
|
||||||
|
options: [
|
||||||
|
{ label: "Red text", value: "text", default: true },
|
||||||
|
{ label: "Red overlay", value: "overlay" }
|
||||||
|
],
|
||||||
|
onChange: () => addDeleteStyle()
|
||||||
|
},
|
||||||
|
logDeletes: {
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
description: "Whether to log deleted messages",
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
collapseDeleted: {
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
description: "Whether to collapse deleted messages, similar to blocked messages",
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
logEdits: {
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
description: "Whether to log edited messages",
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
inlineEdits: {
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
description: "Whether to display edit history as part of message content",
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
ignoreBots: {
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
description: "Whether to ignore messages by bots",
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
ignoreSelf: {
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
description: "Whether to ignore messages by yourself",
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
ignoreUsers: {
|
||||||
|
type: OptionType.STRING,
|
||||||
|
description: "Comma-separated list of user IDs to ignore",
|
||||||
|
default: ""
|
||||||
|
},
|
||||||
|
ignoreChannels: {
|
||||||
|
type: OptionType.STRING,
|
||||||
|
description: "Comma-separated list of channel IDs to ignore",
|
||||||
|
default: ""
|
||||||
|
},
|
||||||
|
ignoreGuilds: {
|
||||||
|
type: OptionType.STRING,
|
||||||
|
description: "Comma-separated list of guild IDs to ignore",
|
||||||
|
default: ""
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "MessageLogger",
|
name: "MessageLogger",
|
||||||
description: "Temporarily logs deleted and edited messages.",
|
description: "Temporarily logs deleted and edited messages.",
|
||||||
authors: [Devs.rushii, Devs.Ven, Devs.AutumnVN, Devs.Nickyux, Devs.Kyuuhachi],
|
authors: [Devs.rushii, Devs.Ven, Devs.AutumnVN, Devs.Nickyux, Devs.Kyuuhachi],
|
||||||
dependencies: ["MessageUpdaterAPI"],
|
dependencies: ["MessageUpdaterAPI"],
|
||||||
|
settings,
|
||||||
|
|
||||||
contextMenus: {
|
contextMenus: {
|
||||||
"message": patchMessageContextMenu,
|
"message": patchMessageContextMenu,
|
||||||
|
@ -168,7 +227,7 @@ export default definePlugin({
|
||||||
(oldMsg, newMsg) => oldMsg?.editHistory === newMsg?.editHistory
|
(oldMsg, newMsg) => oldMsg?.editHistory === newMsg?.editHistory
|
||||||
);
|
);
|
||||||
|
|
||||||
return Settings.plugins.MessageLogger.inlineEdits && (
|
return settings.store.inlineEdits && (
|
||||||
<>
|
<>
|
||||||
{message.editHistory?.map(edit => (
|
{message.editHistory?.map(edit => (
|
||||||
<div className="messagelogger-edited">
|
<div className="messagelogger-edited">
|
||||||
|
@ -193,64 +252,6 @@ export default definePlugin({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
options: {
|
|
||||||
deleteStyle: {
|
|
||||||
type: OptionType.SELECT,
|
|
||||||
description: "The style of deleted messages",
|
|
||||||
default: "text",
|
|
||||||
options: [
|
|
||||||
{ label: "Red text", value: "text", default: true },
|
|
||||||
{ label: "Red overlay", value: "overlay" }
|
|
||||||
],
|
|
||||||
onChange: () => addDeleteStyle()
|
|
||||||
},
|
|
||||||
logDeletes: {
|
|
||||||
type: OptionType.BOOLEAN,
|
|
||||||
description: "Whether to log deleted messages",
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
collapseDeleted: {
|
|
||||||
type: OptionType.BOOLEAN,
|
|
||||||
description: "Whether to collapse deleted messages, similar to blocked messages",
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
logEdits: {
|
|
||||||
type: OptionType.BOOLEAN,
|
|
||||||
description: "Whether to log edited messages",
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
inlineEdits: {
|
|
||||||
type: OptionType.BOOLEAN,
|
|
||||||
description: "Whether to display edit history as part of message content",
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
ignoreBots: {
|
|
||||||
type: OptionType.BOOLEAN,
|
|
||||||
description: "Whether to ignore messages by bots",
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
ignoreSelf: {
|
|
||||||
type: OptionType.BOOLEAN,
|
|
||||||
description: "Whether to ignore messages by yourself",
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
ignoreUsers: {
|
|
||||||
type: OptionType.STRING,
|
|
||||||
description: "Comma-separated list of user IDs to ignore",
|
|
||||||
default: ""
|
|
||||||
},
|
|
||||||
ignoreChannels: {
|
|
||||||
type: OptionType.STRING,
|
|
||||||
description: "Comma-separated list of channel IDs to ignore",
|
|
||||||
default: ""
|
|
||||||
},
|
|
||||||
ignoreGuilds: {
|
|
||||||
type: OptionType.STRING,
|
|
||||||
description: "Comma-separated list of guild IDs to ignore",
|
|
||||||
default: ""
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
handleDelete(cache: any, data: { ids: string[], id: string; mlDeleted?: boolean; }, isBulk: boolean) {
|
handleDelete(cache: any, data: { ids: string[], id: string; mlDeleted?: boolean; }, isBulk: boolean) {
|
||||||
try {
|
try {
|
||||||
if (cache == null || (!isBulk && !cache.has(data.id))) return cache;
|
if (cache == null || (!isBulk && !cache.has(data.id))) return cache;
|
||||||
|
@ -285,7 +286,7 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
|
|
||||||
shouldIgnore(message: any, isEdit = false) {
|
shouldIgnore(message: any, isEdit = false) {
|
||||||
const { ignoreBots, ignoreSelf, ignoreUsers, ignoreChannels, ignoreGuilds, logEdits, logDeletes } = Settings.plugins.MessageLogger;
|
const { ignoreBots, ignoreSelf, ignoreUsers, ignoreChannels, ignoreGuilds, logEdits, logDeletes } = settings.store;
|
||||||
const myId = UserStore.getCurrentUser().id;
|
const myId = UserStore.getCurrentUser().id;
|
||||||
|
|
||||||
return ignoreBots && message.author?.bot ||
|
return ignoreBots && message.author?.bot ||
|
||||||
|
@ -493,7 +494,7 @@ export default definePlugin({
|
||||||
match: /if\((\i)\.blocked\)return \i\.\i\.MESSAGE_GROUP_BLOCKED;/,
|
match: /if\((\i)\.blocked\)return \i\.\i\.MESSAGE_GROUP_BLOCKED;/,
|
||||||
replace: '$&else if($1.deleted) return"MESSAGE_GROUP_DELETED";',
|
replace: '$&else if($1.deleted) return"MESSAGE_GROUP_DELETED";',
|
||||||
},
|
},
|
||||||
predicate: () => Settings.plugins.MessageLogger.collapseDeleted
|
predicate: () => settings.store.collapseDeleted
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Message group rendering
|
// Message group rendering
|
||||||
|
@ -508,7 +509,7 @@ export default definePlugin({
|
||||||
replace: '$&$1.type==="MESSAGE_GROUP_DELETED"?$self.Messages.DELETED_MESSAGE_COUNT:',
|
replace: '$&$1.type==="MESSAGE_GROUP_DELETED"?$self.Messages.DELETED_MESSAGE_COUNT:',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
predicate: () => Settings.plugins.MessageLogger.collapseDeleted
|
predicate: () => settings.store.collapseDeleted
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
import { ApplicationCommandInputType, ApplicationCommandOptionType, findOption, registerCommand, sendBotMessage, unregisterCommand } from "@api/Commands";
|
import { ApplicationCommandInputType, ApplicationCommandOptionType, findOption, registerCommand, sendBotMessage, unregisterCommand } from "@api/Commands";
|
||||||
import * as DataStore from "@api/DataStore";
|
import * as DataStore from "@api/DataStore";
|
||||||
import { Settings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ function createTagCommand(tag: Tag) {
|
||||||
return { content: `/${tag.name}` };
|
return { content: `/${tag.name}` };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings.plugins.MessageTags.clyde) sendBotMessage(ctx.channel.id, {
|
if (settings.store.clyde) sendBotMessage(ctx.channel.id, {
|
||||||
content: `${EMOTE} The tag **${tag.name}** has been sent!`
|
content: `${EMOTE} The tag **${tag.name}** has been sent!`
|
||||||
});
|
});
|
||||||
return { content: tag.message.replaceAll("\\n", "\n") };
|
return { content: tag.message.replaceAll("\\n", "\n") };
|
||||||
|
@ -69,19 +69,20 @@ function createTagCommand(tag: Tag) {
|
||||||
}, "CustomTags");
|
}, "CustomTags");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const settings = definePluginSettings({
|
||||||
|
clyde: {
|
||||||
|
name: "Clyde message on send",
|
||||||
|
description: "If enabled, clyde will send you an ephemeral message when a tag was used.",
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "MessageTags",
|
name: "MessageTags",
|
||||||
description: "Allows you to save messages and to use them with a simple command.",
|
description: "Allows you to save messages and to use them with a simple command.",
|
||||||
authors: [Devs.Luna],
|
authors: [Devs.Luna],
|
||||||
options: {
|
settings,
|
||||||
clyde: {
|
|
||||||
name: "Clyde message on send",
|
|
||||||
description: "If enabled, clyde will send you an ephemeral message when a tag was used.",
|
|
||||||
type: OptionType.BOOLEAN,
|
|
||||||
default: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async start() {
|
async start() {
|
||||||
for (const tag of await getTags()) createTagCommand(tag);
|
for (const tag of await getTags()) createTagCommand(tag);
|
||||||
|
|
|
@ -19,11 +19,12 @@
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import { Flex } from "@components/Flex";
|
import { Flex } from "@components/Flex";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
|
import { LazyComponentType } from "@utils/lazyReact";
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByCodeLazy, findLazy } from "@webpack";
|
import { findByCode, findComponentByCode } from "@webpack";
|
||||||
import { Card, ChannelStore, Forms, GuildStore, PermissionsBits, Switch, TextInput, Tooltip } from "@webpack/common";
|
import { Card, ChannelStore, Forms, GuildStore, PermissionsBits, Switch, TextInput, Tooltip } from "@webpack/common";
|
||||||
import type { Permissions, RC } from "@webpack/types";
|
import type { Permissions } from "@webpack/types";
|
||||||
import type { Channel, Guild, Message, User } from "discord-types/general";
|
import type { Channel, Guild, Message, User } from "discord-types/general";
|
||||||
|
|
||||||
interface Tag {
|
interface Tag {
|
||||||
|
@ -59,9 +60,9 @@ const computePermissions: (options: {
|
||||||
overwrites?: Channel["permissionOverwrites"] | null;
|
overwrites?: Channel["permissionOverwrites"] | null;
|
||||||
checkElevated?: boolean /* = true */;
|
checkElevated?: boolean /* = true */;
|
||||||
excludeGuildPermissions?: boolean /* = false */;
|
excludeGuildPermissions?: boolean /* = false */;
|
||||||
}) => bigint = findByCodeLazy(".getCurrentUser()", ".computeLurkerPermissionsAllowList()");
|
}) => bigint = findByCode(".getCurrentUser()", ".computeLurkerPermissionsAllowList()");
|
||||||
|
|
||||||
const Tag = findLazy(m => m.Types?.[0] === "BOT") as RC<{ type?: number, className?: string, useRemSizes?: boolean; }> & { Types: Record<string, number>; };
|
const Tag = findComponentByCode(".DISCORD_SYSTEM_MESSAGE_BOT_TAG_TOOLTIP_OFFICIAL,") as LazyComponentType<{ type?: number, className?: string, useRemSizes?: boolean; }> & { Types: Record<string, number>; };
|
||||||
|
|
||||||
const isWebhook = (message: Message, user: User) => !!message?.webhookId && user.isNonUserBot();
|
const isWebhook = (message: Message, user: User) => !!message?.webhookId && user.isNonUserBot();
|
||||||
|
|
||||||
|
|
|
@ -20,16 +20,16 @@ import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { isNonNullish } from "@utils/guards";
|
import { isNonNullish } from "@utils/guards";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { findByPropsLazy, findComponentByCodeLazy } from "@webpack";
|
import { findByProps, findComponentByCode } from "@webpack";
|
||||||
import { Avatar, ChannelStore, Clickable, IconUtils, RelationshipStore, ScrollerThin, useMemo, UserStore } from "@webpack/common";
|
import { Avatar, ChannelStore, Clickable, IconUtils, RelationshipStore, ScrollerThin, useMemo, UserStore } from "@webpack/common";
|
||||||
import { Channel, User } from "discord-types/general";
|
import { Channel, User } from "discord-types/general";
|
||||||
|
|
||||||
const SelectedChannelActionCreators = findByPropsLazy("selectPrivateChannel");
|
const SelectedChannelActionCreators = findByProps("selectPrivateChannel");
|
||||||
const UserUtils = findByPropsLazy("getGlobalName");
|
const UserUtils = findByProps("getGlobalName");
|
||||||
|
|
||||||
const ProfileListClasses = findByPropsLazy("emptyIconFriends", "emptyIconGuilds");
|
const ProfileListClasses = findByProps("emptyIconFriends", "emptyIconGuilds");
|
||||||
const ExpandableList = findComponentByCodeLazy(".mutualFriendItem]");
|
const ExpandableList = findComponentByCode(".mutualFriendItem]");
|
||||||
const GuildLabelClasses = findByPropsLazy("guildNick", "guildAvatarWithoutIcon");
|
const GuildLabelClasses = findByProps("guildNick", "guildAvatarWithoutIcon");
|
||||||
|
|
||||||
function getGroupDMName(channel: Channel) {
|
function getGroupDMName(channel: Channel) {
|
||||||
return channel.name ||
|
return channel.name ||
|
||||||
|
|
|
@ -24,18 +24,18 @@ import { definePluginSettings, migratePluginSettings } from "@api/Settings";
|
||||||
import { CogWheel } from "@components/Icons";
|
import { CogWheel } from "@components/Icons";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByCodeLazy, findByPropsLazy, mapMangledModuleLazy } from "@webpack";
|
import { findByCode, findProp, mapMangledModule } from "@webpack";
|
||||||
import { Menu } from "@webpack/common";
|
import { Menu } from "@webpack/common";
|
||||||
import { Guild } from "discord-types/general";
|
import { Guild } from "discord-types/general";
|
||||||
|
|
||||||
const { updateGuildNotificationSettings } = findByPropsLazy("updateGuildNotificationSettings");
|
const updateGuildNotificationSettings = findProp("updateGuildNotificationSettings");
|
||||||
const { toggleShowAllChannels } = mapMangledModuleLazy(".onboardExistingMember(", {
|
const { toggleShowAllChannels } = mapMangledModule(".onboardExistingMember(", {
|
||||||
toggleShowAllChannels: m => {
|
toggleShowAllChannels: m => {
|
||||||
const s = String(m);
|
const s = String(m);
|
||||||
return s.length < 100 && !s.includes("onboardExistingMember") && !s.includes("getOptedInChannels");
|
return s.length < 100 && !s.includes("onboardExistingMember") && !s.includes("getOptedInChannels");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const isOptInEnabledForGuild = findByCodeLazy(".COMMUNITY)||", ".isOptInEnabled(");
|
const isOptInEnabledForGuild = findByCode(".COMMUNITY)||", ".isOptInEnabled(");
|
||||||
|
|
||||||
const settings = definePluginSettings({
|
const settings = definePluginSettings({
|
||||||
guild: {
|
guild: {
|
||||||
|
|
|
@ -16,19 +16,28 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Settings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { RelationshipStore } from "@webpack/common";
|
||||||
import { Message } from "discord-types/general";
|
import { Message } from "discord-types/general";
|
||||||
|
|
||||||
const RelationshipStore = findByPropsLazy("getRelationships", "isBlocked");
|
const settings = definePluginSettings({
|
||||||
|
ignoreBlockedMessages: {
|
||||||
|
description: "Completely ignores (recent) incoming messages from blocked users (locally).",
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
default: false,
|
||||||
|
restartNeeded: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "NoBlockedMessages",
|
name: "NoBlockedMessages",
|
||||||
description: "Hides all blocked messages from chat completely.",
|
description: "Hides all blocked messages from chat completely.",
|
||||||
authors: [Devs.rushii, Devs.Samu],
|
authors: [Devs.rushii, Devs.Samu],
|
||||||
|
settings,
|
||||||
|
|
||||||
patches: [
|
patches: [
|
||||||
{
|
{
|
||||||
find: "Messages.BLOCKED_MESSAGES_HIDE",
|
find: "Messages.BLOCKED_MESSAGES_HIDE",
|
||||||
|
@ -44,7 +53,7 @@ export default definePlugin({
|
||||||
'"displayName","ReadStateStore")'
|
'"displayName","ReadStateStore")'
|
||||||
].map(find => ({
|
].map(find => ({
|
||||||
find,
|
find,
|
||||||
predicate: () => Settings.plugins.NoBlockedMessages.ignoreBlockedMessages === true,
|
predicate: () => settings.store.ignoreBlockedMessages === true,
|
||||||
replacement: [
|
replacement: [
|
||||||
{
|
{
|
||||||
match: /(?<=function (\i)\((\i)\){)(?=.*MESSAGE_CREATE:\1)/,
|
match: /(?<=function (\i)\((\i)\){)(?=.*MESSAGE_CREATE:\1)/,
|
||||||
|
|
|
@ -19,9 +19,9 @@
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findStore } from "@webpack";
|
||||||
|
|
||||||
const MessageRequestStore = findByPropsLazy("getMessageRequestsCount");
|
const MessageRequestStore = findStore("MessageRequestStore");
|
||||||
|
|
||||||
const settings = definePluginSettings({
|
const settings = definePluginSettings({
|
||||||
hideFriendRequestsCount: {
|
hideFriendRequestsCount: {
|
||||||
|
|
|
@ -21,7 +21,7 @@ import { Flex } from "@components/Flex";
|
||||||
import { InfoIcon, OwnerCrownIcon } from "@components/Icons";
|
import { InfoIcon, OwnerCrownIcon } from "@components/Icons";
|
||||||
import { getUniqueUsername } from "@utils/discord";
|
import { getUniqueUsername } from "@utils/discord";
|
||||||
import { ModalCloseButton, ModalContent, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
import { ModalCloseButton, ModalContent, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
||||||
import { findByCodeLazy } from "@webpack";
|
import { findByCode } from "@webpack";
|
||||||
import { Clipboard, ContextMenuApi, FluxDispatcher, GuildMemberStore, GuildStore, i18n, Menu, PermissionsBits, ScrollerThin, Text, Tooltip, useEffect, UserStore, useState, useStateFromStores } from "@webpack/common";
|
import { Clipboard, ContextMenuApi, FluxDispatcher, GuildMemberStore, GuildStore, i18n, Menu, PermissionsBits, ScrollerThin, Text, Tooltip, useEffect, UserStore, useState, useStateFromStores } from "@webpack/common";
|
||||||
import { UnicodeEmoji } from "@webpack/types";
|
import { UnicodeEmoji } from "@webpack/types";
|
||||||
import type { Guild, Role, User } from "discord-types/general";
|
import type { Guild, Role, User } from "discord-types/general";
|
||||||
|
@ -45,7 +45,7 @@ export interface RoleOrUserPermission {
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetRoleIconData = (role: Role, size: number) => { customIconSrc?: string; unicodeEmoji?: UnicodeEmoji; };
|
type GetRoleIconData = (role: Role, size: number) => { customIconSrc?: string; unicodeEmoji?: UnicodeEmoji; };
|
||||||
const getRoleIconData: GetRoleIconData = findByCodeLazy("convertSurrogateToName", "customIconSrc", "unicodeEmoji");
|
const getRoleIconData: GetRoleIconData = findByCode("convertSurrogateToName", "customIconSrc", "unicodeEmoji");
|
||||||
|
|
||||||
function getRoleIconSrc(role: Role) {
|
function getRoleIconSrc(role: Role) {
|
||||||
const icon = getRoleIconData(role, 20);
|
const icon = getRoleIconData(role, 20);
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { ExpandableHeader } from "@components/ExpandableHeader";
|
import { ExpandableHeader } from "@components/ExpandableHeader";
|
||||||
import { classes } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import { filters, findBulk, proxyLazyWebpack } from "@webpack";
|
import { findByProps } from "@webpack";
|
||||||
import { i18n, PermissionsBits, Text, Tooltip, useMemo, UserStore } from "@webpack/common";
|
import { i18n, PermissionsBits, Text, Tooltip, useMemo, UserStore } from "@webpack/common";
|
||||||
import type { Guild, GuildMember } from "discord-types/general";
|
import type { Guild, GuildMember } from "discord-types/general";
|
||||||
|
|
||||||
|
@ -36,15 +36,9 @@ interface UserPermission {
|
||||||
|
|
||||||
type UserPermissions = Array<UserPermission>;
|
type UserPermissions = Array<UserPermission>;
|
||||||
|
|
||||||
const { RoleRootClasses, RoleClasses, RoleBorderClasses } = proxyLazyWebpack(() => {
|
const RoleRootClasses = findByProps("root", "expandButton", "collapseButton");
|
||||||
const [RoleRootClasses, RoleClasses, RoleBorderClasses] = findBulk(
|
const RoleClasses = findByProps("role", "roleCircle", "roleName");
|
||||||
filters.byProps("root", "expandButton", "collapseButton"),
|
const RoleBorderClasses = findByProps("roleCircle", "dot", "dotBorderColor");
|
||||||
filters.byProps("role", "roleCircle", "roleName"),
|
|
||||||
filters.byProps("roleCircle", "dot", "dotBorderColor")
|
|
||||||
) as Record<string, string>[];
|
|
||||||
|
|
||||||
return { RoleRootClasses, RoleClasses, RoleBorderClasses };
|
|
||||||
});
|
|
||||||
|
|
||||||
interface FakeRoleProps extends React.HTMLAttributes<HTMLDivElement> {
|
interface FakeRoleProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||||
text: string;
|
text: string;
|
||||||
|
|
|
@ -25,7 +25,7 @@ import { SafetyIcon } from "@components/Icons";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { classes } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findByProps } from "@webpack";
|
||||||
import { Button, ChannelStore, Dialog, GuildMemberStore, GuildStore, match, Menu, PermissionsBits, Popout, TooltipContainer, UserStore } from "@webpack/common";
|
import { Button, ChannelStore, Dialog, GuildMemberStore, GuildStore, match, Menu, PermissionsBits, Popout, TooltipContainer, UserStore } from "@webpack/common";
|
||||||
import type { Guild, GuildMember } from "discord-types/general";
|
import type { Guild, GuildMember } from "discord-types/general";
|
||||||
|
|
||||||
|
@ -33,8 +33,8 @@ import openRolesAndUsersPermissionsModal, { PermissionType, RoleOrUserPermission
|
||||||
import UserPermissions from "./components/UserPermissions";
|
import UserPermissions from "./components/UserPermissions";
|
||||||
import { getSortedRoles, sortPermissionOverwrites } from "./utils";
|
import { getSortedRoles, sortPermissionOverwrites } from "./utils";
|
||||||
|
|
||||||
const PopoutClasses = findByPropsLazy("container", "scroller", "list");
|
const PopoutClasses = findByProps("container", "scroller", "list");
|
||||||
const RoleButtonClasses = findByPropsLazy("button", "buttonInner", "icon", "banner");
|
const RoleButtonClasses = findByProps("button", "buttonInner", "icon", "banner");
|
||||||
|
|
||||||
export const enum PermissionsSortOrder {
|
export const enum PermissionsSortOrder {
|
||||||
HighestRole,
|
HighestRole,
|
||||||
|
|
|
@ -20,7 +20,7 @@ import { ApplicationCommandInputType, ApplicationCommandOptionType, Argument, Co
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { makeLazy } from "@utils/lazy";
|
import { makeLazy } from "@utils/lazy";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findStore } from "@webpack";
|
||||||
import { DraftType, UploadHandler, UploadManager, UserUtils } from "@webpack/common";
|
import { DraftType, UploadHandler, UploadManager, UserUtils } from "@webpack/common";
|
||||||
import { applyPalette, GIFEncoder, quantize } from "gifenc";
|
import { applyPalette, GIFEncoder, quantize } from "gifenc";
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ const getFrames = makeLazy(() => Promise.all(
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
|
|
||||||
const UploadStore = findByPropsLazy("getUploads");
|
const UploadAttachmentStore = findStore("UploadAttachmentStore");
|
||||||
|
|
||||||
function loadImage(source: File | string) {
|
function loadImage(source: File | string) {
|
||||||
const isFile = source instanceof File;
|
const isFile = source instanceof File;
|
||||||
|
@ -58,7 +58,7 @@ async function resolveImage(options: Argument[], ctx: CommandContext, noServerPf
|
||||||
for (const opt of options) {
|
for (const opt of options) {
|
||||||
switch (opt.name) {
|
switch (opt.name) {
|
||||||
case "image":
|
case "image":
|
||||||
const upload = UploadStore.getUpload(ctx.channel.id, opt.name, DraftType.SlashCommand);
|
const upload = UploadAttachmentStore.getUpload(ctx.channel.id, opt.name, DraftType.SlashCommand);
|
||||||
if (upload) {
|
if (upload) {
|
||||||
if (!upload.isImage) {
|
if (!upload.isImage) {
|
||||||
UploadManager.clearAll(ctx.channel.id, DraftType.SlashCommand);
|
UploadManager.clearAll(ctx.channel.id, DraftType.SlashCommand);
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
import { classNameFactory } from "@api/Styles";
|
import { classNameFactory } from "@api/Styles";
|
||||||
import { ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, openModalLazy } from "@utils/modal";
|
import { ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, openModalLazy } from "@utils/modal";
|
||||||
import { extractAndLoadChunksLazy, findComponentByCodeLazy, findExportedComponentLazy } from "@webpack";
|
import { extractAndLoadChunksLazy, findComponentByCode, findExportedComponent } from "@webpack";
|
||||||
import { Button, Forms, Text, TextInput, Toasts, useEffect, useState } from "@webpack/common";
|
import { Button, Forms, Text, TextInput, Toasts, useEffect, useState } from "@webpack/common";
|
||||||
|
|
||||||
import { DEFAULT_COLOR, SWATCHES } from "../constants";
|
import { DEFAULT_COLOR, SWATCHES } from "../constants";
|
||||||
|
@ -30,10 +30,10 @@ interface ColorPickerWithSwatchesProps {
|
||||||
renderCustomButton?: () => React.ReactNode;
|
renderCustomButton?: () => React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ColorPicker = findComponentByCodeLazy<ColorPickerProps>(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR", ".BACKGROUND_PRIMARY)");
|
const ColorPicker = findComponentByCode<ColorPickerProps>(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR", ".BACKGROUND_PRIMARY)");
|
||||||
const ColorPickerWithSwatches = findExportedComponentLazy<ColorPickerWithSwatchesProps>("ColorPicker", "CustomColorPicker");
|
const ColorPickerWithSwatches = findExportedComponent<ColorPickerWithSwatchesProps>("ColorPicker", "CustomColorPicker");
|
||||||
|
|
||||||
export const requireSettingsMenu = extractAndLoadChunksLazy(['name:"UserSettings"'], /createPromise:.{0,20}Promise\.all\((\[\i\.\i\("?.+?"?\).+?\])\).then\(\i\.bind\(\i,"?(.+?)"?\)\).{0,50}"UserSettings"/);
|
export const requireSettingsMenu = extractAndLoadChunksLazy('name:"UserSettings"', /createPromise:.{0,20}Promise\.all\((\[\i\.\i\("?.+?"?\).+?\])\).then\(\i\.bind\(\i,"?(.+?)"?\)\).{0,50}"UserSettings"/);
|
||||||
|
|
||||||
const cl = classNameFactory("vc-pindms-modal-");
|
const cl = classNameFactory("vc-pindms-modal-");
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { classes } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import definePlugin, { OptionType, StartAt } from "@utils/types";
|
import definePlugin, { OptionType, StartAt } from "@utils/types";
|
||||||
import { findByPropsLazy, findStoreLazy } from "@webpack";
|
import { findByProps, findStore } from "@webpack";
|
||||||
import { ContextMenuApi, FluxDispatcher, Menu, React } from "@webpack/common";
|
import { ContextMenuApi, FluxDispatcher, Menu, React } from "@webpack/common";
|
||||||
import { Channel } from "discord-types/general";
|
import { Channel } from "discord-types/general";
|
||||||
|
|
||||||
|
@ -27,9 +27,9 @@ interface ChannelComponentProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const headerClasses = findByPropsLazy("privateChannelsHeaderContainer");
|
const headerClasses = findByProps("privateChannelsHeaderContainer");
|
||||||
|
|
||||||
export const PrivateChannelSortStore = findStoreLazy("PrivateChannelSortStore") as { getPrivateChannelIds: () => string[]; };
|
export const PrivateChannelSortStore = findStore("PrivateChannelSortStore") as { getPrivateChannelIds: () => string[]; };
|
||||||
|
|
||||||
export let instance: any;
|
export let instance: any;
|
||||||
export const forceUpdate = () => instance?.props?._forceUpdate?.();
|
export const forceUpdate = () => instance?.props?._forceUpdate?.();
|
||||||
|
|
|
@ -21,11 +21,11 @@ import "./style.css";
|
||||||
import { addBadge, BadgePosition, BadgeUserArgs, ProfileBadge, removeBadge } from "@api/Badges";
|
import { addBadge, BadgePosition, BadgeUserArgs, ProfileBadge, removeBadge } from "@api/Badges";
|
||||||
import { addDecorator, removeDecorator } from "@api/MemberListDecorators";
|
import { addDecorator, removeDecorator } from "@api/MemberListDecorators";
|
||||||
import { addDecoration, removeDecoration } from "@api/MessageDecorations";
|
import { addDecoration, removeDecoration } from "@api/MessageDecorations";
|
||||||
import { Settings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByPropsLazy, findStoreLazy } from "@webpack";
|
import { findByProps, findStore } from "@webpack";
|
||||||
import { PresenceStore, Tooltip, UserStore } from "@webpack/common";
|
import { PresenceStore, Tooltip, UserStore } from "@webpack/common";
|
||||||
import { User } from "discord-types/general";
|
import { User } from "discord-types/general";
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ export interface Session {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const SessionsStore = findStoreLazy("SessionsStore") as {
|
const SessionsStore = findStore("SessionsStore") as {
|
||||||
getSessions(): Record<string, Session>;
|
getSessions(): Record<string, Session>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ const Icons = {
|
||||||
};
|
};
|
||||||
type Platform = keyof typeof Icons;
|
type Platform = keyof typeof Icons;
|
||||||
|
|
||||||
const StatusUtils = findByPropsLazy("useStatusFillColor", "StatusTypes");
|
const StatusUtils = findByProps("useStatusFillColor", "StatusTypes");
|
||||||
|
|
||||||
const PlatformIcon = ({ platform, status, small }: { platform: Platform, status: string; small: boolean; }) => {
|
const PlatformIcon = ({ platform, status, small }: { platform: Platform, status: string; small: boolean; }) => {
|
||||||
const tooltip = platform === "embedded"
|
const tooltip = platform === "embedded"
|
||||||
|
@ -195,29 +195,36 @@ const indicatorLocations = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const settings = definePluginSettings({
|
||||||
|
...Object.fromEntries(
|
||||||
|
Object.entries(indicatorLocations).map(([key, value]) => {
|
||||||
|
return [key, {
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
description: `Show indicators ${value.description.toLowerCase()}`,
|
||||||
|
// onChange doesn't give any way to know which setting was changed, so restart required
|
||||||
|
restartNeeded: true,
|
||||||
|
default: true
|
||||||
|
}];
|
||||||
|
})
|
||||||
|
) as Record<"list" | "badges" | "messages", { type: OptionType.BOOLEAN; description: string; restartNeeded: boolean; default: boolean; }>,
|
||||||
|
colorMobileIndicator: {
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
description: "Whether to make the mobile indicator match the color of the user status.",
|
||||||
|
default: true,
|
||||||
|
restartNeeded: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "PlatformIndicators",
|
name: "PlatformIndicators",
|
||||||
description: "Adds platform indicators (Desktop, Mobile, Web...) to users",
|
description: "Adds platform indicators (Desktop, Mobile, Web...) to users",
|
||||||
authors: [Devs.kemo, Devs.TheSun, Devs.Nuckyz, Devs.Ven],
|
authors: [Devs.kemo, Devs.TheSun, Devs.Nuckyz, Devs.Ven],
|
||||||
dependencies: ["MessageDecorationsAPI", "MemberListDecoratorsAPI"],
|
dependencies: ["MessageDecorationsAPI", "MemberListDecoratorsAPI"],
|
||||||
|
settings,
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
const settings = Settings.plugins.PlatformIndicators;
|
|
||||||
const { displayMode } = settings;
|
|
||||||
|
|
||||||
// transfer settings from the old ones, which had a select menu instead of booleans
|
|
||||||
if (displayMode) {
|
|
||||||
if (displayMode !== "both") settings[displayMode] = true;
|
|
||||||
else {
|
|
||||||
settings.list = true;
|
|
||||||
settings.badges = true;
|
|
||||||
}
|
|
||||||
settings.messages = true;
|
|
||||||
delete settings.displayMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.entries(indicatorLocations).forEach(([key, value]) => {
|
Object.entries(indicatorLocations).forEach(([key, value]) => {
|
||||||
if (settings[key]) value.onEnable();
|
if (settings.store[key]) value.onEnable();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -230,7 +237,7 @@ export default definePlugin({
|
||||||
patches: [
|
patches: [
|
||||||
{
|
{
|
||||||
find: ".Masks.STATUS_ONLINE_MOBILE",
|
find: ".Masks.STATUS_ONLINE_MOBILE",
|
||||||
predicate: () => Settings.plugins.PlatformIndicators.colorMobileIndicator,
|
predicate: () => settings.store.colorMobileIndicator,
|
||||||
replacement: [
|
replacement: [
|
||||||
{
|
{
|
||||||
// Return the STATUS_ONLINE_MOBILE mask if the user is on mobile, no matter the status
|
// Return the STATUS_ONLINE_MOBILE mask if the user is on mobile, no matter the status
|
||||||
|
@ -246,7 +253,7 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
find: ".AVATAR_STATUS_MOBILE_16;",
|
find: ".AVATAR_STATUS_MOBILE_16;",
|
||||||
predicate: () => Settings.plugins.PlatformIndicators.colorMobileIndicator,
|
predicate: () => settings.store.colorMobileIndicator,
|
||||||
replacement: [
|
replacement: [
|
||||||
{
|
{
|
||||||
// Return the AVATAR_STATUS_MOBILE size mask if the user is on mobile, no matter the status
|
// Return the AVATAR_STATUS_MOBILE size mask if the user is on mobile, no matter the status
|
||||||
|
@ -267,32 +274,12 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
find: "}isMobileOnline(",
|
find: "}isMobileOnline(",
|
||||||
predicate: () => Settings.plugins.PlatformIndicators.colorMobileIndicator,
|
predicate: () => settings.store.colorMobileIndicator,
|
||||||
replacement: {
|
replacement: {
|
||||||
// Make isMobileOnline return true no matter what is the user status
|
// Make isMobileOnline return true no matter what is the user status
|
||||||
match: /(?<=\i\[\i\.\i\.MOBILE\])===\i\.\i\.ONLINE/,
|
match: /(?<=\i\[\i\.\i\.MOBILE\])===\i\.\i\.ONLINE/,
|
||||||
replace: "!= null"
|
replace: "!= null"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
|
|
||||||
options: {
|
|
||||||
...Object.fromEntries(
|
|
||||||
Object.entries(indicatorLocations).map(([key, value]) => {
|
|
||||||
return [key, {
|
|
||||||
type: OptionType.BOOLEAN,
|
|
||||||
description: `Show indicators ${value.description.toLowerCase()}`,
|
|
||||||
// onChange doesn't give any way to know which setting was changed, so restart required
|
|
||||||
restartNeeded: true,
|
|
||||||
default: true
|
|
||||||
}];
|
|
||||||
})
|
|
||||||
),
|
|
||||||
colorMobileIndicator: {
|
|
||||||
type: OptionType.BOOLEAN,
|
|
||||||
description: "Whether to make the mobile indicator match the color of the user status.",
|
|
||||||
default: true,
|
|
||||||
restartNeeded: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -20,15 +20,14 @@ import { addChatBarButton, ChatBarButton, removeChatBarButton } from "@api/ChatB
|
||||||
import { generateId, sendBotMessage } from "@api/Commands";
|
import { generateId, sendBotMessage } from "@api/Commands";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { StartAt } from "@utils/types";
|
import definePlugin, { StartAt } from "@utils/types";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findStore } from "@webpack";
|
||||||
import { DraftStore, DraftType, SelectedChannelStore, UserStore, useStateFromStores } from "@webpack/common";
|
import { DraftStore, DraftType, SelectedChannelStore, UserStore, useStateFromStores } from "@webpack/common";
|
||||||
import { MessageAttachment } from "discord-types/general";
|
import { MessageAttachment } from "discord-types/general";
|
||||||
|
|
||||||
const UploadStore = findByPropsLazy("getUploads");
|
const UploadAttachmentStore = findStore("UploadAttachmentStore");
|
||||||
|
|
||||||
const getDraft = (channelId: string) => DraftStore.getDraft(channelId, DraftType.ChannelMessage);
|
const getDraft = (channelId: string) => DraftStore.getDraft(channelId, DraftType.ChannelMessage);
|
||||||
|
|
||||||
|
|
||||||
const getImageBox = (url: string): Promise<{ width: number, height: number; } | null> =>
|
const getImageBox = (url: string): Promise<{ width: number, height: number; } | null> =>
|
||||||
new Promise(res => {
|
new Promise(res => {
|
||||||
const img = new Image();
|
const img = new Image();
|
||||||
|
@ -44,7 +43,7 @@ const getImageBox = (url: string): Promise<{ width: number, height: number; } |
|
||||||
|
|
||||||
const getAttachments = async (channelId: string) =>
|
const getAttachments = async (channelId: string) =>
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
UploadStore.getUploads(channelId, DraftType.ChannelMessage)
|
UploadAttachmentStore.getUploads(channelId, DraftType.ChannelMessage)
|
||||||
.map(async (upload: any) => {
|
.map(async (upload: any) => {
|
||||||
const { isImage, filename, spoiler, item: { file } } = upload;
|
const { isImage, filename, spoiler, item: { file } } = upload;
|
||||||
const url = URL.createObjectURL(file);
|
const url = URL.createObjectURL(file);
|
||||||
|
@ -79,7 +78,7 @@ const PreviewButton: ChatBarButton = ({ isMainChat, isEmpty, type: { attachments
|
||||||
|
|
||||||
if (!isMainChat) return null;
|
if (!isMainChat) return null;
|
||||||
|
|
||||||
const hasAttachments = attachments && UploadStore.getUploads(channelId, DraftType.ChannelMessage).length > 0;
|
const hasAttachments = attachments && UploadAttachmentStore.getUploads(channelId, DraftType.ChannelMessage).length > 0;
|
||||||
const hasContent = !isEmpty && draft?.length > 0;
|
const hasContent = !isEmpty && draft?.length > 0;
|
||||||
|
|
||||||
if (!hasContent && !hasAttachments) return null;
|
if (!hasContent && !hasAttachments) return null;
|
||||||
|
|
|
@ -18,13 +18,13 @@
|
||||||
|
|
||||||
import { getCurrentChannel } from "@utils/discord";
|
import { getCurrentChannel } from "@utils/discord";
|
||||||
import { useAwaiter } from "@utils/react";
|
import { useAwaiter } from "@utils/react";
|
||||||
import { findStoreLazy } from "@webpack";
|
import { findStore } from "@webpack";
|
||||||
import { UserProfileStore, UserStore } from "@webpack/common";
|
import { UserProfileStore, UserStore } from "@webpack/common";
|
||||||
|
|
||||||
import { settings } from "./settings";
|
import { settings } from "./settings";
|
||||||
import { PronounMapping, Pronouns, PronounsCache, PronounSets, PronounsFormat, PronounSource, PronounsResponse } from "./types";
|
import { PronounMapping, Pronouns, PronounsCache, PronounSets, PronounsFormat, PronounSource, PronounsResponse } from "./types";
|
||||||
|
|
||||||
const UserSettingsAccountStore = findStoreLazy("UserSettingsAccountStore");
|
const UserSettingsAccountStore = findStore("UserSettingsAccountStore");
|
||||||
|
|
||||||
const EmptyPronouns = { pronouns: undefined, source: "", hasPendingPronouns: false } as const satisfies Pronouns;
|
const EmptyPronouns = { pronouns: undefined, source: "", hasPendingPronouns: false } as const satisfies Pronouns;
|
||||||
|
|
||||||
|
|
|
@ -18,14 +18,14 @@
|
||||||
|
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { classes } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findByProps } from "@webpack";
|
||||||
import { UserStore } from "@webpack/common";
|
import { UserStore } from "@webpack/common";
|
||||||
import { Message } from "discord-types/general";
|
import { Message } from "discord-types/general";
|
||||||
|
|
||||||
import { useFormattedPronouns } from "../api";
|
import { useFormattedPronouns } from "../api";
|
||||||
import { settings } from "../settings";
|
import { settings } from "../settings";
|
||||||
|
|
||||||
const styles: Record<string, string> = findByPropsLazy("timestampInline");
|
const styles: Record<string, string> = findByProps("timestampInline");
|
||||||
|
|
||||||
const AUTO_MODERATION_ACTION = 24;
|
const AUTO_MODERATION_ACTION = 24;
|
||||||
|
|
||||||
|
|
|
@ -19,12 +19,11 @@
|
||||||
import { definePluginSettings, Settings } from "@api/Settings";
|
import { definePluginSettings, Settings } from "@api/Settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findByProps } from "@webpack";
|
||||||
import { ChannelStore, FluxDispatcher as Dispatcher, MessageStore, PermissionsBits, PermissionStore, SelectedChannelStore, UserStore } from "@webpack/common";
|
import { ChannelStore, FluxDispatcher as Dispatcher, MessageStore, PermissionsBits, PermissionStore, RelationshipStore, SelectedChannelStore, UserStore } from "@webpack/common";
|
||||||
import { Message } from "discord-types/general";
|
import { Message } from "discord-types/general";
|
||||||
|
|
||||||
const Kangaroo = findByPropsLazy("jumpToMessage");
|
const Kangaroo = findByProps("jumpToMessage");
|
||||||
const RelationshipStore = findByPropsLazy("getRelationships", "isBlocked");
|
|
||||||
|
|
||||||
const isMac = navigator.platform.includes("Mac"); // bruh
|
const isMac = navigator.platform.includes("Mac"); // bruh
|
||||||
let replyIdx = -1;
|
let replyIdx = -1;
|
||||||
|
|
|
@ -22,8 +22,8 @@ import { addServerListElement, removeServerListElement, ServerListRenderPosition
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { findStoreLazy } from "@webpack";
|
import { findStore } from "@webpack";
|
||||||
import { Button, FluxDispatcher, GuildChannelStore, GuildStore, React, ReadStateStore } from "@webpack/common";
|
import { Button, FluxDispatcher, GenericStore, GuildChannelStore, GuildStore, React, ReadStateStore } from "@webpack/common";
|
||||||
import { Channel } from "discord-types/general";
|
import { Channel } from "discord-types/general";
|
||||||
|
|
||||||
interface ThreadJoined {
|
interface ThreadJoined {
|
||||||
|
@ -34,11 +34,11 @@ interface ThreadJoined {
|
||||||
type ThreadsJoined = Record<string, ThreadJoined>;
|
type ThreadsJoined = Record<string, ThreadJoined>;
|
||||||
type ThreadsJoinedByParent = Record<string, ThreadsJoined>;
|
type ThreadsJoinedByParent = Record<string, ThreadsJoined>;
|
||||||
|
|
||||||
interface ActiveJoinedThreadsStore {
|
interface ActiveJoinedThreadsStore extends GenericStore {
|
||||||
getActiveJoinedThreadsForGuild(guildId: string): ThreadsJoinedByParent;
|
getActiveJoinedThreadsForGuild(guildId: string): ThreadsJoinedByParent;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ActiveJoinedThreadsStore: ActiveJoinedThreadsStore = findStoreLazy("ActiveJoinedThreadsStore");
|
const ActiveJoinedThreadsStore = findStore<ActiveJoinedThreadsStore>("ActiveJoinedThreadsStore");
|
||||||
|
|
||||||
function onClick() {
|
function onClick() {
|
||||||
const channels: Array<any> = [];
|
const channels: Array<any> = [];
|
||||||
|
|
|
@ -19,14 +19,14 @@
|
||||||
import { DataStore, Notices } from "@api/index";
|
import { DataStore, Notices } from "@api/index";
|
||||||
import { showNotification } from "@api/Notifications";
|
import { showNotification } from "@api/Notifications";
|
||||||
import { getUniqueUsername, openUserProfile } from "@utils/discord";
|
import { getUniqueUsername, openUserProfile } from "@utils/discord";
|
||||||
import { findStoreLazy } from "@webpack";
|
import { findStore } from "@webpack";
|
||||||
import { ChannelStore, GuildMemberStore, GuildStore, RelationshipStore, UserStore, UserUtils } from "@webpack/common";
|
import { ChannelStore, GuildMemberStore, GuildStore, RelationshipStore, UserStore, UserUtils } from "@webpack/common";
|
||||||
import { FluxStore } from "@webpack/types";
|
import { FluxStore } from "@webpack/types";
|
||||||
|
|
||||||
import settings from "./settings";
|
import settings from "./settings";
|
||||||
import { ChannelType, RelationshipType, SimpleGroupChannel, SimpleGuild } from "./types";
|
import { ChannelType, RelationshipType, SimpleGroupChannel, SimpleGuild } from "./types";
|
||||||
|
|
||||||
export const GuildAvailabilityStore = findStoreLazy("GuildAvailabilityStore") as FluxStore & {
|
export const GuildAvailabilityStore = findStore("GuildAvailabilityStore") as FluxStore & {
|
||||||
totalGuilds: number;
|
totalGuilds: number;
|
||||||
totalUnavailableGuilds: number;
|
totalUnavailableGuilds: number;
|
||||||
unavailableGuilds: string[];
|
unavailableGuilds: string[];
|
||||||
|
|
|
@ -9,17 +9,17 @@ import "./style.css";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { filters, findByPropsLazy, mapMangledModuleLazy } from "@webpack";
|
import { filters, findByProps, mapMangledModule } from "@webpack";
|
||||||
import { Timestamp } from "@webpack/common";
|
import { Timestamp } from "@webpack/common";
|
||||||
import type { Message } from "discord-types/general";
|
import type { Message } from "discord-types/general";
|
||||||
import type { HTMLAttributes } from "react";
|
import type { HTMLAttributes } from "react";
|
||||||
|
|
||||||
const { calendarFormat, dateFormat, isSameDay } = mapMangledModuleLazy("millisecondsInUnit:", {
|
const { calendarFormat, dateFormat, isSameDay } = mapMangledModule("millisecondsInUnit:", {
|
||||||
calendarFormat: filters.byCode("sameElse"),
|
calendarFormat: filters.byCode("sameElse"),
|
||||||
dateFormat: filters.byCode('":'),
|
dateFormat: filters.byCode(':").concat'),
|
||||||
isSameDay: filters.byCode("Math.abs(+"),
|
isSameDay: filters.byCode("Math.abs(+"),
|
||||||
});
|
});
|
||||||
const MessageClasses = findByPropsLazy("separator", "latin24CompactTimeStamp");
|
const MessageClasses = findByProps("separator", "latin24CompactTimeStamp");
|
||||||
|
|
||||||
function Sep(props: HTMLAttributes<HTMLElement>) {
|
function Sep(props: HTMLAttributes<HTMLElement>) {
|
||||||
return <i className={MessageClasses.separator} aria-hidden={true} {...props} />;
|
return <i className={MessageClasses.separator} aria-hidden={true} {...props} />;
|
||||||
|
|
|
@ -18,10 +18,10 @@
|
||||||
|
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findByProps } from "@webpack";
|
||||||
|
|
||||||
const SpoilerClasses = findByPropsLazy("spoilerContent");
|
const SpoilerClasses = findByProps("spoilerContent");
|
||||||
const MessagesClasses = findByPropsLazy("messagesWrapper");
|
const MessagesClasses = findByProps("messagesWrapper");
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "RevealAllSpoilers",
|
name: "RevealAllSpoilers",
|
||||||
|
|
|
@ -7,15 +7,12 @@
|
||||||
import { DataStore } from "@api/index";
|
import { DataStore } from "@api/index";
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
import { openModal } from "@utils/modal";
|
import { openModal } from "@utils/modal";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { OAuth2AuthorizeModal, showToast, Toasts, UserStore } from "@webpack/common";
|
||||||
import { showToast, Toasts, UserStore } from "@webpack/common";
|
|
||||||
|
|
||||||
import { ReviewDBAuth } from "./entities";
|
import { ReviewDBAuth } from "./entities";
|
||||||
|
|
||||||
const DATA_STORE_KEY = "rdb-auth";
|
const DATA_STORE_KEY = "rdb-auth";
|
||||||
|
|
||||||
const { OAuth2AuthorizeModal } = findByPropsLazy("OAuth2AuthorizeModal");
|
|
||||||
|
|
||||||
export let Auth: ReviewDBAuth = {};
|
export let Auth: ReviewDBAuth = {};
|
||||||
|
|
||||||
export async function initAuth() {
|
export async function initAuth() {
|
||||||
|
|
|
@ -18,10 +18,10 @@
|
||||||
|
|
||||||
import { DeleteIcon } from "@components/Icons";
|
import { DeleteIcon } from "@components/Icons";
|
||||||
import { classes } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findByProps } from "@webpack";
|
||||||
import { Tooltip } from "@webpack/common";
|
import { Tooltip } from "@webpack/common";
|
||||||
|
|
||||||
const iconClasses = findByPropsLazy("button", "wrapper", "disabled", "separator");
|
const iconClasses = findByProps("button", "wrapper", "disabled", "separator");
|
||||||
|
|
||||||
export function DeleteButton({ onClick }: { onClick(): void; }) {
|
export function DeleteButton({ onClick }: { onClick(): void; }) {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -18,8 +18,7 @@
|
||||||
|
|
||||||
import { openUserProfile } from "@utils/discord";
|
import { openUserProfile } from "@utils/discord";
|
||||||
import { classes } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import { LazyComponent } from "@utils/react";
|
import { findByProps } from "@webpack";
|
||||||
import { filters, findBulk } from "@webpack";
|
|
||||||
import { Alerts, Parser, Timestamp, useState } from "@webpack/common";
|
import { Alerts, Parser, Timestamp, useState } from "@webpack/common";
|
||||||
|
|
||||||
import { Auth, getToken } from "../auth";
|
import { Auth, getToken } from "../auth";
|
||||||
|
@ -31,161 +30,150 @@ import { openBlockModal } from "./BlockedUserModal";
|
||||||
import { BlockButton, DeleteButton, ReportButton } from "./MessageButton";
|
import { BlockButton, DeleteButton, ReportButton } from "./MessageButton";
|
||||||
import ReviewBadge from "./ReviewBadge";
|
import ReviewBadge from "./ReviewBadge";
|
||||||
|
|
||||||
export default LazyComponent(() => {
|
const messageClasses = findByProps("cozyMessage");
|
||||||
// this is terrible, blame mantika
|
const containerClasses = findByProps("container", "isHeader");
|
||||||
const p = filters.byProps;
|
const avatarClasses = findByProps("avatar", "zalgo");
|
||||||
const [
|
const buttonClasses = findByProps("button", "wrapper", "selected");
|
||||||
{ cozyMessage, buttons, message, buttonsInner, groupStart },
|
const botTagClasses = findByProps("botTagRegular");
|
||||||
{ container, isHeader },
|
|
||||||
{ avatar, clickable, username, wrapper, cozy },
|
|
||||||
buttonClasses,
|
|
||||||
botTag
|
|
||||||
] = findBulk(
|
|
||||||
p("cozyMessage"),
|
|
||||||
p("container", "isHeader"),
|
|
||||||
p("avatar", "zalgo"),
|
|
||||||
p("button", "wrapper", "selected"),
|
|
||||||
p("botTagRegular")
|
|
||||||
);
|
|
||||||
|
|
||||||
const dateFormat = new Intl.DateTimeFormat();
|
const dateFormat = new Intl.DateTimeFormat();
|
||||||
|
|
||||||
return function ReviewComponent({ review, refetch, profileId }: { review: Review; refetch(): void; profileId: string; }) {
|
export default function ReviewComponent({ review, refetch, profileId }: { review: Review; refetch(): void; profileId: string; }) {
|
||||||
const [showAll, setShowAll] = useState(false);
|
const [showAll, setShowAll] = useState(false);
|
||||||
|
|
||||||
function openModal() {
|
function openModal() {
|
||||||
openUserProfile(review.sender.discordID);
|
openUserProfile(review.sender.discordID);
|
||||||
}
|
}
|
||||||
|
|
||||||
function delReview() {
|
function delReview() {
|
||||||
Alerts.show({
|
Alerts.show({
|
||||||
title: "Are you sure?",
|
title: "Are you sure?",
|
||||||
body: "Do you really want to delete this review?",
|
body: "Do you really want to delete this review?",
|
||||||
confirmText: "Delete",
|
confirmText: "Delete",
|
||||||
cancelText: "Nevermind",
|
cancelText: "Nevermind",
|
||||||
onConfirm: async () => {
|
onConfirm: async () => {
|
||||||
if (!(await getToken())) {
|
if (!(await getToken())) {
|
||||||
return showToast("You must be logged in to delete reviews.");
|
return showToast("You must be logged in to delete reviews.");
|
||||||
} else {
|
} else {
|
||||||
deleteReview(review.id).then(res => {
|
deleteReview(review.id).then(res => {
|
||||||
if (res) {
|
if (res) {
|
||||||
refetch();
|
refetch();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function reportRev() {
|
function reportRev() {
|
||||||
Alerts.show({
|
Alerts.show({
|
||||||
title: "Are you sure?",
|
title: "Are you sure?",
|
||||||
body: "Do you really you want to report this review?",
|
body: "Do you really you want to report this review?",
|
||||||
confirmText: "Report",
|
confirmText: "Report",
|
||||||
cancelText: "Nevermind",
|
cancelText: "Nevermind",
|
||||||
// confirmColor: "red", this just adds a class name and breaks the submit button guh
|
// confirmColor: "red", this just adds a class name and breaks the submit button guh
|
||||||
onConfirm: async () => {
|
onConfirm: async () => {
|
||||||
if (!(await getToken())) {
|
if (!(await getToken())) {
|
||||||
return showToast("You must be logged in to report reviews.");
|
return showToast("You must be logged in to report reviews.");
|
||||||
} else {
|
} else {
|
||||||
reportReview(review.id);
|
reportReview(review.id);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const isAuthorBlocked = Auth?.user?.blockedUsers?.includes(review.sender.discordID) ?? false;
|
const isAuthorBlocked = Auth?.user?.blockedUsers?.includes(review.sender.discordID) ?? false;
|
||||||
|
|
||||||
function blockReviewSender() {
|
function blockReviewSender() {
|
||||||
if (isAuthorBlocked)
|
if (isAuthorBlocked)
|
||||||
return unblockUser(review.sender.discordID);
|
return unblockUser(review.sender.discordID);
|
||||||
|
|
||||||
Alerts.show({
|
Alerts.show({
|
||||||
title: "Are you sure?",
|
title: "Are you sure?",
|
||||||
body: "Do you really you want to block this user? They will be unable to leave further reviews on your profile. You can unblock users in the plugin settings.",
|
body: "Do you really you want to block this user? They will be unable to leave further reviews on your profile. You can unblock users in the plugin settings.",
|
||||||
confirmText: "Block",
|
confirmText: "Block",
|
||||||
cancelText: "Nevermind",
|
cancelText: "Nevermind",
|
||||||
// confirmColor: "red", this just adds a class name and breaks the submit button guh
|
// confirmColor: "red", this just adds a class name and breaks the submit button guh
|
||||||
onConfirm: async () => {
|
onConfirm: async () => {
|
||||||
if (!(await getToken())) {
|
if (!(await getToken())) {
|
||||||
return showToast("You must be logged in to block users.");
|
return showToast("You must be logged in to block users.");
|
||||||
} else {
|
} else {
|
||||||
blockUser(review.sender.discordID);
|
blockUser(review.sender.discordID);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes(cl("review"), cozyMessage, wrapper, message, groupStart, cozy)} style={
|
<div className={classes(cl("review"), messageClasses.cozyMessage, avatarClasses.wrapper, messageClasses.message, messageClasses.groupStart, avatarClasses.cozy)} style={
|
||||||
{
|
{
|
||||||
marginLeft: "0px",
|
marginLeft: "0px",
|
||||||
paddingLeft: "52px", // wth is this
|
paddingLeft: "52px", // wth is this
|
||||||
// nobody knows anymore
|
// nobody knows anymore
|
||||||
}
|
}
|
||||||
}>
|
}>
|
||||||
|
|
||||||
<img
|
<img
|
||||||
className={classes(avatar, clickable)}
|
className={classes(avatarClasses.avatar, avatarClasses.clickable)}
|
||||||
onClick={openModal}
|
onClick={openModal}
|
||||||
src={review.sender.profilePhoto || "/assets/1f0bfc0865d324c2587920a7d80c609b.png?size=128"}
|
src={review.sender.profilePhoto || "/assets/1f0bfc0865d324c2587920a7d80c609b.png?size=128"}
|
||||||
style={{ left: "0px", zIndex: 0 }}
|
style={{ left: "0px", zIndex: 0 }}
|
||||||
/>
|
/>
|
||||||
<div style={{ display: "inline-flex", justifyContent: "center", alignItems: "center" }}>
|
<div style={{ display: "inline-flex", justifyContent: "center", alignItems: "center" }}>
|
||||||
|
<span
|
||||||
|
className={classes(avatarClasses.clickable, avatarClasses.username)}
|
||||||
|
style={{ color: "var(--channels-default)", fontSize: "14px" }}
|
||||||
|
onClick={() => openModal()}
|
||||||
|
>
|
||||||
|
{review.sender.username}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
{review.type === ReviewType.System && (
|
||||||
<span
|
<span
|
||||||
className={classes(clickable, username)}
|
className={classes(botTagClasses.botTagVerified, botTagClasses.botTagRegular, botTagClasses.px, botTagClasses.rem)}
|
||||||
style={{ color: "var(--channels-default)", fontSize: "14px" }}
|
style={{ marginLeft: "4px" }}>
|
||||||
onClick={() => openModal()}
|
<span className={botTagClasses.botText}>
|
||||||
>
|
System
|
||||||
{review.sender.username}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
{review.type === ReviewType.System && (
|
|
||||||
<span
|
|
||||||
className={classes(botTag.botTagVerified, botTag.botTagRegular, botTag.px, botTag.rem)}
|
|
||||||
style={{ marginLeft: "4px" }}>
|
|
||||||
<span className={botTag.botText}>
|
|
||||||
System
|
|
||||||
</span>
|
|
||||||
</span>
|
</span>
|
||||||
)}
|
</span>
|
||||||
</div>
|
|
||||||
{isAuthorBlocked && (
|
|
||||||
<ReviewBadge
|
|
||||||
name="You have blocked this user"
|
|
||||||
description="You have blocked this user"
|
|
||||||
icon="/assets/aaee57e0090991557b66.svg"
|
|
||||||
type={0}
|
|
||||||
onClick={() => openBlockModal()}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{review.sender.badges.map(badge => <ReviewBadge {...badge} />)}
|
|
||||||
|
|
||||||
{
|
|
||||||
!settings.store.hideTimestamps && review.type !== ReviewType.System && (
|
|
||||||
<Timestamp timestamp={new Date(review.timestamp * 1000)} >
|
|
||||||
{dateFormat.format(review.timestamp * 1000)}
|
|
||||||
</Timestamp>)
|
|
||||||
}
|
|
||||||
|
|
||||||
<div className={cl("review-comment")}>
|
|
||||||
{(review.comment.length > 200 && !showAll)
|
|
||||||
? [Parser.parseGuildEventDescription(review.comment.substring(0, 200)), "...", <br />, (<a onClick={() => setShowAll(true)}>Read more</a>)]
|
|
||||||
: Parser.parseGuildEventDescription(review.comment)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{review.id !== 0 && (
|
|
||||||
<div className={classes(container, isHeader, buttons)} style={{
|
|
||||||
padding: "0px",
|
|
||||||
}}>
|
|
||||||
<div className={classes(buttonClasses.wrapper, buttonsInner)} >
|
|
||||||
{canReportReview(review) && <ReportButton onClick={reportRev} />}
|
|
||||||
{canBlockReviewAuthor(profileId, review) && <BlockButton isBlocked={isAuthorBlocked} onClick={blockReviewSender} />}
|
|
||||||
{canDeleteReview(profileId, review) && <DeleteButton onClick={delReview} />}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
{isAuthorBlocked && (
|
||||||
};
|
<ReviewBadge
|
||||||
});
|
name="You have blocked this user"
|
||||||
|
description="You have blocked this user"
|
||||||
|
icon="/assets/aaee57e0090991557b66.svg"
|
||||||
|
type={0}
|
||||||
|
onClick={() => openBlockModal()}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{review.sender.badges.map(badge => <ReviewBadge {...badge} />)}
|
||||||
|
|
||||||
|
{
|
||||||
|
!settings.store.hideTimestamps && review.type !== ReviewType.System && (
|
||||||
|
<Timestamp timestamp={new Date(review.timestamp * 1000)} >
|
||||||
|
{dateFormat.format(review.timestamp * 1000)}
|
||||||
|
</Timestamp>)
|
||||||
|
}
|
||||||
|
|
||||||
|
<div className={cl("review-comment")}>
|
||||||
|
{(review.comment.length > 200 && !showAll)
|
||||||
|
? [Parser.parseGuildEventDescription(review.comment.substring(0, 200)), "...", <br />, (<a onClick={() => setShowAll(true)}>Read more</a>)]
|
||||||
|
: Parser.parseGuildEventDescription(review.comment)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{review.id !== 0 && (
|
||||||
|
<div className={classes(containerClasses.container, containerClasses.isHeader, messageClasses.buttons)} style={{
|
||||||
|
padding: "0px",
|
||||||
|
}}>
|
||||||
|
<div className={classes(buttonClasses.wrapper, messageClasses.buttonsInner)} >
|
||||||
|
{canReportReview(review) && <ReportButton onClick={reportRev} />}
|
||||||
|
{canBlockReviewAuthor(profileId, review) && <BlockButton isBlocked={isAuthorBlocked} onClick={blockReviewSender} />}
|
||||||
|
{canDeleteReview(profileId, review) && <DeleteButton onClick={delReview} />}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { useAwaiter, useForceUpdater } from "@utils/react";
|
import { useAwaiter, useForceUpdater } from "@utils/react";
|
||||||
import { findByCodeLazy, findByPropsLazy, findComponentByCodeLazy } from "@webpack";
|
import { findByCode, findByProps, findComponentByCode } from "@webpack";
|
||||||
import { Forms, React, RelationshipStore, useRef, UserStore } from "@webpack/common";
|
import { Forms, React, RelationshipStore, useRef, UserStore } from "@webpack/common";
|
||||||
|
|
||||||
import { Auth, authorize } from "../auth";
|
import { Auth, authorize } from "../auth";
|
||||||
|
@ -27,11 +27,11 @@ import { settings } from "../settings";
|
||||||
import { cl, showToast } from "../utils";
|
import { cl, showToast } from "../utils";
|
||||||
import ReviewComponent from "./ReviewComponent";
|
import ReviewComponent from "./ReviewComponent";
|
||||||
|
|
||||||
const Transforms = findByPropsLazy("insertNodes", "textToText");
|
const Transforms = findByProps("insertNodes", "textToText");
|
||||||
const Editor = findByPropsLazy("start", "end", "toSlateRange");
|
const Editor = findByProps("start", "end", "toSlateRange");
|
||||||
const ChatInputTypes = findByPropsLazy("FORM");
|
const ChatInputTypes = findByProps("FORM");
|
||||||
const InputComponent = findComponentByCodeLazy("disableThemedBackground", "CHANNEL_TEXT_AREA");
|
const InputComponent = findComponentByCode("disableThemedBackground", "CHANNEL_TEXT_AREA");
|
||||||
const createChannelRecordFromServer = findByCodeLazy(".GUILD_TEXT])", "fromServer)");
|
const createChannelRecordFromServer = findByCode(".GUILD_TEXT])", "fromServer)");
|
||||||
|
|
||||||
interface UserProps {
|
interface UserProps {
|
||||||
discordId: string;
|
discordId: string;
|
||||||
|
|
|
@ -24,7 +24,7 @@ import { NotesIcon, OpenExternalIcon } from "@components/Icons";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { classes } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findByProps } from "@webpack";
|
||||||
import { Alerts, Button, Menu, Parser, TooltipContainer } from "@webpack/common";
|
import { Alerts, Button, Menu, Parser, TooltipContainer } from "@webpack/common";
|
||||||
import { Guild, User } from "discord-types/general";
|
import { Guild, User } from "discord-types/general";
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ import { getCurrentUserInfo, readNotification } from "./reviewDbApi";
|
||||||
import { settings } from "./settings";
|
import { settings } from "./settings";
|
||||||
import { showToast } from "./utils";
|
import { showToast } from "./utils";
|
||||||
|
|
||||||
const RoleButtonClasses = findByPropsLazy("button", "buttonInner", "icon", "banner");
|
const RoleButtonClasses = findByProps("button", "buttonInner", "icon", "banner");
|
||||||
|
|
||||||
const guildPopoutPatch: NavContextMenuPatchCallback = (children, { guild }: { guild: Guild, onClose(): void; }) => {
|
const guildPopoutPatch: NavContextMenuPatchCallback = (children, { guild }: { guild: Guild, onClose(): void; }) => {
|
||||||
if (!guild) return;
|
if (!guild) return;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue