Add chat bar button api ~ fixes buttons for russian users
This commit is contained in:
parent
8938f4a3cf
commit
bf977e0047
10 changed files with 325 additions and 307 deletions
123
src/api/ChatButtons.tsx
Normal file
123
src/api/ChatButtons.tsx
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2024 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
|
import { Logger } from "@utils/Logger";
|
||||||
|
import { Button, ButtonLooks, ButtonWrapperClasses, Tooltip } from "@webpack/common";
|
||||||
|
import { Channel } from "discord-types/general";
|
||||||
|
import { HTMLProps, MouseEventHandler, ReactNode } from "react";
|
||||||
|
|
||||||
|
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 ChatBarButton = (props: ChatBarProps, isMainChat: boolean) => ReactNode;
|
||||||
|
|
||||||
|
const buttonFactories = new Map<string, ChatBarButton>();
|
||||||
|
const logger = new Logger("ChatButtons");
|
||||||
|
|
||||||
|
export function _injectButtons(buttons: ReactNode[], props: ChatBarProps) {
|
||||||
|
if (props.type.analyticsName !== "normal") return;
|
||||||
|
|
||||||
|
for (const [key, makeButton] of buttonFactories) {
|
||||||
|
try {
|
||||||
|
const res = makeButton(props, props.type.analyticsName === "normal");
|
||||||
|
if (res) buttons.push(res);
|
||||||
|
} catch (e) {
|
||||||
|
logger.error(`Failed to render button ${key}`, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const addChatBarButton = (id: string, button: ChatBarButton) => 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>;
|
||||||
|
buttonProps?: Omit<HTMLProps<HTMLButtonElement>, "size" | "onClick" | "onContextMenu">;
|
||||||
|
}
|
||||||
|
export const ChatBarButton = ErrorBoundary.wrap((props: ChatBarButtonProps) => {
|
||||||
|
return (
|
||||||
|
<Tooltip text={props.tooltip}>
|
||||||
|
{({ onMouseEnter, onMouseLeave }) => (
|
||||||
|
<div style={{ display: "flex" }}>
|
||||||
|
<Button
|
||||||
|
aria-label={props.tooltip}
|
||||||
|
size=""
|
||||||
|
look={ButtonLooks.BLANK}
|
||||||
|
onMouseEnter={onMouseEnter}
|
||||||
|
onMouseLeave={onMouseLeave}
|
||||||
|
innerClassName={ButtonWrapperClasses.button}
|
||||||
|
onClick={props.onClick}
|
||||||
|
onContextMenu={props.onContextMenu}
|
||||||
|
{...props.buttonProps}
|
||||||
|
>
|
||||||
|
<div className={ButtonWrapperClasses.buttonWrapper}>
|
||||||
|
{props.children}
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
}, { noop: true });
|
|
@ -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";
|
||||||
|
@ -104,3 +105,8 @@ 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;
|
||||||
|
|
22
src/plugins/_api/chatButtons.ts
Normal file
22
src/plugins/_api/chatButtons.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2024 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Devs } from "@utils/constants";
|
||||||
|
import definePlugin from "@utils/types";
|
||||||
|
|
||||||
|
export default definePlugin({
|
||||||
|
name: "ChatInputButtonAPI",
|
||||||
|
description: "API to add buttons to the chat input",
|
||||||
|
authors: [Devs.Ven],
|
||||||
|
|
||||||
|
patches: [{
|
||||||
|
find: 'location:"ChannelTextAreaButtons"',
|
||||||
|
replacement: {
|
||||||
|
match: /if\(!\i\.isMobile\)\{(?=.+?&&(\i)\.push\(.{0,50}"gift")/,
|
||||||
|
replace: "$&Vencord.Api.ChatButtons._injectButtons($1,arguments[0]);"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
});
|
|
@ -16,13 +16,14 @@
|
||||||
* 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 { addChatBarButton, ChatBarButton } from "@api/ChatButtons";
|
||||||
import { addButton, removeButton } from "@api/MessagePopover";
|
import { addButton, removeButton } from "@api/MessagePopover";
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { getStegCloak } from "@utils/dependencies";
|
import { getStegCloak } from "@utils/dependencies";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { Button, ButtonLooks, ButtonWrapperClasses, ChannelStore, FluxDispatcher, RestAPI, Tooltip } from "@webpack/common";
|
import { ChannelStore, FluxDispatcher, RestAPI, Tooltip } from "@webpack/common";
|
||||||
import { Message } from "discord-types/general";
|
import { Message } from "discord-types/general";
|
||||||
|
|
||||||
import { buildDecModal } from "./components/DecryptionModal";
|
import { buildDecModal } from "./components/DecryptionModal";
|
||||||
|
@ -64,36 +65,19 @@ function Indicator() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function ChatBarIcon(chatBoxProps: {
|
const ChatBarIcon: ChatBarButton = (_, isMainChat) => {
|
||||||
type: {
|
if (!isMainChat) return null;
|
||||||
analyticsName: string;
|
|
||||||
};
|
|
||||||
}) {
|
|
||||||
if (chatBoxProps.type.analyticsName !== "normal") return null;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip text="Encrypt Message">
|
<ChatBarButton
|
||||||
{({ onMouseEnter, onMouseLeave }) => (
|
tooltip="Encrypt Message"
|
||||||
// size="" = Button.Sizes.NONE
|
|
||||||
/*
|
|
||||||
many themes set "> button" to display: none, as the gift button is
|
|
||||||
the only directly descending button (all the other elements are divs.)
|
|
||||||
Thus, wrap in a div here to avoid getting hidden by that.
|
|
||||||
flex is for some reason necessary as otherwise the button goes flying off
|
|
||||||
*/
|
|
||||||
<div style={{ display: "flex" }}>
|
|
||||||
<Button
|
|
||||||
aria-haspopup="dialog"
|
|
||||||
aria-label="Encrypt Message"
|
|
||||||
size=""
|
|
||||||
look={ButtonLooks.BLANK}
|
|
||||||
onMouseEnter={onMouseEnter}
|
|
||||||
onMouseLeave={onMouseLeave}
|
|
||||||
innerClassName={ButtonWrapperClasses.button}
|
|
||||||
onClick={() => buildEncModal()}
|
onClick={() => buildEncModal()}
|
||||||
style={{ padding: "0 2px", scale: "0.9" }}
|
|
||||||
|
buttonProps={{
|
||||||
|
"aria-haspopup": "dialog",
|
||||||
|
style: { padding: "0 2px", scale: "0.9" }
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div className={ButtonWrapperClasses.buttonWrapper}>
|
|
||||||
<svg
|
<svg
|
||||||
aria-hidden
|
aria-hidden
|
||||||
role="img"
|
role="img"
|
||||||
|
@ -104,14 +88,9 @@ function ChatBarIcon(chatBoxProps: {
|
||||||
>
|
>
|
||||||
<path fill="currentColor" d="M 32 9 C 24.832 9 19 14.832 19 22 L 19 27.347656 C 16.670659 28.171862 15 30.388126 15 33 L 15 49 C 15 52.314 17.686 55 21 55 L 43 55 C 46.314 55 49 52.314 49 49 L 49 33 C 49 30.388126 47.329341 28.171862 45 27.347656 L 45 22 C 45 14.832 39.168 9 32 9 z M 32 13 C 36.963 13 41 17.038 41 22 L 41 27 L 23 27 L 23 22 C 23 17.038 27.037 13 32 13 z" />
|
<path fill="currentColor" d="M 32 9 C 24.832 9 19 14.832 19 22 L 19 27.347656 C 16.670659 28.171862 15 30.388126 15 33 L 15 49 C 15 52.314 17.686 55 21 55 L 43 55 C 46.314 55 49 52.314 49 49 L 49 33 C 49 30.388126 47.329341 28.171862 45 27.347656 L 45 22 C 45 14.832 39.168 9 32 9 z M 32 13 C 36.963 13 41 17.038 41 22 L 41 27 L 23 27 L 23 22 C 23 17.038 27.037 13 32 13 z" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</ChatBarButton>
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</Tooltip >
|
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const settings = definePluginSettings({
|
const settings = definePluginSettings({
|
||||||
savedPasswords: {
|
savedPasswords: {
|
||||||
|
@ -125,7 +104,7 @@ export default definePlugin({
|
||||||
name: "InvisibleChat",
|
name: "InvisibleChat",
|
||||||
description: "Encrypt your Messages in a non-suspicious way!",
|
description: "Encrypt your Messages in a non-suspicious way!",
|
||||||
authors: [Devs.SammCheese],
|
authors: [Devs.SammCheese],
|
||||||
dependencies: ["MessagePopoverAPI"],
|
dependencies: ["MessagePopoverAPI", "ChatInputButtonAPI"],
|
||||||
patches: [
|
patches: [
|
||||||
{
|
{
|
||||||
// Indicator
|
// Indicator
|
||||||
|
@ -135,13 +114,6 @@ export default definePlugin({
|
||||||
replace: "try {$1 && $self.INV_REGEX.test($1.message.content) ? $1.content.push($self.indicator()) : null } catch {};$&"
|
replace: "try {$1 && $self.INV_REGEX.test($1.message.content) ? $1.content.push($self.indicator()) : null } catch {};$&"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
find: "ChannelTextAreaButtons",
|
|
||||||
replacement: {
|
|
||||||
match: /(\i)\.push.{1,30}disabled:(\i),.{1,20}\},"gift"\)\)/,
|
|
||||||
replace: "$&,(()=>{try{$2||$1.push($self.chatBarIcon(arguments[0]))}catch{}})()",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
|
|
||||||
EMBED_API_URL: "https://embed.sammcheese.net",
|
EMBED_API_URL: "https://embed.sammcheese.net",
|
||||||
|
@ -154,7 +126,7 @@ export default definePlugin({
|
||||||
const { default: StegCloak } = await getStegCloak();
|
const { default: StegCloak } = await getStegCloak();
|
||||||
steggo = new StegCloak(true, false);
|
steggo = new StegCloak(true, false);
|
||||||
|
|
||||||
addButton("invDecrypt", message => {
|
addButton("InvisibleChat", message => {
|
||||||
return this.INV_REGEX.test(message?.content)
|
return this.INV_REGEX.test(message?.content)
|
||||||
? {
|
? {
|
||||||
label: "Decrypt Message",
|
label: "Decrypt Message",
|
||||||
|
@ -170,10 +142,13 @@ export default definePlugin({
|
||||||
}
|
}
|
||||||
: null;
|
: null;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
addChatBarButton("InvisibleChat", ChatBarIcon);
|
||||||
},
|
},
|
||||||
|
|
||||||
stop() {
|
stop() {
|
||||||
removeButton("invDecrypt");
|
removeButton("InvisibleChat");
|
||||||
|
removeButton("InvisibleChat");
|
||||||
},
|
},
|
||||||
|
|
||||||
// Gets the Embed of a Link
|
// Gets the Embed of a Link
|
||||||
|
@ -216,7 +191,6 @@ export default definePlugin({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
chatBarIcon: ErrorBoundary.wrap(ChatBarIcon, { noop: true }),
|
|
||||||
popOverIcon: () => <PopOverIcon />,
|
popOverIcon: () => <PopOverIcon />,
|
||||||
indicator: ErrorBoundary.wrap(Indicator, { noop: true })
|
indicator: ErrorBoundary.wrap(Indicator, { noop: true })
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,22 +16,14 @@
|
||||||
* 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 { addChatBarButton, ChatBarButton, removeChatBarButton } from "@api/ChatButtons";
|
||||||
import { generateId, sendBotMessage } from "@api/Commands";
|
import { generateId, sendBotMessage } from "@api/Commands";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findByPropsLazy } from "@webpack";
|
||||||
import { Button, ButtonLooks, ButtonWrapperClasses, DraftStore, DraftType, SelectedChannelStore, Tooltip, UserStore, useStateFromStores } from "@webpack/common";
|
import { DraftStore, DraftType, SelectedChannelStore, UserStore, useStateFromStores } from "@webpack/common";
|
||||||
import { MessageAttachment } from "discord-types/general";
|
import { MessageAttachment } from "discord-types/general";
|
||||||
|
|
||||||
interface Props {
|
|
||||||
type: {
|
|
||||||
analyticsName: string;
|
|
||||||
isEmpty: boolean;
|
|
||||||
attachments: boolean;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const UploadStore = findByPropsLazy("getUploads");
|
const UploadStore = findByPropsLazy("getUploads");
|
||||||
|
|
||||||
const getDraft = (channelId: string) => DraftStore.getDraft(channelId, DraftType.ChannelMessage);
|
const getDraft = (channelId: string) => DraftStore.getDraft(channelId, DraftType.ChannelMessage);
|
||||||
|
@ -81,13 +73,13 @@ const getAttachments = async (channelId: string) =>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
export function PreviewButton(chatBoxProps: Props) {
|
const PreviewButton: ChatBarButton = (props, isMainChat) => {
|
||||||
const { isEmpty, attachments } = chatBoxProps.type;
|
const { isEmpty, type: { attachments } } = props;
|
||||||
|
|
||||||
const channelId = SelectedChannelStore.getChannelId();
|
const channelId = SelectedChannelStore.getChannelId();
|
||||||
const draft = useStateFromStores([DraftStore], () => getDraft(channelId));
|
const draft = useStateFromStores([DraftStore], () => getDraft(channelId));
|
||||||
|
|
||||||
if (chatBoxProps.type.analyticsName !== "normal") return null;
|
if (!isMainChat) return null;
|
||||||
|
|
||||||
const hasAttachments = attachments && UploadStore.getUploads(channelId, DraftType.ChannelMessage).length > 0;
|
const hasAttachments = attachments && UploadStore.getUploads(channelId, DraftType.ChannelMessage).length > 0;
|
||||||
const hasContent = !isEmpty && draft?.length > 0;
|
const hasContent = !isEmpty && draft?.length > 0;
|
||||||
|
@ -95,10 +87,8 @@ export function PreviewButton(chatBoxProps: Props) {
|
||||||
if (!hasContent && !hasAttachments) return null;
|
if (!hasContent && !hasAttachments) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip text="Preview Message">
|
<ChatBarButton
|
||||||
{tooltipProps => (
|
tooltip="Preview Message"
|
||||||
<Button
|
|
||||||
{...tooltipProps}
|
|
||||||
onClick={async () =>
|
onClick={async () =>
|
||||||
sendBotMessage(
|
sendBotMessage(
|
||||||
channelId,
|
channelId,
|
||||||
|
@ -108,34 +98,22 @@ export function PreviewButton(chatBoxProps: Props) {
|
||||||
attachments: hasAttachments ? await getAttachments(channelId) : undefined,
|
attachments: hasAttachments ? await getAttachments(channelId) : undefined,
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
size=""
|
buttonProps={{
|
||||||
look={ButtonLooks.BLANK}
|
style: { padding: "0 2px", height: "100%" }
|
||||||
innerClassName={ButtonWrapperClasses.button}
|
}}
|
||||||
style={{ padding: "0 2px", height: "100%" }}
|
|
||||||
>
|
>
|
||||||
<div className={ButtonWrapperClasses.buttonWrapper}>
|
|
||||||
<img width={24} height={24} src="https://discord.com/assets/4c5a77a89716352686f590a6f014770c.svg" />
|
<img width={24} height={24} src="https://discord.com/assets/4c5a77a89716352686f590a6f014770c.svg" />
|
||||||
</div>
|
</ChatBarButton>
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</Tooltip>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
};
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "PreviewMessage",
|
name: "PreviewMessage",
|
||||||
description: "Lets you preview your message before sending it.",
|
description: "Lets you preview your message before sending it.",
|
||||||
authors: [Devs.Aria],
|
authors: [Devs.Aria],
|
||||||
patches: [
|
dependencies: ["ChatInputButtonAPI"],
|
||||||
{
|
|
||||||
find: "ChannelTextAreaButtons",
|
|
||||||
replacement: {
|
|
||||||
match: /(\i)\.push.{1,30}disabled:(\i),.{1,20}\},"gift"\)\)/,
|
|
||||||
replace: "$&,(()=>{try{$2||$1.push($self.chatBarIcon(arguments[0]))}catch{}})()",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
chatBarIcon: ErrorBoundary.wrap(PreviewButton, { noop: true }),
|
start: () => addChatBarButton("previewMessage", PreviewButton),
|
||||||
|
stop: () => removeChatBarButton("previewMessage"),
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
import "./styles.css";
|
import "./styles.css";
|
||||||
|
|
||||||
|
import { addChatBarButton, ChatBarButton, removeChatBarButton } from "@api/ChatButtons";
|
||||||
import { addPreSendListener, removePreSendListener } from "@api/MessageEvents";
|
import { addPreSendListener, removePreSendListener } from "@api/MessageEvents";
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import { classNameFactory } from "@api/Styles";
|
import { classNameFactory } from "@api/Styles";
|
||||||
|
@ -26,7 +27,7 @@ import { getTheme, insertTextIntoChatInputBox, Theme } from "@utils/discord";
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
import { closeModal, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, openModal } from "@utils/modal";
|
import { closeModal, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, openModal } from "@utils/modal";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { Button, ButtonLooks, ButtonWrapperClasses, Forms, Parser, Select, Tooltip, useMemo, useState } from "@webpack/common";
|
import { Button, Forms, Parser, Select, useMemo, useState } from "@webpack/common";
|
||||||
|
|
||||||
const settings = definePluginSettings({
|
const settings = definePluginSettings({
|
||||||
replaceMessageContents: {
|
replaceMessageContents: {
|
||||||
|
@ -122,51 +123,12 @@ function PickerModal({ rootProps, close }: { rootProps: ModalProps, close(): voi
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default definePlugin({
|
const ChatBarIcon: ChatBarButton = (_, isMainChat) => {
|
||||||
name: "SendTimestamps",
|
if (!isMainChat) return null;
|
||||||
description: "Send timestamps easily via chat box button & text shortcuts. Read the extended description!",
|
|
||||||
authors: [Devs.Ven, Devs.Tyler, Devs.Grzesiek11],
|
|
||||||
dependencies: ["MessageEventsAPI"],
|
|
||||||
|
|
||||||
settings: settings,
|
|
||||||
|
|
||||||
patches: [
|
|
||||||
{
|
|
||||||
find: "ChannelTextAreaButtons",
|
|
||||||
replacement: {
|
|
||||||
match: /(\i)\.push.{1,30}disabled:(\i),.{1,20}\},"gift"\)\)/,
|
|
||||||
replace: "$&,(()=>{try{$2||$1.push($self.chatBarIcon(arguments[0]))}catch{}})()",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
start() {
|
|
||||||
this.listener = addPreSendListener((_, msg) => {
|
|
||||||
if (settings.store.replaceMessageContents) {
|
|
||||||
msg.content = msg.content.replace(/`\d{1,2}:\d{2} ?(?:AM|PM)?`/gi, parseTime);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
stop() {
|
|
||||||
removePreSendListener(this.listener);
|
|
||||||
},
|
|
||||||
|
|
||||||
chatBarIcon(chatBoxProps: { type: { analyticsName: string; }; }) {
|
|
||||||
if (chatBoxProps.type.analyticsName !== "normal") return null;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip text="Insert Timestamp">
|
<ChatBarButton
|
||||||
{({ onMouseEnter, onMouseLeave }) => (
|
tooltip="Insert Timestamp"
|
||||||
<div style={{ display: "flex" }}>
|
|
||||||
<Button
|
|
||||||
aria-haspopup="dialog"
|
|
||||||
aria-label="Insert Timestamp"
|
|
||||||
size=""
|
|
||||||
look={ButtonLooks.BLANK}
|
|
||||||
onMouseEnter={onMouseEnter}
|
|
||||||
onMouseLeave={onMouseLeave}
|
|
||||||
innerClassName={ButtonWrapperClasses.button}
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const key = openModal(props => (
|
const key = openModal(props => (
|
||||||
<PickerModal
|
<PickerModal
|
||||||
|
@ -175,9 +137,11 @@ export default definePlugin({
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
}}
|
}}
|
||||||
className={cl("button")}
|
buttonProps={{
|
||||||
|
"aria-haspopup": "dialog",
|
||||||
|
className: cl("button")
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div className={ButtonWrapperClasses.buttonWrapper}>
|
|
||||||
<svg
|
<svg
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
role="img"
|
role="img"
|
||||||
|
@ -190,13 +154,30 @@ export default definePlugin({
|
||||||
<rect width="24" height="24" />
|
<rect width="24" height="24" />
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</ChatBarButton>
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</Tooltip >
|
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default definePlugin({
|
||||||
|
name: "SendTimestamps",
|
||||||
|
description: "Send timestamps easily via chat box button & text shortcuts. Read the extended description!",
|
||||||
|
authors: [Devs.Ven, Devs.Tyler, Devs.Grzesiek11],
|
||||||
|
dependencies: ["MessageEventsAPI", "ChatInputButtonAPI"],
|
||||||
|
|
||||||
|
settings,
|
||||||
|
|
||||||
|
start() {
|
||||||
|
addChatBarButton("SendTimestamps", ChatBarIcon);
|
||||||
|
this.listener = addPreSendListener((_, msg) => {
|
||||||
|
if (settings.store.replaceMessageContents) {
|
||||||
|
msg.content = msg.content.replace(/`\d{1,2}:\d{2} ?(?:AM|PM)?`/gi, parseTime);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
removeChatBarButton("SendTimestamps");
|
||||||
|
removePreSendListener(this.listener);
|
||||||
},
|
},
|
||||||
|
|
||||||
settingsAboutComponent() {
|
settingsAboutComponent() {
|
||||||
|
|
|
@ -16,12 +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 { addChatBarButton, ChatBarButton, removeChatBarButton } from "@api/ChatButtons";
|
||||||
import { addPreSendListener, removePreSendListener, SendListener } from "@api/MessageEvents";
|
import { addPreSendListener, removePreSendListener, SendListener } from "@api/MessageEvents";
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { Button, ButtonLooks, ButtonWrapperClasses, React, Tooltip } from "@webpack/common";
|
import { React, useEffect, useState } from "@webpack/common";
|
||||||
|
|
||||||
let lastState = false;
|
let lastState = false;
|
||||||
|
|
||||||
|
@ -41,19 +41,15 @@ const settings = definePluginSettings({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function SilentMessageToggle(chatBoxProps: {
|
const SilentMessageToggle: ChatBarButton = (_, isMainChat) => {
|
||||||
type: {
|
const [enabled, setEnabled] = useState(lastState);
|
||||||
analyticsName: string;
|
|
||||||
};
|
|
||||||
}) {
|
|
||||||
const [enabled, setEnabled] = React.useState(lastState);
|
|
||||||
|
|
||||||
function setEnabledValue(value: boolean) {
|
function setEnabledValue(value: boolean) {
|
||||||
if (settings.store.persistState) lastState = value;
|
if (settings.store.persistState) lastState = value;
|
||||||
setEnabled(value);
|
setEnabled(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
React.useEffect(() => {
|
useEffect(() => {
|
||||||
const listener: SendListener = (_, message) => {
|
const listener: SendListener = (_, message) => {
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
if (settings.store.autoDisable) setEnabledValue(false);
|
if (settings.store.autoDisable) setEnabledValue(false);
|
||||||
|
@ -65,21 +61,16 @@ function SilentMessageToggle(chatBoxProps: {
|
||||||
return () => void removePreSendListener(listener);
|
return () => void removePreSendListener(listener);
|
||||||
}, [enabled]);
|
}, [enabled]);
|
||||||
|
|
||||||
if (chatBoxProps.type.analyticsName !== "normal") return null;
|
if (!isMainChat) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip text={enabled ? "Disable Silent Message" : "Enable Silent Message"}>
|
<ChatBarButton
|
||||||
{tooltipProps => (
|
tooltip={enabled ? "Disable Silent Message" : "Enable Silent Message"}
|
||||||
<div style={{ display: "flex" }}>
|
|
||||||
<Button
|
|
||||||
{...tooltipProps}
|
|
||||||
onClick={() => setEnabledValue(!enabled)}
|
onClick={() => setEnabledValue(!enabled)}
|
||||||
size=""
|
buttonProps={{
|
||||||
look={ButtonLooks.BLANK}
|
style: { padding: "0 6px" }
|
||||||
innerClassName={ButtonWrapperClasses.button}
|
}}
|
||||||
style={{ padding: "0 6px" }}
|
|
||||||
>
|
>
|
||||||
<div className={ButtonWrapperClasses.buttonWrapper}>
|
|
||||||
<svg width="24" height="24" viewBox="0 0 24 24">
|
<svg width="24" height="24" viewBox="0 0 24 24">
|
||||||
<path fill="currentColor" mask="url(#_)" d="M18 10.7101C15.1085 9.84957 13 7.17102 13 4c0-.30736.0198-.6101.0582-.907C12.7147 3.03189 12.3611 3 12 3 8.686 3 6 5.686 6 9v5c0 1.657-1.344 3-3 3v1h18v-1c-1.656 0-3-1.343-3-3v-3.2899ZM8.55493 19c.693 1.19 1.96897 2 3.44497 2s2.752-.81 3.445-2H8.55493ZM18.2624 5.50209 21 2.5V1h-4.9651v1.49791h2.4411L16 5.61088V7h5V5.50209h-2.7376Z" />
|
<path fill="currentColor" mask="url(#_)" d="M18 10.7101C15.1085 9.84957 13 7.17102 13 4c0-.30736.0198-.6101.0582-.907C12.7147 3.03189 12.3611 3 12 3 8.686 3 6 5.686 6 9v5c0 1.657-1.344 3-3 3v1h18v-1c-1.656 0-3-1.343-3-3v-3.2899ZM8.55493 19c.693 1.19 1.96897 2 3.44497 2s2.752-.81 3.445-2H8.55493ZM18.2624 5.50209 21 2.5V1h-4.9651v1.49791h2.4411L16 5.61088V7h5V5.50209h-2.7376Z" />
|
||||||
{!enabled && <>
|
{!enabled && <>
|
||||||
|
@ -90,30 +81,17 @@ function SilentMessageToggle(chatBoxProps: {
|
||||||
<path fill="var(--status-danger)" d="m21.178 1.70703 1.414 1.414L4.12103 21.593l-1.414-1.415L21.178 1.70703Z" />
|
<path fill="var(--status-danger)" d="m21.178 1.70703 1.414 1.414L4.12103 21.593l-1.414-1.415L21.178 1.70703Z" />
|
||||||
</>}
|
</>}
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</ChatBarButton>
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Tooltip>
|
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "SilentMessageToggle",
|
name: "SilentMessageToggle",
|
||||||
authors: [Devs.Nuckyz, Devs.CatNoir],
|
authors: [Devs.Nuckyz, Devs.CatNoir],
|
||||||
description: "Adds a button to the chat bar to toggle sending a silent message.",
|
description: "Adds a button to the chat bar to toggle sending a silent message.",
|
||||||
dependencies: ["MessageEventsAPI"],
|
dependencies: ["MessageEventsAPI", "ChatInputButtonAPI"],
|
||||||
|
|
||||||
settings,
|
settings,
|
||||||
patches: [
|
|
||||||
{
|
|
||||||
find: "ChannelTextAreaButtons",
|
|
||||||
replacement: {
|
|
||||||
match: /(\i)\.push.{1,30}disabled:(\i),.{1,20}\},"gift"\)\)/,
|
|
||||||
replace: "$&,(()=>{try{$2||$1.push($self.chatBarIcon(arguments[0]))}catch{}})()",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
chatBarIcon: ErrorBoundary.wrap(SilentMessageToggle, { noop: true }),
|
start: () => addChatBarButton("SilentMessageToggle", SilentMessageToggle),
|
||||||
|
stop: () => removeChatBarButton("SilentMessageToggle")
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,12 +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 { addChatBarButton, ChatBarButton, removeChatBarButton } from "@api/ChatButtons";
|
||||||
import { ApplicationCommandInputType, ApplicationCommandOptionType, findOption, sendBotMessage } from "@api/Commands";
|
import { ApplicationCommandInputType, ApplicationCommandOptionType, findOption, sendBotMessage } from "@api/Commands";
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { Button, ButtonLooks, ButtonWrapperClasses, FluxDispatcher, React, Tooltip } from "@webpack/common";
|
import { FluxDispatcher, React } from "@webpack/common";
|
||||||
|
|
||||||
const settings = definePluginSettings({
|
const settings = definePluginSettings({
|
||||||
showIcon: {
|
showIcon: {
|
||||||
|
@ -37,45 +37,35 @@ const settings = definePluginSettings({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function SilentTypingToggle(chatBoxProps: {
|
const SilentTypingToggle: ChatBarButton = (_, isMainChat) => {
|
||||||
type: {
|
const { isEnabled, showIcon } = settings.use(["isEnabled", "showIcon"]);
|
||||||
analyticsName: string;
|
|
||||||
};
|
|
||||||
}) {
|
|
||||||
const { isEnabled } = settings.use(["isEnabled"]);
|
|
||||||
const toggle = () => settings.store.isEnabled = !settings.store.isEnabled;
|
const toggle = () => settings.store.isEnabled = !settings.store.isEnabled;
|
||||||
|
|
||||||
if (chatBoxProps.type.analyticsName !== "normal") return null;
|
if (!isMainChat || !showIcon) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip text={isEnabled ? "Disable Silent Typing" : "Enable Silent Typing"}>
|
<ChatBarButton
|
||||||
{(tooltipProps: any) => (
|
tooltip={isEnabled ? "Disable Silent Typing" : "Enable Silent Typing"}
|
||||||
<div style={{ display: "flex" }}>
|
|
||||||
<Button
|
|
||||||
{...tooltipProps}
|
|
||||||
onClick={toggle}
|
onClick={toggle}
|
||||||
size=""
|
buttonProps={{
|
||||||
look={ButtonLooks.BLANK}
|
style: { padding: "0 6px" }
|
||||||
innerClassName={ButtonWrapperClasses.button}
|
}}
|
||||||
style={{ padding: "0 6px" }}
|
|
||||||
>
|
>
|
||||||
<div className={ButtonWrapperClasses.buttonWrapper}>
|
|
||||||
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512">
|
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512">
|
||||||
<path fill="currentColor" d="M528 448H48c-26.51 0-48-21.49-48-48V112c0-26.51 21.49-48 48-48h480c26.51 0 48 21.49 48 48v288c0 26.51-21.49 48-48 48zM128 180v-40c0-6.627-5.373-12-12-12H76c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm-336 96v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm-336 96v-40c0-6.627-5.373-12-12-12H76c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm288 0v-40c0-6.627-5.373-12-12-12H172c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h232c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12z" />
|
<path fill="currentColor" d="M528 448H48c-26.51 0-48-21.49-48-48V112c0-26.51 21.49-48 48-48h480c26.51 0 48 21.49 48 48v288c0 26.51-21.49 48-48 48zM128 180v-40c0-6.627-5.373-12-12-12H76c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm-336 96v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm-336 96v-40c0-6.627-5.373-12-12-12H76c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm288 0v-40c0-6.627-5.373-12-12-12H172c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h232c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12z" />
|
||||||
{isEnabled && <path d="M13 432L590 48" stroke="var(--red-500)" stroke-width="72" stroke-linecap="round" />}
|
{isEnabled && <path d="M13 432L590 48" stroke="var(--red-500)" stroke-width="72" stroke-linecap="round" />}
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</ChatBarButton>
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Tooltip>
|
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "SilentTyping",
|
name: "SilentTyping",
|
||||||
authors: [Devs.Ven, Devs.Rini],
|
authors: [Devs.Ven, Devs.Rini],
|
||||||
description: "Hide that you are typing",
|
description: "Hide that you are typing",
|
||||||
|
dependencies: ["CommandsAPI", "ChatInputButtonAPI"],
|
||||||
|
settings,
|
||||||
|
|
||||||
patches: [
|
patches: [
|
||||||
{
|
{
|
||||||
find: '.dispatch({type:"TYPING_START_LOCAL"',
|
find: '.dispatch({type:"TYPING_START_LOCAL"',
|
||||||
|
@ -84,17 +74,8 @@ export default definePlugin({
|
||||||
replace: "startTyping:$self.startTyping,stop"
|
replace: "startTyping:$self.startTyping,stop"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
find: "ChannelTextAreaButtons",
|
|
||||||
predicate: () => settings.store.showIcon,
|
|
||||||
replacement: {
|
|
||||||
match: /(\i)\.push.{1,30}disabled:(\i),.{1,20}\},"gift"\)\)/,
|
|
||||||
replace: "$&,(()=>{try{$2||$1.push($self.chatBarIcon(arguments[0]))}catch{}})()",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
dependencies: ["CommandsAPI"],
|
|
||||||
settings,
|
|
||||||
commands: [{
|
commands: [{
|
||||||
name: "silenttype",
|
name: "silenttype",
|
||||||
description: "Toggle whether you're hiding that you're typing or not.",
|
description: "Toggle whether you're hiding that you're typing or not.",
|
||||||
|
@ -120,5 +101,6 @@ export default definePlugin({
|
||||||
FluxDispatcher.dispatch({ type: "TYPING_START_LOCAL", channelId });
|
FluxDispatcher.dispatch({ type: "TYPING_START_LOCAL", channelId });
|
||||||
},
|
},
|
||||||
|
|
||||||
chatBarIcon: ErrorBoundary.wrap(SilentTypingToggle, { noop: true }),
|
start: () => addChatBarButton("SilentTyping", SilentTypingToggle),
|
||||||
|
stop: () => removeChatBarButton("SilentTyping"),
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { ChatBarButton } from "@api/ChatButtons";
|
||||||
import { classes } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import { openModal } from "@utils/modal";
|
import { openModal } from "@utils/modal";
|
||||||
import { Button, ButtonLooks, ButtonWrapperClasses, Tooltip } from "@webpack/common";
|
|
||||||
|
|
||||||
import { settings } from "./settings";
|
import { settings } from "./settings";
|
||||||
import { TranslateModal } from "./TranslateModal";
|
import { TranslateModal } from "./TranslateModal";
|
||||||
|
@ -37,26 +37,16 @@ export function TranslateIcon({ height = 24, width = 24, className }: { height?:
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function TranslateChatBarIcon({ slateProps }: { slateProps: { type: { analyticsName: string; }; }; }) {
|
export const TranslateChatBarIcon: ChatBarButton = (props, isMainChat) => {
|
||||||
const { autoTranslate } = settings.use(["autoTranslate"]);
|
const { autoTranslate } = settings.use(["autoTranslate"]);
|
||||||
|
|
||||||
if (slateProps.type.analyticsName !== "normal")
|
if (!isMainChat) return null;
|
||||||
return null;
|
|
||||||
|
|
||||||
const toggle = () => settings.store.autoTranslate = !autoTranslate;
|
const toggle = () => settings.store.autoTranslate = !autoTranslate;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip text="Open Translate Modal">
|
<ChatBarButton
|
||||||
{({ onMouseEnter, onMouseLeave }) => (
|
tooltip="Open Translate Modal"
|
||||||
<div style={{ display: "flex" }}>
|
|
||||||
<Button
|
|
||||||
aria-haspopup="dialog"
|
|
||||||
aria-label="Open Translate Modal"
|
|
||||||
size=""
|
|
||||||
look={ButtonLooks.BLANK}
|
|
||||||
onMouseEnter={onMouseEnter}
|
|
||||||
onMouseLeave={onMouseLeave}
|
|
||||||
innerClassName={ButtonWrapperClasses.button}
|
|
||||||
onClick={e => {
|
onClick={e => {
|
||||||
if (e.shiftKey) return toggle();
|
if (e.shiftKey) return toggle();
|
||||||
|
|
||||||
|
@ -65,14 +55,12 @@ export function TranslateChatBarIcon({ slateProps }: { slateProps: { type: { ana
|
||||||
));
|
));
|
||||||
}}
|
}}
|
||||||
onContextMenu={() => toggle()}
|
onContextMenu={() => toggle()}
|
||||||
style={{ padding: "0 4px" }}
|
buttonProps={{
|
||||||
|
"aria-haspopup": "dialog",
|
||||||
|
style: { padding: "0 4px" }
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div className={ButtonWrapperClasses.buttonWrapper}>
|
|
||||||
<TranslateIcon className={cl({ "auto-translate": autoTranslate })} />
|
<TranslateIcon className={cl({ "auto-translate": autoTranslate })} />
|
||||||
</div>
|
</ChatBarButton>
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Tooltip>
|
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
|
@ -18,11 +18,11 @@
|
||||||
|
|
||||||
import "./styles.css";
|
import "./styles.css";
|
||||||
|
|
||||||
|
import { addChatBarButton, removeChatBarButton } from "@api/ChatButtons";
|
||||||
import { addContextMenuPatch, findGroupChildrenByChildId, NavContextMenuPatchCallback, removeContextMenuPatch } from "@api/ContextMenu";
|
import { addContextMenuPatch, findGroupChildrenByChildId, NavContextMenuPatchCallback, removeContextMenuPatch } from "@api/ContextMenu";
|
||||||
import { addAccessory, removeAccessory } from "@api/MessageAccessories";
|
import { addAccessory, removeAccessory } from "@api/MessageAccessories";
|
||||||
import { addPreSendListener, removePreSendListener } from "@api/MessageEvents";
|
import { addPreSendListener, removePreSendListener } from "@api/MessageEvents";
|
||||||
import { addButton, removeButton } from "@api/MessagePopover";
|
import { addButton, removeButton } from "@api/MessagePopover";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { ChannelStore, Menu } from "@webpack/common";
|
import { ChannelStore, Menu } from "@webpack/common";
|
||||||
|
@ -55,25 +55,16 @@ export default definePlugin({
|
||||||
name: "Translate",
|
name: "Translate",
|
||||||
description: "Translate messages with Google Translate",
|
description: "Translate messages with Google Translate",
|
||||||
authors: [Devs.Ven],
|
authors: [Devs.Ven],
|
||||||
dependencies: ["MessageAccessoriesAPI", "MessagePopoverAPI", "MessageEventsAPI"],
|
dependencies: ["MessageAccessoriesAPI", "MessagePopoverAPI", "MessageEventsAPI", "ChatInputButtonAPI"],
|
||||||
settings,
|
settings,
|
||||||
// not used, just here in case some other plugin wants it or w/e
|
// not used, just here in case some other plugin wants it or w/e
|
||||||
translate,
|
translate,
|
||||||
|
|
||||||
patches: [
|
|
||||||
{
|
|
||||||
find: "ChannelTextAreaButtons",
|
|
||||||
replacement: {
|
|
||||||
match: /(\i)\.push.{1,30}disabled:(\i),.{1,20}\},"gift"\)\)/,
|
|
||||||
replace: "$&,(()=>{try{$2||$1.push($self.chatBarIcon(arguments[0]))}catch{}})()",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
addAccessory("vc-translation", props => <TranslationAccessory message={props.message} />);
|
addAccessory("vc-translation", props => <TranslationAccessory message={props.message} />);
|
||||||
|
|
||||||
addContextMenuPatch("message", messageCtxPatch);
|
addContextMenuPatch("message", messageCtxPatch);
|
||||||
|
addChatBarButton("vc-translate", TranslateChatBarIcon);
|
||||||
|
|
||||||
addButton("vc-translate", message => {
|
addButton("vc-translate", message => {
|
||||||
if (!message.content) return null;
|
if (!message.content) return null;
|
||||||
|
@ -101,13 +92,8 @@ export default definePlugin({
|
||||||
stop() {
|
stop() {
|
||||||
removePreSendListener(this.preSend);
|
removePreSendListener(this.preSend);
|
||||||
removeContextMenuPatch("message", messageCtxPatch);
|
removeContextMenuPatch("message", messageCtxPatch);
|
||||||
|
removeChatBarButton("vc-translate");
|
||||||
removeButton("vc-translate");
|
removeButton("vc-translate");
|
||||||
removeAccessory("vc-translation");
|
removeAccessory("vc-translation");
|
||||||
},
|
},
|
||||||
|
|
||||||
chatBarIcon: (slateProps: any) => (
|
|
||||||
<ErrorBoundary noop>
|
|
||||||
<TranslateChatBarIcon slateProps={slateProps} />
|
|
||||||
</ErrorBoundary>
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue