aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/typingTweaks/index.tsx
diff options
context:
space:
mode:
authorV <vendicated@riseup.net>2023-09-24 16:02:18 +0200
committerV <vendicated@riseup.net>2023-09-24 16:02:18 +0200
commit30ac25607023752031aa98060cbf8a736109992d (patch)
tree79bb82b6634ef601db6c98e751275607ec54dbea /src/plugins/typingTweaks/index.tsx
parentd0e2a324717e600736a18b88fe89a21c640a406b (diff)
downloadVencord-30ac25607023752031aa98060cbf8a736109992d.tar.gz
Vencord-30ac25607023752031aa98060cbf8a736109992d.tar.bz2
Vencord-30ac25607023752031aa98060cbf8a736109992d.zip
migrate all plugins to folders
Diffstat (limited to 'src/plugins/typingTweaks/index.tsx')
-rw-r--r--src/plugins/typingTweaks/index.tsx139
1 files changed, 139 insertions, 0 deletions
diff --git a/src/plugins/typingTweaks/index.tsx b/src/plugins/typingTweaks/index.tsx
new file mode 100644
index 0000000..b76f493
--- /dev/null
+++ b/src/plugins/typingTweaks/index.tsx
@@ -0,0 +1,139 @@
+/*
+ * 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 { definePluginSettings } from "@api/Settings";
+import ErrorBoundary from "@components/ErrorBoundary";
+import { Devs } from "@utils/constants";
+import { openUserProfile } from "@utils/discord";
+import definePlugin, { OptionType } from "@utils/types";
+import { findByCodeLazy } from "@webpack";
+import { GuildMemberStore, React, RelationshipStore } from "@webpack/common";
+import { User } from "discord-types/general";
+
+const Avatar = findByCodeLazy(".typingIndicatorRef", "svg");
+
+const settings = definePluginSettings({
+ showAvatars: {
+ type: OptionType.BOOLEAN,
+ default: true,
+ description: "Show avatars in the typing indicator"
+ },
+ showRoleColors: {
+ type: OptionType.BOOLEAN,
+ default: true,
+ description: "Show role colors in the typing indicator"
+ },
+ alternativeFormatting: {
+ type: OptionType.BOOLEAN,
+ default: true,
+ description: "Show a more useful message when several users are typing"
+ }
+});
+
+export function buildSeveralUsers({ a, b, c }: { a: string, b: string, c: number; }) {
+ return [
+ <strong key="0">{a}</strong>,
+ ", ",
+ <strong key="2">{b}</strong>,
+ `, and ${c} others are typing...`
+ ];
+}
+
+interface Props {
+ user: User;
+ guildId: string;
+}
+
+const TypingUser = ErrorBoundary.wrap(function ({ user, guildId }: Props) {
+ return (
+ <strong
+ role="button"
+ onClick={() => {
+ openUserProfile(user.id);
+ }}
+ style={{
+ display: "grid",
+ gridAutoFlow: "column",
+ gap: "4px",
+ color: settings.store.showRoleColors ? GuildMemberStore.getMember(guildId, user.id)?.colorString : undefined,
+ cursor: "pointer"
+ }}
+ >
+ {settings.store.showAvatars && (
+ <div style={{ marginTop: "4px" }}>
+ <Avatar
+ size="SIZE_16"
+ src={user.getAvatarURL(guildId, 128)} />
+ </div>
+ )}
+ {GuildMemberStore.getNick(guildId!, user.id)
+ || (!guildId && RelationshipStore.getNickname(user.id))
+ || (user as any).globalName
+ || user.username
+ }
+ </strong>
+ );
+}, { noop: true });
+
+export default definePlugin({
+ name: "TypingTweaks",
+ description: "Show avatars and role colours in the typing indicator",
+ authors: [Devs.zt],
+ patches: [
+ // Style the indicator and add function call to modify the children before rendering
+ {
+ find: "getCooldownTextStyle",
+ replacement: {
+ match: /=(\i)\[2];(.+)"aria-atomic":!0,children:(\i)}\)/,
+ replace: "=$1[2];$2\"aria-atomic\":!0,style:{display:\"grid\",gridAutoFlow:\"column\",gridGap:\"0.25em\"},children:$self.mutateChildren(this.props,$1,$3)})"
+ }
+ },
+ // Changes the indicator to keep the user object when creating the list of typing users
+ {
+ find: "getCooldownTextStyle",
+ replacement: {
+ match: /return \i\.\i\.getName\(.,.\.props\.channel\.id,(.)\)/,
+ replace: "return $1"
+ }
+ },
+ // Adds the alternative formatting for several users typing
+ {
+ find: "getCooldownTextStyle",
+ replacement: {
+ match: /((\i)\.length\?.\..\.Messages\.THREE_USERS_TYPING.format\(\{a:(\i),b:(\i),c:.}\)):.+?SEVERAL_USERS_TYPING/,
+ replace: "$1:$self.buildSeveralUsers({a:$3,b:$4,c:$2.length-2})"
+ },
+ predicate: () => settings.store.alternativeFormatting
+ }
+ ],
+ settings,
+
+ buildSeveralUsers,
+
+ mutateChildren(props: any, users: User[], children: any) {
+ if (!Array.isArray(children)) return children;
+
+ let element = 0;
+
+ return children.map(c =>
+ c.type === "strong"
+ ? <TypingUser {...props} user={users[element++]} />
+ : c
+ );
+ },
+});