diff --git a/README.md b/README.md index 3b3b6071..e8af6a0e 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ You can join our [discord server](https://discord.gg/5Xh2W87egW) for commits, ch ### Extra included plugins
-168 additional plugins +169 additional plugins ### All Platforms @@ -25,7 +25,7 @@ You can join our [discord server](https://discord.gg/5Xh2W87egW) for commits, ch - BetterActivities by D3SOX, Arjix, AutumnVN - BetterAudioPlayer by Creations - BetterBanReasons by Inbestigator -- BetterBlockedUsers by TheArmagan & Elvyra +- BetterBlockedUsers by TheArmagan - BetterInvites by iamme - BetterPlusReacts by Joona - BetterQuickReact by Ven & Sqaaakoi @@ -63,6 +63,7 @@ You can join our [discord server](https://discord.gg/5Xh2W87egW) for commits, ch - FixFileExtensions by thororen - FollowVoiceUser by TheArmagan - FontLoader by vmohammad +- ForwardAnywhere by thororen - Freaky by nyx - FrequentQuickSwitcher by Samwich - FriendCodes by HypedDomi diff --git a/src/equicordplugins/betterBlockedUsers/index.tsx b/src/equicordplugins/betterBlockedUsers/index.tsx index f1a5efb5..87876bbf 100644 --- a/src/equicordplugins/betterBlockedUsers/index.tsx +++ b/src/equicordplugins/betterBlockedUsers/index.tsx @@ -4,57 +4,23 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { definePluginSettings } from "@api/Settings"; -import { Devs, EquicordDevs } from "@utils/constants"; -import { openUserProfile } from "@utils/discord"; -import { openModal } from "@utils/modal"; -import definePlugin, { OptionType } from "@utils/types"; -import { findByCodeLazy, findByPropsLazy, findComponentByCodeLazy } from "@webpack"; -import { Button, FluxDispatcher, React, RelationshipStore, showToast, Text, TextInput, UserStore } from "@webpack/common"; -import { ButtonProps } from "@webpack/types"; -import { User } from "discord-types/general"; +import "./styles.css"; + +import { EquicordDevs } from "@utils/constants"; +import { getIntlMessage, openUserProfile } from "@utils/discord"; +import definePlugin from "@utils/types"; +import { findByPropsLazy } from "@webpack"; +import { Button, React, RelationshipStore, TextInput, UserStore } from "@webpack/common"; + +const ChannelActions = findByPropsLazy("openPrivateChannel"); let lastSearch = ""; let updateFunc = (v: any) => { }; -const ChannelActions = findByPropsLazy("openPrivateChannel"); -const ButtonComponent = findComponentByCodeLazy('submittingStartedLabel","submittingFinishedLabel"]);'); -const ConfirmationModal = findByCodeLazy('"ConfirmModal")', "useLayoutEffect"); - -const settings = definePluginSettings({ - addDmsButton: { - default: true, - type: OptionType.BOOLEAN, - description: "Adds a 'View DMs' button to the users in the blocked/ignored list.", - }, - showUnblockConfirmation: { - default: true, - type: OptionType.BOOLEAN, - description: "Show a warning before unblocking a user from the blocklist.", - }, - showUnblockConfirmationEverywhere: { - default: false, - type: OptionType.BOOLEAN, - description: "Show a warning before unblocking a user anywhere on discord.", - restartNeeded: true, - }, - unblockButtonDanger: { - default: false, - type: OptionType.BOOLEAN, - description: "Color the unblock button in the blocklist red instead of gray.", - }, - allowShiftUnblock: { - default: true, - type: OptionType.BOOLEAN, - description: "Unblock a user without confirmation prompting when holding shift.", - } -}); - export default definePlugin({ name: "BetterBlockedUsers", - description: "Allows you to search in blocked users list and makes names clickable in settings.", - authors: [EquicordDevs.TheArmagan, Devs.Elvyra], - settings, + description: "Allows you to search in blocked users list and makes names selectable in settings.", + authors: [EquicordDevs.TheArmagan], patches: [ { find: '"],{numberOfBlockedUsers:', @@ -64,12 +30,8 @@ export default definePlugin({ replace: ",$1.listType==='blocked'?$self.renderSearchInput():null" }, { - match: /(?<=className:\i.userInfo,)(?=children:.{0,20}user:(\i))/, - replace: "style:{cursor:'pointer'},onClick:()=>$self.openUserProfile($1)," - }, - { - match: /(?<=children:null!=(\i).globalName\?.+?}\),).*?(\{color:.{0,65}?string\((\i).+?"8wXU9P"]\)})\)/, - replace: "$self.generateButtons({user:$1, originalProps:$2, isBlocked:$3})", + match: /(?<=userId:(\i).*?\}\)\]\}\),)(\(.*?\)\}\))/, + replace: "$self.renderUser($1,$2),", }, { match: /(?<=\}=(\i).{0,10}(\i).useState\(.{0,1}\);)/, @@ -80,45 +42,6 @@ export default definePlugin({ replace: "$1(searchResults.length?searchResults:$2)" }, ] - }, - { - find: "#{intl::OUTGOING_FRIEND_REQUEST}", - group: true, - replacement: [ - { - match: /(?<=return \i)\|\|(\i)===.*?.FRIEND/, - replace: (_, type) => `?null:${type} === 1|| ${type} === 2`, - }, - { - match: /(?<=\i.bot.{0,50}children:.*?onClose:)(\i)/, - replace: "() => {$1();$self.closeSettingsWindow()}", - } - ], - }, - - { - find: ".BLOCKED:return", - replacement: { - match: /(?<=\i.BLOCKED:return.{0,65}onClick:)\(\)=>\{(\i.\i.unblockUser\((\i).+?}\))/, - replace: "(event) => {$self.openConfirmationModal(event,()=>{$1}, $2)", - }, - predicate: () => settings.store.showUnblockConfirmationEverywhere, - }, - { - find: "#{intl::UNBLOCK}),", - replacement: { - match: /(?<=#{intl::UNBLOCK}.+?Click=)\(\)=>(\{.+?(\i.getRecipientId\(\))\)})/, - replace: "event => $self.openConfirmationModal(event, ()=>$1, $2)", - }, - predicate: () => settings.store.showUnblockConfirmationEverywhere, - }, - { - find: "#{intl::BLOCK}),action", - replacement: { - match: /(?<=id:"block".{0,100}action:\i\?)\(\)=>(\{.{0,25}unblockUser\((\i).{0,60}:void 0\)})/, - replace: "event => {$self.openConfirmationModal(event, ()=>$1,$2)}", - }, - predicate: () => settings.store.showUnblockConfirmationEverywhere, } ], renderSearchInput() { @@ -141,6 +64,19 @@ export default definePlugin({ }} value={value} >; }, + renderUser(userId: string, rest: any) { + return ( +
+ + {rest} +
+ ); + }, + getSearchResults() { + return !!lastSearch; + }, setUpdateFunc(e, setResults) { if (e.listType !== "blocked") return; updateFunc = setResults; @@ -153,77 +89,5 @@ export default definePlugin({ if (!user) return id === search; return id === search || user?.username?.toLowerCase()?.includes(search) || user?.globalName?.toLowerCase()?.includes(search); }) as string[]; - }, - closeSettingsWindow() { - FluxDispatcher.dispatch({ type: "LAYER_POP" }); - }, - openUserProfile(user: User) { - openUserProfile(user.id); - }, - generateButtons(props: { user: User, originalProps: ButtonProps, isBlocked: boolean; }) { - const { user, originalProps, isBlocked } = props; - - if (settings.store.unblockButtonDanger) originalProps.color = Button.Colors.RED; - - if (settings.store.showUnblockConfirmation || settings.store.showUnblockConfirmationEverywhere) { - const originalOnClick = originalProps.onClick!; - originalProps.onClick = e => { - if (!isBlocked) return originalOnClick(e); - this.openConfirmationModal(e as unknown as MouseEvent, () => originalOnClick(e), user, true); - }; - } - - const unblockButton = ; - - if (!settings.store.addDmsButton) return unblockButton; - - const dmButton = this.openDMChannel(user)}>Show DMs; - - return
- {dmButton} - {unblockButton} -
; - }, - - openDMChannel(user: User) { - try { - ChannelActions.openPrivateChannel(user.id); - } - catch (e) { - showToast("Failed to open DMs for user '" + user.username + "'! Check the console for more info"); - return console.error(e); - } - // only close the settings window if we actually opened a DM channel behind it. - this.closeSettingsWindow(); - }, - - openConfirmationModal(event: MouseEvent, callback: () => any, user: User | string, isSettingsOrigin: boolean = false) { - if (event.shiftKey && settings.store.allowShiftUnblock) return callback(); - - if (typeof user === "string") { - user = UserStore.getUser(user); - } - - return openModal(m => { - callback(); - }}> -
-
- {`Are you sure you want to unblock ${user?.username ?? "this user"}?`} - {`This will allow ${user?.username ?? "them"} to see your profile and message you again.`} -
- {"You can always block them again later."} - {isSettingsOrigin ?
- {"If you just want to read the chat logs instead, you can just click on their profile."} - {"Alternatively, you can enable a button to jump to DMs in the blocklist through the plugin settings."} -
: {"If you just want to read the chat logs, you can do this without unblocking them."}} -
-
); - }, + } }); diff --git a/src/equicordplugins/betterBlockedUsers/styles.css b/src/equicordplugins/betterBlockedUsers/styles.css new file mode 100644 index 00000000..810c6772 --- /dev/null +++ b/src/equicordplugins/betterBlockedUsers/styles.css @@ -0,0 +1,3 @@ +[class*="usersList_"] [class*="text_"] { + user-select: text !important; +} diff --git a/src/equicordplugins/forwardAnywhere/index.ts b/src/equicordplugins/forwardAnywhere/index.ts new file mode 100644 index 00000000..806e8aa7 --- /dev/null +++ b/src/equicordplugins/forwardAnywhere/index.ts @@ -0,0 +1,39 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2025 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { EquicordDevs } from "@utils/constants"; +import { sendMessage } from "@utils/discord"; +import definePlugin from "@utils/types"; +import { Message } from "discord-types/general"; + +export default definePlugin({ + name: "ForwardAnywhere", + description: "If a forward fails send it as a normal message also allows nsfw forwards", + authors: [EquicordDevs.thororen], + patches: [ + { + find: "#{intl::MESSAGE_FORWARDING_NSFW_NOT_ALLOWED}", + replacement: { + match: /if\((\i)\.isNSFW\(\)&&.{0,25}\)\)\)/, + replace: "if(false)", + } + }, + { + find: "#{intl::MESSAGE_ACTION_FORWARD_TO}", + replacement: { + match: /(?<=let (\i)=.{0,25}rejected.{0,25}\);)(?=.{0,25}message:(\i))/, + replace: "if ($1) return $self.sendForward($1,$2);", + } + }, + ], + sendForward(channels: any, message: Message) { + for (const c of channels) { + sendMessage(c.id, { + content: `${message.content}\n\n> Forwarded from <#${message.channel_id}>` + }); + } + } +});