Compare commits

...

1358 commits

Author SHA1 Message Date
9205db27bd Merge branch 'main' of https://github.com/Vendicated/Vencord 2025-02-13 10:57:19 +01:00
Elvyra
205e07d2c5
BetterFolders: Fix not disabling expanded folder background (#3214) 2025-02-12 14:45:57 -03:00
sadan4
fcf8690d26
RoleColorEverywhere: Fix coloring voice user list (#3206) 2025-02-07 18:32:55 +00:00
Suffocate
e4380632e0
fix ToastType enum (#3201)
Co-authored-by: v <vendicated@riseup.net>
2025-02-06 20:04:59 +00:00
khcrysalis
4a447c74ef
feat: add donor and contributor cards in vencord settings (#3049)
Co-authored-by: Cookie <52550063+Covkie@users.noreply.github.com>
Co-authored-by: v <vendicated@riseup.net>
2025-02-06 20:37:18 +01:00
30748b9930 Merge branch 'main' of https://github.com/Vendicated/Vencord 2025-02-06 15:22:59 +01:00
Vendicated
848c2299d2
Bump to v1.11.4 2025-02-05 21:54:43 +01:00
sadan4
1e426b4253
arRPC: Fix find (#3203) 2025-02-05 21:53:47 +01:00
Tomsoz
971e186335
CopyEmojiMarkdown: Fix copying animated emojis (#3179) 2025-02-04 19:29:35 +00:00
Nuckyz
949aad8cc7
Fix webpack finding Popout 2025-02-03 22:20:57 -03:00
Nuckyz
70ce6ff2d6
Fix reporter display for componentByCode 2025-02-03 21:40:54 -03:00
Nuckyz
a73074b69f
MessageDecorationsAPI: Fix bad vertical alignment 2025-02-03 02:02:22 -03:00
Nuckyz
ae98cfb637
Wrap decorators in flex with gap to avoid adding margins 2025-02-02 17:59:22 -03:00
v
6cccb54ffc
Fix lag caused by poorly written CSS rules (#3198)
Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
2025-02-02 01:37:54 +01:00
Nuckyz
4f5ebec4bb
FullUserInChatbox: Fix empty mention when user is unknown
Fixes #3190
2025-01-31 16:24:07 -03:00
jamesbt365
7b9f0a36ba
IrcColors: Allow coloring only users with no color and DMs only (#3186) 2025-01-31 18:54:51 +00:00
Nuckyz
fc4e95806d
Fix ImplicitRelationships and NotificationsVolume (#3184)
Also simplifies MessageEventsAPI patch
2025-01-31 17:55:40 +00:00
Nuckyz
1eff1a02bd
IrcColors: Fix causing react errors sometimes 2025-01-30 16:02:42 -03:00
Nuckyz
414539f45e
Add more FIXME and explain better TODOS for migrations 2025-01-30 16:01:57 -03:00
Nuckyz
b2d5c00a23
Delete NoScreensharePreview ~now a stock feature 2025-01-30 16:01:36 -03:00
Nuckyz
a492f7657b
MessageEventsAPI: Fix for upcoming change 2025-01-30 15:15:40 -03:00
Nuckyz
e280ed2683
Ignore more modules on webpack searching 2025-01-30 14:54:41 -03:00
362f12fa3d additions 2025-01-30 05:58:11 +01:00
4029ac976b Merge branch 'main' of https://github.com/Vendicated/Vencord 2025-01-30 05:57:16 +01:00
Sqaaakoi
8fccda4a24
WhoReacted, TypingIndicator: Fix triggering other actions (#3161)
Prevents typing in message user box from activating parent click handlers
Fixes https://github.com/Vendicated/Vencord/issues/3128
2025-01-29 22:41:32 -03:00
jamesbt365
68662c9625
QuickReply: Fix showing toggle mention in guilds (#3181) 2025-01-30 01:36:56 +00:00
sadan4
7d45862023
Fix IgnoreActivities and AlwaysAnimate for canary (#3182) 2025-01-29 22:28:11 -03:00
Vendicated
240195f9bf
Bump to v1.11.3 2025-01-29 20:44:15 +01:00
Nuckyz
5ad35c36e4
Make Option.Component not require description
Also correctly infers the type from "default"
2025-01-29 14:34:44 -03:00
Nuckyz
a2213d4feb
Re-export Modals 2025-01-29 13:42:24 -03:00
Nuckyz
81dda2ce33
Make more finds not depend on non mangled keys 2025-01-29 11:52:49 -03:00
Nuckyz
7415367d6c
Add missing MenuSearchControl webpack find 2025-01-29 10:09:05 -03:00
Nuckyz
33d4f13a24
Fix everything broken by recent Discord update (#3177)
Co-authored-by: sadan <117494111+sadan4@users.noreply.github.com>
Co-authored-by: Vendicated <vendicated@riseup.net>
2025-01-29 01:04:36 -03:00
Nuckyz
cdc756193e
Settings API: Fix erroring if plugin settings don't exist 2025-01-28 01:13:36 -03:00
jamesbt365
f43baddc55
NoBlockedMessages: Add ignored messages (#3126) 2025-01-27 22:57:16 -03:00
Nuckyz
21ded874a3
Settings API: Add utility to migrate a setting 2025-01-27 21:12:58 -03:00
Vendicated
ea1e96185b
MessageLatency: ErrorBoundary should be noop 2025-01-27 20:54:16 +01:00
Vendicated
ceba9776c4
Delete MoreUserTags for now because it's unstable
This plugin is written in a way that makes it susceptible to crashes.
This is not the first time it has caused crashes and will not be the last.
A rewrite is necessary to make it more robust
2025-01-27 20:44:54 +01:00
Nuckyz
c4f8221f75
IrcColors: Make lightness apply without restart 2025-01-27 14:30:11 -03:00
Vendicated
3350922c09
LastFmRPC: Add option to hide if there is another presence
closes #2866

Co-Authored-By: 54ac <me@54ac.ovh>
2025-01-27 04:25:37 +01:00
vishnyanetchereshnya
f29662c5b3
feat(ViewRaw): add View Role option (#3083)
Co-authored-by: v <vendicated@riseup.net>
2025-01-27 04:12:26 +01:00
Grzesiek11
cf28c65374
Add IrcColors plugin (#2048)
Co-authored-by: V <vendicated@riseup.net>
2025-01-27 03:34:00 +01:00
Suffocate
87cb1fd930
Fix top level settings notifying global listeners (#3166) 2025-01-26 15:32:34 +00:00
sadan4
aac5242dc8
ImageZoom: Fix incorrectly adding context menu in some places (#3150) 2025-01-24 21:15:56 -03:00
sadan4
4036fbab92
ConsoleJanitor: Remove old patch and add getLastCrash (#3151) 2025-01-25 00:01:12 +00:00
jamesbt365
79cbfe96c8
HideAttachments, UnsupressEmbeds: Work with forwarded messages (#2928) 2025-01-24 20:56:39 -03:00
jamesbt365
7ee70e831a
MessageLogger: Make collapseDeleted require a restart (#2923) 2025-01-24 23:46:47 +00:00
jamesbt365
e45b867ff0
ServerInfo: Add Ignored Users tab (#3127) 2025-01-24 23:42:05 +00:00
229ef03adf Merge branch 'main' of https://github.com/Vendicated/Vencord 2025-01-24 18:17:07 +01:00
Nuckyz
78c2f0d61a
Fix calling option onChange listeners for legacy settings 2025-01-24 00:43:33 -03:00
Nuckyz
72ec5e2023
Merge remote-tracking branch main into dev 2025-01-23 21:03:54 -03:00
Vendicated
43501bad07
bump to v1.11.2 2025-01-24 00:33:10 +01:00
Nuckyz
e000a947a3
Optimize slow patches 2025-01-22 23:10:43 -03:00
Nuckyz
5c8ba6e542
Settings API: add support for custom objects / arrays (#3154) 2025-01-23 01:51:11 +00:00
v
317121fc08
Replace API add/remove funcs with methods in plugin definition (#3028) 2025-01-23 01:48:44 +00:00
Nuckyz
30647b6bd9
Fix patches with duplicate finds 2025-01-22 22:44:52 -03:00
Nuckyz
ed99ae7f23
ShowHiddenThings: Fix showing ModView 2025-01-22 22:22:43 -03:00
AutumnVN
17f1ef275e
CustomRPC: improve rich presence preview & UX (#3159)
Co-authored-by: Vendicated <vendicated@riseup.net>
2025-01-23 01:33:11 +01:00
Nuckyz
ea0182a194
Fix BetterUploadButton & FixImagesQuality 2025-01-22 18:03:51 -03:00
Nuckyz
9e9d71d014
AccountPanelServerProfile: Fix buttons unusable and request spam 2025-01-22 17:40:47 -03:00
Vendicated
9bb983d40c
SortFriendRequests: improve formatting & display 2025-01-22 20:01:33 +01:00
Nuckyz
5312514de6
Bump to 1.11.0 2025-01-22 15:09:21 -03:00
Nuckyz
8346dba324
SortFriendRequests: Fix showing dates 2025-01-22 15:07:33 -03:00
Vendicated
47315b0eba
fix plugins modifying message content 2025-01-22 18:19:04 +01:00
sadan4
a60af65b6d
RevealAllSpoilers: Fix error on <C-S-Click> (#3149) 2025-01-18 18:05:06 -03:00
Sqaaakoi
88e3bc037d
ConsoleShortcuts: Set FluxStore toStringTag to store name (#3144) 2025-01-18 20:05:20 +00:00
sadan4
19361ef790
BadgeApi, AccountPanelServerProfile: Fix not working (#3147) 2025-01-18 16:52:35 -03:00
Nuckyz
c8f4ce9785
Fix PinDMs and BetterSettings eager load 2025-01-15 11:17:40 -03:00
Nuckyz
a53257634e
Fix Reporter action 2025-01-11 23:43:25 -03:00
Nuckyz
3243120baa
Reapply "MessagePopoverAPI: Fix buttons not appearing"
Actually applying the fix this time
2025-01-10 01:07:58 -03:00
Nuckyz
4ab297c9e3
Revert "MessagePopoverAPI: Fix buttons not appearing"
I didn't mean to push this yet
2025-01-09 06:22:07 -03:00
sadan4
154f371b14
BetterFolders: Fix for Discord Canary build (#3133) 2025-01-09 09:20:15 +00:00
Nuckyz
263a96c310
MessagePopoverAPI: Fix buttons not appearing 2025-01-08 19:41:13 -03:00
Nuckyz
5a77149b26
PinDMs: Fix real time updating when changing settings
again...
2025-01-08 19:06:09 -03:00
sadan4
2707b10021
BetterFolders: Fix dedicated sidebar (#3129) 2025-01-08 09:14:59 +00:00
v
7be3a40b7c
Add React eslint & update depencenies (#3090)
Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
2025-01-04 03:24:50 -03:00
sadan4
16a1c44947
PictureInPicture: Fix picture in picture button (#3120) 2025-01-04 02:21:50 -03:00
sadan4
3af06edb95
ConsoleShortcuts: Add openModal and openModalLazy (#3118) 2025-01-04 05:01:58 +00:00
nin0dev
34629307dd
SpotifyControls: Setting to restart playing song if playtime >3s (#3103) 2025-01-04 01:54:40 -03:00
sadan4
20ed7dc96b
new plugin FullUserInChatbox (#2766) 2024-12-30 02:07:26 -03:00
sadan4
0fd76ab15a
NoUnblockToJump: Also allow jump for ignored users (#3110) 2024-12-30 02:28:22 +00:00
fae
0e813e78d0
OpenInApp: Add support for geo.music.apple.com links (#3101) 2024-12-30 02:24:29 +00:00
Sqaaakoi
79e2cb15f1
QuickReply: Prevent caret from moving when selecting message (#3104) 2024-12-29 23:22:10 -03:00
Nuckyz
cca5d7dc09
ShowHiddenThings: Discovery filter bypass is patched
Filtering is now done server-side in Discord
2024-12-21 20:55:41 -03:00
Vendicated
9ccc74bde3
use correct prodversion in chrome extension installer 2024-12-20 15:06:19 +01:00
Heli-o
5d1f6e606a Merge branch 'main' of https://github.com/Vendicated/Vencord 2024-12-17 08:39:35 +01:00
Nuckyz
48a9aef2eb
PinDMs: Fix real time updating when changing settings 2024-12-16 19:36:15 -03:00
Nuckyz
fc731bc6c8
Bump to 1.10.9 2024-12-14 02:37:15 -03:00
Nuckyz
0a0bd6a713
NoTrack: Make hasClientMods return false 2024-12-14 02:36:16 -03:00
Nuckyz
40a8cf1a85
PinDMs: Fix duplicate channels 2024-12-12 19:46:51 -03:00
Lumap
5f1c5fa370
AppleMusicRichPresence: Fix token fetching Regex (#3071) 2024-12-12 22:40:44 +00:00
sadan4
00c968473e
FavoriteEmojiFirst: Fix sorting emojis (#3074) 2024-12-12 19:35:40 -03:00
sadan4
2dc8c2bf76
Fix multiple plugins for latest Discord update (#3072) 2024-12-12 03:49:21 -03:00
sadan4
464c4a9b61
TypingTweaks: Fix usernames not being colored (#3070) 2024-12-11 01:06:34 -03:00
sadan4
dcfddcbc21
ConsoleJanitor: Add HLJS deprecations (#3062) 2024-12-10 21:37:21 +00:00
Nuckyz
9d3c91e9df
TypingTweaks: Fix plugin 2024-12-10 18:29:15 -03:00
Nuckyz
8d65bcf743
BetterFolders: Fix folder icon setting 2024-12-10 18:09:54 -03:00
Heli-o
ae6f37267c Merge branch 'main' of https://github.com/Vendicated/Vencord 2024-12-10 18:42:00 +01:00
Nuckyz
4a5f0838e2
Remove workaround for Devtools theme 2024-12-07 20:32:16 -03:00
Nuckyz
99dc65fe4e
Fix TypingIndicator & CallTimer 2024-12-07 20:31:08 -03:00
Nuckyz
3a339636d1
Remove old plugin migrations 2024-12-07 19:55:37 -03:00
Nuckyz
cea0a3c9d9
NoScreensharePreview: Allow plugin to be turned on/off 2024-12-07 19:15:05 -03:00
Vendicated
a3f5dc39a0
CallTimer: fix crashing on canary 2024-12-07 00:14:08 +01:00
sadan4
df44edd41b
BetterFolders: Fix including open folders in main sidebar (#3064) 2024-12-05 21:07:30 -03:00
Nuckyz
cdfc89b819
NoScreensharePreview: Migrate to stock Discord feature 2024-12-03 22:39:36 -03:00
Nuckyz
8711dd9a4b
WebContextMenus: Fix input bar menu 2024-12-03 21:51:41 -03:00
Sqaaakoi
df454ca952
MutualGroupDMs: Fix in DM sidebar when no mutual friends/servers (#2976) 2024-12-02 23:30:56 -03:00
Etorix
6628624082
CommandHelpers: Make findOption use nullish coalescing (#3047) 2024-12-03 02:16:13 +00:00
Etorix
dd87f360d7
CommandsAPI: Fix spread overwriting omitted subcommand options (#3057) 2024-12-03 02:13:27 +00:00
Nuckyz
3f61fe722d
AlwaysTrust: Fix disabling suspicious file popup 2024-12-02 21:51:29 -03:00
Nuckyz
d70e0f27dc
ServerListIndicators: Account for pending clans count 2024-12-02 20:39:54 -03:00
Nuckyz
0ac80ce9d1
MessagePopoverAPI: Add buttons after quick reactions 2024-12-01 00:10:08 -03:00
Nuckyz
fcece61995
Bump to 1.10.8 2024-11-29 19:26:55 -03:00
sadan4
02f50b161b
ImageZoom: Fix zoom level not saving (#3054) 2024-11-29 22:26:10 +00:00
Vendicated
1150a50355
Badges: fix overflow in Discord's css 2024-11-29 22:46:28 +01:00
v
11321eb693
Update CONTRIBUTING.md
Plugins interacting with specific Discord bots are not allowed.
2024-11-29 16:11:55 +01:00
Nuckyz
60b776669b
WebContextMenus: Fix copy context menu 2024-11-25 20:03:34 -03:00
sadan4
d8df96d1e3
BetterFolders: Fix dedicated sidebar (#3037) 2024-11-25 19:44:29 -03:00
Sqaaakoi
a9d44e3341
PermissionsViewer: Fix permission description tooltip & cleanup (#3040) 2024-11-25 01:14:25 -03:00
Mia Rodriguez
e7a54b0587
SilentTyping: Improve button visual look (#3026) 2024-11-25 00:35:12 +00:00
sadan4
23c9e2ce22
ShowHiddenThings: Allow opening mod view on yourself (#3045) 2024-11-24 21:30:27 -03:00
Etorix
5fb63246ca
Add support for onAuxClick on ChatBarButton (#3043) 2024-11-24 21:25:30 -03:00
samara
2bfeef88ca
Update to newer Discord icons in Vencord Settings (#3029) 2024-11-23 23:23:03 -03:00
Hen
7ca4ea3d13
RoleColorEverywhere: Fix message headers colors (#3036) 2024-11-23 23:16:41 -03:00
Cassie
f8dfe217b1
Remove no-longer desired collaborator (#3032) 2024-11-24 02:08:53 +00:00
sadan4
f22d0e14a4
EmoteCloner: Fix recognizing animated emojis (#3027) 2024-11-24 02:07:46 +00:00
sadan4
ac1b1d44f5
ShowHiddenChannels: Fix viewing voice channels (#3033) 2024-11-24 02:03:59 +00:00
sadan4
13993f3f69
Decor: Fix avatar decorations not showing (again) (#3025) 2024-11-24 02:01:58 +00:00
Heli-o
61ddbe9bcd Merge branch 'main' of https://github.com/Vendicated/Vencord 2024-11-22 16:03:58 +01:00
Nuckyz
a0308e03af
Fix OpenInApp & ShowHiddenThings 2024-11-19 21:17:20 -03:00
Nuckyz
cd61f4e744
RoleColorEverywhere: Fix Online/Offline 2024-11-17 20:45:05 -03:00
jenku
5cf22113cf
Decor: Update notice about joining the server for clarity (#3021) 2024-11-17 18:55:33 -03:00
Nuckyz
ea2772476d
RoleColorEverywhere: Poll Results & Cleanup
Co-authored-by: jamesbt365 <jamesbt365@gmail.com>
2024-11-17 18:45:07 -03:00
nyx
99458da3be
ViewRaw: Add support for Group DMs (#3010) 2024-11-14 20:00:11 -03:00
Lumap
c4f6f151e6
PictureInPicture: Fix button not showing up (#3014) 2024-11-14 19:57:16 -03:00
Frocat
8558b1a589
ShikiCodeblocks: Updated codeblocks themes (#3013) 2024-11-14 19:54:01 -03:00
Nuckyz
76df29fba2
Actually stop searching for CSS debugging chunk 2024-11-14 14:51:58 -03:00
80866a609b Merge branch 'main' of https://github.com/Vendicated/Vencord 2024-11-14 13:15:41 +01:00
Nuckyz
25ceff5ec2
ChunkLoader: Avoid CSS debugging chunk 2024-11-13 18:44:21 -03:00
Nuckyz
e0d66ff071
NoMosaic: Fix plugin not working in Canary 2024-11-13 18:10:47 -03:00
sadan4
66a75747f8
ViewIcons: Fix conflict with unread Group DMs (#3011) 2024-11-13 17:44:13 -03:00
Nuckyz
211569f7f5
AlwaysExpandRoles: Fix collapse roles button not appearing 2024-11-13 15:41:57 -03:00
sadan4
af1edc88bf
FakeNitro: Fix embedding animated emojis (#3012) 2024-11-13 18:27:21 +00:00
Nuckyz
7ef536c6c6
Decor: Prevent more crashes 2024-11-12 15:02:56 -03:00
Nuckyz
69dc4fd594
Decor: Fix avatar decorations not showing
This reverts & edits commit 3b295e1f6f.
2024-11-12 14:53:11 -03:00
Nuckyz
1fe7912ec1
Decor: Prevent crashing from useUserDecorAvatarDecoration 2024-11-12 14:23:07 -03:00
Nuckyz
0cb84cee83
Bump to 1.10.7 2024-11-09 10:19:32 -03:00
Nuckyz
49c9fa1c8e
Settings: Fix fallback patch 2024-11-08 15:26:42 -03:00
Nuckyz
fd1aba7bab
NoTrack: Remove obsolete patch 2024-11-08 06:54:09 -03:00
Nuckyz
3b295e1f6f
Revert "Decor: Fix crashing"
cd3a998c4b.
2024-11-08 06:21:38 -03:00
Nuckyz
152d4fdbb3
Fix misc plugins errors on account switch 2024-11-07 15:34:28 -03:00
sadan4
ce0740b885
TypingTweaks: Fix crashing in some languages (#2998) 2024-11-07 15:34:28 -03:00
sadan4
64c3dd1c16
PatchHelper: Prevent trailing comma error (#2913) 2024-11-07 18:23:03 +00:00
sadan4
5f7a2c59c6
BetterFolders: Fix try-catch with no effect (#3000) 2024-11-07 18:16:32 +00:00
Nuckyz
cd3a998c4b
Decor: Fix crashing 2024-11-07 15:07:00 -03:00
Nuckyz
2270b88a98
intl macro: Support raw hash 2024-11-06 21:52:26 -03:00
1d5709763a Merge branch 'main' of https://github.com/Vendicated/Vencord 2024-11-06 06:33:51 +01:00
sadan4
9d4e859a0a
NoBlockedMessages: Fix for new i18n lib (#2996) 2024-11-05 19:01:52 -03:00
Nuckyz
439a4f8eb6
Bump to 1.10.6 2024-11-05 16:51:18 -03:00
Nuckyz
00f82e96bd
Fix all plugins for new i18n lib (#2993) 2024-11-05 16:50:26 -03:00
Nuckyz
5216bcca1e
Fix settings & updater for Canary 2024-11-03 15:47:19 -03:00
Vendicated
e7e298d2e7
ThemeAttributes: fix freezing when changing avatar 2024-10-26 13:48:22 +02:00
sadan4
d897dab054
ShowHiddenChannels: Fix viewing voice channels (#2979) 2024-10-26 07:32:32 -03:00
sadan4
88e8fa7e90
NoPendingCount: Fix hiding offers count (#2975) 2024-10-25 06:48:11 -03:00
Nuckyz
f5f59be1b6
Fix plugins using ImageModals (again) 2024-10-24 08:10:37 -03:00
sadan4
534ab3eb5f
ConsoleJanitor: Brush react-spring deprecation (#2973) 2024-10-24 11:09:12 +00:00
sadan4
a6ea03bacc
ImageZoom: Fix when multiple images with carrousel (#2966)
Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
2024-10-24 11:08:02 +00:00
c3bdc71512 Merge remote-tracking branch 'upstream/main' 2024-10-23 12:35:49 +02:00
Vendicated
e620431210
bump to v1.10.5 2024-10-23 04:47:29 +02:00
Aiden
5afc24b41a
ArmCord -> Legcord (#2948) 2024-10-23 04:39:43 +02:00
Vendicated
7f8e241b9c
"fix" OpenInApp 2024-10-23 04:33:30 +02:00
sadan4
553293ceee
fix MutualGroupDMs (#2964)
Co-authored-by: v <vendicated@riseup.net>
2024-10-23 04:28:30 +02:00
Vendicated
0af820c874
Fix ImageZoom
Also fixes the image modal being off centre when having the plugin enabled

Co-Authored-By: sadan <117494111+sadan4@users.noreply.github.com>
2024-10-23 04:22:11 +02:00
Vendicated
a11ccde40f
Fix ViewIcons & plugins that use image modals
Co-Authored-By: sadan <117494111+sadan4@users.noreply.github.com>
2024-10-23 03:57:46 +02:00
Nuckyz
58c3032bb2
Rework PronounDB -> UserMessagesPronouns 2024-10-19 08:08:34 -03:00
sadan4
4e89352758
Fix ShowHiddenChannels & FakeNitro broken functionality (#2959) 2024-10-19 11:06:42 +00:00
Nuckyz
e818905520
Workaround https://github.com/electron/electron/issues/43367 2024-10-10 09:17:32 -03:00
sadan4
aa1b446c07
ShowHiddenChannels: Fix re-organizing channels (#2942) 2024-10-10 09:16:36 -03:00
programminglaboratorys
2dce060cf9
MessageClickActions: Fix editing messages which failed to send (#2677) 2024-10-09 08:57:30 +00:00
Vendicated
89bb3ee30a
SupportHelper: fix DM warning card 2024-10-09 03:18:31 +02:00
Pavel Djundik
47db61d00e
Add icon to userscript meta (#2936) 2024-10-07 17:11:29 +02:00
a592586af7 Added origin setup 2024-10-07 07:05:24 +00:00
0567320fc6 Merge branch 'main' of https://github.com/Vendicated/Vencord 2024-10-07 07:01:53 +00:00
Nuckyz
416d85dcf0
new plugin FixImagesQuality 2024-10-06 13:20:06 -03:00
Nuckyz
013c8d061d
Bump to 1.10.4 2024-10-05 14:24:39 -03:00
Nuckyz
b5f626d1ff
Fix multiple plugins (again) 2024-10-05 08:01:40 -03:00
sadan4
1e01f85217
NoBlockedMessages: Fix conflict with MessageLogger (#2921) 2024-10-04 09:29:59 +00:00
sadan4
91a32e22de
PermissionsViewer: Fix profile button (#2925) 2024-10-04 06:28:36 -03:00
ryanamay
43b3c137ce
BlurNSFW: Fix not blurring embeds (#2862) 2024-10-03 07:11:37 +00:00
Nuckyz
18f7b74210
Fix required plugins being shown as disabled 2024-09-27 05:46:50 -03:00
sadan4
eab0cf9966
VolumeBooster: fix stream on web based clients (#2916)
Co-authored-by: v <vendicated@riseup.net>
2024-09-27 00:26:13 +02:00
Nuckyz
e7956413e2
Optimize slow patches 2024-09-26 14:02:36 -03:00
Vendicated
832e874c35
bump to v1.10.3 2024-09-26 18:19:08 +02:00
Heli-o
55146db760 Merge branch 'main' of https://github.com/Vendicated/Vencord 2024-09-26 16:52:09 +02:00
sadan4
bc59fc41b3
Fix multiple plugins for latest Discord update (#2911)
Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
Co-authored-by: thororen1234 <78185467+thororen1234@users.noreply.github.com>
2024-09-25 22:25:48 -03:00
Vendicated
1abfb5f0cf
CustomIdle: fix crash on canary 2024-09-25 23:12:08 +02:00
Nuckyz
cb2848f186
ContextMenuAPI: Fix findGroupChildrenByChildId 2024-09-24 02:13:44 -03:00
sadan4
c3f2e76b9c
BetterFolders: Fix sidebar in wrong location (#2904) 2024-09-24 02:09:33 -03:00
Nuckyz
eb63a54fa6
UserVoiceShow: Fix incorrect dependencies 2024-09-23 13:23:30 -03:00
lewisakura
5881716c57
RoleColorEverywhere: Fix unneeded restart on setting change (#2899) 2024-09-23 13:23:30 -03:00
sadan4
d7cbe270e5
FakeNitro: Fix wrongfully allowed emojis in voice calls (#2901) 2024-09-23 13:23:30 -03:00
Nuckyz
c29362ca89
FullSearchContext: Re-add Copy Author ID 2024-09-23 13:23:30 -03:00
Heli-o
fd0fbace2e Merge branch 'main' of https://github.com/Vendicated/Vencord 2024-09-22 19:55:21 +02:00
Nuckyz
409f47bf24
PronounDB: Fix crashing 2024-09-22 14:26:50 -03:00
Vendicated
b0e2f310bc
RoleColorEverywhere: add chat message colour toggle 2024-09-22 18:26:10 +02:00
Nuckyz
65069c673c
UserVoiceShow: Fix showing hidden channels 2024-09-22 13:05:08 -03:00
Nuckyz
b1db18c319
PronounDB: Rework API to avoid rate limits 2024-09-22 12:47:18 -03:00
TheGreenPig
db5fe2a394
Fix plugin settings inconsistency regarding setting names (#2884) 2024-09-22 04:48:54 -03:00
sadan4
e4318a887a
ConsoleJanitor: Ignore all loggers with whitelist (#2896) 2024-09-22 04:48:54 -03:00
Kyuuhachi
eaf62d8c1c
RoleColorEverywhere: Add coloring to message contents (#2893) 2024-09-22 07:11:07 +00:00
DokterKaj
22a5b18bfa
CopyFileContents: Add padding to button (#2848) 2024-09-21 16:54:50 -03:00
Drew
1dc2d92493
ReplaceGoogleSearch: Fix DuckDuckGo URL (#2895) 2024-09-21 16:54:49 -03:00
Joona
492b0cff08
OpenInApp: Fix opening in spotify activity cards for web (#2894) 2024-09-21 16:54:49 -03:00
Nuckyz
2d675b4b2e
ReviewDB: Fix in panel profile (again) 2024-09-21 16:54:49 -03:00
Nuckyz
49b0a38c37
UserVoiceShow: Show in messages 2024-09-21 16:54:49 -03:00
Nuckyz
467157539c
Bump to 1.10.2 2024-09-20 09:16:16 -03:00
Nuckyz
e8242f22c9
UserVoiceShow: Better support for DM channels 2024-09-20 09:06:26 -03:00
Vendicated
f7587d9b2e
ShowHiddenThings: fix discovery keyword filter bypass 2024-09-20 02:03:50 +02:00
adryd
755e869db7
clearURLs: Add si@soundcloud.com to rule list (#2890) 2024-09-20 01:31:20 +02:00
Nuckyz
a015cf96f6
UserVoiceShow: Fix setting name 2024-09-19 13:33:32 -03:00
Vendicated
c7e5295da0
SearchReply => FullSearchContext ~ now adds all options back 2024-09-18 21:33:46 +02:00
Vendicated
8afd79dd50
add Icons to webpack commons 2024-09-18 01:36:52 +02:00
Vendicated
65c5897dc3
remove need to depend on CommandsAPI 2024-09-18 01:26:25 +02:00
Nuckyz
6cce8a8bc4
Experiments: Allow clips to be recorded without streaming 2024-09-17 14:30:23 -03:00
Nuckyz
1848b16536
ReviewDB: Fix in panel profile 2024-09-17 14:30:23 -03:00
Kyuuhachi
c572116b97
BetterSettings: Add submenu for plugins (#2858)
Co-authored-by: Vendicated <vendicated@riseup.net>
2024-09-17 15:40:11 +00:00
Lumap
e26986f66a
AppleMusicRichPresence: fix formatting when listening to radio (#2869)
Co-authored-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
Co-authored-by: v <vendicated@riseup.net>
2024-09-17 17:29:46 +02:00
Nuckyz
f12335a371
UserVoiceShow: Fix for simplified profiles 2024-09-16 15:16:41 -03:00
Nuckyz
640d99dcda
delete NoDefaultHangStatus ~ Removed feature 2024-09-16 07:51:10 -03:00
Vendicated
bcfef05a8a
delete TimeBarAllActivites ~ now a stock feature 2024-09-14 17:22:29 +02:00
Cookie
f17b92c2fd
OpenInApp: support Spotify prerelease links (#2870) 2024-09-14 15:03:58 +00:00
Ryan Cao
292f7d71d3
AppleMusicRichPresence: fix metadata fetching (#2864) 2024-09-14 16:59:05 +02:00
Heli-o
9d67421b34 Merge branch 'main' of https://github.com/Vendicated/Vencord 2024-09-13 11:36:12 +02:00
sadan4
b822542352
BetterFolders: Fix pending clan applications (#2867) 2024-09-12 07:46:00 -03:00
Nuckyz
f27361f017
TimeBarAllActivities: Fix timestamp component 2024-09-11 08:13:23 -03:00
thororen
a765212cfe
NoTrack: Fix blocking analytics (#2857) 2024-09-11 07:50:55 -03:00
Heli-o
c07d78fa96 Merge branch 'main' of https://github.com/Vendicated/Vencord; branch 'main' of https://git.derg.cz/ulysia/Vencord 2024-09-06 21:20:48 +02:00
Relitrix
56459bdcad
new plugin AccountPanelServerProfile (#2836) 2024-09-06 12:33:23 -03:00
Nuckyz
868b2ea9f0
Fix SortFriendRequests received date 2024-09-06 09:40:10 -03:00
Nuckyz
9e7f8829f2
CustomRPC: Fix activity preview styling 2024-09-06 09:22:52 -03:00
niko
e5a4db6460
TimeBarAllActivities: Fix not working (#2847) 2024-09-06 11:40:29 +00:00
Vendicated
8890c8c6b4
fix Commands, Badges, RoleColorEverywhere 2024-09-05 02:35:40 +02:00
Vendicated
61d3c08f1f
bump to v1.10.1 2024-09-05 02:25:27 +02:00
Vendicated
e6994e1946
MentionAvatars: Fix compatibility with ServerInfo plugin 2024-09-05 02:24:35 +02:00
Nyako
40512d7294
XSOverlay: fix profile images (#2788)
Fixes https://github.com/Vendicated/Vencord/issues/2787

Co-authored-by: v <vendicated@riseup.net>
2024-09-05 00:16:41 +00:00
Vendicated
be02baffaa
MemberCount: fix null safety
and improve types for PopoutPosition

Co-Authored-By: fres621 <126067139+fres621@users.noreply.github.com>
2024-09-05 02:13:40 +02:00
Haruka
99cd423efb
fix crashing on canary when searching slash commands (#2844) 2024-09-04 23:26:08 +02:00
Nuckyz
7333f40db6
Dearrow: Fix thumbnails with default option 2024-09-04 10:16:45 -03:00
ElectricSteve
244cb26c32
Dearrow: Add option to not dearrow by default (#2818) 2024-09-04 09:12:58 -03:00
Nuckyz
df8aec8e3c
Fix BetterFolders and FriendsSince 2024-09-04 08:25:23 -03:00
sadan4
d10e649b63
VolumeBooster: Fix playing sound in wrong output device (#2840) 2024-09-04 08:04:17 -03:00
Ramzi Al Haddad
7f784befc2
SecretRingToneEnabler: Option to always play Snow Halation Theme (#2831) 2024-09-03 10:50:25 +00:00
Maddie
30e4e83158
NoServerEmojis: Fix detecting server emojis (#2835) 2024-09-03 01:53:03 +00:00
Maddie
4c4f2894fb
PronounDB: Fix patched pronoun tooltip (#2832) 2024-09-02 08:37:54 +00:00
June Park
c51d7b8fb4
ReviewDB: Fix wording in server reviews (#2826) 2024-09-02 08:09:45 +00:00
Nuckyz
accfc15125
Ban ts-pattern normal import 2024-09-02 01:54:16 -03:00
Maddie
27e81b20db
Allow online themes to be applied only in dark or light mode (#2701) 2024-09-02 04:51:29 +00:00
Joona
d0ad4e6c1d
MutualGroupDMs: Add Mutual Groups to DM Sidebar (#2817) 2024-09-02 03:50:52 +00:00
vishnyanetchereshnya
0c71d6c3fa
PermissionsViewer: Show RoleIcons & which role grants permission (#2824) 2024-09-02 00:42:52 -03:00
sadan4
74fd85bd3d
VolumeBooster: Fix on Vesktop (#2828)
Also fixed an IgnoreActivities patch and added a README to it
2024-09-01 20:39:19 -03:00
Nuckyz
968e688c10
Bump to 1.9.9 2024-09-01 00:53:46 -03:00
vxray
b595a3e33c
OpenInApp: Add support for localization in Spotify URL regex (#2776) 2024-09-01 03:20:22 +00:00
sadan4
e07a4e19e6
VolumeBooster: Support browser and Vesktop (#2730) 2024-09-01 03:08:33 +00:00
ImBanana
273981deb7
new plugin StickerPaste ~ Insert stickers instead of sending (#2781) 2024-08-31 23:40:03 -03:00
sadan4
81eabc7ee2
PatchHelper: Add Copy as Codeblock button (#2820) 2024-09-01 02:13:22 +00:00
Obsidian
d5eaae9d51
new plugin CopyFileContents ~Easily copy text file attachments contents (#2790) 2024-08-31 23:09:14 -03:00
niko
00276cad7c
TimeBarAllActivities: Support new activity cards (#2813) 2024-09-01 01:45:57 +00:00
Heli-o
ee9fbc4d25 added steps 2024-08-30 17:16:12 +02:00
Heli-o
0cea347264 Merge branch 'main' of https://github.com/Vendicated/Vencord 2024-08-30 16:57:58 +02:00
Nuckyz
eb0d91fd8e
Add ts-pattern as @webpack/common 2024-08-30 06:12:28 -03:00
Nick Oates
07e629d8d4
SuperReactionTweaks: Allow disabling Super Reactions (#2805) 2024-08-30 05:39:40 +00:00
Cookie
e473a57c3d
IgnoreActivities: Add option for blacklist filter (#2712) 2024-08-30 01:08:48 +00:00
Nuckyz
ad3d936dfd
Fix settings wrapping fallback 2024-08-29 21:41:51 -03:00
Nuckyz
db2f5c9292
ConsoleJanitor: Remove non needed patch
notosans no longer errors
2024-08-29 03:56:21 -03:00
Surge
5bfc608f7d
new plugin AlwaysExpandRoles ~ Alternative to ShowAllRoles (#2809) 2024-08-29 06:43:52 +00:00
Nuckyz
7d8214fc37
Fix PermissionsViewer on user popouts 2024-08-28 02:10:24 -03:00
Heli-o
cdf72cf4be added a userplugin 2024-08-26 21:21:02 +02:00
SerStars
4b16fbcaa9
MentionAvatars: Also display role icons in role mentions (#2801)
Co-authored-by: Vendicated <vendicated@riseup.net>
2024-08-26 10:27:00 +00:00
Nuckyz
7ec842d4b0
MoreUserTags: fix settings ui logic
Co-authored-by: Vendicated <vendicated@riseup.net>
2024-08-23 20:09:58 -03:00
Vendicated
6659f2c413
bump to v1.9.8 2024-08-24 00:19:10 +02:00
Nuckyz
1fb5e8df99
Add missing methods to ExpressionPickerStore 2024-08-23 19:00:26 -03:00
Nuckyz
1e8f59f13d
ReviewDB: Add view review button to other profiles types 2024-08-23 18:50:05 -03:00
Nuckyz
f0e6986835
PronounDB: Fix on user profiles 2024-08-23 18:41:40 -03:00
Supertiger
8afcb8e4dd
new plugin NoMaskedLinkPaste (#2782)
Co-authored-by: v <vendicated@riseup.net>
2024-08-23 23:36:47 +02:00
ImBanana
2569c39ddf
MemberCount: add thread support (#2785)
Co-authored-by: v <vendicated@riseup.net>
2024-08-23 17:54:12 +02:00
Nuckyz
ed9b28febf
Fix ViewIcons and NoProfileThemes 2024-08-23 03:02:04 -03:00
Nuckyz
2e81b9aeba
PermissionsViewer: Fix user popout 2024-08-22 20:29:39 -03:00
v
44c8463496
Remove obsolete patches for old profiles (#2800)
Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
2024-08-22 17:13:57 +02:00
Vendicated
2bdc2f4e82
delete ShowAllRoles ~ now a stock feature 2024-08-22 17:08:46 +02:00
Nuckyz
66b247b2d3
Fix persisting $$vencordPatchedSource when a module is loaded again 2024-08-20 04:13:21 -03:00
Nuckyz
3d80cb2d55
Delete AutomodContext ~ Now a stock feature 2024-08-19 17:50:21 -03:00
rini ☔
904022a2f7
[Webkeybinds] Don't override browser keybinds (#2792) 2024-08-18 20:20:03 +02:00
Nuckyz
9cada9ad13
fix(Webpack): Not canonicalizing regex in some places 2024-08-18 00:47:16 -03:00
Nuckyz
051bce89f8
feat(Webpack): Add $$vencordPatchedSource to patched factories 2024-08-18 00:26:40 -03:00
HAHALOSAH
eaca14bb5a
Fix Online Themes tab (#2786) 2024-08-17 04:30:34 +00:00
Nuckyz
d388aa4347
Decor: Fix on current user area 2024-08-14 19:34:59 -03:00
Nuckyz
4301ed889d
Fix ShowHiddenThings feature & PauseInvitesForever 2024-08-13 01:51:18 -03:00
Joona
1a712e75a6
fix(SpotifyControls): sync with external shuffle toggles (#2767)
Co-authored-by: v <vendicated@riseup.net>
2024-08-10 16:35:21 +00:00
Vendicated
87e6fa8647
build: improve errors when breaking module boundaries 2024-08-10 17:25:47 +02:00
Lumap
003e4a08d5
fix PictureInPicture (#2773)
Co-authored-by: v <vendicated@riseup.net>
2024-08-10 16:39:33 +02:00
Vendicated
4e3c178043
fix MutualGroupDMs 2024-08-10 16:35:11 +02:00
Vendicated
5160f906f4
delete MaskedLinkPaste ~ now a stock Discord feature 2024-08-03 19:02:48 +02:00
Vendicated
021d9bf179
fix message hover buttons... again 2024-08-03 17:54:25 +02:00
Vendicated
d1996034b7
fix YoutubeAdblock not working for some users 2024-08-03 15:18:35 +02:00
Vendicated
8274b67597
fix message hover buttons 2024-08-03 11:04:03 +02:00
Nuckyz
e437498c8f
Fix broken patches 2024-08-02 21:27:02 -03:00
Nyako
09c6c16cf9
XSOverlay: Return old API for compatibility (#2753) 2024-08-02 18:19:15 +00:00
Aiden
e99eec50bc
Migrate to eslint flat config; update dependencies (#2627)
Co-authored-by: vee <vendicated@riseup.net>
2024-08-02 12:12:59 +02:00
Vendicated
d919cd6bf1
bump to v1.9.7 2024-08-01 15:08:08 +02:00
Sqaaakoi
c185f47f4d
ShowHiddenThings: Fix ModView highest role fix (#2747) 2024-08-01 13:04:52 +00:00
ingobeans
83d90f03ee
FakeProfileThemes: fix crash when encountering invalid colours (#2714) 2024-08-01 15:01:48 +02:00
Vendicated
0f8d21a846
new plugin YoutubeAdblock: blocks ads in embeds (formerly WatchTogetherAdblock) 2024-08-01 14:50:09 +02:00
Sqaaakoi
2658459a98
fix: Add ViewRaw & MessageLogger context menu options on threads (#2750) 2024-08-01 12:12:44 +00:00
Ashton
f8b01c1a31
Translate: Add DeepL support (#2721)
Co-authored-by: v <vendicated@riseup.net>
2024-08-01 14:10:27 +02:00
jenku
2382294e8b
Decor: add copy preset id button (#2737)
Co-authored-by: v <vendicated@riseup.net>
2024-08-01 08:57:00 +00:00
Luna
d47be6c017
MentionAvatars: Add option to hide @ symbol(#2725)
Co-authored-by: v <vendicated@riseup.net>
2024-08-01 07:20:00 +00:00
Nick Oates
6c12a33aa6
fix(BetterFolders): Close folders when switching accounts (#2748) 2024-08-01 09:12:02 +02:00
Scab
9cc42bf457
MutualGroupDms: make display consistent with Mutual Servers (#2727)
Co-authored-by: Cookie <52550063+Covkie@users.noreply.github.com>
2024-08-01 09:10:30 +02:00
Vendicated
1bfdcf2697
fix BetterUploadButton on canary 2024-07-31 03:08:57 +02:00
Vendicated
3013c669c0
Fix ShowConnections
Co-Authored-By: Masterjoona <69722179+Masterjoona@users.noreply.github.com>
2024-07-31 03:02:10 +02:00
fres621
e460b5efb6
Fix MessagePopoverAPI patch (#2746)
Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
2024-07-30 20:26:58 -03:00
Nyako
902a86c3b2
XSOverlay: Update to new API (#2736)
Co-authored-by: v <vendicated@riseup.net>
2024-07-30 21:48:11 +00:00
Surge
51ae019cd5
feat(plugins/openInApp) Refactor code and add Apple Music support (#2744)
Co-authored-by: v <vendicated@riseup.net>
Co-authored-by: Shiggy <136832773+shiggybot@users.noreply.github.com>
2024-07-30 23:42:57 +02:00
Sqaaakoi
0f5cf37ef9
fix(ShowHiddenThings): always render highest role in ModView (#2709) 2024-07-30 21:18:42 +00:00
thororen
5c88284ed3
feat(showHiddenChannels): Fix Broken Patch (#2726) 2024-07-26 12:55:32 -03:00
Vendicated
5e9a9fe836
bump to v1.9.6 2024-07-25 13:49:01 +02:00
Masterjoona
bc801853e2
Fix ImageZoom, SpotifyControls and ViewIcons (#2723)
Co-authored-by: Vendicated <vendicated@riseup.net>
2024-07-25 13:46:00 +02:00
Vendicated
2044264729
fix PictureInPicture on canary 2024-07-23 02:56:24 +02:00
Nuckyz
3704c71ae1
Fix loading scientific notation chunks 2024-07-19 00:50:39 -03:00
Vendicated
80b493d7a8
WhoReacted: fix errors 2024-07-17 21:30:10 +02:00
Vendicated
67632ecc11
MentionAvatars: fix mentions being ultra wide in topics 2024-07-17 02:36:19 +02:00
Vendicated
c3852cb892
fix badges on canary 2024-07-17 02:34:05 +02:00
Vendicated
5bd10c8608
MessageLogger: fix edit modal close button 2024-07-15 05:09:13 +02:00
Kyuuhachi
ea746f6633
MessageLogger: add compact display of history & edit modal (#2299)
Co-authored-by: vee <vendicated@riseup.net>
2024-07-15 04:51:42 +02:00
Vendicated
2b273d9dbd
fix(MessageLogger edits): render with proper guild context 2024-07-15 03:54:01 +02:00
Jono99
71977f070a
fix(ShowMeYourName) - proper case insensitive name comparison (#2633)
Co-authored-by: vee <vendicated@riseup.net>
2024-07-14 22:24:55 +02:00
Vendicated
bbf43c3073
fix(FakeNitro): do not convert applicable twitch sub emotes 2024-07-13 20:34:16 +02:00
Hen
0e7570ad71
InvisibleChat: fix embeds missing decrypted content (#2655) 2024-07-13 17:17:00 +00:00
vee
92ae62602b
new plugin MentionAvatars: Shows user avatars inside mentions (#2691) 2024-07-13 19:14:22 +02:00
Nuckyz
0057ab42e8
Fix broken experiments patch 2024-07-12 16:40:26 -03:00
Ulysses Zhan
993304f96c
CtrlEnterSend: fix for new Discord update (#2689)
Co-authored-by: vee <vendicated@riseup.net>
2024-07-12 19:27:28 +00:00
Nuckyz
04dce64bfd
Fix broken patches/finds 2024-07-11 16:56:02 -03:00
Nuckyz
9f8c749421
Fix broken patches 2024-07-10 04:33:03 -03:00
Vendicated
02092a985c
BetterNotes: fix crashing 2024-07-06 18:43:13 +02:00
Vendicated
9f79cc05a6
bump to v1.9.4 2024-07-06 18:31:43 +02:00
Vendicated
319a99c293
fix(MessageLogger): don't break attachment edits 2024-07-05 18:43:51 +02:00
Vendicated
c3f7950f2e
MessageLogger: fix not blurring deleted spoilers 2024-07-05 17:12:46 +02:00
Vendicated
93dc880bc0
Delete UrbanDictionary ~ better done via user app
https://discord.com/application-directory/search?q=urban
2024-07-05 16:58:11 +02:00
Vendicated
78d2713151
Delete WikiSearch ~ better done via user app
https://discord.com/application-directory/search?q=wiki
2024-07-05 16:56:32 +02:00
Nuckyz
bec4c76d9a
Fix ShowAllRoles 2024-07-04 17:04:16 -03:00
Nuckyz
256a85c95c
feat(plugins): ConsoleJanitor (#2659) 2024-07-03 00:10:08 -03:00
Vendicated
99b41dba19
improve settings ui (again) 2024-07-02 21:49:09 -03:00
Ulysses Zhan
77492061f5
ctrlEnterSend: fix for new Discord update (#2647) 2024-07-01 00:59:36 +02:00
Vendicated
5c05443f45
improve settings ui 2024-06-29 20:27:00 +02:00
Masterjoona
8a7c0d7e61
WebContextMenus: implement context menu for text selection (#2577)
Co-authored-by: vee <vendicated@riseup.net>
2024-06-29 16:42:27 +00:00
Antti Ellilä
2d570a524b
friendsSince: add support for new profiles (#2623)
Co-authored-by: vee <vendicated@riseup.net>
2024-06-29 16:39:09 +00:00
Luna
086c31c890
new plugin ShowAllRoles: show all roles in simplified profiles (#2624)
Co-authored-by: vee <vendicated@riseup.net>
2024-06-29 15:43:25 +00:00
Vendicated
169edcb5b7
improve support helper 2024-06-29 17:34:13 +02:00
Vendicated
bda0e1844b
browser: increase minimum browser versions 2024-06-29 11:21:13 +02:00
Nuckyz
2fa56b80ab
Harder conditions for Sentry patching 2024-06-29 01:33:16 -03:00
Nuckyz
5c1c786cf9
Fix ReviewDB patch 2024-06-28 18:34:23 -03:00
Nuckyz
62485e8694
Obliterate Sentry 2024-06-28 18:34:23 -03:00
Vendicated
e4bf71784e
TextReplace: support /v regex flag 2024-06-28 16:04:51 +02:00
Vendicated
484d70fb15
bump to v1.9.3 2024-06-28 13:20:24 +02:00
Nuckyz
df6ffd90e3
Fix broken patches 2024-06-28 00:53:09 -03:00
Nuckyz
96873ccef7
Temp fix for disabling Sentry 2024-06-27 23:58:01 -03:00
Nuckyz
cbc7f7230a
Fix acquiring WebpackRequire 2024-06-27 23:37:10 -03:00
Vendicated
e37a0cfec9
bump to v1.9.2 2024-06-27 16:16:29 +02:00
Nuckyz
f81cd5d9a4
Fix broken patches 2024-06-27 16:15:42 +02:00
Vendicated
7c923b9962
fix enabled by default logic 2024-06-27 16:14:32 +02:00
Vendicated
14e11973ef
fix ShowConnections & FakeProfileThemes 2024-06-26 18:42:05 +02:00
Vendicated
bc0d4a80ff
BadgeAPI: fix bugs in new profiles 2024-06-26 18:09:21 +02:00
Vendicated
e0d99e2f6c
add ReviewDB in new profiles 2024-06-26 17:37:21 +02:00
Vendicated
6d4c9339dc
PermissionsViewer: add to simplified profiles 2024-06-26 17:36:00 +02:00
Vendicated
705da29df5
add Mutual Groups to new profiles 2024-06-26 17:10:48 +02:00
Vendicated
7f1ccef383
fix ShowConnections 2024-06-26 13:27:39 +02:00
Scyye
3ad76b7f0f
NewGuildSettings: Add "Apply NewGuildSettings" button in menu (#2556)
Co-authored-by: vee <vendicated@riseup.net>
2024-06-26 11:10:39 +00:00
Lorenzo Rizzotti
4008c93069
ShowHiddenThings: fix discovery filter bypass (#2626)
Co-authored-by: vee <vendicated@riseup.net>
2024-06-26 13:03:23 +02:00
programminglaboratorys
cd205b1386
ReviewDB: add to context menu in new profile ui (#2622)
Co-authored-by: vee <vendicated@riseup.net>
2024-06-26 11:02:20 +00:00
Bloofield
3688c7e4c9
ShowMeYourName: compare username & nick case insensitive (#2630)
Co-authored-by: vee <vendicated@riseup.net>
2024-06-26 10:59:24 +00:00
Oliver Anderson
32c2128c5b
ReplaceGoogleSearch: improve search engine selection (#2620)
Co-authored-by: vee <vendicated@riseup.net>
2024-06-26 10:57:18 +00:00
Vendicated
d61a930b99
Developer Documentation has moved to https://docs.vencord.dev 2024-06-26 01:12:19 +02:00
Jakup
df32e8d305
fix missing space in MoreKaomoji (#2625) 2024-06-25 21:40:25 +02:00
Nuckyz
62afad3e65
IgnoredActivities: Fix not ignoring in tracked activities (used in Content Feed) 2024-06-22 20:22:43 -03:00
Nuckyz
87d3e30ebf
web extension: fix vencord sometimes breaking after reloading
Co-Authored-By: vee <vendicated+git@riseup.net>
2024-06-22 08:05:18 +02:00
Vendicated
3d46f19025
bump to v1.9.1 2024-06-22 03:25:40 +02:00
Vendicated
6ce7fde19c
upgrade monaco (QuickCss Editor) to 0.50.0; fixes some syntax 2024-06-22 01:10:08 +02:00
Vendicated
18df66a4b4
fix SpotifyControls 2024-06-22 00:31:28 +02:00
Nuckyz
e16c9ca70f
GameActivityToggle: Fix moving settings button outside 2024-06-21 18:50:21 -03:00
Vendicated
495da11347
fix Summaries 2024-06-21 22:49:55 +02:00
Vendicated
0b033aa51b
PluginManager: catch errors during plugin flux handlers 2024-06-21 22:42:25 +02:00
Vendicated
b9392c3be2
Improve SupportHelper
- improve update check when entering support channel
- add "Run Snippet" button to venbot messages with codeblock
- add "Send /vencord-debug" button to messages that contain /vencord-debug
- add "Update Now" button to messages by venbot and in #known-issues that contain "update"
- add some common issues like RPC disabled / NoRPC enabled to /vencord-debug
- split plugin list into separate /vencord-plugins command to reduce size & avoid >2000 chars errors
2024-06-21 19:58:01 +02:00
Nuckyz
7dc1d4c498
ReverseImageSearch: Fix duplicate find 2024-06-21 04:15:45 -03:00
Vendicated
c7e4bec940
Plugin Page: add indicator for excluded plugins 2024-06-21 04:15:45 -03:00
Nuckyz
db1481711b
Reporter: Test mapMangledModule 2024-06-21 04:15:44 -03:00
Nuckyz
d4ed747434
Clean-up related additions to mangled exports 2024-06-21 04:15:44 -03:00
Nuckyz
d07042236d
Add wrapSettingsHook back; Fix FakeNitro subscription emoji bypass 2024-06-19 23:50:03 -03:00
Vendicated
3ce241021f
PluginModals: add plugin website & source code links 2024-06-20 04:40:07 +02:00
Masterjoona
76f6912511
VoiceMessages: properly respect user's microphone choice (#2602) 2024-06-19 20:04:39 +02:00
Vendicated
e9e789be70
fix NewGuildSettings 2024-06-19 16:59:54 +02:00
ryan-0324
920f326053
fix MoreUserTags (#2599) 2024-06-19 16:56:01 +02:00
Vendicated
d12624ac4b
Fix ShowHiddenThings 2024-06-19 16:51:04 +02:00
Vendicated
28ddadf732
Fix CustomIdle 2024-06-19 16:24:24 +02:00
Nuckyz
d04ead7d35
FakeNitro: Fix theme bypass 2024-06-19 02:39:15 -03:00
Vendicated
7b6259215a
Fix VoiceMessages 2024-06-19 07:38:21 +02:00
vee
3505adad6d
final batch of fixes ~ we are SO BACK!! (#2598)
* Fix ImplicitRelationships

* performance fixes

* fix false pos

* fix super reaction tweaks

* Fix PermissionFreeWill

* Fix AlwaysTrust

* clean ups

* Fix ImageLink

* Fix ValidReply

* Fix ShowHiddenChannels partially and race conditions related to exports

* fix bucnh of webpack finds

* Fix FriendsSince, RevealAllSpoilers

* finish show hidden channels

* read if cute

* doomsday fix: ClientTheme (#2597)

* fix friendinvites

* fix extractAndLoadChunks

* bleh

* fix FakeNitro

* fake nitro part 2

* and part 3

* bump to v1.9.0

* remove dead settings patch

* fix ForceOwnerCrown

* fix decor lazy load

---------

Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
Co-authored-by: rushii <33725716+rushiiMachine@users.noreply.github.com>
2024-06-19 07:16:29 +02:00
vee
d19b0aeb5b
second batch of fixes (#2596)
Co-authored-by: programminglaboratorys <107296738+programminglaboratorys@users.noreply.github.com>
Co-authored-by: Haruka <personal@shiroko.me>
Co-authored-by: Amia <9750071+aamiaa@users.noreply.github.com>
Co-authored-by: AutumnVN <autumnvnchino@gmail.com>
Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
2024-06-19 04:36:21 +02:00
vee
d6f1209438
fix first set of plugins (#2591)
* Add back mangled webpack searching

* Make window non enumerable in all cases

* fix some webpack commons

* oops

* fix more webpack commons

* fix some finds

* fix more webpack commons

* fix common names

* fix reporter

* fix Constants common

* more fix

* fix SettingsStores (return of old SettingsStoreAPI)

* doomsday fix: MutualGroupDMs (#2585)

* fix SettingsStoreAPI

* fix MessageLinkEmbeds

* fix checking uninitialised settings

* doomsday fix: BetterSessions (#2587)

* doomsday fix: ReviewDB and Summaries (#2586)

Co-authored-by: vee <vendicated@riseup.net>

* fix various things that use default/other names

* fix settings

* wbctxmenus

* fix BetterSettings

* wouldnt it be funny if discord reverted again once we're done

* fix ViewIcons

* fix showconnections

* fix FriendsSince

* FakeNitro: fix app icons

* doomsday fix: NoPendingCount (#2590)

---------

Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
Co-authored-by: Amia <9750071+aamiaa@users.noreply.github.com>
Co-authored-by: Manti <67705577+mantikafasi@users.noreply.github.com>
2024-06-19 03:04:15 +02:00
Nuckyz
db6b1f5aaf
Fix plugins on stable 2024-06-18 17:13:57 -03:00
Vendicated
098124175f
Fix crashes & settings on canary 2024-06-17 23:00:25 +02:00
SuperStormer
c1593e1806
Dearrow: fix ">" handling (#2582) 2024-06-17 19:13:27 +02:00
Vendicated
e79430ca84
RelationShipNotifier: try to fix false positives for unavailable guilds 2024-06-14 23:04:43 +02:00
Vendicated
ca810250d1
ConsoleShortcuts: add Stores map with all stores 2024-06-14 22:56:21 +02:00
Nuckyz
2f4e346e26
FixCodeblockGap: Fix broken patch 2024-06-13 23:28:38 -03:00
Nuckyz
e0e35058fd
Discord code blocks can't have indentation 2024-06-12 19:15:26 -03:00
Nuckyz
dc74d28b86
Reporter: Fix summary code blocks 2024-06-12 18:30:11 -03:00
Nuckyz
0561bd1951
fix: ShowConnections patch; chore: Remove dead code 2024-06-12 16:39:04 -03:00
Vendicated
40c5ade82d
MessageLinkEmbeds: fix display when using compact mode 2024-06-12 04:48:42 +02:00
Nuckyz
008227cdfc
Bump to 1.8.9 2024-06-11 23:31:42 -03:00
Nuckyz
fd2311db3b
Fix broken patches 2024-06-11 23:10:47 -03:00
Vendicated
9de18ac8c7
Experiments: add toggle for toolbar dev button
Co-Authored-By: F53 <fseusb@gmail.com>
2024-06-12 03:45:29 +02:00
Vendicated
64025bc523
MessageLogger: fix bugs with embeds & edits back to prev state 2024-06-12 02:32:42 +02:00
Nuckyz
26f5e829fe
o7 ResurrectHome - Home feature was removed from Discord
Discord deleted pretty much all the client side code for the legacy home. While it's still possible for the client side code to be reconstructed, it won't be an easy task, so the plugin is getting deleted for now (in case someone ever implements the home again).
2024-06-11 17:45:35 -03:00
Vendicated
aaba22f577
ShowConnections: improve look in simplified prof; fix tooltip overflow 2024-06-09 04:09:08 +02:00
Vendicated
4bf28f4634
BadgeAPI: fix our badges not showing if there are 0 discord badges 2024-06-09 04:09:08 +02:00
programminglaboratorys
50c4513737
RoleColorEverywhere: show role colors in the reactor list (#2490)
Co-authored-by: vee <vendicated@riseup.net>
2024-06-09 04:09:07 +02:00
Masterjoona
62830464af
fix showconnections in new profiles (#2567)
Co-authored-by: Vendicated <vendicated@riseup.net>
2024-06-09 04:09:07 +02:00
Vendicated
4ec01d0f40
disable UseEcoQoSForBackgroundProcess 2024-06-08 05:54:36 +02:00
Vendicated
65970618d8
fix badges in new profiles 2024-06-08 05:40:09 +02:00
AutumnVN
810ff894dc
ui(RestartCard): fix yellow button now being blue (#2550) 2024-06-08 04:21:27 +02:00
AutumnVN
914b211a91
betterRoleDot: fix click to copy role color in profile (#2551)
Co-authored-by: vee <vendicated@riseup.net>
2024-06-08 02:21:01 +00:00
Vendicated
2c5079b49f
MessageLogger: fix potential error 2024-06-08 04:15:29 +02:00
vee
239da032ec
README: add shiggy background on github 2024-06-08 00:49:11 +02:00
AutumnVN
5996e67c7d
fix USRBG & ViewIcons in new profiles (#2557)
Co-authored-by: Vendicated <vendicated@riseup.net>
2024-06-07 23:42:12 +02:00
Nickyux
29c65948b4
MessageLogger: add context menu option to clear channel history (#2008)
Co-authored-by: vee <vendicated@riseup.net>
2024-06-07 21:28:17 +00:00
Elvyra
1bc9a800a6
fix moreUserTags (#2563) 2024-06-07 23:05:14 +02:00
Lumap
40db2f5078
AppleMusicRichPresence: add option to disable large/small image (#2562) 2024-06-07 23:04:40 +02:00
NuclideK
c54650b29a
customRPC: fix typos in settings descriptions (#2559) 2024-06-07 20:24:49 +02:00
Nuckyz
43b6933fe6
Reporter: Include page errors; load wasm chunks 2024-06-06 00:48:54 -03:00
AutumnVN
0b611a2911
USRBG: fix in simplified profile (#2549) 2024-06-06 03:07:20 +00:00
AutumnVN
5976d52cbc
viewIcons: support new simplified profile (#2535)
Co-authored-by: Sqaaakoi <sqaaakoi-git@sqaaakoi.xyz>
2024-06-06 05:05:53 +02:00
notsu
9cafe8084c
SpotifyControls: fix no artists on local files (#2543)
Co-authored-by: vee <vendicated@riseup.net>
2024-06-06 02:17:47 +00:00
nekohaxx
67b709a796
new plugin NoOnboardingDelay: skip long onboarding animations (#2533)
Co-authored-by: Vendicated <vendicated@riseup.net>
2024-06-06 02:01:44 +00:00
nyx
0dac08c17d
PlatformIndicators: fix embedded (console) devices (#2546)
Co-authored-by: Vendicated <vendicated@riseup.net>
Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
2024-06-06 03:40:31 +02:00
Vendicated
b88be8014e
experiments: change toolbar help button -> dev menu 2024-06-06 02:55:18 +02:00
vishnyanetchereshnya
e5e8b9ba01
new plugin CopyEmojiMarkdown ~ more easily copy emoji formatting (#2266)
Co-authored-by: Happy enderman <66224387+happyendermangit@users.noreply.github.com>
Co-authored-by: vee <vendicated@riseup.net>
2024-06-06 01:40:02 +02:00
Ryan Cao
0aa7bef9fa
new plugin AppleMusicRichPresence (#2455)
Co-authored-by: Vendicated <vendicated@riseup.net>
2024-06-06 01:19:53 +02:00
Vendicated
9ab7b8b9c9
experiments: remove obsolete isStaff patch; rename ServerProfile -> ServerInfo 2024-06-05 23:46:53 +02:00
Nuckyz
23584393a9
NoPendingCount: Fix for message requests 2024-06-05 23:46:53 +02:00
Nuckyz
ed5ae2ba5c
Add shortcut for lazy loading chunks 2024-06-05 23:46:52 +02:00
Vendicated
8fd5d068da
fix(css): brand-experiment is now brand-500 2024-06-05 23:46:52 +02:00
lewisakura
06824c273f
chore: security advisory link for blank issues [skip ci] (#2542) 2024-06-03 12:01:34 +00:00
Nuckyz
a66138f157
Bump to 1.8.8 2024-06-01 00:30:18 -03:00
Nuckyz
aa7eb77050
ShowHiddenChannels: Fix patch 2024-05-31 23:41:38 -03:00
Nuckyz
d07e4c71b5
Make Reporter runnable in desktop 2024-05-31 23:28:58 -03:00
Nuckyz
7ccd073506
Fix ShowConnections & FriendsSince patches 2024-05-31 00:16:56 -03:00
Nuckyz
2b565fed25
Make vencord-debug usable everywhere if user is pluginDev 2024-05-30 18:34:16 -03:00
Nuckyz
05a40445c8
refactor: improve build scripts & automatic testing
- Fix reporter breaking because of ConsoleShortcuts
- Fix extractAndLoadChunks issue with 2 match groups; Improve testing of lazy extractAndLoadChunks
- Reporter: Properly implement reporter build of Vencord; Test more plugins; Fix running in wrong pages
- Fix wrong external files and clean up build script; Remove non used stuff
2024-05-30 23:30:44 +02:00
Nuckyz
537fc5e33d
feat(API): updateMessage API for forcing re-renders 2024-05-29 04:57:18 -03:00
Vendicated
9b9a5322c9
webpack: make window exports non enumerable 2024-05-29 06:32:49 +02:00
Vendicated
da01237c05
Summaries: update README 2024-05-29 05:21:05 +02:00
Vendicated
86aabe73eb
add more flags for preventing background unloading 2024-05-29 04:24:48 +02:00
vee
a78dba321d
ConsoleShortcuts: Fix autocomplete on lazies, add more utils (#2519) 2024-05-28 17:31:58 -03:00
Lexi
b9e83d9d28
new plugin DontRoundMyTimestamps: round 7.6y -> 7y instead of 8y (#2060)
Co-authored-by: V <vendicated@riseup.net>
2024-05-28 02:22:42 +00:00
AutumnVN
8131ca8f15
USRBG: support new simplified profile (#2501)
Co-authored-by: vee <vendicated@riseup.net>
2024-05-28 02:15:48 +00:00
Vendicated
5b35d7c644
fix occasional errors in Dearrow & ImageZoom 2024-05-28 02:35:40 +02:00
sunnie
c2f8837602
new plugin: MaskedLinkPaste (#2514)
Co-authored-by: vee <vendicated@riseup.net>
2024-05-28 02:23:30 +02:00
nin0dev
c431b7d2ab
fix(MessageLogger): correctly mark markdown headers red (#2511)
Co-authored-by: vee <vendicated@riseup.net>
2024-05-28 02:21:12 +02:00
Ulysses Zhan
8bda3a1e6a
LoadingQuotes: more customization & custom quotes support (#1795)
Co-authored-by: lewisakura <lewi@lewisakura.moe>
Co-authored-by: Vendicated <vendicated@riseup.net>
2024-05-27 18:36:09 +02:00
Nuckyz
6b4899804a
Summaries: Fix start error if no summaries-data exist 2024-05-26 21:16:12 -03:00
Luna
41c5bbd952
new plugin WatchTogetherAdblock: block ads in youtube activity (#2021)
Co-authored-by: vee <vendicated@riseup.net>
2024-05-26 19:44:04 +00:00
Vendicated
9ec671819d
build: improve fileInclude plugin 2024-05-26 19:15:51 +02:00
Vendicated
c836270320
fix minor bugs in various plugins
- FriendsSince: Don't show for friend requests
- FakeNitro: Fix attempting to bypass unicode emojis #2503
- MessageLatency: ignore bots #2504
- CtrlEnterSend: use cmd+enter on macOS #2502
- ReplaceGoogleSearch: trim LF character #2488

Co-authored-by: AutumnVN <autumnvnchino@gmail.com>
Co-authored-by: rushiiMachine <33725716+rushiiMachine@users.noreply.github.com>
Co-authored-by: Lumap <lumap@duck.com>
Co-authored-by: Mylloon <kennel.anri@tutanota.com>
2024-05-26 18:24:02 +02:00
Manti
4f2c2b8e4a
new plugin Summaries: show Discords AI-generated convo summaries (#2481)
Co-authored-by: Vendicated <vendicated@riseup.net>
2024-05-26 18:14:29 +02:00
Nuckyz
a8e18f17e2
ConsoleShortcuts: Start at Init 2024-05-26 01:11:36 -03:00
Nuckyz
8f59cd8a1a
Optimize slowest patches 2024-05-23 21:48:12 -03:00
Vendicated
1866e4d379
Bump to v1.8.6 2024-05-24 01:07:07 +02:00
Vendicated
349169e67a
discord why tf would u roll back to 10 days old build??? 2024-05-24 01:05:17 +02:00
Nuckyz
775877281e
Revert removal of DevTools context menu fix 2024-05-23 06:04:50 -03:00
Vendicated
a0778f6a2e
work around discord unloading in background 2024-05-23 03:35:02 +02:00
Vendicated
869e71112e
fix AnonymiseFilenames 2024-05-23 03:26:23 +02:00
Vendicated
b335df7fe2
MessageLogger: fix edit logging 2024-05-23 03:25:02 +02:00
Nuckyz
f686cba398
Fix not setting property on originalOnChunksLoaded 2024-05-22 05:11:09 -03:00
Nuckyz
f469060ccf
Fix reporter false positive and DefaultExtractAndLoadChunksRegex not catching all cases 2024-05-22 00:47:12 -03:00
Nuckyz
afd56820db
Revert "MessageLinkEmbeds: No longer need to reset global regex"
It is still needed for messageLinkRegex.test
2024-05-21 23:58:37 -03:00
PWall
0751722add
QuickReply: skip blocked messages if NoBlockedMessages enabled (#2476) 2024-05-21 02:52:43 +02:00
k26pl
44d708129b
fix(MessageLogger): correctly blur spoilered images (#2433)
Co-authored-by: vee <vendicated@riseup.net>
2024-05-21 00:44:29 +00:00
dolfies
08d7de06b2
ShowHiddenThings: more effectively explode Algolia filters (#2484)
Co-authored-by: vee <vendicated@riseup.net>
2024-05-21 02:28:06 +02:00
goodbee
9c092b9c29
feat(BetterRoleContext): Add option to view role icons (#2482)
Co-authored-by: vee <vendicated@riseup.net>
2024-05-21 00:24:00 +00:00
Alyxia Sother
f384fe6aa5
fakeProfileThemes: settings UI improvements (#966)
Co-authored-by: V <vendicated@riseup.net>
2024-05-21 00:13:24 +00:00
Vendicated
dac2d7520d
bump to v1.8.5 2024-05-20 18:19:45 +02:00
Nuckyz
025508f18d
StartupTimings: Fix patch 2024-05-19 23:32:15 -03:00
Nuckyz
0a595120b9
Fix: Ignore bundled lib webpack on web 2024-05-19 23:08:33 -03:00
Nuckyz
5f8b96dced
Change duplicate find for SHC and VCDoubleClick 2024-05-19 22:11:42 -03:00
Nuckyz
a94b88cd56
MessageLinkEmbeds: No longer need to reset global regex 2024-05-19 04:20:27 -03:00
Nuckyz
b33b5bdc9f
MessageLinkEmbeds: Add limit for nested links 2024-05-19 03:54:49 -03:00
Nuckyz
bc8b465753
chore: Make package manager version not strict 2024-05-19 03:40:38 -03:00
Nuckyz
eac8a026a6
fix(PatchHelper): Make find and match more responsive 2024-05-18 21:53:38 -03:00
Eric
d43731833a
Fix: PatchHelper not auto filling match field (#2338) 2024-05-19 00:45:05 +00:00
Noxillio
caed7cd92c
MoreUserTags: If server owner tag is disabled, do not give other tags (#2219) 2024-05-19 00:22:45 +00:00
Eric
54e1bac6c6
new plugin CustomIdle (#2342) 2024-05-18 23:41:58 +00:00
Nuckyz
04a86490a5
FriendsSince: Show in user profile modal 2024-05-18 00:36:50 -03:00
Nuckyz
4e92612aa8
ResurrectHome: Likely fix breaking latest messages in chat 2024-05-17 19:41:12 -03:00
Nuckyz
8b0e7030ad
ViewIcons: Fix Group Icons being clickable in channel list 2024-05-17 18:42:28 -03:00
vee
c3757a2ae6
add package for publishing types to npm (#2473)
https://www.npmjs.com/package/@vencord/types
2024-05-17 23:01:07 +02:00
flag
54817ab506
lastfmRPC: add setting to toggle "View Song" button (#2292)
Co-authored-by: vee <vendicated@riseup.net>
2024-05-17 16:36:35 +00:00
Nico
5fc6ba86d1
fix(replaceGoogleSearch): correct GitHub casing (#2471) 2024-05-17 17:40:01 +02:00
Nuckyz
84e477f678
Add missing README to new plugins 2024-05-17 05:43:40 -03:00
Nico
0b4b6031c5
new plugin NoDefaultHangStatus (#2468) 2024-05-17 08:21:12 +00:00
Nuckyz
60f8225b96
chore: Fix non standard plugin names 2024-05-17 04:51:59 -03:00
Nuckyz
6547cc10f7
FakeNitro: Fix attempting to bypass unicode emojis
Closes #2470
2024-05-17 04:34:50 -03:00
Moxxie
ffe1d7cc4d
new plugin ReplaceGoogleSearch (#2450) 2024-05-17 04:17:14 -03:00
Tuur Martens
03d83e1ff7
new plugin AutomodContext (#2290) 2024-05-17 04:11:41 -03:00
Nuckyz
0c50e153ef
FakeNitro: Fix & rewrite emoji bypass patches 2024-05-16 23:02:50 -03:00
Nuckyz
c5e554e48c
ViewIcon: Replace regex find with string find 2024-05-16 02:37:24 -03:00
nyx
cddc811c02
feat(ViewIcons): Group & User DMs icons support (#2464) 2024-05-16 05:26:40 +00:00
DShadow
fb19642d8d
fix(readAllNotificationsButton): Mark threads as read (#2437) 2024-05-16 01:07:14 -03:00
Sqaaakoi
4281b7a94a
ShowTimeoutDuration: Simplify tooltip style, allow changing style without reload (#2441) 2024-05-16 00:21:52 -03:00
Nuckyz
09f894468a
MessageLatency: Fix wrong constant & false positive 2024-05-15 23:38:36 -03:00
rozbrajaczpoziomow
7b4ecff67e
feat(MessageLatency): Show milliseconds option (#2454) 2024-05-15 23:22:45 -03:00
Nuckyz
c0c897fc23
extractAndLoadChunksLazy: Cache result to avoid searching factories everytime 2024-05-15 23:00:21 -03:00
Eric
0460374af0
Fix: Plugins without start/stop function failing to stop/start (#2463) 2024-05-16 01:46:09 +00:00
Nuckyz
54f58cd7c9
Fix: Canonicalize regex finds 2024-05-15 00:38:18 -03:00
Nuckyz
f74da73086
feat: Allow finds to use regex (#2452) 2024-05-14 23:57:43 -03:00
ScattrdBlade
4da8b9aad7
PetPet: Fix Upload Image Option (#2461) 2024-05-15 02:44:47 +00:00
Aztup
f4d6461690
feat(plugins/openInApp) Add tidal support (#2404)
Co-authored-by: vee <vendicated@riseup.net>
2024-05-15 04:35:00 +02:00
Eric
4d572670f1
new plugin ValidReply ~ fix "Message could not be loaded" (#2337)
Co-authored-by: V <vendicated@riseup.net>
2024-05-15 02:10:29 +00:00
Nuckyz
1fea842093
BetterFolders: Fix scrolling 2024-05-14 22:47:35 -03:00
mcpower
46801de21f
chore: tidy up suggested vscode extensions list (#2221)
Co-authored-by: Vendicated <vendicated@riseup.net>
2024-05-15 01:42:09 +00:00
Vendicated
0e4724ec0d
Settings: remove obsolete patch; add redundancy & more useful dbg copy 2024-05-15 03:14:02 +02:00
Nuckyz
840d571ce2
Fix BetterSettings & StartupTimings patch 2024-05-14 21:34:34 -03:00
! Sleepy
97dd56ccda
MoreUserTags: Add chat moderator tag (#2424)
Co-authored-by: Vendicated <vendicated@riseup.net>
2024-05-15 02:17:19 +02:00
Ulysses Zhan
81d3f5df1a
new plugin CtrlEnterSend (#1794)
Co-authored-by: vee <vendicated@riseup.net>
2024-05-15 01:21:00 +02:00
Ulysses Zhan
5232a85319
new plugin NoServerEmoji ~ hides server emojis from autocomplete (#1787)
Co-authored-by: vee <vendicated@riseup.net>
2024-05-15 01:18:30 +02:00
Board
d8b3869b81
ThemeAttributes: add larger avatar url variables to avatars (#2449)
Co-authored-by: vee <vendicated@riseup.net>
2024-05-14 23:07:33 +00:00
Vendicated
719c6140f3
fix Vencord Settings section being added multiple times 2024-05-14 21:18:43 +02:00
Vendicated
a54b55edad
bump to v1.8.4 2024-05-14 18:54:00 +02:00
Vendicated
12376c622e
fix settings ui on canary 2024-05-14 18:52:35 +02:00
Nuckyz
d4ebfc233f
Make all RestAPI calls use Endpoints object 2024-05-13 23:00:11 -03:00
Nuckyz
9dc8e4e244
Properly ErrorBoundary recent changes 2024-05-13 23:00:11 -03:00
Anubis
892167420a
MessageLogger: use discord variables instead of hardcoded colors (#2428) 2024-05-14 01:57:20 +00:00
Haruka
5d049534a7
FakeNitro: allow using subscription-locked emojis (#2456)
Co-authored-by: Vendicated <vendicated@riseup.net>
2024-05-14 03:39:05 +02:00
Amia
bd6f9e6f32
fix(MutualGroupDMs): properly pass props (#2457)
Co-authored-by: vee <vendicated@riseup.net>
2024-05-14 01:22:49 +00:00
axiand
9621dc7bb3
EmoteCloner: allow cloning from reactions (#2458) 2024-05-14 01:16:49 +00:00
dolfies
59ee9c501d
feat(ShowHiddenThings): Remove Discovery banned/NSFW filters (#2453) 2024-05-13 05:09:19 +00:00
Vendicated
f6765818d2
ValidUser: fix rendering old mentions when message is edited
Fixes https://github.com/Vendicated/Vencord/issues/2451
2024-05-13 03:54:15 +02:00
Vendicated
1f1c80c5f3
ValidUser: fix crashing when viewing a valid-userd staff's profile 2024-05-13 03:30:24 +02:00
Nuckyz
902b6bcdf2
PinDMs: ErrorBoundary renderChannel 2024-05-12 20:58:26 -03:00
dolfies
fd7dafb153
fix(MessageLatency): Adjust for Discord kotlin clients (#2443) 2024-05-12 23:07:12 +00:00
nyan
5c7fa5578c
XSOverlay: Adjust message length timeout (#2445) 2024-05-12 19:54:08 -03:00
Vendicated
bbec51fd19
but here's the bumper (v1.8.3) 2024-05-12 03:23:00 +02:00
Cats
a99354503f
feat(Translate): add toggle for chat bar icon (#2418) 2024-05-12 02:44:06 +02:00
HAHALOSAH
d6507947f5
Plugin Settings: fix text overflow for long plugin names (#2383)
Co-authored-by: V <vendicated@riseup.net>
2024-05-12 00:32:44 +00:00
Claire
f21db5cb01
add Native settings implementation (#2346)
Co-authored-by: vee <vendicated@riseup.net>
2024-05-12 02:08:17 +02:00
Vendicated
0f9acba59e
settingsSync: include date in filename for better sorting
Co-authored-by: cd CreepArghhh_ <65649991+cd-CreepArghhh@users.noreply.github.com>
2024-05-12 02:00:29 +02:00
Elvyra
b22bfc80fd
pronounDB: Update to API v2 (#2355)
Co-authored-by: vee <vendicated@riseup.net>
2024-05-12 01:23:51 +02:00
Fafa
cc5e39c9a9
Dearrow: allow configuring which elements get dearrowd (#2414)
Co-authored-by: Vendicated <vendicated@riseup.net>
2024-05-11 21:50:29 +00:00
Nuckyz
c55b0de30c
FakeNitro: Update description 2024-05-11 18:34:54 -03:00
nin0dev
207fe84636
CustomRPC: show warning when game activity is disabled (#2245)
Co-authored-by: V <vendicated@riseup.net>
2024-05-11 23:29:31 +02:00
Overcast Warmth System
9b328da4ce
ThemeAttributes: add data-author-username to messages (#2422) 2024-05-11 22:57:48 +02:00
Im_Banana
2eb8ba1841
SilentTyping: add chat input context menu option to toggle (#2386)
Co-authored-by: vee <vendicated@riseup.net>
2024-05-11 22:49:00 +02:00
Han Seung Min - 한승민
6b88eaccbb
messageLatency: fix grammar & add aliucord/kotlin client tooltip (#2426) 2024-05-11 16:09:48 +00:00
nyan
fbaa4ad5bc
XSOverlay: add settings for different notification types (#2055)
Co-authored-by: vee <vendicated@riseup.net>
2024-05-11 18:05:22 +02:00
DShadow
395b0007bf
permissionsViewer: add role & user context menus to copy id (#2436)
Co-authored-by: V <vendicated@riseup.net>
2024-05-11 17:43:34 +02:00
Nuckyz
1a3a378fb1
ErrorBoundary some more components 2024-05-09 03:14:20 -03:00
Vendicated
14e68d9a24
im the dumbest dumdum 2024-05-09 03:19:11 +02:00
Vendicated
251ee32e01
new plugin ShowTimeoutDuration ~ shows how much longer a user's timeout will last 2024-05-09 03:10:15 +02:00
Vendicated
a2acce55c3
BetterSettings: fix error handling crashing in some niche cases 2024-05-09 03:10:15 +02:00
Nuckyz
840a8f1fdd
CrashHandler: Increment timeout for trying to recover 2024-05-08 18:53:55 -03:00
Vendicated
6bd0898efe
fix(SupportHelper): dont flag vencord web as externally updated 2024-05-08 23:52:28 +02:00
Vendicated
025193533d
VoiceDownload: fix doing nothing on discord desktop app 2024-05-08 23:49:47 +02:00
Vendicated
b1cc67a860
fix(BetterSettings): do not catch errors of other ui 2024-05-08 23:42:04 +02:00
Nuckyz
6ad17ff7e7
BetterFolders: Fix component erroring 2024-05-08 17:12:13 -03:00
Vendicated
449f95500a
bump to v1.8.2 2024-05-08 03:56:25 +02:00
KK2-5
dd3b7e5346
LastfmRichPresence: Add option to use album name as status name (#2400)
Co-authored-by: vee <vendicated@riseup.net>
2024-05-08 03:55:32 +02:00
dolfies
5c787145e3
showHiddenThings: also show ModView & hidden discovery servers (#2415)
Co-authored-by: vee <vendicated@riseup.net>
2024-05-08 03:50:26 +02:00
puv
1317222c35
feat(plugin): VoiceDownload (#2280)
Co-authored-by: vee <vendicated@riseup.net>
2024-05-08 03:44:57 +02:00
Kyuuhachi
d3acd7edc7
new plugin ReplyTimestamp: show timestamps of replied messages (#2296)
Co-authored-by: vee <vendicated@riseup.net>
2024-05-08 03:39:20 +02:00
Han Seung Min - 한승민
efca196ded
new plugin MessageLatency: indicator for other people's latency (#2353) 2024-05-08 03:25:32 +02:00
kaitlynkitty
e2dc9e75d1
new plugin WebScreenShareFixes: remove low stream bitrate limit (#2405) 2024-05-08 03:17:42 +02:00
Vendicated
21d2019e60
improve SupportHelper 2024-05-08 03:14:41 +02:00
Nuckyz
53dda32fb0
BetterFolders: Fix broken patch 2024-05-07 21:39:34 -03:00
Vendicated
799b903da9
Revert "messageLogger: fix niche bug ignoring edits when content is same (#2403)"
This reverts commit 85d6d74a3e.

As suspected, this code was actually necessary
2024-05-07 22:40:14 +02:00
Vendicated
97acffafcc
fix useStateFromStores JSDoc
Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
2024-05-07 16:32:19 +02:00
Nuckyz
75847147d1
FakeNitro: Add custom notifications sound bypass 2024-05-07 03:20:56 -03:00
Nuckyz
0e66c4a1f5
Fix subscribing to plugin flux events twice 2024-05-07 02:47:08 -03:00
Vendicated
72b17761bb
upgrade nodejs & pnpm to latest versions 2024-05-07 04:54:25 +02:00
Nuckyz
ecf6af5884
FakeNitro: Make disableEmbedPermissionCheck setting not private 2024-05-06 05:07:46 -03:00
Sqaaakoi
61235ce994
ImageLink: Fix embed showing in gifs (#2417) 2024-05-05 17:53:51 -03:00
Fafa
45c1e42ce4
ReviewDB: Fix context menus being added to folders (#2416) 2024-05-05 17:53:51 -03:00
Nuckyz
a090872d8f
ImplicitRelationships: Properly test find 2024-05-05 17:53:51 -03:00
Nuckyz
60e6fdacfa
Resolve PluginSettings circular deps better 2024-05-05 17:53:51 -03:00
Vendicated
ce18000c4e
fix webpack patch on client using discordapp.com part 2 2024-05-05 18:58:23 +02:00
Vendicated
066b872219
fix webpack patch on client using discordapp.com 2024-05-05 18:56:49 +02:00
Vendicated
a525cd0113
bump to v1.8.1 2024-05-05 04:00:52 +02:00
Nuckyz
80b738ff3e
Future proof FakeNitro and Experiments to not brick Discord startup 2024-05-04 21:15:14 -03:00
Vendicated
dfb06e47d0
fix overflow when having two rows of badges 2024-05-04 01:39:38 +02:00
Gabriel Ruiz Pérez
04d7cb8797
NewGuildSettings: add push notifs, highlights & events (#2413)
Co-authored-by: V <vendicated@riseup.net>
2024-05-04 01:15:18 +02:00
dolfies
a6c09bc909
feat(ValidUser): also display badges & banner (#2235)
Co-authored-by: V <vendicated@riseup.net>
2024-05-04 00:21:02 +02:00
Nuckyz
a98f12bd1e
SecretRingToneEnabler: Fix patch 2024-05-03 19:07:43 -03:00
Nuckyz
54bb7b96e9
Test Patches: Remove pnpm add puppeteer as it's already in deps 2024-05-03 18:58:56 -03:00
Nuckyz
1ef87361f2
Test Patches: Faster chromium setup; Update action versions (#2412) 2024-05-03 21:47:15 +00:00
Kyuuhachi
0350db7690
feat(plugin): ImageLink (#2297) 2024-05-03 22:42:14 +02:00
Vendicated
520e915168
fix badges with custom component 2024-05-03 22:18:31 +02:00
sunnie
78183eb226
MsgClickActions: control ping via shift & NoReplyMention plugin (#2390)
Co-authored-by: V <vendicated@riseup.net>
2024-05-03 22:00:42 +02:00
katlyn
1af44b25f3
feat(USRBG): update to new API (#2388) 2024-05-03 14:51:53 +00:00
Sqaaakoi
315f4f4e58
ReviewDB: add more context menu shortcuts to view reviews (#2382)
Co-authored-by: V <vendicated@riseup.net>
2024-05-03 15:17:12 +02:00
dolfies
03d7e0fb93
fix sort conflict of ImplicitRelationships & SortFriendRequests (#2408) 2024-05-03 13:09:54 +00:00
Nuckyz
84c53b4a27
MoreUserTags: Remove old workaround; MessageClickActions: Move finds outside of start 2024-05-03 04:52:07 -03:00
dolfies
86b53b24a6
feat(plugin): PauseInvitesForever (#2372)
Co-authored-by: V <vendicated@riseup.net>
2024-05-02 23:09:53 +00:00
HAHALOSAH
85d6d74a3e
messageLogger: fix niche bug ignoring edits when content is same (#2403) 2024-05-02 23:00:00 +00:00
Nuckyz
a055b1d47b
refactor(Webpack): more reliable patching (#2237) 2024-05-02 23:52:41 +02:00
Vendicated
0a598ae966
fix FriendsSince 2024-05-02 15:38:53 +02:00
Vendicated
f54dcb74d7
improve contributor modal & badge 2024-05-02 15:24:00 +02:00
Nuckyz
5bc20ba162
NoTrack: Option to keep analytics, improve patches 2024-05-02 00:36:37 -03:00
Nuckyz
7af733c7c8
RoleColorEverywhere: Actually fix patch 2024-05-01 17:19:42 -03:00
Nuckyz
0f7e60b208
ResurrectHome: Fix patch 2024-05-01 17:09:45 -03:00
Nuckyz
761e6b39ed
RoleColorEverywhere: Fix patch 2024-05-01 16:35:48 -03:00
Nuckyz
51729c828e
Bump to 1.8.0 2024-04-30 20:49:27 -03:00
HAHALOSAH
6d01093eec
fix(fakeNitro): Use getEmojiURL as emoji.url was removed (#2401) 2024-04-30 20:30:01 -03:00
Nuckyz
97886e5728
BetterFolders: Fix patch; MessageLogger: Ignore Venbot; ReviewDB: Clean migration code 2024-04-30 17:34:45 -03:00
dolfies
840c775ed8
fix(ImplicitRelationships): Use new Flux event (#2392) 2024-04-27 17:29:29 -03:00
Nuckyz
d2941281a4
Bump to 1.7.9 2024-04-27 01:04:47 -03:00
Nuckyz
304bc96660
RoleColorEverywhere: Fix patch again 2024-04-27 01:03:07 -03:00
Nuckyz
fafd46d202
FriendsSince: Remove workaround for stable compatibility 2024-04-26 18:32:03 -03:00
Nuckyz
c10466f607
MoreUserTags: Fix patches 2024-04-26 18:31:57 -03:00
Nuckyz
36327ebd70
PronounDB: Fix patch 2024-04-26 15:56:06 -03:00
Elvyra
4fce88fa8f
Fix OnePingPerDM and RoleColorEverywhere patches (#2387) 2024-04-24 18:05:02 -03:00
Koda!!
9e0aa4b23c
feat(plugin): StreamerModeOnStream (#2320)
Co-authored-by: V <vendicated@riseup.net>
2024-04-24 05:51:49 +02:00
dolfies
d55205c55a
feat(plugin): ImplicitRelationships (#947)
Co-authored-by: Angelos Bouklis <53124886+ArjixWasTaken@users.noreply.github.com>
Co-authored-by: V <vendicated@riseup.net>
2024-04-24 05:41:53 +02:00
My-Name-Is-Jeff
6a69701b54
fix ValidUser (#2381) 2024-04-24 03:30:23 +00:00
Vendicated
d5f70070ef
fix badges 2024-04-24 05:27:14 +02:00
Vendicated
7f0e7dd02b
fix FakeProfileThemes 2024-04-24 05:23:50 +02:00
Amia
5cf014cb06
New Plugin: BetterSessions (#1324)
Co-authored-by: V <vendicated@riseup.net>
2024-04-23 23:06:19 +02:00
dolfies
af67ddefa1
ShowTimeouts->ShowHiddenThings ~show invite-disabled tooltip too (#2375) 2024-04-23 01:46:11 +02:00
Vendicated
8f73b9fd5f
Make Updater slightly more future proof
- Removes the option to disable update notifications. Users really should not be outdated, so this option was never good. To disable notifications, turn on auto update
- Enables auto update by default. Users keep complaining about issues while being outdated, so this should help
- Update Notification now opens Updater in a modal to remove dependency on Settings patch. This makes it slightly more failsafe, it's unlikely that both modals and our settings patch break
2024-04-20 14:51:33 +02:00
Vendicated
0bebc85b0d
fix FriendsSince on canary 2024-04-20 11:52:58 +02:00
Vendicated
74df53e7c8
ValidUser: fix not working for @unknown-user mentions 2024-04-20 11:37:22 +02:00
Vendicated
87ef214810
RoleColorEverywhere: fix chat mentions 2024-04-20 11:29:15 +02:00
Elvyra
5aa19bbf49
fix ValidUser (#2369) 2024-04-20 11:18:03 +02:00
Vendicated
97ce410f57
bump to v1.7.8 2024-04-18 00:53:28 +02:00
Vendicated
82d914e62f
CustomRPC: fix preview styles 2024-04-18 00:40:09 +02:00
Vendicated
0c6ddf80e8
ShowConnections: fix icon theme logic 2024-04-18 00:26:09 +02:00
Vendicated
89c82e2cd1
fix settings patch 2024-04-17 23:42:56 +02:00
Vendicated
538b87062a
bump to v1.7.7 2024-04-17 04:44:56 +02:00
Vendicated
23b0841cc7
fix ShowConnections 2024-04-17 04:44:42 +02:00
Elvyra
3a79e41d67
fix MessageLogger (#2358) 2024-04-16 20:11:25 +00:00
AutumnVN
356a2c290d
fix: RoleColorEverywhere, PictureInPicture, NoMosaic (#2356) 2024-04-16 20:10:15 +00:00
Vendicated
52f8a85ab9
fix(FavoriteEmojiFirst): don't lower suggestion count on hover 2024-04-14 14:26:36 +02:00
Vendicated
0f5a75aa4b
bump to v1.7.6 2024-04-14 02:39:04 +02:00
Vendicated
99f523b87c
fix extractAndLoadChunks for when there are no chunks to be loaded 2024-04-14 02:22:13 +02:00
Vendicated
00427c53d8
fix pronoundb 2024-04-14 01:50:18 +02:00
AutumnVN
59fc922aee
viewIcons: fix for banners (#2351) 2024-04-13 23:40:27 +00:00
Elvyra
af7d1b9df2
fix ShowMeYourName (#2354) 2024-04-13 23:36:56 +00:00
Vendicated
e5bd5534db
Fix SpotifyControls 2024-04-14 01:35:04 +02:00
Vendicated
89dc74d5d7
partially revert "Array support for find + ResurrectHome: View Server Home Button on Server Guide (#2283)"
This reverts commit 5636f9d979.

It breaks Vesktop which is not acceptable. Need to resolve this conflict and add this back later
2024-04-14 00:59:04 +02:00
Nuckyz
5636f9d979
Array support for find + ResurrectHome: View Server Home Button on Server Guide (#2283) 2024-04-09 17:09:23 -03:00
Vendicated
dc4c678aa3
bump to v1.7.5 2024-04-09 04:19:35 +02:00
AutumnVN
7fa1259821
NoMosaic: make loading image work with responsive layout (#2095) 2024-04-09 04:04:09 +02:00
Haruka
34c74b43bd
new plugin UnlockedAvatarZoom: allows crop zooming in further (#2287)
Co-authored-by: V <vendicated@riseup.net>
2024-04-09 03:56:28 +02:00
Vendicated
38ffdd7d94
FriendsSince: Add icon to be consistent with "member since"
Co-authored-by: Trey <47907719+trwy7@users.noreply.github.com>
2024-04-09 02:52:21 +02:00
Sqaaakoi
26f3618c2c
TypingIndicator: Add an option to show user avatars (#2319)
Co-authored-by: Vendicated <vendicated@riseup.net>
2024-04-09 02:41:48 +02:00
byron
ae01e88e13
EmoteCloner: fix low quality; don't count managed emojis (#2321)
Co-authored-by: Nam Anh <phamnamanh25@gmail.com>
Co-authored-by: ryan-0324 <77452312+ryan-0324@users.noreply.github.com>
Co-authored-by: V <vendicated@riseup.net>
2024-04-09 02:33:18 +02:00
AutumnVN
3ecd2deae5
plugin settings: fix filter dropdown having no padding (#2332) 2024-04-09 02:23:55 +02:00
Eric
cba611c1cc
Better error for primitives on proxyLazy + fix StartupTimings (#2339) 2024-04-08 04:33:35 +00:00
Vendicated
e0becc1ba0
ShowHiddenChannels: Fix incompatibility with favorite channels experiment 2024-04-07 21:46:32 +02:00
Jade ・:*・。*・
c311155d7c
PinDMs: Fix unexpected behaviours when using last message sort (#2324) 2024-04-05 16:29:08 -03:00
Nuckyz
778d79cd35
Fix MutualGroupDMs and UserVoiceShow patch 2024-04-05 16:09:04 -03:00
Kyuuhachi
18d4780635
fix(MessageLinkEmbeds): Actually disable when disabled (#2323) 2024-04-03 12:51:28 +00:00
Nuckyz
88f353e7f6
ResurrectHome: Fix Force Server Home patch 2024-04-02 13:39:28 -03:00
Koda!!
c623e44786
ReviewDB: Fix website url (#2318)
Co-authored-by: V <vendicated@riseup.net>
2024-03-31 04:33:03 +02:00
Vendicated
b158cecd4b
FakeNitro: Fix sending unavailable emotes of the current server 2024-03-31 01:26:57 +01:00
Vendicated
69b349da77
fix minor updater bugs 2024-03-30 00:28:15 +01:00
Syncx
650f4050e1
fix(PinDMs): display properly when there are 0 unpinned dms (#2281)
Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
Co-authored-by: V <vendicated@riseup.net>
2024-03-28 21:40:47 +01:00
Nuckyz
60f6678107
Decor: Fix find targetting wrong module in some cases 2024-03-28 12:57:28 -03:00
Nuckyz
bdef47eb8a
Bump to 1.7.4 2024-03-28 11:44:38 -03:00
Nuckyz
7fe718a018
FakeNitro: Make Soundboard sounds not require boost level 2024-03-28 11:30:04 -03:00
Nuckyz
126023f8f2
ShowHiddenChannels: Fix patches 2024-03-28 10:46:28 -03:00
Nuckyz
762684a138
Fix more patches 2024-03-28 10:30:29 -03:00
Nuckyz
74c38146d5
Fix BetterSettings patches (#2307) 2024-03-28 10:17:05 -03:00
AutumnVN
2f07dc230a
fix BetterGifPicker, Experiments 2024-03-28 10:02:09 -03:00
TheKodeToad
344f8c9f03
Fix DisableCallIdle 2024-03-28 09:58:57 -03:00
Nuckyz
ec34412100
Fix store finds 2024-03-28 09:49:59 -03:00
AutumnVN
de9122b05b
fix ImageZoom, LoadingQuote, NoRPC, RevealAllSpoilers, SecretRingTone (#2306) 2024-03-28 06:43:05 +01:00
Vendicated
82ab3ad1b9
i may be stupid :3 2024-03-28 05:18:00 +01:00
Vendicated
e71fcc3010
Fix FakeNitro 2024-03-28 04:21:52 +01:00
Nuckyz
c997ff7ada
Fix lazy chunk force loading 2024-03-28 04:05:11 +01:00
Vendicated
6c711e2781
Fix PinDMs 2024-03-28 03:58:11 +01:00
Vendicated
b1009baf7a
Fix MessageLogger 2024-03-28 03:47:00 +01:00
Vendicated
74b6ceee78
Fix WhoReacted 2024-03-28 03:43:37 +01:00
Vendicated
8ab56f5bcf
ReadAllNotificationButton: make button less ugly 2024-03-27 21:44:54 +01:00
Vendicated
0d22ff0091
webpack: fix infinite recursion when using ConsoleShortcuts plugin 2024-03-27 21:27:56 +01:00
Nuckyz
31c21594e6
Reporter: Ignore another useless error 2024-03-27 10:39:58 -03:00
Nuckyz
0983a038f1
Fix broken patches 2024-03-27 10:30:34 -03:00
Nuckyz
e1f8b3cb30
UserVoiceShow: Fix UserPopout patch stealing predicates from another component 2024-03-22 09:45:28 -03:00
Nuckyz
8d35cc6112
BetterNotes: Fix patches 2024-03-22 09:45:28 -03:00
Vendicated
ca18b6e044
Fix CloudSync 2024-03-22 04:08:08 +01:00
Vendicated
caa14ece0d
bump to v1.7.3 2024-03-22 03:14:57 +01:00
mcpower
ec66c35d41
MessageLinkEmbeds: Load embeds from newest to oldest (#2230)
Co-authored-by: V <vendicated@riseup.net>
2024-03-22 01:27:09 +00:00
Inbestigator
1cb295b1b9
new plugin: OverrideForumDefaults (#2272)
Co-authored-by: Vendicated <vendicated@riseup.net>
2024-03-22 02:16:24 +01:00
MrDiamondDog
5646fe402a
feat(PatchHelper): Paste Full Patch (#1982) 2024-03-21 23:59:25 +00:00
Syncx
2ce3487477
PinDMs: add category support & fix bugs (#2203)
Co-authored-by: V <vendicated@riseup.net>
2024-03-22 00:55:37 +01:00
Trey
55901ba35e
AlwaysTrust: Add options for each popup (#2234)
Co-authored-by: V <vendicated@riseup.net>
2024-03-21 23:44:37 +00:00
Masterjoona
04d5423b08
fix(AnonymiseFileNames): anonymise files in forum posts (#2270) 2024-03-21 23:42:41 +00:00
Eric Liu
021948c919
WhoReacted: fix scroll jumping when rendering users (#2271)
Co-authored-by: V <vendicated@riseup.net>
2024-03-22 00:39:26 +01:00
Vendicated
3e332a6062
fix RestAPI find 2024-03-21 23:27:08 +01:00
Vendicated
0d5f492891
fix ReviewDB 2024-03-21 21:17:47 +01:00
thororen
ae9435ac55
MemberCount: Fix error when not in a channel (#2277) 2024-03-19 12:06:09 +01:00
AutumnVN
90ee07fd98
emoteCloner: fix cloning gif stickers (#2268) 2024-03-16 16:43:04 +01:00
Hyper
356d8d8e5e
feat(MessageLogger): Add delete & edit toggle (#2032)
Co-authored-by: V <vendicated@riseup.net>
2024-03-16 02:27:59 +00:00
Vendicated
23aeb21272
fix ViewIcons & Decor patches 2024-03-16 02:30:36 +01:00
Kyuuhachi
6140b95814
new plugin: BetterSettings ~ improves Discord's settings (#2222)
- makes opening settings much faster
- removes the scuffed transition animation
- organises the settings cog context menu into categories

Co-authored-by: Vendicated <vendicated@riseup.net>
2024-03-16 02:19:26 +01:00
stupid cat
f3ee43fe66
favGifSearch: don't error on favourited non-urls (#2260) 2024-03-13 22:23:04 +01:00
Vendicated
afdcf0edb9
refactor shared utils to more obviously separate contexts 2024-03-13 21:59:09 +01:00
V
9aa205b5ec
rewrite settings api to use SettingsStore class (#2257)
Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
2024-03-13 21:45:45 +01:00
Vendicated
7190437e92
rename Devs.obscurity => Devs.fawn :3 2024-03-13 00:36:42 +01:00
Nuckyz
bf9a225038
HTTP Updater: Only include first commit line 2024-03-12 20:18:46 -03:00
Nuckyz
6a7657de3f
Remove getGuildRoles 2024-03-12 20:18:44 -03:00
Nuckyz
6e363814d1
ResurrectHome: Fix README image 2024-03-11 12:37:59 -03:00
Vendicated
2730eada8d
Bump to v1.7.2 2024-03-11 16:35:21 +01:00
Elvyra
f9924d555a
new Plugin: FriendsSince ~ shows friend date in profiles (#2240)
* feat: Create friendsSince plugin

* chore: add devs entry

* fix text

* Update src/plugins/friendsSince/index.tsx

Co-authored-by: V <vendicated@riseup.net>

* refactor: Put element into its own section

* feat: add section to user profile in DMs

* escape {

* fixes

* Add README

* Wrap in ErrorBoundary

---------

Co-authored-by: V <vendicated@riseup.net>
2024-03-11 15:31:36 +00:00
Haruka
1fbc4f7ce1
fix(ServerProfile): crop banner to prevent overflow (#2250) 2024-03-11 16:19:35 +01:00
Vendicated
34390e0365
Add workaround for guild role api changes on canary/ptb
fixes RoleColorEverywhere, ServerInfo, PermissionViewer, BetterRoleContext
2024-03-11 16:15:49 +01:00
Jack
497f0de9a1
chore(Decor): Change URL formula for cost savings (#2247) 2024-03-11 15:52:11 +01:00
Nuckyz
992533245b
RoleColorEverywhere: Wrap roleGroupColor in ErrorBoundary 2024-03-08 19:05:30 -03:00
Nuckyz
b0d37c981e
Bump to 1.7.1 2024-03-08 00:29:06 -03:00
Nuckyz
cf7830e747
ShowHiddenChannels: Fix patches 2024-03-08 00:24:23 -03:00
Nuckyz
10f33b3dec
Make more finds use filters.componentByCode 2024-03-08 00:24:21 -03:00
Amia
688ff255d2
fix(MutualGroupDMs): update regex (#2242) 2024-03-08 03:18:18 +00:00
Vendicated
2e90d4c03d
New plugin: BetterRoleContext ~ edit/copy colour shortcuts in profile 2024-03-07 20:23:07 +01:00
Nuckyz
1c1d82f9a8
VencordToolbox: don't subscribe to all settings
Also remove one indirection from useSettings
2024-03-07 13:06:08 -03:00
Nuckyz
102842d528
Close Ipc FS watchers if window is closed 2024-03-07 11:33:00 -03:00
Nuckyz
19799767ad
Fix trying to check for updates if origin doesn't have same branch 2024-03-07 10:27:50 -03:00
Sam
f70114238c
MemberCount: Add options to choose where the member count will be displayed (#2224) 2024-03-07 10:27:50 -03:00
AutumnVN
a59c14f9aa
CustomRPC: Change timestamp to milisecond (#2231) 2024-03-07 10:27:50 -03:00
Nuckyz
980206d315
Fix waitFor initial finds traces getting logged to the console even though they always fail 2024-03-07 10:27:50 -03:00
Kyuuhachi
42a9fa2d47
Refactor ContextMenuAPI (#2236) 2024-03-07 10:06:24 +00:00
Nuckyz
612fdf8952
FakeNitro: Fix trimming wrong content 2024-03-06 07:12:09 -03:00
dolfies
4f0c0a12dc
feat(plugin): ResurrectHome (#2232) 2024-03-05 22:38:49 +00:00
Nuckyz
23ff82fa62
FakeNitro: Remove extra space in modal 2024-03-03 17:49:21 +01:00
Nuckyz
553a48b6ce
FakeNitro: Fix hyperlink text setting for stickers 2024-03-03 17:48:50 +01:00
Nuckyz
806960f1c6
ClientTheme: do not use lodash on start method 2024-03-03 17:47:26 +01:00
Nuckyz
1a1156e1ed
Add more settings to IgnoreActivities (#2153) 2024-03-01 04:09:55 +00:00
[object Object]
9179f55bf2
fix Vencloud not working on UserScript (#2213)
Co-authored-by: V <vendicated@riseup.net>
2024-03-01 01:26:32 +01:00
Vendicated
3ebde1aae8
fix some minor bugs 2024-03-01 00:18:09 +01:00
Vendicated
da50c7a19b
MemberCount: Also add to server tooltip; refactor code 2024-02-28 20:25:08 +01:00
Nuckyz
7de54a294f
Fix NotificationVolume 2024-02-27 23:43:03 -03:00
Nuckyz
e0166ef1e6
Fix FakeNitro patch and message content patch error 2024-02-27 23:42:57 -03:00
Vendicated
8ccd731aee
bump to v1.7.0 2024-02-27 13:41:55 +01:00
Andrei Neacsu
1afa185f57
LastfmRichPresence: Add an option to hide the Last.fm logo (#2189)
Co-authored-by: V <vendicated@riseup.net>
2024-02-27 12:30:27 +00:00
Lualt
76de8c424e
feat(plugin) FakeNitro: Allow customising hyperlink text (#2192)
Co-authored-by: Vendicated <vendicated@riseup.net>
2024-02-27 13:27:37 +01:00
Nuckyz
ed5e1be7a4
Add permissions checks for FakeNitro actions (#2160)
Co-authored-by: Vendicated <vendicated@riseup.net>
2024-02-27 13:19:05 +01:00
WackyModer
27696ed62a
whoReacted: fix reaction count being off by one (#2209)
Co-authored-by: V <vendicated@riseup.net>
2024-02-27 11:31:51 +00:00
Vendicated
b9d0a1c563
SpotifyControls: fix seekbar grabber alignment 2024-02-27 12:01:15 +01:00
Av32000
5e7b4e9c92
SpotifyControls: export album cover as CSS variable for themes (#2197)
--vc-spotify-track-image
2024-02-27 10:27:34 +00:00
Nuckyz
9958f5a2ea
Fix ReviewDB 2024-02-27 05:04:54 -03:00
Sqaaakoi
414184ef25
ImageZoom: negate the border offsetting the lens (#2117)
Co-authored-by: Lewis Crichton <lewi@lewisakura.moe>
2024-02-25 23:51:09 +00:00
Vendicated
2d8715adf0
SuperReactionTweaks: only super react by default if user has nitro 2024-02-23 13:06:03 +01:00
Nuckyz
e3fd954512
Fix Decor patch 2024-02-22 21:31:15 -03:00
Manti
f922f0bc0d
fix reviewdb auth not working on userscript (#2194) 2024-02-20 18:13:25 +00:00
Vendicated
604f4c49af
VoiceMessages: Add warning if audio file is not OggOpus 2024-02-18 18:22:48 +01:00
Margot
c3030bbad0
MuteNewGuild -> NewGuildSettings; add 'show all channels' option (#2065)
Co-authored-by: MopigamesYT <mopigames@proton.me>
Co-authored-by: V <vendicated@riseup.net>
2024-02-18 17:42:26 +01:00
Syncx
7b96071643
fix ImageZoom patch (#2181) 2024-02-16 06:52:09 +00:00
Vendicated
a501da692f
MessageLinkEmbeds: fix group dm support, improve ui 2024-02-15 11:08:43 +01:00
Vendicated
bc0a55053d
MessageLinkEmbeds: fix erroring on some invalid message links 2024-02-15 10:12:33 +01:00
Vendicated
89367e3b2a
WebContextMenus: fix copying images
it broke because of the new url expiry parameters
2024-02-15 09:25:51 +01:00
Nuckyz
f1bdf385eb
Bump to 1.6.9 2024-02-14 15:25:10 -03:00
Nuckyz
93b2095d71
Fix FakeNitro hyperlinks not working sometimes
It is caused by emoji names with conflict with default emojis, but have a letter capitalized
2024-02-14 15:16:31 -03:00
Nuckyz
46ee193cd0
Fix MessageLogger edit Timestamp component 2024-02-14 15:07:51 -03:00
Nuckyz
48822bdc58
Attempt to fix CrashHandler odd issues 2024-02-14 15:00:29 -03:00
Vendicated
0c9d2a6a21
Fix plugins using the Timestamp component 2024-02-13 09:05:19 +01:00
Vendicated
8b6a40311b
Bump to v1.6.8 2024-02-13 09:04:28 +01:00
Nuckyz
38beb93e5f
Fix CrashHandler failing to recover and showing gray screen instead 2024-02-10 13:42:31 -03:00
Nuckyz
cc0d9a90bc
Fix UserVoiceShow patch 2024-02-09 21:27:34 -03:00
Nuckyz
d3bbd2c02e
FakeNitro: option to use hyperlinks or not 2024-02-09 21:00:15 -03:00
Nuckyz
558c2a0b2e
Make PermissionsViewer and ShowHiddenChannels default dropdown change when clicked 2024-02-09 19:47:43 -03:00
Nuckyz
237f080471
DisableDMCallIdle -> DisableCallIdle; add more functionality 2024-02-09 19:33:15 -03:00
sappho
b2c047390e
FakeNitro: Send fake links using Discord hyperlink markdown feature (#2158) 2024-02-09 19:33:14 -03:00
Klen_list
f1f0da4a9d
fixYoutubeEmbeds: fix when youtube decides to use http without s (#2155)
Co-authored-by: V <vendicated@riseup.net>
2024-02-08 18:55:48 +00:00
Nuckyz
935d0a0a03
Fix broken patches and finds 2024-02-08 15:33:49 -03:00
Nuckyz
a108448255
Improve DisableDMCallIdle 2024-02-07 20:39:02 -03:00
Nuckyz
3325a8de40
Fix FakeNitro patch 2024-02-06 21:30:07 -03:00
Vendicated
377def4a33
Fix crash when toggling chat button plugins without restart 2024-02-06 18:12:09 +01:00
Vendicated
de570a4800
inject: suppress ugly node error 2024-02-06 17:59:44 +01:00
Vendicated
685b6f2fa7
Improve PreviewMessage icon; make button padding/margin more consistent
Co-authored-by: Andrew Grant <andrew.grant@mail.rit.edu>
2024-02-06 17:52:05 +01:00
Nuckyz
7592b5c172
Fix devtools context menus on canary 2024-02-06 13:31:18 -03:00
Kuba (kb)
8b3189f1ed
fixYoutubeEmbeds - Support locales other than english (#2128)
Co-authored-by: V <vendicated@riseup.net>
2024-02-06 16:18:49 +00:00
ssranked
115da04724
clearURLs: add music.youtube.com (#2118)
Co-authored-by: ssranked <ssrankedghoul@gmail.com>
2024-02-06 16:13:43 +00:00
sunnie
ec53b0230f
readAllNotificationsButton: also mark voice channels as read (#2140) 2024-02-06 16:12:26 +00:00
Vendicated
64fa2f8652
ChatButtonApi: do not add buttons if you can't send messages 2024-02-06 17:06:26 +01:00
Vendicated
e58aa5dbab
Translate: Add auto translate enable alert
somehow people accidently enable it then get confused why vencord has "auto correct". this should hopefully solve the issue
2024-02-06 17:04:01 +01:00
Vendicated
2c198e547c
Fix PreviewMessage icon being offcentre 2024-02-06 16:50:21 +01:00
Vendicated
bf977e0047
Add chat bar button api ~ fixes buttons for russian users 2024-02-06 16:29:47 +01:00
EdVraz
8938f4a3cf
fix moreUserTags (#2146) 2024-02-03 21:50:51 -03:00
Vendicated
cc885b5bb3
remove lumap 2024-02-03 02:11:59 +01:00
V
620c127b58
[skip ci] fix pnpm inject 2024-01-25 07:22:34 +01:00
EdVraz
4bb0db5066
fix anonymiseFileNames (#2125) 2024-01-22 00:21:10 +00:00
Manti
e707538b73
[ReviewDB] update for new api changes; some fixes (#2120)
Co-authored-by: Vendicated <vendicated@riseup.net>
2024-01-22 00:18:48 +00:00
~coolelectronics
1670733458
feat(plugin): FixYoutubeEmbeds - fix UMG blocked embeds (#2116)
Co-authored-by: V <vendicated@riseup.net>
2024-01-19 01:07:35 +00:00
Vendicated
988435714e
Add back transparency option 2024-01-19 01:08:25 +01:00
Vendicated
74300e0a69
WebContextMenus: only force png on copy image, not save image 2024-01-18 00:58:40 +01:00
Vendicated
3d64f3da41
WebContextMenus: fix copying images 2024-01-18 00:54:52 +01:00
Vendicated
8a168bd185
bump to v1.6.7 2024-01-16 04:12:15 +01:00
Bloofield
e8e09c17e9
ClearURLs: Add igsh (#2103) 2024-01-16 04:07:05 +01:00
AutumnVN
11d3165009
roleColorEverywhere: thread role color (again) (#2098)
Co-authored-by: V <vendicated@riseup.net>
2024-01-16 04:01:59 +01:00
Sam
60bc823eab
new plugin: BetterGifPicker (#2108)
Co-authored-by: V <vendicated@riseup.net>
2024-01-16 03:00:41 +00:00
CodeF53
f14001b531
ClientTheme light mode support, shortcut buttons (#2010)
Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
Co-authored-by: V <vendicated@riseup.net>
2024-01-16 02:53:27 +00:00
rini
1a982ae9aa
feat(anonymisefilenames): add icon to toggle anonymising (#2087)
Co-authored-by: V <vendicated@riseup.net>
Co-authored-by: fawn <fawn@rinici.de>
2024-01-16 02:51:12 +00:00
Vendicated
a171b35e97
ReviewDB fixes 2024-01-15 19:58:33 +01:00
Manti
8bd54173db
Bring back ReviewDB (#2097)
Changes from old version:
- You can now delete reviews on your own profile
- You can now block up to 50 users. This will prevent them from leaving reviews on your profile

Co-authored-by: V <vendicated@riseup.net>
2024-01-14 22:46:24 +01:00
Vendicated
2ab1c50c73
QuickCss: reopen existing window instead of new one 2024-01-13 19:27:41 +01:00
Vendicated
69a4d2734e
fix(git updater): correctly persist isDev switch 2024-01-13 19:08:11 +01:00
Vendicated
cb7045c00b
WebContextMenus: use vesktop native clipboard - fixes some permission issues 2024-01-13 19:05:01 +01:00
Vendicated
8c89002867
forgor not everyone uses enlgihs 2024-01-09 17:44:18 +01:00
Vendicated
ba6d23a31f
fix adding View Raw to undesired channel context menus 2024-01-09 17:39:38 +01:00
Grzesiek11
ba2695b499
Add FixCodeblockGap plugin (#2064) 2024-01-06 02:05:23 +00:00
Vendicated
d73790efb3
bump to v1.6.6 2024-01-06 01:22:04 +01:00
effct • Lia Aaron Thoma
0d6bb35075
TextReplace: allow replacing with nothing (#1933) 2024-01-06 00:02:09 +00:00
Hari Rana
d5c58ab2b3
updater: Add top and bottom margins between commits (#2042)
Co-authored-by: V <vendicated@riseup.net>
2024-01-05 23:55:14 +00:00
Grzesiek11
be9ec3b7ac
SendTimestamps: add setting to disable message replacement (#2076) 2024-01-05 23:23:09 +00:00
Moxie
6530526fb2
Updater: Fix grammar (1 Updates => 1 Update) (#2084)
Co-authored-by: V <vendicated@riseup.net>
2024-01-06 00:10:16 +01:00
Vendicated
13961a4ba5
ReverseImageSearch: add support for image modal 2024-01-05 23:52:22 +01:00
Vendicated
4d198e46bc
fix wrongly patching 'Events' context menu 2024-01-05 23:31:34 +01:00
Vendicated
3eada99ad6
fix(ToolBox): don't add entries of disabled plugins 2024-01-05 22:15:54 +01:00
sunnie
88fc15752d
webContextMenus: add Show My Camera item (#2086) 2024-01-05 22:12:13 +01:00
Vendicated
9e810e5511
fix cobu sync 2024-01-05 22:07:00 +01:00
Nuckyz
4a1c85c8ad
Decor: only search for DecorationModalStyles once 2024-01-03 09:58:09 -03:00
nexpid
1eb2510353
feat(Decor): Enforce guidelines more (#2035) 2024-01-03 09:49:03 -03:00
Jack
a963a19bdc
fix(Decor): Fix AvatarDecorationModalPreview find (#2089) 2024-01-03 12:37:56 +00:00
Lewis Crichton
d0dfdbbd5f
fix: Vencord_cloudSecret check (#2077)
finally got around to fixing it - `null` is never a valid return value,
it's `undefined` 🤦
2024-01-03 09:31:57 -03:00
V
7e395fc696
Update codeburger mirror 2023-12-31 05:02:05 +01:00
jd
30bc979c8d
feat(Urban Dictionary): Chooses top rated definition & more results. (#2080) 2023-12-31 00:06:19 +00:00
Nuckyz
5dee2e8549
Future proof reporter to work in latest canary 2023-12-21 21:46:34 -03:00
Nuckyz
109d842e29
Fix NSFWGateBypass possibly Vencord 2023-12-21 21:46:22 -03:00
Vendicated
686f2d925f
fix canary crashing 2023-12-21 23:41:12 +01:00
Nuckyz
fdf3480b27
Fix DeArrow patch 2023-12-20 01:34:08 -03:00
TheKodeToad
2e04b3d1ef
Implement Twitter easter egg for ShowConnections (#2062) 2023-12-17 18:12:42 -03:00
Nuckyz
9950bf00b2
GameActivityToggle: option to use old icon 2023-12-17 18:06:16 -03:00
Nuckyz
467c5e0c4c
Delete FixImagesQuality
Discord fixed their issue with images getting converted to webp losing quality. In the future this plugin can be re-purposed to keep images format as the original, but that requires more than just removing part of the Discord code, and a bit of study to make sure it does not cause issues.
2023-12-17 17:40:59 -03:00
Nuckyz
2cd82944e3
Move commons from discord utils; Make ThemesTab use invite modal util 2023-12-13 22:01:07 -03:00
Nuckyz
2f1dc2c704
reporter: fix icon 2023-12-13 21:46:51 -03:00
Nuckyz
a5442d87d5
Fix reporter and AlwaysAnimate patch 2023-12-13 21:41:09 -03:00
V
a8b0ce6f03
fix(notrack): murder sentry 2023-12-14 01:29:57 +01:00
Andrew Grant
b32959126e
TypingIndicator: setting to disable for current channel (#2043) 2023-12-13 19:54:09 -03:00
zImPatrick
2cf52d0775
AlwaysAnimate: Add guild banner (#2036) 2023-12-13 20:41:50 +00:00
sappho
40b3ec57ce
FakeNitro: fix non apng gif stickers being sent as images (#2050) 2023-12-13 06:37:31 -03:00
ruukulada
817cb9b60b
GameActivityToggle: Icon cleanup (#2041) 2023-12-12 23:40:13 -03:00
Nuckyz
c86de3299e
fixAll.eslint: true -> "explicit" 2023-12-12 23:29:22 -03:00
Nuckyz
1df0b571af
Fix broken patches 2023-12-12 22:57:32 -03:00
AutumnVN
6d911790e9
oneko: allow oneko in reduced motion (#2018) 2023-12-10 02:05:40 +01:00
Nuckyz
c9f7cf7540
ci: test all branches 2023-12-09 18:34:58 -03:00
Nuckyz
a9568bc055
reporter: fix bad logic 2023-12-09 17:57:25 -03:00
Nuckyz
539e538d87
commandHelpers: use MessageActions import 2023-12-09 17:57:25 -03:00
AutumnVN
799e6e7292
platformIndicators: fix (#2038) 2023-12-09 21:55:13 +01:00
maisy
510bfb8fa3
ReactErrorDecoder: fix using wrong react version's error map (#2040)
Co-authored-by: V <vendicated@riseup.net>
2023-12-09 20:36:58 +00:00
AutumnVN
534ca1e28d
fix: createBotMessage (#2033) 2023-12-07 02:44:14 +01:00
Vendicated
d629281e72
bump to v1.6.5 2023-12-07 00:35:05 +01:00
Damien Erambert
34cbb22efe
feat: add dropdown to choose vibrancy value on macOS (#1941)
Co-authored-by: V <vendicated@riseup.net>
2023-12-07 00:30:41 +01:00
Ajay Ramachandran
6ee50d30f6
fix(dearrow): remove > from DeArrow titles (#1999) 2023-12-07 00:26:08 +01:00
Han Seung Min - 한승민
fd9c675942
fix: patch helper overflow (#2007) 2023-12-07 00:25:13 +01:00
AutumnVN
920252956f
shikiCodeBlocks: support file preview (#1977) 2023-12-06 22:42:40 +00:00
Nickyux
e4942397dc
MessageClickActions: Ignore Ephemeral & Deleted Messages (#1972)
Co-authored-by: V <vendicated@riseup.net>
2023-12-06 22:18:03 +00:00
philipbry
9faa1331da
new plugin: notificationVolume (#1992)
Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
Co-authored-by: V <vendicated@riseup.net>
2023-12-06 22:15:34 +00:00
fres621
613b2dc5f6
Fix QuickMention not working in DMs (#2028)
Co-authored-by: V <vendicated@riseup.net>
2023-12-06 22:54:23 +01:00
nya
9a89f7b3b2
feat(plugin): XSOverlay (#1901)
Co-authored-by: V <vendicated@riseup.net>
2023-12-06 22:31:22 +01:00
AutumnVN
c0b6d8f1c4
devCompanion: add findComponentByCode (#2026) 2023-12-06 22:27:06 +01:00
Carter
3453d0c97c
feat(clearUrls): moar twitter rules (#2029) 2023-12-06 22:25:53 +01:00
Syncx
cf7028331c
Native Folder Support (#2031) 2023-12-06 22:25:29 +01:00
Nuckyz
08036f7af2
convert non lazy finds to test with reporter 2023-12-06 01:37:42 -03:00
Nuckyz
9dd00fb766
Fix SuperReactionTweaks patch 2023-12-01 23:06:18 -03:00
Nuckyz
80016180b6
FixImagesQuality: no longer make gifs play when autoplay is off 2023-12-01 16:39:15 -03:00
megumin
3e7d946296
fix(SpotifyControls): Requests double-sending when using Spotify Connect (#2023) 2023-11-30 16:32:48 -03:00
V
fccdd3dc08
migrate to new badge api
we used to store badges on the discord cdn.
since discord is now making
it harder to use their cdn for such purposes (due to expiring links), we
are forced to stop using it
thus, badges are now stored on our server, accessible via
https://badges.vencord.dev. The full list of badges is now at https://badges.vencord.dev/badges.json
2023-11-30 17:28:53 +01:00
Nuckyz
8e1546be00
Include ignored Discord errors in summary 2023-11-30 02:38:12 -03:00
Nuckyz
66dbe7ef07
Fix reporter testing for extractAndLoadChunks 2023-11-30 02:26:18 -03:00
Jack
b47a5f569e
feat: Add Decor plugin (#910) 2023-11-30 02:10:50 -03:00
Nuckyz
8ef1882d43
use findBulk on CrashHandler and cleaups 2023-11-30 00:43:23 -03:00
Nuckyz
9945219de7
openInviteModal utility
Co-authored-by: AutumnVN <autumnvnchino@gmail.com>
2023-11-29 23:15:19 -03:00
Nuckyz
091d29bf5e
CrashHandler: attempt to prevent more crashes 2023-11-29 16:14:05 -03:00
Nuckyz
9b6308a835
Fix a console shortcut and suppressExperimentalWarnings on more scripts 2023-11-28 22:12:00 -03:00
Nuckyz
597a74ff6c
ClientTheme: make color picker finder more specific 2023-11-28 17:05:11 -03:00
V
f814eeb74c
VoiceMessages: fix preview being blank 2023-11-28 16:33:02 -03:00
Nuckyz
1619ee404a
Utility function for loading Discord chunks (#2017) 2023-11-28 16:33:02 -03:00
Nuckyz
1b179f3c6d
Simplify some components finds; Make undo of patch groups more clear 2023-11-28 16:33:00 -03:00
Korbo
6573c4757c
fix: strikethrough in SilentMessageToggle's disabled SVG (#2004) 2023-11-28 18:32:29 +00:00
V
ec16fd8741
fix ci 2023-11-25 02:55:59 +01:00
V
6bbf562ab6
bump to v1.6.4 2023-11-25 02:51:58 +01:00
V
604cf00211
reporter: fix markdown output 2023-11-25 02:51:19 +01:00
V
7c3b247d84
fix WebContextMenus 2023-11-25 02:43:29 +01:00
V
68fca78541
reporter: test dev instead of main 2023-11-25 02:02:50 +01:00
V
598ffe6368
reporter: remove sleeps 2023-11-25 01:52:11 +01:00
V
534565db25
Add webpack find testing (#2016)
Co-authored-by: V <vendicated@riseup.net>
Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
2023-11-25 01:32:21 +01:00
Nuckyz
3e8e106be7
Fix broken patches 2023-11-24 16:49:19 -03:00
Nuckyz
fdddfdb05b
feat(plugins): FixImagesQuality 2023-11-24 16:32:30 -03:00
cat
e14fba28a5
ClearURLS for x.com links (#2005) 2023-11-23 14:31:25 -03:00
V
81fb7c6322
add back code that got lost 2023-11-23 06:45:01 +01:00
V
f39f16d34b
fix circular import bricking browser version 2023-11-23 06:43:22 +01:00
Nuckyz
0f74817e25
Fix broken SHC find 2023-11-23 02:22:04 -03:00
V
4832a9433f
fix broken webpack finds 2023-11-23 06:18:44 +01:00
V
6f05612e34
Remove obsolete webpack hacks 2023-11-23 03:41:09 +01:00
V
9efc0ff579
Remove obsolete nested webpack search 2023-11-23 03:21:58 +01:00
V
63451bad25
Remove obsolete mapMangledModule ~ modules are no longer mangled 2023-11-23 03:11:17 +01:00
V
6869705673
beef up ConsoleShortcuts 2023-11-23 02:44:04 +01:00
V
a2560ede1c
fix showConnections & better webpack errors 2023-11-23 02:20:24 +01:00
Jack
93a95b6d56
feat(patcher): Grouped replacements (#2009)
Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
Co-authored-by: V <vendicated@riseup.net>
2023-11-22 07:23:21 +01:00
V
7b24c8ac69
move new webpack methods to more appropriate file 2023-11-22 07:04:17 +01:00
V
b21b6d7e5d
Make it possible to destructure lazy webpack finds 2023-11-22 02:54:46 -03:00
Nuckyz
ffe6512693
Improve component finding api and migrate plugins to use them 2023-11-22 02:49:08 -03:00
V
371b5b0be8
allow plugins to specify how soon their start() method is called 2023-11-22 06:14:16 +01:00
V
074ebae334
ClientTheme fixes 2023-11-22 01:57:00 +01:00
CodeF53
6face7f8ef
feat(plugin): ClientTheme (#807) 2023-11-21 16:30:29 -03:00
Nuckyz
2f1e86f333
TypingIndicator: support threads 2023-11-21 00:51:12 -03:00
Nuckyz
18d63af241
PermViewer: Use role pill border conditionally 2023-11-20 23:26:07 -03:00
Nuckyz
6ab4cf0a0b
Fix broken patches due to unread changes 2023-11-20 23:16:34 -03:00
Nuckyz
9980c0d04f
IgnoreActivities: fix and improvements 2023-11-18 22:53:50 -03:00
V
4a5371a746
Update README.md 2023-11-16 05:40:50 +01:00
adryd
77749ed5e1
oneko: update script version (#1994) 2023-11-16 01:26:35 +01:00
Justice Almanzar
45aa9fbb6d
Fix hljs find (#1983) 2023-11-15 15:30:31 -03:00
megumin
4a2657f928
fix(channeltags): message author should be clyde (#644) (#1986) 2023-11-15 15:15:43 -03:00
AutumnVN
6578eb487e
MessageLogger: fix attachment ignore (#1989) 2023-11-15 15:13:19 -03:00
Thoth
c080a0eaac
shikiCodeblocks: transform lang to lower case to avoid failing detection (#1990) 2023-11-15 15:09:26 -03:00
Jack
3ea6a96715
chore: Fix PinDMs patch (#1981) 2023-11-15 15:01:50 -03:00
Nuckyz
af614465a4
Remove obsolete experiments patch 2023-11-15 14:54:48 -03:00
Nuckyz
7b248ee309
Fix SHC patches 2023-11-15 14:50:52 -03:00
Ajay Ramachandran
fd25b5f296
fix(dearrow): support DeArrow thumbnail submissions at 0 seconds (#1979) 2023-11-15 14:30:48 -03:00
megumin
77d08c5c28
feat: Add Environment variable to disable updater auto-patching (#1971) 2023-11-15 14:30:48 -03:00
V
ea11f2244f
README: Add sponsors 2023-11-13 01:37:15 +01:00
V
96126fa39f
remove pipebomb from github actions (#1968) 2023-11-09 07:15:49 +01:00
AM
9bd82943e3
[Plugin] Super Reaction Tweaks (#1958)
Co-authored-by: V <vendicated@riseup.net>
Co-authored-by: Jack Matthews <jm5112356@gmail.com>
2023-11-09 04:42:35 +01:00
V
5edc94062c
make packageManager key less specific 2023-11-09 02:42:34 +01:00
AutumnVN
394d2060eb
searchReply: fix (#1961) 2023-11-09 02:34:40 +01:00
V
119b628f33
feat: simple plugin natives (#1965) 2023-11-09 02:32:34 +01:00
zImPatrick
32f2043193
Fix FakeNitro sticker bypass (#1964) 2023-11-07 22:24:17 -03:00
Marvin Witt
04d2dd26c4
fix(dearrow): don't replace thumbnail if only original available (#1959) 2023-11-07 22:24:08 -03:00
Vendicated
86e94343cc
bump to v1.6.3 2023-11-05 02:07:33 +01:00
Vendicated
dd44ac1ad2
OpenInApp: Support podcasts 2023-11-04 19:08:44 +01:00
Vendicated
370b3d366d
OpenInApp: Fix links in messages 2023-11-04 18:59:16 +01:00
Vendicated
a67c7f841d
Fix ViewIcons correctly 2023-11-04 18:54:29 +01:00
Vendicated
2c9793202d
Revert "Fix ViewIcons"
This reverts commit 098da8c3fd.
2023-11-04 18:54:02 +01:00
AutumnVN
a257926609
customRpc: fix discord attachment link (#1949) 2023-11-04 18:45:17 +01:00
AutumnVN
77659be4f0
fakeNitro: disallow emoji in add reaction (#1954) 2023-11-04 18:44:53 +01:00
AutumnVN
37b9a62460
favGifSearch: fix search bar (#1955) 2023-11-04 18:44:29 +01:00
Lewis Crichton
7f73e13364
docs: point people to advisories for security bugs (#1957) 2023-11-04 18:41:38 +01:00
Vendicated
fcf2bdda70
fix TypingTweaks 2023-11-03 02:03:58 +01:00
AutumnVN
fa9da2d693
noMosaic: play video inline + optional media layout type (#1946) 2023-11-03 01:57:39 +01:00
AutumnVN
44b21394b3
gifPaste: fix unable to use gif picker in profile customization (#1947) 2023-11-03 01:56:31 +01:00
Nuckyz
27fffc8bc3
Fix ShowMeYourName 2023-11-01 23:28:52 -03:00
Nuckyz
098da8c3fd
Fix ViewIcons 2023-11-01 23:26:13 -03:00
Nuckyz
9cf88d4232
Fix MessageDecorationsAPI 2023-11-01 22:46:06 -03:00
Vendicated
dd61b0c999
bump to v1.6.2 2023-11-01 02:25:13 +01:00
Haruka
5dc0d06be1
EmoteCloner: make the error toasts useful (#1938)
Co-authored-by: Vendicated <vendicated@riseup.net>
2023-11-01 02:23:45 +01:00
AutumnVN
9de6c2d4ff
previewMessage: fix button (#1919) 2023-11-01 02:19:26 +01:00
AutumnVN
e37f62ac0a
imageZoom: dont close carousel modal on image click (#1926)
Co-authored-by: Vendicated <vendicated@riseup.net>
2023-11-01 02:19:02 +01:00
AutumnVN
56a9d79f85
PiP: fix issues / styles (#1927) 2023-11-01 02:14:32 +01:00
Nuckyz
9d78233afa
Fix displaying BetterFolders sidebar when watching streams in fullscreen 2023-11-01 02:10:58 +01:00
Vendicated
9af2ec65ae
OnePingPerDM: fix server pings 2023-11-01 02:09:43 +01:00
Vendicated
584885acf5
[skip ci] Revert "add react linting"
doesnt work properly :(

This reverts commit 18fdc33ee7.
2023-10-31 23:56:13 +01:00
Vendicated
18fdc33ee7
[skip ci] add react linting 2023-10-31 23:50:55 +01:00
V
522fdcd15d
WebKeyBinds: Fix & make available on ArmCord 2023-10-28 23:51:04 +02:00
Nuckyz
af135b9245
Fix AlwaysAnimate 2023-10-28 17:43:27 -03:00
Nuckyz
4b958d17fd
Fix BetterFolders freeze and add new options (#1923) 2023-10-28 20:18:00 +00:00
Nuckyz
bfb48b4faf
BetterFolders: Option to choose whether to keep guild icons (#1918) 2023-10-28 04:00:17 +00:00
Hugo C
9dd8e72245
fix: PiP replacing video download button (#1910) 2023-10-28 02:22:04 +02:00
AutumnVN
aae790f1c1
vencordToolbox: correct hover color + oneko (#1913) 2023-10-28 02:21:35 +02:00
AutumnVN
7f17e70697
noSystemBadge: fix (#1914) 2023-10-28 02:20:29 +02:00
Vendicated
b3311c6f12
BetterGifAltText: Fix displaying undefined 2023-10-28 02:19:43 +02:00
Nuckyz
bc09225258
Add missing patches predicates to BetterFolders 2023-10-27 20:10:44 -03:00
Nuckyz
9ce923d4d7
Fix BetterFolders 2023-10-27 19:56:11 -03:00
Nuckyz
7845af0802
Remove hacks to support no longer active versions of Discord 2023-10-27 19:55:39 -03:00
Nuckyz
89672882b9
PermViewer: Fix incorrectly displaying some role names as Unknown Role 2023-10-27 14:33:18 -03:00
Nuckyz
e05c630a54
SHC: Make Chat Input Bar channel list include hidden channels 2023-10-27 14:29:25 -03:00
Nuckyz
38834ef7ac
Fix git updater 2023-10-27 13:03:52 -03:00
Luna
98d49af728
Fix git updater for other branches (#1915) 2023-10-27 12:09:39 -03:00
Susheel Thapa
0afe319141
fix typo in multiple files (#1911) 2023-10-27 12:09:38 -03:00
Vendicated
a9e67e2955
Bump to v1.6.1 2023-10-27 03:53:58 +02:00
Nuckyz
1676956f61
Fix hidden channels triggering the unread box 2023-10-26 20:59:48 -03:00
Nuckyz
8692109bc5
Add comments to some SHC patches 2023-10-26 18:13:25 -03:00
Nuckyz
0847f205b8
Fix some hidden channels not collapsing 2023-10-26 18:11:00 -03:00
AutumnVN
2f94e167c4
noProfileThemes: fix usrbg compatibility (#1905) 2023-10-26 22:52:48 +02:00
Vendicated
589c070773
fix not removing vencord 'chunks' from webpack 2023-10-26 22:51:07 +02:00
Nuckyz
8567ff6239
Little bit of SHC cleanup 2023-10-26 16:51:37 -03:00
Vendicated
e4701769a5
Fix entry webpack modules not being patched 2023-10-26 21:21:21 +02:00
Vendicated
25f101602d
fix modules being patched multiple times 2023-10-26 21:03:05 +02:00
Nuckyz
85bfa1e719
Fix duplicated WebContextMenus find 2023-10-26 15:36:05 -03:00
Nuckyz
b48998d485
More accurate ShowAllMessageButtons patch 2023-10-26 15:25:29 -03:00
Nuckyz
6d605050e1
Fix BetterNoteBox 2023-10-26 15:07:44 -03:00
TheKodeToad
07c4a097e0
Fix EmoteCloner (#1907) 2023-10-26 13:49:18 -03:00
TheKodeToad
c1de41436a
Fix plugins using promptToUpload (#1908) 2023-10-26 13:49:06 -03:00
Nuckyz
64c6f5740f
Fix FakeNitro completely (#1903) 2023-10-26 03:19:26 +00:00
AutumnVN
03523446c1
silentTyping: fix showIcon toggle (#1898) 2023-10-26 00:50:33 +00:00
Vendicated
25dc25c707
Fix VoiceMessages 2023-10-26 02:28:17 +02:00
Hugo C
8ac8048845
fix: ImageZoom + PiP (#1894)
Co-authored-by: V <vendicated@riseup.net>
2023-10-26 02:17:31 +02:00
Vendicated
ffe6bb1c5d
Bump to v1.6.0 2023-10-26 01:32:15 +02:00
Vendicated
74faaa216f
Fix PlatformIndicators colorMobileIndicator 2023-10-26 01:29:52 +02:00
Luna
a6b8b59d5c
fix: shikicodeblocks, betterroledot (#1895) 2023-10-26 01:03:11 +02:00
redstonekasi
9eaeb24196
fix: RoleColorEverywhere (#1884)
Co-authored-by: Vendicated <vendicated@riseup.net>
2023-10-26 00:56:39 +02:00
Nuckyz
6b28e5ad85
Partially fix FakeNitro 2023-10-25 19:38:35 -03:00
Vendicated
d852393cfb
fix UserVoiceShow 2023-10-26 00:36:28 +02:00
IThundxr
0c12500c0a
Fix: noUnblockToJump (#1893) 2023-10-26 00:29:26 +02:00
Vendicated
1502024440
Fix iLoveSpam 2023-10-26 00:29:03 +02:00
Vendicated
45fa4f89c6
Fix NoScreensharePreview 2023-10-26 00:20:56 +02:00
Vendicated
96dff84ed8
Fix PlatformIndicators 2023-10-26 00:03:51 +02:00
Vendicated
c1b8739104
Fix RevealAllSpoilers 2023-10-26 00:01:49 +02:00
Vendicated
2183d2d29d
fix TimeBarAllActivities 2023-10-25 23:59:38 +02:00
Vendicated
722dcb033e
Fix RelationShipNotifier 2023-10-25 23:50:33 +02:00
Ben Richeson
53cd14844f
Fix MessageLogger (#1888)
Co-authored-by: Vendicated <vendicated@riseup.net>
2023-10-25 23:46:51 +02:00
nora
38daf6ec2b
ImageZoom: fix typo (#1832) 2023-10-25 23:37:07 +02:00
Amia
635b80c58b
fix: NoPendingCount (#1886) 2023-10-25 23:26:50 +02:00
Jack
ec9e111047
fix: (rewrite) SecretRingToneEnabler (#1887) 2023-10-25 23:25:39 +02:00
Jack
d54f8b5e8e
fix: BANger (#1885) 2023-10-25 23:25:02 +02:00
Vendicated
09a922a01c
Fix MuteNewGuild 2023-10-25 23:20:04 +02:00
Nuckyz
23963f40c2
Fix IgnoreActivities 2023-10-25 18:12:28 -03:00
Vendicated
a41abfef31
Fix MemberCount 2023-10-25 23:06:30 +02:00
Vendicated
ddee3e1264
Fix VencordToolbox 2023-10-25 23:00:11 +02:00
Aubrey/オーブリー
6c4afa52a3
Fix titlebar duplication with native Windows titlebar (#1890)
Co-authored-by: V <vendicated@riseup.net>
2023-10-25 22:49:41 +02:00
Vendicated
ce6081c39b
Merge branch 'main' into dev 2023-10-25 22:49:09 +02:00
Nuckyz
123853e848
Fix ShowHiddenChannels 2023-10-25 17:25:44 -03:00
Vendicated
0c6445b66b
fix reporter 2023-10-25 21:06:18 +02:00
Vendicated
7094345516
fix lintttttttttttttttttt :3 2023-10-25 21:01:20 +02:00
Vendicated
148a32096c
Fix PronounDB in profile 2023-10-25 20:51:37 +02:00
TheKodeToad
ab1b002ed1
TypingTweaks: fix (#1883) 2023-10-25 20:43:48 +02:00
rini
c7a20769f9
fix things using lodash (#1882) 2023-10-25 20:29:32 +02:00
Amia
9c13befcb6
fix: ServerProfile (#1881) 2023-10-25 20:24:31 +02:00
Vendicated
3fdd0edf14
Fix InvisibleChat 2023-10-25 20:24:17 +02:00
Vendicated
2169090ce5
Fix SpotifyCrack 2023-10-25 20:20:46 +02:00
redstonekasi
5e13de72c2
fix: BlurNSFW (#1880) 2023-10-25 20:16:57 +02:00
Vendicated
3a7c27253b
Fix PermissionFreeWill 2023-10-25 20:14:39 +02:00
Vendicated
465a87f66b
Fix ColorSighted 2023-10-25 20:07:45 +02:00
Amia
13c59f47cb
fix: MutualGroupDMs (#1879) 2023-10-25 20:01:25 +02:00
Vendicated
0d7157dd20
Fix BetterNoteBox 2023-10-25 19:59:20 +02:00
Vendicated
88c6e2a0e9
Fix PermissionViewer 2023-10-25 19:54:13 +02:00
Vendicated
535d510d3b
Fix LoadingQuotes 2023-10-25 19:47:29 +02:00
Vendicated
cbc23b1bdd
Fix BetterGifAltText 2023-10-25 19:41:18 +02:00
Vendicated
aa2a57b733
Fix Dearrow 2023-10-25 19:33:39 +02:00
Vendicated
c3ccbbfa99
Fix SpotifyControls 2023-10-25 19:28:07 +02:00
Vendicated
685f44d40f
Fix OpenInApp 2023-10-25 19:22:57 +02:00
Vendicated
8f0009778a
Fix ViewIcons 2023-10-25 19:09:59 +02:00
rini
f385dc380e
fix whoreacted, betteruploadbutton (#1877) 2023-10-25 19:09:37 +02:00
redstonekasi
bb900785ed
fix: ShowAllMessageButtons (#1876) 2023-10-25 18:52:21 +02:00
redstonekasi
61fac0a8f1
fix: NoPendingCount (#1871)
Co-authored-by: V <vendicated@riseup.net>
2023-10-25 18:46:32 +02:00
Jack
1a607639cc
fix: greetStickerPicker (#1874) 2023-10-25 18:43:28 +02:00
Vendicated
c90440f031
Fix Settings Proto 2023-10-25 18:42:31 +02:00
Vendicated
baf952512c
Fix InvisChat, PreviewMsg, SendTimestamps, SilentMsg, SilentType, Translate 2023-10-25 18:35:03 +02:00
rini
fbc5038306
fix: RPC plugins (#1873) 2023-10-25 18:20:32 +02:00
Vendicated
ddc39fe84d
Fix SettingStores, GameActivityToggle 2023-10-25 18:15:18 +02:00
redstonekasi
4f8c75372c
fix: NoBlockedMessages (#1870) 2023-10-25 18:09:04 +02:00
Jack Matthews
024a77c577 fix: typingIndicator 2023-10-25 18:07:41 +02:00
Vendicated
1130521e4b
Fix WebContextMenus 2023-10-25 18:07:12 +02:00
redstonekasi
3bd657611c fix: StartupTimings (#1869) 2023-10-25 17:38:55 +02:00
Syncx
b659d4e9c1 fix: FavoriteEmojiFirst (#1844) 2023-10-25 17:38:55 +02:00
rini
9c60b38acc Fix PinDMs, SMYN, SilentTyping, ValidUser, PlatformIndicators (#1865) 2023-10-25 17:38:55 +02:00
sunnie
c5dd50ad8f fix messageLinkEmbeds, moreUserTags (#1859) 2023-10-25 17:38:55 +02:00
redstonekasi
131e91a37c fix: AlwaysTrust (#1868) 2023-10-25 17:38:55 +02:00
Nico
06b4dffa62 forceOwnerCrown: fix (#1858) 2023-10-25 17:38:55 +02:00
Syncx
3917193e8f fix: ImageZoom (#1864) 2023-10-25 17:38:55 +02:00
redstonekasi
8d1561aed4 fix: NoticesAPI (#1863) 2023-10-25 17:38:55 +02:00
Dea
cf3c28e1ff fix: onePingPerDM (#1867) 2023-10-25 17:38:55 +02:00
Vendicated
af1aa39647 Delete RNNoise - Krisp is now on web, so this is obsolete 2023-10-25 17:38:55 +02:00
megumin
7de1b5dcb6 fix: sortFriendRequests patches (#1848) 2023-10-25 17:38:55 +02:00
megumin
cd06980016 fix: pronoundb profile popout (#1860) 2023-10-25 17:38:55 +02:00
Nico
e69236c5f8 fix(vcDoubleClick): update for new discord build (#1862) 2023-10-25 17:38:55 +02:00
AutumnVN
2478ffb695 fix userutils (#1861) 2023-10-25 17:38:55 +02:00
Vendicated
788d22f9e9 MessageDecorationsAPI: fix 2023-10-25 17:38:55 +02:00
Vendicated
b69ac1cdad Fix PlatformIndicators 2023-10-25 17:38:55 +02:00
redstonekasi
892a79b2a7 fix: CommandsAPI 2023-10-25 17:38:55 +02:00
Vendicated
9895540943 MemberListDecoratorAPI: Fix 2023-10-25 17:38:55 +02:00
Vendicated
7e0fc1d0ea ServerListAPI: fix 2023-10-25 17:38:55 +02:00
Vendicated
bb771153e3 MessageEvents: Fix 2023-10-25 17:38:55 +02:00
TheKodeToad
65d39dcf21 ShowConnections, NoProfileThemes: Fix (#1854) 2023-10-25 17:38:55 +02:00
Jack
cf5e93ee52 fix: fakeProfileThemes (#1837) 2023-10-25 17:38:55 +02:00
megumin
4d8e4e62ca fix: notrack failing patches (#1857) 2023-10-25 17:38:55 +02:00
AutumnVN
cb2532d22c disableDMCallIdle: fix (#1856) 2023-10-25 17:38:55 +02:00
AutumnVN
8c998b9330 experiments: fix (#1855) 2023-10-25 17:38:55 +02:00
Vendicated
fb22c57da1 MessageAccessoriesAPI: Fix 2023-10-25 17:38:55 +02:00
Vendicated
554bb18e9b BadgeAPI: fix 2023-10-25 17:38:55 +02:00
Vendicated
44c9675795 ContextMenuApi: fix 2023-10-25 17:38:55 +02:00
AutumnVN
322ecc5e88 usrbg: fix (#1853) 2023-10-25 17:38:55 +02:00
Vendicated
7ee9a8bb99 SpotifyControls: Fix 2023-10-25 17:38:55 +02:00
Vendicated
69b54535c3 Fix NoTrack 2023-10-25 17:38:55 +02:00
AutumnVN
2a56081bc2 callTimer: fix (#1850) 2023-10-25 17:38:55 +02:00
AutumnVN
baa7d8c078 noDevToolsWarning: fix (#1851) 2023-10-25 17:38:55 +02:00
AutumnVN
940193c30b noMosaic: fix (#1849) 2023-10-25 17:38:55 +02:00
Hugo C
09b646b860 fix: PictureInPicture (#1839)
Co-authored-by: V <vendicated@riseup.net>
2023-10-25 17:38:55 +02:00
Syncx
922e3ce6fe fix: FavoriteGifSearch (#1842) 2023-10-25 17:38:55 +02:00
Erik
cb93c11e16 Fix CustomRPC (#1846) 2023-10-25 17:38:55 +02:00
megumin
4beef9f73b fix: ComponentDispatch and GifPaste plugin (#1843)
Co-authored-by: V <vendicated@riseup.net>
2023-10-25 17:38:55 +02:00
Vendicated
4da79abb21 Fix components filter 2023-10-25 17:38:55 +02:00
Vendicated
4e27722b54 fix webpack patching 2023-10-25 17:38:55 +02:00
Vendicated
97c0face2f
PinDMs: Fix canary crash 2023-10-25 00:38:02 +02:00
V
1a1d9b07e8
Fix canary crashing (#1833) 2023-10-25 00:17:11 +02:00
Nuckyz
4a2def03e7
Fix MessageDecorationsAPI patch 2023-10-23 22:42:23 -03:00
Vendicated
544edce9f9
bump to v1.5.8 2023-10-21 19:26:29 +02:00
Dea
e4485165d0
onePingPerDM: add settings (#1802)
Co-authored-by: V <vendicated@riseup.net>
Co-authored-by: Dea <dea-banana@riseup.net>
2023-10-21 18:42:37 +02:00
Macintosh II
fada76ec81
PlatformIndicators: make size same as other memberlist icons (#1789)
Co-authored-by: V <vendicated@riseup.net>
2023-10-21 18:41:56 +02:00
zImPatrick
f659c46031
FakeNitro: Add app icon customization (#1822)
Co-authored-by: V <vendicated@riseup.net>
2023-10-21 17:53:00 +02:00
Nuckyz
ae1dc4eab0
Make reporter ignore useless Discord errors (#1829) 2023-10-21 17:51:07 +02:00
Nuckyz
fe60a72b80
Fix NoPendingCount patch 2023-10-21 12:26:04 -03:00
Nuckyz
5a0b2ee3f5
Fix FakeNitro patch 2023-10-21 12:26:04 -03:00
Nuckyz
6c1b8b0d8a
Fix MessageDecorationsAPI 2023-10-21 12:25:57 -03:00
Nuckyz
b2a1410a96
Remove useless Experiments patch 2023-10-21 12:03:54 -03:00
Nuckyz
c25c95eecd
Fix IgnoreActivities making reporter angry 2023-10-21 12:00:09 -03:00
ioj4
d94418f42f
fix: windows host update patching (#1820) 2023-10-19 11:14:40 +02:00
Vendicated
da1a8cdd67
web: Fix themes tab 2023-10-19 10:13:05 +02:00
Vendicated
5d7ede34d8
bump to v1.5.7 2023-10-19 01:23:59 +02:00
Vendicated
cd61354998
ContributorModal: Fix vertical overflow on multi word names 2023-10-19 00:22:49 +02:00
AutumnVN
a452945ac8
feat(plugin): NoTypingAnimation (#1680) 2023-10-19 00:14:14 +02:00
Marocco2
b577660800
feat(VcNarrator): add {{NICKNAME}} as placeholder (#1792) 2023-10-19 00:05:47 +02:00
AutumnVN
4f57c7eded
betterNotes, userVoiceShow: fix padding issue (#1804) 2023-10-18 23:54:35 +02:00
Ryan Cao
e3e5da10a9
fix: Content Security Policy patching (#1814)
Co-authored-by: Vendicated <vendicated@riseup.net>
2023-10-18 23:44:29 +02:00
Vendicated
998ce72f3b
ForceOwnerCrown: Remove log spam 2023-10-14 02:46:57 +02:00
AutumnVN
188d12d1a3
roleColorEverywhere: role group color in thread/forum (#1778) 2023-10-13 04:26:18 +02:00
AutumnVN
a522eab40d
feat(plugin): NoMosaic (#1791) 2023-10-13 04:10:36 +02:00
AutumnVN
c2721f158f
imageZoom: fix again (#1793)
Co-authored-by: V <vendicated@riseup.net>
2023-10-13 04:07:21 +02:00
Vendicated
61cd7b4d99
arrpc: refactor for use in vesktop 2023-10-13 03:49:58 +02:00
Marocco2
926af0d1cd
feat(VcNarrator): add {{DISPLAY_NAME}} as placeholder (#1642)
Co-authored-by: V <vendicated@riseup.net>
2023-10-12 04:05:46 +02:00
sunnie
dcaf4aec97
fix moreUserTags (#1780) 2023-10-12 03:30:32 +02:00
Nuckyz
5a97adb435
Fix broken IgnoreActivities patch 2023-10-10 05:10:46 -03:00
V
925d709335
bump to v1.5.6 2023-10-09 03:57:44 +02:00
V
1a36dbbc9b
ci: cleanup publish workflow 2023-10-09 03:56:41 +02:00
V
b59db2f8c2
Drop Firefox extension support
Despite me already fixing all issues, mozilla is still giving me more
trouble. Now they are asking me to provide them with testing credentials
for discord. Not only do i not want to give them my account, it also
isn't even possible because of how discord's login from new location
verification works

i am very tired of having to fight mozilla and their stupid guidelines /
requests. publishing to amo is a nightmare. as such, official support
for the extension is hereby dropped

we cannot even distribute the extension ourselves because extensions
NEED TO BE SIGNED to install them (unless you use firefox nightly).
and guess how you sign? VIA THEIR STUPID STORE

Options for firefox users:
- use the UserScript
- grab extension-firefox.zip from releases and install it on firefox
  nightly
- make your own firefox developer account and manually sign the
  extension-firefox.zip and pray they sign it for you (they wouldn't
  sign my unlisted upload of it)
- use a chromium browser
2023-10-09 03:49:33 +02:00
V
d81302f64c
Revert mozilla store compliance changes
This reverts commit 97b6699afe.

Vencord is dropping support for the firefox extension, so these changes
are now obsolete. revert so users can still install the extension
manually and enjoy the full experience
2023-10-09 03:15:43 +02:00
V
390987e4a9
Remove ReviewDB
abuse / harassment has gotten pretty bad.
i proposed the ability to allow users to delete comments from their own
profile, but there seems to be no interest among the reviewdb owners.

i don't want vencord to harbour harassment, so i'm removing the plugin
for now
2023-10-09 03:09:56 +02:00
V
377cf60055
fix global settings listeners 2023-10-09 03:01:54 +02:00
Nico
34ac718705
fix(forceOwnerCrown): update broken patch (#1777) 2023-10-07 23:20:36 -03:00
Nuckyz
e4659ed7c3
Rewrite IgnoreActivities (#1693) 2023-10-07 23:04:17 -03:00
Vendicated
c33d59b45d
serverProfile: fix crash with lurked guilds
Co-authored-by: aamiaa <9750071+aamiaa@users.noreply.github.com>
2023-10-08 03:49:00 +02:00
Vendicated
ac1b67ccbd
Experiments(isStaff): Fix search history not showing 2023-10-07 23:00:44 +02:00
Vendicated
c0f2c97458
ReviewDB: proper multi account support 2023-10-06 19:43:24 +02:00
Vendicated
664dd0a992
ReviewDB: allow deleting reviews on own profile 2023-10-06 18:44:22 +02:00
Vendicated
f66e35b658
fix(SendTimestamps): Do not add to ReviewDB input 2023-10-06 18:05:53 +02:00
Vendicated
df214e1e93
chore: remove legacy code 2023-10-06 18:01:19 +02:00
Vendicated
47a39a062e
Fix Vesktop SettingsCog context menu 2023-10-06 17:54:46 +02:00
Vendicated
9e63da6d78
bump to v1.5.5 2023-10-06 04:08:49 +02:00
AutumnVN
79295683ee
PictureInPicture: pip button hover styles (#1775)
Co-authored-by: V <vendicated@riseup.net>
2023-10-06 04:07:16 +02:00
Vendicated
5eb9dd04df
Fix member list decorations api 2023-10-06 04:00:09 +02:00
Vendicated
03b5dc9c27
BetterRoleDot: Fix ci test false positives 2023-10-06 03:17:44 +02:00
wntiv-main
726a1b5d96
Fix command API (#1776)
Co-authored-by: V <vendicated@riseup.net>
2023-10-06 03:16:21 +02:00
AutumnVN
581fe252a4
fix imageZoom (#1772) 2023-10-03 02:39:34 +02:00
Vendicated
30b2e88e77
Bump to v1.5.4 2023-10-03 02:29:57 +02:00
TheKodeToad
1f38a8eeab
Fix WhoReacted (#1769) 2023-10-03 02:26:38 +02:00
Vendicated
6db9721c06
ReviewDB: fix usericons appearing over modals 2023-10-03 02:17:28 +02:00
Dea
9891791fa7
feat(plugin): onePingPerDM (#1757)
Co-authored-by: V <vendicated@riseup.net>
2023-10-03 01:53:14 +02:00
Lewis Crichton
8dd5eeead2
feat(plugin): PermissionFreeWill (#1763)
Co-authored-by: V <vendicated@riseup.net>
2023-10-03 01:26:57 +02:00
whqwert
abf8667a5d
fix(plugin): Party mode 🎉 2023-10-02 23:17:51 +02:00
Vendicated
e33ac900bc
Merge remote-tracking branch 'origin/main' into dev 2023-10-02 23:10:07 +02:00
V
8a026060c7
Update blank.yml 2023-09-29 19:01:55 +02:00
V
c8b77bb187
Update bug_report.yml 2023-09-29 19:00:50 +02:00
AutumnVN
88b06191b9
fix modal image + reviewdb bot tag (#1761)
* fix modal image

* fix reviewdb bot tag
2023-09-29 00:46:33 +02:00
Vendicated
62277770a8
bump to v1.5.3 2023-09-28 02:42:55 +02:00
V
4facc3cad7
webContextMenus: support pasting images 2023-09-27 04:13:40 +02:00
TheKodeToad
837d1fc083
web: fix themes tab (#1756) 2023-09-26 21:47:12 +02:00
V
608a67c9ae
fix quick/searchReply & MessageClickactions not working in dms 2023-09-26 03:54:59 +02:00
AutumnVN
f32d25b641
viewRaw, viewIcons, permissionsViewer: fix some edge cases (#1745)
Co-authored-by: V <vendicated@riseup.net>
2023-09-26 01:48:09 +02:00
V
4c7a2ba340
Merge branch 'main' into dev 2023-09-26 01:45:38 +02:00
V
da7f0cfff6
PluginModal: Fix cancel button being white on white in light theme 2023-09-26 01:38:46 +02:00
V
ae6584da7c
add os-accent-color variable (following BetterDiscord) 2023-09-25 18:53:10 +02:00
V
c6b1b9463c
improve webpack find error messages 2023-09-25 18:27:18 +02:00
V
376aaf39ce
fix SearchReply filter 2023-09-25 18:07:43 +02:00
V
5454a41243
update issue templates 2023-09-25 04:27:16 +02:00
Hugo C
044f64e446
Improve permission checks on several plugins (#1746)
Co-authored-by: V <vendicated@riseup.net>
2023-09-24 16:42:53 +02:00
V
0b7fca864a
plugin READMEs: migrate from imgur to github assets 2023-09-24 16:17:33 +02:00
V
30ac256070
migrate all plugins to folders 2023-09-24 16:02:18 +02:00
Sam
d0e2a32471
VcNarrator: Ignore multiple underscores (#1748)
Co-authored-by: V <vendicated@riseup.net>
2023-09-24 15:55:23 +02:00
V
ec026ca34c
Update bug_report.yml 2023-09-24 15:45:22 +02:00
V
4baaa9bd91
Delete .github/ISSUE_TEMPLATE/feature_request.yml 2023-09-24 15:44:02 +02:00
V
d9933c5793
settingsSync: correctly use platform agnostic relaunch 2023-09-24 01:16:50 +02:00
V
2735037a67
[skip ci] bump to v1.5.2 2023-09-24 01:12:00 +02:00
Dziurwa
83bfe28fa4
FriendInvites: Add picking uses (1 or 5) (#1727)
Co-authored-by: V <vendicated@riseup.net>
2023-09-23 03:50:14 +02:00
V
08c5d23636
add max attempts to lazys 2023-09-23 03:25:19 +02:00
V
ac0f834155
Fix Plugin Settings on canary 2023-09-23 03:15:07 +02:00
V
fa16e1b56f
fix updater 2023-09-22 15:58:29 +02:00
V
cfca393f2b
ci(generatePluginList): add filePath 2023-09-22 04:48:54 +02:00
Nuckyz
eacc673bcc
Fix BetterRoleDot making reporter angry 2023-09-21 23:28:40 -03:00
Nuckyz
dba6c4cea6
Fix broken FakeNitro patch (again) 2023-09-21 22:41:25 -03:00
V
6b10947d06
Bump to v1.5.1 2023-09-21 18:58:43 +02:00
V
97b6699afe
Fuck you Mozilla 2023-09-21 18:56:58 +02:00
V
7e91edc757
browser: unhardcode rnnoise 2023-09-21 18:19:59 +02:00
V
a82544e93e
Delete FixInbox: Discord fixed this issue themselves now 2023-09-21 17:57:14 +02:00
AutumnVN
d8c8b74ed7
BetterRoleDot: Setting for copying role color in profile popout (#1698) 2023-09-21 17:40:37 +02:00
Daniel Foster
fadd1598f5
Settings: use nearest-neighbour for shiggy (#1739)
Co-authored-by: V <vendicated@riseup.net>
2023-09-21 17:18:41 +02:00
Manti
e5c0898dd6
[ReviewDB] add emojis, discord markdown & notifications (#1718)
Co-authored-by: V <vendicated@riseup.net>
2023-09-21 17:16:15 +02:00
Nuckyz
9550b74b2a
Fix broken FakeNitro patch 2023-09-20 02:44:31 -03:00
V
6cfb67a52e
fix ci 2023-09-19 04:15:34 +02:00
V
12fe367385
bump to v1.5.0 2023-09-19 04:12:54 +02:00
AutumnVN
fc0417eb80
moreUserTags: fix user tag in member list (#1730) 2023-09-19 04:11:30 +02:00
AutumnVN
1f87d14ab2
textReplace: pad space only in string rules (#1738) 2023-09-19 04:11:30 +02:00
XAlboX
7d8f3508a8
ClearURLs: Add si parameter on youtube.com (#1733)
Co-authored-by: V <vendicated@riseup.net>
2023-09-19 04:11:30 +02:00
V
41f5d71e38
Bundle dependencies with extensions for webstore rule compliance (#1740) 2023-09-19 04:11:27 +02:00
AutumnVN
efb88a4df8
favGifSearch: fix search bar (#1732) 2023-09-19 04:10:15 +02:00
Syncx
a73d09a2f0
PreviewMessage: Add attachments (& misc changes) (#1715) 2023-09-12 23:14:17 +02:00
AutumnVN
cf7c4d63b6
pictureInPicture: don't show PiP button on normal file (#1725) 2023-09-12 23:11:53 +02:00
Archer
a95311ef2c
lastfm: Add setting for artist name and song title only (#1726)
Co-authored-by: V <vendicated@riseup.net>
2023-09-12 23:11:25 +02:00
lovenginx
dd23f9802c
InvisibleChat: fixup decryption modal (#1720) 2023-09-12 23:04:50 +02:00
Nuckyz
f23ddf4cae
oopsies 2023-09-12 05:10:44 -03:00
Nuckyz
4222c7fd9f
Fix broken FakeNitro patch on canary 2023-09-12 05:01:18 -03:00
Nuckyz
09f65b401e
Fix broken MessageLogger patches 2023-09-12 04:28:55 -03:00
V
7364776715
Dearrow: Fix button part 2 2023-09-09 19:51:30 +02:00
V
3a5b70d410
Dearrow: Fix button 2023-09-09 19:49:11 +02:00
V
e08d49edac
New Plugin: Dearrow (#1723) 2023-09-09 19:17:50 +02:00
Mushrrom
17abbd3e3e
LastFM: Add setting for using name + artist as activity name (#1713)
Co-authored-by: V <vendicated@riseup.net>
2023-09-09 04:22:41 +02:00
V
25a1d934c6
bump to v1.4.7 2023-09-09 00:22:24 +02:00
Luna
620319a4bc blurnsfw: fix crash (#31)
Reviewed-on: https://codeberg.org/Ven/cord/pulls/31
Co-authored-by: Luna <imlvnaa@gmail.com>
Co-committed-by: Luna <imlvnaa@gmail.com>
2023-09-08 21:55:27 +00:00
Hugo C
4c9996d620
feat(plugin): PictureInPicture (#1697)
Co-authored-by: V <vendicated@riseup.net>
2023-09-08 03:57:44 +02:00
V
885c75fdaa
add custom plugin author popouts (#1712) 2023-09-08 03:42:20 +02:00
Lewis Crichton
f2a22c5e57
feat: crash info in /vencord-debug (#1714)
Co-authored-by: V <vendicated@riseup.net>
2023-09-08 03:41:30 +02:00
V
5e3a485edc
ci: generate plugin readme map 2023-09-08 02:26:47 +02:00
Luna
452bf72e56 rnnoise: fix error on webcam (#29)
errored because there was no audio stream, luckily the patched function had a boolean indicating if it was audio or not so just ignore it if it isnt

Reviewed-on: https://codeberg.org/Ven/cord/pulls/29
Co-authored-by: Luna <imlvnaa@gmail.com>
Co-committed-by: Luna <imlvnaa@gmail.com>
2023-09-06 17:10:33 +00:00
Luna
afa47addd7 usrbg: export the data to allow other plugins to access (#30)
Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
Co-authored-by: Ven <ven@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/Ven/cord/pulls/30
Co-authored-by: Luna <imlvnaa@gmail.com>
Co-committed-by: Luna <imlvnaa@gmail.com>
2023-09-06 17:10:04 +00:00
V
8ecee3d09f
fix ViewRaw & VoiceMessages context menu style 2023-09-06 19:08:48 +02:00
luk1337
d2aac5edc5
ClearURLs: Add share_id parameter on reddit.com (#1706) 2023-09-06 18:53:28 +02:00
lovenginx
fc45510053
LoadingQuotes: add a new quote (#1710) 2023-09-06 18:52:14 +02:00
AutumnVN
77bfaf38a5
HideAttachments: fix broken css (#1707) 2023-09-06 18:51:48 +02:00
AutumnVN
a4cadc03d8
viewRaw: dont add context menu to guild folders (#1708) 2023-09-06 18:51:18 +02:00
AutumnVN
315fcf1972
messageLogger: make ignoreChannels also ignore threads (#1709) 2023-09-06 18:50:20 +02:00
Nuckyz
f1b3b3c0a3
Uncanonicalize reported patches 2023-09-06 18:47:54 +02:00
V
4c805d08be
[skip ci] PatchHelper: Fix copy button style 2023-09-05 21:37:39 +02:00
V
9b987d1e56
Bump to v1.4.6 2023-09-05 21:25:16 +02:00
V
774318d583
ViewRaw: Update description 2023-09-05 21:24:43 +02:00
V
7d954f9ade
ViewRaw: Fix ugly copy icon & context menu position 2023-09-05 21:20:13 +02:00
Luna
860d6edc7b HideAttachments: allow hiding stickers (#13)
Self explanatory

Reviewed-on: https://codeberg.org/Ven/cord/pulls/13
Co-authored-by: Luna <imlvnaa@gmail.com>
Co-committed-by: Luna <imlvnaa@gmail.com>
2023-09-05 18:56:28 +00:00
Rini
223b0366c6 pinDMs: fix alt+shift+up (#25)
applies the same fix as alt+up/down to the jump to unread one

confirmed non-explosion of shc

Reviewed-on: https://codeberg.org/Ven/cord/pulls/25
Co-authored-by: Rini <rini@rinici.de>
Co-committed-by: Rini <rini@rinici.de>
2023-09-05 18:51:22 +00:00
Luna
69cb7593eb View Raw on more objects (#27)
Shows view raw on guilds, channels, and users

Reviewed-on: https://codeberg.org/Ven/cord/pulls/27
Co-authored-by: Luna <imlvnaa@gmail.com>
Co-committed-by: Luna <imlvnaa@gmail.com>
2023-09-05 18:49:57 +00:00
V
8614e17633
Fix some plugins wrongly displaying the settings cog 2023-09-05 20:10:42 +02:00
Ryan Cao
aecd9d8fda
feat(memberCount): format count according to user locale (#1679) 2023-09-05 19:46:33 +02:00
Hugo C
faeb4fb585
previewMessage: Hide the button once a message is sent (#1692)
Co-authored-by: V <vendicated@riseup.net>
2023-09-05 19:45:44 +02:00
dolfies
0d18b44ba7
feat(plugin): ShowTimeouts (#1687)
Co-authored-by: TheKodeToad <TheKodeToad@proton.me>
Co-authored-by: V <vendicated@riseup.net>
2023-09-05 19:42:35 +02:00
omahs
d671bd65ac
fix typos (#1703) 2023-09-05 19:40:32 +02:00
AutumnVN
8e952c630b
MessageLogger: fix ignore by id doesn't ignore edited (#1705) 2023-09-05 19:39:22 +02:00
V
2c758ccdf8
new plugin: ServerProfile (#1704)
Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
2023-09-05 18:36:14 +02:00
Nuckyz
c165725297
Fix OpenInApp patch 2023-09-02 03:03:50 -03:00
Nuckyz
29fbe3701a
Fix CrashHandler patch 2023-09-02 03:03:31 -03:00
V
0b7c0e9587
new plugin: themeAttributes (#1686) 2023-08-31 01:49:53 +02:00
Cynthia Foxwell
d88524e8cf
ShowMeYourName: Fix username being wrong on slash commands (#1690)
Co-authored-by: V <vendicated@riseup.net>
2023-08-31 01:01:29 +02:00
Hugo C
d6efd99849
messageLinkEmbeds: fix AutoModEmbed on compact mode (#1691)
Co-authored-by: V <vendicated@riseup.net>
2023-08-31 01:00:16 +02:00
ruukulada
fe6be987fd
gameActivityToggle: Fix disabled SVG look (#1696) 2023-08-31 00:53:05 +02:00
V
d688075c0a
Update Screenshot 2023-08-29 01:12:47 +02:00
V
c752be45b2
fix(security - ipc): do not expose sender 2023-08-25 14:57:04 +02:00
V
07c1f5eed1
Fix theme upload on crapOs 2023-08-25 14:37:50 +02:00
V
4df01b1e62
ci: fix generatePluginList 2023-08-25 14:33:33 +02:00
AutumnVN
ebe10d3fad
customRPC fixes (#1666)
Co-authored-by: V <vendicated@riseup.net>
2023-08-25 14:30:12 +02:00
Adrian Castro
eca4af829f
feat: add copyUserURLs plugin (#1683)
Co-authored-by: V <vendicated@riseup.net>
2023-08-25 14:24:58 +02:00
CanadaHonk
60458cdf1f
Win32Updater: use before-quit event instead of patching updater (#1668) 2023-08-25 14:21:27 +02:00
Sefa Eyeoglu
714d87241c
build: allow overriding git details & disabling updating (#1677)
Co-authored-by: V <vendicated@riseup.net>
2023-08-25 14:15:02 +02:00
Elliott Tallis
f628aa7a70
ClearURLs: Add si parameter on youtu.be (#1681) 2023-08-25 14:03:58 +02:00
megumin
0f0282551d
🗿 but HD (#1678) 2023-08-25 14:02:10 +02:00
V
0335e1ca59
new plugin FixSpotifyEmbeds: less loud embeds 2023-08-21 16:59:32 +02:00
V
817f0f7473
[skip ci] fix getPluginTarget 2023-08-20 15:14:28 +02:00
V
98a03c8862
bump to 1.4.5 2023-08-19 01:44:11 +02:00
V
72ce7a5ad1
themes: ignore non theme files 2023-08-19 01:33:39 +02:00
Syncx
e699ea63c7
feat(plugin): PreviewMessage (#1607)
Co-authored-by: V <vendicated@riseup.net>
2023-08-19 01:19:10 +02:00
VMGuy23
97e1e9eb7a
messageLogger: apply deleted style to ephemeral messages (#1608)
Co-authored-by: V <vendicated@riseup.net>
2023-08-19 01:14:51 +02:00
bb010g
4c4036546a
new plugin: NormalizeMessageLinks (#1641) 2023-08-19 01:10:59 +02:00
CanadaHonk
d582e61ec3
Fix patching Win32 updater with OpenAsar (#1667)
This is more generic rewrite allowing for more paths to be added in the future for whatever reason (like a rename in future Discord versions).

(The "OpenAsar" code previously was completely wrong)
2023-08-19 00:54:35 +02:00
V
ccd2ce8baf
Bump to 1.4.4 2023-08-16 02:10:06 +02:00
V
ede507e80c
chore: update for 'Vencord Desktop' -> 'Vesktop' rebrand 2023-08-16 01:55:56 +02:00
Justice Almanzar
ffdf63563b
feat(plugins): Web/Vesktop AI Noise Suppression powered by RNNoise (#1477)
Co-authored-by: V <vendicated@riseup.net>
2023-08-16 01:32:11 +02:00
Sammy
55b755b2df
InvisibleChat: improve encryption validator (#1646) 2023-08-16 00:57:56 +02:00
Nuckyz
ca439e9e9a
Fix ReviewDB buttons 2023-08-15 19:21:16 -03:00
Nuckyz
e02fcce3dc
Fix ServerListAPI 2023-08-15 18:48:50 -03:00
V
3e732646e5
Fix plugins broken by latest canary update (#1637)
* Fix WebContextMenus
* BetterGifAltText: futureproof find
* Fix pronoundb profile patch
* Fix NoScreensharePreview
* Fix FakeNitro emote text patch

---------

Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
2023-08-12 05:27:59 +02:00
V
d5b3b51050
bump to v1.4.3 2023-08-12 03:02:55 +02:00
V
725fb27e54
futureproof settings patches 2023-08-12 03:01:53 +02:00
V
243381fc91
Settings: Give vencord sections classes so themes can match them 2023-08-12 02:59:24 +02:00
V
54cbdfdad0
MemberCount: Remove negative margin, fixes issues with some themes 2023-08-12 02:46:38 +02:00
V
fe80b8cc85
AnonymiseFileNames: Properly keep .tar.* extensions 2023-08-12 02:45:11 +02:00
Andrew-DLO
742f5cf556
feat(plugin): SecretRingToneEnabler (#1570)
Co-authored-by: V <vendicated@riseup.net>
2023-08-12 02:23:00 +02:00
fawn
3b3da90c44
feat(VencordToolbox): add quickcss toggle (#1604)
Co-authored-by: V <vendicated@riseup.net>
2023-08-12 02:14:07 +02:00
TheKodeToad
c79e065d09
ShowMeYourName: Option to use display names instead of usernames (#1634)
Co-authored-by: V <vendicated@riseup.net>
2023-08-12 01:53:06 +02:00
V
3b8b43c7e0
ci: Fix reporter
Co-authored-by: Justice Almanzar <superdash993@gmail.com>
2023-08-12 01:36:19 +02:00
AutumnVN
6e7996659f
messageLogger: fix ingore guild (#1632) 2023-08-11 06:10:49 +02:00
Arrow
abdf4ebb05
feat(plugin): NoSentryConsole (#1623)
Co-authored-by: V <vendicated@riseup.net>
Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
2023-08-11 00:17:29 +02:00
Justice Almanzar
fa124d8877
build: split preload & renderer.css into D. desktop / vesktop (#1629) 2023-08-11 00:14:50 +02:00
im-h
135da2a5f3
Translate/SendTimestamps: Fix accessibility (#1628)
Co-authored-by: V <vendicated@riseup.net>
2023-08-10 02:31:28 +02:00
Manti
c96a1a9998
[ReviewDB] hide blocked users (#1626)
Co-authored-by: V <vendicated@riseup.net>
2023-08-10 00:28:46 +00:00
Rini
8b6c8bc0ec chore: transition to shorter license headers (#6)
Transition from the GPL jumpscare to a more concise header:

	/*
     * Vencord, a Discord client mod
	 * Copyright (c) 2023 Vendicated and contributors
     *
	 * SPDX-License-Identifier: GPL-3.0
     */

Old files still keep the old headers, while eslint will now autofix the new header

Reviewed-on: https://codeberg.org/Ven/cord/pulls/6
Co-authored-by: Rini <rini@rinici.de>
Co-committed-by: Rini <rini@rinici.de>
2023-08-10 00:17:49 +00:00
V
1a62249da6
bump to v1.4.2 2023-08-04 20:20:07 +02:00
Ryan Cao
21318850b1
fix: open links externally in Quick CSS editor (#1487)
Co-authored-by: V <vendicated@riseup.net>
2023-08-04 20:13:53 +02:00
Lewis Crichton
885ad134b3
fix(cloud): cross-client enabling without proper validation (#1531) 2023-08-04 20:10:12 +02:00
V
3e7d4e2623
make QuickCSS have priority over themes 2023-08-04 20:08:13 +02:00
AutumnVN
d3691f74c4
chore: Fix greetStickerPicker file name (#1610) 2023-08-04 20:01:49 +02:00
Justice Almanzar
268f3a1840
add bottom margin to settings section (#1616) 2023-08-04 19:56:40 +02:00
megumin
d6c43986fd
Add proper user-friendly theme manager (#635)
Co-authored-by: Justice Almanzar <superdash993@gmail.com>
Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
Co-authored-by: V <vendicated@riseup.net>
2023-08-04 19:52:20 +02:00
V
bb7deeb09c
UserVoiceShow: Fix error 2023-08-03 00:13:04 +02:00
AutumnVN
0407be9847
textReplace: fix edge case (#1521)
Co-authored-by: V <vendicated@riseup.net>
2023-08-02 00:28:44 +00:00
Hugo C
645749b5ae
VoiceMessages: Improve permission check (#1544)
Co-authored-by: V <vendicated@riseup.net>
2023-08-02 00:27:10 +00:00
AutumnVN
2e002107a6
customRPC: add validation & some fixes (#1481)
Signed-off-by: V <vendicated@riseup.net>
2023-08-02 01:52:08 +02:00
Nickyux
cc07518a34
VoiceMessages: Support replies (#1565)
Co-authored-by: TheKodeToad <TheKodeToad@proton.me>
Co-authored-by: Justice Almanzar <superdash993@gmail.com>
Co-authored-by: V <vendicated@riseup.net>
Signed-off-by: V <vendicated@riseup.net>
2023-08-02 01:51:39 +02:00
Lewis Crichton
ea64b33e24
star history :3 (#1528) 2023-08-01 05:35:45 +02:00
V
1a92d3ff8d
bump to v1.4.1 2023-08-01 05:34:43 +02:00
Rawir
45bb1af011
MuteNewGuild: Support lurked guilds (#1546)
Co-authored-by: Rawiros <45668076+Rawiros@users.noreply.github.com01~>
2023-08-01 05:32:29 +02:00
V
39ad88f433
Experiments: Fix canary 2023-08-01 05:23:52 +02:00
V
8cf4d2a2c0
Update 1_INSTALLING.md 2023-07-28 16:44:17 +02:00
V
fe5e041db8
VoiceMessages: Read file from dynamic path (fixes mac & linux support) 2023-07-27 02:06:18 +02:00
V
d18681c197
Delete blank.yml 2023-07-27 01:35:58 +02:00
V
c024db1bc4
Update config.yml 2023-07-27 01:35:44 +02:00
V
d8a0db8bee
Update blank.yml 2023-07-27 01:34:41 +02:00
V
f62efa5aa7
Update blank.yml 2023-07-27 01:33:55 +02:00
Hugo C
1d77ab0ade
MemberCount: fix family center crash (#1486) 2023-07-26 00:33:00 +00:00
V
9268cf3ffb
Bump to 1.4.0 2023-07-26 02:17:20 +02:00
Syncx
208371c471
feat(plugin): Favorite Gif Search (#1386)
Co-authored-by: V <vendicated@riseup.net>
2023-07-26 01:50:24 +02:00
Ryan Cao
c69c6f8cb7
feat(MessageLinkEmbeds): add whitelist/blacklist modes (#813)
Co-authored-by: V <vendicated@riseup.net>
2023-07-26 01:41:41 +02:00
alexia
f2c6fcaa3b
fix(PronounDB): don't use guild pronouns in global profile modal (#1462) 2023-07-26 01:34:51 +02:00
Aayush Shah
abf62f28db
Themes tab: Add QuickCss button (#1475) 2023-07-26 01:29:57 +02:00
V
8620a1d86d
New plugin: VoiceMessages (#1380)
Co-authored-by: V <vendicated@riseup.net>
Co-authored-by: Justice Almanzar <superdash993@gmail.com>
2023-07-26 01:27:04 +02:00
V
198b35ffdc
Merge branch 'main' into dev 2023-07-26 01:25:30 +02:00
Ryan Cao
b4d0d95731
fix vencord toolbox being unusable with drag region (#1480)
* fix(OpenInApp): Broken patch (#1434)

* fix: vencord toolbox unreachable with drag region

---------

Co-authored-by: whqwert <94757998+whqwert@users.noreply.github.com>
2023-07-25 15:34:57 +02:00
whqwert
f785aa1473
fix(OpenInApp): Broken patch (#1434) 2023-07-17 02:05:20 -03:00
Commandtechno
d56e6560e5
[chore] Update DisableDMCallIdle description (#1422) 2023-07-16 00:51:14 +02:00
Justice Almanzar
a7e74ee4d5
classNameFactory: Allow (& ignore) all sorts of falsy values (#1427) 2023-07-16 00:50:21 +02:00
Luca Zeuch
1340f023a3
feat(MessageLogger): add option to ignore channels and guilds (#1420) 2023-07-14 18:21:29 +02:00
V
2bf0c324d7
chore: Update dev ids 2023-07-14 01:12:07 +02:00
V
f621cdb50b
Bump monaco editor 2023-07-14 01:10:53 +02:00
echo
9717001783
delete uwuifier plugin (#1414)
Co-authored-by: exhq <exhq@exhq.dev>
2023-07-14 01:08:27 +02:00
MrDiamondDog
065ab75627
Add "Show New" option in plugin settings (#1416)
Co-authored-by: V <vendicated@riseup.net>
2023-07-13 19:35:40 +02:00
V
8aea72c1be
FakeNitro: Fix crash 2023-07-10 22:39:40 +02:00
V
bea7a1711e
Bump to v1.3.4 2023-07-08 03:40:31 +02:00
Lewis Crichton
e52ae62441
feat(cloud): support multiple user accounts (#1382)
Co-authored-by: V <vendicated@riseup.net>
2023-07-08 03:36:59 +02:00
V
7cd1d4c60f
translate: Add context menu item; fix MLE compatibility 2023-07-08 03:30:16 +02:00
V
2a318e390e
QuickCss: Fix wrongly applying quickcss when editing while disabled 2023-07-08 03:13:32 +02:00
V
7c7723bfb1
Plugin Settings: Use Switches for booleans 2023-07-08 03:04:58 +02:00
dolfies
2db0e71e5b
fix(RelationshipNotifier): Ignore user-actioned friend requests (#1390) 2023-07-08 02:37:32 +02:00
Ryan Cao
cde8074f44
feat(ClearURLs): add Threads share link tracking param (#1384) 2023-07-08 02:34:16 +02:00
Nuckyz
8b1630bc99
Fix ShowAllMessageButtons (#1392)
Co-authored-by: V <vendicated@riseup.net>
2023-07-08 02:33:37 +02:00
V
bf34b2ae43
Bump to v1.3.3 2023-07-06 01:26:31 +02:00
V
cb5f23d9b5
ProxyLazy: Limit attempts 2023-07-06 00:54:49 +02:00
V
cd2cbfa0ef
ShowHiddenChannels: Fix crashing on canary 2023-07-06 00:43:43 +02:00
Ryan Cao
232e340fab
fix: send notification when settings are manually synced (#1378)
Co-authored-by: V <vendicated@riseup.net>
2023-07-04 15:59:42 +00:00
V
8027daa2b0
Fix types 2023-07-04 17:58:32 +02:00
Ryan Cao
0f7b9f588e
perf(cloud sync): minify synced settings (#1377) 2023-07-04 17:57:28 +02:00
V
93482ac2a5
SpotifyControls: improve open in app capabilities & styles 2023-07-04 17:53:17 +02:00
V
994c3b3c92
OpenInApp: Fix bot buttons 2023-07-04 17:52:52 +02:00
V
c696c186e8
WebKeybinds: Fix scope 2023-07-02 01:23:51 +02:00
V
30d5e2108f
Bump to 1.3.2 2023-07-02 01:22:53 +02:00
V
1eabd1b701
WebKeybinds: Fix broken zoom on vesktop 2023-07-02 01:22:37 +02:00
V
1cbf2b43e1
Fix Badges 2023-07-02 01:17:02 +02:00
V
4c197d5d51
New Plugin: WebKeyBinds 2023-07-02 01:08:06 +02:00
V
f89027f46a
Bump to 1.3.1 2023-06-30 17:08:57 +02:00
V
07a0ebb1d2
PronounDB: Fix crash when having pronouns in profile disabled 2023-06-30 17:08:43 +02:00
V
f09b44b0d5
VcNarrator: Ignore stage channels 2023-06-30 15:55:20 +02:00
V
b607eebcb7
ImageZoom: Add square lens option 2023-06-30 15:50:56 +02:00
V
0936ca2985
ValidUser: Fix mentions with ! (<@!...>) 2023-06-30 15:43:21 +02:00
V
13bde79ec8
PronounDB: Fix profile patch, add pronoun source to tooltip 2023-06-30 15:39:33 +02:00
V
b592defaaf
OpenInApp: Add Epic Games; properly respect settings 2023-06-30 15:16:42 +02:00
V
73354973a3
OpenInApp: Support steam; integrate with SpotifyControls & ShowConnections 2023-06-29 16:15:07 +02:00
V
e12c0e546c
PronounDB: Fix crash 2023-06-29 14:28:16 +02:00
V
088a8bd1b6
OpenInApp: Support profile activity on web & profile connection 2023-06-29 05:02:13 +02:00
V
51adb26d01
New plugin: OpenInApp - Open spotify urls in spotify app 2023-06-29 04:33:35 +02:00
Nuckyz
cb980a1cad
Fix broken SHC patches (#1360) 2023-06-28 03:45:16 +00:00
V
69b10c1f07
Bump to 1.3.0 2023-06-27 23:12:56 +02:00
alexia
8e9ba7c7ee
PronounDB: fix caching not respecting user preference (#1344) 2023-06-27 22:46:52 +02:00
Commandtechno
12e3c9234d
ViewIcons: Fix animated server pfps & profile edit button (#1350)
fixes #1236
2023-06-27 22:41:52 +02:00
Sammy
1d8dcef394
InvisibleChat: fix indicator & crashes (#1356) 2023-06-27 22:41:33 +02:00
Syncx
4fe2845234
ImageZoom: add nearest neighbour (#1341) 2023-06-27 22:41:19 +02:00
V
5e71ed286e
PronounDB: Strip newlines from Discord Pronouns (Discord is stupid) 2023-06-25 19:08:18 +02:00
V
5edbd2391d
Fix build 2023-06-25 18:33:44 +02:00
ActuallyTheSun
8472c3823e
feat(🗿): ignore blocked users (#1327)
Co-authored-by: V <vendicated@riseup.net>
2023-06-25 18:31:39 +02:00
V
2103e52115
WebContextMenus: Support all text areas 2023-06-25 18:22:36 +02:00
Nuckyz
afbfb641e8
Fix IgnoreActivities broken patch (#1337) 2023-06-25 09:57:18 +00:00
629 changed files with 35824 additions and 13972 deletions

View file

@ -1,118 +0,0 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"ignorePatterns": ["dist", "browser"],
"plugins": [
"@typescript-eslint",
"header",
"simple-import-sort",
"unused-imports",
"path-alias"
],
"settings": {
"import/resolver": {
"alias": {
"map": [
["@webpack", "./src/webpack"],
["@webpack/common", "./src/webpack/common"],
["@utils", "./src/utils"],
["@api", "./src/api"],
["@components", "./src/components"]
]
}
}
},
"rules": {
// Since it's only been a month and Vencord has already been stolen
// by random skids who rebranded it to "AlphaCord" and erased all license
// information
"header/header": [
2,
"block",
[
{
"pattern": "!?",
"template": " "
},
" * Vencord, a modification for Discord's desktop app",
{
"pattern": " \\* Copyright \\(c\\) \\d{4}",
"template": " * Copyright (c) 2023 Vendicated and contributors"
},
" *",
" * This program is free software: you can redistribute it and/or modify",
" * it under the terms of the GNU General Public License as published by",
" * the Free Software Foundation, either version 3 of the License, or",
" * (at your option) any later version.",
" *",
" * This program is distributed in the hope that it will be useful,",
" * but WITHOUT ANY WARRANTY; without even the implied warranty of",
" * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
" * GNU General Public License for more details.",
" *",
" * You should have received a copy of the GNU General Public License",
" * along with this program. If not, see <https://www.gnu.org/licenses/>.",
""
],
2
],
"quotes": ["error", "double", { "avoidEscape": true }],
"jsx-quotes": ["error", "prefer-double"],
"no-mixed-spaces-and-tabs": "error",
"indent": ["error", 4, { "SwitchCase": 1 }],
"arrow-parens": ["error", "as-needed"],
"eol-last": ["error", "always"],
"@typescript-eslint/func-call-spacing": ["error", "never"],
"no-multi-spaces": "error",
"no-trailing-spaces": "error",
"no-whitespace-before-property": "error",
"semi": ["error", "always"],
"semi-style": ["error", "last"],
"space-in-parens": ["error", "never"],
"block-spacing": ["error", "always"],
"object-curly-spacing": ["error", "always"],
"eqeqeq": ["error", "always", { "null": "ignore" }],
"spaced-comment": ["error", "always", { "markers": ["!"] }],
"yoda": "error",
"prefer-destructuring": ["error", { "object": true, "array": false }],
"operator-assignment": ["error", "always"],
"no-useless-computed-key": "error",
"no-unneeded-ternary": ["error", { "defaultAssignment": false }],
"no-invalid-regexp": "error",
"no-constant-condition": ["error", { "checkLoops": false }],
"no-duplicate-imports": "error",
"no-extra-semi": "error",
"dot-notation": "error",
"no-useless-escape": [
"error",
{
"extra": "i"
}
],
"no-fallthrough": "error",
"for-direction": "error",
"no-async-promise-executor": "error",
"no-cond-assign": "error",
"no-dupe-else-if": "error",
"no-duplicate-case": "error",
"no-irregular-whitespace": "error",
"no-loss-of-precision": "error",
"no-misleading-character-class": "error",
"no-prototype-builtins": "error",
"no-regex-spaces": "error",
"no-shadow-restricted-names": "error",
"no-unexpected-multiline": "error",
"no-unsafe-optional-chaining": "error",
"no-useless-backreference": "error",
"use-isnan": "error",
"prefer-const": "error",
"prefer-spread": "error",
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error",
"unused-imports/no-unused-imports": "error",
"path-alias/no-relative": "error"
}
}

View file

@ -1,14 +1,24 @@
name: Blank Template name: Blank Issue
description: Use this only if your issue does not fit into another template. **DO NOT ASK FOR SUPPORT OR REQUEST PLUGINS** description: Create a blank issue. ALWAYS FIRST USE OUR SUPPORT CHANNEL! ONLY USE THIS FORM IF YOU ARE A CONTRIBUTOR OR WERE TOLD TO DO SO IN THE SUPPORT CHANNEL.
labels: []
body: body:
- type: textarea - type: markdown
id: info-sec
attributes: attributes:
label: Tell us all about it. value: |
description: Go nuts, let us know what you're wanting to bring attention to. # READ THIS BEFORE OPENING AN ISSUE
placeholder: ...
This form is ONLY FOR DEVELOPERS. YOUR ISSUE WILL BE CLOSED AND YOU WILL POSSIBLY BE BLOCKED FROM THE REPOSITORY IF YOU IGNORE THIS.
DO NOT USE THIS FORM, unless
- you are a vencord contributor
- you were given explicit permission to use this form by a moderator in our support server
DO NOT USE THIS FORM FOR SECURITY RELATED ISSUES. [CREATE A SECURITY ADVISORY INSTEAD.](https://github.com/Vendicated/Vencord/security/advisories/new)
- type: textarea
id: content
attributes:
label: Content
validations: validations:
required: true required: true
@ -16,7 +26,6 @@ body:
id: agreement-check id: agreement-check
attributes: attributes:
label: Request Agreement label: Request Agreement
description: DO NOT USE THIS TEMPLATE FOR SUPPORT OR PLUGIN REQUESTS!!! For Support, **join our Discord**. For plugin requests, **use discussions**
options: options:
- label: This is not a support or plugin request - label: I have read the requirements for opening an issue above
required: true required: true

View file

@ -1,9 +1,22 @@
name: Bug/Crash Report name: Bug/Crash Report
description: Create a bug or crash report for Vencord description: Create a bug or crash report for Vencord. ALWAYS FIRST USE OUR SUPPORT CHANNEL! ONLY USE THIS FORM IF YOU ARE A CONTRIBUTOR OR WERE TOLD TO DO SO IN THE SUPPORT CHANNEL.
labels: [bug] labels: [bug]
title: "[Bug] <title>" title: "[Bug] <title>"
body: body:
- type: markdown
attributes:
value: |
# READ THIS BEFORE OPENING AN ISSUE
This form is ONLY FOR DEVELOPERS. YOUR ISSUE WILL BE CLOSED AND YOU WILL POSSIBLY BE BLOCKED FROM THE REPOSITORY IF YOU IGNORE THIS.
DO NOT USE THIS FORM, unless
- you are a vencord contributor
- you were given explicit permission to use this form by a moderator in our support server
DO NOT USE THIS FORM FOR SECURITY RELATED ISSUES. [CREATE A SECURITY ADVISORY INSTEAD.](https://github.com/Vendicated/Vencord/security/advisories/new)
- type: input - type: input
id: discord id: discord
attributes: attributes:
@ -64,3 +77,5 @@ body:
options: options:
- label: I am using Discord Stable or tried on Stable and this bug happens there as well - label: I am using Discord Stable or tried on Stable and this bug happens there as well
required: true required: true
- label: I have read the requirements for opening an issue above
required: true

View file

@ -1,32 +0,0 @@
name: Feature Request
description: Create a feature request for Vencord. To request new plugins, please use the Discussions tab
labels: [enhancement]
title: "[Feature Request] <title>"
body:
- type: input
id: discord
attributes:
label: Discord Account
description: Who on Discord is making this request? Not required but encouraged for easier follow-up
placeholder: username#0000
validations:
required: false
- type: textarea
id: feature-basic-description
attributes:
label: What is it that you'd like to see?
description: Describe the feature you want added as detailed as possible
placeholder: I think ... would be a cool feature to add. This would be awesome, thanks!
validations:
required: true
- type: checkboxes
id: agreement-check
attributes:
label: Request Agreement
description: DO NOT USE THIS TEMPLATE FOR PLUGIN REQUESTS!!! For plugin requests, **use discussions**
options:
- label: This is not a plugin request
required: true

View file

@ -18,31 +18,31 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: pnpm/action-setup@v2 # Install pnpm using packageManager key in package.json - uses: pnpm/action-setup@v3 # Install pnpm using packageManager key in package.json
- name: Use Node.js 19 - name: Use Node.js 20
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
node-version: 19 node-version: 20
cache: "pnpm" cache: "pnpm"
- name: Install dependencies - name: Install dependencies
run: pnpm install --frozen-lockfile run: pnpm install --frozen-lockfile
- name: Build web - name: Build web
run: pnpm buildWeb --standalone run: pnpm buildWebStandalone
- name: Build - name: Build
run: pnpm build --standalone run: pnpm build --standalone
- name: Generate plugin list - name: Generate plugin list
run: pnpm generatePluginJson dist/plugins.json run: pnpm generatePluginJson dist/plugins.json dist/plugin-readmes.json
- name: Clean up obsolete files - name: Clean up obsolete files
run: | run: |
rm -rf dist/*-unpacked Vencord.user.css vencordDesktopRenderer.css vencordDesktopRenderer.css.map rm -rf dist/*-unpacked dist/monaco Vencord.user.css vencordDesktopRenderer.css vencordDesktopRenderer.css.map
- name: Get some values needed for the release - name: Get some values needed for the release
id: release_values id: release_values

View file

@ -13,10 +13,10 @@ jobs:
if: github.repository == 'Vendicated/Vencord' if: github.repository == 'Vendicated/Vencord'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: pixta-dev/repository-mirroring-action@674e65a7d483ca28dafaacba0d07351bdcc8bd75 # v1.1.1 - uses: pixta-dev/repository-mirroring-action@674e65a7d483ca28dafaacba0d07351bdcc8bd75 # v1.1.1
with: with:
target_repo_url: "git@codeberg.org:Ven/cord.git" target_repo_url: "git@codeberg.org:Vee/cord.git"
ssh_private_key: ${{ secrets.CODEBERG_SSH_PRIVATE_KEY }} ssh_private_key: ${{ secrets.CODEBERG_SSH_PRIVATE_KEY }}

View file

@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: check that tag matches package.json version - name: check that tag matches package.json version
run: | run: |
@ -20,42 +20,26 @@ jobs:
exit 1 exit 1
fi fi
- uses: pnpm/action-setup@v2 # Install pnpm using packageManager key in package.json - uses: pnpm/action-setup@v3 # Install pnpm using packageManager key in package.json
- name: Use Node.js 19 - name: Use Node.js 19
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
node-version: 19 node-version: 20
cache: "pnpm" cache: "pnpm"
- name: Install dependencies - name: Install dependencies
run: pnpm install --frozen-lockfile run: pnpm install --frozen-lockfile
- name: Build web - name: Build web
run: pnpm buildWeb --standalone run: pnpm buildWebStandalone
- name: Publish extension - name: Publish extension
run: | run: |
# Do not fail so that even if chrome fails, firefox gets a shot. But also store exit code to fail workflow later
EXIT_CODE=0
# Chrome
cd dist/chromium-unpacked cd dist/chromium-unpacked
pnpx chrome-webstore-upload-cli@2.1.0 upload --auto-publish || EXIT_CODE=$? pnpx chrome-webstore-upload-cli@2.1.0 upload --auto-publish
# Firefox
cd ../firefox-unpacked
npm i -g web-ext@7.4.0 web-ext-submit@7.4.0
web-ext-submit || EXIT_CODE=$?
exit $EXIT_CODE
env: env:
# Chrome
EXTENSION_ID: ${{ secrets.CHROME_EXTENSION_ID }} EXTENSION_ID: ${{ secrets.CHROME_EXTENSION_ID }}
CLIENT_ID: ${{ secrets.CHROME_CLIENT_ID }} CLIENT_ID: ${{ secrets.CHROME_CLIENT_ID }}
CLIENT_SECRET: ${{ secrets.CHROME_CLIENT_SECRET }} CLIENT_SECRET: ${{ secrets.CHROME_CLIENT_SECRET }}
REFRESH_TOKEN: ${{ secrets.CHROME_REFRESH_TOKEN }} REFRESH_TOKEN: ${{ secrets.CHROME_REFRESH_TOKEN }}
# Firefox
WEB_EXT_API_KEY: ${{ secrets.WEBEXT_USER }}
WEB_EXT_API_SECRET: ${{ secrets.WEBEXT_SECRET }}

View file

@ -11,31 +11,40 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
if: ${{ github.event_name == 'schedule' }}
- uses: pnpm/action-setup@v2 # Install pnpm using packageManager key in package.json
- name: Use Node.js 19
uses: actions/setup-node@v3
with: with:
node-version: 19 ref: dev
- uses: actions/checkout@v4
if: ${{ github.event_name == 'workflow_dispatch' }}
- uses: pnpm/action-setup@v3 # Install pnpm using packageManager key in package.json
- name: Use Node.js 20
uses: actions/setup-node@v4
with:
node-version: 20
cache: "pnpm" cache: "pnpm"
- name: Install dependencies - name: Install dependencies
run: | run: |
pnpm install --frozen-lockfile pnpm install --frozen-lockfile
pnpm add puppeteer
sudo apt-get install -y chromium-browser - name: Install Google Chrome
id: setup-chrome
uses: browser-actions/setup-chrome@82b9ce628cc5595478a9ebadc480958a36457dc2
with:
chrome-version: stable
- name: Build web - name: Build Vencord Reporter Version
run: pnpm buildWeb --standalone run: pnpm buildReporter
- name: Create Report - name: Create Report
timeout-minutes: 10 timeout-minutes: 10
run: | run: |
export PATH="$PWD/node_modules/.bin:$PATH" export PATH="$PWD/node_modules/.bin:$PATH"
export CHROMIUM_BIN=$(which chromium-browser) export CHROMIUM_BIN=${{ steps.setup-chrome.outputs.chrome-path }}
esbuild scripts/generateReport.ts > dist/report.mjs esbuild scripts/generateReport.ts > dist/report.mjs
node dist/report.mjs >> $GITHUB_STEP_SUMMARY node dist/report.mjs >> $GITHUB_STEP_SUMMARY
@ -48,7 +57,7 @@ jobs:
if: success() || failure() # even run if previous one failed if: success() || failure() # even run if previous one failed
run: | run: |
export PATH="$PWD/node_modules/.bin:$PATH" export PATH="$PWD/node_modules/.bin:$PATH"
export CHROMIUM_BIN=$(which chromium-browser) export CHROMIUM_BIN=${{ steps.setup-chrome.outputs.chrome-path }}
export USE_CANARY=true export USE_CANARY=true
esbuild scripts/generateReport.ts > dist/report.mjs esbuild scripts/generateReport.ts > dist/report.mjs

View file

@ -1,23 +1,22 @@
name: test name: test
on: on:
push: push:
branches:
- main
pull_request: pull_request:
branches: branches:
- main - main
- dev
jobs: jobs:
test: test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: pnpm/action-setup@v2 # Install pnpm using packageManager key in package.json - uses: pnpm/action-setup@v3 # Install pnpm using packageManager key in package.json
- name: Use Node.js 18 - name: Use Node.js 20
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
node-version: 18 node-version: 20
cache: "pnpm" cache: "pnpm"
- name: Install dependencies - name: Install dependencies

2
.gitignore vendored
View file

@ -18,7 +18,5 @@ lerna-debug.log*
.pnpm-debug.log* .pnpm-debug.log*
*.tsbuildinfo *.tsbuildinfo
src/userplugins
ExtensionCache/ ExtensionCache/
settings/ settings/

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "src/userplugins/vc-message-logger-enhanced"]
path = src/userplugins/vc-message-logger-enhanced
url = https://github.com/Syncxv/vc-message-logger-enhanced.git

1
.npmrc
View file

@ -1 +1,2 @@
strict-peer-dependencies=false strict-peer-dependencies=false
package-manager-strict=false

View file

@ -1,6 +1,11 @@
{ {
"extends": "stylelint-config-standard", "extends": "stylelint-config-standard",
"rules": { "rules": {
"indentation": 4 "selector-class-pattern": [
"^[a-z][a-zA-Z0-9]*(-[a-z0-9][a-zA-Z0-9]*)*$",
{
"message": "Expected class selector to be kebab-case with camelCase segments"
}
]
} }
} }

View file

@ -1,11 +1,9 @@
{ {
"recommendations": [ "recommendations": [
"dbaeumer.vscode-eslint", "dbaeumer.vscode-eslint",
"eamodio.gitlens",
"EditorConfig.EditorConfig", "EditorConfig.EditorConfig",
"ExodiusStudios.comment-anchors",
"formulahendry.auto-rename-tag",
"GregorBiswanger.json2ts", "GregorBiswanger.json2ts",
"stylelint.vscode-stylelint" "stylelint.vscode-stylelint",
"Vendicated.vencord-companion"
] ]
} }

View file

@ -1,7 +1,7 @@
{ {
"editor.formatOnSave": true, "editor.formatOnSave": true,
"editor.codeActionsOnSave": { "editor.codeActionsOnSave": {
"source.fixAll.eslint": true "source.fixAll.eslint": "explicit"
}, },
"[typescript]": { "[typescript]": {
"editor.defaultFormatter": "vscode.typescript-language-features" "editor.defaultFormatter": "vscode.typescript-language-features"

View file

@ -16,5 +16,6 @@ DON'T
Repetitive violations of these guidelines might get your access to the repository restricted. Repetitive violations of these guidelines might get your access to the repository restricted.
If you feel like a user is violating these guidelines or feel treated unfairly, please refrain from vigilantism
If you feel like a user is violating these guidelines or feel treated unfairly, please refrain from publicly challenging them and instead contact a Moderator on our Discord server or send an email to vendicated+conduct@riseup.net! and instead report the issue to a moderator! The best way is joining our [official Discord community](https://vencord.dev/discord)
and opening a modmail ticket.

View file

@ -1,82 +1,56 @@
# Contribution Guide # Contributing to Vencord
First of all, thank you for contributing! :3 Vencord is a community project and welcomes any kind of contribution from anyone!
To ensure your contribution is robust, please follow the below guide! We have development documentation for new contributors, which can be found at <https://docs.vencord.dev>.
For a friendly introduction to plugins, see [Megu's Plugin Guide!](docs/2_PLUGINS.md) All contributions should be made in accordance with our [Code of Conduct](./CODE_OF_CONDUCT.md).
## Style Guide ## How to contribute
- This project has a very minimal .editorconfig. Make sure your editor supports this! Contributions can be sent via pull requests. If you're new to Git, check [this guide](https://opensource.com/article/19/7/create-pull-request-github).
If you are using VSCode, it should automatically recommend you the extension; If not,
please install the Editorconfig extension
- Try to follow the formatting in the rest of the project and stay consistent
- Follow the file naming convention. File names should usually be camelCase, unless they export a Class
or React Component, in which case they should be PascalCase
## Contributing a Plugin Pull requests can be made either to the `main` or the `dev` branch. However, unless you're an advanced user, I recommend sticking to `main`. This is because the dev branch might contain unstable changes and be force pushed frequently, which could cause conflicts in your pull request.
Because plugins modify code directly, incompatibilities are a problem. ## Write a plugin
Thus, 3rd party plugins are not supported, instead all plugins are part of Vencord itself. Writing a plugin is the primary way to contribute.
This way we can ensure compatibility and high quality patches.
Follow the below guide to make your first plugin! Before starting your plugin:
- Check existing pull requests to see if someone is already working on a similar plugin
- Check our [plugin requests tracker](https://github.com/Vencord/plugin-requests/issues) to see if there is an existing request, or if the same idea has been rejected
- If there isn't an existing request, [open one](https://github.com/Vencord/plugin-requests/issues/new?assignees=&labels=&projects=&template=request.yml) yourself
and include that you'd like to work on this yourself. Then wait for feedback to see if the idea even has any chance of being accepted. Or maybe others have some ideas to improve it!
- Familarise yourself with our plugin rules below to ensure your plugin is not banned
### Finding the right module to patch ### Plugin Rules
If the thing you want to patch is an action performed when interacting with a part of the UI, use React DevTools. - No simple slash command plugins like `/cat`. Instead, make a [user installable Discord bot](https://discord.com/developers/docs/change-log#userinstallable-apps-preview)
They come preinstalled and can be found as the "Components" tab in DevTools. - No simple text replace plugins like Let me Google that for you. The TextReplace plugin can do this
Use the Selector (top left) to select the UI Element. Now you can see all callbacks, props or jump to the source - No raw DOM manipulation. Use proper patches and React
directly. - No FakeDeafen or FakeMute
- No StereoMic
- No plugins that simply hide or redesign ui elements. This can be done with CSS
- No plugins that interact with specific Discord bots (official Discord apps like Youtube WatchTogether are okay)
- No selfbots or API spam (animated status, message pruner, auto reply, nitro snipers, etc)
- No untrusted third party APIs. Popular services like Google or GitHub are fine, but absolutely no self hosted ones
- No plugins that require the user to enter their own API key
- Do not introduce new dependencies unless absolutely necessary and warranted
If it is anything else, or you're too lazy to use React DevTools, hit `CTRL + Shift + F` while in DevTools and ## Improve Vencord itself
enter a search term, for example "getUser" to search all source files.
Look at the results until you find something promising. Set a breakpoint and trigger the execution of that part of Code to inspect arguments, locals, etc...
### Writing a robust patch If you have any ideas on how to improve Vencord itself, or want to propose a new plugin API, feel free to open a feature request so we can discuss.
##### "find" Or if you notice any bugs or typos, feel free to fix them!
First you need to find a good `find` value. This should be a string that is unique to your module. ## Contribute to our Documentation
If you want to patch the `getUser` function, usually a good first try is `getUser:` or `function getUser()`,
depending on how the module is structured. Again, make sure this string is unique to your module and is not
found in any other module. To verify this, search for it in all bundles (CTRL + Shift + F)
##### "match" The source code of our documentation is available at <https://github.com/Vencord/Docs>
This is the regex that will operate on the module found with "find". Just like in find, you should make sure If you see anything outdated, incorrect or lacking, please fix it!
this only matches exactly the part you want to patch and no other parts in the file. If you think a new page should be added, feel free to suggest it via an issue and we can discuss.
The easiest way to write and test your regex is the following: ## Help out users in our Discord community
- Get the ID of the module you want to patch. To do this, go to it in the sources tab and scroll up until you We have an open support channel in our [Discord community](https://vencord.dev/discord).
see something like `447887: (e,t,n)=>{` (Obviously the number will differ). Helping out users there is always appreciated! The more, the merrier.
- Now paste the following into the console: `Vencord.Webpack.wreq.m[447887].toString()` (Changing the number to your ID)
- Now either test regexes on this string in the console or use a tool like https://regex101.com
Also pay attention to the following:
- Never hardcode variable or parameter names or any other minified names. They will change in the future. The only Exception to this rule
are the react props parameter which seems to always be `e`, but even then only rely on this if it is necessary.
Instead, use one of the following approaches where applicable:
- Match 1 or 2 of any character: `.{1,2}`, for example to match the variable name in `var a=b`, `var (.{1,2})=`
- Match any but a guaranteed terminating character: `[^;]+`, for example to match the entire assigned value in `var a=b||c||func();`,
`var .{1,2}=([^;]+);`
- If you don't care about that part, just match a bunch of chars: `.{0,50}`, for example to extract the variable "b" in `createElement("div",{a:"foo",c:"bar"},b)`, `createElement\("div".{0,30},(.{1,2})\),`. Note the `.{0,30}`, this is essentially the same as `.+`, but safer as you can't end up accidently eating thousands of characters
- Additionally, as you might have noticed, all of the appove approaches use regex groups (`(...)`) to capture the variable name. You can then use those groups in your replacement to access those variables dynamically
#### "replace"
This is the replacement for the match. This is the second argument to [String.replace](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace), so refer to those docs for info.
Never hardcode minified variable or parameter names here. Instead, use capture groups in your regex to capture the variable names
and use those in your replacement
Make sure your replacement does not introduce any whitespace. While this might seem weird, random whitespace may mess up other patches.
This includes spaces, tabs and especially newlines
---
And that's it! Now open a Pull Request with your Plugin

View file

@ -1,11 +1,12 @@
# Vencord # Vencord
[![Codeberg Mirror](https://img.shields.io/static/v1?style=for-the-badge&label=Codeberg%20Mirror&message=codeberg.org/Ven/cord&color=2185D0&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABmJLR0QA/wD/AP+gvaeTAAAKbUlEQVR4nNVae3AV5RX/nW/3Pva+b24e5HHzIICQKGoiYiW8NFBFgohaa6ctglpbFSujSGurzUinohWsOij/gGX6R2fqOK0d1FYTEZXaTrWCBbEikJCEyCvkeXNvkrunf+zdkJDkPnex/c3cmd29+53v/M6e73znnF2Cydj4Tntldzi6qrN/qKqzf2jy6b7BnL4B1dI7oMp9AyoRAIdVsNMqhlxWMZjtspzyK/Jhr036OMsm//bh2vzPzNSPzBD6xFutd7R0Dq758ky4orkjYuc05RCAkixbeEq2/UCJ1/LczxcX/c5IPfU5DMHmxpbCpu7o1k/b+xc1n43YjJI7EqV+W2RmvuPt0oDjB2vn5bQbITNjAzzdeKK8qTO0bU9T77zucNQUjzofHrvENWWu3aUBZfW6+ZOOZiIrbYXrmUXo9daX3v6i667O/iGRiRLpwqtIvKDc+0efJ3hb/UIaSkdGWgZ4sqGt9r2m3lc/P9HvSWe80ZiRp3TPL/UsX1+bvyvVsSkb4NE3WjbuPNj5SM8Fcvdk4bAKrqvwv7DxhuCPUxmXNIn6XSy3nWr6R8OhrqrU1btwqJ3m/bgwu/SqZJdEUgbYsuuka09b9/4Pm3tLMlPvwuAbpe6m+RcplfdcURBKdG9CA2zZddLV2Nx1+JO2vlxj1LswqCpynlxc6SxLZIS40bueWfy9vXvv/xt5APhXa1/u7v+EPqvfxXK8++IaoO2Vpn9+cLS33FjVLhw+bOotOX7q6N/i3TOhAX7y+rHN/+sBLxm8fah71k93tjw/0f/jGuDJxtZrdh7setA8tS4sdn7eef+v3mmfP95/Ywxw6x9Yev9I35/6Iubv83WVfl5a6Uu3VkoavZEo7TnS/Vo98xi+Yy6UKC3bDp7sd5ut1OWFDjyzNMib6oq5Oug0ezp8dqLfG3r92Nbzr48ywNONJ8obDnV/z2xlAk4ZW1aUqhaJIAvCb5YVqwFn3GBtCBoO9dz5TOPxUbnMKAM0dYa2d5lc2AgCNi8r5klui3aBgWynjE11QZbI3FV3NjQkjnYNbB+lj36wubGlcE9T71xTNQDw0Px8nlvmHl73GmfCrKCL19Tkmh4P9jT1LHz2vVP5+vmwAZq71a1m1/PXTPXwD68eS5KIEVUZd1yZwwumeEw1Qld/lJrPhF7Sz4cNsO+rUK2ZExd6rfj10iCPZ2GJCCoAZuCJxQUc9FvNVAX72kPX6ccC0Hp4zR0Ru1kT2mTCSzeXqn5l/EAniMAqoDLDYZWwqa5EVSzmhaKmsxHbLxvbbgdiBmjpHFxj2mwANlxXxBdPUib8nwgQgqAyEFUZxT4L1i/MN3UpHDsTWQvEDHDoTLjCrIluuyzAt8zMSkhGFhp5hrYUFk3z8IqZftOMcKRj4GIAEM80tFccM8n9Z+Qq+MXigqRIWCQCMzQvYIbKwH1X53FFnjkr88iZsLKpoXWa6BiIrjbDzF67hK23lKp2Obm1LAstPEZVjTwDkAio/2ZQ9dolw/VjAB0DfKfoCg9WGy2cADy1NMhBX2rR3CIRGICq8rAhAg4Jj9UWsDBhg+4MR6vF2VC0zGjB99fk8eJp3pQdyyrRMHF9KURVxswCB6+alWO4o3b2RyeLU32D2UYKnVPm5gfm5qWlrF0Wo4hzbCmoDNw0089XlboNNcLpvsFc0RtRDXuNle+x4Lkbi9PO6WWJIBFGEY+qjGjswtq5eVzosRilLnoiUavoH1INiTCyIDy/vETNcmRW1dl0L4gRVxmx3YFhlwnrry1QrZIxASE0yJIIDaiGSHt8UQFXF2Ve1zusYgzxkXGhyGvFvePUE+mgfyAqhGqAqKWVPv5udbYhSjmtkpYWq6OJqzFjqCpjTpmbl1Rk3klSGRBWmTISNC3Hjo1LgoYFJ0GA1aIVR+cTVxlQoS2Pb18a4PLszMKXzSJYuCySmq4Al03CiytKVYfBhYvLKk1IXE+XLRLhwZp81WlNf26HTFHhd0jhdAYTgKduCPLkgPHfQjitYkLiAIEZBDBlu2R6aF7euCV2Mgg45bDw2qWOdAavnp3D109PPdlJBvpTnYg4kVY3MDMuylVw62WJi63x4LHLZ0TAIR9OdWBVodPUclUQwWmT4hLXfgCIUDfDi6oiR8rzBJzyl8LnkD9KZVCOU8aLN5eoshnJ+Qh4bFJC4gztmEjgrtk5anaKnWWfXfpIuBTLjmSpSILw/E0laq7LuGxsIngVCYmIa96hLRG3TaZ1C/KTfjAEQLFIO8TPFk7aH/RZI8kMWrdgEs8udqXLKSUoMkEW4ETEQTRsoHyPlVZfmVw+Uuy3hR9bVHBQAMD0XPu/Ew24dqqH777K/La1DiKCxyYlRRzQymgG4+oyDxZOTdxZnp5r3wvEWmJ5btuL8W4uzbJh87LitLebdOFVpKSJx4IlwIzbL81CcYLO8iSX/IImGQCYae6Wg/2tXQNjNnW7LPDKyilqZd7ETU2zEBlifNTSS4i9PNFIx44x4jh2nZlBsUr0dN8QP/6XVhEaHJvnlfhtkXd/NF0BUextKRFXFznfGk+JDdcX8tdBHtDa6YpFsB4I9ac88omf8wbEgqa2XAIOme6bM35foqrQ+QZIKwGG80ifVbrXZZNGDfhOVYBvviS9JMMoaP3AEcQpPnHdOxiMGXkKbrx4dGfZY5c4T8H9+vmwAeqXFLXOKXW9r59fWuDA44sKv1byAOBzyCkTH+kdS2f4MLPgXJI0p9T17vrFxcf181GVxEUB+0qfIqt+RcKWFSWGNR4ygd4RTpW4HiCJgFWzstmnSPA7ZLU827pypPwxDB/687GXl1X6Vs6bbGz/LRN80hZCT+yLFZ0cgHED4egACeiXm89GsP9EePuzy4rvGil7jAGYmQDsBjDHUBYZ4GhHBMfORigd4rpnyIS9u6d4rqgnGrUtjCmmSYuOqwB0GcwjbWh9xviurpNnxnDA1IspMPe6bOL755MHJvhKjIgOA7jbJD4pw22Thj+kSIW47h2KRaydVezeP57sCdspRPQqgGeNJJIuBAE+ReJUiOv32mXaXjPZs21C2QnmXgdghyEsMoRfkVMiDgCywF/by9z3xJMb1wCxeHAPgDczZpAh/Iq+HSYmDjCsstgThmf5t4ii8eQm7CgS0SCA5QBezoRApnBaBSyCEhIHCLJEb4ZUd+2SqZSwzE+qpUpEQ9CC4qb01M8cRIQsh8zxiKsMtsn08nvlnrpkyAPj5AGJwMw3AtgGwJ/q2ExxvHsQB74KxfKBMblAyGmTHq4pc4/5GjQeUm6qE9FrAK4E8H6ie41GlkN/jTk6F5Ak2ueUpNmpkgfSMAAAENERAAsB3AHgZDoy0oFdFnBYpXPEBfU4beLRD6Z4qmumug+kIzPjaoeZfQDWAHgAQFam8hLh4MkwWjsHemyS2OF08IYrCjynzZ4zKTCzi5nXMvOnzBw16bevIxR95JOj7DNKb1PqXWa+HMDtAGoBXII0lxq0N2OfAmgA8Hsi2muMhudgesHPzNkA5gKoADADwFRoS8UHQO+x9wLoBNAB4AsAnwM4AOADIjLVxf8L9kdXUOE0IskAAAAASUVORK5CYII=)](https://codeberg.org/Ven/cord) [![Codeberg Mirror](https://img.shields.io/static/v1?style=for-the-badge&label=Codeberg%20Mirror&message=codeberg.org/Vee/cord&color=2185D0&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABmJLR0QA/wD/AP+gvaeTAAAKbUlEQVR4nNVae3AV5RX/nW/3Pva+b24e5HHzIICQKGoiYiW8NFBFgohaa6ctglpbFSujSGurzUinohWsOij/gGX6R2fqOK0d1FYTEZXaTrWCBbEikJCEyCvkeXNvkrunf+zdkJDkPnex/c3cmd29+53v/M6e73znnF2Cydj4Tntldzi6qrN/qKqzf2jy6b7BnL4B1dI7oMp9AyoRAIdVsNMqhlxWMZjtspzyK/Jhr036OMsm//bh2vzPzNSPzBD6xFutd7R0Dq758ky4orkjYuc05RCAkixbeEq2/UCJ1/LczxcX/c5IPfU5DMHmxpbCpu7o1k/b+xc1n43YjJI7EqV+W2RmvuPt0oDjB2vn5bQbITNjAzzdeKK8qTO0bU9T77zucNQUjzofHrvENWWu3aUBZfW6+ZOOZiIrbYXrmUXo9daX3v6i667O/iGRiRLpwqtIvKDc+0efJ3hb/UIaSkdGWgZ4sqGt9r2m3lc/P9HvSWe80ZiRp3TPL/UsX1+bvyvVsSkb4NE3WjbuPNj5SM8Fcvdk4bAKrqvwv7DxhuCPUxmXNIn6XSy3nWr6R8OhrqrU1btwqJ3m/bgwu/SqZJdEUgbYsuuka09b9/4Pm3tLMlPvwuAbpe6m+RcplfdcURBKdG9CA2zZddLV2Nx1+JO2vlxj1LswqCpynlxc6SxLZIS40bueWfy9vXvv/xt5APhXa1/u7v+EPqvfxXK8++IaoO2Vpn9+cLS33FjVLhw+bOotOX7q6N/i3TOhAX7y+rHN/+sBLxm8fah71k93tjw/0f/jGuDJxtZrdh7setA8tS4sdn7eef+v3mmfP95/Ywxw6x9Yev9I35/6Iubv83WVfl5a6Uu3VkoavZEo7TnS/Vo98xi+Yy6UKC3bDp7sd5ut1OWFDjyzNMib6oq5Oug0ezp8dqLfG3r92Nbzr48ywNONJ8obDnV/z2xlAk4ZW1aUqhaJIAvCb5YVqwFn3GBtCBoO9dz5TOPxUbnMKAM0dYa2d5lc2AgCNi8r5klui3aBgWynjE11QZbI3FV3NjQkjnYNbB+lj36wubGlcE9T71xTNQDw0Px8nlvmHl73GmfCrKCL19Tkmh4P9jT1LHz2vVP5+vmwAZq71a1m1/PXTPXwD68eS5KIEVUZd1yZwwumeEw1Qld/lJrPhF7Sz4cNsO+rUK2ZExd6rfj10iCPZ2GJCCoAZuCJxQUc9FvNVAX72kPX6ccC0Hp4zR0Ru1kT2mTCSzeXqn5l/EAniMAqoDLDYZWwqa5EVSzmhaKmsxHbLxvbbgdiBmjpHFxj2mwANlxXxBdPUib8nwgQgqAyEFUZxT4L1i/MN3UpHDsTWQvEDHDoTLjCrIluuyzAt8zMSkhGFhp5hrYUFk3z8IqZftOMcKRj4GIAEM80tFccM8n9Z+Qq+MXigqRIWCQCMzQvYIbKwH1X53FFnjkr88iZsLKpoXWa6BiIrjbDzF67hK23lKp2Obm1LAstPEZVjTwDkAio/2ZQ9dolw/VjAB0DfKfoCg9WGy2cADy1NMhBX2rR3CIRGICq8rAhAg4Jj9UWsDBhg+4MR6vF2VC0zGjB99fk8eJp3pQdyyrRMHF9KURVxswCB6+alWO4o3b2RyeLU32D2UYKnVPm5gfm5qWlrF0Wo4hzbCmoDNw0089XlboNNcLpvsFc0RtRDXuNle+x4Lkbi9PO6WWJIBFGEY+qjGjswtq5eVzosRilLnoiUavoH1INiTCyIDy/vETNcmRW1dl0L4gRVxmx3YFhlwnrry1QrZIxASE0yJIIDaiGSHt8UQFXF2Ve1zusYgzxkXGhyGvFvePUE+mgfyAqhGqAqKWVPv5udbYhSjmtkpYWq6OJqzFjqCpjTpmbl1Rk3klSGRBWmTISNC3Hjo1LgoYFJ0GA1aIVR+cTVxlQoS2Pb18a4PLszMKXzSJYuCySmq4Al03CiytKVYfBhYvLKk1IXE+XLRLhwZp81WlNf26HTFHhd0jhdAYTgKduCPLkgPHfQjitYkLiAIEZBDBlu2R6aF7euCV2Mgg45bDw2qWOdAavnp3D109PPdlJBvpTnYg4kVY3MDMuylVw62WJi63x4LHLZ0TAIR9OdWBVodPUclUQwWmT4hLXfgCIUDfDi6oiR8rzBJzyl8LnkD9KZVCOU8aLN5eoshnJ+Qh4bFJC4gztmEjgrtk5anaKnWWfXfpIuBTLjmSpSILw/E0laq7LuGxsIngVCYmIa96hLRG3TaZ1C/KTfjAEQLFIO8TPFk7aH/RZI8kMWrdgEs8udqXLKSUoMkEW4ETEQTRsoHyPlVZfmVw+Uuy3hR9bVHBQAMD0XPu/Ew24dqqH777K/La1DiKCxyYlRRzQymgG4+oyDxZOTdxZnp5r3wvEWmJ5btuL8W4uzbJh87LitLebdOFVpKSJx4IlwIzbL81CcYLO8iSX/IImGQCYae6Wg/2tXQNjNnW7LPDKyilqZd7ETU2zEBlifNTSS4i9PNFIx44x4jh2nZlBsUr0dN8QP/6XVhEaHJvnlfhtkXd/NF0BUextKRFXFznfGk+JDdcX8tdBHtDa6YpFsB4I9ac88omf8wbEgqa2XAIOme6bM35foqrQ+QZIKwGG80ifVbrXZZNGDfhOVYBvviS9JMMoaP3AEcQpPnHdOxiMGXkKbrx4dGfZY5c4T8H9+vmwAeqXFLXOKXW9r59fWuDA44sKv1byAOBzyCkTH+kdS2f4MLPgXJI0p9T17vrFxcf181GVxEUB+0qfIqt+RcKWFSWGNR4ygd4RTpW4HiCJgFWzstmnSPA7ZLU827pypPwxDB/687GXl1X6Vs6bbGz/LRN80hZCT+yLFZ0cgHED4egACeiXm89GsP9EePuzy4rvGil7jAGYmQDsBjDHUBYZ4GhHBMfORigd4rpnyIS9u6d4rqgnGrUtjCmmSYuOqwB0GcwjbWh9xviurpNnxnDA1IspMPe6bOL755MHJvhKjIgOA7jbJD4pw22Thj+kSIW47h2KRaydVezeP57sCdspRPQqgGeNJJIuBAE+ReJUiOv32mXaXjPZs21C2QnmXgdghyEsMoRfkVMiDgCywF/by9z3xJMb1wCxeHAPgDczZpAh/Iq+HSYmDjCsstgThmf5t4ii8eQm7CgS0SCA5QBezoRApnBaBSyCEhIHCLJEb4ZUd+2SqZSwzE+qpUpEQ9CC4qb01M8cRIQsh8zxiKsMtsn08nvlnrpkyAPj5AGJwMw3AtgGwJ/q2ExxvHsQB74KxfKBMblAyGmTHq4pc4/5GjQeUm6qE9FrAK4E8H6ie41GlkN/jTk6F5Ak2ueUpNmpkgfSMAAAENERAAsB3AHgZDoy0oFdFnBYpXPEBfU4beLRD6Z4qmumug+kIzPjaoeZfQDWAHgAQFam8hLh4MkwWjsHemyS2OF08IYrCjynzZ4zKTCzi5nXMvOnzBw16bevIxR95JOj7DNKb1PqXWa+HMDtAGoBXII0lxq0N2OfAmgA8Hsi2muMhudgesHPzNkA5gKoADADwFRoS8UHQO+x9wLoBNAB4AsAnwM4AOADIjLVxf8L9kdXUOE0IskAAAAASUVORK5CYII=)](https://codeberg.org/Vee/cord)
The cutest Discord client mod The cutest Discord client mod
![](https://user-images.githubusercontent.com/45497981/235015332-0453d3eb-1da6-4601-963e-ef5e454123a1.png) | ![image](https://github.com/Vendicated/Vencord/assets/45497981/706722b1-32de-4d99-bee9-93993b504334) |
*A screenshot of Vencord featuring the [ClearVision-v6 theme](https://github.com/ClearVision/ClearVision-v6) (Vencord does not come with it pre-installed, it is only an example)* | :--------------------------------------------------------------------------------------------------: |
| A screenshot of vencord showcasing the [vencord-theme](https://github.com/synqat/vencord-theme) |
## Features ## Features
@ -23,34 +24,30 @@ The cutest Discord client mod
## Installing / Uninstalling ## Installing / Uninstalling
Click the below button to install Vencord to the Discord Desktop app Visit https://vencord.dev/download
[![Download and run the Installer](https://img.shields.io/github/v/release/Vencord/Installer?label=Download%20Vencord%20Installer&style=for-the-badge)](https://github.com/Vencord/Installer#vencord-installer)
## Installing on Browser
[![Get it on the Firefox Webstore](https://blog.mozilla.org/addons/files/2015/11/get-the-addon.png)](https://addons.mozilla.org/en-GB/firefox/addon/vencord-web/) [![Get it on the Chrome Webstore](https://storage.googleapis.com/web-dev-uploads/image/WlD8wC6g8khYWPJUsQceQkhXSlv1/UV4C4ybeBTsZt43U4xis.png)](https://chrome.google.com/webstore/detail/vencord-web/cbghhgpcnddeihccjmnadmkaejncjndb)
Or use the [UserScript](https://raw.githubusercontent.com/Vencord/builds/main/Vencord.user.js) - Please note that the CSS Editor, Themes loaded from remote sources and co. will not work in the UserScript. Use the extension if you need any of those
<details>
<summary>Alternative Downloads</summary>
## Vencord Desktop
> **Warning**
> This is an alternative app. It currently doesn't support keybinds and possibly some more features. If you just want to install to the normal Discord Desktop app, scroll up
As an alternative to the Discord Desktop app, Vencord also has its own standalone Desktop app that is snappier and lighter than Discord's official Desktop app
[![Download Vencord Desktop](https://img.shields.io/github/v/release/Vencord/Desktop?label=Download%20Vencord%20Desktop&style=for-the-badge)](https://github.com/Vencord/Desktop#vencord-desktop)
</details>
## Join our Support/Community Server ## Join our Support/Community Server
https://discord.gg/D9uwnFnqmd https://discord.gg/D9uwnFnqmd
## Sponsors
| **Thanks a lot to all Vencord [sponsors](https://github.com/sponsors/Vendicated)!!** |
| :------------------------------------------------------------------------------------------: |
| [![](https://meow.vendicated.dev/sponsors.png)](https://github.com/sponsors/Vendicated) |
| *generated using [github-sponsor-graph](https://github.com/Vendicated/github-sponsor-graph)* |
## Star History
<a href="https://star-history.com/#Vendicated/Vencord&Timeline">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=Vendicated/Vencord&type=Timeline&theme=dark" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=Vendicated/Vencord&type=Timeline" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=Vendicated/Vencord&type=Timeline" />
</picture>
</a>
## Disclaimer ## Disclaimer
Discord is trademark of Discord Inc. and solely mentioned for the sake of descriptivity. Discord is trademark of Discord Inc. and solely mentioned for the sake of descriptivity.

View file

@ -62,7 +62,7 @@ function GM_fetch(url, opt) {
resp.arrayBuffer = () => blobTo("arrayBuffer", blob); resp.arrayBuffer = () => blobTo("arrayBuffer", blob);
resp.text = () => blobTo("text", blob); resp.text = () => blobTo("text", blob);
resp.json = async () => JSON.parse(await blobTo("text", blob)); resp.json = async () => JSON.parse(await blobTo("text", blob));
resp.headers = new Headers(parseHeaders(resp.responseHeaders)); resp.headers = parseHeaders(resp.responseHeaders);
resp.ok = resp.status >= 200 && resp.status < 300; resp.ok = resp.status >= 200 && resp.status < 300;
resolve(resp); resolve(resp);
}; };

View file

@ -19,10 +19,14 @@
/// <reference path="../src/modules.d.ts" /> /// <reference path="../src/modules.d.ts" />
/// <reference path="../src/globals.d.ts" /> /// <reference path="../src/globals.d.ts" />
import monacoHtml from "~fileContent/../src/components/monacoWin.html"; import monacoHtmlLocal from "file://monacoWin.html?minify";
import monacoHtmlCdn from "file://../src/main/monacoWin.html?minify";
import * as DataStore from "../src/api/DataStore"; import * as DataStore from "../src/api/DataStore";
import { debounce } from "../src/utils"; import { debounce } from "../src/utils";
import { EXTENSION_BASE_URL } from "../src/utils/web-metadata";
import { getTheme, Theme } from "../src/utils/discord"; import { getTheme, Theme } from "../src/utils/discord";
import { getThemeInfo } from "../src/main/themes";
import { Settings } from "../src/Vencord";
// Discord deletes this so need to store in variable // Discord deletes this so need to store in variable
const { localStorage } = window; const { localStorage } = window;
@ -34,8 +38,21 @@ const NOOP_ASYNC = async () => { };
const setCssDebounced = debounce((css: string) => VencordNative.quickCss.set(css)); const setCssDebounced = debounce((css: string) => VencordNative.quickCss.set(css));
const themeStore = DataStore.createStore("VencordThemes", "VencordThemeData");
// probably should make this less cursed at some point // probably should make this less cursed at some point
window.VencordNative = { window.VencordNative = {
themes: {
uploadTheme: (fileName: string, fileData: string) => DataStore.set(fileName, fileData, themeStore),
deleteTheme: (fileName: string) => DataStore.del(fileName, themeStore),
getThemesDir: async () => "",
getThemesList: () => DataStore.entries(themeStore).then(entries =>
entries.map(([name, css]) => getThemeInfo(css, name.toString()))
),
getThemeData: (fileName: string) => DataStore.get(fileName, themeStore),
getSystemValues: async () => ({}),
},
native: { native: {
getVersions: () => ({}), getVersions: () => ({}),
openExternal: async (url) => void open(url, "_blank") openExternal: async (url) => void open(url, "_blank")
@ -57,6 +74,7 @@ window.VencordNative = {
addChangeListener(cb) { addChangeListener(cb) {
cssListeners.add(cb); cssListeners.add(cb);
}, },
addThemeChangeListener: NOOP,
openFile: NOOP_ASYNC, openFile: NOOP_ASYNC,
async openEditor() { async openEditor() {
const features = `popup,width=${Math.min(window.innerWidth, 1000)},height=${Math.min(window.innerHeight, 1000)}`; const features = `popup,width=${Math.min(window.innerWidth, 1000)},height=${Math.min(window.innerHeight, 1000)}`;
@ -66,6 +84,7 @@ window.VencordNative = {
return; return;
} }
win.baseUrl = EXTENSION_BASE_URL;
win.setCss = setCssDebounced; win.setCss = setCssDebounced;
win.getCurrentCss = () => VencordNative.quickCss.get(); win.getCurrentCss = () => VencordNative.quickCss.get();
win.getTheme = () => win.getTheme = () =>
@ -73,13 +92,22 @@ window.VencordNative = {
? "vs-light" ? "vs-light"
: "vs-dark"; : "vs-dark";
win.document.write(monacoHtml); win.document.write(IS_EXTENSION ? monacoHtmlLocal : monacoHtmlCdn);
}, },
}, },
settings: { settings: {
get: () => localStorage.getItem("VencordSettings") || "{}", get: () => {
set: async (s: string) => localStorage.setItem("VencordSettings", s), try {
return JSON.parse(localStorage.getItem("VencordSettings") || "{}");
} catch (e) {
console.error("Failed to parse settings from localStorage: ", e);
return {};
}
},
set: async (s: Settings) => localStorage.setItem("VencordSettings", JSON.stringify(s)),
getSettingsDir: async () => "LocalStorage" getSettingsDir: async () => "LocalStorage"
} },
pluginHelpers: {} as any,
}; };

View file

@ -2,18 +2,22 @@ if (typeof browser === "undefined") {
var browser = chrome; var browser = chrome;
} }
const script = document.createElement("script");
script.src = browser.runtime.getURL("dist/Vencord.js");
const style = document.createElement("link"); const style = document.createElement("link");
style.type = "text/css"; style.type = "text/css";
style.rel = "stylesheet"; style.rel = "stylesheet";
style.href = browser.runtime.getURL("dist/Vencord.css"); style.href = browser.runtime.getURL("dist/Vencord.css");
document.documentElement.append(script);
document.addEventListener( document.addEventListener(
"DOMContentLoaded", "DOMContentLoaded",
() => document.documentElement.append(style), () => {
document.documentElement.append(style);
window.postMessage({
type: "vencord:meta",
meta: {
EXTENSION_VERSION: browser.runtime.getManifest().version,
EXTENSION_BASE_URL: browser.runtime.getURL(""),
}
});
},
{ once: true } { once: true }
); );

View file

@ -1,6 +1,6 @@
{ {
"manifest_version": 3, "manifest_version": 3,
"minimum_chrome_version": "91", "minimum_chrome_version": "111",
"name": "Vencord Web", "name": "Vencord Web",
"description": "The cutest Discord mod now in your browser", "description": "The cutest Discord mod now in your browser",
@ -22,13 +22,21 @@
"run_at": "document_start", "run_at": "document_start",
"matches": ["*://*.discord.com/*"], "matches": ["*://*.discord.com/*"],
"js": ["content.js"], "js": ["content.js"],
"all_frames": true "all_frames": true,
"world": "ISOLATED"
},
{
"run_at": "document_start",
"matches": ["*://*.discord.com/*"],
"js": ["dist/Vencord.js"],
"all_frames": true,
"world": "MAIN"
} }
], ],
"web_accessible_resources": [ "web_accessible_resources": [
{ {
"resources": ["dist/Vencord.js", "dist/Vencord.css"], "resources": ["dist/*", "third-party/*"],
"matches": ["*://*.discord.com/*"] "matches": ["*://*.discord.com/*"]
} }
], ],

View file

@ -22,7 +22,15 @@
"run_at": "document_start", "run_at": "document_start",
"matches": ["*://*.discord.com/*"], "matches": ["*://*.discord.com/*"],
"js": ["content.js"], "js": ["content.js"],
"all_frames": true "all_frames": true,
"world": "ISOLATED"
},
{
"run_at": "document_start",
"matches": ["*://*.discord.com/*"],
"js": ["dist/Vencord.js"],
"all_frames": true,
"world": "MAIN"
} }
], ],
@ -35,7 +43,7 @@
"browser_specific_settings": { "browser_specific_settings": {
"gecko": { "gecko": {
"id": "vencord-firefox@vendicated.dev", "id": "vencord-firefox@vendicated.dev",
"strict_min_version": "91.0" "strict_min_version": "128.0"
} }
} }
} }

43
browser/monaco.ts Normal file
View file

@ -0,0 +1,43 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2023 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import "./patch-worker";
import * as monaco from "monaco-editor/esm/vs/editor/editor.main.js";
declare global {
const baseUrl: string;
const getCurrentCss: () => Promise<string>;
const setCss: (css: string) => void;
const getTheme: () => string;
}
const BASE = "/dist/monaco/vs";
self.MonacoEnvironment = {
getWorkerUrl(_moduleId: unknown, label: string) {
const path = label === "css" ? "/language/css/css.worker.js" : "/editor/editor.worker.js";
return new URL(BASE + path, baseUrl).toString();
}
};
getCurrentCss().then(css => {
const editor = monaco.editor.create(
document.getElementById("container")!,
{
value: css,
language: "css",
theme: getTheme(),
}
);
editor.onDidChangeModelContent(() =>
setCss(editor.getValue())
);
window.addEventListener("resize", () => {
// make monaco re-layout
editor.layout();
});
});

37
browser/monacoWin.html Normal file
View file

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Vencord QuickCSS Editor</title>
<style>
html,
body,
#container {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="container"></div>
<script>
const script = document.createElement("script");
script.src = new URL("/dist/monaco/index.js", baseUrl);
const style = document.createElement("link");
style.type = "text/css";
style.rel = "stylesheet";
style.href = new URL("/dist/monaco/index.css", baseUrl);
document.body.append(style, script);
</script>
</body>
</html>

135
browser/patch-worker.js Normal file
View file

@ -0,0 +1,135 @@
/*
Copyright 2013 Rob Wu <gwnRob@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Target: Chrome 20+
// W3-compliant Worker proxy.
// This module replaces the global Worker object.
// When invoked, the default Worker object is called.
// If this call fails with SECURITY_ERR, the script is fetched
// using async XHR, and transparently proxies all calls and
// setters/getters to the new Worker object.
// Note: This script does not magically circumvent the Same origin policy.
(function () {
'use strict';
var Worker_ = window.Worker;
var URL = window.URL || window.webkitURL;
// Create dummy worker for the following purposes:
// 1. Don't override the global Worker object if the fallback isn't
// going to work (future API changes?)
// 2. Use it to trigger early validation of postMessage calls
// Note: Blob constructor is supported since Chrome 20, but since
// some of the used Chrome APIs are only supported as of Chrome 20,
// I don't bother adding a BlobBuilder fallback.
var dummyWorker = new Worker_(
URL.createObjectURL(new Blob([], { type: 'text/javascript' })));
window.Worker = function Worker(scriptURL) {
if (arguments.length === 0) {
throw new TypeError('Not enough arguments');
}
try {
return new Worker_(scriptURL);
} catch (e) {
if (e.code === 18/*DOMException.SECURITY_ERR*/) {
return new WorkerXHR(scriptURL);
} else {
throw e;
}
}
};
// Bind events and replay queued messages
function bindWorker(worker, workerURL) {
if (worker._terminated) {
return;
}
worker.Worker = new Worker_(workerURL);
worker.Worker.onerror = worker._onerror;
worker.Worker.onmessage = worker._onmessage;
var o;
while ((o = worker._replayQueue.shift())) {
worker.Worker[o.method].apply(worker.Worker, o.arguments);
}
while ((o = worker._messageQueue.shift())) {
worker.Worker.postMessage.apply(worker.Worker, o);
}
}
function WorkerXHR(scriptURL) {
var worker = this;
var x = new XMLHttpRequest();
x.responseType = 'blob';
x.onload = function () {
// http://stackoverflow.com/a/10372280/938089
var workerURL = URL.createObjectURL(x.response);
bindWorker(worker, workerURL);
};
x.open('GET', scriptURL);
x.send();
worker._replayQueue = [];
worker._messageQueue = [];
}
WorkerXHR.prototype = {
constructor: Worker_,
terminate: function () {
if (!this._terminated) {
this._terminated = true;
if (this.Worker)
this.Worker.terminate();
}
},
postMessage: function (message, transfer) {
if (!(this instanceof WorkerXHR))
throw new TypeError('Illegal invocation');
if (this.Worker) {
this.Worker.postMessage.apply(this.Worker, arguments);
} else {
// Trigger validation:
dummyWorker.postMessage(message);
// Alright, push the valid message to the queue.
this._messageQueue.push(arguments);
}
}
};
// Implement the EventTarget interface
[
'addEventListener',
'removeEventListener',
'dispatchEvent'
].forEach(function (method) {
WorkerXHR.prototype[method] = function () {
if (!(this instanceof WorkerXHR)) {
throw new TypeError('Illegal invocation');
}
if (this.Worker) {
this.Worker[method].apply(this.Worker, arguments);
} else {
this._replayQueue.push({ method: method, arguments: arguments });
}
};
});
Object.defineProperties(WorkerXHR.prototype, {
onmessage: {
get: function () { return this._onmessage || null; },
set: function (func) {
this._onmessage = typeof func === 'function' ? func : null;
}
},
onerror: {
get: function () { return this._onerror || null; },
set: function (func) {
this._onerror = typeof func === 'function' ? func : null;
}
}
});
})();

View file

@ -5,6 +5,7 @@
// @author Vendicated (https://github.com/Vendicated) // @author Vendicated (https://github.com/Vendicated)
// @namespace https://github.com/Vendicated/Vencord // @namespace https://github.com/Vendicated/Vencord
// @supportURL https://github.com/Vendicated/Vencord // @supportURL https://github.com/Vendicated/Vencord
// @icon https://raw.githubusercontent.com/Vendicated/Vencord/refs/heads/main/browser/icon.png
// @license GPL-3.0 // @license GPL-3.0
// @match *://*.discord.com/* // @match *://*.discord.com/*
// @grant GM_xmlhttpRequest // @grant GM_xmlhttpRequest

View file

@ -1,98 +0,0 @@
> **Warning**
> These instructions are only for advanced users. If you're not a Developer, you should use our [graphical installer](https://github.com/Vendicated/VencordInstaller#usage) instead.
# Installation Guide
Welcome to Megu's Installation Guide! In this file, you will learn about how to download, install, and uninstall Vencord!
## Sections
- [Installation Guide](#installation-guide)
- [Sections](#sections)
- [Dependencies](#dependencies)
- [Installing Vencord](#installing-vencord)
- [Updating Vencord](#updating-vencord)
- [Uninstalling Vencord](#uninstalling-vencord)
## Dependencies
- Install Git from https://git-scm.com/download
- Install Node.JS LTS from here: https://nodejs.dev/en/
## Installing Vencord
Install `pnpm`:
> :exclamation: This next command may need to be run as admin/root depending on your system, and you may need to close and reopen your terminal for pnpm to be in your PATH.
```shell
npm i -g pnpm
```
> :exclamation: **IMPORTANT** Make sure you aren't using an admin/root terminal from here onwards. It **will** mess up your Discord/Vencord instance and you **will** most likely have to reinstall.
Clone Vencord:
```shell
git clone https://github.com/Vendicated/Vencord
cd Vencord
```
Install dependencies:
```shell
pnpm install --frozen-lockfile
```
Build Vencord:
```shell
pnpm build
```
Inject vencord into your client:
```shell
pnpm inject
```
Then fully close Discord from your taskbar or task manager, and restart it. Vencord should be injected - you can check this by looking for the Vencord section in Discord settings.
## Updating Vencord
If you're using Discord already, go into the `Updater` tab in settings.
Sometimes it may be neccessary to manually update if the GUI updater fails.
To pull latest changes:
```shell
git pull
```
If this fails, you likely need to reset your local changes to vencord to resolve merge errors:
> :exclamation: This command will remove any local changes you've made to vencord. Make sure you back up if you made any code changes you don't want to lose!
```shell
git reset --hard
git pull
```
and then to build the changes:
```shell
pnpm build
```
Then just refresh your client
## Uninstalling Vencord
Simply run:
```shell
pnpm uninject
```
If you need more help, ask in the support channel in our [Discord Server](https://discord.gg/D9uwnFnqmd).

View file

@ -1,111 +0,0 @@
# Plugins Guide
Welcome to Megu's Plugin Guide! In this file, you will learn about how to write your own plugin!
You don't need to run `pnpm build` every time you make a change. Instead, use `pnpm watch` - this will auto-compile Vencord whenever you make a change. If using code patches (recommended), you will need to CTRL+R to load the changes.
## Plugin Entrypoint
> If it doesn't already exist, create a folder called `userplugins` in the `src` directory of this repo.
1. Create a folder in `src/userplugins/` with the name of your plugin. For example, `src/userplugins/epicPlugin/` - All of your plugin files will go here.
2. Create a file in that folder called `index.ts`
3. In `index.ts`, copy-paste the following template code:
```ts
import definePlugin from "@utils/types";
export default definePlugin({
name: "Epic Plugin",
description: "This plugin is absolutely epic",
authors: [
{
id: 12345n,
name: "Your Name",
},
],
patches: [],
// Delete these two below if you are only using code patches
start() {},
stop() {},
});
```
Change the name, description, and authors to your own information.
Replace `12345n` with your user ID ending in `n` (e.g., `545581357812678656n`). If you don't want to share your Discord account, use `0n` instead!
## How Plugins Work In Vencord
Vencord uses a different way of making mods than you're used to.
Instead of monkeypatching webpack, we directly modify the code before Discord loads it.
This is _significantly_ more efficient than monkeypatching webpack, and is surprisingly easy, but it may be confusing at first.
## Making your patch
For an in-depth guide into patching code, see [CONTRIBUTING.md](../CONTRIBUTING.md)
in the `index.ts` file we made earlier, you'll see a `patches` array.
> You'll see examples of how patches are used in all the existing plugins, and it'll be easier to understand by looking at those examples, so do that first, and then return here!
> For a good example of a plugin using code patches AND runtime patching, check `src/plugins/unindent.ts`, which uses code patches to run custom runtime code.
One of the patches in the `isStaff` plugin, looks like this:
```ts
{
match: /(\w+)\.isStaff=function\(\){return\s*!1};/,
replace: "$1.isStaff=function(){return true};",
},
```
The above regex matches the string in discord that will look something like:
```js
abc.isStaff = function () {
return !1;
};
```
Remember that Discord code is minified, so there won't be any newlines, and there will only be spaces where necessary. So the source code looks something like:
```
abc.isStaff=function(){return!1;}
```
You can find these snippets by opening the devtools (`ctrl+shift+i`) and pressing `ctrl+shift+f`, searching for what you're looking to modify in there, and beautifying the file to make it more readable.
In the `match` regex in the example shown above, you'll notice at the start there is a `(\w+)`.
Anything in the brackets will be accessible in the `replace` string using `$<number>`. e.g., the first pair of brackets will be `$1`, the second will be `$2`, etc.
The replacement string we used is:
```
"$1.isStaff=function(){return true;};"
```
Which, using the above example, would replace the code with:
> **Note**
> In this example, `$1` becomes `abc`
```js
abc.isStaff = function () {
return true;
};
```
The match value _can_ be a string, rather than regex, however usually regex will be better suited, as it can work with unknown values, whereas strings must be exact matches.
Once you've made your plugin, make sure you run `pnpm test` and make sure your code is nice and clean!
If you want to publish your plugin into the Vencord repo, move your plugin from `src/userplugins` into the `src/plugins` folder and open a PR!
> **Warning**
> Make sure you've read [CONTRIBUTING.md](../CONTRIBUTING.md) before opening a PR
If you need more help, ask in the support channel in our [Discord Server](https://discord.gg/D9uwnFnqmd).

147
eslint.config.mjs Normal file
View file

@ -0,0 +1,147 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2023 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import stylistic from "@stylistic/eslint-plugin";
import pathAlias from "eslint-plugin-path-alias";
import react from "eslint-plugin-react";
import header from "eslint-plugin-simple-header";
import simpleImportSort from "eslint-plugin-simple-import-sort";
import unusedImports from "eslint-plugin-unused-imports";
import tseslint from "typescript-eslint";
export default tseslint.config(
{ ignores: ["dist", "browser", "packages/vencord-types"] },
{
files: ["src/**/*.{tsx,ts,mts,mjs,js,jsx}", "eslint.config.mjs"],
settings: {
react: {
version: "18"
}
},
...react.configs.flat.recommended,
rules: {
...react.configs.flat.recommended.rules,
"react/react-in-jsx-scope": "off",
"react/prop-types": "off",
"react/display-name": "off",
"react/no-unescaped-entities": "off",
}
},
{
files: ["src/**/*.{tsx,ts,mts,mjs,js,jsx}", "eslint.config.mjs"],
plugins: {
"simple-header": header,
"@stylistic": stylistic,
"@typescript-eslint": tseslint.plugin,
"simple-import-sort": simpleImportSort,
"unused-imports": unusedImports,
"path-alias": pathAlias
},
settings: {
"import/resolver": {
map: [
["@webpack", "./src/webpack"],
["@webpack/common", "./src/webpack/common"],
["@utils", "./src/utils"],
["@api", "./src/api"],
["@components", "./src/components"]
]
}
},
languageOptions: {
parser: tseslint.parser,
parserOptions: {
project: ["./tsconfig.json"],
tsconfigRootDir: import.meta.dirname
}
},
rules: {
/*
* Since it's only been a month and Vencord has already been stolen
* by random skids who rebranded it to "AlphaCord" and erased all license
* information
*/
"simple-header/header": [
"error",
{
"files": ["scripts/header-new.txt", "scripts/header-old.txt"],
"templates": { "author": [".*", "Vendicated and contributors"] }
}
],
// Style Rules
"@stylistic/jsx-quotes": ["error", "prefer-double"],
"@stylistic/quotes": ["error", "double", { "avoidEscape": true }],
"@stylistic/no-mixed-spaces-and-tabs": "error",
"@stylistic/arrow-parens": ["error", "as-needed"],
"@stylistic/eol-last": ["error", "always"],
"@stylistic/no-multi-spaces": "error",
"@stylistic/no-trailing-spaces": "error",
"@stylistic/no-whitespace-before-property": "error",
"@stylistic/semi": ["error", "always"],
"@stylistic/semi-style": ["error", "last"],
"@stylistic/space-in-parens": ["error", "never"],
"@stylistic/block-spacing": ["error", "always"],
"@stylistic/object-curly-spacing": ["error", "always"],
"@stylistic/spaced-comment": ["error", "always", { "markers": ["!"] }],
"@stylistic/no-extra-semi": "error",
// TS Rules
"@stylistic/func-call-spacing": ["error", "never"],
// ESLint Rules
"yoda": "error",
"eqeqeq": ["error", "always", { "null": "ignore" }],
"prefer-destructuring": ["error", {
"VariableDeclarator": { "array": false, "object": true },
"AssignmentExpression": { "array": false, "object": false }
}],
"operator-assignment": ["error", "always"],
"no-useless-computed-key": "error",
"no-unneeded-ternary": ["error", { "defaultAssignment": false }],
"no-invalid-regexp": "error",
"no-constant-condition": ["error", { "checkLoops": false }],
"no-duplicate-imports": "error",
"@typescript-eslint/dot-notation": [
"error",
{
"allowPrivateClassPropertyAccess": true,
"allowProtectedClassPropertyAccess": true
}
],
"no-useless-escape": [
"error",
{
"extra": "i"
}
],
"no-fallthrough": "error",
"for-direction": "error",
"no-async-promise-executor": "error",
"no-cond-assign": "error",
"no-dupe-else-if": "error",
"no-duplicate-case": "error",
"no-irregular-whitespace": "error",
"no-loss-of-precision": "error",
"no-misleading-character-class": "error",
"no-prototype-builtins": "error",
"no-regex-spaces": "error",
"no-shadow-restricted-names": "error",
"no-unexpected-multiline": "error",
"no-unsafe-optional-chaining": "error",
"no-useless-backreference": "error",
"use-isnan": "error",
"prefer-const": "error",
"prefer-spread": "error",
// Plugin Rules
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error",
"unused-imports/no-unused-imports": "error",
"path-alias/no-relative": "error"
}
}
);

View file

@ -1,7 +1,7 @@
{ {
"name": "vencord", "name": "vencord",
"private": "true", "private": "true",
"version": "1.2.9", "version": "1.11.4",
"description": "The cutest Discord client mod", "description": "The cutest Discord client mod",
"homepage": "https://github.com/Vendicated/Vencord#readme", "homepage": "https://github.com/Vendicated/Vencord#readme",
"bugs": { "bugs": {
@ -11,65 +11,80 @@
"type": "git", "type": "git",
"url": "git+https://github.com/Vendicated/Vencord.git" "url": "git+https://github.com/Vendicated/Vencord.git"
}, },
"license": "GPL-3.0", "license": "GPL-3.0-or-later",
"author": "Vendicated", "author": "Vendicated",
"directories": {
"doc": "docs"
},
"scripts": { "scripts": {
"build": "node scripts/build/build.mjs", "build": "node --require=./scripts/suppressExperimentalWarnings.js scripts/build/build.mjs",
"buildStandalone": "pnpm build --standalone",
"buildWeb": "node --require=./scripts/suppressExperimentalWarnings.js scripts/build/buildWeb.mjs", "buildWeb": "node --require=./scripts/suppressExperimentalWarnings.js scripts/build/buildWeb.mjs",
"buildWebStandalone": "pnpm buildWeb --standalone",
"buildReporter": "pnpm buildWebStandalone --reporter --skip-extension",
"buildReporterDesktop": "pnpm build --reporter",
"watch": "pnpm build --watch",
"dev": "pnpm watch",
"watchWeb": "pnpm buildWeb --watch",
"generatePluginJson": "tsx scripts/generatePluginList.ts", "generatePluginJson": "tsx scripts/generatePluginList.ts",
"generateTypes": "tspc --emitDeclarationOnly --declaration --outDir packages/vencord-types",
"inject": "node scripts/runInstaller.mjs", "inject": "node scripts/runInstaller.mjs",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx --ignore-pattern src/userplugins", "uninject": "node scripts/runInstaller.mjs",
"lint": "eslint",
"lint-styles": "stylelint \"src/**/*.css\" --ignore-pattern src/userplugins", "lint-styles": "stylelint \"src/**/*.css\" --ignore-pattern src/userplugins",
"lint:fix": "pnpm lint --fix", "lint:fix": "pnpm lint --fix",
"test": "pnpm build && pnpm lint && pnpm lint-styles && pnpm testTsc && pnpm generatePluginJson", "test": "pnpm buildStandalone && pnpm lint && pnpm lint-styles && pnpm testTsc && pnpm generatePluginJson",
"testWeb": "pnpm lint && pnpm buildWeb && pnpm testTsc", "testWeb": "pnpm lint && pnpm buildWeb && pnpm testTsc",
"testTsc": "tsc --noEmit", "testTsc": "tsc --noEmit"
"uninject": "node scripts/runInstaller.mjs",
"watch": "node scripts/build/build.mjs --watch"
}, },
"dependencies": { "dependencies": {
"@intrnl/xxhash64": "^0.1.2",
"@sapphi-red/web-noise-suppressor": "0.3.5",
"@vap/core": "0.0.12", "@vap/core": "0.0.12",
"@vap/shiki": "0.10.5", "@vap/shiki": "0.10.5",
"fflate": "^0.7.4", "fflate": "^0.8.2",
"nanoid": "^4.0.2", "gifenc": "github:mattdesl/gifenc#64842fca317b112a8590f8fef2bf3825da8f6fe3",
"monaco-editor": "^0.52.2",
"nanoid": "^5.0.9",
"virtual-merge": "^1.0.1" "virtual-merge": "^1.0.1"
}, },
"devDependencies": { "devDependencies": {
"@types/diff": "^5.0.3", "@stylistic/eslint-plugin": "^2.12.1",
"@types/lodash": "^4.14.194", "@types/chrome": "^0.0.287",
"@types/node": "^18.16.3", "@types/diff": "^6.0.0",
"@types/react": "^18.2.0", "@types/lodash": "^4.17.14",
"@types/react-dom": "^18.2.1", "@types/node": "^22.10.5",
"@types/yazl": "^2.4.2", "@types/react": "^19.0.2",
"@typescript-eslint/eslint-plugin": "^5.59.1", "@types/react-dom": "^19.0.2",
"@typescript-eslint/parser": "^5.59.1", "@types/yazl": "^2.4.5",
"diff": "^5.1.0", "diff": "^7.0.0",
"discord-types": "^1.3.26", "discord-types": "^1.3.26",
"esbuild": "^0.15.18", "esbuild": "^0.15.18",
"eslint": "^8.28.0", "eslint": "^9.17.0",
"eslint-import-resolver-alias": "^1.1.2", "eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-header": "^3.1.1", "eslint-plugin-path-alias": "2.1.0",
"eslint-plugin-path-alias": "^1.0.0", "eslint-plugin-react": "^7.37.3",
"eslint-plugin-simple-import-sort": "^10.0.0", "eslint-plugin-simple-header": "^1.2.1",
"eslint-plugin-unused-imports": "^2.0.0", "eslint-plugin-simple-import-sort": "^12.1.1",
"highlight.js": "10.6.0", "eslint-plugin-unused-imports": "^4.1.4",
"moment": "^2.29.4", "highlight.js": "11.7.0",
"puppeteer-core": "^19.11.1", "html-minifier-terser": "^7.2.0",
"moment": "^2.22.2",
"puppeteer-core": "^23.11.1",
"standalone-electron-types": "^1.0.0", "standalone-electron-types": "^1.0.0",
"stylelint": "^15.6.0", "stylelint": "^16.12.0",
"stylelint-config-standard": "^33.0.0", "stylelint-config-standard": "^36.0.1",
"tsx": "^3.12.7", "ts-patch": "^3.3.0",
"type-fest": "^3.9.0", "ts-pattern": "^5.6.0",
"typescript": "^5.0.4" "tsx": "^4.19.2",
"type-fest": "^4.31.0",
"typescript": "^5.7.2",
"typescript-eslint": "^8.19.0",
"typescript-transform-paths": "^3.5.3",
"zip-local": "^0.3.5"
}, },
"packageManager": "pnpm@8.1.1", "packageManager": "pnpm@9.1.0",
"pnpm": { "pnpm": {
"patchedDependencies": { "patchedDependencies": {
"eslint-plugin-path-alias@1.0.0": "patches/eslint-plugin-path-alias@1.0.0.patch", "eslint@9.17.0": "patches/eslint@9.17.0.patch",
"eslint@8.28.0": "patches/eslint@8.28.0.patch" "eslint-plugin-path-alias@2.1.0": "patches/eslint-plugin-path-alias@2.1.0.patch"
}, },
"peerDependencyRules": { "peerDependencyRules": {
"ignoreMissing": [ "ignoreMissing": [
@ -89,10 +104,10 @@
"build": { "build": {
"overwriteDest": true "overwriteDest": true
}, },
"sourceDir": "./dist/extension-v2-unpacked" "sourceDir": "./dist/firefox-unpacked"
}, },
"engines": { "engines": {
"node": ">=18", "node": ">=18",
"pnpm": ">=8" "pnpm": ">=9"
} }
} }

7
packages/vencord-types/.gitignore vendored Normal file
View file

@ -0,0 +1,7 @@
*
!.*ignore
!package.json
!*.md
!prepare.ts
!index.d.ts
!globals.d.ts

View file

@ -0,0 +1,4 @@
node_modules
prepare.ts
.gitignore
HOW2PUB.md

View file

@ -0,0 +1,5 @@
# How to publish
1. run `pnpm generateTypes` in the project root
2. bump package.json version
3. npm publish

View file

@ -0,0 +1,11 @@
# Vencord Types
Typings for Vencord's api, published to npm
```sh
npm i @vencord/types
yarn add @vencord/types
pnpm add @vencord/types
```

24
packages/vencord-types/globals.d.ts vendored Normal file
View file

@ -0,0 +1,24 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2022 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare global {
export var VencordNative: typeof import("./VencordNative").default;
export var Vencord: typeof import("./Vencord");
}
export { };

5
packages/vencord-types/index.d.ts vendored Normal file
View file

@ -0,0 +1,5 @@
/* eslint-disable */
/// <reference path="Vencord.d.ts" />
/// <reference path="globals.d.ts" />
/// <reference path="modules.d.ts" />

View file

@ -0,0 +1,28 @@
{
"name": "@vencord/types",
"private": false,
"version": "0.1.3",
"description": "",
"types": "index.d.ts",
"scripts": {
"prepublishOnly": "tsx ./prepare.ts",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "Vencord",
"license": "GPL-3.0",
"devDependencies": {
"@types/fs-extra": "^11.0.4",
"fs-extra": "^11.2.0",
"tsx": "^3.12.6"
},
"dependencies": {
"@types/lodash": "^4.14.191",
"@types/node": "^18.11.18",
"@types/react": "^18.2.0",
"@types/react-dom": "^18.0.10",
"discord-types": "^1.3.26",
"standalone-electron-types": "^1.0.0",
"type-fest": "^3.5.3"
}
}

View file

@ -0,0 +1,47 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { cpSync, moveSync, readdirSync, rmSync } from "fs-extra";
import { join } from "path";
readdirSync(join(__dirname, "src"))
.forEach(child => moveSync(join(__dirname, "src", child), join(__dirname, child), { overwrite: true }));
const VencordSrc = join(__dirname, "..", "..", "src");
for (const file of ["preload.d.ts", "userplugins", "main", "debug", "src", "browser", "scripts"]) {
rmSync(join(__dirname, file), { recursive: true, force: true });
}
function copyDtsFiles(from: string, to: string) {
for (const file of readdirSync(from, { withFileTypes: true })) {
// bad
if (from === VencordSrc && file.name === "globals.d.ts") continue;
const fullFrom = join(from, file.name);
const fullTo = join(to, file.name);
if (file.isDirectory()) {
copyDtsFiles(fullFrom, fullTo);
} else if (file.name.endsWith(".d.ts")) {
cpSync(fullFrom, fullTo);
}
}
}
copyDtsFiles(VencordSrc, __dirname);

View file

@ -1,13 +0,0 @@
diff --git a/lib/rules/no-relative.js b/lib/rules/no-relative.js
index 71594c83f1f4f733ffcc6047d7f7084348335dbe..d8623d87c89499c442171db3272cba07c9efabbe 100644
--- a/lib/rules/no-relative.js
+++ b/lib/rules/no-relative.js
@@ -41,7 +41,7 @@ module.exports = {
ImportDeclaration(node) {
const importPath = node.source.value;
- if (!/^(\.?\.\/)/.test(importPath)) {
+ if (!/^(\.\.\/)/.test(importPath)) {
return;
}

View file

@ -0,0 +1,14 @@
diff --git a/dist/index.js b/dist/index.js
index 67de6fb139070fd0e49beca65e3b63c531202e16..aa2883c8126e4952a42872ee920f59547a066430 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -1 +1 @@
-var C=Object.create;var f=Object.defineProperty;var I=Object.getOwnPropertyDescriptor;var U=Object.getOwnPropertyNames;var S=Object.getPrototypeOf,F=Object.prototype.hasOwnProperty;var $=(e,t)=>{for(var r in t)f(e,r,{get:t[r],enumerable:!0})},y=(e,t,r,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of U(t))!F.call(e,s)&&s!==r&&f(e,s,{get:()=>t[s],enumerable:!(i=I(t,s))||i.enumerable});return e};var b=(e,t,r)=>(r=e!=null?C(S(e)):{},y(t||!e||!e.__esModule?f(r,"default",{value:e,enumerable:!0}):r,e)),D=e=>y(f({},"__esModule",{value:!0}),e);var N={};$(N,{default:()=>J});module.exports=D(N);var h="eslint-plugin-path-alias",v="2.0.0";var l=require("path"),M=b(require("nanomatch"));function j(e){return`https://github/com/msfragala/eslint-plugin-path-alias/blob/master/docs/rules/${e}.md`}var R=require("get-tsconfig"),a=require("path"),w=b(require("find-pkg")),O=require("fs");function P(e){if(e.options[0]?.paths)return z(e);let t=e.getFilename?.()??e.filename,r=(0,R.getTsconfig)(t);if(r?.config?.compilerOptions?.paths)return q(r);let i=w.default.sync((0,a.dirname)(t));if(!i)return;let s=JSON.parse((0,O.readFileSync)(i).toString());if(s?.imports)return L(s,i)}function L(e,t){let r=new Map,i=e.imports??{},s=(0,a.dirname)(t);return Object.entries(i).forEach(([o,n])=>{if(!n||typeof n!="string")return;let p=(0,a.resolve)(s,n);r.set(o,[p])}),r}function q(e){let t=new Map,r=e?.config?.compilerOptions?.paths??{},i=(0,a.dirname)(e.path);return e.config.compilerOptions?.baseUrl&&(i=(0,a.resolve)((0,a.dirname)(e.path),e.config.compilerOptions.baseUrl)),Object.entries(r).forEach(([s,o])=>{s=s.replace(/\/\*$/,""),o=o.map(n=>(0,a.resolve)(i,n.replace(/\/\*$/,""))),t.set(s,o)}),t}function z(e){let t=new Map,r=e.options[0]?.paths??{};return Object.entries(r).forEach(([i,s])=>{if(!s||typeof s!="string")return;if(s.startsWith("/")){t.set(i,[s]);return}let o=e.getCwd?.()??e.cwd,n=(0,a.resolve)(o,s);t.set(i,[n])}),t}var T={meta:{type:"suggestion",docs:{description:"Ensure imports use path aliases whenever possible vs. relative paths",url:j("no-relative")},fixable:"code",schema:[{type:"object",properties:{exceptions:{type:"array",items:{type:"string"}},paths:{type:"object"}},additionalProperties:!1}],messages:{shouldUseAlias:"Import should use path alias instead of relative path"}},create(e){let t=e.options[0]?.exceptions,r=e.getFilename?.()??e.filename,i=P(e);return i?.size?{ImportExpression(s){if(s.source.type!=="Literal"||typeof s.source.value!="string")return;let o=s.source.raw,n=s.source.value;if(!/^(\.?\.\/)/.test(n))return;let p=(0,l.resolve)((0,l.dirname)(r),n);if(A(p,t))return;let c=k(p,i);c&&e.report({node:s,messageId:"shouldUseAlias",data:{alias:c},fix(m){let g=E(p,c,i.get(c)),d=o.replace(n,g);return m.replaceText(s.source,d)}})},ImportDeclaration(s){if(typeof s.source.value!="string")return;let o=s.source.value;if(!/^(\.?\.\/)/.test(o))return;let n=(0,l.resolve)((0,l.dirname)(r),o),p=A(n,t),u=k(n,i);p||u&&e.report({node:s,messageId:"shouldUseAlias",data:{alias:u},fix(c){let m=s.source.raw,g=E(n,u,i.get(u)),d=m.replace(o,g);return c.replaceText(s.source,d)}})}}:{}}};function k(e,t){return Array.from(t.keys()).find(r=>t.get(r).some(s=>e.indexOf(s)===0))}function A(e,t){if(!t)return!1;let r=(0,l.basename)(e);return(0,M.default)(r,t).includes(r)}function E(e,t,r){for(let i of r)if(e.indexOf(i)===0)return e.replace(i,t)}var J={name:h,version:v,meta:{name:h,version:v},rules:{"no-relative":T}};
+var C=Object.create;var f=Object.defineProperty;var I=Object.getOwnPropertyDescriptor;var U=Object.getOwnPropertyNames;var S=Object.getPrototypeOf,F=Object.prototype.hasOwnProperty;var $=(e,t)=>{for(var r in t)f(e,r,{get:t[r],enumerable:!0})},y=(e,t,r,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of U(t))!F.call(e,s)&&s!==r&&f(e,s,{get:()=>t[s],enumerable:!(i=I(t,s))||i.enumerable});return e};var b=(e,t,r)=>(r=e!=null?C(S(e)):{},y(t||!e||!e.__esModule?f(r,"default",{value:e,enumerable:!0}):r,e)),D=e=>y(f({},"__esModule",{value:!0}),e);var N={};$(N,{default:()=>J});module.exports=D(N);var h="eslint-plugin-path-alias",v="2.0.0";var l=require("path"),M=b(require("nanomatch"));function j(e){return`https://github/com/msfragala/eslint-plugin-path-alias/blob/master/docs/rules/${e}.md`}var R=require("get-tsconfig"),a=require("path"),w=b(require("find-pkg")),O=require("fs");function P(e){if(e.options[0]?.paths)return z(e);let t=e.getFilename?.()??e.filename,r=(0,R.getTsconfig)(t);if(r?.config?.compilerOptions?.paths)return q(r);let i=w.default.sync((0,a.dirname)(t));if(!i)return;let s=JSON.parse((0,O.readFileSync)(i).toString());if(s?.imports)return L(s,i)}function L(e,t){let r=new Map,i=e.imports??{},s=(0,a.dirname)(t);return Object.entries(i).forEach(([o,n])=>{if(!n||typeof n!="string")return;let p=(0,a.resolve)(s,n);r.set(o,[p])}),r}function q(e){let t=new Map,r=e?.config?.compilerOptions?.paths??{},i=(0,a.dirname)(e.path);return e.config.compilerOptions?.baseUrl&&(i=(0,a.resolve)((0,a.dirname)(e.path),e.config.compilerOptions.baseUrl)),Object.entries(r).forEach(([s,o])=>{s=s.replace(/\/\*$/,""),o=o.map(n=>(0,a.resolve)(i,n.replace(/\/\*$/,""))),t.set(s,o)}),t}function z(e){let t=new Map,r=e.options[0]?.paths??{};return Object.entries(r).forEach(([i,s])=>{if(!s||typeof s!="string")return;if(s.startsWith("/")){t.set(i,[s]);return}let o=e.getCwd?.()??e.cwd,n=(0,a.resolve)(o,s);t.set(i,[n])}),t}var T={meta:{type:"suggestion",docs:{description:"Ensure imports use path aliases whenever possible vs. relative paths",url:j("no-relative")},fixable:"code",schema:[{type:"object",properties:{exceptions:{type:"array",items:{type:"string"}},paths:{type:"object"}},additionalProperties:!1}],messages:{shouldUseAlias:"Import should use path alias instead of relative path"}},create(e){let t=e.options[0]?.exceptions,r=e.getFilename?.()??e.filename,i=P(e);return i?.size?{ImportExpression(s){if(s.source.type!=="Literal"||typeof s.source.value!="string")return;let o=s.source.raw,n=s.source.value;if(!/^(\.\.\/)/.test(n))return;let p=(0,l.resolve)((0,l.dirname)(r),n);if(A(p,t))return;let c=k(p,i);c&&e.report({node:s,messageId:"shouldUseAlias",data:{alias:c},fix(m){let g=E(p,c,i.get(c)),d=o.replace(n,g);return m.replaceText(s.source,d)}})},ImportDeclaration(s){if(typeof s.source.value!="string")return;let o=s.source.value;if(!/^(\.\.\/)/.test(o))return;let n=(0,l.resolve)((0,l.dirname)(r),o),p=A(n,t),u=k(n,i);p||u&&e.report({node:s,messageId:"shouldUseAlias",data:{alias:u},fix(c){let m=s.source.raw,g=E(n,u,i.get(u)),d=m.replace(o,g);return c.replaceText(s.source,d)}})}}:{}}};function k(e,t){return Array.from(t.keys()).find(r=>t.get(r).some(s=>e.indexOf(s)===0))}function A(e,t){if(!t)return!1;let r=(0,l.basename)(e);return(0,M.default)(r,t).includes(r)}function E(e,t,r){for(let i of r)if(e.indexOf(i)===0)return e.replace(i,t)}var J={name:h,version:v,meta:{name:h,version:v},rules:{"no-relative":T}};
diff --git a/dist/index.mjs b/dist/index.mjs
index 96de18e06d4cc413e11af038cd760e4804c32e59..27e8c4e3e2c942400cc3982e52159904ca6eedfa 100644
--- a/dist/index.mjs
+++ b/dist/index.mjs
@@ -1 +1 @@
-var d="eslint-plugin-path-alias",h="2.0.0";import{dirname as x,resolve as j,basename as I}from"path";import U from"nanomatch";function y(e){return`https://github/com/msfragala/eslint-plugin-path-alias/blob/master/docs/rules/${e}.md`}import{getTsconfig as k}from"get-tsconfig";import{resolve as c,dirname as u}from"path";import A from"find-pkg";import{readFileSync as E}from"fs";function b(e){if(e.options[0]?.paths)return C(e);let s=e.getFilename?.()??e.filename,i=k(s);if(i?.config?.compilerOptions?.paths)return T(i);let r=A.sync(u(s));if(!r)return;let t=JSON.parse(E(r).toString());if(t?.imports)return M(t,r)}function M(e,s){let i=new Map,r=e.imports??{},t=u(s);return Object.entries(r).forEach(([o,n])=>{if(!n||typeof n!="string")return;let a=c(t,n);i.set(o,[a])}),i}function T(e){let s=new Map,i=e?.config?.compilerOptions?.paths??{},r=u(e.path);return e.config.compilerOptions?.baseUrl&&(r=c(u(e.path),e.config.compilerOptions.baseUrl)),Object.entries(i).forEach(([t,o])=>{t=t.replace(/\/\*$/,""),o=o.map(n=>c(r,n.replace(/\/\*$/,""))),s.set(t,o)}),s}function C(e){let s=new Map,i=e.options[0]?.paths??{};return Object.entries(i).forEach(([r,t])=>{if(!t||typeof t!="string")return;if(t.startsWith("/")){s.set(r,[t]);return}let o=e.getCwd?.()??e.cwd,n=c(o,t);s.set(r,[n])}),s}var P={meta:{type:"suggestion",docs:{description:"Ensure imports use path aliases whenever possible vs. relative paths",url:y("no-relative")},fixable:"code",schema:[{type:"object",properties:{exceptions:{type:"array",items:{type:"string"}},paths:{type:"object"}},additionalProperties:!1}],messages:{shouldUseAlias:"Import should use path alias instead of relative path"}},create(e){let s=e.options[0]?.exceptions,i=e.getFilename?.()??e.filename,r=b(e);return r?.size?{ImportExpression(t){if(t.source.type!=="Literal"||typeof t.source.value!="string")return;let o=t.source.raw,n=t.source.value;if(!/^(\.?\.\/)/.test(n))return;let a=j(x(i),n);if(w(a,s))return;let l=R(a,r);l&&e.report({node:t,messageId:"shouldUseAlias",data:{alias:l},fix(f){let m=O(a,l,r.get(l)),g=o.replace(n,m);return f.replaceText(t.source,g)}})},ImportDeclaration(t){if(typeof t.source.value!="string")return;let o=t.source.value;if(!/^(\.?\.\/)/.test(o))return;let n=j(x(i),o),a=w(n,s),p=R(n,r);a||p&&e.report({node:t,messageId:"shouldUseAlias",data:{alias:p},fix(l){let f=t.source.raw,m=O(n,p,r.get(p)),g=f.replace(o,m);return l.replaceText(t.source,g)}})}}:{}}};function R(e,s){return Array.from(s.keys()).find(i=>s.get(i).some(t=>e.indexOf(t)===0))}function w(e,s){if(!s)return!1;let i=I(e);return U(i,s).includes(i)}function O(e,s,i){for(let r of i)if(e.indexOf(r)===0)return e.replace(r,s)}var Q={name:d,version:h,meta:{name:d,version:h},rules:{"no-relative":P}};export{Q as default};
+var d="eslint-plugin-path-alias",h="2.0.0";import{dirname as x,resolve as j,basename as I}from"path";import U from"nanomatch";function y(e){return`https://github/com/msfragala/eslint-plugin-path-alias/blob/master/docs/rules/${e}.md`}import{getTsconfig as k}from"get-tsconfig";import{resolve as c,dirname as u}from"path";import A from"find-pkg";import{readFileSync as E}from"fs";function b(e){if(e.options[0]?.paths)return C(e);let s=e.getFilename?.()??e.filename,i=k(s);if(i?.config?.compilerOptions?.paths)return T(i);let r=A.sync(u(s));if(!r)return;let t=JSON.parse(E(r).toString());if(t?.imports)return M(t,r)}function M(e,s){let i=new Map,r=e.imports??{},t=u(s);return Object.entries(r).forEach(([o,n])=>{if(!n||typeof n!="string")return;let a=c(t,n);i.set(o,[a])}),i}function T(e){let s=new Map,i=e?.config?.compilerOptions?.paths??{},r=u(e.path);return e.config.compilerOptions?.baseUrl&&(r=c(u(e.path),e.config.compilerOptions.baseUrl)),Object.entries(i).forEach(([t,o])=>{t=t.replace(/\/\*$/,""),o=o.map(n=>c(r,n.replace(/\/\*$/,""))),s.set(t,o)}),s}function C(e){let s=new Map,i=e.options[0]?.paths??{};return Object.entries(i).forEach(([r,t])=>{if(!t||typeof t!="string")return;if(t.startsWith("/")){s.set(r,[t]);return}let o=e.getCwd?.()??e.cwd,n=c(o,t);s.set(r,[n])}),s}var P={meta:{type:"suggestion",docs:{description:"Ensure imports use path aliases whenever possible vs. relative paths",url:y("no-relative")},fixable:"code",schema:[{type:"object",properties:{exceptions:{type:"array",items:{type:"string"}},paths:{type:"object"}},additionalProperties:!1}],messages:{shouldUseAlias:"Import should use path alias instead of relative path"}},create(e){let s=e.options[0]?.exceptions,i=e.getFilename?.()??e.filename,r=b(e);return r?.size?{ImportExpression(t){if(t.source.type!=="Literal"||typeof t.source.value!="string")return;let o=t.source.raw,n=t.source.value;if(!/^(\.\.\/)/.test(n))return;let a=j(x(i),n);if(w(a,s))return;let l=R(a,r);l&&e.report({node:t,messageId:"shouldUseAlias",data:{alias:l},fix(f){let m=O(a,l,r.get(l)),g=o.replace(n,m);return f.replaceText(t.source,g)}})},ImportDeclaration(t){if(typeof t.source.value!="string")return;let o=t.source.value;if(!/^(\.\.\/)/.test(o))return;let n=j(x(i),o),a=w(n,s),p=R(n,r);a||p&&e.report({node:t,messageId:"shouldUseAlias",data:{alias:p},fix(l){let f=t.source.raw,m=O(n,p,r.get(p)),g=f.replace(o,m);return l.replaceText(t.source,g)}})}}:{}}};function R(e,s){return Array.from(s.keys()).find(i=>s.get(i).some(t=>e.indexOf(t)===0))}function w(e,s){if(!s)return!1;let i=I(e);return U(i,s).includes(i)}function O(e,s,i){for(let r of i)if(e.indexOf(r)===0)return e.replace(r,s)}var Q={name:d,version:h,meta:{name:d,version:h},rules:{"no-relative":P}};export{Q as default};

View file

@ -1,8 +1,8 @@
diff --git a/lib/rules/no-useless-escape.js b/lib/rules/no-useless-escape.js diff --git a/lib/rules/no-useless-escape.js b/lib/rules/no-useless-escape.js
index 2046a148a17fd1d5f3a4bbc9f45f7700259d11fa..f4898c6b57355a4fd72c43a9f32bf1a36a6ccf4a 100644 index 0e0f6f09f2c35f3276173c08f832cde9f2cf56a0..7dc22851715f3574d935f513c1b5e35552985711 100644
--- a/lib/rules/no-useless-escape.js --- a/lib/rules/no-useless-escape.js
+++ b/lib/rules/no-useless-escape.js +++ b/lib/rules/no-useless-escape.js
@@ -97,12 +97,30 @@ module.exports = { @@ -65,13 +65,31 @@ module.exports = {
escapeBackslash: "Replace the `\\` with `\\\\` to include the actual backslash character." escapeBackslash: "Replace the `\\` with `\\\\` to include the actual backslash character."
}, },
@ -25,21 +25,25 @@ index 2046a148a17fd1d5f3a4bbc9f45f7700259d11fa..f4898c6b57355a4fd72c43a9f32bf1a3
create(context) { create(context) {
+ const options = context.options[0] || {}; + const options = context.options[0] || {};
+ const { extra, extraCharClass } = options || '' + const { extra, extraCharClass } = options;
const sourceCode = context.getSourceCode(); const sourceCode = context.sourceCode;
const parser = new RegExpParser();
+ const NON_CHARCLASS_ESCAPES = union(REGEX_NON_CHARCLASS_ESCAPES, new Set(extra)) + const NON_CHARCLASS_ESCAPES = union(REGEX_NON_CHARCLASS_ESCAPES, new Set(extra));
+ const CHARCLASS_ESCAPES = union(REGEX_GENERAL_ESCAPES, new Set(extraCharClass)) + const CHARCLASS_ESCAPES = union(REGEX_GENERAL_ESCAPES, new Set(extraCharClass));
+ +
/** /**
* Reports a node * Reports a node
* @param {ASTNode} node The node to report * @param {ASTNode} node The node to report
@@ -238,7 +256,7 @@ module.exports = { @@ -200,9 +218,9 @@ module.exports = {
.filter(charInfo => charInfo.escaped) let allowedEscapes;
// Filter out characters that are valid to escape, based on their position in the regular expression. if (characterClassStack.length) {
- .filter(charInfo => !(charInfo.inCharClass ? REGEX_GENERAL_ESCAPES : REGEX_NON_CHARCLASS_ESCAPES).has(charInfo.text)) - allowedEscapes = unicodeSets ? REGEX_CLASSSET_CHARACTER_ESCAPES : REGEX_GENERAL_ESCAPES;
+ .filter(charInfo => !(charInfo.inCharClass ? CHARCLASS_ESCAPES : NON_CHARCLASS_ESCAPES).has(charInfo.text)) + allowedEscapes = unicodeSets ? REGEX_CLASSSET_CHARACTER_ESCAPES : CHARCLASS_ESCAPES;
} else {
// Report all the remaining characters. - allowedEscapes = REGEX_NON_CHARCLASS_ESCAPES;
.forEach(charInfo => report(node, charInfo.index, charInfo.text)); + allowedEscapes = NON_CHARCLASS_ESCAPES;
}
if (allowedEscapes.has(escapedChar)) {
return;

File diff suppressed because it is too large Load diff

2
pnpm-workspace.yaml Normal file
View file

@ -0,0 +1,2 @@
packages:
- packages/*

View file

@ -18,17 +18,24 @@
*/ */
import esbuild from "esbuild"; import esbuild from "esbuild";
import { readdir } from "fs/promises";
import { join } from "path";
import { commonOpts, globPlugins, isStandalone, VERSION, watch } from "./common.mjs"; import { BUILD_TIMESTAMP, commonOpts, exists, globPlugins, IS_DEV, IS_REPORTER, IS_STANDALONE, IS_UPDATER_DISABLED, resolvePluginName, VERSION, commonRendererPlugins, watch } from "./common.mjs";
const defines = { const defines = {
IS_STANDALONE: isStandalone, IS_STANDALONE,
IS_DEV: JSON.stringify(watch), IS_DEV,
IS_REPORTER,
IS_UPDATER_DISABLED,
IS_WEB: false,
IS_EXTENSION: false,
VERSION: JSON.stringify(VERSION), VERSION: JSON.stringify(VERSION),
BUILD_TIMESTAMP: Date.now(), BUILD_TIMESTAMP
}; };
if (defines.IS_STANDALONE === "false")
// If this is a local build (not standalone), optimise if (defines.IS_STANDALONE === false)
// If this is a local build (not standalone), optimize
// for the specific platform we're on // for the specific platform we're on
defines["process.platform"] = JSON.stringify(process.platform); defines["process.platform"] = JSON.stringify(process.platform);
@ -40,26 +47,63 @@ const nodeCommonOpts = {
format: "cjs", format: "cjs",
platform: "node", platform: "node",
target: ["esnext"], target: ["esnext"],
minify: true, external: ["electron", "original-fs", "~pluginNatives", ...commonOpts.external],
bundle: true, define: defines
external: ["electron", ...commonOpts.external],
define: defines,
}; };
const sourceMapFooter = s => watch ? "" : `//# sourceMappingURL=vencord://${s}.js.map`; const sourceMapFooter = s => watch ? "" : `//# sourceMappingURL=vencord://${s}.js.map`;
const sourcemap = watch ? "inline" : "external"; const sourcemap = watch ? "inline" : "external";
await Promise.all([ /**
// common preload * @type {import("esbuild").Plugin}
esbuild.build({ */
...nodeCommonOpts, const globNativesPlugin = {
entryPoints: ["src/preload.ts"], name: "glob-natives-plugin",
outfile: "dist/preload.js", setup: build => {
footer: { js: "//# sourceURL=VencordPreload\n" + sourceMapFooter("preload") }, const filter = /^~pluginNatives$/;
sourcemap, build.onResolve({ filter }, args => {
}), return {
namespace: "import-natives",
path: args.path
};
});
// Discord Desktop main & renderer build.onLoad({ filter, namespace: "import-natives" }, async () => {
const pluginDirs = ["plugins", "userplugins"];
let code = "";
let natives = "\n";
let i = 0;
for (const dir of pluginDirs) {
const dirPath = join("src", dir);
if (!await exists(dirPath)) continue;
const plugins = await readdir(dirPath, { withFileTypes: true });
for (const file of plugins) {
const fileName = file.name;
const nativePath = join(dirPath, fileName, "native.ts");
const indexNativePath = join(dirPath, fileName, "native/index.ts");
if (!(await exists(nativePath)) && !(await exists(indexNativePath)))
continue;
const pluginName = await resolvePluginName(dirPath, file);
const mod = `p${i}`;
code += `import * as ${mod} from "./${dir}/${fileName}/native";\n`;
natives += `${JSON.stringify(pluginName)}:${mod},\n`;
i++;
}
}
code += `export default {${natives}};`;
return {
contents: code,
resolveDir: "./src"
};
});
}
};
await Promise.all([
// Discord Desktop main & renderer & preload
esbuild.build({ esbuild.build({
...nodeCommonOpts, ...nodeCommonOpts,
entryPoints: ["src/main/index.ts"], entryPoints: ["src/main/index.ts"],
@ -69,8 +113,12 @@ await Promise.all([
define: { define: {
...defines, ...defines,
IS_DISCORD_DESKTOP: true, IS_DISCORD_DESKTOP: true,
IS_VENCORD_DESKTOP: false IS_VESKTOP: false
} },
plugins: [
...nodeCommonOpts.plugins,
globNativesPlugin
]
}), }),
esbuild.build({ esbuild.build({
...commonOpts, ...commonOpts,
@ -83,17 +131,28 @@ await Promise.all([
sourcemap, sourcemap,
plugins: [ plugins: [
globPlugins("discordDesktop"), globPlugins("discordDesktop"),
...commonOpts.plugins ...commonRendererPlugins
], ],
define: { define: {
...defines, ...defines,
IS_WEB: false,
IS_DISCORD_DESKTOP: true, IS_DISCORD_DESKTOP: true,
IS_VENCORD_DESKTOP: false IS_VESKTOP: false
}
}),
esbuild.build({
...nodeCommonOpts,
entryPoints: ["src/preload.ts"],
outfile: "dist/preload.js",
footer: { js: "//# sourceURL=VencordPreload\n" + sourceMapFooter("preload") },
sourcemap,
define: {
...defines,
IS_DISCORD_DESKTOP: true,
IS_VESKTOP: false
} }
}), }),
// Vencord Desktop main & renderer // Vencord Desktop main & renderer & preload
esbuild.build({ esbuild.build({
...nodeCommonOpts, ...nodeCommonOpts,
entryPoints: ["src/main/index.ts"], entryPoints: ["src/main/index.ts"],
@ -103,8 +162,12 @@ await Promise.all([
define: { define: {
...defines, ...defines,
IS_DISCORD_DESKTOP: false, IS_DISCORD_DESKTOP: false,
IS_VENCORD_DESKTOP: true IS_VESKTOP: true
} },
plugins: [
...nodeCommonOpts.plugins,
globNativesPlugin
]
}), }),
esbuild.build({ esbuild.build({
...commonOpts, ...commonOpts,
@ -117,13 +180,24 @@ await Promise.all([
sourcemap, sourcemap,
plugins: [ plugins: [
globPlugins("vencordDesktop"), globPlugins("vencordDesktop"),
...commonOpts.plugins ...commonRendererPlugins
], ],
define: { define: {
...defines, ...defines,
IS_WEB: false,
IS_DISCORD_DESKTOP: false, IS_DISCORD_DESKTOP: false,
IS_VENCORD_DESKTOP: true IS_VESKTOP: true
}
}),
esbuild.build({
...nodeCommonOpts,
entryPoints: ["src/preload.ts"],
outfile: "dist/vencordDesktopPreload.js",
footer: { js: "//# sourceURL=VencordPreload\n" + sourceMapFooter("vencordDesktopPreload") },
sourcemap,
define: {
...defines,
IS_DISCORD_DESKTOP: false,
IS_VESKTOP: true
} }
}), }),
]).catch(err => { ]).catch(err => {

View file

@ -17,14 +17,13 @@
* 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 esbuild from "esbuild"; import esbuild from "esbuild";
import { zip } from "fflate";
import { readFileSync } from "fs"; import { readFileSync } from "fs";
import { appendFile, mkdir, readFile, rm, writeFile } from "fs/promises"; import { appendFile, mkdir, readdir, readFile, rm, writeFile } from "fs/promises";
import { join } from "path"; import { join } from "path";
import Zip from "zip-local";
import { commonOpts, globPlugins, VERSION, watch } from "./common.mjs"; import { BUILD_TIMESTAMP, commonOpts, globPlugins, IS_DEV, IS_REPORTER, VERSION, commonRendererPlugins } from "./common.mjs";
/** /**
* @type {esbuild.BuildOptions} * @type {esbuild.BuildOptions}
@ -34,36 +33,78 @@ const commonOptions = {
entryPoints: ["browser/Vencord.ts"], entryPoints: ["browser/Vencord.ts"],
globalName: "Vencord", globalName: "Vencord",
format: "iife", format: "iife",
external: ["plugins", "git-hash", "/assets/*"], external: ["~plugins", "~git-hash", "/assets/*"],
plugins: [ plugins: [
globPlugins("web"), globPlugins("web"),
...commonOpts.plugins, ...commonRendererPlugins
], ],
target: ["esnext"], target: ["esnext"],
define: { define: {
IS_WEB: "true", IS_WEB: true,
IS_STANDALONE: "true", IS_EXTENSION: false,
IS_DEV: JSON.stringify(watch), IS_STANDALONE: true,
IS_DISCORD_DESKTOP: "false", IS_DEV,
IS_VENCORD_DESKTOP: "false", IS_REPORTER,
IS_DISCORD_DESKTOP: false,
IS_VESKTOP: false,
IS_UPDATER_DISABLED: true,
VERSION: JSON.stringify(VERSION), VERSION: JSON.stringify(VERSION),
BUILD_TIMESTAMP: Date.now(), BUILD_TIMESTAMP
} }
}; };
const MonacoWorkerEntryPoints = [
"vs/language/css/css.worker.js",
"vs/editor/editor.worker.js"
];
const RnNoiseFiles = [
"dist/rnnoise.wasm",
"dist/rnnoise_simd.wasm",
"dist/rnnoise/workletProcessor.js",
"LICENSE"
];
await Promise.all( await Promise.all(
[ [
esbuild.build({
entryPoints: MonacoWorkerEntryPoints.map(entry => `node_modules/monaco-editor/esm/${entry}`),
bundle: true,
minify: true,
format: "iife",
outbase: "node_modules/monaco-editor/esm/",
outdir: "dist/monaco"
}),
esbuild.build({
entryPoints: ["browser/monaco.ts"],
bundle: true,
minify: true,
format: "iife",
outfile: "dist/monaco/index.js",
loader: {
".ttf": "file"
}
}),
esbuild.build({ esbuild.build({
...commonOptions, ...commonOptions,
outfile: "dist/browser.js", outfile: "dist/browser.js",
footer: { js: "//# sourceURL=VencordWeb" }, footer: { js: "//# sourceURL=VencordWeb" }
}),
esbuild.build({
...commonOptions,
outfile: "dist/extension.js",
define: {
...commonOptions?.define,
IS_EXTENSION: true,
},
footer: { js: "//# sourceURL=VencordWeb" }
}), }),
esbuild.build({ esbuild.build({
...commonOptions, ...commonOptions,
inject: ["browser/GMPolyfill.js", ...(commonOptions?.inject || [])], inject: ["browser/GMPolyfill.js", ...(commonOptions?.inject || [])],
define: { define: {
"window": "unsafeWindow", ...(commonOptions?.define),
...(commonOptions?.define) window: "unsafeWindow",
}, },
outfile: "dist/Vencord.user.js", outfile: "dist/Vencord.user.js",
banner: { banner: {
@ -72,18 +113,52 @@ await Promise.all(
footer: { footer: {
// UserScripts get wrapped in an iife, so define Vencord prop on window that returns our local // UserScripts get wrapped in an iife, so define Vencord prop on window that returns our local
js: "Object.defineProperty(unsafeWindow,'Vencord',{get:()=>Vencord});" js: "Object.defineProperty(unsafeWindow,'Vencord',{get:()=>Vencord});"
}, }
}) })
] ]
); ).catch(err => {
console.error("Build failed");
console.error(err.message);
if (!commonOpts.watch)
process.exit(1);
});;
/** /**
* @type {(target: string, files: string[], shouldZip: boolean) => Promise<void>} * @type {(dir: string) => Promise<string[]>}
*/ */
async function buildPluginZip(target, files, shouldZip) { async function globDir(dir) {
const files = [];
for (const child of await readdir(dir, { withFileTypes: true })) {
const p = join(dir, child.name);
if (child.isDirectory())
files.push(...await globDir(p));
else
files.push(p);
}
return files;
}
/**
* @type {(dir: string, basePath?: string) => Promise<Record<string, string>>}
*/
async function loadDir(dir, basePath = "") {
const files = await globDir(dir);
return Object.fromEntries(await Promise.all(files.map(async f => [f.slice(basePath.length), await readFile(f)])));
}
/**
* @type {(target: string, files: string[]) => Promise<void>}
*/
async function buildExtension(target, files) {
const entries = { const entries = {
"dist/Vencord.js": await readFile("dist/browser.js"), "dist/Vencord.js": await readFile("dist/extension.js"),
"dist/Vencord.css": await readFile("dist/browser.css"), "dist/Vencord.css": await readFile("dist/extension.css"),
...await loadDir("dist/monaco"),
...Object.fromEntries(await Promise.all(RnNoiseFiles.map(async file =>
[`third-party/rnnoise/${file.replace(/^dist\//, "")}`, await readFile(`node_modules/@sapphi-red/web-noise-suppressor/${file}`)]
))),
...Object.fromEntries(await Promise.all(files.map(async f => { ...Object.fromEntries(await Promise.all(files.map(async f => {
let content = await readFile(join("browser", f)); let content = await readFile(join("browser", f));
if (f.startsWith("manifest")) { if (f.startsWith("manifest")) {
@ -96,34 +171,18 @@ async function buildPluginZip(target, files, shouldZip) {
f.startsWith("manifest") ? "manifest.json" : f, f.startsWith("manifest") ? "manifest.json" : f,
content content
]; ];
}))), })))
}; };
if (shouldZip) { await rm(target, { recursive: true, force: true });
return new Promise((resolve, reject) => { await Promise.all(Object.entries(entries).map(async ([file, content]) => {
zip(entries, {}, (err, data) => { const dest = join("dist", target, file);
if (err) { const parentDirectory = join(dest, "..");
reject(err); await mkdir(parentDirectory, { recursive: true });
} else { await writeFile(dest, content);
const out = join("dist", target); }));
writeFile(out, data).then(() => {
console.info("Extension written to " + out);
resolve();
}).catch(reject);
}
});
});
} else {
await rm(target, { recursive: true, force: true });
await Promise.all(Object.entries(entries).map(async ([file, content]) => {
const dest = join("dist", target, file);
const parentDirectory = join(dest, "..");
await mkdir(parentDirectory, { recursive: true });
await writeFile(dest, content);
}));
console.info("Unpacked Extension written to dist/" + target); console.info("Unpacked Extension written to dist/" + target);
}
} }
const appendCssRuntime = readFile("dist/Vencord.user.css", "utf-8").then(content => { const appendCssRuntime = readFile("dist/Vencord.user.css", "utf-8").then(content => {
@ -139,10 +198,19 @@ const appendCssRuntime = readFile("dist/Vencord.user.css", "utf-8").then(content
return appendFile("dist/Vencord.user.js", cssRuntime); return appendFile("dist/Vencord.user.js", cssRuntime);
}); });
await Promise.all([ if (!process.argv.includes("--skip-extension")) {
appendCssRuntime, await Promise.all([
buildPluginZip("extension.zip", ["modifyResponseHeaders.json", "content.js", "manifest.json", "icon.png"], true), appendCssRuntime,
buildPluginZip("chromium-unpacked", ["modifyResponseHeaders.json", "content.js", "manifest.json", "icon.png"], false), buildExtension("chromium-unpacked", ["modifyResponseHeaders.json", "content.js", "manifest.json", "icon.png"]),
buildPluginZip("firefox-unpacked", ["background.js", "content.js", "manifestv2.json", "icon.png"], false), buildExtension("firefox-unpacked", ["background.js", "content.js", "manifestv2.json", "icon.png"]),
]); ]);
Zip.sync.zip("dist/chromium-unpacked").compress().save("dist/extension-chrome.zip");
console.info("Packed Chromium Extension written to dist/extension-chrome.zip");
Zip.sync.zip("dist/firefox-unpacked").compress().save("dist/extension-firefox.zip");
console.info("Packed Firefox Extension written to dist/extension-firefox.zip");
} else {
await appendCssRuntime;
}

View file

@ -20,28 +20,71 @@ import "../suppressExperimentalWarnings.js";
import "../checkNodeVersion.js"; import "../checkNodeVersion.js";
import { exec, execSync } from "child_process"; import { exec, execSync } from "child_process";
import { existsSync, readFileSync } from "fs"; import esbuild from "esbuild";
import { readdir, readFile } from "fs/promises"; import { constants as FsConstants, readFileSync } from "fs";
import { access, readdir, readFile } from "fs/promises";
import { minify as minifyHtml } from "html-minifier-terser";
import { join, relative } from "path"; import { join, relative } from "path";
import { promisify } from "util"; import { promisify } from "util";
// wtf is this assert syntax import { getPluginTarget } from "../utils.mjs";
import PackageJSON from "../../package.json" assert { type: "json" }; import { builtinModules } from "module";
/** @type {import("../../package.json")} */
const PackageJSON = JSON.parse(readFileSync("package.json"));
export const VERSION = PackageJSON.version; export const VERSION = PackageJSON.version;
export const BUILD_TIMESTAMP = Date.now(); // https://reproducible-builds.org/docs/source-date-epoch/
export const BUILD_TIMESTAMP = Number(process.env.SOURCE_DATE_EPOCH) || Date.now();
export const watch = process.argv.includes("--watch"); export const watch = process.argv.includes("--watch");
export const isStandalone = JSON.stringify(process.argv.includes("--standalone")); export const IS_DEV = watch || process.argv.includes("--dev");
export const gitHash = execSync("git rev-parse --short HEAD", { encoding: "utf-8" }).trim(); export const IS_REPORTER = process.argv.includes("--reporter");
export const IS_STANDALONE = process.argv.includes("--standalone");
export const IS_UPDATER_DISABLED = process.argv.includes("--disable-updater");
export const gitHash = process.env.VENCORD_HASH || execSync("git rev-parse --short HEAD", { encoding: "utf-8" }).trim();
export const banner = { export const banner = {
js: ` js: `
// Vencord ${gitHash} // Vencord ${gitHash}
// Standalone: ${isStandalone} // Standalone: ${IS_STANDALONE}
// Platform: ${isStandalone === "false" ? process.platform : "Universal"} // Platform: ${IS_STANDALONE === false ? process.platform : "Universal"}
// Updater Disabled: ${IS_UPDATER_DISABLED}
`.trim() `.trim()
}; };
const isWeb = process.argv.slice(0, 2).some(f => f.endsWith("buildWeb.mjs")); const PluginDefinitionNameMatcher = /definePlugin\(\{\s*(["'])?name\1:\s*(["'`])(.+?)\2/;
/**
* @param {string} base
* @param {import("fs").Dirent} dirent
*/
export async function resolvePluginName(base, dirent) {
const fullPath = join(base, dirent.name);
const content = dirent.isFile()
? await readFile(fullPath, "utf-8")
: await (async () => {
for (const file of ["index.ts", "index.tsx"]) {
try {
return await readFile(join(fullPath, file), "utf-8");
} catch {
continue;
}
}
throw new Error(`Invalid plugin ${fullPath}: could not resolve entry point`);
})();
return PluginDefinitionNameMatcher.exec(content)?.[3]
?? (() => {
throw new Error(`Invalid plugin ${fullPath}: must contain definePlugin call with simple string name property as first property`);
})();
}
export async function exists(path) {
return await access(path, FsConstants.F_OK)
.then(() => true)
.catch(() => false);
}
// https://github.com/evanw/esbuild/issues/619#issuecomment-751995294 // https://github.com/evanw/esbuild/issues/619#issuecomment-751995294
/** /**
@ -52,7 +95,7 @@ export const makeAllPackagesExternalPlugin = {
setup(build) { setup(build) {
const filter = /^[^./]|^\.[^./]|^\.\.[^/]/; // Must not start with "/" or "./" or "../" const filter = /^[^./]|^\.[^./]|^\.\.[^/]/; // Must not start with "/" or "./" or "../"
build.onResolve({ filter }, args => ({ path: args.path, external: true })); build.onResolve({ filter }, args => ({ path: args.path, external: true }));
}, }
}; };
/** /**
@ -72,32 +115,48 @@ export const globPlugins = kind => ({
build.onLoad({ filter, namespace: "import-plugins" }, async () => { build.onLoad({ filter, namespace: "import-plugins" }, async () => {
const pluginDirs = ["plugins/_api", "plugins/_core", "plugins", "userplugins"]; const pluginDirs = ["plugins/_api", "plugins/_core", "plugins", "userplugins"];
let code = ""; let code = "";
let plugins = "\n"; let pluginsCode = "\n";
let metaCode = "\n";
let excludedCode = "\n";
let i = 0; let i = 0;
for (const dir of pluginDirs) { for (const dir of pluginDirs) {
if (!existsSync(`./src/${dir}`)) continue; const userPlugin = dir === "userplugins";
const files = await readdir(`./src/${dir}`);
for (const file of files) {
if (file.startsWith("_") || file.startsWith(".")) continue;
if (file === "index.ts") continue;
const fileBits = file.split("."); const fullDir = `./src/${dir}`;
if (fileBits.length > 2 && ["ts", "tsx"].includes(fileBits.at(-1))) { if (!await exists(fullDir)) continue;
const mod = fileBits.at(-2); const files = await readdir(fullDir, { withFileTypes: true });
if (mod === "dev" && !watch) continue; for (const file of files) {
if (mod === "web" && kind === "discordDesktop") continue; const fileName = file.name;
if (mod === "desktop" && kind === "web") continue; if (fileName.startsWith("_") || fileName.startsWith(".")) continue;
if (mod === "discordDesktop" && kind !== "discordDesktop") continue; if (fileName === "index.ts") continue;
if (mod === "vencordDesktop" && kind !== "vencordDesktop") continue;
const target = getPluginTarget(fileName);
if (target && !IS_REPORTER) {
const excluded =
(target === "dev" && !IS_DEV) ||
(target === "web" && kind === "discordDesktop") ||
(target === "desktop" && kind === "web") ||
(target === "discordDesktop" && kind !== "discordDesktop") ||
(target === "vencordDesktop" && kind !== "vencordDesktop");
if (excluded) {
const name = await resolvePluginName(fullDir, file);
excludedCode += `${JSON.stringify(name)}:${JSON.stringify(target)},\n`;
continue;
}
} }
const folderName = `src/${dir}/${fileName}`.replace(/^src\/plugins\//, "");
const mod = `p${i}`; const mod = `p${i}`;
code += `import ${mod} from "./${dir}/${file.replace(/\.tsx?$/, "")}";\n`; code += `import ${mod} from "./${dir}/${fileName.replace(/\.tsx?$/, "")}";\n`;
plugins += `[${mod}.name]:${mod},\n`; pluginsCode += `[${mod}.name]:${mod},\n`;
metaCode += `[${mod}.name]:${JSON.stringify({ folderName, userPlugin })},\n`; // TODO: add excluded plugins to display in the UI?
i++; i++;
} }
} }
code += `export default {${plugins}};`; code += `export default {${pluginsCode}};export const PluginMeta={${metaCode}};export const ExcludedPlugins={${excludedCode}};`;
return { return {
contents: code, contents: code,
resolveDir: "./src" resolveDir: "./src"
@ -133,11 +192,14 @@ export const gitRemotePlugin = {
namespace: "git-remote", path: args.path namespace: "git-remote", path: args.path
})); }));
build.onLoad({ filter, namespace: "git-remote" }, async () => { build.onLoad({ filter, namespace: "git-remote" }, async () => {
const res = await promisify(exec)("git remote get-url origin", { encoding: "utf-8" }); let remote = process.env.VENCORD_REMOTE;
const remote = res.stdout.trim() if (!remote) {
.replace("https://github.com/", "") const res = await promisify(exec)("git remote get-url origin", { encoding: "utf-8" });
.replace("git@github.com:", "") remote = res.stdout.trim()
.replace(/.git$/, ""); .replace("https://github.com/", "")
.replace("git@github.com:", "")
.replace(/.git$/, "");
}
return { contents: `export default "${remote}"` }; return { contents: `export default "${remote}"` };
}); });
@ -147,21 +209,60 @@ export const gitRemotePlugin = {
/** /**
* @type {import("esbuild").Plugin} * @type {import("esbuild").Plugin}
*/ */
export const fileIncludePlugin = { export const fileUrlPlugin = {
name: "file-include-plugin", name: "file-uri-plugin",
setup: build => { setup: build => {
const filter = /^~fileContent\/.+$/; const filter = /^file:\/\/.+$/;
build.onResolve({ filter }, args => ({ build.onResolve({ filter }, args => ({
namespace: "include-file", namespace: "file-uri",
path: args.path, path: args.path,
pluginData: { pluginData: {
path: join(args.resolveDir, args.path.slice("include-file/".length)) uri: args.path,
path: join(args.resolveDir, args.path.slice("file://".length).split("?")[0])
} }
})); }));
build.onLoad({ filter, namespace: "include-file" }, async ({ pluginData: { path } }) => { build.onLoad({ filter, namespace: "file-uri" }, async ({ pluginData: { path, uri } }) => {
const [name, format] = path.split(";"); const { searchParams } = new URL(uri);
const base64 = searchParams.has("base64");
const minify = IS_STANDALONE === true && searchParams.has("minify");
const noTrim = searchParams.get("trim") === "false";
const encoding = base64 ? "base64" : "utf-8";
let content;
if (!minify) {
content = await readFile(path, encoding);
if (!noTrim) content = content.trimEnd();
} else {
if (path.endsWith(".html")) {
content = await minifyHtml(await readFile(path, "utf-8"), {
collapseWhitespace: true,
removeComments: true,
minifyCSS: true,
minifyJS: true,
removeEmptyAttributes: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
useShortDoctype: true
});
} else if (/[mc]?[jt]sx?$/.test(path)) {
const res = await esbuild.build({
entryPoints: [path],
write: false,
minify: true
});
content = res.outputFiles[0].text;
} else {
throw new Error(`Don't know how to minify file type: ${path}`);
}
if (base64)
content = Buffer.from(content).toString("base64");
}
return { return {
contents: `export default ${JSON.stringify(await readFile(name, format ?? "utf-8"))}` contents: `export default ${JSON.stringify(content)}`
}; };
}); });
} }
@ -192,6 +293,18 @@ export const stylePlugin = {
} }
}; };
/**
* @type {(filter: RegExp, message: string) => import("esbuild").Plugin}
*/
export const banImportPlugin = (filter, message) => ({
name: "ban-imports",
setup: build => {
build.onResolve({ filter }, () => {
return { errors: [{ text: message }] };
});
}
});
/** /**
* @type {import("esbuild").BuildOptions} * @type {import("esbuild").BuildOptions}
*/ */
@ -203,7 +316,7 @@ export const commonOpts = {
sourcemap: watch ? "inline" : "", sourcemap: watch ? "inline" : "",
legalComments: "linked", legalComments: "linked",
banner, banner,
plugins: [fileIncludePlugin, gitHashPlugin, gitRemotePlugin, stylePlugin], plugins: [fileUrlPlugin, gitHashPlugin, gitRemotePlugin, stylePlugin],
external: ["~plugins", "~git-hash", "~git-remote", "/assets/*"], external: ["~plugins", "~git-hash", "~git-remote", "/assets/*"],
inject: ["./scripts/build/inject/react.mjs"], inject: ["./scripts/build/inject/react.mjs"],
jsxFactory: "VencordCreateElement", jsxFactory: "VencordCreateElement",
@ -211,3 +324,16 @@ export const commonOpts = {
// Work around https://github.com/evanw/esbuild/issues/2460 // Work around https://github.com/evanw/esbuild/issues/2460
tsconfig: "./scripts/build/tsconfig.esbuild.json" tsconfig: "./scripts/build/tsconfig.esbuild.json"
}; };
const escapedBuiltinModules = builtinModules
.map(m => m.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&"))
.join("|");
const builtinModuleRegex = new RegExp(`^(node:)?(${escapedBuiltinModules})$`);
export const commonRendererPlugins = [
banImportPlugin(builtinModuleRegex, "Cannot import node inbuilt modules in browser code. You need to use a native.ts file"),
banImportPlugin(/^react$/, "Cannot import from react. React and hooks should be imported from @webpack/common"),
banImportPlugin(/^electron(\/.*)?$/, "Cannot import electron in browser code. You need to use a native.ts file"),
banImportPlugin(/^ts-pattern$/, "Cannot import from ts-pattern. match and P should be imported from @webpack/common"),
...commonOpts.plugins
];

View file

@ -18,9 +18,12 @@
import { Dirent, readdirSync, readFileSync, writeFileSync } from "fs"; import { Dirent, readdirSync, readFileSync, writeFileSync } from "fs";
import { access, readFile } from "fs/promises"; import { access, readFile } from "fs/promises";
import { join } from "path"; import { join, sep } from "path";
import { normalize as posixNormalize, sep as posixSep } from "path/posix";
import { BigIntLiteral, createSourceFile, Identifier, isArrayLiteralExpression, isCallExpression, isExportAssignment, isIdentifier, isObjectLiteralExpression, isPropertyAccessExpression, isPropertyAssignment, isSatisfiesExpression, isStringLiteral, isVariableStatement, NamedDeclaration, NodeArray, ObjectLiteralExpression, ScriptTarget, StringLiteral, SyntaxKind } from "typescript"; import { BigIntLiteral, createSourceFile, Identifier, isArrayLiteralExpression, isCallExpression, isExportAssignment, isIdentifier, isObjectLiteralExpression, isPropertyAccessExpression, isPropertyAssignment, isSatisfiesExpression, isStringLiteral, isVariableStatement, NamedDeclaration, NodeArray, ObjectLiteralExpression, ScriptTarget, StringLiteral, SyntaxKind } from "typescript";
import { getPluginTarget } from "./utils.mjs";
interface Dev { interface Dev {
name: string; name: string;
id: string; id: string;
@ -36,7 +39,8 @@ interface PluginData {
hasCommands: boolean; hasCommands: boolean;
required: boolean; required: boolean;
enabledByDefault: boolean; enabledByDefault: boolean;
target: "discordDesktop" | "vencordDesktop" | "web" | "dev"; target: "discordDesktop" | "vencordDesktop" | "desktop" | "web" | "dev";
filePath: string;
} }
const devs = {} as Record<string, Dev>; const devs = {} as Record<string, Dev>;
@ -151,21 +155,29 @@ async function parseFile(fileName: string) {
case "required": case "required":
case "enabledByDefault": case "enabledByDefault":
data[key] = value.kind === SyntaxKind.TrueKeyword; data[key] = value.kind === SyntaxKind.TrueKeyword;
if (!data[key] && value.kind !== SyntaxKind.FalseKeyword) throw fail(`${key} is not a boolean literal`);
break; break;
} }
} }
if (!data.name || !data.description || !data.authors) throw fail("name, description or authors are missing"); if (!data.name || !data.description || !data.authors) throw fail("name, description or authors are missing");
const fileBits = fileName.split("."); const target = getPluginTarget(fileName);
if (fileBits.length > 2 && ["ts", "tsx"].includes(fileBits.at(-1)!)) { if (target) {
const mod = fileBits.at(-2)!; if (!["web", "discordDesktop", "vencordDesktop", "desktop", "dev"].includes(target)) throw fail(`invalid target ${target}`);
if (!["web", "discordDesktop", "vencordDesktop", "dev"].includes(mod)) throw fail(`invalid target ${fileBits.at(-2)}`); data.target = target as any;
data.target = mod as any;
} }
return data; data.filePath = posixNormalize(fileName)
.split(sep)
.join(posixSep)
.replace(/\/index\.([jt]sx?)$/, "")
.replace(/^src\/plugins\//, "");
let readme = "";
try {
readme = readFileSync(join(fileName, "..", "README.md"), "utf-8");
} catch { }
return [data, readme] as const;
} }
throw fail("no default export called 'definePlugin' found"); throw fail("no default export called 'definePlugin' found");
@ -194,18 +206,24 @@ function isPluginFile({ name }: { name: string; }) {
(async () => { (async () => {
parseDevs(); parseDevs();
const plugins = ["src/plugins", "src/plugins/_core"].flatMap(dir => const plugins = [] as PluginData[];
const readmes = {} as Record<string, string>;
await Promise.all(["src/plugins", "src/plugins/_core"].flatMap(dir =>
readdirSync(dir, { withFileTypes: true }) readdirSync(dir, { withFileTypes: true })
.filter(isPluginFile) .filter(isPluginFile)
.map(async dirent => .map(async dirent => {
parseFile(await getEntryPoint(dir, dirent)) const [data, readme] = await parseFile(await getEntryPoint(dir, dirent));
) plugins.push(data);
); if (readme) readmes[data.name] = readme;
})
));
const data = JSON.stringify(await Promise.all(plugins)); const data = JSON.stringify(plugins);
if (process.argv.length > 2) { if (process.argv.length > 3) {
writeFileSync(process.argv[2], data); writeFileSync(process.argv[2], data);
writeFileSync(process.argv[3], JSON.stringify(readmes));
} else { } else {
console.log(data); console.log(data);
} }

View file

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
/* eslint-disable no-fallthrough */
// eslint-disable-next-line spaced-comment // eslint-disable-next-line spaced-comment
/// <reference types="../src/globals" /> /// <reference types="../src/globals" />
// eslint-disable-next-line spaced-comment // eslint-disable-next-line spaced-comment
@ -35,15 +37,18 @@ 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();
await page.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"); await page.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36");
await page.setBypassCSP(true);
function maybeGetError(handle: JSHandle) { async function maybeGetError(handle: JSHandle): Promise<string | undefined> {
return (handle as JSHandle<Error>)?.getProperty("message") return await (handle as JSHandle<Error>)?.getProperty("message")
.then(m => m.jsonValue()); .then(m => m?.jsonValue())
.catch(() => undefined);
} }
const report = { const report = {
@ -58,41 +63,72 @@ const report = {
plugin: string; plugin: string;
error: string; error: string;
}[], }[],
otherErrors: [] as string[] otherErrors: [] as string[],
ignoredErrors: [] as string[],
badWebpackFinds: [] as string[]
}; };
function toCodeBlock(s: string) { const IGNORED_DISCORD_ERRORS = [
"KeybindStore: Looking for callback action",
"Unable to process domain list delta: Client revision number is null",
"Downloading the full bad domains file",
/\[GatewaySocket\].{0,110}Cannot access '/,
"search for 'name' in undefined",
"Attempting to set fast connect zstd when unsupported"
] as Array<string | RegExp>;
function toCodeBlock(s: string, indentation = 0, isDiscord = false) {
s = s.replace(/```/g, "`\u200B`\u200B`"); s = s.replace(/```/g, "`\u200B`\u200B`");
return "```" + s + " ```";
const indentationStr = Array(!isDiscord ? indentation : 0).fill(" ").join("");
return `\`\`\`\n${s.split("\n").map(s => indentationStr + s).join("\n")}\n${indentationStr}\`\`\``;
} }
async function printReport() { async function printReport() {
console.log();
console.log("# Vencord Report" + (CANARY ? " (Canary)" : "")); console.log("# Vencord Report" + (CANARY ? " (Canary)" : ""));
console.log(); console.log();
console.log("## Bad Patches"); console.log("## Bad Patches");
report.badPatches.forEach(p => { report.badPatches.forEach(p => {
console.log(`- ${p.plugin} (${p.type})`); console.log(`- ${p.plugin} (${p.type})`);
console.log(` - ID: \`${p.id}\``); console.log(` - ID: \`${p.id}\``);
console.log(` - Match: ${toCodeBlock(p.match)}`); console.log(` - Match: ${toCodeBlock(p.match, " - Match: ".length)}`);
if (p.error) console.log(` - Error: ${toCodeBlock(p.error)}`); if (p.error) console.log(` - Error: ${toCodeBlock(p.error, " - Error: ".length)}`);
}); });
console.log(); console.log();
console.log("## Bad Webpack Finds");
report.badWebpackFinds.forEach(p => console.log("- " + toCodeBlock(p, "- ".length)));
console.log();
console.log("## Bad Starts"); console.log("## Bad Starts");
report.badStarts.forEach(p => { report.badStarts.forEach(p => {
console.log(`- ${p.plugin}`); console.log(`- ${p.plugin}`);
console.log(` - Error: ${toCodeBlock(p.error)}`); console.log(` - Error: ${toCodeBlock(p.error, " - Error: ".length)}`);
}); });
console.log();
console.log("## Discord Errors"); console.log("## Discord Errors");
report.otherErrors.forEach(e => { report.otherErrors.forEach(e => {
console.log(`- ${toCodeBlock(e)}`); console.log(`- ${toCodeBlock(e, "- ".length)}`);
}); });
console.log();
console.log("## Ignored Discord Errors");
report.ignoredErrors.forEach(e => {
console.log(`- ${toCodeBlock(e, "- ".length)}`);
});
console.log();
if (process.env.DISCORD_WEBHOOK) { if (process.env.DISCORD_WEBHOOK) {
// this code was written almost entirely by Copilot xD
await fetch(process.env.DISCORD_WEBHOOK, { await fetch(process.env.DISCORD_WEBHOOK, {
method: "POST", method: "POST",
headers: { headers: {
@ -101,7 +137,6 @@ async function printReport() {
body: JSON.stringify({ body: JSON.stringify({
description: "Here's the latest Vencord Report!", description: "Here's the latest Vencord Report!",
username: "Vencord Reporter" + (CANARY ? " (Canary)" : ""), username: "Vencord Reporter" + (CANARY ? " (Canary)" : ""),
avatar_url: "https://cdn.discordapp.com/icons/1015060230222131221/f0204a918c6c9c9a43195997e97d8adf.webp",
embeds: [ embeds: [
{ {
title: "Bad Patches", title: "Bad Patches",
@ -109,19 +144,24 @@ async function printReport() {
const lines = [ const lines = [
`**__${p.plugin} (${p.type}):__**`, `**__${p.plugin} (${p.type}):__**`,
`ID: \`${p.id}\``, `ID: \`${p.id}\``,
`Match: ${toCodeBlock(p.match)}` `Match: ${toCodeBlock(p.match, "Match: ".length, true)}`
]; ];
if (p.error) lines.push(`Error: ${toCodeBlock(p.error)}`); if (p.error) lines.push(`Error: ${toCodeBlock(p.error, "Error: ".length, true)}`);
return lines.join("\n"); return lines.join("\n");
}).join("\n\n") || "None", }).join("\n\n") || "None",
color: report.badPatches.length ? 0xff0000 : 0x00ff00 color: report.badPatches.length ? 0xff0000 : 0x00ff00
}, },
{
title: "Bad Webpack Finds",
description: report.badWebpackFinds.map(f => toCodeBlock(f, 0, true)).join("\n") || "None",
color: report.badWebpackFinds.length ? 0xff0000 : 0x00ff00
},
{ {
title: "Bad Starts", title: "Bad Starts",
description: report.badStarts.map(p => { description: report.badStarts.map(p => {
const lines = [ const lines = [
`**__${p.plugin}:__**`, `**__${p.plugin}:__**`,
toCodeBlock(p.error) toCodeBlock(p.error, 0, true)
]; ];
return lines.join("\n"); return lines.join("\n");
} }
@ -130,7 +170,7 @@ async function printReport() {
}, },
{ {
title: "Discord Errors", title: "Discord Errors",
description: report.otherErrors.length ? toCodeBlock(report.otherErrors.join("\n")) : "None", description: report.otherErrors.length ? toCodeBlock(report.otherErrors.join("\n"), 0, true) : "None",
color: report.otherErrors.length ? 0xff0000 : 0x00ff00 color: report.otherErrors.length ? 0xff0000 : 0x00ff00
} }
] ]
@ -144,152 +184,137 @@ async function printReport() {
page.on("console", async e => { page.on("console", async e => {
const level = e.type(); const level = e.type();
const args = e.args(); const rawArgs = e.args();
const firstArg = (await args[0]?.jsonValue()); async function getText() {
if (firstArg === "PUPPETEER_TEST_DONE_SIGNAL") { try {
await browser.close(); return await Promise.all(
await printReport(); e.args().map(async a => {
process.exit(); return await maybeGetError(a) || await a.jsonValue();
})
).then(a => a.join(" ").trim());
} catch {
return e.text();
}
} }
const isVencord = (await args[0]?.jsonValue()) === "[Vencord]"; const firstArg = await rawArgs[0]?.jsonValue();
const isDebug = (await args[0]?.jsonValue()) === "[PUP_DEBUG]";
const isVencord = firstArg === "[Vencord]";
const isDebug = firstArg === "[PUP_DEBUG]";
outer:
if (isVencord) { if (isVencord) {
// make ci fail try {
process.exitCode = 1; var args = await Promise.all(e.args().map(a => a.jsonValue()));
} catch {
break outer;
}
const jsonArgs = await Promise.all(args.map(a => a.jsonValue())); const [, tag, message, otherMessage] = args as Array<string>;
const [, tag, message] = jsonArgs;
const cause = await maybeGetError(args[3]);
switch (tag) { switch (tag) {
case "WebpackInterceptor:": case "WebpackInterceptor:":
const [, plugin, type, id, regex] = (message as string).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) \(Module id is (.+?)\): (.+)/)!;
if (!patchFailMatch) break;
console.error(await getText());
process.exitCode = 1;
const [, plugin, type, id, regex] = patchFailMatch;
report.badPatches.push({ report.badPatches.push({
plugin, plugin,
type, type,
id, id,
match: regex, match: regex.replace(/\(\?:\[A-Za-z_\$\]\[\\w\$\]\*\)/g, "\\i"),
error: cause error: await maybeGetError(e.args()[3])
}); });
break; break;
case "PluginManager:": case "PluginManager:":
const [, name] = (message as string).match(/Failed to start (.+)/)!; const failedToStartMatch = message.match(/Failed to start (.+)/);
if (!failedToStartMatch) break;
console.error(await getText());
process.exitCode = 1;
const [, name] = failedToStartMatch;
report.badStarts.push({ report.badStarts.push({
plugin: name, plugin: name,
error: cause error: await maybeGetError(e.args()[3]) ?? "Unknown error"
}); });
break; break;
} case "LazyChunkLoader:":
} else if (isDebug) { console.error(await getText());
console.error(e.text());
} else if (level === "error") { switch (message) {
const text = await Promise.all( case "A fatal error occurred:":
e.args().map(async a => { process.exit(1);
try {
return await maybeGetError(a) || await a.jsonValue();
} catch (e) {
return a.toString();
} }
})
).then(a => a.join(" ").trim());
break;
case "Reporter:":
console.error(await getText());
if (text.length && !text.startsWith("Failed to load resource: the server responded with a status of")) { switch (message) {
console.error("Got unexpected error", text); case "A fatal error occurred:":
report.otherErrors.push(text); process.exit(1);
case "Webpack Find Fail:":
process.exitCode = 1;
report.badWebpackFinds.push(otherMessage);
break;
case "Finished test":
await browser.close();
await printReport();
process.exit();
}
}
}
if (isDebug) {
console.error(await getText());
} else if (level === "error") {
const text = await getText();
if (text.length && !text.startsWith("Failed to load resource: the server responded with a status of") && !text.includes("Webpack")) {
if (IGNORED_DISCORD_ERRORS.some(regex => text.match(regex))) {
report.ignoredErrors.push(text);
} else {
console.error("[Unexpected Error]", text);
report.otherErrors.push(text);
}
} }
} }
}); });
page.on("error", e => console.error("[Error]", e)); page.on("error", e => console.error("[Error]", e.message));
page.on("pageerror", e => console.error("[Page Error]", e)); page.on("pageerror", e => {
if (e.message.includes("Sentry successfully disabled")) return;
await page.setBypassCSP(true); if (!e.message.startsWith("Object") && !e.message.includes("Cannot find module")) {
console.error("[Page Error]", e.message);
function runTime(token: string) { report.otherErrors.push(e.message);
console.error("[PUP_DEBUG]", "Starting test..."); } else {
report.ignoredErrors.push(e.message);
try {
// spoof languages to not be suspicious
Object.defineProperty(navigator, "languages", {
get: function () {
return ["en-US", "en"];
},
});
// Monkey patch Logger to not log with custom css
// @ts-ignore
Vencord.Util.Logger.prototype._log = function (level, levelColor, args) {
if (level === "warn" || level === "error")
console[level]("[Vencord]", this.name + ":", ...args);
};
// force enable all plugins and patches
Vencord.Plugins.patches.length = 0;
Object.values(Vencord.Plugins.plugins).forEach(p => {
// Needs native server to run
if (p.name === "WebRichPresence (arRPC)") return;
Vencord.Settings.plugins[p.name].enabled = true;
p.patches?.forEach(patch => {
patch.plugin = p.name;
delete patch.predicate;
if (!Array.isArray(patch.replacement))
patch.replacement = [patch.replacement];
Vencord.Plugins.patches.push(patch);
});
});
Vencord.Webpack.waitFor(
"loginToken",
m => {
console.error("[PUP_DEBUG]", "Logging in with token...");
m.loginToken(token);
}
);
// force load all chunks
Vencord.Webpack.onceReady.then(() => setTimeout(async () => {
console.error("[PUP_DEBUG]", "Webpack is ready!");
const { wreq } = Vencord.Webpack;
console.error("[PUP_DEBUG]", "Loading all chunks...");
const ids = Function("return" + wreq.u.toString().match(/\{.+\}/s)![0])();
for (const id in ids) {
const isWasm = await fetch(wreq.p + wreq.u(id))
.then(r => r.text())
.then(t => t.includes(".module.wasm"));
if (!isWasm)
await wreq.e(id as any);
await new Promise(r => setTimeout(r, 150));
}
console.error("[PUP_DEBUG]", "Finished loading chunks!");
for (const patch of Vencord.Plugins.patches) {
if (!patch.all) {
new Vencord.Util.Logger("WebpackInterceptor").warn(`Patch by ${patch.plugin} found no module (Module id is -): ${patch.find}`);
}
}
setTimeout(() => console.log("PUPPETEER_TEST_DONE_SIGNAL"), 1000);
}, 1000));
} catch (e) {
console.error("[PUP_DEBUG]", "A fatal error occured");
console.error("[PUP_DEBUG]", e);
process.exit(1);
} }
});
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(`
${readFileSync("./dist/browser.js", "utf-8")} if (location.host.endsWith("discord.com")) {
${readFileSync("./dist/browser.js", "utf-8")};
;(${runTime.toString()})(${JSON.stringify(process.env.DISCORD_TOKEN)}); (${reporterRuntime.toString()})(${JSON.stringify(process.env.DISCORD_TOKEN)});
}
`); `);
await page.goto(CANARY ? "https://canary.discord.com/login" : "https://discord.com/login"); await page.goto(CANARY ? "https://canary.discord.com/login" : "https://discord.com/login");

3
scripts/header-new.txt Normal file
View file

@ -0,0 +1,3 @@
Vencord, a Discord client mod
Copyright (c) {year} {author}
SPDX-License-Identifier: GPL-3.0-or-later

17
scripts/header-old.txt Normal file
View file

@ -0,0 +1,17 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) {year} {author}
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

View file

@ -35,11 +35,11 @@ const ETAG_FILE = join(FILE_DIR, "etag.txt");
function getFilename() { function getFilename() {
switch (process.platform) { switch (process.platform) {
case "win32": case "win32":
return "VencordInstaller.exe"; return "VencordInstallerCli.exe";
case "darwin": case "darwin":
return "VencordInstaller.MacOS.zip"; return "VencordInstaller.MacOS.zip";
case "linux": case "linux":
return "VencordInstaller-" + (process.env.WAYLAND_DISPLAY ? "wayland" : "x11"); return "VencordInstallerCli-linux";
default: default:
throw new Error("Unsupported platform: " + process.platform); throw new Error("Unsupported platform: " + process.platform);
} }
@ -118,11 +118,15 @@ const installerBin = await ensureBinary();
console.log("Now running Installer..."); console.log("Now running Installer...");
execFileSync(installerBin, { try {
stdio: "inherit", execFileSync(installerBin, {
env: { stdio: "inherit",
...process.env, env: {
VENCORD_USER_DATA_DIR: BASE_DIR, ...process.env,
VENCORD_DEV_INSTALL: "1" VENCORD_USER_DATA_DIR: BASE_DIR,
} VENCORD_DEV_INSTALL: "1"
}); }
});
} catch {
console.error("Something went wrong. Please check the logs above.");
}

30
scripts/utils.mjs Normal file
View file

@ -0,0 +1,30 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* @param {string} filePath
* @returns {string | null}
*/
export function getPluginTarget(filePath) {
const pathParts = filePath.split(/[/\\]/);
if (/^index\.tsx?$/.test(pathParts.at(-1))) pathParts.pop();
const identifier = pathParts.at(-1).replace(/\.tsx?$/, "");
const identiferBits = identifier.split(".");
return identiferBits.length === 1 ? null : identiferBits.at(-1);
}

20
setup.bat Normal file
View file

@ -0,0 +1,20 @@
@echo off
:: Check if 'upstream' remote exists
git remote | findstr upstream >nul
if errorlevel 1 (
:: Add upstream remote
git remote add upstream https://github.com/Vendicated/Vencord.git
echo Added upstream remote
)
:: Disable push to upstream by setting push URL to 'no_push'
git remote set-url --push upstream no_push
echo Disabled push to upstream remote
:: Add alias for sync: fetch, merge, and push to origin
git config alias.sync "!git fetch upstream && git merge upstream/main && git push origin main"
echo Configured sync alias
echo Setup completed!

18
setup.sh Normal file
View file

@ -0,0 +1,18 @@
#!/bin/bash
# Add upstream remote if it doesn't exist
if ! git remote | grep -q 'upstream'; then
git remote add upstream https://github.com/Vendicated/Vencord.git
echo "Added upstream remote"
fi
# Disable push to upstream by removing its push URL
git remote set-url --push upstream no_push
echo "Disabled push to upstream remote"
# Add alias for sync: fetch, merge, and push to origin
git config alias.sync '!git fetch upstream && git merge upstream/main && git push origin main'
echo "Configured sync alias"
echo "Setup completed!"

View file

@ -17,6 +17,7 @@
*/ */
export * as Api from "./api"; export * as Api from "./api";
export * as Components from "./components";
export * as Plugins from "./plugins"; export * as Plugins from "./plugins";
export * as Util from "./utils"; export * as Util from "./utils";
export * as QuickCss from "./utils/quickCss"; export * as QuickCss from "./utils/quickCss";
@ -27,6 +28,10 @@ export { PlainSettings, Settings };
import "./utils/quickCss"; import "./utils/quickCss";
import "./webpack/patchWebpack"; import "./webpack/patchWebpack";
import { openUpdaterModal } from "@components/VencordSettings/UpdaterTab";
import { StartAt } from "@utils/types";
import { get as dsGet } from "./api/DataStore";
import { showNotification } from "./api/Notifications"; import { showNotification } from "./api/Notifications";
import { PlainSettings, Settings } from "./api/Settings"; import { PlainSettings, Settings } from "./api/Settings";
import { patches, PMLogger, startAllPlugins } from "./plugins"; import { patches, PMLogger, startAllPlugins } from "./plugins";
@ -37,7 +42,27 @@ import { checkForUpdates, update, UpdateLogger } from "./utils/updater";
import { onceReady } from "./webpack"; import { onceReady } from "./webpack";
import { SettingsRouter } from "./webpack/common"; import { SettingsRouter } from "./webpack/common";
if (IS_REPORTER) {
require("./debug/runReporter");
}
async function syncSettings() { async function syncSettings() {
// pre-check for local shared settings
if (
Settings.cloud.authenticated &&
!await dsGet("Vencord_cloudSecret") // this has been enabled due to local settings share or some other bug
) {
// show a notification letting them know and tell them how to fix it
showNotification({
title: "Cloud Integrations",
body: "We've noticed you have cloud integrations enabled in another client! Due to limitations, you will " +
"need to re-authenticate to continue using them. Click here to go to the settings page to do so!",
color: "var(--yellow-360)",
onClick: () => SettingsRouter.open("VencordCloud")
});
return;
}
if ( if (
Settings.cloud.settingsSync && // if it's enabled Settings.cloud.settingsSync && // if it's enabled
Settings.cloud.authenticated // if cloud integrations are enabled Settings.cloud.authenticated // if cloud integrations are enabled
@ -62,11 +87,11 @@ async function syncSettings() {
async function init() { async function init() {
await onceReady; await onceReady;
startAllPlugins(); startAllPlugins(StartAt.WebpackReady);
syncSettings(); syncSettings();
if (!IS_WEB) { if (!IS_WEB && !IS_UPDATER_DISABLED) {
try { try {
const isOutdated = await checkForUpdates(); const isOutdated = await checkForUpdates();
if (!isOutdated) return; if (!isOutdated) return;
@ -84,16 +109,13 @@ async function init() {
return; return;
} }
if (Settings.notifyAboutUpdates) setTimeout(() => showNotification({
setTimeout(() => showNotification({ title: "A Vencord update is available!",
title: "A Vencord update is available!", body: "Click here to view the update",
body: "Click here to view the update", permanent: true,
permanent: true, noPersist: true,
noPersist: true, onClick: openUpdaterModal!
onClick() { }), 10_000);
SettingsRouter.open("VencordUpdater");
}
}), 10_000);
} catch (err) { } catch (err) {
UpdateLogger.error("Failed to check for updates", err); UpdateLogger.error("Failed to check for updates", err);
} }
@ -113,13 +135,16 @@ async function init() {
} }
} }
startAllPlugins(StartAt.Init);
init(); init();
if (IS_DISCORD_DESKTOP && Settings.winNativeTitleBar && navigator.platform.toLowerCase().startsWith("win")) { document.addEventListener("DOMContentLoaded", () => {
document.addEventListener("DOMContentLoaded", () => { startAllPlugins(StartAt.DOMContentLoaded);
if (IS_DISCORD_DESKTOP && Settings.winNativeTitleBar && navigator.platform.toLowerCase().startsWith("win")) {
document.head.append(Object.assign(document.createElement("style"), { document.head.append(Object.assign(document.createElement("style"), {
id: "vencord-native-titlebar-style", id: "vencord-native-titlebar-style",
textContent: "[class*=titleBar-]{display: none!important}" textContent: "[class*=titleBar]{display: none!important}"
})); }));
}, { once: true }); }
} }, { once: true });

View file

@ -1,23 +1,14 @@
/* /*
* Vencord, a modification for Discord's desktop app * Vencord, a Discord client mod
* Copyright (c) 2022 * Copyright (c) 2023 Vendicated and contributors
* * SPDX-License-Identifier: GPL-3.0-or-later
* This program is free software: you can redistribute it and/or modify */
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { IpcEvents } from "@utils/IpcEvents"; import { PluginIpcMappings } from "@main/ipcPlugins";
import type { UserThemeHeader } from "@main/themes";
import { IpcEvents } from "@shared/IpcEvents";
import { IpcRes } from "@utils/types"; import { IpcRes } from "@utils/types";
import type { Settings } from "api/Settings";
import { ipcRenderer } from "electron"; import { ipcRenderer } from "electron";
function invoke<T = any>(event: IpcEvents, ...args: any[]) { function invoke<T = any>(event: IpcEvents, ...args: any[]) {
@ -28,7 +19,26 @@ export function sendSync<T = any>(event: IpcEvents, ...args: any[]) {
return ipcRenderer.sendSync(event, ...args) as T; return ipcRenderer.sendSync(event, ...args) as T;
} }
const PluginHelpers = {} as Record<string, Record<string, (...args: any[]) => Promise<any>>>;
const pluginIpcMap = sendSync<PluginIpcMappings>(IpcEvents.GET_PLUGIN_IPC_METHOD_MAP);
for (const [plugin, methods] of Object.entries(pluginIpcMap)) {
const map = PluginHelpers[plugin] = {};
for (const [methodName, method] of Object.entries(methods)) {
map[methodName] = (...args: any[]) => invoke(method as IpcEvents, ...args);
}
}
export default { export default {
themes: {
uploadTheme: (fileName: string, fileData: string) => invoke<void>(IpcEvents.UPLOAD_THEME, fileName, fileData),
deleteTheme: (fileName: string) => invoke<void>(IpcEvents.DELETE_THEME, fileName),
getThemesDir: () => invoke<string>(IpcEvents.GET_THEMES_DIR),
getThemesList: () => invoke<Array<UserThemeHeader>>(IpcEvents.GET_THEMES_LIST),
getThemeData: (fileName: string) => invoke<string | undefined>(IpcEvents.GET_THEME_DATA, fileName),
getSystemValues: () => invoke<Record<string, string>>(IpcEvents.GET_THEME_SYSTEM_VALUES),
},
updater: { updater: {
getUpdates: () => invoke<IpcRes<Record<"hash" | "author" | "message", string>[]>>(IpcEvents.GET_UPDATES), getUpdates: () => invoke<IpcRes<Record<"hash" | "author" | "message", string>[]>>(IpcEvents.GET_UPDATES),
update: () => invoke<IpcRes<boolean>>(IpcEvents.UPDATE), update: () => invoke<IpcRes<boolean>>(IpcEvents.UPDATE),
@ -37,8 +47,8 @@ export default {
}, },
settings: { settings: {
get: () => sendSync<string>(IpcEvents.GET_SETTINGS), get: () => sendSync<Settings>(IpcEvents.GET_SETTINGS),
set: (settings: string) => invoke<void>(IpcEvents.SET_SETTINGS, settings), set: (settings: Settings, pathToNotify?: string) => invoke<void>(IpcEvents.SET_SETTINGS, settings, pathToNotify),
getSettingsDir: () => invoke<string>(IpcEvents.GET_SETTINGS_DIR), getSettingsDir: () => invoke<string>(IpcEvents.GET_SETTINGS_DIR),
}, },
@ -50,6 +60,10 @@ export default {
ipcRenderer.on(IpcEvents.QUICK_CSS_UPDATE, (_, css) => cb(css)); ipcRenderer.on(IpcEvents.QUICK_CSS_UPDATE, (_, css) => cb(css));
}, },
addThemeChangeListener(cb: () => void) {
ipcRenderer.on(IpcEvents.THEME_UPDATE, () => cb());
},
openFile: () => invoke<void>(IpcEvents.OPEN_QUICKCSS), openFile: () => invoke<void>(IpcEvents.OPEN_QUICKCSS),
openEditor: () => invoke<void>(IpcEvents.OPEN_MONACO_EDITOR), openEditor: () => invoke<void>(IpcEvents.OPEN_MONACO_EDITOR),
}, },
@ -58,4 +72,6 @@ export default {
getVersions: () => process.versions as Partial<NodeJS.ProcessVersions>, getVersions: () => process.versions as Partial<NodeJS.ProcessVersions>,
openExternal: (url: string) => invoke<void>(IpcEvents.OPEN_EXTERNAL, url) openExternal: (url: string) => invoke<void>(IpcEvents.OPEN_EXTERNAL, url)
}, },
pluginHelpers: PluginHelpers
}; };

View file

@ -17,7 +17,6 @@
*/ */
import ErrorBoundary from "@components/ErrorBoundary"; import ErrorBoundary from "@components/ErrorBoundary";
import { User } from "discord-types/general";
import { ComponentType, HTMLProps } from "react"; import { ComponentType, HTMLProps } from "react";
import Plugins from "~plugins"; import Plugins from "~plugins";
@ -36,7 +35,7 @@ export interface ProfileBadge {
image?: string; image?: string;
link?: string; link?: string;
/** Action to perform when you click the badge */ /** Action to perform when you click the badge */
onClick?(): void; onClick?(event: React.MouseEvent<HTMLButtonElement, MouseEvent>, props: BadgeUserArgs): void;
/** 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 */
@ -45,6 +44,11 @@ export interface ProfileBadge {
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 */
key?: string; key?: string;
/**
* Allows dynamically returning multiple badges
*/
getBadges?(userInfo: BadgeUserArgs): ProfileBadge[];
} }
const Badges = new Set<ProfileBadge>(); const Badges = new Set<ProfileBadge>();
@ -53,7 +57,7 @@ const Badges = new Set<ProfileBadge>();
* Register a new badge with the Badges API * Register a new badge with the Badges API
* @param badge The badge to register * @param badge The badge to register
*/ */
export function addBadge(badge: ProfileBadge) { export function addProfileBadge(badge: ProfileBadge) {
badge.component &&= ErrorBoundary.wrap(badge.component, { noop: true }); badge.component &&= ErrorBoundary.wrap(badge.component, { noop: true });
Badges.add(badge); Badges.add(badge);
} }
@ -62,7 +66,7 @@ export function addBadge(badge: ProfileBadge) {
* Unregister a badge from the Badges API * Unregister a badge from the Badges API
* @param badge The badge to remove * @param badge The badge to remove
*/ */
export function removeBadge(badge: ProfileBadge) { export function removeProfileBadge(badge: ProfileBadge) {
return Badges.delete(badge); return Badges.delete(badge);
} }
@ -74,37 +78,25 @@ export function _getBadges(args: BadgeUserArgs) {
const badges = [] as ProfileBadge[]; const badges = [] as ProfileBadge[];
for (const badge of Badges) { for (const badge of Badges) {
if (!badge.shouldShow || badge.shouldShow(args)) { if (!badge.shouldShow || badge.shouldShow(args)) {
const b = badge.getBadges
? badge.getBadges(args).map(b => {
b.component &&= ErrorBoundary.wrap(b.component, { noop: true });
return b;
})
: [{ ...badge, ...args }];
badge.position === BadgePosition.START badge.position === BadgePosition.START
? badges.unshift({ ...badge, ...args }) ? badges.unshift(...b)
: badges.push({ ...badge, ...args }); : badges.push(...b);
} }
} }
const donorBadges = (Plugins.BadgeAPI as unknown as typeof import("../plugins/_api/badges").default).getDonorBadges(args.user.id); const donorBadges = (Plugins.BadgeAPI as unknown as typeof import("../plugins/_api/badges").default).getDonorBadges(args.userId);
if (donorBadges) badges.unshift(...donorBadges); if (donorBadges) badges.unshift(...donorBadges);
return badges; return badges;
} }
export interface BadgeUserArgs { export interface BadgeUserArgs {
user: User; userId: string;
profile: Profile; guildId: string;
premiumSince: Date;
premiumGuildSince?: Date;
}
interface ConnectedAccount {
type: string;
id: string;
name: string;
verified: boolean;
}
interface Profile {
connectedAccounts: ConnectedAccount[];
premiumType: number;
premiumSince: string;
premiumGuildSince?: any;
lastFetched: number;
profileFetchFailed: boolean;
application?: any;
} }

4
src/api/ChatButton.css Normal file
View file

@ -0,0 +1,4 @@
.vc-chatbar-button {
display: flex;
align-items: center;
}

130
src/api/ChatButtons.tsx Normal file
View file

@ -0,0 +1,130 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import "./ChatButton.css";
import ErrorBoundary from "@components/ErrorBoundary";
import { Logger } from "@utils/Logger";
import { waitFor } from "@webpack";
import { Button, ButtonWrapperClasses, Tooltip } from "@webpack/common";
import { Channel } from "discord-types/general";
import { HTMLProps, JSX, MouseEventHandler, ReactNode } from "react";
let ChannelTextAreaClasses: Record<"button" | "buttonContainer", string>;
waitFor(["buttonContainer", "channelTextArea"], m => ChannelTextAreaClasses = m);
export interface ChatBarProps {
channel: Channel;
disabled: boolean;
isEmpty: boolean;
type: {
analyticsName: string;
attachments: boolean;
autocomplete: {
addReactionShortcut: boolean,
forceChatLayer: boolean,
reactions: boolean;
},
commands: {
enabled: boolean;
},
drafts: {
type: number,
commandType: number,
autoSave: boolean;
},
emojis: {
button: boolean;
},
gifs: {
button: boolean,
allowSending: boolean;
},
gifts: {
button: boolean;
},
permissions: {
requireSendMessages: boolean;
},
showThreadPromptOnReply: boolean,
stickers: {
button: boolean,
allowSending: boolean,
autoSuggest: boolean;
},
users: {
allowMentioning: boolean;
},
submit: {
button: boolean,
ignorePreference: boolean,
disableEnterToSubmit: boolean,
clearOnSubmit: boolean,
useDisabledStylesOnSubmit: boolean;
},
uploadLongMessages: boolean,
upsellLongMessages: {
iconOnly: boolean;
},
showCharacterCount: boolean,
sedReplace: boolean;
};
}
export type ChatBarButtonFactory = (props: ChatBarProps & { isMainChat: boolean; }) => JSX.Element | null;
const buttonFactories = new Map<string, ChatBarButtonFactory>();
const logger = new Logger("ChatButtons");
export function _injectButtons(buttons: ReactNode[], props: ChatBarProps) {
if (props.disabled) return;
for (const [key, Button] of buttonFactories) {
buttons.push(
<ErrorBoundary noop key={key} onError={e => logger.error(`Failed to render ${key}`, e.error)}>
<Button {...props} isMainChat={props.type.analyticsName === "normal"} />
</ErrorBoundary>
);
}
}
export const addChatBarButton = (id: string, button: ChatBarButtonFactory) => buttonFactories.set(id, button);
export const removeChatBarButton = (id: string) => buttonFactories.delete(id);
export interface ChatBarButtonProps {
children: ReactNode;
tooltip: string;
onClick: MouseEventHandler<HTMLButtonElement>;
onContextMenu?: MouseEventHandler<HTMLButtonElement>;
onAuxClick?: MouseEventHandler<HTMLButtonElement>;
buttonProps?: Omit<HTMLProps<HTMLButtonElement>, "size" | "onClick" | "onContextMenu" | "onAuxClick">;
}
export const ChatBarButton = ErrorBoundary.wrap((props: ChatBarButtonProps) => {
return (
<Tooltip text={props.tooltip}>
{({ onMouseEnter, onMouseLeave }) => (
<div className={`expression-picker-chat-input-button ${ChannelTextAreaClasses?.buttonContainer ?? ""} vc-chatbar-button`}>
<Button
aria-label={props.tooltip}
size=""
look={Button.Looks.BLANK}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
innerClassName={`${ButtonWrapperClasses.button} ${ChannelTextAreaClasses?.button}`}
onClick={props.onClick}
onContextMenu={props.onContextMenu}
onAuxClick={props.onAuxClick}
{...props.buttonProps}
>
<div className={ButtonWrapperClasses.buttonWrapper}>
{props.children}
</div>
</Button>
</div>
)}
</Tooltip>
);
}, { noop: true });

View file

@ -16,16 +16,15 @@
* 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 { mergeDefaults } from "@utils/misc"; import { mergeDefaults } from "@utils/mergeDefaults";
import { findByCodeLazy, findByPropsLazy } from "@webpack"; import { findByCodeLazy } from "@webpack";
import { 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 = findByCodeLazy('username:"Clyde"');
const MessageSender = findByPropsLazy("receiveMessage");
export function generateId() { export function generateId() {
return `-${SnowflakeUtils.fromTimestamp(Date.now())}`; return `-${SnowflakeUtils.fromTimestamp(Date.now())}`;
@ -40,7 +39,7 @@ export function generateId() {
export function sendBotMessage(channelId: string, message: PartialDeep<Message>): Message { export function sendBotMessage(channelId: string, message: PartialDeep<Message>): Message {
const botMessage = createBotMessage({ channelId, content: "", embeds: [] }); const botMessage = createBotMessage({ channelId, content: "", embeds: [] });
MessageSender.receiveMessage(channelId, mergeDefaults(message, botMessage)); MessageActions.receiveMessage(channelId, mergeDefaults(message, botMessage));
return message as Message; return message as Message;
} }
@ -55,5 +54,5 @@ export function sendBotMessage(channelId: string, message: PartialDeep<Message>)
export function findOption<T>(args: Argument[], name: string): T & {} | undefined; export function findOption<T>(args: Argument[], name: string): T & {} | undefined;
export function findOption<T>(args: Argument[], name: string, fallbackValue: T): T & {}; export function findOption<T>(args: Argument[], name: string, fallbackValue: T): T & {};
export function findOption(args: Argument[], name: string, fallbackValue?: any) { export function findOption(args: Argument[], name: string, fallbackValue?: any) {
return (args.find(a => a.name === name)?.value || fallbackValue) as any; return (args.find(a => a.name === name)?.value ?? fallbackValue) as any;
} }

View file

@ -16,6 +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 { Logger } from "@utils/Logger";
import { makeCodeblock } from "@utils/text"; import { makeCodeblock } from "@utils/text";
import { sendBotMessage } from "./commandHelpers"; import { sendBotMessage } from "./commandHelpers";
@ -46,10 +47,10 @@ export let RequiredMessageOption: Option = ReqPlaceholder;
export const _init = function (cmds: Command[]) { export const _init = function (cmds: Command[]) {
try { try {
BUILT_IN = cmds; BUILT_IN = cmds;
OptionalMessageOption = cmds.find(c => c.name === "shrug")!.options![0]; OptionalMessageOption = cmds.find(c => (c.untranslatedName || c.displayName) === "shrug")!.options![0];
RequiredMessageOption = cmds.find(c => c.name === "me")!.options![0]; RequiredMessageOption = cmds.find(c => (c.untranslatedName || c.displayName) === "me")!.options![0];
} catch (e) { } catch (e) {
console.error("Failed to load CommandsApi"); new Logger("CommandsAPI").error("Failed to load CommandsApi", e, " - cmds is", cmds);
} }
return cmds; return cmds;
} as never; } as never;
@ -109,6 +110,7 @@ function registerSubCommands(cmd: Command, plugin: string) {
const subCmd = { const subCmd = {
...cmd, ...cmd,
...o, ...o,
options: o.options !== undefined ? o.options : undefined,
type: ApplicationCommandType.CHAT_INPUT, type: ApplicationCommandType.CHAT_INPUT,
name: `${cmd.name} ${o.name}`, name: `${cmd.name} ${o.name}`,
id: `${o.name}-${cmd.id}`, id: `${o.name}-${cmd.id}`,
@ -138,6 +140,8 @@ export function registerCommand<C extends Command>(command: C, plugin: string) {
throw new Error(`Command '${command.name}' already exists.`); throw new Error(`Command '${command.name}' already exists.`);
command.isVencordCommand = true; command.isVencordCommand = true;
command.untranslatedName ??= command.name;
command.untranslatedDescription ??= command.description;
command.id ??= `-${BUILT_IN.length + 1}`; command.id ??= `-${BUILT_IN.length + 1}`;
command.applicationId ??= "-1"; // BUILT_IN; command.applicationId ??= "-1"; // BUILT_IN;
command.type ??= ApplicationCommandType.CHAT_INPUT; command.type ??= ApplicationCommandType.CHAT_INPUT;

View file

@ -93,8 +93,10 @@ export interface Command {
isVencordCommand?: boolean; isVencordCommand?: boolean;
name: string; name: string;
untranslatedName?: string;
displayName?: string; displayName?: string;
description: string; description: string;
untranslatedDescription?: string;
displayDescription?: string; displayDescription?: string;
options?: Option[]; options?: Option[];

View file

@ -17,22 +17,20 @@
*/ */
import { Logger } from "@utils/Logger"; import { Logger } from "@utils/Logger";
import { Menu, React } from "@webpack/common";
import type { ReactElement } from "react"; import type { ReactElement } from "react";
type ContextMenuPatchCallbackReturn = (() => void) | void;
/** /**
* @param children The rendered context menu elements * @param children The rendered context menu elements
* @param args Any arguments passed into making the context menu, like the guild, channel, user or message for example * @param args Any arguments passed into making the context menu, like the guild, channel, user or message for example
* @returns A callback which is only ran once used to modify the context menu elements (Use to avoid duplicates)
*/ */
export type NavContextMenuPatchCallback = (children: Array<ReactElement | null>, ...args: Array<any>) => ContextMenuPatchCallbackReturn; export type NavContextMenuPatchCallback = (children: Array<ReactElement<any> | null>, ...args: Array<any>) => void;
/** /**
* @param navId The navId of the context menu being patched * @param navId The navId of the context menu being patched
* @param children The rendered context menu elements * @param children The rendered context menu elements
* @param args Any arguments passed into making the context menu, like the guild, channel, user or message for example * @param args Any arguments passed into making the context menu, like the guild, channel, user or message for example
* @returns A callback which is only ran once used to modify the context menu elements (Use to avoid duplicates)
*/ */
export type GlobalContextMenuPatchCallback = (navId: string, children: Array<ReactElement | null>, ...args: Array<any>) => ContextMenuPatchCallbackReturn; export type GlobalContextMenuPatchCallback = (navId: string, children: Array<ReactElement<any> | null>, ...args: Array<any>) => void;
const ContextMenuLogger = new Logger("ContextMenu"); const ContextMenuLogger = new Logger("ContextMenu");
@ -69,10 +67,10 @@ export function addGlobalContextMenuPatch(patch: GlobalContextMenuPatchCallback)
* Remove a context menu patch * Remove a context menu patch
* @param navId The navId(s) for the context menu(s) to remove the patch * @param navId The navId(s) for the context menu(s) to remove the patch
* @param patch The patch to be removed * @param patch The patch to be removed
* @returns Wheter the patch was sucessfully removed from the context menu(s) * @returns Whether the patch was successfully removed from the context menu(s)
*/ */
export function removeContextMenuPatch<T extends string | Array<string>>(navId: T, patch: NavContextMenuPatchCallback): T extends string ? boolean : Array<boolean> { export function removeContextMenuPatch<T extends string | Array<string>>(navId: T, patch: NavContextMenuPatchCallback): T extends string ? boolean : Array<boolean> {
const navIds = Array.isArray(navId) ? navId : [navId as string]; const navIds: string[] = Array.isArray(navId) ? navId : [navId];
const results = navIds.map(id => navPatches.get(id)?.delete(patch) ?? false); const results = navIds.map(id => navPatches.get(id)?.delete(patch) ?? false);
@ -82,7 +80,7 @@ export function removeContextMenuPatch<T extends string | Array<string>>(navId:
/** /**
* Remove a global context menu patch * Remove a global context menu patch
* @param patch The patch to be removed * @param patch The patch to be removed
* @returns Wheter the patch was sucessfully removed * @returns Whether the patch was successfully removed
*/ */
export function removeGlobalContextMenuPatch(patch: GlobalContextMenuPatchCallback): boolean { export function removeGlobalContextMenuPatch(patch: GlobalContextMenuPatchCallback): boolean {
return globalPatches.delete(patch); return globalPatches.delete(patch);
@ -92,15 +90,21 @@ export function removeGlobalContextMenuPatch(patch: GlobalContextMenuPatchCallba
* A helper function for finding the children array of a group nested inside a context menu based on the id(s) of its children * A helper function for finding the children array of a group nested inside a context menu based on the id(s) of its children
* @param id The id of the child. If an array is specified, all ids will be tried * @param id The id of the child. If an array is specified, all ids will be tried
* @param children The context menu children * @param children The context menu children
* @param matchSubstring Whether to check if the id is a substring of the child id
*/ */
export function findGroupChildrenByChildId(id: string | string[], children: Array<ReactElement | null>, _itemsArray?: Array<ReactElement | null>): Array<ReactElement | null> | null { export function findGroupChildrenByChildId(id: string | string[], children: Array<ReactElement<any> | null | undefined>, matchSubstring = false): Array<ReactElement<any> | null | undefined> | null {
for (const child of children) { for (const child of children) {
if (child == null) continue; if (child == null) continue;
if (Array.isArray(child)) {
const found = findGroupChildrenByChildId(id, child, matchSubstring);
if (found !== null) return found;
}
if ( if (
(Array.isArray(id) && id.some(id => child.props?.id === id)) (Array.isArray(id) && id.some(id => matchSubstring ? child.props?.id?.includes(id) : child.props?.id === id))
|| child.props?.id === id || (matchSubstring ? child.props?.id?.includes(id) : child.props?.id === id)
) return _itemsArray ?? null; ) return children;
let nextChildren = child.props?.children; let nextChildren = child.props?.children;
if (nextChildren) { if (nextChildren) {
@ -109,7 +113,7 @@ export function findGroupChildrenByChildId(id: string | string[], children: Arra
child.props.children = nextChildren; child.props.children = nextChildren;
} }
const found = findGroupChildrenByChildId(id, nextChildren, nextChildren); const found = findGroupChildrenByChildId(id, nextChildren, matchSubstring);
if (found !== null) return found; if (found !== null) return found;
} }
} }
@ -118,18 +122,21 @@ export function findGroupChildrenByChildId(id: string | string[], children: Arra
} }
interface ContextMenuProps { interface ContextMenuProps {
contextMenuApiArguments?: Array<any>; contextMenuAPIArguments?: Array<any>;
navId: string; navId: string;
children: Array<ReactElement | null>; children: Array<ReactElement<any> | null>;
"aria-label": string; "aria-label": string;
onSelect: (() => void) | undefined; onSelect: (() => void) | undefined;
onClose: (callback: (...args: Array<any>) => any) => void; onClose: (callback: (...args: Array<any>) => any) => void;
} }
const patchedMenus = new WeakSet(); export function _usePatchContextMenu(props: ContextMenuProps) {
props = {
...props,
children: cloneMenuChildren(props.children),
};
export function _patchContextMenu(props: ContextMenuProps) { props.contextMenuAPIArguments ??= [];
props.contextMenuApiArguments ??= [];
const contextMenuPatches = navPatches.get(props.navId); const contextMenuPatches = navPatches.get(props.navId);
if (!Array.isArray(props.children)) props.children = [props.children]; if (!Array.isArray(props.children)) props.children = [props.children];
@ -137,8 +144,7 @@ export function _patchContextMenu(props: ContextMenuProps) {
if (contextMenuPatches) { if (contextMenuPatches) {
for (const patch of contextMenuPatches) { for (const patch of contextMenuPatches) {
try { try {
const callback = patch(props.children, ...props.contextMenuApiArguments); patch(props.children, ...props.contextMenuAPIArguments);
if (!patchedMenus.has(props)) callback?.();
} catch (err) { } catch (err) {
ContextMenuLogger.error(`Patch for ${props.navId} errored,`, err); ContextMenuLogger.error(`Patch for ${props.navId} errored,`, err);
} }
@ -147,12 +153,30 @@ export function _patchContextMenu(props: ContextMenuProps) {
for (const patch of globalPatches) { for (const patch of globalPatches) {
try { try {
const callback = patch(props.navId, props.children, ...props.contextMenuApiArguments); patch(props.navId, props.children, ...props.contextMenuAPIArguments);
if (!patchedMenus.has(props)) callback?.();
} catch (err) { } catch (err) {
ContextMenuLogger.error("Global patch errored,", err); ContextMenuLogger.error("Global patch errored,", err);
} }
} }
patchedMenus.add(props); return props;
}
function cloneMenuChildren(obj: ReactElement<any> | Array<ReactElement<any> | null> | null) {
if (Array.isArray(obj)) {
return obj.map(cloneMenuChildren);
}
if (React.isValidElement(obj)) {
obj = React.cloneElement(obj);
if (
obj?.props?.children &&
(obj.type !== Menu.MenuControlItem || obj.type === Menu.MenuControlItem && obj.props.control != null)
) {
obj.props.children = cloneMenuChildren(obj.props.children);
}
}
return obj;
} }

View file

@ -1,4 +1,4 @@
/* eslint-disable header/header */ /* eslint-disable simple-header/header */
/*! /*!
* idb-keyval v6.2.0 * idb-keyval v6.2.0
@ -49,7 +49,7 @@ let defaultGetStoreFunc: UseStore | undefined;
function defaultGetStore() { function defaultGetStore() {
if (!defaultGetStoreFunc) { if (!defaultGetStoreFunc) {
defaultGetStoreFunc = createStore("VencordData", "VencordStore"); defaultGetStoreFunc = createStore(!IS_REPORTER ? "VencordData" : "VencordDataReporter", "VencordStore");
} }
return defaultGetStoreFunc; return defaultGetStoreFunc;
} }

View file

@ -16,11 +16,12 @@
* 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 ErrorBoundary from "@components/ErrorBoundary";
import { Channel, User } from "discord-types/general/index.js"; import { Channel, User } from "discord-types/general/index.js";
import { JSX } from "react";
interface DecoratorProps { interface DecoratorProps {
activities: any[]; activities: any[];
canUseAvatarDecorations: boolean;
channel: Channel; channel: Channel;
/** /**
* Only for DM members * Only for DM members
@ -39,27 +40,39 @@ interface DecoratorProps {
user: User; user: User;
[key: string]: any; [key: string]: any;
} }
export type Decorator = (props: DecoratorProps) => JSX.Element | null; export type MemberListDecoratorFactory = (props: DecoratorProps) => JSX.Element | null;
type OnlyIn = "guilds" | "dms"; type OnlyIn = "guilds" | "dms";
export const decorators = new Map<string, { decorator: Decorator, onlyIn?: OnlyIn; }>(); export const decoratorsFactories = new Map<string, { render: MemberListDecoratorFactory, onlyIn?: OnlyIn; }>();
export function addDecorator(identifier: string, decorator: Decorator, onlyIn?: OnlyIn) { export function addMemberListDecorator(identifier: string, render: MemberListDecoratorFactory, onlyIn?: OnlyIn) {
decorators.set(identifier, { decorator, onlyIn }); decoratorsFactories.set(identifier, { render, onlyIn });
} }
export function removeDecorator(identifier: string) { export function removeMemberListDecorator(identifier: string) {
decorators.delete(identifier); decoratorsFactories.delete(identifier);
} }
export function __addDecoratorsToList(props: DecoratorProps): (JSX.Element | null)[] { export function __getDecorators(props: DecoratorProps): JSX.Element {
const isInGuild = !!(props.guildId); const isInGuild = !!(props.guildId);
return [...decorators.values()].map(decoratorObj => {
const { decorator, onlyIn } = decoratorObj; const decorators = Array.from(
// this can most likely be done cleaner decoratorsFactories.entries(),
if (!onlyIn || (onlyIn === "guilds" && isInGuild) || (onlyIn === "dms" && !isInGuild)) { ([key, { render: Decorator, onlyIn }]) => {
return decorator(props); if ((onlyIn === "guilds" && !isInGuild) || (onlyIn === "dms" && isInGuild))
return null;
return (
<ErrorBoundary noop key={key} message={`Failed to render ${key} Member List Decorator`}>
<Decorator {...props} />
</ErrorBoundary>
);
} }
return null; );
});
return (
<div className="vc-member-list-decorators-wrapper">
{decorators}
</div>
);
} }

View file

@ -16,26 +16,29 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
export type AccessoryCallback = (props: Record<string, any>) => JSX.Element | null | Array<JSX.Element | null>; import ErrorBoundary from "@components/ErrorBoundary";
export type Accessory = { import { JSX, ReactNode } from "react";
callback: AccessoryCallback;
export type MessageAccessoryFactory = (props: Record<string, any>) => ReactNode;
export type MessageAccessory = {
render: MessageAccessoryFactory;
position?: number; position?: number;
}; };
export const accessories = new Map<String, Accessory>(); export const accessories = new Map<string, MessageAccessory>();
export function addAccessory( export function addMessageAccessory(
identifier: string, identifier: string,
callback: AccessoryCallback, render: MessageAccessoryFactory,
position?: number position?: number
) { ) {
accessories.set(identifier, { accessories.set(identifier, {
callback, render,
position, position,
}); });
} }
export function removeAccessory(identifier: string) { export function removeMessageAccessory(identifier: string) {
accessories.delete(identifier); accessories.delete(identifier);
} }
@ -43,15 +46,12 @@ export function _modifyAccessories(
elements: JSX.Element[], elements: JSX.Element[],
props: Record<string, any> props: Record<string, any>
) { ) {
for (const accessory of accessories.values()) { for (const [key, accessory] of accessories.entries()) {
let accessories = accessory.callback(props); const res = (
if (accessories == null) <ErrorBoundary message={`Failed to render ${key} Message Accessory`} key={key}>
continue; <accessory.render {...props} />
</ErrorBoundary>
if (!Array.isArray(accessories)) );
accessories = [accessories];
else if (accessories.length === 0)
continue;
elements.splice( elements.splice(
accessory.position != null accessory.position != null
@ -60,7 +60,7 @@ export function _modifyAccessories(
: accessory.position : accessory.position
: elements.length, : elements.length,
0, 0,
...accessories.filter(e => e != null) as JSX.Element[] res
); );
} }

View file

@ -16,9 +16,11 @@
* 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 ErrorBoundary from "@components/ErrorBoundary";
import { Channel, Message } from "discord-types/general/index.js"; import { Channel, Message } from "discord-types/general/index.js";
import { JSX } from "react";
interface DecorationProps { export interface MessageDecorationProps {
author: { author: {
/** /**
* Will be username if the user has no nickname * Will be username if the user has no nickname
@ -44,20 +46,31 @@ interface DecorationProps {
message: Message; message: Message;
[key: string]: any; [key: string]: any;
} }
export type Decoration = (props: DecorationProps) => JSX.Element | null; export type MessageDecorationFactory = (props: MessageDecorationProps) => JSX.Element | null;
export const decorations = new Map<string, Decoration>(); export const decorationsFactories = new Map<string, MessageDecorationFactory>();
export function addDecoration(identifier: string, decoration: Decoration) { export function addMessageDecoration(identifier: string, decoration: MessageDecorationFactory) {
decorations.set(identifier, decoration); decorationsFactories.set(identifier, decoration);
} }
export function removeDecoration(identifier: string) { export function removeMessageDecoration(identifier: string) {
decorations.delete(identifier); decorationsFactories.delete(identifier);
} }
export function __addDecorationsToMessage(props: DecorationProps): (JSX.Element | null)[] { export function __addDecorationsToMessage(props: MessageDecorationProps): JSX.Element {
return [...decorations.values()].map(decoration => { const decorations = Array.from(
return decoration(props); decorationsFactories.entries(),
}); ([key, Decoration]) => (
<ErrorBoundary noop message={`Failed to render ${key} Message Decoration`} key={key}>
<Decoration {...props} />
</ErrorBoundary>
)
);
return (
<div className="vc-message-decorations-wrapper">
{decorations}
</div>
);
} }

View file

@ -73,18 +73,18 @@ export interface MessageExtra {
openWarningPopout: (props: any) => any; openWarningPopout: (props: any) => any;
} }
export type SendListener = (channelId: string, messageObj: MessageObject, extra: MessageExtra) => Promisable<void | { cancel: boolean; }>; export type MessageSendListener = (channelId: string, messageObj: MessageObject, extra: MessageExtra) => Promisable<void | { cancel: boolean; }>;
export type EditListener = (channelId: string, messageId: string, messageObj: MessageObject) => Promisable<void>; export type MessageEditListener = (channelId: string, messageId: string, messageObj: MessageObject) => Promisable<void | { cancel: boolean; }>;
const sendListeners = new Set<SendListener>(); const sendListeners = new Set<MessageSendListener>();
const editListeners = new Set<EditListener>(); const editListeners = new Set<MessageEditListener>();
export async function _handlePreSend(channelId: string, messageObj: MessageObject, extra: MessageExtra, replyOptions: MessageReplyOptions) { export async function _handlePreSend(channelId: string, messageObj: MessageObject, extra: MessageExtra, replyOptions: MessageReplyOptions) {
extra.replyOptions = replyOptions; extra.replyOptions = replyOptions;
for (const listener of sendListeners) { for (const listener of sendListeners) {
try { try {
const result = await listener(channelId, messageObj, extra); const result = await listener(channelId, messageObj, extra);
if (result && result.cancel === true) { if (result?.cancel) {
return true; return true;
} }
} catch (e) { } catch (e) {
@ -97,39 +97,43 @@ export async function _handlePreSend(channelId: string, messageObj: MessageObjec
export async function _handlePreEdit(channelId: string, messageId: string, messageObj: MessageObject) { export async function _handlePreEdit(channelId: string, messageId: string, messageObj: MessageObject) {
for (const listener of editListeners) { for (const listener of editListeners) {
try { try {
await listener(channelId, messageId, messageObj); const result = await listener(channelId, messageId, messageObj);
if (result?.cancel) {
return true;
}
} catch (e) { } catch (e) {
MessageEventsLogger.error("MessageEditHandler: Listener encountered an unknown error\n", e); MessageEventsLogger.error("MessageEditHandler: Listener encountered an unknown error\n", e);
} }
} }
return false;
} }
/** /**
* Note: This event fires off before a message is sent, allowing you to edit the message. * Note: This event fires off before a message is sent, allowing you to edit the message.
*/ */
export function addPreSendListener(listener: SendListener) { export function addMessagePreSendListener(listener: MessageSendListener) {
sendListeners.add(listener); sendListeners.add(listener);
return listener; return listener;
} }
/** /**
* Note: This event fires off before a message's edit is applied, allowing you to further edit the message. * Note: This event fires off before a message's edit is applied, allowing you to further edit the message.
*/ */
export function addPreEditListener(listener: EditListener) { export function addMessagePreEditListener(listener: MessageEditListener) {
editListeners.add(listener); editListeners.add(listener);
return listener; return listener;
} }
export function removePreSendListener(listener: SendListener) { export function removeMessagePreSendListener(listener: MessageSendListener) {
return sendListeners.delete(listener); return sendListeners.delete(listener);
} }
export function removePreEditListener(listener: EditListener) { export function removeMessagePreEditListener(listener: MessageEditListener) {
return editListeners.delete(listener); return editListeners.delete(listener);
} }
// Message clicks // Message clicks
type ClickListener = (message: Message, channel: Channel, event: MouseEvent) => void; export type MessageClickListener = (message: Message, channel: Channel, event: MouseEvent) => void;
const listeners = new Set<ClickListener>(); const listeners = new Set<MessageClickListener>();
export function _handleClick(message: Message, channel: Channel, event: MouseEvent) { export function _handleClick(message: Message, channel: Channel, event: MouseEvent) {
// message object may be outdated, so (try to) fetch latest one // message object may be outdated, so (try to) fetch latest one
@ -143,11 +147,11 @@ export function _handleClick(message: Message, channel: Channel, event: MouseEve
} }
} }
export function addClickListener(listener: ClickListener) { export function addMessageClickListener(listener: MessageClickListener) {
listeners.add(listener); listeners.add(listener);
return listener; return listener;
} }
export function removeClickListener(listener: ClickListener) { export function removeMessageClickListener(listener: MessageClickListener) {
return listeners.delete(listener); return listeners.delete(listener);
} }

View file

@ -16,54 +16,59 @@
* 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 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 { MouseEventHandler } from "react"; import type { ComponentType, MouseEventHandler } from "react";
const logger = new Logger("MessagePopover"); const logger = new Logger("MessagePopover");
export interface ButtonItem { export interface MessagePopoverButtonItem {
key?: string, key?: string,
label: string, label: string,
icon: React.ComponentType<any>, icon: ComponentType<any>,
message: Message, message: Message,
channel: Channel, channel: Channel,
onClick?: MouseEventHandler<HTMLButtonElement>, onClick?: MouseEventHandler<HTMLButtonElement>,
onContextMenu?: MouseEventHandler<HTMLButtonElement>; onContextMenu?: MouseEventHandler<HTMLButtonElement>;
} }
export type getButtonItem = (message: Message) => ButtonItem | null; export type MessagePopoverButtonFactory = (message: Message) => MessagePopoverButtonItem | null;
export const buttons = new Map<string, getButtonItem>(); export const buttons = new Map<string, MessagePopoverButtonFactory>();
export function addButton( export function addMessagePopoverButton(
identifier: string, identifier: string,
item: getButtonItem, item: MessagePopoverButtonFactory,
) { ) {
buttons.set(identifier, item); buttons.set(identifier, item);
} }
export function removeButton(identifier: string) { export function removeMessagePopoverButton(identifier: string) {
buttons.delete(identifier); buttons.delete(identifier);
} }
export function _buildPopoverElements( export function _buildPopoverElements(
msg: Message, Component: React.ComponentType<MessagePopoverButtonItem>,
makeButton: (item: ButtonItem) => React.ComponentType message: Message
) { ) {
const items = [] as React.ComponentType[]; const items: React.ReactNode[] = [];
for (const [identifier, getItem] of buttons.entries()) { for (const [identifier, getItem] of buttons.entries()) {
try { try {
const item = getItem(msg); const item = getItem(message);
if (item) { if (item) {
item.key ??= identifier; item.key ??= identifier;
items.push(makeButton(item)); items.push(
<ErrorBoundary noop>
<Component {...item} />
</ErrorBoundary>
);
} }
} catch (err) { } catch (err) {
logger.error(`[${identifier}]`, err); logger.error(`[${identifier}]`, err);
} }
} }
return items; return <>{items}</>;
} }

29
src/api/MessageUpdater.ts Normal file
View file

@ -0,0 +1,29 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { MessageCache, MessageStore } from "@webpack/common";
import { FluxStore } from "@webpack/types";
import { Message } from "discord-types/general";
/**
* Update and re-render a message
* @param channelId The channel id of the message
* @param messageId The message id
* @param fields The fields of the message to change. Leave empty if you just want to re-render
*/
export function updateMessage(channelId: string, messageId: string, fields?: Partial<Message & Record<string, any>>) {
const channelMessageCache = MessageCache.getOrCreate(channelId);
if (!channelMessageCache.has(messageId)) return;
// To cause a message to re-render, we basically need to create a new instance of the message and obtain a new reference
// If we have fields to modify we can use the merge method of the class, otherwise we just create a new instance with the old fields
const newChannelMessageCache = channelMessageCache.update(messageId, (oldMessage: any) => {
return fields ? oldMessage.merge(fields) : new oldMessage.constructor(oldMessage);
});
MessageCache.commit(newChannelMessageCache);
(MessageStore as unknown as FluxStore).emitChange();
}

View file

@ -113,7 +113,7 @@ export default ErrorBoundary.wrap(function NotificationComponent({
{timeout !== 0 && !permanent && ( {timeout !== 0 && !permanent && (
<div <div
className="vc-notification-progressbar" className="vc-notification-progressbar"
style={{ width: `${(1 - timeoutProgress) * 100}%`, backgroundColor: color || "var(--brand-experiment)" }} style={{ width: `${(1 - timeoutProgress) * 100}%`, backgroundColor: color || "var(--brand-500)" }}
/> />
)} )}
</button> </button>

View file

@ -100,6 +100,7 @@ export async function showNotification(data: NotificationData) {
const n = new Notification(title, { const n = new Notification(title, {
body, body,
icon, icon,
// @ts-expect-error ts is drunk
image image
}); });
n.onclick = onClick; n.onclick = onClick;

View file

@ -19,9 +19,11 @@
import * as DataStore from "@api/DataStore"; import * as DataStore from "@api/DataStore";
import { Settings } from "@api/Settings"; import { Settings } from "@api/Settings";
import { classNameFactory } from "@api/Styles"; import { classNameFactory } from "@api/Styles";
import { Flex } from "@components/Flex";
import { openNotificationSettingsModal } from "@components/VencordSettings/NotificationSettings";
import { closeModal, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal"; import { closeModal, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
import { useAwaiter } from "@utils/react"; import { useAwaiter } from "@utils/react";
import { Alerts, Button, Forms, moment, React, Text, Timestamp, useEffect, useReducer, useState } from "@webpack/common"; import { Alerts, Button, Forms, React, Text, Timestamp, useEffect, useReducer, useState } from "@webpack/common";
import { nanoid } from "nanoid"; import { nanoid } from "nanoid";
import type { DispatchWithoutAction } from "react"; import type { DispatchWithoutAction } from "react";
@ -129,7 +131,7 @@ function NotificationEntry({ data }: { data: PersistentNotificationData; }) {
richBody={ richBody={
<div className={cl("body")}> <div className={cl("body")}>
{data.body} {data.body}
<Timestamp timestamp={moment(data.timestamp)} className={cl("timestamp")} /> <Timestamp timestamp={new Date(data.timestamp)} className={cl("timestamp")} />
</div> </div>
} }
/> />
@ -170,24 +172,31 @@ function LogModal({ modalProps, close }: { modalProps: ModalProps; close(): void
</ModalContent> </ModalContent>
<ModalFooter> <ModalFooter>
<Button <Flex>
disabled={log.length === 0} <Button onClick={openNotificationSettingsModal}>
onClick={() => { Notification Settings
Alerts.show({ </Button>
title: "Are you sure?",
body: `This will permanently remove ${log.length} notification${log.length === 1 ? "" : "s"}. This action cannot be undone.`, <Button
async onConfirm() { disabled={log.length === 0}
await DataStore.set(KEY, []); color={Button.Colors.RED}
signals.forEach(x => x()); onClick={() => {
}, Alerts.show({
confirmText: "Do it!", title: "Are you sure?",
confirmColor: "vc-notification-log-danger-btn", body: `This will permanently remove ${log.length} notification${log.length === 1 ? "" : "s"}. This action cannot be undone.`,
cancelText: "Nevermind" async onConfirm() {
}); await DataStore.set(KEY, []);
}} signals.forEach(x => x());
> },
Clear Notification Log confirmText: "Do it!",
</Button> confirmColor: "vc-notification-log-danger-btn",
cancelText: "Nevermind"
});
}}
>
Clear Notification Log
</Button>
</Flex>
</ModalFooter> </ModalFooter>
</ModalRoot> </ModalRoot>
); );

View file

@ -16,40 +16,36 @@
* 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 { Logger } from "@utils/Logger"; import ErrorBoundary from "@components/ErrorBoundary";
import { ComponentType } from "react";
const logger = new Logger("ServerListAPI");
export const enum ServerListRenderPosition { export const enum ServerListRenderPosition {
Above, Above,
In, In,
} }
const renderFunctionsAbove = new Set<Function>(); const componentsAbove = new Set<ComponentType>();
const renderFunctionsIn = new Set<Function>(); const componentsBelow = new Set<ComponentType>();
function getRenderFunctions(position: ServerListRenderPosition) { function getRenderFunctions(position: ServerListRenderPosition) {
return position === ServerListRenderPosition.Above ? renderFunctionsAbove : renderFunctionsIn; return position === ServerListRenderPosition.Above ? componentsAbove : componentsBelow;
} }
export function addServerListElement(position: ServerListRenderPosition, renderFunction: Function) { export function addServerListElement(position: ServerListRenderPosition, renderFunction: ComponentType) {
getRenderFunctions(position).add(renderFunction); getRenderFunctions(position).add(renderFunction);
} }
export function removeServerListElement(position: ServerListRenderPosition, renderFunction: Function) { export function removeServerListElement(position: ServerListRenderPosition, renderFunction: ComponentType) {
getRenderFunctions(position).delete(renderFunction); getRenderFunctions(position).delete(renderFunction);
} }
export const renderAll = (position: ServerListRenderPosition) => { export const renderAll = (position: ServerListRenderPosition) => {
const ret: Array<JSX.Element> = []; return Array.from(
getRenderFunctions(position),
for (const renderFunction of getRenderFunctions(position)) { (Component, i) => (
try { <ErrorBoundary noop key={i}>
ret.unshift(renderFunction()); <Component />
} catch (e) { </ErrorBoundary>
logger.error("Failed to render server list element:", e); )
} );
}
return ret;
}; };

View file

@ -16,28 +16,42 @@
* 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 { debounce } from "@utils/debounce"; import { debounce } from "@shared/debounce";
import { SettingsStore as SettingsStoreClass } from "@shared/SettingsStore";
import { localStorage } from "@utils/localStorage"; import { localStorage } from "@utils/localStorage";
import { Logger } from "@utils/Logger"; import { Logger } from "@utils/Logger";
import { mergeDefaults } from "@utils/misc"; import { mergeDefaults } from "@utils/mergeDefaults";
import { putCloudSettings } from "@utils/settingsSync"; import { putCloudSettings } from "@utils/settingsSync";
import { DefinedSettings, OptionType, SettingsChecks, SettingsDefinition } from "@utils/types"; import { DefinedSettings, OptionType, SettingsChecks, SettingsDefinition } from "@utils/types";
import { React } from "@webpack/common"; import { React, useEffect } from "@webpack/common";
import plugins from "~plugins"; import plugins from "~plugins";
const logger = new Logger("Settings"); const logger = new Logger("Settings");
export interface Settings { export interface Settings {
notifyAboutUpdates: boolean;
autoUpdate: boolean; autoUpdate: boolean;
autoUpdateNotification: boolean, autoUpdateNotification: boolean,
useQuickCss: boolean; useQuickCss: boolean;
enableReactDevtools: boolean; enableReactDevtools: boolean;
themeLinks: string[]; themeLinks: string[];
enabledThemes: string[];
frameless: boolean; frameless: boolean;
transparent: boolean; transparent: boolean;
winCtrlQ: boolean; winCtrlQ: boolean;
macosTranslucency: boolean; macosVibrancyStyle:
| "content"
| "fullscreen-ui"
| "header"
| "hud"
| "menu"
| "popover"
| "selection"
| "sidebar"
| "titlebar"
| "tooltip"
| "under-page"
| "window"
| undefined;
disableMinSize: boolean; disableMinSize: boolean;
winNativeTitleBar: boolean; winNativeTitleBar: boolean;
plugins: { plugins: {
@ -63,16 +77,16 @@ export interface Settings {
} }
const DefaultSettings: Settings = { const DefaultSettings: Settings = {
notifyAboutUpdates: true, autoUpdate: true,
autoUpdate: false,
autoUpdateNotification: true, autoUpdateNotification: true,
useQuickCss: true, useQuickCss: true,
themeLinks: [], themeLinks: [],
enabledThemes: [],
enableReactDevtools: false, enableReactDevtools: false,
frameless: false, frameless: false,
transparent: false, transparent: false,
winCtrlQ: false, winCtrlQ: false,
macosTranslucency: false, macosVibrancyStyle: undefined,
disableMinSize: false, disableMinSize: false,
winNativeTitleBar: false, winNativeTitleBar: false,
plugins: {}, plugins: {},
@ -92,13 +106,8 @@ const DefaultSettings: Settings = {
} }
}; };
try { const settings = !IS_REPORTER ? VencordNative.settings.get() : {} as Settings;
var settings = JSON.parse(VencordNative.settings.get()) as Settings; mergeDefaults(settings, DefaultSettings);
mergeDefaults(settings, DefaultSettings);
} catch (err) {
var settings = mergeDefaults({} as Settings, DefaultSettings);
logger.error("An error occurred while loading the settings. Corrupt settings file?\n", err);
}
const saveSettingsOnFrequentAction = debounce(async () => { const saveSettingsOnFrequentAction = debounce(async () => {
if (Settings.cloud.settingsSync && Settings.cloud.authenticated) { if (Settings.cloud.settingsSync && Settings.cloud.authenticated) {
@ -107,74 +116,52 @@ const saveSettingsOnFrequentAction = debounce(async () => {
} }
}, 60_000); }, 60_000);
type SubscriptionCallback = ((newValue: any, path: string) => void) & { _path?: string; };
const subscriptions = new Set<SubscriptionCallback>();
const proxyCache = {} as Record<string, any>; export const SettingsStore = new SettingsStoreClass(settings, {
readOnly: true,
getDefaultValue({
target,
key,
path
}) {
const v = target[key];
if (!plugins) return v; // plugins not initialised yet. this means this path was reached by being called on the top level
// Wraps the passed settings object in a Proxy to nicely handle change listeners and default values if (path === "plugins" && key in plugins)
function makeProxy(settings: any, root = settings, path = ""): Settings { return target[key] = {
return proxyCache[path] ??= new Proxy(settings, { enabled: IS_REPORTER || plugins[key].required || plugins[key].enabledByDefault || false
get(target, p: string) { };
const v = target[p];
// using "in" is important in the following cases to properly handle falsy or nullish values // Since the property is not set, check if this is a plugin's setting and if so, try to resolve
if (!(p in target)) { // the default value.
// Return empty for plugins with no settings if (path.startsWith("plugins.")) {
if (path === "plugins" && p in plugins) const plugin = path.slice("plugins.".length);
return target[p] = makeProxy({ if (plugin in plugins) {
enabled: plugins[p].required ?? plugins[p].enabledByDefault ?? false const setting = plugins[plugin].options?.[key];
}, root, `plugins.${p}`); if (!setting) return v;
// Since the property is not set, check if this is a plugin's setting and if so, try to resolve if ("default" in setting)
// the default value. // normal setting with a default value
if (path.startsWith("plugins.")) { return (target[key] = setting.default);
const plugin = path.slice("plugins.".length);
if (plugin in plugins) {
const setting = plugins[plugin].options?.[p];
if (!setting) return v;
if ("default" in setting)
// normal setting with a default value
return (target[p] = setting.default);
if (setting.type === OptionType.SELECT) {
const def = setting.options.find(o => o.default);
if (def)
target[p] = def.value;
return def?.value;
}
}
}
return v;
}
// Recursively proxy Objects with the updated property path if (setting.type === OptionType.SELECT) {
if (typeof v === "object" && !Array.isArray(v) && v !== null) const def = setting.options.find(o => o.default);
return makeProxy(v, root, `${path}${path && "."}${p}`); if (def)
target[key] = def.value;
// primitive or similar, no need to proxy further return def?.value;
return v;
},
set(target, p: string, v) {
// avoid unnecessary updates to React Components and other listeners
if (target[p] === v) return true;
target[p] = v;
// Call any listeners that are listening to a setting of this path
const setPath = `${path}${path && "."}${p}`;
delete proxyCache[setPath];
for (const subscription of subscriptions) {
if (!subscription._path || subscription._path === setPath) {
subscription(v, setPath);
} }
} }
// And don't forget to persist the settings!
PlainSettings.cloud.settingsSyncVersion = Date.now();
localStorage.Vencord_settingsDirty = true;
saveSettingsOnFrequentAction();
VencordNative.settings.set(JSON.stringify(root, null, 4));
return true;
} }
return v;
}
});
if (!IS_REPORTER) {
SettingsStore.addGlobalChangeListener((_, path) => {
SettingsStore.plain.cloud.settingsSyncVersion = Date.now();
localStorage.Vencord_settingsDirty = true;
saveSettingsOnFrequentAction();
VencordNative.settings.set(SettingsStore.plain, path);
}); });
} }
@ -192,7 +179,7 @@ export const PlainSettings = settings;
* the updated settings to disk. * the updated settings to disk.
* This recursively proxies objects. If you need the object non proxied, use {@link PlainSettings} * This recursively proxies objects. If you need the object non proxied, use {@link PlainSettings}
*/ */
export const Settings = makeProxy(settings); export const Settings = SettingsStore.store;
/** /**
* Settings hook for React components. Returns a smart settings * Settings hook for React components. Returns a smart settings
@ -205,42 +192,21 @@ export const Settings = makeProxy(settings);
export function useSettings(paths?: UseSettings<Settings>[]) { export function useSettings(paths?: UseSettings<Settings>[]) {
const [, forceUpdate] = React.useReducer(() => ({}), {}); const [, forceUpdate] = React.useReducer(() => ({}), {});
const onUpdate: SubscriptionCallback = paths useEffect(() => {
? (value, path) => paths.includes(path as UseSettings<Settings>) && forceUpdate() if (paths) {
: forceUpdate; paths.forEach(p => SettingsStore.addChangeListener(p, forceUpdate));
return () => paths.forEach(p => SettingsStore.removeChangeListener(p, forceUpdate));
} else {
SettingsStore.addGlobalChangeListener(forceUpdate);
return () => SettingsStore.removeGlobalChangeListener(forceUpdate);
}
}, [paths]);
React.useEffect(() => { return SettingsStore.store;
subscriptions.add(onUpdate);
return () => void subscriptions.delete(onUpdate);
}, []);
return Settings;
}
// Resolves a possibly nested prop in the form of "some.nested.prop" to type of T.some.nested.prop
type ResolvePropDeep<T, P> = P extends "" ? T :
P extends `${infer Pre}.${infer Suf}` ?
Pre extends keyof T ? ResolvePropDeep<T[Pre], Suf> : never : P extends keyof T ? T[P] : never;
/**
* Add a settings listener that will be invoked whenever the desired setting is updated
* @param path Path to the setting that you want to watch, for example "plugins.Unindent.enabled" will fire your callback
* whenever Unindent is toggled. Pass an empty string to get notified for all changes
* @param onUpdate Callback function whenever a setting matching path is updated. It gets passed the new value and the path
* to the updated setting. This path will be the same as your path argument, unless it was an empty string.
*
* @example addSettingsListener("", (newValue, path) => console.log(`${path} is now ${newValue}`))
* addSettingsListener("plugins.Unindent.enabled", v => console.log("Unindent is now", v ? "enabled" : "disabled"))
*/
export function addSettingsListener<Path extends keyof Settings>(path: Path, onUpdate: (newValue: Settings[Path], path: Path) => void): void;
export function addSettingsListener<Path extends string>(path: Path, onUpdate: (newValue: Path extends "" ? any : ResolvePropDeep<Settings, Path>, path: Path extends "" ? string : Path) => void): void;
export function addSettingsListener(path: string, onUpdate: (newValue: any, path: string) => void) {
(onUpdate as SubscriptionCallback)._path = path;
subscriptions.add(onUpdate);
} }
export function migratePluginSettings(name: string, ...oldNames: string[]) { export function migratePluginSettings(name: string, ...oldNames: string[]) {
const { plugins } = settings; const { plugins } = SettingsStore.plain;
if (name in plugins) return; if (name in plugins) return;
for (const oldName of oldNames) { for (const oldName of oldNames) {
@ -248,12 +214,23 @@ export function migratePluginSettings(name: string, ...oldNames: string[]) {
logger.info(`Migrating settings from old name ${oldName} to ${name}`); logger.info(`Migrating settings from old name ${oldName} to ${name}`);
plugins[name] = plugins[oldName]; plugins[name] = plugins[oldName];
delete plugins[oldName]; delete plugins[oldName];
VencordNative.settings.set(JSON.stringify(settings, null, 4)); SettingsStore.markAsChanged();
break; break;
} }
} }
} }
export function migratePluginSetting(pluginName: string, oldSetting: string, newSetting: string) {
const settings = SettingsStore.plain.plugins[pluginName];
if (!settings) return;
if (!Object.hasOwn(settings, oldSetting) || Object.hasOwn(settings, newSetting)) return;
settings[newSetting] = settings[oldSetting];
delete settings[oldSetting];
SettingsStore.markAsChanged();
}
export function definePluginSettings< export function definePluginSettings<
Def extends SettingsDefinition, Def extends SettingsDefinition,
Checks extends SettingsChecks<Def>, Checks extends SettingsChecks<Def>,
@ -264,6 +241,10 @@ export function definePluginSettings<
if (!definedSettings.pluginName) throw new Error("Cannot access settings before plugin is initialized"); if (!definedSettings.pluginName) throw new Error("Cannot access settings before plugin is initialized");
return Settings.plugins[definedSettings.pluginName] as any; return Settings.plugins[definedSettings.pluginName] as any;
}, },
get plain() {
if (!definedSettings.pluginName) throw new Error("Cannot access settings before plugin is initialized");
return PlainSettings.plugins[definedSettings.pluginName] as any;
},
use: settings => useSettings( use: settings => useSettings(
settings?.map(name => `plugins.${definedSettings.pluginName}.${name}`) as UseSettings<Settings>[] settings?.map(name => `plugins.${definedSettings.pluginName}.${name}`) as UseSettings<Settings>[]
).plugins[definedSettings.pluginName] as any, ).plugins[definedSettings.pluginName] as any,

View file

@ -1,69 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { proxyLazy } from "@utils/lazy";
import { Logger } from "@utils/Logger";
import { findModuleId, wreq } from "@webpack";
import { Settings } from "./Settings";
interface Setting<T> {
/**
* Get the setting value
*/
getSetting(): T;
/**
* Update the setting value
* @param value The new value
*/
updateSetting(value: T | ((old: T) => T)): Promise<void>;
/**
* React hook for automatically updating components when the setting is updated
*/
useSetting(): T;
settingsStoreApiGroup: string;
settingsStoreApiName: string;
}
const SettingsStores: Array<Setting<any>> | undefined = proxyLazy(() => {
const modId = findModuleId('"textAndImages","renderSpoilers"');
if (modId == null) return new Logger("SettingsStoreAPI").error("Didn't find stores module.");
const mod = wreq(modId);
if (mod == null) return;
return Object.values(mod).filter((s: any) => s?.settingsStoreApiGroup) as any;
});
/**
* Get the store for a setting
* @param group The setting group
* @param name The name of the setting
*/
export function getSettingStore<T = any>(group: string, name: string): Setting<T> | undefined {
if (!Settings.plugins.SettingsStoreAPI.enabled) throw new Error("Cannot use SettingsStoreAPI without setting as dependency.");
return SettingsStores?.find(s => s?.settingsStoreApiGroup === group && s?.settingsStoreApiName === name);
}
/**
* getSettingStore but lazy
*/
export function getSettingStoreLazy<T = any>(group: string, name: string) {
return proxyLazy(() => getSettingStore<T>(group, name));
}

View file

@ -141,7 +141,7 @@ export const compileStyle = (style: Style) => {
*/ */
export const classNameToSelector = (name: string, prefix = "") => name.split(" ").map(n => `.${prefix}${n}`).join(""); export const classNameToSelector = (name: string, prefix = "") => name.split(" ").map(n => `.${prefix}${n}`).join("");
type ClassNameFactoryArg = string | string[] | Record<string, unknown>; type ClassNameFactoryArg = string | string[] | Record<string, unknown> | false | null | undefined | 0 | "";
/** /**
* @param prefix The prefix to add to each class, defaults to `""` * @param prefix The prefix to add to each class, defaults to `""`
* @returns A classname generator function * @returns A classname generator function
@ -154,9 +154,9 @@ type ClassNameFactoryArg = string | string[] | Record<string, unknown>;
export const classNameFactory = (prefix: string = "") => (...args: ClassNameFactoryArg[]) => { export const classNameFactory = (prefix: string = "") => (...args: ClassNameFactoryArg[]) => {
const classNames = new Set<string>(); const classNames = new Set<string>();
for (const arg of args) { for (const arg of args) {
if (typeof arg === "string") classNames.add(arg); if (arg && typeof arg === "string") classNames.add(arg);
else if (Array.isArray(arg)) arg.forEach(name => classNames.add(name)); else if (Array.isArray(arg)) arg.forEach(name => classNames.add(name));
else if (typeof arg === "object") Object.entries(arg).forEach(([name, value]) => value && classNames.add(name)); else if (arg && typeof arg === "object") Object.entries(arg).forEach(([name, value]) => value && classNames.add(name));
} }
return Array.from(classNames, name => prefix + name).join(" "); return Array.from(classNames, name => prefix + name).join(" ");
}; };

81
src/api/UserSettings.ts Normal file
View file

@ -0,0 +1,81 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { proxyLazy } from "@utils/lazy";
import { Logger } from "@utils/Logger";
import { findModuleId, proxyLazyWebpack, wreq } from "@webpack";
interface UserSettingDefinition<T> {
/**
* Get the setting value
*/
getSetting(): T;
/**
* Update the setting value
* @param value The new value
*/
updateSetting(value: T): Promise<void>;
/**
* Update the setting value
* @param value A callback that accepts the old value as the first argument, and returns the new value
*/
updateSetting(value: (old: T) => T): Promise<void>;
/**
* Stateful React hook for this setting value
*/
useSetting(): T;
userSettingsAPIGroup: string;
userSettingsAPIName: string;
}
export const UserSettings: Record<PropertyKey, UserSettingDefinition<any>> | undefined = proxyLazyWebpack(() => {
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.
*
* @param group The setting group
* @param name The name of the setting
*/
export function getUserSetting<T = any>(group: string, name: string): UserSettingDefinition<T> | undefined {
if (!Vencord.Plugins.isPluginEnabled("UserSettingsAPI")) throw new Error("Cannot use UserSettingsAPI without setting as dependency.");
for (const key in UserSettings) {
const userSetting = UserSettings[key];
if (userSetting.userSettingsAPIGroup === group && userSetting.userSettingsAPIName === name) {
return userSetting;
}
}
}
/**
* {@link getUserSettingDefinition}, lazy.
*
* Get the setting with the given setting group and name.
*
* @param group The setting group
* @param name The name of the setting
*/
export function getUserSettingLazy<T = any>(group: string, name: string) {
return proxyLazy(() => getUserSetting<T>(group, name));
}

View file

@ -17,6 +17,7 @@
*/ */
import * as $Badges from "./Badges"; import * as $Badges from "./Badges";
import * as $ChatButtons from "./ChatButtons";
import * as $Commands from "./Commands"; import * as $Commands from "./Commands";
import * as $ContextMenu from "./ContextMenu"; import * as $ContextMenu from "./ContextMenu";
import * as $DataStore from "./DataStore"; import * as $DataStore from "./DataStore";
@ -25,12 +26,13 @@ import * as $MessageAccessories from "./MessageAccessories";
import * as $MessageDecorations from "./MessageDecorations"; import * as $MessageDecorations from "./MessageDecorations";
import * as $MessageEventsAPI from "./MessageEvents"; import * as $MessageEventsAPI from "./MessageEvents";
import * as $MessagePopover from "./MessagePopover"; import * as $MessagePopover from "./MessagePopover";
import * as $MessageUpdater from "./MessageUpdater";
import * as $Notices from "./Notices"; import * as $Notices from "./Notices";
import * as $Notifications from "./Notifications"; import * as $Notifications from "./Notifications";
import * as $ServerList from "./ServerList"; import * as $ServerList from "./ServerList";
import * as $Settings from "./Settings"; import * as $Settings from "./Settings";
import * as $SettingsStore from "./SettingsStore";
import * as $Styles from "./Styles"; import * as $Styles from "./Styles";
import * as $UserSettings from "./UserSettings";
/** /**
* An API allowing you to listen to Message Clicks or run your own logic * An API allowing you to listen to Message Clicks or run your own logic
@ -91,10 +93,6 @@ export const MemberListDecorators = $MemberListDecorators;
* An API allowing you to persist data * An API allowing you to persist data
*/ */
export const Settings = $Settings; export const Settings = $Settings;
/**
* An API allowing you to read, manipulate and automatically update components based on Discord settings
*/
export const SettingsStore = $SettingsStore;
/** /**
* An API allowing you to dynamically load styles * An API allowing you to dynamically load styles
* a * a
@ -109,3 +107,18 @@ export const Notifications = $Notifications;
* An api allowing you to patch and add/remove items to/from context menus * An api allowing you to patch and add/remove items to/from context menus
*/ */
export const ContextMenu = $ContextMenu; export const ContextMenu = $ContextMenu;
/**
* An API allowing you to add buttons to the chat input
*/
export const ChatButtons = $ChatButtons;
/**
* An API allowing you to update and re-render messages
*/
export const MessageUpdater = $MessageUpdater;
/**
* An API allowing you to get an user setting
*/
export const UserSettings = $UserSettings;

View file

@ -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/>.
*/ */
export function Badge({ text, color }): JSX.Element { export function Badge({ text, color }) {
return ( return (
<div className="vc-plugins-badge" style={{ <div className="vc-plugins-badge" style={{
backgroundColor: color, backgroundColor: color,

View file

@ -0,0 +1,21 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2023 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { findByPropsLazy } from "@webpack";
import { Parser } from "@webpack/common";
const CodeContainerClasses = findByPropsLazy("markup", "codeContainer");
/**
* Renders code in a Discord codeblock
*/
export function CodeBlock(props: { content?: string, lang: string; }) {
return (
<div className={CodeContainerClasses.markup}>
{Parser.defaultRules.codeBlock.react(props, null, {})}
</div>
);
}

View file

@ -17,16 +17,22 @@
*/ */
import { Button } from "@webpack/common"; import { Button } from "@webpack/common";
import { ButtonProps } from "@webpack/types";
import { Heart } from "./Heart"; import { Heart } from "./Heart";
export default function DonateButton(props: any) { export default function DonateButton({
look = Button.Looks.LINK,
color = Button.Colors.TRANSPARENT,
...props
}: Partial<ButtonProps>) {
return ( return (
<Button <Button
{...props} {...props}
look={Button.Looks.LINK} look={look}
color={Button.Colors.TRANSPARENT} color={color}
onClick={() => VencordNative.native.openExternal("https://github.com/sponsors/Vendicated")} onClick={() => VencordNative.native.openExternal("https://github.com/sponsors/Vendicated")}
innerClassName="vc-donate-button"
> >
<Heart /> <Heart />
Donate Donate

View file

@ -27,7 +27,7 @@ interface Props<T = any> {
/** Render nothing if an error occurs */ /** Render nothing if an error occurs */
noop?: boolean; noop?: boolean;
/** Fallback component to render if an error occurs */ /** Fallback component to render if an error occurs */
fallback?: React.ComponentType<React.PropsWithChildren<{ error: any; message: string; stack: string; }>>; fallback?: React.ComponentType<React.PropsWithChildren<{ error: any; message: string; stack: string; wrappedProps: T; }>>;
/** called when an error occurs. The props property is only available if using .wrap */ /** called when an error occurs. The props property is only available if using .wrap */
onError?(data: { error: Error, errorInfo: React.ErrorInfo, props: T; }): void; onError?(data: { error: Error, errorInfo: React.ErrorInfo, props: T; }): void;
/** Custom error message */ /** Custom error message */
@ -70,8 +70,7 @@ const ErrorBoundary = LazyComponent(() => {
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) { componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
this.props.onError?.({ error, errorInfo, props: this.props.wrappedProps }); this.props.onError?.({ error, errorInfo, props: this.props.wrappedProps });
logger.error("A component threw an Error\n", error); logger.error(`${this.props.message || "A component threw an Error"}\n`, error, errorInfo.componentStack);
logger.error("Component Stack", errorInfo.componentStack);
} }
render() { render() {
@ -80,10 +79,14 @@ const ErrorBoundary = LazyComponent(() => {
if (this.props.noop) return null; if (this.props.noop) return null;
if (this.props.fallback) if (this.props.fallback)
return <this.props.fallback return (
children={this.props.children} <this.props.fallback
{...this.state} wrappedProps={this.props.wrappedProps}
/>; {...this.state}
>
{this.props.children}
</this.props.fallback>
);
const msg = this.props.message || "An error occurred while rendering this Component. More info can be found below and in your console."; const msg = this.props.message || "An error occurred while rendering this Component. More info can be found below and in your console.";

View file

@ -1,12 +0,0 @@
.vc-expandableheader-center-flex {
display: flex;
justify-items: center;
align-items: center;
}
.vc-expandableheader-btn {
all: unset;
cursor: pointer;
width: 24px;
height: 24px;
}

View file

@ -1,108 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { classNameFactory } from "@api/Styles";
import { Text, Tooltip, useState } from "@webpack/common";
export const cl = classNameFactory("vc-expandableheader-");
import "./ExpandableHeader.css";
export interface ExpandableHeaderProps {
onMoreClick?: () => void;
moreTooltipText?: string;
onDropDownClick?: (state: boolean) => void;
defaultState?: boolean;
headerText: string;
children: React.ReactNode;
buttons?: React.ReactNode[];
}
export default function ExpandableHeader({ children, onMoreClick, buttons, moreTooltipText, defaultState = false, onDropDownClick, headerText }: ExpandableHeaderProps) {
const [showContent, setShowContent] = useState(defaultState);
return (
<>
<div style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
marginBottom: "8px"
}}>
<Text
tag="h2"
variant="eyebrow"
style={{
color: "var(--header-primary)",
display: "inline"
}}
>
{headerText}
</Text>
<div className={cl("center-flex")}>
{
buttons ?? null
}
{
onMoreClick && // only show more button if callback is provided
<Tooltip text={moreTooltipText}>
{tooltipProps => (
<button
{...tooltipProps}
className={cl("btn")}
onClick={onMoreClick}>
<svg
width="24"
height="24"
viewBox="0 0 24 24"
>
<path fill="var(--text-normal)" d="M7 12.001C7 10.8964 6.10457 10.001 5 10.001C3.89543 10.001 3 10.8964 3 12.001C3 13.1055 3.89543 14.001 5 14.001C6.10457 14.001 7 13.1055 7 12.001ZM14 12.001C14 10.8964 13.1046 10.001 12 10.001C10.8954 10.001 10 10.8964 10 12.001C10 13.1055 10.8954 14.001 12 14.001C13.1046 14.001 14 13.1055 14 12.001ZM19 10.001C20.1046 10.001 21 10.8964 21 12.001C21 13.1055 20.1046 14.001 19 14.001C17.8954 14.001 17 13.1055 17 12.001C17 10.8964 17.8954 10.001 19 10.001Z" />
</svg>
</button>
)}
</Tooltip>
}
<Tooltip text={showContent ? "Hide " + headerText : "Show " + headerText}>
{tooltipProps => (
<button
{...tooltipProps}
className={cl("btn")}
onClick={() => {
setShowContent(v => !v);
onDropDownClick?.(showContent);
}}
>
<svg
width="24"
height="24"
viewBox="0 0 24 24"
transform={showContent ? "scale(1 -1)" : "scale(1 1)"}
>
<path fill="var(--text-normal)" d="M16.59 8.59003L12 13.17L7.41 8.59003L6 10L12 16L18 10L16.59 8.59003Z" />
</svg>
</button>
)}
</Tooltip>
</div>
</div>
{showContent && children}
</>
);
}

28
src/components/Grid.tsx Normal file
View file

@ -0,0 +1,28 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { CSSProperties, JSX } from "react";
interface Props {
columns: number;
gap?: string;
inline?: boolean;
}
export function Grid(props: Props & JSX.IntrinsicElements["div"]) {
const style: CSSProperties = {
display: props.inline ? "inline-grid" : "grid",
gridTemplateColumns: `repeat(${props.columns}, 1fr)`,
gap: props.gap,
...props.style
};
return (
<div {...props} style={style}>
{props.children}
</div>
);
}

View file

@ -16,18 +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/>.
*/ */
export function Heart() { import { classes } from "@utils/misc";
import { SVGProps } from "react";
export function Heart(props: SVGProps<SVGSVGElement>) {
return ( return (
<svg <svg
aria-hidden="true" aria-hidden="true"
height="16"
viewBox="0 0 16 16" viewBox="0 0 16 16"
height="16"
width="16" width="16"
style={{ marginRight: "0.5em", transform: "translateY(2px)" }} {...props}
className={classes("vc-heart-icon", props.className)}
> >
<path <path
fill="#db61a2" fill="#db61a2"
fill-rule="evenodd" fillRule="evenodd"
d="M4.25 2.5c-1.336 0-2.75 1.164-2.75 3 0 2.15 1.58 4.144 3.365 5.682A20.565 20.565 0 008 13.393a20.561 20.561 0 003.135-2.211C12.92 9.644 14.5 7.65 14.5 5.5c0-1.836-1.414-3-2.75-3-1.373 0-2.609.986-3.029 2.456a.75.75 0 01-1.442 0C6.859 3.486 5.623 2.5 4.25 2.5zM8 14.25l-.345.666-.002-.001-.006-.003-.018-.01a7.643 7.643 0 01-.31-.17 22.075 22.075 0 01-3.434-2.414C2.045 10.731 0 8.35 0 5.5 0 2.836 2.086 1 4.25 1 5.797 1 7.153 1.802 8 3.02 8.847 1.802 10.203 1 11.75 1 13.914 1 16 2.836 16 5.5c0 2.85-2.045 5.231-3.885 6.818a22.08 22.08 0 01-3.744 2.584l-.018.01-.006.003h-.002L8 14.25zm0 0l.345.666a.752.752 0 01-.69 0L8 14.25z" d="M4.25 2.5c-1.336 0-2.75 1.164-2.75 3 0 2.15 1.58 4.144 3.365 5.682A20.565 20.565 0 008 13.393a20.561 20.561 0 003.135-2.211C12.92 9.644 14.5 7.65 14.5 5.5c0-1.836-1.414-3-2.75-3-1.373 0-2.609.986-3.029 2.456a.75.75 0 01-1.442 0C6.859 3.486 5.623 2.5 4.25 2.5zM8 14.25l-.345.666-.002-.001-.006-.003-.018-.01a7.643 7.643 0 01-.31-.17 22.075 22.075 0 01-3.434-2.414C2.045 10.731 0 8.35 0 5.5 0 2.836 2.086 1 4.25 1 5.797 1 7.153 1.802 8 3.02 8.847 1.802 10.203 1 11.75 1 13.914 1 16 2.836 16 5.5c0 2.85-2.045 5.231-3.885 6.818a22.08 22.08 0 01-3.744 2.584l-.018.01-.006.003h-.002L8 14.25zm0 0l.345.666a.752.752 0 01-.69 0L8 14.25z"
/> />
</svg> </svg>

View file

@ -18,19 +18,16 @@
import "./iconStyles.css"; import "./iconStyles.css";
import { getIntlMessage } from "@utils/discord";
import { classes } from "@utils/misc"; import { classes } from "@utils/misc";
import { i18n } from "@webpack/common"; import type { JSX, PropsWithChildren } from "react";
import type { PropsWithChildren, SVGProps } from "react";
interface BaseIconProps extends IconProps { interface BaseIconProps extends IconProps {
viewBox: string; viewBox: string;
} }
interface IconProps extends SVGProps<SVGSVGElement> { type IconProps = JSX.IntrinsicElements["svg"];
className?: string; type ImageProps = JSX.IntrinsicElements["img"];
height?: number;
width?: number;
}
function Icon({ height = 24, width = 24, className, children, viewBox, ...svgProps }: PropsWithChildren<BaseIconProps>) { function Icon({ height = 24, width = 24, className, children, viewBox, ...svgProps }: PropsWithChildren<BaseIconProps>) {
return ( return (
@ -58,7 +55,7 @@ export function LinkIcon({ height = 24, width = 24, className }: IconProps) {
className={classes(className, "vc-link-icon")} className={classes(className, "vc-link-icon")}
viewBox="0 0 24 24" viewBox="0 0 24 24"
> >
<g fill="none" fill-rule="evenodd"> <g fill="none" fillRule="evenodd">
<path fill="currentColor" d="M10.59 13.41c.41.39.41 1.03 0 1.42-.39.39-1.03.39-1.42 0a5.003 5.003 0 0 1 0-7.07l3.54-3.54a5.003 5.003 0 0 1 7.07 0 5.003 5.003 0 0 1 0 7.07l-1.49 1.49c.01-.82-.12-1.64-.4-2.42l.47-.48a2.982 2.982 0 0 0 0-4.24 2.982 2.982 0 0 0-4.24 0l-3.53 3.53a2.982 2.982 0 0 0 0 4.24zm2.82-4.24c.39-.39 1.03-.39 1.42 0a5.003 5.003 0 0 1 0 7.07l-3.54 3.54a5.003 5.003 0 0 1-7.07 0 5.003 5.003 0 0 1 0-7.07l1.49-1.49c-.01.82.12 1.64.4 2.43l-.47.47a2.982 2.982 0 0 0 0 4.24 2.982 2.982 0 0 0 4.24 0l3.53-3.53a2.982 2.982 0 0 0 0-4.24.973.973 0 0 1 0-1.42z" /> <path fill="currentColor" d="M10.59 13.41c.41.39.41 1.03 0 1.42-.39.39-1.03.39-1.42 0a5.003 5.003 0 0 1 0-7.07l3.54-3.54a5.003 5.003 0 0 1 7.07 0 5.003 5.003 0 0 1 0 7.07l-1.49 1.49c.01-.82-.12-1.64-.4-2.42l.47-.48a2.982 2.982 0 0 0 0-4.24 2.982 2.982 0 0 0-4.24 0l-3.53 3.53a2.982 2.982 0 0 0 0 4.24zm2.82-4.24c.39-.39 1.03-.39 1.42 0a5.003 5.003 0 0 1 0 7.07l-3.54 3.54a5.003 5.003 0 0 1-7.07 0 5.003 5.003 0 0 1 0-7.07l1.49-1.49c-.01.82.12 1.64.4 2.43l-.47.47a2.982 2.982 0 0 0 0 4.24 2.982 2.982 0 0 0 4.24 0l3.53-3.53a2.982 2.982 0 0 0 0-4.24.973.973 0 0 1 0-1.42z" />
<rect width={width} height={height} /> <rect width={width} height={height} />
</g> </g>
@ -67,8 +64,7 @@ export function LinkIcon({ height = 24, width = 24, className }: IconProps) {
} }
/** /**
* Discord's copy icon, as seen in the user popout right of the username when clicking * Discord's copy icon, as seen in the user panel popout on the right of the username and in large code blocks
* your own username in the bottom left user panel
*/ */
export function CopyIcon(props: IconProps) { export function CopyIcon(props: IconProps) {
return ( return (
@ -78,8 +74,9 @@ export function CopyIcon(props: IconProps) {
viewBox="0 0 24 24" viewBox="0 0 24 24"
> >
<g fill="currentColor"> <g fill="currentColor">
<path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1z" /> <path d="M3 16a1 1 0 0 1-1-1v-5a8 8 0 0 1 8-8h5a1 1 0 0 1 1 1v.5a.5.5 0 0 1-.5.5H10a6 6 0 0 0-6 6v5.5a.5.5 0 0 1-.5.5H3Z" />
<path d="M15 5H8c-1.1 0-1.99.9-1.99 2L6 21c0 1.1.89 2 1.99 2H19c1.1 0 2-.9 2-2V11l-6-6zM8 21V7h6v5h5v9H8z" /> <path d="M6 18a4 4 0 0 0 4 4h8a4 4 0 0 0 4-4v-4h-3a5 5 0 0 1-5-5V6h-4a4 4 0 0 0-4 4v8Z" />
<path d="M21.73 12a3 3 0 0 0-.6-.88l-4.25-4.24a3 3 0 0 0-.88-.61V9a3 3 0 0 0 3 3h2.73Z" />
</g> </g>
</Icon> </Icon>
); );
@ -97,7 +94,7 @@ export function OpenExternalIcon(props: IconProps) {
> >
<polygon <polygon
fill="currentColor" fill="currentColor"
fill-rule="nonzero" fillRule="nonzero"
points="13 20 11 20 11 8 5.5 13.5 4.08 12.08 12 4.16 19.92 12.08 18.5 13.5 13 8" points="13 20 11 20 11 8 5.5 13.5 4.08 12.08 12 4.16 19.92 12.08 18.5 13.5 13 8"
/> />
</Icon> </Icon>
@ -121,9 +118,13 @@ export function InfoIcon(props: IconProps) {
<Icon <Icon
{...props} {...props}
className={classes(props.className, "vc-info-icon")} className={classes(props.className, "vc-info-icon")}
viewBox="0 0 12 12" viewBox="0 0 24 24"
> >
<path fill="currentColor" d="M6 1C3.243 1 1 3.244 1 6c0 2.758 2.243 5 5 5s5-2.242 5-5c0-2.756-2.243-5-5-5zm0 2.376a.625.625 0 110 1.25.625.625 0 010-1.25zM7.5 8.5h-3v-1h1V6H5V5h1a.5.5 0 01.5.5v2h1v1z" /> <path
fill="currentColor"
fillRule="evenodd"
d="M23 12a11 11 0 1 1-22 0 11 11 0 0 1 22 0Zm-9.5-4.75a1.25 1.25 0 1 1-2.5 0 1.25 1.25 0 0 1 2.5 0Zm-.77 3.96a1 1 0 1 0-1.96-.42l-1.04 4.86a2.77 2.77 0 0 0 4.31 2.83l.24-.17a1 1 0 1 0-1.16-1.62l-.24.17a.77.77 0 0 1-1.2-.79l1.05-4.86Z" clipRule="evenodd"
/>
</Icon> </Icon>
); );
} }
@ -131,7 +132,7 @@ export function InfoIcon(props: IconProps) {
export function OwnerCrownIcon(props: IconProps) { export function OwnerCrownIcon(props: IconProps) {
return ( return (
<Icon <Icon
aria-label={i18n.Messages.GUILD_OWNER} aria-label={getIntlMessage("GUILD_OWNER")}
{...props} {...props}
className={classes(props.className, "vc-owner-crown-icon")} className={classes(props.className, "vc-owner-crown-icon")}
role="img" role="img"
@ -139,8 +140,8 @@ export function OwnerCrownIcon(props: IconProps) {
> >
<path <path
fill="currentColor" fill="currentColor"
fill-rule="evenodd" fillRule="evenodd"
clip-rule="evenodd" clipRule="evenodd"
d="M13.6572 5.42868C13.8879 5.29002 14.1806 5.30402 14.3973 5.46468C14.6133 5.62602 14.7119 5.90068 14.6473 6.16202L13.3139 11.4954C13.2393 11.7927 12.9726 12.0007 12.6666 12.0007H3.33325C3.02725 12.0007 2.76058 11.792 2.68592 11.4954L1.35258 6.16202C1.28792 5.90068 1.38658 5.62602 1.60258 5.46468C1.81992 5.30468 2.11192 5.29068 2.34325 5.42868L5.13192 7.10202L7.44592 3.63068C7.46173 3.60697 7.48377 3.5913 7.50588 3.57559C7.5192 3.56612 7.53255 3.55663 7.54458 3.54535L6.90258 2.90268C6.77325 2.77335 6.77325 2.56068 6.90258 2.43135L7.76458 1.56935C7.89392 1.44002 8.10658 1.44002 8.23592 1.56935L9.09792 2.43135C9.22725 2.56068 9.22725 2.77335 9.09792 2.90268L8.45592 3.54535C8.46794 3.55686 8.48154 3.56651 8.49516 3.57618C8.51703 3.5917 8.53897 3.60727 8.55458 3.63068L10.8686 7.10202L13.6572 5.42868ZM2.66667 12.6673H13.3333V14.0007H2.66667V12.6673Z" d="M13.6572 5.42868C13.8879 5.29002 14.1806 5.30402 14.3973 5.46468C14.6133 5.62602 14.7119 5.90068 14.6473 6.16202L13.3139 11.4954C13.2393 11.7927 12.9726 12.0007 12.6666 12.0007H3.33325C3.02725 12.0007 2.76058 11.792 2.68592 11.4954L1.35258 6.16202C1.28792 5.90068 1.38658 5.62602 1.60258 5.46468C1.81992 5.30468 2.11192 5.29068 2.34325 5.42868L5.13192 7.10202L7.44592 3.63068C7.46173 3.60697 7.48377 3.5913 7.50588 3.57559C7.5192 3.56612 7.53255 3.55663 7.54458 3.54535L6.90258 2.90268C6.77325 2.77335 6.77325 2.56068 6.90258 2.43135L7.76458 1.56935C7.89392 1.44002 8.10658 1.44002 8.23592 1.56935L9.09792 2.43135C9.22725 2.56068 9.22725 2.77335 9.09792 2.90268L8.45592 3.54535C8.46794 3.55686 8.48154 3.56651 8.49516 3.57618C8.51703 3.5917 8.53897 3.60727 8.55458 3.63068L10.8686 7.10202L13.6572 5.42868ZM2.66667 12.6673H13.3333V14.0007H2.66667V12.6673Z"
/> />
</Icon> </Icon>
@ -159,8 +160,6 @@ export function ScreenshareIcon(props: IconProps) {
> >
<path <path
fill="currentColor" fill="currentColor"
fill-rule="evenodd"
clip-rule="evenodd"
d="M2 4.5C2 3.397 2.897 2.5 4 2.5H20C21.103 2.5 22 3.397 22 4.5V15.5C22 16.604 21.103 17.5 20 17.5H13V19.5H17V21.5H7V19.5H11V17.5H4C2.897 17.5 2 16.604 2 15.5V4.5ZM13.2 14.3375V11.6C9.864 11.6 7.668 12.6625 6 15C6.672 11.6625 8.532 8.3375 13.2 7.6625V5L18 9.6625L13.2 14.3375Z" d="M2 4.5C2 3.397 2.897 2.5 4 2.5H20C21.103 2.5 22 3.397 22 4.5V15.5C22 16.604 21.103 17.5 20 17.5H13V19.5H17V21.5H7V19.5H11V17.5H4C2.897 17.5 2 16.604 2 15.5V4.5ZM13.2 14.3375V11.6C9.864 11.6 7.668 12.6625 6 15C6.672 11.6625 8.532 8.3375 13.2 7.6625V5L18 9.6625L13.2 14.3375Z"
/> />
</Icon> </Icon>
@ -190,3 +189,248 @@ export function ImageInvisible(props: IconProps) {
</Icon> </Icon>
); );
} }
export function Microphone(props: IconProps) {
return (
<Icon
{...props}
className={classes(props.className, "vc-microphone")}
viewBox="0 0 24 24"
>
<path fillRule="evenodd" clipRule="evenodd" d="M14.99 11C14.99 12.66 13.66 14 12 14C10.34 14 9 12.66 9 11V5C9 3.34 10.34 2 12 2C13.66 2 15 3.34 15 5L14.99 11ZM12 16.1C14.76 16.1 17.3 14 17.3 11H19C19 14.42 16.28 17.24 13 17.72V21H11V17.72C7.72 17.23 5 14.41 5 11H6.7C6.7 14 9.24 16.1 12 16.1ZM12 4C11.2 4 11 4.66667 11 5V11C11 11.3333 11.2 12 12 12C12.8 12 13 11.3333 13 11V5C13 4.66667 12.8 4 12 4Z" fill="currentColor" />
<path fillRule="evenodd" clipRule="evenodd" d="M14.99 11C14.99 12.66 13.66 14 12 14C10.34 14 9 12.66 9 11V5C9 3.34 10.34 2 12 2C13.66 2 15 3.34 15 5L14.99 11ZM12 16.1C14.76 16.1 17.3 14 17.3 11H19C19 14.42 16.28 17.24 13 17.72V22H11V17.72C7.72 17.23 5 14.41 5 11H6.7C6.7 14 9.24 16.1 12 16.1Z" fill="currentColor" />
</Icon >
);
}
export function CogWheel(props: IconProps) {
return (
<Icon
{...props}
className={classes(props.className, "vc-cog-wheel")}
viewBox="0 0 24 24"
>
<path
fill="currentColor"
fillRule="evenodd"
d="M10.56 1.1c-.46.05-.7.53-.64.98.18 1.16-.19 2.2-.98 2.53-.8.33-1.79-.15-2.49-1.1-.27-.36-.78-.52-1.14-.24-.77.59-1.45 1.27-2.04 2.04-.28.36-.12.87.24 1.14.96.7 1.43 1.7 1.1 2.49-.33.8-1.37 1.16-2.53.98-.45-.07-.93.18-.99.64a11.1 11.1 0 0 0 0 2.88c.06.46.54.7.99.64 1.16-.18 2.2.19 2.53.98.33.8-.14 1.79-1.1 2.49-.36.27-.52.78-.24 1.14.59.77 1.27 1.45 2.04 2.04.36.28.87.12 1.14-.24.7-.95 1.7-1.43 2.49-1.1.8.33 1.16 1.37.98 2.53-.07.45.18.93.64.99a11.1 11.1 0 0 0 2.88 0c.46-.06.7-.54.64-.99-.18-1.16.19-2.2.98-2.53.8-.33 1.79.14 2.49 1.1.27.36.78.52 1.14.24.77-.59 1.45-1.27 2.04-2.04.28-.36.12-.87-.24-1.14-.96-.7-1.43-1.7-1.1-2.49.33-.8 1.37-1.16 2.53-.98.45.07.93-.18.99-.64a11.1 11.1 0 0 0 0-2.88c-.06-.46-.54-.7-.99-.64-1.16.18-2.2-.19-2.53-.98-.33-.8.14-1.79 1.1-2.49.36-.27.52-.78.24-1.14a11.07 11.07 0 0 0-2.04-2.04c-.36-.28-.87-.12-1.14.24-.7.96-1.7 1.43-2.49 1.1-.8-.33-1.16-1.37-.98-2.53.07-.45-.18-.93-.64-.99a11.1 11.1 0 0 0-2.88 0ZM16 12a4 4 0 1 1-8 0 4 4 0 0 1 8 0Z"
clipRule="evenodd"
/>
</Icon>
);
}
export function ReplyIcon(props: IconProps) {
return (
<Icon
{...props}
className={classes(props.className, "vc-reply-icon")}
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M10 8.26667V4L3 11.4667L10 18.9333V14.56C15 14.56 18.5 16.2667 21 20C20 14.6667 17 9.33333 10 8.26667Z"
/>
</Icon>
);
}
export function DeleteIcon(props: IconProps) {
return (
<Icon
{...props}
className={classes(props.className, "vc-delete-icon")}
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M15 3.999V2H9V3.999H3V5.999H21V3.999H15Z"
/>
<path
fill="currentColor"
d="M5 6.99902V18.999C5 20.101 5.897 20.999 7 20.999H17C18.103 20.999 19 20.101 19 18.999V6.99902H5ZM11 17H9V11H11V17ZM15 17H13V11H15V17Z"
/>
</Icon>
);
}
export function PlusIcon(props: IconProps) {
return (
<Icon
{...props}
className={classes(props.className, "vc-plus-icon")}
viewBox="0 0 18 18"
>
<polygon
fillRule="nonzero"
fill="currentColor"
points="15 10 10 10 10 15 8 15 8 10 3 10 3 8 8 8 8 3 10 3 10 8 15 8"
/>
</Icon>
);
}
export function NoEntrySignIcon(props: IconProps) {
return (
<Icon
{...props}
className={classes(props.className, "vc-no-entry-sign-icon")}
viewBox="0 0 24 24"
>
<path
d="M0 0h24v24H0z"
fill="none"
/>
<path
fill="currentColor"
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8 0-1.85.63-3.55 1.69-4.9L16.9 18.31C15.55 19.37 13.85 20 12 20zm6.31-3.1L7.1 5.69C8.45 4.63 10.15 4 12 4c4.42 0 8 3.58 8 8 0 1.85-.63 3.55-1.69 4.9z"
/>
</Icon>
);
}
export function SafetyIcon(props: IconProps) {
return (
<Icon
{...props}
className={classes(props.className, "vc-safety-icon")}
viewBox="0 0 24 24"
>
<path
fill="currentColor"
fillRule="evenodd"
clipRule="evenodd"
d="M4.27 5.22A2.66 2.66 0 0 0 3 7.5v2.3c0 5.6 3.3 10.68 8.42 12.95.37.17.79.17 1.16 0A14.18 14.18 0 0 0 21 9.78V7.5c0-.93-.48-1.78-1.27-2.27l-6.17-3.76a3 3 0 0 0-3.12 0L4.27 5.22ZM6 7.68l6-3.66V12H6.22C6.08 11.28 6 10.54 6 9.78v-2.1Zm6 12.01V12h5.78A11.19 11.19 0 0 1 12 19.7Z"
/>
</Icon>
);
}
export function NotesIcon(props: IconProps) {
return (
<Icon
{...props}
className={classes(props.className, "vc-notes-icon")}
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M8 3C7.44771 3 7 3.44772 7 4V5C7 5.55228 7.44772 6 8 6H16C16.5523 6 17 5.55228 17 5V4C17 3.44772 16.5523 3 16 3H15.1245C14.7288 3 14.3535 2.82424 14.1002 2.52025L13.3668 1.64018C13.0288 1.23454 12.528 1 12 1C11.472 1 10.9712 1.23454 10.6332 1.64018L9.8998 2.52025C9.64647 2.82424 9.27121 3 8.8755 3H8Z"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
fill="currentColor"
d="M19 4.49996V4.99996C19 6.65681 17.6569 7.99996 16 7.99996H8C6.34315 7.99996 5 6.65681 5 4.99996V4.49996C5 4.22382 4.77446 3.99559 4.50209 4.04109C3.08221 4.27826 2 5.51273 2 6.99996V19C2 20.6568 3.34315 22 5 22H19C20.6569 22 22 20.6568 22 19V6.99996C22 5.51273 20.9178 4.27826 19.4979 4.04109C19.2255 3.99559 19 4.22382 19 4.49996ZM8 12C7.44772 12 7 12.4477 7 13C7 13.5522 7.44772 14 8 14H16C16.5523 14 17 13.5522 17 13C17 12.4477 16.5523 12 16 12H8ZM7 17C7 16.4477 7.44772 16 8 16H13C13.5523 16 14 16.4477 14 17C14 17.5522 13.5523 18 13 18H8C7.44772 18 7 17.5522 7 17Z"
/>
</Icon>
);
}
export function FolderIcon(props: IconProps) {
return (
<Icon
{...props}
className={classes(props.className, "vc-folder-icon")}
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M2 5a3 3 0 0 1 3-3h3.93a2 2 0 0 1 1.66.9L12 5h7a3 3 0 0 1 3 3v11a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V5Z"
/>
</Icon>
);
}
export function LogIcon(props: IconProps) {
return (
<Icon
{...props}
className={classes(props.className, "vc-log-icon")}
viewBox="0 0 24 24"
>
<path
fill="currentColor"
fillRule="evenodd"
clipRule="evenodd"
d="M3.11 8H6v10.82c0 .86.37 1.68 1 2.27.46.43 1.02.71 1.63.84A1 1 0 0 0 9 22h10a4 4 0 0 0 4-4v-1a2 2 0 0 0-2-2h-1V5a3 3 0 0 0-3-3H4.67c-.87 0-1.7.32-2.34.9-.63.6-1 1.42-1 2.28 0 .71.3 1.35.52 1.75a5.35 5.35 0 0 0 .48.7l.01.01h.01L3.11 7l-.76.65a1 1 0 0 0 .76.35Zm1.56-4c-.38 0-.72.14-.97.37-.24.23-.37.52-.37.81a1.69 1.69 0 0 0 .3.82H6v-.83c0-.29-.13-.58-.37-.8C5.4 4.14 5.04 4 4.67 4Zm5 13a3.58 3.58 0 0 1 0 3H19a2 2 0 0 0 2-2v-1H9.66ZM3.86 6.35ZM11 8a1 1 0 1 0 0 2h5a1 1 0 1 0 0-2h-5Zm-1 5a1 1 0 0 1 1-1h5a1 1 0 1 1 0 2h-5a1 1 0 0 1-1-1Z"
/>
</Icon>
);
}
export function RestartIcon(props: IconProps) {
return (
<Icon
{...props}
className={classes(props.className, "vc-restart-icon")}
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M4 12a8 8 0 0 1 14.93-4H15a1 1 0 1 0 0 2h6a1 1 0 0 0 1-1V3a1 1 0 1 0-2 0v3a9.98 9.98 0 0 0-18 6 10 10 0 0 0 16.29 7.78 1 1 0 0 0-1.26-1.56A8 8 0 0 1 4 12Z"
/>
</Icon>
);
}
export function PaintbrushIcon(props: IconProps) {
return (
<Icon
{...props}
className={classes(props.className, "vc-paintbrush-icon")}
viewBox="0 0 24 24"
>
<path
fill="currentColor"
fillRule="evenodd"
clipRule="evenodd"
d="M15.35 7.24C15.9 6.67 16 5.8 16 5a3 3 0 1 1 3 3c-.8 0-1.67.09-2.24.65a1.5 1.5 0 0 0 0 2.11l1.12 1.12a3 3 0 0 1 0 4.24l-5 5a3 3 0 0 1-4.25 0l-5.76-5.75a3 3 0 0 1 0-4.24l4.04-4.04.97-.97a3 3 0 0 1 4.24 0l1.12 1.12c.58.58 1.52.58 2.1 0ZM6.9 9.9 4.3 12.54a1 1 0 0 0 0 1.42l2.17 2.17.83-.84a1 1 0 0 1 1.42 1.42l-.84.83.59.59 1.83-1.84a1 1 0 0 1 1.42 1.42l-1.84 1.83.17.17a1 1 0 0 0 1.42 0l2.63-2.62L6.9 9.9Z"
/>
</Icon>
);
}
export function PencilIcon(props: IconProps) {
return (
<Icon
{...props}
className={classes(props.className, "vc-pencil-icon")}
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="m13.96 5.46 4.58 4.58a1 1 0 0 0 1.42 0l1.38-1.38a2 2 0 0 0 0-2.82l-3.18-3.18a2 2 0 0 0-2.82 0l-1.38 1.38a1 1 0 0 0 0 1.42ZM2.11 20.16l.73-4.22a3 3 0 0 1 .83-1.61l7.87-7.87a1 1 0 0 1 1.42 0l4.58 4.58a1 1 0 0 1 0 1.42l-7.87 7.87a3 3 0 0 1-1.6.83l-4.23.73a1.5 1.5 0 0 1-1.73-1.73Z"
/>
</Icon>
);
}
export function GithubIcon(props: IconProps) {
return (
<Icon
{...props}
viewBox="-3 -3 30 30"
>
<path
fill={props.fill || "currentColor"}
d="M12 0C5.37 0 0 5.37 0 12c0 5.3 3.438 9.8 8.205 11.385.6.11.82-.26.82-.577v-2.17c-3.338.726-4.042-1.61-4.042-1.61-.546-1.387-1.333-1.757-1.333-1.757-1.09-.745.083-.73.083-.73 1.205.084 1.84 1.237 1.84 1.237 1.07 1.835 2.807 1.305 3.492.998.108-.775.42-1.305.763-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.467-2.38 1.235-3.22-.123-.303-.535-1.523.117-3.176 0 0 1.008-.322 3.3 1.23.957-.266 1.98-.398 3-.403 1.02.005 2.043.137 3 .403 2.29-1.552 3.297-1.23 3.297-1.23.653 1.653.24 2.873.118 3.176.77.84 1.233 1.91 1.233 3.22 0 4.61-2.803 5.625-5.475 5.92.43.37.823 1.102.823 2.222v3.293c0 .32.218.694.825.577C20.565 21.797 24 17.298 24 12c0-6.63-5.37-12-12-12z"
/>
</Icon>
);
}
export function WebsiteIcon(props: IconProps) {
return (
<Icon
{...props}
viewBox="0 0 24 24"
>
<path
fill={props.fill || "currentColor"}
d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zM4 12c0-.899.156-1.762.431-2.569L6 11l2 2v2l2 2 1 1v1.931C7.061 19.436 4 16.072 4 12zm14.33 4.873C17.677 16.347 16.687 16 16 16v-1a2 2 0 0 0-2-2h-4v-3a2 2 0 0 0 2-2V7h1a2 2 0 0 0 2-2v-.411C17.928 5.778 20 8.65 20 12a7.947 7.947 0 0 1-1.67 4.873z"
/>
</Icon>
);
}

View file

@ -0,0 +1,115 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2023 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import "./contributorModal.css";
import { useSettings } from "@api/Settings";
import { classNameFactory } from "@api/Styles";
import ErrorBoundary from "@components/ErrorBoundary";
import { Link } from "@components/Link";
import { DevsById } from "@utils/constants";
import { fetchUserProfile } from "@utils/discord";
import { classes, pluralise } from "@utils/misc";
import { ModalContent, ModalRoot, openModal } from "@utils/modal";
import { Forms, showToast, useEffect, useMemo, UserProfileStore, useStateFromStores } from "@webpack/common";
import { User } from "discord-types/general";
import Plugins from "~plugins";
import { PluginCard } from ".";
import { GithubButton, WebsiteButton } from "./LinkIconButton";
const cl = classNameFactory("vc-author-modal-");
export function openContributorModal(user: User) {
openModal(modalProps =>
<ModalRoot {...modalProps}>
<ErrorBoundary>
<ModalContent className={cl("root")}>
<ContributorModal user={user} />
</ModalContent>
</ErrorBoundary>
</ModalRoot>
);
}
function ContributorModal({ user }: { user: User; }) {
useSettings();
const profile = useStateFromStores([UserProfileStore], () => UserProfileStore.getUserProfile(user.id));
useEffect(() => {
if (!profile && !user.bot && user.id)
fetchUserProfile(user.id);
}, [user.id, user.bot, profile]);
const githubName = profile?.connectedAccounts?.find(a => a.type === "github")?.name;
const website = profile?.connectedAccounts?.find(a => a.type === "domain")?.name;
const plugins = useMemo(() => {
const allPlugins = Object.values(Plugins);
const pluginsByAuthor = DevsById[user.id]
? allPlugins.filter(p => p.authors.includes(DevsById[user.id]))
: allPlugins.filter(p => p.authors.some(a => a.name === user.username));
return pluginsByAuthor
.filter(p => !p.name.endsWith("API"))
.sort((a, b) => Number(a.required ?? false) - Number(b.required ?? false));
}, [user.id, user.username]);
const ContributedHyperLink = <Link href="https://vencord.dev/source">contributed</Link>;
return (
<>
<div className={cl("header")}>
<img
className={cl("avatar")}
src={user.getAvatarURL(void 0, 512, true)}
alt=""
/>
<Forms.FormTitle tag="h2" className={cl("name")}>{user.username}</Forms.FormTitle>
<div className={classes("vc-settings-modal-links", cl("links"))}>
{website && (
<WebsiteButton
text={website}
href={`https://${website}`}
/>
)}
{githubName && (
<GithubButton
text={githubName}
href={`https://github.com/${githubName}`}
/>
)}
</div>
</div>
{plugins.length ? (
<Forms.FormText>
This person has {ContributedHyperLink} to {pluralise(plugins.length, "plugin")}!
</Forms.FormText>
) : (
<Forms.FormText>
This person has not made any plugins. They likely {ContributedHyperLink} to Vencord in other ways!
</Forms.FormText>
)}
{!!plugins.length && (
<div className={cl("plugins")}>
{plugins.map(p =>
<PluginCard
key={p.name}
plugin={p}
disabled={p.required ?? false}
onRestartNeeded={() => showToast("Restart to apply changes!")}
/>
)}
</div>
)}
</>
);
}

View file

@ -0,0 +1,12 @@
.vc-settings-modal-link-icon {
height: 32px;
width: 32px;
border-radius: 50%;
border: 4px solid var(--background-tertiary);
box-sizing: border-box
}
.vc-settings-modal-links {
display: flex;
gap: 0.2em;
}

View file

@ -0,0 +1,42 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import "./LinkIconButton.css";
import { getTheme, Theme } from "@utils/discord";
import { MaskedLink, Tooltip } from "@webpack/common";
import { GithubIcon, WebsiteIcon } from "..";
export function GithubLinkIcon() {
const theme = getTheme() === Theme.Light ? "#000000" : "#FFFFFF";
return <GithubIcon aria-hidden fill={theme} className={"vc-settings-modal-link-icon"} />;
}
export function WebsiteLinkIcon() {
const theme = getTheme() === Theme.Light ? "#000000" : "#FFFFFF";
return <WebsiteIcon aria-hidden fill={theme} className={"vc-settings-modal-link-icon"} />;
}
interface Props {
text: string;
href: string;
}
function LinkIcon({ text, href, Icon }: Props & { Icon: React.ComponentType; }) {
return (
<Tooltip text={text}>
{props => (
<MaskedLink {...props} href={href}>
<Icon />
</MaskedLink>
)}
</Tooltip>
);
}
export const WebsiteButton = (props: Props) => <LinkIcon {...props} Icon={WebsiteLinkIcon} />;
export const GithubButton = (props: Props) => <LinkIcon {...props} Icon={GithubLinkIcon} />;

View file

@ -0,0 +1,7 @@
.vc-plugin-modal-info {
align-items: center;
}
.vc-plugin-modal-description {
flex-grow: 1;
}

View file

@ -16,23 +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 "./PluginModal.css";
import { generateId } from "@api/Commands"; import { generateId } from "@api/Commands";
import { useSettings } from "@api/Settings"; import { useSettings } from "@api/Settings";
import { disableStyle, enableStyle } from "@api/Styles"; 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 { proxyLazy } from "@utils/lazy"; import { proxyLazy } from "@utils/lazy";
import { Margins } from "@utils/margins"; import { Margins } from "@utils/margins";
import { classes } from "@utils/misc"; import { classes, isObjectEmpty } from "@utils/misc";
import { ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize } from "@utils/modal"; import { ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
import { LazyComponent } from "@utils/react";
import { OptionType, Plugin } from "@utils/types"; import { OptionType, Plugin } from "@utils/types";
import { findByCode, findByPropsLazy } from "@webpack"; import { findByPropsLazy, findComponentByCodeLazy } from "@webpack";
import { Button, FluxDispatcher, Forms, React, Text, Tooltip, UserStore, UserUtils } from "@webpack/common"; import { Button, Clickable, FluxDispatcher, Forms, React, Text, Tooltip, UserStore, 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";
import { PluginMeta } from "~plugins";
import { import {
ISettingCustomElementProps,
ISettingElementProps, ISettingElementProps,
SettingBooleanComponent, SettingBooleanComponent,
SettingCustomComponent, SettingCustomComponent,
@ -41,9 +46,12 @@ import {
SettingSliderComponent, SettingSliderComponent,
SettingTextComponent SettingTextComponent
} from "./components"; } from "./components";
import hideBotTagStyle from "./userPopoutHideBotTag.css?managed"; import { openContributorModal } from "./ContributorModal";
import { GithubButton, WebsiteButton } from "./LinkIconButton";
const UserSummaryItem = LazyComponent(() => findByCode("defaultRenderUser", "showDefaultAvatarsForNullUsers")); const cl = classNameFactory("vc-plugin-modal-");
const UserSummaryItem = findComponentByCodeLazy("defaultRenderUser", "showDefaultAvatarsForNullUsers");
const AvatarStyles = findByPropsLazy("moreUsers", "emptyUser", "avatarContainer", "clickableAvatar"); const AvatarStyles = findByPropsLazy("moreUsers", "emptyUser", "avatarContainer", "clickableAvatar");
const UserRecord: Constructor<Partial<User>> = proxyLazy(() => UserStore.getCurrentUser().constructor) as any; const UserRecord: Constructor<Partial<User>> = proxyLazy(() => UserStore.getCurrentUser().constructor) as any;
@ -67,14 +75,15 @@ function makeDummyUser(user: { username: string; id?: string; avatar?: string; }
return newUser; return newUser;
} }
const Components: Record<OptionType, React.ComponentType<ISettingElementProps<any>>> = { const Components: Record<OptionType, React.ComponentType<ISettingElementProps<any> | ISettingCustomElementProps<any>>> = {
[OptionType.STRING]: SettingTextComponent, [OptionType.STRING]: SettingTextComponent,
[OptionType.NUMBER]: SettingNumericComponent, [OptionType.NUMBER]: SettingNumericComponent,
[OptionType.BIGINT]: SettingNumericComponent, [OptionType.BIGINT]: SettingNumericComponent,
[OptionType.BOOLEAN]: SettingBooleanComponent, [OptionType.BOOLEAN]: SettingBooleanComponent,
[OptionType.SELECT]: SettingSelectComponent, [OptionType.SELECT]: SettingSelectComponent,
[OptionType.SLIDER]: SettingSliderComponent, [OptionType.SLIDER]: SettingSliderComponent,
[OptionType.COMPONENT]: SettingCustomComponent [OptionType.COMPONENT]: SettingCustomComponent,
[OptionType.CUSTOM]: () => null,
}; };
export default function PluginModal({ plugin, onRestartNeeded, onClose, transitionState }: PluginModalProps) { export default function PluginModal({ plugin, onRestartNeeded, onClose, transitionState }: PluginModalProps) {
@ -89,31 +98,20 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
const canSubmit = () => Object.values(errors).every(e => !e); const canSubmit = () => Object.values(errors).every(e => !e);
const hasSettings = Boolean(pluginSettings && plugin.options); const hasSettings = Boolean(pluginSettings && plugin.options && !isObjectEmpty(plugin.options));
React.useEffect(() => { React.useEffect(() => {
enableStyle(hideBotTagStyle);
let originalUser: User;
(async () => { (async () => {
for (const user of plugin.authors.slice(0, 6)) { for (const user of plugin.authors.slice(0, 6)) {
const author = user.id const author = user.id
? await UserUtils.fetchUser(`${user.id}`) ? await UserUtils.getUser(`${user.id}`)
// only show name & pfp and no actions so users cannot harass plugin devs for support (send dms, add as friend, etc)
.then(u => (originalUser = u, makeDummyUser(u)))
.catch(() => makeDummyUser({ username: user.name })) .catch(() => makeDummyUser({ username: user.name }))
: makeDummyUser({ username: user.name }); : makeDummyUser({ username: user.name });
setAuthors(a => [...a, author]); setAuthors(a => [...a, author]);
} }
})(); })();
}, [plugin.authors]);
return () => {
disableStyle(hideBotTagStyle);
if (originalUser)
FluxDispatcher.dispatch({ type: "USER_UPDATE", user: originalUser });
};
}, []);
async function saveAndClose() { async function saveAndClose() {
if (!plugin.options) { if (!plugin.options) {
@ -133,7 +131,8 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
for (const [key, value] of Object.entries(tempSettings)) { for (const [key, value] of Object.entries(tempSettings)) {
const option = plugin.options[key]; const option = plugin.options[key];
pluginSettings[key] = value; pluginSettings[key] = value;
option?.onChange?.(value);
if (option.type === OptionType.CUSTOM) continue;
if (option?.restartNeeded) restartNeeded = true; if (option?.restartNeeded) restartNeeded = true;
} }
if (restartNeeded) onRestartNeeded(); if (restartNeeded) onRestartNeeded();
@ -145,7 +144,7 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
return <Forms.FormText>There are no settings for this plugin.</Forms.FormText>; return <Forms.FormText>There are no settings for this plugin.</Forms.FormText>;
} else { } else {
const options = Object.entries(plugin.options).map(([key, setting]) => { const options = Object.entries(plugin.options).map(([key, setting]) => {
if (setting.hidden) return null; if (setting.type === OptionType.CUSTOM || setting.hidden) return null;
function onChange(newValue: any) { function onChange(newValue: any) {
setTempSettings(s => ({ ...s, [key]: newValue })); setTempSettings(s => ({ ...s, [key]: newValue }));
@ -193,16 +192,54 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
); );
} }
/*
function switchToPopout() {
onClose();
const PopoutKey = `DISCORD_VENCORD_PLUGIN_SETTINGS_MODAL_${plugin.name}`;
PopoutActions.open(
PopoutKey,
() => <PluginModal
transitionState={transitionState}
plugin={plugin}
onRestartNeeded={onRestartNeeded}
onClose={() => PopoutActions.close(PopoutKey)}
/>
);
}
*/
const pluginMeta = PluginMeta[plugin.name];
return ( return (
<ModalRoot transitionState={transitionState} size={ModalSize.MEDIUM} className="vc-text-selectable"> <ModalRoot transitionState={transitionState} size={ModalSize.MEDIUM} className="vc-text-selectable">
<ModalHeader separator={false}> <ModalHeader separator={false}>
<Text variant="heading-lg/semibold" style={{ flexGrow: 1 }}>{plugin.name}</Text> <Text variant="heading-lg/semibold" style={{ flexGrow: 1 }}>{plugin.name}</Text>
{/*
<Button look={Button.Looks.BLANK} onClick={switchToPopout}>
<OpenExternalIcon aria-label="Open in Popout" />
</Button>
*/}
<ModalCloseButton onClick={onClose} /> <ModalCloseButton onClick={onClose} />
</ModalHeader> </ModalHeader>
<ModalContent> <ModalContent>
<Forms.FormSection> <Forms.FormSection>
<Forms.FormTitle tag="h3">About {plugin.name}</Forms.FormTitle> <Flex className={cl("info")}>
<Forms.FormText>{plugin.description}</Forms.FormText> <Forms.FormText className={cl("description")}>{plugin.description}</Forms.FormText>
{!pluginMeta.userPlugin && (
<div className="vc-settings-modal-links">
<WebsiteButton
text="View more info"
href={`https://vencord.dev/plugins/${plugin.name}`}
/>
<GithubButton
text="View source code"
href={`https://github.com/${gitRemote}/tree/main/src/plugins/${pluginMeta.folderName}`}
/>
</div>
)}
</Flex>
<Forms.FormTitle tag="h3" style={{ marginTop: 8, marginBottom: 0 }}>Authors</Forms.FormTitle> <Forms.FormTitle tag="h3" style={{ marginTop: 8, marginBottom: 0 }}>Authors</Forms.FormTitle>
<div style={{ width: "fit-content", marginBottom: 8 }}> <div style={{ width: "fit-content", marginBottom: 8 }}>
<UserSummaryItem <UserSummaryItem
@ -214,6 +251,19 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
showDefaultAvatarsForNullUsers showDefaultAvatarsForNullUsers
showUserPopout showUserPopout
renderMoreUsers={renderMoreUsers} renderMoreUsers={renderMoreUsers}
renderUser={(user: User) => (
<Clickable
className={AvatarStyles.clickableAvatar}
onClick={() => openContributorModal(user)}
>
<img
className={AvatarStyles.avatar}
src={user.getAvatarURL(void 0, 80, true)}
alt={user.username}
title={user.username}
/>
</Clickable>
)}
/> />
</div> </div>
</Forms.FormSection> </Forms.FormSection>
@ -226,7 +276,7 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
</Forms.FormSection> </Forms.FormSection>
</div> </div>
)} )}
<Forms.FormSection> <Forms.FormSection className={Margins.bottom16}>
<Forms.FormTitle tag="h3">Settings</Forms.FormTitle> <Forms.FormTitle tag="h3">Settings</Forms.FormTitle>
{renderSettings()} {renderSettings()}
</Forms.FormSection> </Forms.FormSection>
@ -237,7 +287,7 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
<Button <Button
onClick={onClose} onClick={onClose}
size={Button.Sizes.SMALL} size={Button.Sizes.SMALL}
color={Button.Colors.WHITE} color={Button.Colors.PRIMARY}
look={Button.Looks.LINK} look={Button.Looks.LINK}
> >
Cancel Cancel
@ -263,3 +313,13 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
</ModalRoot> </ModalRoot>
); );
} }
export function openPluginModal(plugin: Plugin, onRestartNeeded?: (pluginName: string) => void) {
openModal(modalProps => (
<PluginModal
{...modalProps}
plugin={plugin}
onRestartNeeded={() => onRestartNeeded?.(plugin.name)}
/>
));
}

View file

@ -16,8 +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 { wordsFromCamel, wordsToTitle } from "@utils/text";
import { PluginOptionBoolean } from "@utils/types"; import { PluginOptionBoolean } from "@utils/types";
import { Forms, React, Select } from "@webpack/common"; import { Forms, React, Switch } from "@webpack/common";
import { ISettingElementProps } from "."; import { ISettingElementProps } from ".";
@ -31,11 +32,6 @@ export function SettingBooleanComponent({ option, pluginSettings, definedSetting
onError(error !== null); onError(error !== null);
}, [error]); }, [error]);
const options = [
{ label: "Enabled", value: true, default: def === true },
{ label: "Disabled", value: false, default: typeof def === "undefined" || def === false },
];
function handleChange(newValue: boolean): void { function handleChange(newValue: boolean): void {
const isValid = option.isValid?.call(definedSettings, newValue) ?? true; const isValid = option.isValid?.call(definedSettings, newValue) ?? true;
if (typeof isValid === "string") setError(isValid); if (typeof isValid === "string") setError(isValid);
@ -49,18 +45,17 @@ export function SettingBooleanComponent({ option, pluginSettings, definedSetting
return ( return (
<Forms.FormSection> <Forms.FormSection>
<Forms.FormTitle>{option.description}</Forms.FormTitle> <Switch
<Select value={state}
isDisabled={option.disabled?.call(definedSettings) ?? false} onChange={handleChange}
options={options} note={option.description}
placeholder={option.placeholder ?? "Select an option"} disabled={option.disabled?.call(definedSettings) ?? false}
maxVisibleItems={5}
closeOnSelect={true}
select={handleChange}
isSelected={v => v === state}
serialize={v => String(v)}
{...option.componentProps} {...option.componentProps}
/> hideBorder
style={{ marginBottom: "0.5em" }}
>
{wordsToTitle(wordsFromCamel(id))}
</Switch>
{error && <Forms.FormText style={{ color: "var(--text-danger)" }}>{error}</Forms.FormText>} {error && <Forms.FormText style={{ color: "var(--text-danger)" }}>{error}</Forms.FormText>}
</Forms.FormSection> </Forms.FormSection>
); );

View file

@ -18,8 +18,8 @@
import { PluginOptionComponent } from "@utils/types"; import { PluginOptionComponent } from "@utils/types";
import { ISettingElementProps } from "."; import { ISettingCustomElementProps } from ".";
export function SettingCustomComponent({ option, onChange, onError }: ISettingElementProps<PluginOptionComponent>) { export function SettingCustomComponent({ option, onChange, onError }: ISettingCustomElementProps<PluginOptionComponent>) {
return option.component({ setValue: onChange, setError: onError, option }); return option.component({ setValue: onChange, setError: onError, option });
} }

View file

@ -16,6 +16,8 @@
* 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 { Margins } from "@utils/margins";
import { wordsFromCamel, wordsToTitle } from "@utils/text";
import { OptionType, PluginOptionNumber } from "@utils/types"; import { OptionType, PluginOptionNumber } from "@utils/types";
import { Forms, React, TextInput } from "@webpack/common"; import { Forms, React, TextInput } from "@webpack/common";
@ -54,7 +56,8 @@ export function SettingNumericComponent({ option, pluginSettings, definedSetting
return ( return (
<Forms.FormSection> <Forms.FormSection>
<Forms.FormTitle>{option.description}</Forms.FormTitle> <Forms.FormTitle>{wordsToTitle(wordsFromCamel(id))}</Forms.FormTitle>
<Forms.FormText className={Margins.bottom20} type="description">{option.description}</Forms.FormText>
<TextInput <TextInput
type="number" type="number"
pattern="-?[0-9]+" pattern="-?[0-9]+"

View file

@ -16,6 +16,8 @@
* 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 { Margins } from "@utils/margins";
import { wordsFromCamel, wordsToTitle } from "@utils/text";
import { PluginOptionSelect } from "@utils/types"; import { PluginOptionSelect } from "@utils/types";
import { Forms, React, Select } from "@webpack/common"; import { Forms, React, Select } from "@webpack/common";
@ -44,7 +46,8 @@ export function SettingSelectComponent({ option, pluginSettings, definedSettings
return ( return (
<Forms.FormSection> <Forms.FormSection>
<Forms.FormTitle>{option.description}</Forms.FormTitle> <Forms.FormTitle>{wordsToTitle(wordsFromCamel(id))}</Forms.FormTitle>
<Forms.FormText className={Margins.bottom16} type="description">{option.description}</Forms.FormText>
<Select <Select
isDisabled={option.disabled?.call(definedSettings) ?? false} isDisabled={option.disabled?.call(definedSettings) ?? false}
options={option.options} options={option.options}

View file

@ -16,6 +16,8 @@
* 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 { Margins } from "@utils/margins";
import { wordsFromCamel, wordsToTitle } from "@utils/text";
import { PluginOptionSlider } from "@utils/types"; import { PluginOptionSlider } from "@utils/types";
import { Forms, React, Slider } from "@webpack/common"; import { Forms, React, Slider } from "@webpack/common";
@ -50,7 +52,8 @@ export function SettingSliderComponent({ option, pluginSettings, definedSettings
return ( return (
<Forms.FormSection> <Forms.FormSection>
<Forms.FormTitle>{option.description}</Forms.FormTitle> <Forms.FormTitle>{wordsToTitle(wordsFromCamel(id))}</Forms.FormTitle>
<Forms.FormText className={Margins.bottom20} type="description">{option.description}</Forms.FormText>
<Slider <Slider
disabled={option.disabled?.call(definedSettings) ?? false} disabled={option.disabled?.call(definedSettings) ?? false}
markers={option.markers} markers={option.markers}

View file

@ -16,6 +16,8 @@
* 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 { Margins } from "@utils/margins";
import { wordsFromCamel, wordsToTitle } from "@utils/text";
import { PluginOptionString } from "@utils/types"; import { PluginOptionString } from "@utils/types";
import { Forms, React, TextInput } from "@webpack/common"; import { Forms, React, TextInput } from "@webpack/common";
@ -33,16 +35,16 @@ export function SettingTextComponent({ option, pluginSettings, definedSettings,
const isValid = option.isValid?.call(definedSettings, newValue) ?? true; const isValid = option.isValid?.call(definedSettings, newValue) ?? true;
if (typeof isValid === "string") setError(isValid); if (typeof isValid === "string") setError(isValid);
else if (!isValid) setError("Invalid input provided."); else if (!isValid) setError("Invalid input provided.");
else { else setError(null);
setError(null);
setState(newValue); setState(newValue);
onChange(newValue); onChange(newValue);
}
} }
return ( return (
<Forms.FormSection> <Forms.FormSection>
<Forms.FormTitle>{option.description}</Forms.FormTitle> <Forms.FormTitle>{wordsToTitle(wordsFromCamel(id))}</Forms.FormTitle>
<Forms.FormText className={Margins.bottom20} type="description">{option.description}</Forms.FormText>
<TextInput <TextInput
type="text" type="text"
value={state} value={state}

Some files were not shown because too many files have changed in this diff Show more