move-youtube-comments-to-sidebar

Make the Youtube comments section visible from the sidebar

  1. // ==UserScript==
  2. // @name move-youtube-comments-to-sidebar
  3. // @version 1.0.1
  4. // @license MIT
  5. // @name:ja YouTubeのコメント欄をサイドバーで見れるようにする
  6. // @author yakisova41
  7. // @description Make the Youtube comments section visible from the sidebar
  8. // @description:ja YouTubeのコメント欄をサイドバーから見れるようにします。
  9. // @match https://www.youtube.com/*
  10. // @namespace https://yakisova.com
  11. // @icon data:image/png;base64,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
  12. // ==/UserScript==
  13.  
  14. (() => {
  15. var __create = Object.create;
  16. var __defProp = Object.defineProperty;
  17. var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
  18. var __getOwnPropNames = Object.getOwnPropertyNames;
  19. var __getProtoOf = Object.getPrototypeOf;
  20. var __hasOwnProp = Object.prototype.hasOwnProperty;
  21. var __esm = (fn, res) => function __init() {
  22. return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
  23. };
  24. var __commonJS = (cb, mod) => function __require() {
  25. return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
  26. };
  27. var __copyProps = (to, from, except, desc) => {
  28. if (from && typeof from === "object" || typeof from === "function") {
  29. for (let key of __getOwnPropNames(from))
  30. if (!__hasOwnProp.call(to, key) && key !== except)
  31. __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  32. }
  33. return to;
  34. };
  35. var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  36. // If the importer is in node compatibility mode or this is not an ESM
  37. // file that has been converted to a CommonJS file using a Babel-
  38. // compatible transform (i.e. "__esModule" has not been set), then set
  39. // "default" to the CommonJS "module.exports" for node compatibility.
  40. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  41. mod
  42. ));
  43.  
  44. // src/findElement.ts
  45. var findElement;
  46. var init_findElement = __esm({
  47. "src/findElement.ts"() {
  48. findElement = (selector) => {
  49. return new Promise((resolve) => {
  50. const interval = setInterval(() => {
  51. const elem = document.querySelector(selector);
  52. if (elem !== null) {
  53. clearInterval(interval);
  54. resolve(elem);
  55. }
  56. });
  57. });
  58. };
  59. }
  60. });
  61.  
  62. // src/css/style.css
  63. var require_style = __commonJS({
  64. "src/css/style.css"(exports, module) {
  65. (function() {
  66. if (!document.getElementById("7e1065fb51bb77ce35a77cffc916cbd9c74a211ded1e7f6c59e5d2b931e3a9eb")) {
  67. var e = document.createElement("style");
  68. e.id = "7e1065fb51bb77ce35a77cffc916cbd9c74a211ded1e7f6c59e5d2b931e3a9eb";
  69. e.textContent = `.mycsButton_cbfc566d866c2a43bc5bcf5094735b68_1{background:var(--yt-spec-badge-chip-background);border:none;color:var(--yt-spec-text-primary);font-size:14px;line-height:36px;height:36px;padding:0 16px;margin-left:8px;border-radius:18px;cursor:pointer;font-family:"Roboto; Arial; sans-serif;";position:relative;display:flex;justify-content:center;align-items:center}.mycsButton_cbfc566d866c2a43bc5bcf5094735b68_1>svg{fill:var(--yt-spec-text-primary)}.mycsButtonDown_cbfc566d866c2a43bc5bcf5094735b68_1{border-radius:18px;position:absolute;width:100%;height:100%;top:0;left:0}.mycsButton_cbfc566d866c2a43bc5bcf5094735b68_1:hover{background:var(--yt-spec-mono-tonal-hover)}.mycsButtonDown_cbfc566d866c2a43bc5bcf5094735b68_1:active{background:var(--yt-spec-touch-response);opacity:.1}.mycsCommentArea_cbfc566d866c2a43bc5bcf5094735b68_1{width:100%}.mycsCommentAreaSecondaryInner_cbfc566d866c2a43bc5bcf5094735b68_1{height:var(--ytd-watch-flexy-chat-max-height);margin-bottom:20px}.mycsCommentAreaBelow_cbfc566d866c2a43bc5bcf5094735b68_1{height:calc(100vh - 56.25vw - var(--ytd-margin-6x) - 56px);margin:20px 0}.mycsCommentInner_cbfc566d866c2a43bc5bcf5094735b68_1{width:100%;height:100%;border-radius:12px;border:solid 1px var(--ytd-searchbox-legacy-button-border-color)}.mycsComments_cbfc566d866c2a43bc5bcf5094735b68_1{overflow-y:scroll;overscroll-behavior:contain;padding:0 20px;height:100%}.mycsComments_cbfc566d866c2a43bc5bcf5094735b68_1::-webkit-scrollbar-thumb{height:56px;border-radius:8px;border:4px solid transparent;background-clip:content-box;background-color:var(--yt-spec-icon-disabled)}.mycsComments_cbfc566d866c2a43bc5bcf5094735b68_1::-webkit-scrollbar{background:transparent;width:16px}.mycsHidden_cbfc566d866c2a43bc5bcf5094735b68_1{display:none}`;
  70. document.head.appendChild(e);
  71. }
  72. })();
  73. module.exports = JSON.parse('{"mycsButton":"mycsButton_cbfc566d866c2a43bc5bcf5094735b68_1","mycsButtonDown":"mycsButtonDown_cbfc566d866c2a43bc5bcf5094735b68_1","mycsCommentArea":"mycsCommentArea_cbfc566d866c2a43bc5bcf5094735b68_1","mycsCommentAreaSecondaryInner":"mycsCommentAreaSecondaryInner_cbfc566d866c2a43bc5bcf5094735b68_1","mycsCommentAreaBelow":"mycsCommentAreaBelow_cbfc566d866c2a43bc5bcf5094735b68_1","mycsCommentInner":"mycsCommentInner_cbfc566d866c2a43bc5bcf5094735b68_1","mycsComments":"mycsComments_cbfc566d866c2a43bc5bcf5094735b68_1","mycsHidden":"mycsHidden_cbfc566d866c2a43bc5bcf5094735b68_1"}');
  74. }
  75. });
  76.  
  77. // src/addButton.ts
  78. var import_style, addButton_default;
  79. var init_addButton = __esm({
  80. "src/addButton.ts"() {
  81. init_findElement();
  82. import_style = __toESM(require_style());
  83. addButton_default = async (eventElement) => {
  84. const button = document.createElement("button");
  85. button.className = import_style.default.mycsButton;
  86. button.innerHTML = button.innerHTML + `<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24" viewBox="0 0 24 24" width="24"><path d="M8,7h8v2H8V7z M8,13h5v-2H8V13z M5,3v13h10h0.41l0.29,0.29L19,19.59V3H5 M4,2h16v20l-5-5H4V2L4,2z"></path></svg>`;
  87. const buttonDown = document.createElement("div");
  88. button.appendChild(buttonDown);
  89. buttonDown.className = import_style.default.mycsButtonDown;
  90. const buttonsParent = await findElement(
  91. "ytd-menu-renderer.ytd-watch-metadata"
  92. );
  93. buttonsParent.appendChild(button);
  94. button.onclick = (e) => {
  95. eventElement.dispatchEvent(
  96. new CustomEvent("toggleClick", {
  97. detail: e
  98. })
  99. );
  100. };
  101. };
  102. }
  103. });
  104.  
  105. // src/createComments.ts
  106. async function createComments() {
  107. const root = document.createElement("div");
  108. root.classList.add(import_style2.default.mycsCommentArea);
  109. root.innerHTML = `<div class=${import_style2.default.mycsCommentInner}><div class=${import_style2.default.mycsComments}></div></div>`;
  110. const commentsOuter = root.querySelector(`.${import_style2.default.mycsComments}`);
  111. const comments = await findElement("ytd-comments#comments");
  112. return {
  113. root,
  114. commentsOuter,
  115. comments
  116. };
  117. }
  118. async function smallMode(root) {
  119. const panels = await findElement("#primary-inner > #below > #panels");
  120. panels.before(root);
  121. root.classList.add(import_style2.default.mycsCommentAreaBelow);
  122. root.classList.remove(import_style2.default.mycsCommentAreaSecondaryInner);
  123. }
  124. async function bigMode(root) {
  125. const panels = await findElement("#secondary-inner > #panels");
  126. panels.before(root);
  127. root.classList.add(import_style2.default.mycsCommentAreaSecondaryInner);
  128. root.classList.remove(import_style2.default.mycsCommentAreaBelow);
  129. }
  130. var import_style2, createComments_default;
  131. var init_createComments = __esm({
  132. "src/createComments.ts"() {
  133. import_style2 = __toESM(require_style());
  134. init_findElement();
  135. createComments_default = async (eventElement) => {
  136. const { root, comments, commentsOuter } = await createComments();
  137. if (window.innerWidth > 1015) {
  138. bigMode(root);
  139. } else {
  140. smallMode(root);
  141. }
  142. let innerWidthTmp = 0;
  143. window.addEventListener("resize", () => {
  144. setTimeout(async () => {
  145. if (innerWidthTmp > 1015 && window.innerWidth < 1015) {
  146. await smallMode(root);
  147. const related = commentsOuter.querySelector("#related");
  148. findElement("#primary-inner > #below").then(
  149. (e) => e.appendChild(related)
  150. );
  151. } else if (innerWidthTmp < 1015 && window.innerWidth > 1015) {
  152. bigMode(root);
  153. }
  154. innerWidthTmp = window.innerWidth;
  155. }, 1);
  156. });
  157. eventElement.addEventListener(
  158. "toggleComments",
  159. async (e) => {
  160. if (e.detail) {
  161. root.classList.add(import_style2.default.mycsHidden);
  162. const commentParent = await findElement(
  163. "#primary-inner > #below"
  164. );
  165. commentParent.appendChild(comments);
  166. } else {
  167. root.classList.remove(import_style2.default.mycsHidden);
  168. commentsOuter.appendChild(comments);
  169. }
  170. }
  171. );
  172. };
  173. }
  174. });
  175.  
  176. // src/main.ts
  177. function pageChangeListener(eventelement) {
  178. let beforeHref = "";
  179. const observer = new MutationObserver(() => {
  180. const href = location.href;
  181. if (href !== beforeHref) {
  182. eventelement.dispatchEvent(
  183. new CustomEvent("pageChange", {
  184. detail: {
  185. beforeHref,
  186. newHref: href
  187. }
  188. })
  189. );
  190. }
  191. beforeHref = href;
  192. });
  193. observer.observe(document.querySelector("body"), {
  194. childList: true,
  195. subtree: true
  196. });
  197. }
  198. function main() {
  199. const mycs = document.createElement("div");
  200. let isButtonCreated = false;
  201. let isCommentsCreated = false;
  202. let commentsHide = true;
  203. pageChangeListener(mycs);
  204. mycs.addEventListener(
  205. "pageChange",
  206. async (e) => {
  207. const { newHref } = e.detail;
  208. const pageName = newHref.split("/")[3].split("?")[0];
  209. if (pageName === "watch") {
  210. console.log(isButtonCreated);
  211. if (!isButtonCreated) {
  212. isButtonCreated = true;
  213. await addButton_default(mycs);
  214. }
  215. if (!isCommentsCreated) {
  216. isCommentsCreated = true;
  217. await createComments_default(mycs);
  218. }
  219. commentsHide = true;
  220. mycs.dispatchEvent(
  221. new CustomEvent("toggleComments", {
  222. detail: commentsHide
  223. })
  224. );
  225. }
  226. }
  227. );
  228. mycs.addEventListener("toggleClick", () => {
  229. if (commentsHide) {
  230. commentsHide = false;
  231. } else {
  232. commentsHide = true;
  233. }
  234. mycs.dispatchEvent(
  235. new CustomEvent("toggleComments", {
  236. detail: commentsHide
  237. })
  238. );
  239. });
  240. }
  241. var init_main = __esm({
  242. "src/main.ts"() {
  243. init_addButton();
  244. init_createComments();
  245. }
  246. });
  247.  
  248. // src/index.ts
  249. var require_src = __commonJS({
  250. "src/index.ts"() {
  251. init_main();
  252. main();
  253. }
  254. });
  255. require_src();
  256. })();

QingJ © 2025

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