Twitch chat - align pseudos

Align the text in the twitch chat

  1. // ==UserScript==
  2. // @name Twitch chat - align pseudos
  3. // @version 0.2
  4. // @grant none
  5. // @include http://*.twitch.tv/*
  6. // @include https://*.twitch.tv/*
  7. // @exclude http://api.twitch.tv/*
  8. // @exclude https://api.twitch.tv/*
  9. // @namespace http://tampermonkey.net/
  10. // @description Align the text in the twitch chat
  11. // ==/UserScript==
  12.  
  13. var sizeChat = 0;
  14. var longestPseudo = 0;
  15.  
  16. const spacePx = 8;
  17. const maxWidth = 80;
  18.  
  19. // True: align pseudo on left
  20. // False: align pseudo on right
  21. const alignLeft = false;
  22.  
  23. // True: remove icons (mods, sub, bits)
  24. // False: keep icons
  25. const removeIcons = true;
  26.  
  27. const config = { attributes: true, childList: true, subtree: true };
  28.  
  29. var init = function () {
  30.  
  31. addGlobalStyle(".chat-line__message, message-block{ display:flex }");
  32. addGlobalStyle(".chat-line__username, .chat-line__dots, .message-block>*{ flex-shrink:0 }");
  33. addGlobalStyle(".chat-line__username {max-width:" + maxWidth + "px; white-space:nowrap; overflow:hidden}");
  34.  
  35. // document.getElementById('root').addEventListener('DOMSubtreeModified', function (e) {
  36. // if (e.target == document.querySelectorAll('[role="log"]')[0]) {
  37. // console.log('Dom modified');
  38. // let target = e.target;
  39. // let msg = target.lastChild;
  40.  
  41. // if (![...msg.classList].includes('chat-line__message'))
  42. // return;
  43.  
  44. // //remove the icons (mod, sub, bits, ...)
  45. // if (msg.children[0].classList.length == 0)
  46. // msg.children[0].remove();
  47.  
  48. // msg.children[1].classList.add("chat-line__dots");
  49.  
  50. // let elText = [...msg.children].splice(2);
  51.  
  52. // let span = document.createElement("span");
  53. // span.classList.add("message-block");
  54.  
  55. // elText.forEach(el => {
  56. // let clone = el.cloneNode(true);
  57. // clone = span.appendChild(clone);
  58.  
  59. // el.style.display = 'none';
  60. // });
  61. // msg.appendChild(span);
  62.  
  63. // elText.forEach((el, i) => {
  64. // el.addEventListener('DOMSubtreeModified', function (original) {
  65. // console.log('Dom modified (in msg)');
  66. // span.children[i].outerHTML = el.outerHTML;
  67. // span.children[i].style.display = '';
  68. // });
  69. // });
  70.  
  71. // if (alignLeft) {
  72. // let pseudo = msg.children[0].clientWidth;
  73. // let pixelToAdd = maxWidth - pseudo;
  74.  
  75. // msg.children[1].style.width = (pixelToAdd + spacePx) + 'px';
  76. // } else {
  77. // msg.children[0].style.width = maxWidth + 'px';
  78. // msg.children[0].style.textAlign = 'right';
  79. // msg.children[1].style.width = spacePx + 'px';
  80. // }
  81. // } else if (e.target == document.getElementsByClassName("chat-input")[0]) {
  82. // sizeChat = document.getElementsByClassName("chat-input")[0].children[0].clientWidth;
  83. // }
  84. // });
  85.  
  86.  
  87.  
  88. var initObserver = new MutationObserver(wait);
  89.  
  90. initObserver.observe(document.body, config);
  91.  
  92. //var observer = new MutationObserver(waitForNewMsg);
  93.  
  94. //observer.observe(document.querySelectorAll('[role="log"]')[0], config);
  95.  
  96. // Later, you can stop observing
  97. }
  98.  
  99. var addGlobalStyle = function (css) {
  100.  
  101. var head, style;
  102. head = document.getElementsByTagName('head')[0];
  103.  
  104. if (!head)
  105. return;
  106.  
  107. style = document.createElement('style');
  108. style.type = 'text/css';
  109. style.innerHTML = css;
  110. head.appendChild(style);
  111. }
  112.  
  113. var waitForNewMsg = function (mutationsList, obs) {
  114. for (let mutation of mutationsList) {
  115. if (mutation.type == 'childList') {
  116.  
  117. if (!mutation.addedNodes[0].classList.contains('chat-line__message'))
  118. return;
  119.  
  120. let msg = mutation.addedNodes[0];
  121.  
  122. //remove the icons (mod, sub, bits, ...)
  123. if (removeIcons && msg.children[0].classList.length == 0)
  124. msg.children[0].remove();
  125.  
  126. let elText = [...msg.children].splice(2);
  127.  
  128. let span = document.createElement("span");
  129. span.classList.add("message-block");
  130.  
  131. elText.forEach(el => {
  132. let clone = el.cloneNode(true);
  133. clone = span.appendChild(clone);
  134.  
  135. el.style.display = 'none';
  136. });
  137.  
  138. msg.appendChild(span);
  139.  
  140. elText.forEach((el, i) => {
  141. //TODO: depracated function
  142. el.addEventListener('DOMSubtreeModified', function (original) {
  143. console.log('Dom modified (in msg)');
  144. span.children[i].outerHTML = el.outerHTML;
  145. span.children[i].style.display = '';
  146. });
  147. });
  148.  
  149. if (alignLeft) {
  150. let pseudo = msg.children[0].clientWidth;
  151. let pixelToAdd = maxWidth - pseudo;
  152.  
  153. msg.children[1].style.width = (pixelToAdd + spacePx) + 'px';
  154. } else {
  155. msg.children[0].style.width = maxWidth + 'px';
  156. msg.children[0].style.textAlign = 'right';
  157. msg.children[1].style.width = spacePx + 'px';
  158. }
  159.  
  160. }
  161. else if (mutation.type == 'attributes') {
  162. }
  163. }
  164. };
  165.  
  166. var wait = function (mutationsList, obs) {
  167. for (var mutation of mutationsList) {
  168. if (mutation.target == document.querySelectorAll('[role="log"]')[0]) {
  169.  
  170. var observer = new MutationObserver(waitForNewMsg);
  171. observer.observe(mutation.target, config);
  172.  
  173. obs.disconnect();
  174. }
  175. }
  176. }
  177.  
  178. init();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址