Disable Discord chat input

Avoid accidentally typing in chat

  1. // ==UserScript==
  2. // @name Disable Discord chat input
  3. // @namespace https://github.com/Dragosarus/Userscripts/
  4. // @version 4.1
  5. // @description Avoid accidentally typing in chat
  6. // @author Dragosarus
  7. // @match http://discord.com/*
  8. // @match https://discord.com/*
  9. // @grant GM_registerMenuCommand
  10. // @grant GM_unregisterMenuCommand
  11. // @grant GM.setValue
  12. // @grant GM.getValue
  13. // @require http://code.jquery.com/jquery-latest.js
  14. // ==/UserScript==
  15.  
  16. // NOTE: Does not work with Greasemonkey as it neither supports GM_registerMenuCommand nor GM_unregisterMenuCommand.
  17. // Use Tampermonkey or Violentmonkey instead.
  18.  
  19. (function() {
  20. 'use strict';
  21. var persist = true; // Remember selected mode across page refreshes and browser reloads
  22.  
  23. // Modes (use menu to cycle between these):
  24. // "hover": Enable chat input only when the cursor is hovering over it
  25. // "strict": Disables chat input completely
  26. // "off": Keep chat input enabled.
  27. var modes = ["hover", "strict", "off"];
  28. var menuShortcut = 'm';
  29. var modeIndex;
  30. var menuId;
  31.  
  32. const channelObserver = new MutationObserver(channelObserverCallback);
  33. const serverObserver = new MutationObserver(serverObserverCallback);
  34. const options = {childList:true, attributes:true};
  35. init();
  36.  
  37. async function init() {
  38. // Will activate the mode of the next index (default: hover)
  39. const modeIndex_default = modes.length - 1;
  40.  
  41. // Load stored value if available and persist is set to true
  42. if (persist) {
  43. var storedMode = await GM.getValue("mode", "hover");
  44. modeIndex = modes.indexOf(storedMode);
  45. if (modeIndex != -1) {
  46. modeIndex = (modeIndex - 1) % modes.length;
  47. } else { // Mode does not exist
  48. modeIndex = modeIndex_default;
  49. }
  50. } else {
  51. modeIndex = modeIndex_default;
  52. }
  53. start();
  54. }
  55.  
  56. function start(){
  57. switchMode();
  58. addObserver(serverObserver,"div[class*='content-']");
  59. serverObserverCallback(); // Init
  60. }
  61.  
  62. function serverObserverCallback(mutationList, observer) { // When changing servers
  63. //console.log("server callback");
  64. addObserver(channelObserver,"div[class*='chat-']", disable);
  65. addHoverFunc();
  66. }
  67. function channelObserverCallback(mutationList, observer) { // When changing channels
  68. //console.log("channel callback");
  69. disable();
  70. addHoverFunc();
  71. }
  72.  
  73. function addObserver(observer, query, onSuccess = function(){}) {
  74. var q = $(query);
  75. if (!q.length) { setTimeout(function(){addObserver(observer, query, onSuccess)},100);}
  76. else {
  77. observer.observe(q[0], options);
  78. onSuccess();
  79. }
  80. }
  81.  
  82. function switchMode() {
  83. modeIndex = (modeIndex + 1) % modes.length;
  84. if (persist) {GM.setValue("mode",modes[modeIndex]);}
  85. GM_unregisterMenuCommand(menuId);
  86. menuId = GM_registerMenuCommand("Switch mode [current: " + modes[modeIndex] + "]", switchMode, menuShortcut);
  87. switch (modes[modeIndex]){
  88. case "hover":
  89. case "strict":
  90. disable();
  91. break;
  92. case "off":
  93. enable();
  94. break;
  95. default:
  96. console.error("Disable Discord chat input: Unimplemented mode.");
  97. break;
  98. }
  99. }
  100.  
  101. function disable() {
  102. if (modes[modeIndex] != "off") {
  103. //console.log("disabled!");
  104. var textareaQuery = $("div[class*='slateTextArea']");
  105. if (textareaQuery.length) {
  106. textareaQuery.attr("contenteditable","false");
  107. textareaQuery[0].style.removeProperty("-webkit-user-modify"); // Needed for Chrome
  108. textareaQuery.parent().parent()[0].style.setProperty("pointer-events","none"); // Disable mouse events
  109. } else {
  110. setTimeout(disable, 100);
  111. }
  112. }
  113. }
  114.  
  115. function enable() {
  116. var textareaQuery = $("div[class*='slateTextArea']");
  117. if (textareaQuery.length) {
  118. textareaQuery.attr("contenteditable","true");
  119. textareaQuery[0].style.setProperty("-webkit-user-modify", "read-write-plaintext-only");
  120. textareaQuery.parent().parent()[0].style.removeProperty("pointer-events");
  121. } else {
  122. setTimeout(enable, 100);
  123. }
  124. }
  125.  
  126. function addHoverFunc() {
  127. var textareaQuery = $("div[class*='scrollableContainer']");
  128. if (textareaQuery.length) {
  129. textareaQuery.hover(hoverEnter, hoverExit);
  130. } else {
  131. setTimeout(addHoverFunc, 100);
  132. }
  133. }
  134.  
  135. function hoverEnter() {
  136. if (modes[modeIndex] == "hover"){
  137. enable();
  138. }
  139. }
  140.  
  141. function hoverExit() {
  142. if (modes[modeIndex] == "hover"){
  143. disable();
  144. }
  145. }
  146.  
  147. })();
  148. /*eslint-env jquery*/ // stop eslint from showing "'$' is not defined" warnings