diff --git a/package.json b/package.json index 65d97f2e0..65a2f4512 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vencord", "private": "true", - "version": "1.9.8", + "version": "1.9.9", "description": "The cutest Discord client mod", "homepage": "https://github.com/Vendicated/Vencord#readme", "bugs": { @@ -70,6 +70,7 @@ "stylelint": "^16.8.1", "stylelint-config-standard": "^36.0.1", "ts-patch": "^3.2.1", + "ts-pattern": "^5.3.1", "tsx": "^4.16.5", "type-fest": "^4.23.0", "typescript": "^5.5.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9567475fb..eaa6b537c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -116,6 +116,9 @@ importers: ts-patch: specifier: ^3.2.1 version: 3.2.1 + ts-pattern: + specifier: ^5.3.1 + version: 5.3.1 tsx: specifier: ^4.16.5 version: 4.16.5 @@ -2524,6 +2527,9 @@ packages: resolution: {integrity: sha512-hlR43v+GUIUy8/ZGFP1DquEqPh7PFKQdDMTAmYt671kCCA6AkDQMoeFaFmZ7ObPLYOmpMgyKUqL1C+coFMf30w==} hasBin: true + ts-pattern@5.3.1: + resolution: {integrity: sha512-1RUMKa8jYQdNfmnK4jyzBK3/PS/tnjcZ1CW0v1vWDeYe5RBklc/nquw03MEoB66hVBm4BnlCfmOqDVxHyT1DpA==} + tsconfig-paths@3.15.0: resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} @@ -5158,6 +5164,8 @@ snapshots: semver: 7.6.3 strip-ansi: 6.0.1 + ts-pattern@5.3.1: {} + tsconfig-paths@3.15.0: dependencies: '@types/json5': 0.0.29 diff --git a/src/components/Icons.tsx b/src/components/Icons.tsx index 7ba078d33..fa142a18c 100644 --- a/src/components/Icons.tsx +++ b/src/components/Icons.tsx @@ -65,8 +65,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 - * your own username in the bottom left user panel + * Discord's copy icon, as seen in the user panel popout on the right of the username and in large code blocks */ export function CopyIcon(props: IconProps) { return ( @@ -76,8 +75,9 @@ export function CopyIcon(props: IconProps) { viewBox="0 0 24 24" > - - + + + ); diff --git a/src/components/VencordSettings/PatchHelperTab.tsx b/src/components/VencordSettings/PatchHelperTab.tsx index e09a1dbf3..fd33c09df 100644 --- a/src/components/VencordSettings/PatchHelperTab.tsx +++ b/src/components/VencordSettings/PatchHelperTab.tsx @@ -382,6 +382,7 @@ function PatchHelper() { Code + )} diff --git a/src/plugins/CopyFileContents/README.md b/src/plugins/CopyFileContents/README.md new file mode 100644 index 000000000..18dc2d3df --- /dev/null +++ b/src/plugins/CopyFileContents/README.md @@ -0,0 +1,5 @@ +# CopyFileContents + +Adds a button to text file attachments to copy their contents. + +![](https://github.com/user-attachments/assets/b1a0f6f4-106f-4953-94d9-4c5ef5810bca) diff --git a/src/plugins/CopyFileContents/index.tsx b/src/plugins/CopyFileContents/index.tsx new file mode 100644 index 000000000..13b649174 --- /dev/null +++ b/src/plugins/CopyFileContents/index.tsx @@ -0,0 +1,60 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import "./style.css"; + +import ErrorBoundary from "@components/ErrorBoundary"; +import { CopyIcon, NoEntrySignIcon } from "@components/Icons"; +import { Devs } from "@utils/constants"; +import { copyWithToast } from "@utils/misc"; +import definePlugin from "@utils/types"; +import { Tooltip, useState } from "@webpack/common"; + +const CheckMarkIcon = () => { + return + + ; +}; + +export default definePlugin({ + name: "CopyFileContents", + description: "Adds a button to text file attachments to copy their contents", + authors: [Devs.Obsidian, Devs.Nuckyz], + patches: [ + { + find: ".Messages.PREVIEW_BYTES_LEFT.format(", + replacement: { + match: /\.footerGap.+?url:\i,fileName:\i,fileSize:\i}\),(?<=fileContents:(\i),bytesLeft:(\i).+?)/g, + replace: "$&$self.addCopyButton({fileContents:$1,bytesLeft:$2})," + } + } + ], + + addCopyButton: ErrorBoundary.wrap(({ fileContents, bytesLeft }: { fileContents: string, bytesLeft: number; }) => { + const [recentlyCopied, setRecentlyCopied] = useState(false); + + return ( + 0 ? "File too large to copy" : "Copy File Contents"}> + {tooltipProps => ( +
{ + if (!recentlyCopied && bytesLeft <= 0) { + copyWithToast(fileContents); + setRecentlyCopied(true); + setTimeout(() => setRecentlyCopied(false), 2000); + } + }} + > + {recentlyCopied ? : bytesLeft > 0 ? : } +
+ )} +
+ ); + }, { noop: true }), +}); diff --git a/src/plugins/CopyFileContents/style.css b/src/plugins/CopyFileContents/style.css new file mode 100644 index 000000000..c643cf0f0 --- /dev/null +++ b/src/plugins/CopyFileContents/style.css @@ -0,0 +1,8 @@ +.vc-cfc-button { + color: var(--interactive-normal); + cursor: pointer; +} + +.vc-cfc-button:hover { + color: var(--interactive-hover); +} diff --git a/src/plugins/_core/settings.tsx b/src/plugins/_core/settings.tsx index 3cc020836..be220db1a 100644 --- a/src/plugins/_core/settings.tsx +++ b/src/plugins/_core/settings.tsx @@ -64,7 +64,7 @@ export default definePlugin({ replace: (_, sectionTypes, commaOrSemi, elements, element) => `${commaOrSemi} $self.addSettings(${elements}, ${element}, ${sectionTypes}) ${commaOrSemi}` }, { - match: /({(?=.+?function (\i).{0,120}(\i)=\i\.useMemo.{0,30}return \i\.useMemo\(\(\)=>\i\(\3).+?function\(\){return )\2(?=})/, + match: /({(?=.+?function (\i).{0,120}(\i)=\i\.useMemo.{0,60}return \i\.useMemo\(\(\)=>\i\(\3).+?function\(\){return )\2(?=})/, replace: (_, rest, settingsHook) => `${rest}$self.wrapSettingsHook(${settingsHook})` } ] diff --git a/src/plugins/ignoreActivities/index.tsx b/src/plugins/ignoreActivities/index.tsx index bab69d89b..9e6c21bdd 100644 --- a/src/plugins/ignoreActivities/index.tsx +++ b/src/plugins/ignoreActivities/index.tsx @@ -26,6 +26,11 @@ interface IgnoredActivity { type: ActivitiesTypes; } +const enum FilterMode { + Whitelist, + Blacklist +} + const RunningGameStore = findStoreLazy("RunningGameStore"); const ShowCurrentGame = getUserSettingLazy("status", "showCurrentGame")!; @@ -70,14 +75,17 @@ function handleActivityToggle(e: React.MouseEvent if (ignoredActivityIndex === -1) settings.store.ignoredActivities = getIgnoredActivities().concat(activity); else settings.store.ignoredActivities = getIgnoredActivities().filter((_, index) => index !== ignoredActivityIndex); - // Trigger activities recalculation + recalculateActivities(); +} + +function recalculateActivities() { ShowCurrentGame.updateSetting(old => old); } function ImportCustomRPCComponent() { return ( - Import the application id of the CustomRPC plugin to the allowed list + Import the application id of the CustomRPC plugin to the filter list