2023-01-14 14:47:12 -03:00
/ *
* 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/>.
* /
2025-01-23 02:48:44 +01:00
import { ChatBarButton , ChatBarButtonFactory } from "@api/ChatButtons" ;
2023-01-14 14:47:12 -03:00
import { ApplicationCommandInputType , ApplicationCommandOptionType , findOption , sendBotMessage } from "@api/Commands" ;
2024-05-11 23:49:00 +03:00
import { findGroupChildrenByChildId , NavContextMenuPatchCallback } from "@api/ContextMenu" ;
2023-05-06 01:36:00 +02:00
import { definePluginSettings } from "@api/Settings" ;
2025-07-31 09:49:23 -07:00
import { openPluginModal } from "@components/index" ;
import { Devs , EquicordDevs } from "@utils/constants" ;
2023-01-14 14:47:12 -03:00
import definePlugin , { OptionType } from "@utils/types" ;
2025-07-31 09:49:23 -07:00
import { Channel } from "@vencord/discord-types" ;
import { ChannelStore , FluxDispatcher , Menu , React } from "@webpack/common" ;
2023-01-14 14:47:12 -03:00
const settings = definePluginSettings ( {
2025-08-22 12:44:16 -07:00
enabledGlobally : {
2023-01-14 14:47:12 -03:00
type : OptionType . BOOLEAN ,
2025-07-31 09:49:23 -07:00
description : "Toggle functionality of your own typing indicator globally." ,
2023-01-14 14:47:12 -03:00
default : true ,
2024-09-01 20:38:00 -04:00
} ,
2025-07-31 09:49:23 -07:00
hideChatBoxTypingIndicators : {
2024-09-01 20:38:00 -04:00
type : OptionType . BOOLEAN ,
2025-07-31 09:49:23 -07:00
description : "Hide other users' typing indicators from above the chat bar." ,
2024-09-01 20:38:00 -04:00
default : false ,
} ,
2025-07-31 09:49:23 -07:00
hideMembersListTypingIndicators : {
2024-09-01 20:38:00 -04:00
type : OptionType . BOOLEAN ,
2025-07-31 09:49:23 -07:00
description : "Hide other users' typing indicators from the members list." ,
2024-09-01 20:38:00 -04:00
default : false ,
} ,
2025-07-31 09:49:23 -07:00
chatIcon : {
2024-09-01 20:38:00 -04:00
type : OptionType . BOOLEAN ,
2025-07-31 09:49:23 -07:00
description : "Show an icon in the chat bar for modifying the plugin on the go." ,
default : true ,
} ,
chatIconLeftClickAction : {
type : OptionType . SELECT ,
description : "What to do when left clicking the chat icon." ,
options : [
2025-08-22 12:44:16 -07:00
{ label : "Toggle Typing Globally" , value : "global" } ,
2025-07-31 09:49:23 -07:00
{ label : "Toggle Typing in Channel" , value : "channel" , default : true } ,
{ label : "Toggle Typing in Guild" , value : "guild" } ,
{ label : "Open Plugin Settings" , value : "settings" }
]
} ,
chatIconMiddleClickAction : {
type : OptionType . SELECT ,
description : "What to do when middle clicking the chat icon." ,
options : [
2025-08-22 12:44:16 -07:00
{ label : "Toggle Typing Globally" , value : "global" } ,
2025-07-31 09:49:23 -07:00
{ label : "Toggle Typing in Channel" , value : "channel" } ,
{ label : "Toggle Typing in Guild" , value : "guild" } ,
{ label : "Open Plugin Settings" , value : "settings" , default : true }
]
2024-09-01 20:38:00 -04:00
} ,
2025-07-31 09:49:23 -07:00
chatIconRightClickAction : {
type : OptionType . SELECT ,
description : "What to do when right clicking the chat icon." ,
options : [
2025-08-22 12:44:16 -07:00
{ label : "Toggle Typing Globally" , value : "global" , default : true } ,
2025-07-31 09:49:23 -07:00
{ label : "Toggle Typing in Channel" , value : "channel" } ,
{ label : "Toggle Typing in Guild" , value : "guild" } ,
{ label : "Open Plugin Settings" , value : "settings" }
]
} ,
chatContextMenu : {
2024-09-01 20:38:00 -04:00
type : OptionType . BOOLEAN ,
2025-07-31 09:49:23 -07:00
description : "Show a dropdown in the chat context menu to modify plugin settings on the go." ,
default : true
2024-09-01 20:38:00 -04:00
} ,
2025-07-31 09:49:23 -07:00
defaultHidden : {
2024-09-01 20:38:00 -04:00
type : OptionType . BOOLEAN ,
2025-07-31 09:49:23 -07:00
description : "If enabled, the plugin will hide your typing from others in any DMs/channels/guilds not listed in \"Disabled Locations\" below. If disabled, the plugin will show your typing to others for any DMs/channels/guilds not listed in \"Enabled Locations\" below." ,
default : true ,
} ,
enabledLocations : {
type : OptionType . STRING ,
description : "Enable functionality for these IDs. Accepts a comma separated list of DM IDs, channel IDs, and guild IDs. Only used if \"Default Hidden\" is disabled." ,
default : "" ,
} ,
disabledLocations : {
type : OptionType . STRING ,
description : "Disable functionality for these IDs. Accepts a comma separated list of DM IDs, channel IDs, and guild IDs. Only used if \"Default Hidden\" is enabled." ,
default : "" ,
} ,
2023-01-14 14:47:12 -03:00
} ) ;
2025-07-31 09:49:23 -07:00
function toggleGlobal ( ) : void {
2025-08-22 12:44:16 -07:00
settings . store . enabledGlobally = ! settings . store . enabledGlobally ;
2025-07-31 09:49:23 -07:00
}
function toggleLocation ( locationId : string , effectiveList : string [ ] , defaultHidden : boolean ) : void {
if ( effectiveList . includes ( locationId ) ) {
effectiveList . splice ( effectiveList . indexOf ( locationId ) , 1 ) ;
} else {
effectiveList . push ( locationId ) ;
}
if ( defaultHidden ) {
settings . store . disabledLocations = effectiveList . join ( ", " ) ;
} else {
settings . store . enabledLocations = effectiveList . join ( ", " ) ;
}
}
const SilentTypingChatToggle : ChatBarButtonFactory = ( { channel , type } ) = > {
const {
2025-08-22 12:44:16 -07:00
enabledGlobally ,
2025-07-31 09:49:23 -07:00
chatIcon ,
2025-09-26 01:40:28 -04:00
defaultHidden ,
enabledLocations ,
disabledLocations ,
chatIconLeftClickAction ,
chatIconMiddleClickAction ,
chatIconRightClickAction ,
2025-07-31 09:49:23 -07:00
} = settings . use ( [
2025-08-22 12:44:16 -07:00
"enabledGlobally" ,
2025-07-31 09:49:23 -07:00
"chatIcon" ,
2025-09-26 01:40:28 -04:00
"defaultHidden" ,
"enabledLocations" ,
"disabledLocations" ,
"chatIconLeftClickAction" ,
"chatIconMiddleClickAction" ,
"chatIconRightClickAction" ,
2025-07-31 09:49:23 -07:00
] ) ;
2023-01-14 14:47:12 -03:00
2025-07-31 09:49:23 -07:00
const validChat = [ "normal" , "sidebar" ] . some ( x = > type . analyticsName === x ) ;
if ( ! validChat || ! chatIcon ) return null ;
const effectiveList = getEffectiveList ( ) ;
2025-08-22 12:44:16 -07:00
const enabledLocally = enabledGlobally && checkEnabled ( channel ) ;
2025-07-31 09:49:23 -07:00
const location = channel . guild_id && effectiveList . includes ( channel . guild_id ) ? "Guild" : effectiveList . includes ( channel . id ) ? "Channel" : "Global" ;
2025-08-22 12:44:16 -07:00
const tooltip = enabledGlobally ? (
2025-07-31 09:49:23 -07:00
enabledLocally ? ` Typing Hidden ( ${ location } ) ` : ` Typing Visible ( ${ location } ) `
) : "Typing Visible (Global)" ;
function performAction ( action : string ) : void {
switch ( action ) {
case "global" :
toggleGlobal ( ) ;
break ;
case "channel" :
toggleLocation ( channel . id , effectiveList , defaultHidden ) ;
break ;
case "guild" :
channel . guild_id ? toggleLocation ( channel . guild_id , effectiveList , defaultHidden ) : null ;
break ;
case "settings" :
openPluginModal ( Vencord . Plugins . plugins . SilentTyping ) ;
break ;
}
}
2023-03-28 18:56:12 +02:00
2023-01-14 14:47:12 -03:00
return (
2024-02-06 16:29:47 +01:00
< ChatBarButton
2025-07-31 09:49:23 -07:00
tooltip = { tooltip }
onClick = { e = > {
if ( e . button === 0 ) {
performAction ( settings . store . chatIconLeftClickAction ) ;
}
} }
onAuxClick = { e = > {
if ( e . button === 1 ) {
performAction ( settings . store . chatIconMiddleClickAction ) ;
}
} }
onContextMenu = { e = > {
if ( e . button === 2 ) {
performAction ( settings . store . chatIconRightClickAction ) ;
}
} } >
2025-04-04 18:32:15 -04:00
< svg width = "20" height = "20" xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 24 24" style = { { scale : "1.2" } } >
2024-11-24 19:35:12 -05:00
< path fill = "currentColor" mask = "url(#silent-typing-msg-mask)" d = "M18.333 15.556H1.667a1.667 1.667 0 0 1 -1.667 -1.667v-10a1.667 1.667 0 0 1 1.667 -1.667h16.667a1.667 1.667 0 0 1 1.667 1.667v10a1.667 1.667 0 0 1 -1.667 1.667M4.444 6.25V4.861a0.417 0.417 0 0 0 -0.417 -0.417H2.639a0.417 0.417 0 0 0 -0.417 0.417V6.25a0.417 0.417 0 0 0 0.417 0.417h1.389a0.417 0.417 0 0 0 0.417 -0.417m3.333 0V4.861a0.417 0.417 0 0 0 -0.417 -0.417H5.973a0.417 0.417 0 0 0 -0.417 0.417V6.25a0.417 0.417 0 0 0 0.417 0.417h1.389a0.417 0.417 0 0 0 0.417 -0.417m3.333 0V4.861a0.417 0.417 0 0 0 -0.417 -0.417h-1.389a0.417 0.417 0 0 0 -0.417 0.417V6.25a0.417 0.417 0 0 0 0.417 0.417h1.389a0.417 0.417 0 0 0 0.417 -0.417m3.333 0V4.861a0.417 0.417 0 0 0 -0.417 -0.417h-1.389a0.417 0.417 0 0 0 -0.417 0.417V6.25a0.417 0.417 0 0 0 0.417 0.417h1.389a0.417 0.417 0 0 0 0.417 -0.417m3.333 0V4.861a0.417 0.417 0 0 0 -0.417 -0.417h-1.389a0.417 0.417 0 0 0 -0.417 0.417V6.25a0.417 0.417 0 0 0 0.417 0.417h1.389a0.417 0.417 0 0 0 0.417 -0.417m-11.667 3.333V8.194a0.417 0.417 0 0 0 -0.417 -0.417H4.306a0.417 0.417 0 0 0 -0.417 0.417V9.583a0.417 0.417 0 0 0 0.417 0.417h1.389a0.417 0.417 0 0 0 0.417 -0.417m3.333 0V8.194a0.417 0.417 0 0 0 -0.417 -0.417H7.639a0.417 0.417 0 0 0 -0.417 0.417V9.583a0.417 0.417 0 0 0 0.417 0.417h1.389a0.417 0.417 0 0 0 0.417 -0.417m3.333 0V8.194a0.417 0.417 0 0 0 -0.417 -0.417h-1.389a0.417 0.417 0 0 0 -0.417 0.417V9.583a0.417 0.417 0 0 0 0.417 0.417h1.389a0.417 0.417 0 0 0 0.417 -0.417m3.333 0V8.194a0.417 0.417 0 0 0 -0.417 -0.417h-1.389a0.417 0.417 0 0 0 -0.417 0.417V9.583a0.417 0.417 0 0 0 0.417 0.417h1.389a0.417 0.417 0 0 0 0.417 -0.417m-11.667 3.333v-1.389a0.417 0.417 0 0 0 -0.417 -0.417H2.639a0.417 0.417 0 0 0 -0.417 0.417V12.917a0.417 0.417 0 0 0 0.417 0.417h1.389a0.417 0.417 0 0 0 0.417 -0.417m10 0v-1.389a0.417 0.417 0 0 0 -0.417 -0.417H5.973a0.417 0.417 0 0 0 -0.417 0.417V12.917a0.417 0.417 0 0 0 0.417 0.417h8.056a0.417 0.417 0 0 0 0.417 -0.417m3.333 0v-1.389a0.417 0.417 0 0 0 -0.417 -0.417h-1.389a0.417 0.417 0 0 0 -0.417 0.417V12.917a0.417 0.417 0 0 0 0.417 0.417h1.389a0.417 0.417 0 0 0 0.417 -0.417" transform = "translate(2, 3)" / >
2025-07-31 09:49:23 -07:00
{ ( enabledLocally ) && (
2024-11-24 19:35:12 -05:00
< >
< mask id = "silent-typing-msg-mask" >
< path fill = "#fff" d = "M0 0h24v24H0Z" > < / path >
< path stroke = "#000" strokeWidth = "5.99068" d = "M0 24 24 0" transform = "translate(-2, -3)" > < / path >
< / mask >
< path fill = "var(--status-danger)" d = "m21.178 1.70703 1.414 1.414L4.12103 21.593l-1.414-1.415L21.178 1.70703Z" / >
< / >
) }
2024-02-06 16:29:47 +01:00
< / svg >
< / ChatBarButton >
2023-01-14 14:47:12 -03:00
) ;
2024-02-06 16:29:47 +01:00
} ;
2023-01-14 14:47:12 -03:00
2025-07-31 09:49:23 -07:00
function getEffectiveList ( ) : string [ ] {
if ( settings . store . defaultHidden ) {
if ( ! settings . store . disabledLocations ) {
settings . store . disabledLocations = "" ;
return [ ] ;
} else {
return settings . store . disabledLocations . split ( "," ) . map ( x = > x . trim ( ) ) . filter ( Boolean ) ;
}
} else {
if ( ! settings . store . enabledLocations ) {
settings . store . enabledLocations = "" ;
return [ ] ;
} else {
return settings . store . enabledLocations . split ( "," ) . map ( x = > x . trim ( ) ) . filter ( Boolean ) ;
}
}
}
function checkEnabled ( channel : string | Channel ) : boolean {
2025-08-22 12:44:16 -07:00
if ( ! settings . store . enabledGlobally ) return false ;
2025-07-31 09:49:23 -07:00
const channelId = typeof channel === "string" ? channel : channel.id ;
const guildId = typeof channel === "string" ? ChannelStore . getChannel ( channelId ) ? . guild_id : channel.guild_id ;
const effectiveChannels = getEffectiveList ( ) ;
if ( settings . store . defaultHidden ) {
return ! effectiveChannels . includes ( guildId ) && ! effectiveChannels . includes ( channelId ) ;
} else {
return effectiveChannels . includes ( guildId ) || effectiveChannels . includes ( channelId ) ;
}
}
2024-05-11 23:49:00 +03:00
const ChatBarContextCheckbox : NavContextMenuPatchCallback = children = > {
2025-07-31 09:49:23 -07:00
const {
chatIcon ,
chatContextMenu ,
2025-08-22 12:44:16 -07:00
enabledGlobally ,
2025-09-26 01:40:28 -04:00
defaultHidden ,
hideChatBoxTypingIndicators ,
hideMembersListTypingIndicators
2025-07-31 09:49:23 -07:00
} = settings . use ( [
"chatIcon" ,
"chatContextMenu" ,
2025-08-22 12:44:16 -07:00
"enabledGlobally" ,
2025-09-26 01:40:28 -04:00
"defaultHidden" ,
"hideChatBoxTypingIndicators" ,
"hideMembersListTypingIndicators"
2025-07-31 09:49:23 -07:00
] ) ;
if ( ! chatContextMenu ) return ;
2024-05-11 23:49:00 +03:00
2025-07-31 09:49:23 -07:00
const group = findGroupChildrenByChildId ( "submit-button" , children as ( React . ReactElement | null | undefined ) [ ] ) ;
2024-05-11 23:49:00 +03:00
if ( ! group ) return ;
const idx = group . findIndex ( c = > c ? . props ? . id === "submit-button" ) ;
2025-07-31 09:49:23 -07:00
group . splice ( idx >= 0 ? idx : 0 , 0 ,
< Menu.MenuItem id = "vc-silent-typing" label = "Silent Typing" >
2025-08-22 12:44:16 -07:00
< Menu.MenuCheckboxItem id = "vc-silent-typing-enabled" label = "Enabled" checked = { enabledGlobally }
action = { ( ) = > settings . store . enabledGlobally = ! settings . store . enabledGlobally } / >
2025-07-31 09:49:23 -07:00
< Menu.MenuCheckboxItem id = "vc-silent-typing-chat-bar-indicators" label = "Chat Bar Indicators" checked = { settings . store . hideChatBoxTypingIndicators }
action = { ( ) = > settings . store . hideChatBoxTypingIndicators = ! settings . store . hideChatBoxTypingIndicators } / >
< Menu.MenuCheckboxItem id = "vc-silent-typing-members-list-indicators" label = "Members List Indicators" checked = { settings . store . hideMembersListTypingIndicators }
action = { ( ) = > settings . store . hideMembersListTypingIndicators = ! settings . store . hideMembersListTypingIndicators } / >
< Menu.MenuCheckboxItem id = "vc-silent-typing-chat-icon" label = "Chat Icon" checked = { chatIcon }
action = { ( ) = > settings . store . chatIcon = ! settings . store . chatIcon } / >
< Menu.MenuCheckboxItem id = "vc-silent-typing-default" label = "Default Hidden" checked = { defaultHidden }
action = { ( ) = > settings . store . defaultHidden = ! settings . store . defaultHidden } / >
< / Menu.MenuItem >
2024-05-11 23:49:00 +03:00
) ;
} ;
2025-07-31 09:49:23 -07:00
function shouldHideChatBarTypingIndicators ( ) : boolean {
const { hideChatBoxTypingIndicators } = settings . use ( [ "hideChatBoxTypingIndicators" ] ) ;
return hideChatBoxTypingIndicators ;
}
function shouldHideMembersListTypingIndicators ( ) : boolean {
const { hideMembersListTypingIndicators } = settings . use ( [ "hideMembersListTypingIndicators" ] ) ;
return hideMembersListTypingIndicators ;
}
2023-01-14 14:47:12 -03:00
export default definePlugin ( {
name : "SilentTyping" ,
2025-07-31 09:49:23 -07:00
authors : [ Devs . Ven , Devs . Rini , Devs . ImBanana , EquicordDevs . Etorix ] ,
description : "Hide your typing indicator from chat." ,
dependencies : [ "ChatInputButtonAPI" ] ,
2024-02-06 16:29:47 +01:00
settings ,
2025-01-23 02:48:44 +01:00
2025-07-31 09:49:23 -07:00
shouldHideChatBarTypingIndicators ,
shouldHideMembersListTypingIndicators ,
2024-05-11 23:49:00 +03:00
contextMenus : {
"textarea-context" : ChatBarContextCheckbox
} ,
2025-01-23 02:48:44 +01:00
2023-01-14 14:47:12 -03:00
patches : [
{
2023-10-25 12:34:23 -03:00
find : '.dispatch({type:"TYPING_START_LOCAL"' ,
2023-01-14 14:47:12 -03:00
replacement : {
2023-10-25 12:34:23 -03:00
match : /startTyping\(\i\){.+?},stop/ ,
2023-01-14 14:47:12 -03:00
replace : "startTyping:$self.startTyping,stop"
}
} ,
2024-09-01 20:38:00 -04:00
{
2025-07-31 09:49:23 -07:00
find : "activityInviteEducationActivity:" ,
2025-08-07 00:32:13 -07:00
group : true ,
replacement : [
{
match : /(let{activityInviteEducationActivity)/ ,
replace : "const silentTypingShouldHideChatBarTypingIndicators=$self.shouldHideChatBarTypingIndicators();$1"
} ,
{
match : /(typingDots,ref:\i,children:)(\[.{0,340}?}\)\])/ ,
replace : "$1silentTypingShouldHideChatBarTypingIndicators?[]:$2"
}
]
2024-09-01 20:38:00 -04:00
} ,
{
2025-07-31 09:49:23 -07:00
find : ",{avatarCutoutX" ,
2024-09-01 20:38:00 -04:00
replacement : {
2025-07-31 09:49:23 -07:00
match : /isTyping:(\i)=!1(,typingIndicatorRef:\i,isSpeaking:)/ ,
replace : "silentTypingIsTyping:$1=$self.shouldHideMembersListTypingIndicators()?false:(arguments[0].isTyping??false)$2"
}
} ,
2023-01-14 14:47:12 -03:00
] ,
2024-02-06 16:29:47 +01:00
2023-01-14 14:47:12 -03:00
commands : [ {
2025-07-31 09:49:23 -07:00
name : "silent-typing" ,
description : "Hide your typing indicator from chat." ,
2023-01-14 14:47:12 -03:00
inputType : ApplicationCommandInputType.BUILT_IN ,
2025-07-31 09:49:23 -07:00
2023-01-14 14:47:12 -03:00
options : [
{
2025-07-31 09:49:23 -07:00
name : "toggle" ,
description : "Toggle functionality globally, for the channel, or for the guild." ,
required : false ,
type : ApplicationCommandOptionType . STRING ,
choices : [
{ name : "Global" , label : "Global" , value : "global" } ,
{ name : "Channel" , label : "Channel" , value : "channel" } ,
{ name : "Guild" , label : "Guild" , value : "guild" } ,
]
} ,
{
name : "chat-bar-indicators" ,
description : "Hide other users' typing indicators from above the chat bar." ,
required : false ,
type : ApplicationCommandOptionType . BOOLEAN ,
} ,
{
name : "members-list-indicators" ,
description : "Hide other users' typing indicators from the members list." ,
2023-01-14 14:47:12 -03:00
required : false ,
type : ApplicationCommandOptionType . BOOLEAN ,
} ,
2025-07-31 09:49:23 -07:00
{
name : "chat-icon" ,
description : "Show an icon in the chat bar for toggling the plugin on the go." ,
required : false ,
type : ApplicationCommandOptionType . BOOLEAN ,
} ,
{
name : "chat-context-menu" ,
description : "Show a dropdown in the chat context menu to toggle plugin settings on the go." ,
required : false ,
type : ApplicationCommandOptionType . BOOLEAN ,
} ,
{
name : "default-hidden" ,
description : "Whether to hide typing in DMs/channels/guilds by default or not." ,
required : false ,
type : ApplicationCommandOptionType . BOOLEAN ,
}
2023-01-14 14:47:12 -03:00
] ,
2025-07-31 09:49:23 -07:00
2023-01-14 14:47:12 -03:00
execute : async ( args , ctx ) = > {
2025-07-31 09:49:23 -07:00
let updated = false ;
const location = findOption ( args , "toggle" ) ;
if ( typeof location === "string" ) {
updated = true ;
if ( location === "global" ) {
toggleGlobal ( ) ;
} else {
const locationId = location === "guild" ? ctx.channel.guild_id : ctx.channel.id ;
toggleLocation ( locationId , getEffectiveList ( ) , settings . store . defaultHidden ) ;
}
}
const updateChatIcon = findOption ( args , "chat-icon" ) ;
if ( typeof updateChatIcon === "boolean" ) {
updated = true ;
settings . store . chatIcon = ! ! updateChatIcon ;
}
const updateChatContextMenu = findOption ( args , "chat-context-menu" ) ;
if ( typeof updateChatContextMenu === "boolean" ) {
updated = true ;
settings . store . chatContextMenu = ! ! updateChatContextMenu ;
}
const updateDefaultHidden = findOption ( args , "default-hidden" ) ;
if ( typeof updateDefaultHidden === "boolean" ) {
updated = true ;
settings . store . defaultHidden = ! ! updateDefaultHidden ;
}
2023-01-14 14:47:12 -03:00
sendBotMessage ( ctx . channel . id , {
2025-07-31 09:49:23 -07:00
content : updated ? "Silent typing settings updated." : "No changes made to silent typing settings." ,
2023-01-14 14:47:12 -03:00
} ) ;
} ,
} ] ,
async startTyping ( channelId : string ) {
2025-07-31 09:49:23 -07:00
if ( checkEnabled ( channelId ) ) return ;
2023-01-14 14:47:12 -03:00
FluxDispatcher . dispatch ( { type : "TYPING_START_LOCAL" , channelId } ) ;
} ,
2025-07-31 09:49:23 -07:00
renderChatBarButton : SilentTypingChatToggle ,
2023-01-14 14:47:12 -03:00
} ) ;