Microsoft Teams - Toggle Sidebar + Expand Message Pane

Add toggle buttons to hide the Chat/Teams sidebar and also expand the message pane

目前为 2024-09-19 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Microsoft Teams - Toggle Sidebar + Expand Message Pane
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.2.0
  5. // @description Add toggle buttons to hide the Chat/Teams sidebar and also expand the message pane
  6. // @author D365Fixes
  7. // @license MIT
  8. // @match https://teams.microsoft.com/v2/*
  9. // @icon https://www.google.com/s2/favicons?sz=64&domain=teams.microsoft.com
  10. // @run-at document-start
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. "use strict";
  15.  
  16. const styles = `
  17. .hide-sub-nav div[data-tid="experience-layout"] {
  18. --sub-nav-width: 0rem !important;
  19. }
  20.  
  21. .hide-sub-nav div[data-tid="app-layout-area--sub-nav"] {
  22. opacity: 0;
  23. visibility: hidden;
  24. }
  25.  
  26. #chat-pane-list, #chat-pane-list, div[data-tid="message-pane-footer"], div[data-tid="simplified-formatting-toolbar"] {
  27. transition: max-width .25s ease-in-out;
  28. }
  29.  
  30. div[data-tid="simplified-formatting-toolbar"] {
  31. column-gap: normal;
  32. }
  33.  
  34. @media (min-width: 947px) {
  35. .expand-msg-pane div[data-tid="message-pane-list-runway"], .expand-msg-pane div[data-tid="message-pane-footer"] {
  36. max-width: 80vw;
  37. }
  38. .expand-msg-pane div[data-tid="simplified-formatting-toolbar"] {
  39. max-width: none;
  40. }
  41. }
  42.  
  43. div[data-tid="experience-layout"], div[data-tid^="app-layout-area"], div[data-tid="app-layout-area--sub-nav"] {
  44. transition: all .25s ease-in-out !important;
  45. transition-delay: unset !important;
  46. }
  47.  
  48. #toggle-sidebar-btn, #expand-msg-pane-btn {
  49. background-color: transparent;
  50. color: #fff;
  51. display: flex;
  52. align-items: center;
  53. justify-content: center;
  54. font-size: 20px;
  55. line-height: 1;
  56. width: 36px;
  57. height: 36px;
  58. padding: 5px;
  59. margin-left: 10px;
  60. border: 0;
  61. cursor: pointer;
  62. }
  63.  
  64. .fui-light-mode #toggle-sidebar-btn, .fui-light-mode #expand-msg-pane-btn {
  65. color: rgb(66, 66, 66);
  66. }
  67. `;
  68.  
  69. function injectStyles() {
  70. const styleElement = document.createElement("style");
  71. styleElement.appendChild(document.createTextNode(styles));
  72. document.head.appendChild(styleElement);
  73. }
  74.  
  75. function observeThemeChanges() {
  76. const targetNode = document.body;
  77. const config = { attributes: true, childList: true, subtree: true };
  78.  
  79. const callback = function(mutationsList, observer) {
  80. for(let mutation of mutationsList) {
  81. if (mutation.type === 'childList') {
  82. const themeSelector = document.querySelector('button[data-tid="appearance-settings-theme-selector-dropdown"]');
  83. if (themeSelector) {
  84. checkTitleBarColor();
  85. break;
  86. }
  87. }
  88. }
  89. };
  90.  
  91. const observer = new MutationObserver(callback);
  92. observer.observe(targetNode, config);
  93. }
  94.  
  95. function checkTitleBarColor() {
  96. const titleBar = document.querySelector('div[data-tid="title-bar"]');
  97.  
  98. if (titleBar) {
  99. const bgColor = window.getComputedStyle(titleBar).backgroundColor;
  100. const rgb = bgColor.match(/\d+/g).map(Number);
  101. const luminance = (0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2]) / 255;
  102. if (luminance > 0.5) {
  103. document.body.classList.add('fui-light-mode');
  104. } else {
  105. document.body.classList.remove('fui-light-mode');
  106. }
  107. }
  108. }
  109.  
  110. function createSVGIcon(collapse) {
  111. const svgNS = "http://www.w3.org/2000/svg";
  112. const svg = document.createElementNS(svgNS, "svg");
  113. svg.setAttribute("xmlns", svgNS);
  114. svg.setAttribute("width", "24");
  115. svg.setAttribute("height", "24");
  116. svg.setAttribute("fill", "currentColor");
  117. svg.setAttribute("aria-hidden", "true");
  118.  
  119. const path = document.createElementNS(svgNS, "path");
  120. const d = collapse
  121. ? "m13.1 11.3 1.4-1.2c.3-.3.3-.7.1-1s-.7-.3-1-.1l-2.8 2.4c-.3.2-.3.7-.1 1 0 0 0 .1.1.1l2.8 2.4c.3.3.7.2 1-.1.3-.3.2-.7-.1-1l-1.4-1.2h5.1c.4 0 .7-.3.7-.7 0-.4-.3-.7-.7-.7h-5.1zM2.2 20.2h19.6c.7 0 1.2-.5 1.2-1.2V5c0-.7-.5-1.2-1.2-1.2H2.2C1.5 3.8 1 4.3 1 5v14c0 .7.5 1.2 1.2 1.2zm.2-1.9V5.7c0-.3.3-.6.6-.6h4.9v13.8H3c-.4 0-.6-.3-.6-.6zm6.8.6V5.1H21c.3 0 .6.3.6.6v12.5c0 .3-.3.6-.6.6H9.2z"
  122. : "M16.4 12.7 15 13.9c-.3.3-.3.7-.1 1 .3.3.7.3 1 .1l2.8-2.4c.3-.2.3-.7.1-1 0 0 0-.1-.1-.1l-2.8-2.4c-.3-.3-.7-.2-1 .1-.3.3-.2.7.1 1l1.4 1.2h-5.1c-.4 0-.7.3-.7.7 0 .4.3.7.7.7h5.1zM2.2 20.2h19.6c.7 0 1.2-.5 1.2-1.2V5c0-.7-.5-1.2-1.2-1.2H2.2C1.5 3.8 1 4.3 1 5v14c0 .7.5 1.2 1.2 1.2zm.2-1.9V5.7c0-.3.3-.6.6-.6h4.9v13.8H3c-.4 0-.6-.3-.6-.6zm6.8.6V5.1H21c.3 0 .6.3.6.6v12.5c0 .3-.3.6-.6.6H9.2z";
  123.  
  124. path.setAttribute("d", d);
  125. path.setAttribute("fill", "currentColor");
  126.  
  127. svg.appendChild(path);
  128.  
  129. return svg;
  130. }
  131.  
  132. function createMessagePaneSVGIcon(expanded) {
  133. const svgNS = "http://www.w3.org/2000/svg";
  134. const svg = document.createElementNS(svgNS, "svg");
  135. svg.setAttribute("xmlns", svgNS);
  136. svg.setAttribute("width", "24");
  137. svg.setAttribute("height", "24");
  138. svg.setAttribute("fill", "currentColor");
  139. svg.setAttribute("aria-hidden", "true");
  140.  
  141. const path = document.createElementNS(svgNS, "path");
  142. const d = expanded
  143. ? "m16.4 12.7 1.4 1.2c.3.3.3.7.1 1-.3.3-.7.3-1 .1l-2.8-2.4c-.3-.2-.3-.7-.1-1 0 0 0-.1.1-.1l2.8-2.4c.3-.3.7-.2 1 .1.3.3.2.7-.1 1l-1.4 1.2h5.1c.4 0 .7.3.7.7s-.3.7-.7.7h-5.1v-.1zM7.6 12.7l-1.4 1.2c-.3.3-.3.7-.1 1 .3.3.7.3 1 .1l2.8-2.4c.3-.2.3-.7.1-1 0 0 0-.1-.1-.1L7.1 9.1c-.3-.3-.7-.2-1 .1s-.2.7.1 1l1.4 1.2H2.5c-.4 0-.7.3-.7.7s.3.7.7.7h5.1v-.1zM2 2h20v2H2M2 6h20v2H2M2 16h20v2H2M2 20h20v2H2"
  144. : "m19.6 12.7-1.4 1.2c-.3.3-.3.7-.1 1 .3.3.7.3 1 .1l2.8-2.4c.3-.2.3-.7.1-1 0 0 0-.1-.1-.1l-2.8-2.4c-.3-.3-.7-.2-1 .1-.3.3-.2.7.1 1l1.4 1.2h-5.1c-.4 0-.7.3-.7.7s.3.7.7.7h5.1v-.1zM4.4 12.7l1.4 1.2c.3.3.3.7.1 1-.3.3-.7.3-1 .1l-2.8-2.4c-.3-.2-.3-.7-.1-1 0 0 0-.1.1-.1l2.8-2.4c.3-.3.7-.2 1 .1s.2.7-.1 1l-1.4 1.2h5.1c.4 0 .7.3.7.7s-.3.7-.7.7H4.4v-.1zM2 2h20v2H2M2 6h20v2H2M2 16h20v2H2M2 20h20v2H2";
  145.  
  146. path.setAttribute("d", d);
  147. path.setAttribute("fill", "currentColor");
  148.  
  149. svg.appendChild(path);
  150.  
  151. return svg;
  152. }
  153.  
  154. function addToggleButton() {
  155. const waitForTitlebarStartSlot = window.setInterval(function() {
  156. const titlebarSlot = document.querySelector('div[data-tid="titlebar-start-slot"]');
  157. if (titlebarSlot) {
  158. window.clearInterval(waitForTitlebarStartSlot);
  159.  
  160. const toggleButton = document.createElement("button");
  161. toggleButton.id = "toggle-sidebar-btn";
  162.  
  163. let sidebarOpen = true;
  164.  
  165. toggleButton.appendChild(createSVGIcon(sidebarOpen));
  166.  
  167. toggleButton.addEventListener("click", function() {
  168. sidebarOpen = !sidebarOpen;
  169.  
  170. while (toggleButton.firstChild) {
  171. toggleButton.removeChild(toggleButton.firstChild);
  172. }
  173.  
  174. toggleButton.appendChild(createSVGIcon(sidebarOpen));
  175.  
  176. document.body.classList.toggle("hide-sub-nav");
  177. });
  178.  
  179. titlebarSlot.appendChild(toggleButton);
  180.  
  181. const expandButton = document.createElement("button");
  182. expandButton.id = "expand-msg-pane-btn";
  183.  
  184. let messagePaneExpanded = false;
  185.  
  186. expandButton.appendChild(createMessagePaneSVGIcon(messagePaneExpanded));
  187.  
  188. expandButton.addEventListener("click", function() {
  189. messagePaneExpanded = !messagePaneExpanded;
  190.  
  191. while (expandButton.firstChild) {
  192. expandButton.removeChild(expandButton.firstChild);
  193. }
  194.  
  195. expandButton.appendChild(createMessagePaneSVGIcon(messagePaneExpanded));
  196.  
  197. document.body.classList.toggle("expand-msg-pane");
  198. });
  199.  
  200. titlebarSlot.appendChild(expandButton);
  201.  
  202. checkTitleBarColor();
  203. }
  204. }, 300);
  205. }
  206.  
  207. document.addEventListener("DOMContentLoaded", function() {
  208. injectStyles();
  209. addToggleButton();
  210. observeThemeChanges();
  211. });
  212. })();