YouTube: Floating Chat Window on Fullscreen

To make floating chat window on fullscreen

当前为 2023-07-21 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name YouTube: Floating Chat Window on Fullscreen
  3. // @namespace UserScript
  4. // @match https://www.youtube.com/*
  5. // @exclude /^https?://\S+\.(txt|png|jpg|jpeg|gif|xml|svg|manifest|log|ini)[^\/]*$/
  6. // @version 0.2.0
  7. // @license MIT License
  8. // @author CY Fung
  9. // @description To make floating chat window on fullscreen
  10. // @require https://greasyfork.org/scripts/465819-api-for-customelements-in-youtube/code/API%20for%20CustomElements%20in%20YouTube.js?version=1215161
  11. // @run-at document-start
  12. // @grant none
  13. // @unwrap
  14. // @allFrames true
  15. // @inject-into page
  16. // ==/UserScript==
  17.  
  18.  
  19. ((__CONTEXT__) => {
  20.  
  21. const hkey_script = 'vdnvorrwsksy';
  22.  
  23.  
  24. const {isIframe, isTopFrame}=(()=>{
  25.  
  26. let isIframe = false, isTopFrame = false;
  27. try{
  28. isIframe = window.document !== top.document
  29. }catch(e){}
  30.  
  31. try{
  32. isTopFrame = window.document === top.document
  33. }catch(e){}
  34.  
  35. return {isIframe, isTopFrame};
  36.  
  37. })();
  38.  
  39. if(isIframe^isTopFrame){}else return;
  40.  
  41. if(isTopFrame){
  42.  
  43.  
  44.  
  45. const createStyleText = () => `
  46.  
  47.  
  48. [floating-chat-window]:fullscreen ytd-live-chat-frame#chat:not([collapsed]) {
  49. position:fixed !important;
  50. top: var(--f3-top, 5px) !important;
  51. left: var(--f3-left, calc(60vw + 100px)) !important;
  52. height: var(--f3-h, 60vh) !important;
  53. width: var(--f3-w, 320px) !important;
  54. display:flex !important;
  55. flex-direction: column !important;
  56. padding: 4px;
  57. cursor: all-scroll;
  58. z-index:9999;
  59. box-sizing: border-box !important;
  60. margin:0 !important;
  61. opacity: var(--floating-window-opacity, 1.0) !important;
  62. background: transparent;
  63. background-color: rgba(0, 0, 0, 0.5);
  64. transition: background-color 300ms;
  65. }
  66.  
  67. [floating-chat-window]:fullscreen ytd-live-chat-frame#chat:not([collapsed]):hover {
  68. background-color: rgba(0, 0, 0, 0.85);
  69.  
  70. }
  71.  
  72. .no-floating[floating-chat-window]:fullscreen ytd-live-chat-frame#chat:not([collapsed]) {
  73.  
  74. top: -300vh !important;
  75. left: -300vh !important;
  76. }
  77.  
  78.  
  79. [floating-chat-window]:fullscreen ytd-live-chat-frame#chat:not([collapsed]) #show-hide-button[class]{
  80. flex-grow: 0;
  81. flex-shrink:0;
  82. position:static;
  83. cursor: all-scroll;
  84. }
  85. [floating-chat-window]:fullscreen ytd-live-chat-frame#chat:not([collapsed]) #show-hide-button[class] *[class]{
  86. cursor: inherit;
  87. }
  88. [floating-chat-window]:fullscreen ytd-live-chat-frame#chat:not([collapsed]) iframe[class]{
  89. flex-grow: 100;
  90. flex-shrink:0;
  91. height: 0;
  92. position:static;
  93. }
  94.  
  95.  
  96. html{
  97. --fc7-handle-color: #0cb8da;
  98. }
  99. html[dark]{
  100. --fc7-handle-color: #0c74e4;
  101. }
  102.  
  103. :fullscreen .resize-handle {
  104.  
  105. position: absolute !important;
  106. top: 0;
  107. left: 0;
  108. bottom: 0;
  109. background: transparent;
  110. right: 0;
  111. z-index: 999 !important;
  112. border-radius: inherit !important;
  113. box-sizing: border-box !important;
  114. pointer-events:none !important;
  115. visibility: collapse;
  116. border: 4px solid transparent;
  117. border-color: transparent;
  118. transition: border-color 300ms;
  119. }
  120.  
  121. [floating-chat-window]:fullscreen ytd-live-chat-frame#chat:not([collapsed]):hover .resize-handle {
  122.  
  123. visibility: visible;
  124.  
  125. border-color: var(--fc7-handle-color);
  126. }
  127.  
  128. [moving] {
  129. cursor: all-scroll;
  130. --pointer-events:initial;
  131. }
  132.  
  133. [moving] body {
  134. --pointer-events:none;
  135. }
  136.  
  137. [moving] ytd-live-chat-frame#chat{
  138.  
  139. --pointer-events:initial;
  140. }
  141.  
  142.  
  143. [moving] ytd-live-chat-frame#chat iframe {
  144.  
  145. --pointer-events:none;
  146. }
  147.  
  148.  
  149. [moving="move"] ytd-live-chat-frame#chat {
  150. background-color: var(--yt-spec-general-background-a);
  151.  
  152. }
  153.  
  154.  
  155. [moving="move"] ytd-live-chat-frame#chat iframe {
  156.  
  157. visibility: collapse;
  158. }
  159.  
  160. [moving] * {
  161. pointer-events:var(--pointer-events) !important;
  162.  
  163. }
  164. [moving] *, [moving] [class] {
  165. user-select: none !important;
  166. }
  167.  
  168. :fullscreen tyt-iframe-popup-btn{
  169. display: none !important;
  170. }
  171.  
  172. [moving] tyt-iframe-popup-btn{
  173. display: none !important;
  174. }
  175.  
  176. [floating-chat-window]:fullscreen ytd-live-chat-frame#chat:not([collapsed]) #show-hide-button.ytd-live-chat-frame>ytd-toggle-button-renderer.ytd-live-chat-frame {
  177.  
  178. background: transparent;
  179.  
  180. }
  181.  
  182.  
  183.  
  184. `;
  185.  
  186. const addCSS = () => {
  187. let text = createStyleText();
  188. let style = document.createElement('style');
  189. style.id = 'rvZ0t';
  190. style.textContent = text;
  191. document.head.appendChild(style);
  192. }
  193.  
  194. const { Promise, requestAnimationFrame } = __CONTEXT__;
  195.  
  196. let chatWindowWR = null;
  197. let showHideButtonWR = null;
  198.  
  199.  
  200. /* globals WeakRef:false */
  201.  
  202. /** @type {(o: Object | null) => WeakRef | null} */
  203. const mWeakRef = typeof WeakRef === 'function' ? (o => o ? new WeakRef(o) : null) : (o => o || null); // typeof InvalidVar == 'undefined'
  204.  
  205. /** @type {(wr: Object | null) => Object | null} */
  206. const kRef = (wr => (wr && wr.deref) ? wr.deref() : wr);
  207.  
  208.  
  209.  
  210. let startX;
  211. let startY;
  212. let startWidth;
  213. let startHeight;
  214.  
  215.  
  216. let edge = 0;
  217.  
  218.  
  219. let initialLeft;
  220. let initialTop;
  221.  
  222. let stopResize;
  223. let stopMove;
  224.  
  225.  
  226. const getXY = (e) => {
  227. let rect = e.target.getBoundingClientRect();
  228. let x = e.clientX - rect.left; //x position within the element.
  229. let y = e.clientY - rect.top; //y position within the element.
  230. return { x, y }
  231. }
  232.  
  233. let beforeEvent = null;
  234.  
  235. function resizeWindow(e) {
  236.  
  237.  
  238. const chatWindow = kRef(chatWindowWR);
  239. if (chatWindow) {
  240.  
  241. const mEdge = edge;
  242.  
  243. if (mEdge == 4 || mEdge == 1) {
  244.  
  245. } else if (mEdge == 8 || mEdge == 16) {
  246. } else {
  247. return;
  248. }
  249.  
  250.  
  251. Promise.resolve(chatWindow).then(chatWindow => {
  252. let rect;
  253.  
  254. if (mEdge == 4 || mEdge == 1 || mEdge == 16) {
  255.  
  256. let newWidth = startWidth + (startX - e.pageX);
  257.  
  258. let newLeft = initialLeft + startWidth - newWidth;
  259. chatWindow.style.setProperty('--f3-w', newWidth + "px");
  260. chatWindow.style.setProperty('--f3-left', newLeft + "px");
  261.  
  262.  
  263.  
  264. let newHeight = startHeight + (startY - e.pageY);
  265.  
  266. let newTop = initialTop + startHeight - newHeight;
  267. chatWindow.style.setProperty('--f3-h', newHeight + "px");
  268. chatWindow.style.setProperty('--f3-top', newTop + "px");
  269.  
  270. rect = {
  271. x: newLeft,
  272. y: newTop,
  273. w: newWidth,
  274.  
  275. h: newHeight,
  276.  
  277.  
  278. };
  279.  
  280.  
  281.  
  282. } else if (mEdge == 8) {
  283.  
  284. let newWidth = startWidth + e.pageX - startX;
  285. let newHeight = startHeight + e.pageY - startY;
  286.  
  287. chatWindow.style.setProperty('--f3-w', newWidth + "px");
  288. chatWindow.style.setProperty('--f3-h', newHeight + "px");
  289.  
  290.  
  291. rect = {
  292. x: initialLeft,
  293. y: initialTop,
  294. w: newWidth,
  295.  
  296. h: newHeight,
  297.  
  298.  
  299. };
  300.  
  301. }
  302.  
  303.  
  304.  
  305. updateOpacity(chatWindow, rect, screen);
  306.  
  307. })
  308.  
  309.  
  310. e.stopPropagation();
  311. e.preventDefault();
  312.  
  313.  
  314. }
  315.  
  316. }
  317.  
  318. function moveWindow(e) {
  319.  
  320.  
  321. const chatWindow = kRef(chatWindowWR);
  322. if (chatWindow) {
  323.  
  324. Promise.resolve(chatWindow).then(chatWindow => {
  325.  
  326.  
  327. let newX = initialLeft + e.pageX - startX;
  328. let newY = initialTop + e.pageY - startY;
  329.  
  330. chatWindow.style.setProperty('--f3-left', newX + "px");
  331. chatWindow.style.setProperty('--f3-top', newY + "px");
  332.  
  333.  
  334.  
  335. updateOpacity(chatWindow, {
  336. x: newX,
  337. y: newY,
  338. w: startWidth,
  339.  
  340. h: startHeight,
  341.  
  342.  
  343. }, screen);
  344.  
  345. });
  346.  
  347.  
  348.  
  349. e.stopPropagation();
  350. e.preventDefault();
  351.  
  352. }
  353. }
  354.  
  355.  
  356.  
  357.  
  358. function initializeResize(e) {
  359.  
  360. if (!document.fullscreenElement) return;
  361.  
  362. if (!document.querySelector('[floating-chat-window]:fullscreen ytd-live-chat-frame#chat:not([collapsed])')) return;
  363.  
  364. if (e.target.id !== 'chat') return;
  365.  
  366. console.log(123)
  367.  
  368.  
  369. const { x, y } = getXY(e);
  370. edge = 0;
  371. if (x < 16 && y < 16) { edge = 16; }
  372. else if (x < 16) edge = 4;
  373. else if (y < 16) edge = 1;
  374. else edge = 8;
  375.  
  376. if (edge <= 0) return;
  377.  
  378. startX = e.pageX;
  379. startY = e.pageY;
  380.  
  381. const chatWindow = kRef(chatWindowWR);
  382. if (chatWindow) {
  383.  
  384. Promise.resolve(chatWindow).then(chatWindow => {
  385.  
  386. let rect = chatWindow.getBoundingClientRect();
  387. initialLeft = rect.x;
  388. initialTop = rect.y;
  389.  
  390.  
  391.  
  392. startWidth = rect.width;
  393. startHeight = rect.height;
  394.  
  395.  
  396. chatWindow.style.setProperty('--f3-left', initialLeft + "px");
  397. chatWindow.style.setProperty('--f3-top', initialTop + "px");
  398. chatWindow.style.setProperty('--f3-w', startWidth + "px");
  399. chatWindow.style.setProperty('--f3-h', startHeight + "px");
  400.  
  401. });
  402.  
  403. }
  404.  
  405.  
  406.  
  407.  
  408. document.documentElement.setAttribute('moving', 'resize');
  409.  
  410. document.documentElement.removeEventListener("mousemove", resizeWindow, false);
  411. document.documentElement.removeEventListener("mousemove", moveWindow, false);
  412. document.documentElement.removeEventListener("mouseup", stopResize, false);
  413. document.documentElement.removeEventListener("mouseup", stopMove, false);
  414.  
  415. document.documentElement.addEventListener("mousemove", resizeWindow);
  416. document.documentElement.addEventListener("mouseup", stopResize);
  417.  
  418. }
  419.  
  420.  
  421. let updateOpacityRid = 0;
  422.  
  423. function updateOpacity(chatWindow, rect, screen) {
  424.  
  425. let tid = ++updateOpacityRid;
  426.  
  427. requestAnimationFrame(() => {
  428.  
  429.  
  430. if (tid !== updateOpacityRid) return;
  431.  
  432. let { x, y, w, h } = rect;
  433. let [left, top, right, bottom] = [x, y, x + w, y + h];
  434.  
  435.  
  436. let opacityW = (Math.min(right, screen.width) - Math.max(0, left)) / w;
  437. let opacityH = (Math.min(bottom, screen.height) - Math.max(0, top)) / h;
  438.  
  439. let opacity = Math.min(opacityW, opacityH);
  440.  
  441. chatWindow.style.setProperty('--floating-window-opacity', Math.round(opacity * 100 * 5, 0) / 5 / 100);
  442.  
  443.  
  444. })
  445.  
  446.  
  447.  
  448.  
  449.  
  450. }
  451.  
  452. function initializeMove(e) {
  453.  
  454. if (!document.fullscreenElement) return;
  455. if (!document.querySelector('[floating-chat-window]:fullscreen ytd-live-chat-frame#chat:not([collapsed])')) return;
  456.  
  457.  
  458. console.log(122)
  459.  
  460. const chatWindow = kRef(chatWindowWR);
  461.  
  462.  
  463.  
  464. startX = e.pageX;
  465. startY = e.pageY;
  466.  
  467.  
  468. if (chatWindow) {
  469.  
  470. Promise.resolve(chatWindow).then(chatWindow => {
  471.  
  472.  
  473. let rect = chatWindow.getBoundingClientRect();
  474. initialLeft = rect.x;
  475. initialTop = rect.y;
  476.  
  477.  
  478.  
  479. startWidth = rect.width;
  480. startHeight = rect.height;
  481.  
  482.  
  483. chatWindow.style.setProperty('--f3-left', initialLeft + "px");
  484. chatWindow.style.setProperty('--f3-top', initialTop + "px");
  485. chatWindow.style.setProperty('--f3-w', startWidth + "px");
  486. chatWindow.style.setProperty('--f3-h', startHeight + "px");
  487.  
  488. })
  489.  
  490.  
  491. }
  492.  
  493.  
  494.  
  495. document.documentElement.setAttribute('moving', 'move');
  496.  
  497. document.documentElement.removeEventListener("mousemove", resizeWindow, false);
  498. document.documentElement.removeEventListener("mousemove", moveWindow, false);
  499. document.documentElement.removeEventListener("mouseup", stopResize, false);
  500. document.documentElement.removeEventListener("mouseup", stopMove, false);
  501.  
  502. document.documentElement.addEventListener("mousemove", moveWindow, false);
  503. document.documentElement.addEventListener("mouseup", stopMove, false);
  504.  
  505. e.stopPropagation();
  506. e.preventDefault();
  507.  
  508. beforeEvent = e;
  509.  
  510. }
  511.  
  512.  
  513. function checkClick(beforeEvent, currentEvent) {
  514.  
  515. const d = currentEvent.timeStamp - beforeEvent.timeStamp;
  516. if (d < 300 && d > 30) {
  517.  
  518. document.documentElement.classList.add('no-floating');
  519.  
  520. }
  521.  
  522. }
  523.  
  524.  
  525. stopResize = (e) => {
  526.  
  527. document.documentElement.removeAttribute('moving');
  528. document.documentElement.removeEventListener("mousemove", resizeWindow);
  529. }
  530.  
  531. stopMove = (e) => {
  532. document.documentElement.removeAttribute('moving');
  533. document.documentElement.removeEventListener("mousemove", moveWindow);
  534.  
  535. beforeEvent && checkClick(beforeEvent, e);
  536. beforeEvent = null;
  537. }
  538.  
  539.  
  540. function reset() {
  541.  
  542. document.documentElement.removeAttribute('moving');
  543. document.documentElement.removeEventListener("mousemove", resizeWindow, false);
  544. document.documentElement.removeEventListener("mousemove", moveWindow, false);
  545. document.documentElement.removeEventListener("mouseup", stopResize, false);
  546. document.documentElement.removeEventListener("mouseup", stopMove, false);
  547.  
  548.  
  549. startX = 0;
  550. startY = 0;
  551. startWidth = 0;
  552. startHeight = 0;
  553.  
  554.  
  555. edge = 0;
  556.  
  557.  
  558. initialLeft = 0;
  559. initialTop = 0;
  560.  
  561. beforeEvent = null;
  562.  
  563.  
  564. }
  565.  
  566. function iframeLoaded(){
  567.  
  568. }
  569.  
  570. function onMessage(evt){
  571. if(evt.data === 'vdnvorrwsksy'){
  572.  
  573. const iframeWin = evt.source;
  574. const iframeDoc = iframeWin.document;
  575.  
  576.  
  577.  
  578. function onReady() {
  579.  
  580. iframeDoc.head.appendChild(document.createElement('style')).textContent=`
  581.  
  582. .youtube-floating-chat-iframe #right-arrow-container.yt-live-chat-ticker-renderer,
  583. .youtube-floating-chat-iframe #left-arrow-container.yt-live-chat-ticker-renderer
  584.  
  585. {
  586. background: transparent;
  587. }
  588.  
  589. .youtube-floating-chat-iframe yt-live-chat-renderer.yt-live-chat-app {
  590.  
  591. --yt-live-chat-background-color: transparent;
  592. --yt-live-chat-action-panel-background-color: rgba(0, 0, 0, 0.08);
  593. --yt-live-chat-header-background-color: rgba(0, 0, 0, 0.18);
  594. --yt-spec-static-overlay-background-medium: rgba(0, 0, 0, 0.08);
  595. --yt-live-chat-banner-gradient-scrim: transparent;
  596.  
  597. }
  598.  
  599.  
  600.  
  601. .youtube-floating-chat-iframe yt-live-chat-renderer.yt-live-chat-app yt-live-chat-banner-manager #visible-banners > yt-live-chat-banner-renderer {
  602. --fc7-banner-opacity: 0.86;
  603. }
  604.  
  605. .youtube-floating-chat-iframe yt-live-chat-renderer.yt-live-chat-app yt-live-chat-banner-manager #visible-banners > yt-live-chat-banner-renderer[collapsed] {
  606. --fc7-banner-opacity: 0.66;
  607. }
  608.  
  609.  
  610. .youtube-floating-chat-iframe yt-live-chat-renderer.yt-live-chat-app yt-live-chat-banner-manager:hover #visible-banners > yt-live-chat-banner-renderer[class] {
  611. --fc7-banner-opacity: 1;
  612. }
  613.  
  614.  
  615.  
  616. .youtube-floating-chat-iframe yt-live-chat-renderer.yt-live-chat-app yt-live-chat-banner-manager #visible-banners > yt-live-chat-banner-renderer {
  617. opacity: var(--fc7-banner-opacity) !important;
  618. }
  619.  
  620.  
  621.  
  622.  
  623. [dark].youtube-floating-chat-iframe yt-live-chat-app ::-webkit-scrollbar-track,
  624. [dark].youtube-floating-chat-iframe yt-live-chat-kevlar-container ::-webkit-scrollbar-track {
  625. background-color: var(--ytd-searchbox-legacy-button-color);
  626. }
  627.  
  628. .youtube-floating-chat-iframe yt-live-chat-app ::-webkit-scrollbar-track,
  629. .youtube-floating-chat-iframe yt-live-chat-kevlar-container ::-webkit-scrollbar-track {
  630. background-color: #fcfcfc;
  631. }
  632.  
  633.  
  634. [dark].youtube-floating-chat-iframe yt-live-chat-app ::-webkit-scrollbar-thumb,
  635. [dark].youtube-floating-chat-iframe yt-live-chat-kevlar-container ::-webkit-scrollbar-thumb{
  636.  
  637. background-color: var(--ytd-searchbox-legacy-button-color);
  638. border: 2px solid var(--ytd-searchbox-legacy-button-color);
  639.  
  640. }
  641.  
  642.  
  643.  
  644. `;
  645.  
  646. iframeDoc.documentElement.classList.add('youtube-floating-chat-iframe');
  647. }
  648.  
  649.  
  650.  
  651. Promise.resolve().then(() => {
  652.  
  653. if (iframeDoc.readyState !== 'loading') {
  654. onReady();
  655. } else {
  656. iframeWin.addEventListener("DOMContentLoaded", onReady, false);
  657. }
  658.  
  659. });
  660.  
  661.  
  662. }
  663.  
  664. }
  665.  
  666.  
  667. function setChat(chat) {
  668.  
  669. let resizeHandle = HTMLElement.prototype.querySelector.call(chat, '.resize-handle')
  670. if (resizeHandle) return;
  671.  
  672.  
  673.  
  674. let cw = (()=>{
  675. try{
  676. const {head, body} = chat.$.chatframe.contentWindow.document;
  677. return {head, body}
  678.  
  679. }catch(e){return null;}
  680. })();
  681.  
  682. if(!cw) return;
  683.  
  684. window.removeEventListener('message', onMessage , false);
  685. window.addEventListener('message', onMessage , false);
  686.  
  687.  
  688.  
  689. let script = document.getElementById('rvZ0t') || (document.evaluate("//div[contains(text(), 'userscript-control[enable-customized-floating-window]')]", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null) || 0).singleNodeValue;
  690. if (!script) addCSS();
  691.  
  692. if (!document.documentElement.hasAttribute('floating-chat-window')) document.documentElement.setAttribute('floating-chat-window', '');
  693.  
  694.  
  695. chat.setAttribute('allowtransparency', 'true');
  696.  
  697.  
  698.  
  699. resizeHandle = document.createElement("div");
  700. resizeHandle.className = "resize-handle";
  701. chat.appendChild(resizeHandle);
  702. resizeHandle = null;
  703.  
  704. let chatWindow;
  705. let showHideButton;
  706.  
  707. chatWindow = kRef(chatWindowWR);
  708. showHideButton = kRef(showHideButtonWR);
  709.  
  710.  
  711.  
  712. if (chatWindow) chatWindow.removeEventListener("mousedown", initializeResize, false);
  713. if (showHideButton) showHideButton.removeEventListener("mousedown", initializeMove, false);
  714.  
  715.  
  716. chatWindow = chat;
  717. showHideButton = HTMLElement.prototype.querySelector.call(chat, '#show-hide-button');
  718. chatWindowWR = mWeakRef(chat)
  719. showHideButtonWR = mWeakRef(showHideButton);
  720.  
  721.  
  722.  
  723. chatWindow.addEventListener("mousedown", initializeResize, false);
  724. showHideButton.addEventListener("mousedown", initializeMove, false);
  725.  
  726. reset();
  727.  
  728. }
  729.  
  730. function noChat(chat) {
  731.  
  732. let chatWindow;
  733. let showHideButton;
  734.  
  735. chatWindow = kRef(chatWindowWR);
  736. showHideButton = kRef(showHideButtonWR);
  737.  
  738.  
  739.  
  740. if (chatWindow) chatWindow.removeEventListener("mousedown", initializeResize, false);
  741. if (showHideButton) showHideButton.removeEventListener("mousedown", initializeMove, false);
  742.  
  743.  
  744. let resizeHandle = HTMLElement.prototype.querySelector.call(chat, '.resize-handle')
  745. if (resizeHandle) {
  746. resizeHandle.remove();
  747. }
  748.  
  749. chat.removeEventListener("mousedown", initializeResize, false);
  750.  
  751.  
  752. showHideButton = HTMLElement.prototype.querySelector.call(chat, '#show-hide-button');
  753.  
  754. if (showHideButton) showHideButton.removeEventListener("mousedown", initializeMove, false);
  755.  
  756.  
  757. reset();
  758. }
  759.  
  760. document.addEventListener('fullscreenchange', () => {
  761. document.documentElement.classList.remove('no-floating')
  762. })
  763.  
  764. customYtElements.whenRegistered('ytd-live-chat-frame', (proto) => {
  765.  
  766.  
  767. proto.attached = ((attached) => (function () { Promise.resolve(this).then(setChat); return attached.apply(this, arguments) }))(proto.attached);
  768.  
  769. proto.detached = ((detached) => (function () { Promise.resolve(this).then(noChat); return detached.apply(this, arguments) }))(proto.detached);
  770.  
  771. let chat = document.querySelector('ytd-live-chat-frame');
  772. if (chat) Promise.resolve(chat).then(setChat);
  773.  
  774. })
  775.  
  776.  
  777.  
  778.  
  779. }else if(isIframe && top===parent){
  780.  
  781.  
  782.  
  783. top.postMessage(hkey_script, `${location.protocol}//${location.hostname}`);
  784.  
  785.  
  786.  
  787.  
  788. }
  789.  
  790.  
  791.  
  792.  
  793. })({ Promise, requestAnimationFrame });