Tabview YouTube Totara

製作資訊、評論、影片和播放列表的標籤

  1. // ==UserScript==
  2. // @name Tabview YouTube Totara
  3. // @version 5.0.055
  4. // @namespace https://www.youtube.com/
  5. // @author CY Fung
  6. // @license MIT
  7. // @match https://www.youtube.com/*
  8.  
  9. // @name:zh-TW Tabview YouTube Totara
  10. // @name:ja Tabview YouTube Totara
  11. // @description To make tabs for Info, Comments, Videos and Playlist
  12.  
  13. // @description:es Para crear pestañas para Información, Comentarios, Videos y Lista de reproducción
  14. // @description:fr Pour créer des onglets pour Infos, Commentaires, Vidéos et Playlist
  15. // @description:de Um Tabs für Informationen, Kommentare, Videos und Playlist zu erstellen
  16. // @description:zh 制作信息、评论、视频和播放列表的标签
  17. // @description:zh-CN 制作信息、评论、视频和播放列表的标签
  18. // @description:zh-TW 製作資訊、評論、影片和播放列表的標籤
  19. // @description:zh-HK 製作資訊、評論、影片視頻和播放列表的標籤
  20. // @description:ja 情報、コメント、動画、および再生リストのタブを作成するために
  21. // @description:ko 정보, 댓글, 동영상 및 재생 목록에 대한 탭 만들기
  22. // @description:ru Чтобы создать вкладки для Информации, Комментариев, Видео и Плейлиста
  23. // @description:pt Para fazer abas para Informações, Comentários, Vídeos e Playlist
  24. // @description:ar لإنشاء علامات تبويب للمعلومات والتعليقات والفيديو وقائمة التشغيل
  25.  
  26. // @icon https://raw.githubusercontent.com/tabview-youtube/Tabview-YouTube-Totara/main/images/icon128p.png
  27. // @supportURL https://github.com/tabview-youtube/Tabview-YouTube-Totara
  28. // @run-at document-start
  29. // @grant GM_getResourceText
  30. // @grant GM.getResourceText
  31. // @grant GM_registerMenuCommand
  32. // @grant GM_addElement
  33. // @noframes
  34. // @exclude /^https?://\w+\.youtube\.com\/live_chat.*$/
  35. // @exclude /^https?://\S+\.(txt|png|jpg|jpeg|gif|xml|svg|manifest|log|ini)[^\/]*$/
  36. // @require https://cdn.jsdelivr.net/gh/cyfung1031/userscript-supports@7221a4efffd49d852de0074ec503d4febb99f28b/library/nextBrowserTick.min.js
  37. //
  38. // ==/UserScript==
  39.  
  40. /*
  41.  
  42. MIT License
  43.  
  44. Copyright (c) 2024 cyfung1031
  45.  
  46. Permission is hereby granted, free of charge, to any person obtaining a copy
  47. of this software and associated documentation files (the "Software"), to deal
  48. in the Software without restriction, including without limitation the rights
  49. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  50. copies of the Software, and to permit persons to whom the Software is
  51. furnished to do so, subject to the following conditions:
  52.  
  53. The above copyright notice and this permission notice shall be included in all
  54. copies or substantial portions of the Software.
  55.  
  56. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  57. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  58. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  59. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  60. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  61. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  62. SOFTWARE.
  63.  
  64. */
  65.  
  66. if (typeof trustedTypes !== 'undefined' && trustedTypes.defaultPolicy === null) {
  67. let s = s => s;
  68. trustedTypes.createPolicy('default', { createHTML: s, createScriptURL: s, createScript: s });
  69. }
  70.  
  71. const defaultPolicy = (typeof trustedTypes !== 'undefined' && trustedTypes.defaultPolicy) || { createHTML: s => s };
  72. function createHTML(s) {
  73. return defaultPolicy.createHTML(s);
  74. }
  75.  
  76. let trustHTMLErr = null;
  77. try {
  78. document.createElement('div').innerHTML = createHTML('1');
  79. } catch (e) {
  80. trustHTMLErr = e;
  81. }
  82.  
  83. if (trustHTMLErr) {
  84. console.log(`trustHTMLErr`, trustHTMLErr);
  85. trustHTMLErr(); // exit userscript
  86. }
  87.  
  88.  
  89. // -----------------------------------------------------------------------------------------------------------------------------
  90.  
  91. const VAL_ROUNDED_A1 = 12;
  92.  
  93. const executionScript = (communicationKey) => {
  94.  
  95.  
  96.  
  97. if (typeof trustedTypes !== 'undefined' && trustedTypes.defaultPolicy === null) {
  98. let s = s => s;
  99. trustedTypes.createPolicy('default', { createHTML: s, createScriptURL: s, createScript: s });
  100. }
  101. const defaultPolicy = (typeof trustedTypes !== 'undefined' && trustedTypes.defaultPolicy) || { createHTML: s => s };
  102. function createHTML(s) {
  103. return defaultPolicy.createHTML(s);
  104. }
  105.  
  106. let trustHTMLErr = null;
  107. try {
  108. document.createElement('div').innerHTML = createHTML('1');
  109. } catch (e) {
  110. trustHTMLErr = e;
  111. }
  112.  
  113. if (trustHTMLErr) {
  114. console.log(`trustHTMLErr`, trustHTMLErr);
  115. trustHTMLErr(); // exit userscript
  116. }
  117.  
  118. try {
  119.  
  120. let executionFinished = 0;
  121.  
  122. if (typeof CustomElementRegistry === 'undefined') return;
  123. if (CustomElementRegistry.prototype.define000) return;
  124. if (typeof CustomElementRegistry.prototype.define !== 'function') return;
  125.  
  126. /** @type {HTMLElement} */
  127. const HTMLElement_ = HTMLElement.prototype.constructor;
  128.  
  129. /**
  130. * @param {Element} elm
  131. * @param {string} selector
  132. * @returns {Element | null}
  133. * */
  134. const qsOne = (elm, selector) => {
  135. return HTMLElement_.prototype.querySelector.call(elm, selector);
  136. }
  137.  
  138. /**
  139. * @param {Element} elm
  140. * @param {string} selector
  141. * @returns {NodeListOf<Element>}
  142. * */
  143. const qsAll = (elm, selector) => {
  144. return HTMLElement_.prototype.querySelectorAll.call(elm, selector);
  145. }
  146.  
  147. const pdsBaseDF = Object.getOwnPropertyDescriptors(DocumentFragment.prototype);
  148.  
  149. Object.defineProperties(DocumentFragment.prototype, {
  150. replaceChildren000: pdsBaseDF.replaceChildren,
  151. });
  152.  
  153. const pdsBaseNode = Object.getOwnPropertyDescriptors(Node.prototype);
  154. // console.log(pdsBaseElement.setAttribute, pdsBaseElement.getAttribute)
  155.  
  156. Object.defineProperties(Node.prototype, {
  157. appendChild000: pdsBaseNode.appendChild,
  158. insertBefore000: pdsBaseNode.insertBefore
  159. });
  160.  
  161. // class BaseElement extends Element{
  162.  
  163. // }
  164. const pdsBaseElement = Object.getOwnPropertyDescriptors(Element.prototype);
  165. // console.log(pdsBaseElement.setAttribute, pdsBaseElement.getAttribute)
  166.  
  167. Object.defineProperties(Element.prototype, {
  168. setAttribute000: pdsBaseElement.setAttribute,
  169. getAttribute000: pdsBaseElement.getAttribute,
  170. hasAttribute000: pdsBaseElement.hasAttribute,
  171. removeAttribute000: pdsBaseElement.removeAttribute,
  172. querySelector000: pdsBaseElement.querySelector,
  173. replaceChildren000: pdsBaseElement.replaceChildren
  174. });
  175.  
  176. Element.prototype.setAttribute111 = function (p, v) {
  177. v = `${v}`;
  178. if (this.getAttribute000(p) === v) return;
  179. this.setAttribute000(p, v)
  180. }
  181.  
  182. Element.prototype.incAttribute111 = function (p){
  183. let v = +this.getAttribute000(p) || 0;
  184. v = v > 1e9 ? v + 1 : 9;
  185. this.setAttribute000(p, `${v}`);
  186. return v;
  187. }
  188.  
  189. Element.prototype.assignChildern111 = function (previousSiblings, node, nextSiblings) {
  190. // assume all previousSiblings, node, and nextSiblings are on the page
  191. // -> only remove triggering is needed
  192. let nodeList = [];
  193. for (let t = this.firstChild; t instanceof Node; t = t.nextSibling) {
  194. if (t === node) continue;
  195. nodeList.push(t);
  196. }
  197.  
  198. inPageRearrange = true;
  199. if (node.parentNode === this) {
  200. let fm = new DocumentFragment();
  201. if (nodeList.length > 0) {
  202. fm.replaceChildren000(...nodeList);
  203. // nodeList.length = 0;
  204. }
  205. // nodeList = null;
  206. if (previousSiblings && previousSiblings.length > 0) {
  207. fm.replaceChildren000(...previousSiblings);
  208. this.insertBefore000(fm, node);
  209. }
  210. if (nextSiblings && nextSiblings.length > 0) {
  211. fm.replaceChildren000(...nextSiblings);
  212. this.appendChild000(fm);
  213. }
  214. fm.replaceChildren000();
  215. fm = null;
  216. } else {
  217. if (!previousSiblings) previousSiblings = [];
  218. if (!nextSiblings) nextSiblings = [];
  219. this.replaceChildren000(...previousSiblings, node, ...nextSiblings);
  220. }
  221. inPageRearrange = false;
  222. if (nodeList.length > 0) {
  223. for (const t of nodeList) {
  224. if (t instanceof Element && t.isConnected === false) t.remove(); // remove triggering
  225. }
  226. }
  227. nodeList.length = 0;
  228. nodeList = null;
  229. }
  230.  
  231.  
  232. // ==============================================================================================================================================================================================================================================================================
  233.  
  234. const DISABLE_FLAGS_SHADYDOM_FREE = true;
  235.  
  236. /**
  237. *
  238. * Minified Code from https://greasyfork.org/en/scripts/475632-ytconfighacks/code (ytConfigHacks)
  239. * Date: 2024.04.17
  240. * Minifier: https://www.toptal.com/developers/javascript-minifier
  241. *
  242. */
  243. (() => {
  244. let e = "undefined" != typeof unsafeWindow ? unsafeWindow : this instanceof Window ?
  245. this : window; if (!e._ytConfigHacks) {
  246. let t = 4; class n extends Set {
  247. add(e) {
  248. if (t <= 0) return console.warn(
  249. "yt.config_ is already applied on the page."); "function" == typeof e && super.add(e)
  250. }
  251. } let a = (async () => { })()
  252. .constructor, i = e._ytConfigHacks = new n, l = () => { let t = e.ytcsi.originalYtcsi; t && (e.ytcsi = t, l = null) },
  253. c = null, o = () => {
  254. if (t >= 1) {
  255. let n = (e.yt || 0).config_ || (e.ytcfg || 0).data_ || 0; if ("string" == typeof n.
  256. INNERTUBE_API_KEY && "object" == typeof n.EXPERIMENT_FLAGS) for (let a of (--t <= 0 && l && l(), c = !0, i)) a(n)
  257. }
  258. }, f = 1,
  259. d = t => {
  260. if (t = t || e.ytcsi) return e.ytcsi = new Proxy(t, { get: (e, t, n) => "originalYtcsi" === t ? e : (o(), c && --f <= 0 && l && l(), e[t]) })
  261. , !0
  262. }; d() || Object.defineProperty(e, "ytcsi", {
  263. get() { }, set: t => (t && (delete e.ytcsi, d(t)), !0), enumerable: !1, configurable: !0
  264. }); let { addEventListener: s, removeEventListener: y } = Document.prototype; function r(t) {
  265. o(),
  266. t && e.removeEventListener("DOMContentLoaded", r, !1)
  267. } new a(e => {
  268. if ("undefined" != typeof AbortSignal) s.call(document,
  269. "yt-page-data-fetched", e, { once: !0 }), s.call(document, "yt-navigate-finish", e, { once: !0 }), s.call(document, "spfdone", e,
  270. { once: !0 }); else {
  271. let t = () => {
  272. e(), y.call(document, "yt-page-data-fetched", t, !1), y.call(document, "yt-navigate-finish", t, !1),
  273. y.call(document, "spfdone", t, !1)
  274. }; s.call(document, "yt-page-data-fetched", t, !1), s.call(document, "yt-navigate-finish", t, !1),
  275. s.call(document, "spfdone", t, !1)
  276. }
  277. }).then(o), new a(e => {
  278. if ("undefined" != typeof AbortSignal) s.call(document, "yt-action", e,
  279. { once: !0, capture: !0 }); else { let t = () => { e(), y.call(document, "yt-action", t, !0) }; s.call(document, "yt-action", t, !0) }
  280. }).then(o),
  281. a.resolve().then(() => { "loading" !== document.readyState ? r() : e.addEventListener("DOMContentLoaded", r, !1) })
  282. }
  283. })();
  284.  
  285. let configOnce = false;
  286. window._ytConfigHacks.add((config_) => {
  287. if (configOnce) return;
  288. configOnce = true;
  289.  
  290. const EXPERIMENT_FLAGS = config_.EXPERIMENT_FLAGS || 0;
  291. const EXPERIMENTS_FORCED_FLAGS = config_.EXPERIMENTS_FORCED_FLAGS || 0;
  292. for (const flags of [EXPERIMENT_FLAGS, EXPERIMENTS_FORCED_FLAGS]) {
  293. if (flags) {
  294. // flags.kevlar_watch_metadata_refresh_no_old_secondary_data = false;
  295. // flags.live_chat_overflow_hide_chat = false;
  296. flags.web_watch_chat_hide_button_killswitch = false;
  297. flags.web_watch_theater_chat = false; // for re-openable chat (ytd-watch-flexy's liveChatCollapsed is always undefined)
  298. flags.suppress_error_204_logging = true;
  299. flags.kevlar_watch_grid = false; // A/B testing for watch grid
  300.  
  301. if (DISABLE_FLAGS_SHADYDOM_FREE) {
  302. flags.enable_shadydom_free_scoped_node_methods = false;
  303. flags.enable_shadydom_free_scoped_query_methods = false;
  304. flags.enable_shadydom_free_scoped_readonly_properties_batch_one = false;
  305. flags.enable_shadydom_free_parent_node = false;
  306. flags.enable_shadydom_free_children = false;
  307. flags.enable_shadydom_free_last_child = false;
  308. }
  309. }
  310. }
  311.  
  312. });
  313.  
  314. // ==============================================================================================================================================================================================================================================================================
  315.  
  316.  
  317. /* globals WeakRef:false */
  318.  
  319. /** @type {(o: Object | null) => WeakRef | null} */
  320. const mWeakRef = typeof WeakRef === 'function' ? (o => o ? new WeakRef(o) : null) : (o => o || null); // typeof InvalidVar == 'undefined'
  321.  
  322. /** @type {(wr: Object | null) => Object | null} */
  323. const kRef = (wr => (wr && wr.deref) ? wr.deref() : wr);
  324.  
  325.  
  326. /** @type {globalThis.PromiseConstructor} */
  327. const Promise = (async () => { })().constructor; // YouTube hacks Promise in WaterFox Classic and "Promise.resolve(0)" nevers resolve.
  328.  
  329. const delayPn = delay => new Promise((fn => setTimeout(fn, delay)));
  330.  
  331. const insp = o => o ? (o.polymerController || o.inst || o || 0) : (o || 0);
  332.  
  333. const setTimeout_ = setTimeout.bind(window);
  334.  
  335. const PromiseExternal = ((resolve_, reject_) => {
  336. const h = (resolve, reject) => { resolve_ = resolve; reject_ = reject };
  337. return class PromiseExternal extends Promise {
  338. constructor(cb = h) {
  339. super(cb);
  340. if (cb === h) {
  341. /** @type {(value: any) => void} */
  342. this.resolve = resolve_;
  343. /** @type {(reason?: any) => void} */
  344. this.reject = reject_;
  345. }
  346. }
  347. };
  348. })();
  349.  
  350. // ------------------------------------------------------------------------ nextBrowserTick ------------------------------------------------------------------------
  351. !function (e) {
  352. "use strict"; if (e.nextBrowserTick) return; if (!function () {
  353. if (e.postMessage && !e.importScripts && e.addEventListener) {
  354. let t = !0, s = () => { t = !1 };
  355. return e.addEventListener("message", s, !1), e.postMessage("", "*"), e.removeEventListener("message", s, !1), t
  356. }
  357. }())
  358. return void console.warn("Your browser environment cannot use nextBrowserTick"); const t = (async () => { })().constructor,
  359. s = ((e, s) => { const n = (t, n) => { e = t, s = n }; return class extends t { constructor(t = n) { super(t), t === n && (this.resolve = e, this.reject = s) } } })();
  360. let n, r = null; do { n = `$$nextBrowserTick$$${(Math.random() + 8).toString().slice(2)}$$` } while (n in e); const o = n; e[o] = 1; e.addEventListener("message",
  361. (e => { (null !== r ? (e || 0).data : 0) === o && e.source === (e.target || 1) && r.resolve(r = null) }), !1), e.nextBrowserTick = t => {
  362. r || (r = new s, e.postMessage(o, "*")),
  363. r.then(t).catch(console.warn)
  364. }
  365. }("undefined" == typeof self ? "undefined" == typeof global ? this : global : self);
  366.  
  367. // ------------------------------------------------------------------------ nextBrowserTick ------------------------------------------------------------------------
  368.  
  369. const isPassiveArgSupport = (typeof IntersectionObserver === 'function');
  370. const bubblePassive = isPassiveArgSupport ? { capture: false, passive: true } : false;
  371. const capturePassive = isPassiveArgSupport ? { capture: true, passive: true } : true;
  372.  
  373.  
  374.  
  375. class Attributer {
  376. constructor(list) {
  377. this.list = list;
  378. this.flag = 0;
  379. }
  380. makeString() {
  381. let k = 1;
  382. let s = '';
  383. let i = 0;
  384. while (this.flag >= k) {
  385. if (this.flag & k) {
  386. s += this.list[i];
  387. }
  388. i++;
  389. k <<= 1;
  390. }
  391. return s;
  392. }
  393. }
  394.  
  395. const mLoaded = new Attributer('icp');
  396.  
  397. const wrSelfMap = new WeakMap();
  398.  
  399. /** @type {Object.<string, Element | null>} */
  400. const elements = new Proxy({
  401. related: null,
  402. comments: null,
  403. infoExpander: null,
  404. }, {
  405. get(target, prop) {
  406. return kRef(target[prop]);
  407. },
  408. set(target, prop, value) {
  409. if (value) {
  410. let wr = wrSelfMap.get(value);
  411. if (!wr) {
  412. wr = mWeakRef(value);
  413. wrSelfMap.set(value, wr);
  414. }
  415. target[prop] = wr;
  416. } else {
  417. target[prop] = null;
  418. }
  419. return true;
  420. }
  421. });
  422. const getMainInfo = () => {
  423. const infoExpander = elements.infoExpander;
  424. if (!infoExpander) return null;
  425. const mainInfo = infoExpander.matches('[tyt-main-info]') ? infoExpander : infoExpander.querySelector000('[tyt-main-info]');
  426. return mainInfo || null;
  427. }
  428. const asyncWrap = (asyncFn) => {
  429. return () => {
  430. Promise.resolve().then(asyncFn);
  431. };
  432. }
  433.  
  434.  
  435. let pageType = null;
  436.  
  437. let pageLang = 'en';
  438. const langWords = {
  439. 'en': {
  440. //'share':'Share',
  441. 'info': 'Info',
  442. 'videos': 'Videos',
  443. 'playlist': 'Playlist'
  444. },
  445. 'jp': {
  446. //'share':'共有',
  447. 'info': '情報',
  448. 'videos': '動画',
  449. 'playlist': '再生リスト'
  450. },
  451. 'tw': {
  452. //'share':'分享',
  453. 'info': '資訊',
  454. 'videos': '影片',
  455. 'playlist': '播放清單'
  456. },
  457. 'cn': {
  458. //'share':'分享',
  459. 'info': '资讯',
  460. 'videos': '视频',
  461. 'playlist': '播放列表'
  462. },
  463. 'du': {
  464. //'share':'Teilen',
  465. 'info': 'Info',
  466. 'videos': 'Videos',
  467. 'playlist': 'Playlist'
  468. },
  469. 'fr': {
  470. //'share':'Partager',
  471. 'info': 'Info',
  472. 'videos': 'Vidéos',
  473. 'playlist': 'Playlist'
  474. },
  475. 'kr': {
  476. //'share':'공유',
  477. 'info': '정보',
  478. 'videos': '동영상',
  479. 'playlist': '재생목록'
  480. },
  481. 'ru': {
  482. //'share':'Поделиться',
  483. 'info': 'Описание',
  484. 'videos': 'Видео',
  485. 'playlist': 'Плейлист'
  486. }
  487. };
  488.  
  489. const svgComments = `<path d="M80 27H12A12 12 90 0 0 0 39v42a12 12 90 0 0 12 12h12v20a2 2 90 0 0 3.4 2L47 93h33a12
  490. 12 90 0 0 12-12V39a12 12 90 0 0-12-12zM20 47h26a2 2 90 1 1 0 4H20a2 2 90 1 1 0-4zm52 28H20a2 2 90 1 1 0-4h52a2 2 90
  491. 1 1 0 4zm0-12H20a2 2 90 1 1 0-4h52a2 2 90 1 1 0 4zm36-58H40a12 12 90 0 0-12 12v6h52c9 0 16 7 16 16v42h0v4l7 7a2 2 90
  492. 0 0 3-1V71h2a12 12 90 0 0 12-12V17a12 12 90 0 0-12-12z"/>`.trim();
  493.  
  494. const svgVideos = `<path d="M89 10c0-4-3-7-7-7H7c-4 0-7 3-7 7v70c0 4 3 7 7 7h75c4 0 7-3 7-7V10zm-62 2h13v10H27V12zm-9
  495. 66H9V68h9v10zm0-56H9V12h9v10zm22 56H27V68h13v10zm-3-25V36c0-2 2-3 4-2l12 8c2 1 2 4 0 5l-12 8c-2 1-4 0-4-2zm25
  496. 25H49V68h13v10zm0-56H49V12h13v10zm18 56h-9V68h9v10zm0-56h-9V12h9v10z"/>`.trim();
  497.  
  498. const svgInfo = `<path d="M30 0C13.3 0 0 13.3 0 30s13.3 30 30 30 30-13.3 30-30S46.7 0 30 0zm6.2 46.6c-1.5.5-2.6
  499. 1-3.6 1.3a10.9 10.9 0 0 1-3.3.5c-1.7 0-3.3-.5-4.3-1.4a4.68 4.68 0 0 1-1.6-3.6c0-.4.2-1 .2-1.5a20.9 20.9 90 0 1
  500. .3-2l2-6.8c.1-.7.3-1.3.4-1.9a8.2 8.2 90 0 0 .3-1.6c0-.8-.3-1.4-.7-1.8s-1-.5-2-.5a4.53 4.53 0 0 0-1.6.3c-.5.2-1
  501. .2-1.3.4l.6-2.1c1.2-.5 2.4-1 3.5-1.3s2.3-.6 3.3-.6c1.9 0 3.3.6 4.3 1.3s1.5 2.1 1.5 3.5c0 .3 0 .9-.1 1.6a10.4 10.4
  502. 90 0 1-.4 2.2l-1.9 6.7c-.2.5-.2 1.1-.4 1.8s-.2 1.3-.2 1.6c0 .9.2 1.6.6 1.9s1.1.5 2.1.5a6.1 6.1 90 0 0 1.5-.3 9 9 90
  503. 0 0 1.4-.4l-.6 2.2zm-3.8-35.2a1 1 0 010 8.6 1 1 0 010-8.6z"/>`.trim();
  504.  
  505. const svgPlayList = `<path d="M0 3h12v2H0zm0 4h12v2H0zm0 4h8v2H0zm16 0V7h-2v4h-4v2h4v4h2v-4h4v-2z"/>`.trim();
  506.  
  507. const svgDiag1 = `<svg stroke="currentColor" fill="none"><path d="M8 2h2v2M7 5l3-3m-6 8H2V8m0 2l3-3"/></svg>`;
  508. const svgDiag2 = `<svg stroke="currentColor" fill="none"><path d="M7 3v2h2M7 5l3-3M5 9V7H3m-1 3l3-3"/></svg>`;
  509.  
  510.  
  511. const getGMT = () => {
  512. let m = new Date('2023-01-01T00:00:00Z');
  513. return m.getDate() === 1 ? `+${m.getHours()}` : `-${24 - m.getHours()}`;
  514. };
  515.  
  516. function getWord(tag) {
  517. return langWords[pageLang][tag] || langWords['en'][tag] || '';
  518. }
  519.  
  520. const svgElm = (w, h, vw, vh, p, m) => `<svg${m ? ` class=${m}` : ''} width="${w}" height="${h}" viewBox="0 0 ${vw} ${vh}" preserveAspectRatio="xMidYMid meet">${p}</svg>`
  521.  
  522. let hiddenTabsByUserCSS = 0;
  523.  
  524. function getTabsHTML() {
  525.  
  526. const sTabBtnVideos = `${svgElm(16, 16, 90, 90, svgVideos)}<span>${getWord('videos')}</span>`;
  527. const sTabBtnInfo = `${svgElm(16, 16, 60, 60, svgInfo)}<span>${getWord('info')}</span>`;
  528. const sTabBtnPlayList = `${svgElm(16, 16, 20, 20, svgPlayList)}<span>${getWord('playlist')}</span>`;
  529.  
  530. let str1 = `
  531. <paper-ripple class="style-scope yt-icon-button">
  532. <div id="background" class="style-scope paper-ripple" style="opacity:0;"></div>
  533. <div id="waves" class="style-scope paper-ripple"></div>
  534. </paper-ripple>
  535. `;
  536.  
  537. let str_fbtns = `
  538. <div class="font-size-right">
  539. <div class="font-size-btn font-size-plus" tyt-di="8rdLQ">
  540. <svg width="12" height="12" viewbox="0 0 50 50" preserveAspectRatio="xMidYMid meet"
  541. stroke="currentColor" stroke-width="6" stroke-linecap="round" vector-effect="non-scaling-size">
  542. <path d="M12 25H38M25 12V38"/>
  543. </svg>
  544. </div><div class="font-size-btn font-size-minus" tyt-di="8rdLQ">
  545. <svg width="12" height="12" viewbox="0 0 50 50" preserveAspectRatio="xMidYMid meet"
  546. stroke="currentColor" stroke-width="6" stroke-linecap="round" vector-effect="non-scaling-size">
  547. <path d="M12 25h26"/>
  548. </svg>
  549. </div>
  550. </div>
  551. `.replace(/[\r\n]+/g, '');
  552.  
  553. const str_tabs = [
  554. `<a id="tab-btn1" tyt-di="q9Kjc" tyt-tab-content="#tab-info" class="tab-btn${(hiddenTabsByUserCSS & 1) === 1 ? ' tab-btn-hidden' : ''}">${sTabBtnInfo}${str1}${str_fbtns}</a>`,
  555. `<a id="tab-btn3" tyt-di="q9Kjc" tyt-tab-content="#tab-comments" class="tab-btn${(hiddenTabsByUserCSS & 2) === 2 ? ' tab-btn-hidden' : ''}">${svgElm(16, 16, 120, 120, svgComments)}<span id="tyt-cm-count"></span>${str1}${str_fbtns}</a>`,
  556. `<a id="tab-btn4" tyt-di="q9Kjc" tyt-tab-content="#tab-videos" class="tab-btn${(hiddenTabsByUserCSS & 4) === 4 ? ' tab-btn-hidden' : ''}">${sTabBtnVideos}${str1}${str_fbtns}</a>`,
  557. `<a id="tab-btn5" tyt-di="q9Kjc" tyt-tab-content="#tab-list" class="tab-btn tab-btn-hidden">${sTabBtnPlayList}${str1}${str_fbtns}</a>`
  558. ].join('');
  559.  
  560. let addHTML = `
  561. <div id="right-tabs">
  562. <tabview-view-pos-thead></tabview-view-pos-thead>
  563. <header>
  564. <div id="material-tabs">
  565. ${str_tabs}
  566. </div>
  567. </header>
  568. <div class="tab-content">
  569. <div id="tab-info" class="tab-content-cld tab-content-hidden" tyt-hidden userscript-scrollbar-render></div>
  570. <div id="tab-comments" class="tab-content-cld tab-content-hidden" tyt-hidden userscript-scrollbar-render></div>
  571. <div id="tab-videos" class="tab-content-cld tab-content-hidden" tyt-hidden userscript-scrollbar-render></div>
  572. <div id="tab-list" class="tab-content-cld tab-content-hidden" tyt-hidden userscript-scrollbar-render></div>
  573. </div>
  574. </div>
  575. `;
  576.  
  577. return addHTML;
  578.  
  579. }
  580.  
  581.  
  582. function getLang() {
  583.  
  584. let lang = 'en';
  585. let htmlLang = ((document || 0).documentElement || 0).lang || '';
  586. switch (htmlLang) {
  587. case 'en':
  588. case 'en-GB':
  589. lang = 'en';
  590. break;
  591. case 'de':
  592. case 'de-DE':
  593. lang = 'du';
  594. break;
  595. case 'fr':
  596. case 'fr-CA':
  597. case 'fr-FR':
  598. lang = 'fr';
  599. break;
  600. case 'zh-Hant':
  601. case 'zh-Hant-HK':
  602. case 'zh-Hant-TW':
  603. lang = 'tw';
  604. break;
  605. case 'zh-Hans':
  606. case 'zh-Hans-CN':
  607. lang = 'cn';
  608. break;
  609. case 'ja':
  610. case 'ja-JP':
  611. lang = 'jp';
  612. break;
  613. case 'ko':
  614. case 'ko-KR':
  615. lang = 'kr';
  616. break;
  617. case 'ru':
  618. case 'ru-RU':
  619. lang = 'ru';
  620. break;
  621. default:
  622. lang = 'en';
  623. }
  624.  
  625. return lang;
  626.  
  627. }
  628.  
  629. function getLangForPage() {
  630.  
  631. let lang = getLang();
  632.  
  633. if (langWords[lang]) pageLang = lang; else pageLang = 'en';
  634.  
  635. }
  636.  
  637. /** @type {Object.<string, number>} */
  638. const _locks = {}
  639.  
  640. const lockGet = new Proxy(_locks,
  641. {
  642. get(target, prop) {
  643. return (target[prop] || 0);
  644. },
  645. set(target, prop, val) {
  646. return true;
  647. }
  648. }
  649. );
  650.  
  651. const lockSet = new Proxy(_locks,
  652. {
  653. get(target, prop) {
  654. if (target[prop] > 1e9) target[prop] = 9;
  655. return (target[prop] = (target[prop] || 0) + 1);
  656. },
  657. set(target, prop, val) {
  658. return true;
  659. }
  660. }
  661. );
  662.  
  663. // note: xxxxxxxxxAsyncLock is not expected for calling multiple time in a short period.
  664. // it is just to split the process into microTasks.
  665.  
  666. const videosElementProvidedPromise = new PromiseExternal();
  667. const navigateFinishedPromise = new PromiseExternal();
  668.  
  669. let isRightTabsInserted = false;
  670. const rightTabsProvidedPromise = new PromiseExternal();
  671.  
  672. const infoExpanderElementProvidedPromise = new PromiseExternal();
  673.  
  674.  
  675. const funcCanCollapse = function (s) {
  676. if (!s) return;
  677. this.canToggle = this.shouldUseNumberOfLines && (this.alwaysCollapsed || this.collapsed)
  678. ? this.alwaysToggleable || this.$.content.offsetHeight < this.$.content.scrollHeight
  679. : this.alwaysToggleable || this.$.content.scrollHeight > this.collapsedHeight
  680. };
  681.  
  682. const aoChatAttrChangeFn = async (lockId) => {
  683. if (lockGet['aoChatAttrAsyncLock'] !== lockId) return;
  684.  
  685. const chatElm = elements.chat;
  686. const ytdFlexyElm = elements.flexy;
  687. // console.log(1882, chatElm, ytdFlexyElm)
  688. if (chatElm && ytdFlexyElm) {
  689.  
  690. const isChatCollapsed = chatElm.hasAttribute000('collapsed');
  691. if (isChatCollapsed) {
  692.  
  693. ytdFlexyElm.setAttribute111('tyt-chat-collapsed', '')
  694. } else {
  695.  
  696. ytdFlexyElm.removeAttribute000('tyt-chat-collapsed')
  697. }
  698.  
  699. ytdFlexyElm.setAttribute111('tyt-chat', isChatCollapsed ? '-' : '+');
  700.  
  701. }
  702. };
  703.  
  704. // const aoInfoAttrChangeFn = async (lockId) => {
  705. // if (lockGet['aoInfoAttrAsyncLock'] !== lockId) return;
  706. // };
  707.  
  708. // const zoInfoAttrChangeFn = async (lockId) => {
  709. // if (lockGet['zoInfoAttrAsyncLock'] !== lockId) return;
  710. // };
  711.  
  712. const aoPlayListAttrChangeFn = async (lockId) => {
  713. if (lockGet['aoPlayListAttrAsyncLock'] !== lockId) return;
  714.  
  715. const playlistElm = elements.playlist;
  716. const ytdFlexyElm = elements.flexy;
  717. // console.log(1882, chatElm, ytdFlexyElm)
  718. if (playlistElm && ytdFlexyElm) {
  719. if (playlistElm.hasAttribute000('collapsed')) {
  720. ytdFlexyElm.removeAttribute000('tyt-playlist-expanded')
  721. } else {
  722.  
  723. ytdFlexyElm.setAttribute111('tyt-playlist-expanded', '')
  724. }
  725. }else if(ytdFlexyElm){
  726.  
  727. ytdFlexyElm.removeAttribute000('tyt-playlist-expanded')
  728. }
  729. };
  730.  
  731. const aoChat = new MutationObserver(()=>{
  732. Promise.resolve(lockSet['aoChatAttrAsyncLock']).then(aoChatAttrChangeFn).catch(console.warn);
  733. });
  734.  
  735. // const aoInfo = new MutationObserver(()=>{
  736. // Promise.resolve(lockSet['aoInfoAttrAsyncLock']).then(aoInfoAttrChangeFn).catch(console.warn);
  737. // });
  738.  
  739. // const zoInfo = new MutationObserver(()=>{
  740. // Promise.resolve(lockSet['zoInfoAttrAsyncLock']).then(zoInfoAttrChangeFn).catch(console.warn);
  741. // });
  742.  
  743. const aoPlayList = new MutationObserver(()=>{
  744. Promise.resolve(lockSet['aoPlayListAttrAsyncLock']).then(aoPlayListAttrChangeFn).catch(console.warn);
  745. });
  746.  
  747. const aoComment = new MutationObserver(async (mutations) => {
  748. const commentsArea = elements.comments;
  749. const ytdFlexyElm = elements.flexy;
  750.  
  751. //tyt-comments-video-id //tyt-comments-data-status // hidden
  752. if (!commentsArea) return;
  753. let bfHidden = false;
  754. let bfCommentsVideoId = false;
  755. let bfCommentDisabled = false;
  756. for (const mutation of mutations) {
  757. if (mutation.attributeName === 'hidden' && mutation.target === commentsArea) {
  758. bfHidden = true;
  759. } else if (mutation.attributeName === 'tyt-comments-video-id' && mutation.target === commentsArea) {
  760. bfCommentsVideoId = true;
  761. } else if (mutation.attributeName === 'tyt-comments-data-status' && mutation.target === commentsArea) {
  762. bfCommentDisabled = true;
  763. }
  764. }
  765.  
  766. if (bfHidden) {
  767.  
  768. if (!commentsArea.hasAttribute000('hidden')) {
  769. Promise.resolve(commentsArea).then(eventMap['settingCommentsVideoId']).catch(console.warn);
  770. }
  771.  
  772. Promise.resolve(lockSet['removeKeepCommentsScrollerLock']).then(removeKeepCommentsScroller).catch(console.warn);
  773. }
  774.  
  775. if ((bfHidden || bfCommentsVideoId || bfCommentDisabled) && ytdFlexyElm) {
  776.  
  777. const commentsDataStatus = +commentsArea.getAttribute000('tyt-comments-data-status');
  778. if (commentsDataStatus === 2) {
  779. ytdFlexyElm.setAttribute111('tyt-comment-disabled', '')
  780. } else if (commentsDataStatus === 1) {
  781. ytdFlexyElm.removeAttribute000('tyt-comment-disabled')
  782. }
  783.  
  784. Promise.resolve(lockSet['checkCommentsShouldBeHiddenLock']).then(eventMap['checkCommentsShouldBeHidden']).catch(console.warn);
  785.  
  786.  
  787. const lockId = lockSet['rightTabReadyLock01'];
  788. await rightTabsProvidedPromise.then();
  789. if (lockGet['rightTabReadyLock01'] !== lockId) return;
  790. if (elements.comments !== commentsArea) return;
  791. if (commentsArea.isConnected === false) return;
  792. // console.log(7932, 'comments');
  793.  
  794. if (commentsArea.closest('#tab-comments')) {
  795. const shouldTabVisible = !commentsArea.closest('[hidden]');
  796. document.querySelector('[tyt-tab-content="#tab-comments"]').classList.toggle('tab-btn-hidden', !shouldTabVisible);
  797. }
  798.  
  799. }
  800.  
  801.  
  802. });
  803.  
  804. const ioComment = new IntersectionObserver((entries) => {
  805.  
  806. for (const entry of entries) {
  807. const target = entry.target;
  808. const cnt = insp(target);
  809. if (entry.isIntersecting && target instanceof HTMLElement_ && typeof cnt.calculateCanCollapse === 'function') {
  810. lockSet['removeKeepCommentsScrollerLock'];
  811. cnt.calculateCanCollapse(true);
  812. target.setAttribute111('io-intersected', '');
  813. const ytdFlexyElm = elements.flexy;
  814. if (ytdFlexyElm && !ytdFlexyElm.hasAttribute000('keep-comments-scroller')) {
  815. ytdFlexyElm.setAttribute111('keep-comments-scroller', '');
  816. }
  817. } else if (target.hasAttribute000('io-intersected')) {
  818.  
  819. target.removeAttribute000('io-intersected');
  820. }
  821. }
  822.  
  823. }, {
  824. threshold: [0],
  825. rootMargin: "32px" // enlarging viewport for getting intersection earlier
  826. });
  827.  
  828.  
  829. let bFixForResizedTabLater = false;
  830. let lastRoRightTabsWidth = 0;
  831. const roRightTabs = new ResizeObserver((entries) => {
  832. const entry = entries[entries.length - 1];
  833. const width = Math.round(entry.borderBoxSize.inlineSize);
  834. if (lastRoRightTabsWidth !== width) {
  835. lastRoRightTabsWidth = width;
  836. if ((tabAStatus & 2) === 2) {
  837. bFixForResizedTabLater = false;
  838. Promise.resolve(1).then(eventMap['fixForTabDisplay']);
  839. } else {
  840. bFixForResizedTabLater = true;
  841. }
  842. }
  843. // console.log('resize')
  844. });
  845.  
  846. const switchToTab = (activeLink) => {
  847.  
  848. if (typeof activeLink === 'string') {
  849. activeLink = document.querySelector(`a[tyt-tab-content="${activeLink}"]`) || null;
  850. }
  851.  
  852. const ytdFlexyElm = elements.flexy;
  853.  
  854.  
  855. const links = document.querySelectorAll('#material-tabs a[tyt-tab-content]');
  856.  
  857. //console.log(701, activeLink)
  858.  
  859. for (const link of links) {
  860. const content = document.querySelector(link.getAttribute000('tyt-tab-content'));
  861. if (link && content) {
  862. if (link !== activeLink) {
  863. link.classList.remove("active");
  864. content.classList.add("tab-content-hidden");
  865. if (!content.hasAttribute000("tyt-hidden")) {
  866. content.setAttribute111("tyt-hidden", ""); // for https://greasyfork.org/en/scripts/456108
  867. }
  868. } else {
  869. link.classList.add("active");
  870. if (content.hasAttribute000("tyt-hidden")) {
  871. content.removeAttribute000("tyt-hidden"); // for https://greasyfork.org/en/scripts/456108
  872. }
  873. content.classList.remove("tab-content-hidden");
  874. }
  875. }
  876. }
  877.  
  878. const switchingTo = activeLink ? activeLink.getAttribute000('tyt-tab-content') : '';
  879. if (switchingTo) {
  880. lastTab = lastPanel = switchingTo
  881. }
  882.  
  883. if (ytdFlexyElm.getAttribute000('tyt-chat') === '') ytdFlexyElm.removeAttribute000('tyt-chat');
  884. ytdFlexyElm.setAttribute111('tyt-tab', switchingTo);
  885.  
  886. if (switchingTo) {
  887. bFixForResizedTabLater = false;
  888. Promise.resolve(0).then(eventMap['fixForTabDisplay']);
  889. }
  890.  
  891. }
  892.  
  893. let tabAStatus = 0;
  894. const calculationFn = (r = 0, flag) => {
  895. const ytdFlexyElm = elements.flexy;
  896. if (!ytdFlexyElm) return r;
  897. if (flag & 1) {
  898. r |= 1;
  899. if (!ytdFlexyElm.hasAttribute000('theater')) r -= 1;
  900. }
  901. if (flag & 2) {
  902. r |= 2;
  903. if (!ytdFlexyElm.getAttribute000('tyt-tab')) r -= 2;
  904. }
  905. if (flag & 4) {
  906. r |= 4;
  907. if (ytdFlexyElm.getAttribute000('tyt-chat') !== '-') r -= 4;
  908. }
  909. if (flag & 8) {
  910. r |= 8;
  911. if (ytdFlexyElm.getAttribute000('tyt-chat') !== '+') r -= 8;
  912. }
  913. if (flag & 16) {
  914. r |= 16;
  915. if (!ytdFlexyElm.hasAttribute000('is-two-columns_')) r -= 16;
  916. }
  917. if (flag & 32) {
  918. r |= 32;
  919. if (!ytdFlexyElm.hasAttribute000('tyt-egm-panel_')) r -= 32;
  920. }
  921. if (flag & 64) {
  922.  
  923. r |= 64;
  924. if (!document.fullscreenElement) r -= 64;
  925. }
  926.  
  927. if (flag & 128) {
  928. r |= 128;
  929. if (!ytdFlexyElm.hasAttribute000('tyt-playlist-expanded')) r -= 128;
  930. }
  931. return r;
  932.  
  933. }
  934.  
  935. function isTheater() {
  936. const ytdFlexyElm = elements.flexy;
  937. return (ytdFlexyElm && ytdFlexyElm.hasAttribute000('theater'))
  938. }
  939.  
  940. function ytBtnSetTheater() {
  941. if (!isTheater()) {
  942. const sizeBtn = document.querySelector('ytd-watch-flexy #ytd-player button.ytp-size-button')
  943. if (sizeBtn) sizeBtn.click();
  944. }
  945. }
  946.  
  947. function ytBtnCancelTheater() {
  948. if (isTheater()) {
  949. const sizeBtn = document.querySelector('ytd-watch-flexy #ytd-player button.ytp-size-button')
  950. if (sizeBtn) sizeBtn.click();
  951. }
  952. }
  953.  
  954.  
  955. function ytBtnExpandChat() {
  956. let button = document.querySelector('ytd-live-chat-frame#chat[collapsed] > .ytd-live-chat-frame#show-hide-button')
  957. if (button) {
  958. button =
  959. button.querySelector000('div.yt-spec-touch-feedback-shape') ||
  960. button.querySelector000('ytd-toggle-button-renderer');
  961. if (button) button.click();
  962. }
  963. }
  964.  
  965. function ytBtnCollapseChat() {
  966. let button = document.querySelector('ytd-live-chat-frame#chat:not([collapsed]) > .ytd-live-chat-frame#show-hide-button')
  967. if (button) {
  968. button =
  969. button.querySelector000('div.yt-spec-touch-feedback-shape') ||
  970. button.querySelector000('ytd-toggle-button-renderer');
  971. if (button) button.click();
  972. }
  973. }
  974.  
  975. function ytBtnEgmPanelCore(arr) {
  976.  
  977. if (!arr) return
  978. if (!('length' in arr)) arr = [arr]
  979.  
  980. const ytdFlexyElm = elements.flexy;
  981. if (!ytdFlexyElm) return;
  982.  
  983. let actions = []
  984.  
  985. for (const entry of arr) {
  986.  
  987. if (!entry) continue;
  988.  
  989. let panelId = entry.panelId
  990.  
  991. let toHide = entry.toHide
  992. let toShow = entry.toShow
  993.  
  994. if (toHide === true && !toShow) {
  995.  
  996. actions.push({
  997. "changeEngagementPanelVisibilityAction": {
  998. "targetId": panelId,
  999. "visibility": "ENGAGEMENT_PANEL_VISIBILITY_HIDDEN"
  1000. }
  1001. })
  1002.  
  1003. } else if (toShow === true && !toHide) {
  1004.  
  1005. actions.push({
  1006. "showEngagementPanelEndpoint": {
  1007. "panelIdentifier": panelId
  1008. }
  1009. })
  1010.  
  1011. }
  1012.  
  1013. if (actions.length > 0) {
  1014. const cnt = insp(ytdFlexyElm);
  1015.  
  1016. cnt.resolveCommand(
  1017. {
  1018. "signalServiceEndpoint": {
  1019. "signal": "CLIENT_SIGNAL",
  1020. "actions": actions
  1021. }
  1022. },
  1023.  
  1024. {},
  1025. false);
  1026. }
  1027. actions = null;
  1028.  
  1029. }
  1030. }
  1031.  
  1032. /*
  1033. function ytBtnCloseEngagementPanel( s) {
  1034. //ePanel.setAttribute('visibility',"ENGAGEMENT_PANEL_VISIBILITY_HIDDEN");
  1035. let panelId = s.getAttribute('target-id')
  1036. scriptletDeferred.debounce(() => {
  1037. document.dispatchEvent(new CustomEvent('tyt-engagement-panel-visibility-change', {
  1038. detail: {
  1039. panelId,
  1040. toHide: true
  1041. }
  1042. }))
  1043. })
  1044. }
  1045. function ytBtnCloseEngagementPanels() {
  1046. if (isEngagementPanelExpanded()) {
  1047. for (const s of document.querySelectorAll(
  1048. `ytd-watch-flexy[flexy][tyt-tab] #panels.ytd-watch-flexy ytd-engagement-panel-section-list-renderer[target-id][visibility]:not([hidden])`
  1049. )) {
  1050. if (s.getAttribute('visibility') == "ENGAGEMENT_PANEL_VISIBILITY_EXPANDED") ytBtnCloseEngagementPanel(s);
  1051. }
  1052. }
  1053. }
  1054. */
  1055.  
  1056.  
  1057. function ytBtnCloseEngagementPanels() {
  1058.  
  1059. const actions = [];
  1060. for (const panelElm of document.querySelectorAll(
  1061. `ytd-watch-flexy[flexy][tyt-tab] #panels.ytd-watch-flexy ytd-engagement-panel-section-list-renderer[target-id][visibility]:not([hidden])`
  1062. )) {
  1063. if (panelElm.getAttribute('visibility') == "ENGAGEMENT_PANEL_VISIBILITY_EXPANDED" && !panelElm.closest('[hidden]')) {
  1064. actions.push({
  1065. panelId: panelElm.getAttribute000('target-id'),
  1066. toHide: true
  1067. });
  1068. }
  1069. }
  1070. ytBtnEgmPanelCore(actions);
  1071. }
  1072.  
  1073.  
  1074. function ytBtnOpenPlaylist() {
  1075.  
  1076. const cnt = insp(elements.playlist);
  1077. if (cnt && typeof cnt.collapsed === 'boolean') {
  1078. cnt.collapsed = false;
  1079. }
  1080. }
  1081. function ytBtnClosePlaylist() {
  1082.  
  1083. const cnt = insp(elements.playlist);
  1084. if (cnt && typeof cnt.collapsed === 'boolean') {
  1085. cnt.collapsed = true;
  1086. }
  1087. }
  1088.  
  1089. const updateChatLocation498 = function () {
  1090. /*
  1091. updateChatLocation: function() {
  1092. if (this.is !== "ytd-watch-grid" && y("web_watch_theater_chat")) {
  1093. var a = T(this.hostElement).querySelector("#chat-container")
  1094. , b = this.theater && (!this.fullscreen || y("web_watch_fullscreen_panels"));
  1095. this.watchWhileWindowSizeSufficient && this.liveChatPresentAndExpanded && b ? y("web_watch_theater_chat_beside_player") ? (b = T(this.hostElement).querySelector("#panels-full-bleed-container"),
  1096. (a == null ? void 0 : a.parentElement) !== b && b.append(a),
  1097. this.panelsBesidePlayer = !0) : y("web_watch_theater_fixed_chat") && (b = T(this.hostElement).querySelector("#columns"),
  1098. (a == null ? void 0 : a.parentElement) !== b && b.append(a),
  1099. this.fixedPanels = !0) : (y("web_watch_theater_chat_beside_player") ? this.panelsBesidePlayer = !1 : y("web_watch_theater_fixed_chat") && (this.fixedPanels = !1),
  1100. b = T(this.hostElement).querySelector("#playlist"),
  1101. a && b ? Fh(a, b) : Gm(new zk("Missing element when updating chat location",{
  1102. "chatContainer defined": !!a,
  1103. "playlist defined": !!b
  1104. })));
  1105. this.updatePageMediaQueries();
  1106. this.schedulePlayerSizeUpdate_()
  1107. }
  1108. },
  1109. */
  1110.  
  1111. // console.log('updateChatLocation498')
  1112. if (this.is !== "ytd-watch-grid") {
  1113. this.updatePageMediaQueries();
  1114. this.schedulePlayerSizeUpdate_()
  1115. }
  1116.  
  1117. }
  1118.  
  1119. const mirrorNodeWS = new WeakMap();
  1120.  
  1121. /*
  1122. const infoFix = () => {
  1123. const infoExpander = elements.infoExpander;
  1124. const ytdFlexyElm = elements.flexy;
  1125. if (!infoExpander || !ytdFlexyElm) return;
  1126. console.log(386, infoExpander, infoExpander.matches('#tab-info > [class]'))
  1127. if (!infoExpander.matches('#tab-info > [class]')) return;
  1128. // const elms = [...document.querySelectorAll('ytd-watch-metadata.ytd-watch-flexy div[slot="extra-content"], ytd-watch-metadata.ytd-watch-flexy ytd-metadata-row-container-renderer')].filter(elm=>{
  1129. // if(elm.parentNode.closest('div[slot="extra-content"], ytd-metadata-row-container-renderer')) return false;
  1130. // return true;
  1131. // });
  1132. const requireElements = [...document.querySelectorAll('ytd-watch-metadata.ytd-watch-flexy div[slot="extra-content"] > *, ytd-watch-metadata.ytd-watch-flexy #extra-content > *')].filter(elm => {
  1133. return typeof elm.is == 'string'
  1134. }).map(elm => {
  1135. const is = elm.is;
  1136. while (elm instanceof HTMLElement_) {
  1137. const q = [...elm.querySelectorAll(is)].filter(e => insp(e).data);
  1138. if (q.length >= 1) return q[0];
  1139. elm = elm.parentNode;
  1140. }
  1141. }).filter(elm => !!elm && typeof elm.is === 'string');
  1142. console.log(requireElements)
  1143. const source = requireElements.map(entry=>({
  1144. data: insp(entry).data,
  1145. tag: insp(entry).is,
  1146. elm: entry
  1147. }))
  1148. if (!document.querySelector('noscript#aythl')) {
  1149. const noscript = document.createElement('noscript')
  1150. noscript.id = 'aythl';
  1151. ytdFlexyElm.insertBefore000(noscript, ytdFlexyElm.firstChild);
  1152. }
  1153. const noscript = document.querySelector('noscript#aythl');
  1154. const clones = new Set();
  1155. for (const {data, tag, elm} of source) {
  1156. // const cloneNode = document.createElement(tag);
  1157. let cloneNode = elm.cloneNode(true);
  1158. // noscript.appendChild(cloneNode);
  1159. // insp(cloneNode).data = null;
  1160. insp(cloneNode).data = data;
  1161. source.clone = cloneNode;
  1162. clones.add(cloneNode);
  1163. }
  1164. // const elms = [...document.querySelectorAll('ytd-watch-metadata.ytd-watch-flexy div[slot="extra-content"]')].filter(elm => {
  1165. // if (elm.parentNode.closest('div[slot="extra-content"], ytd-metadata-row-container-renderer')) return false;
  1166. // return true;
  1167. // });
  1168. // let arr = [];
  1169. // for(const elm of elms){
  1170. // if(elm.hasAttribute('slot')) arr.push(...elm.childNodes);
  1171. // else arr.push(elm);
  1172. // }
  1173. // arr = arr.filter(e=>e && e.nodeType === 1);
  1174. // console.log(386,arr)
  1175. // const clones = arr.map(e=>e.cloneNode(true));
  1176. // for(let node = infoExpander.nextSibling; node instanceof Node; node = node.nextSibling) node.remove();
  1177. // infoExpander.parentNode.assignChildern111(null, infoExpander, [...clones]);
  1178. let removal = [];
  1179. for(let node = infoExpander.nextSibling; node instanceof Node; node = node.nextSibling)removal.push(node);
  1180. for(const node of removal) node.remove();
  1181. for(const node of clones) infoExpander.parentNode.appendChild(node);
  1182. for (const {data, tag, elm, clone} of source) {
  1183. insp(clone).data = null;
  1184. insp(clone).data = data;
  1185. }
  1186. // console.log(infoExpander.parentNode.childNodes)
  1187. }
  1188. */
  1189.  
  1190. const dummyNode = document.createElement('noscript');
  1191.  
  1192. // const __j4838__ = Symbol();
  1193. const __j4836__ = Symbol();
  1194. const __j5744__ = Symbol(); // original element
  1195. const __j5733__ = Symbol(); // __lastChanged__
  1196.  
  1197. const monitorDataChangedByDOMMutation = async function (mutations) {
  1198.  
  1199. const nodeWR = this;
  1200. const node = kRef(nodeWR);
  1201. if (!node) return;
  1202.  
  1203. const cnt = insp(node);
  1204. const __lastChanged__ = cnt[__j5733__];
  1205.  
  1206.  
  1207. const val = cnt.data ? (cnt.data[__j4836__] || 1) : 0;
  1208.  
  1209. if (__lastChanged__ !== val) {
  1210. cnt[__j5733__] = val > 0 ? (cnt.data[__j4836__] = Date.now()) : 0;
  1211.  
  1212. await Promise.resolve(); // required for making sufficient delay for data rendering
  1213. attributeInc(node, 'tyt-data-change-counter'); // next macro task
  1214.  
  1215. }
  1216.  
  1217. }
  1218.  
  1219. const moChangeReflection = function (mutations) {
  1220.  
  1221. const nodeWR = this;
  1222. const node = kRef(nodeWR);
  1223. if (!node) return;
  1224. const originElement = kRef(node[__j5744__] || null) || null;
  1225. if (!originElement) return;
  1226.  
  1227. const cnt = insp(node);
  1228. const oriCnt = insp(originElement);
  1229.  
  1230. if (mutations) {
  1231.  
  1232. let bfDataChangeCounter = false;
  1233. for (const mutation of mutations) {
  1234.  
  1235. if (mutation.attributeName === 'tyt-clone-refresh-count' && mutation.target === originElement) {
  1236. bfDataChangeCounter = true;
  1237. } else if (mutation.attributeName === 'tyt-data-change-counter' && mutation.target === originElement) {
  1238. bfDataChangeCounter = true;
  1239. }
  1240. }
  1241. if (bfDataChangeCounter && oriCnt.data) {
  1242. node.replaceWith(dummyNode);
  1243. cnt.data = Object.assign({}, oriCnt.data);
  1244. dummyNode.replaceWith(node);
  1245. }
  1246.  
  1247. }
  1248. }
  1249.  
  1250. /*
  1251. const moChangeReflection = async function (mutations) {
  1252. const nodeWR = this;
  1253. const node = kRef(nodeWR);
  1254. if (!node) return;
  1255. const originElement = kRef(node[__j5744__] || null) || null;
  1256. if (!originElement) return;
  1257. const cnt = insp(node);
  1258. const oriCnt = insp(originElement);
  1259. if(mutations){
  1260. let bfDataChangeCounter = false;
  1261. for (const mutation of mutations) {
  1262. if (mutation.attributeName === 'tyt-data-change-counter' && mutation.target === originElement) {
  1263. bfDataChangeCounter = true;
  1264. }
  1265. }
  1266. if(bfDataChangeCounter && oriCnt.data){
  1267. node.replaceWith(dummyNode);
  1268. cnt.data = Object.assign({}, oriCnt.data);
  1269. dummyNode.replaceWith(node);
  1270. }
  1271. }
  1272. // console.log(8348, originElement)
  1273. if (cnt.isAttached === false) {
  1274. // do nothing
  1275. // don't call infoFix() as it shall be only called in ytd-expander::attached and yt-navigate-finish
  1276. } else if (oriCnt.isAttached === false && cnt.isAttached === true) {
  1277. if (node.isConnected && node.parentNode instanceof HTMLElement_) {
  1278. node.parentNode.removeChild(node);
  1279. } else {
  1280. node.remove();
  1281. }
  1282. if (oriCnt.data !== null) {
  1283. cnt.data = null;
  1284. }
  1285. } else if (oriCnt.isAttached === true && cnt.isAttached === true) {
  1286. if (!oriCnt.data) {
  1287. if(cnt.data){
  1288. cnt.data = null;
  1289. }
  1290. } else if (!cnt.data || oriCnt.data[__j4838__] !== cnt.data[__j4838__]) {
  1291. oriCnt.data[__j4838__] = Date.now();
  1292. await Promise.resolve(); // required for making sufficient delay for data rendering
  1293. attributeInc(originElement, 'tyt-data-change-counter'); // next macro task
  1294. }
  1295. }
  1296. };
  1297. */
  1298.  
  1299. const attributeInc = (elm, prop) => {
  1300. let v = (+elm.getAttribute000(prop) || 0) + 1;
  1301. if (v > 1e9) v = 9;
  1302. elm.setAttribute000(prop, v);
  1303. return v;
  1304. }
  1305.  
  1306.  
  1307. /**
  1308. * UC[-_a-zA-Z0-9+=.]{22}
  1309. * https://support.google.com/youtube/answer/6070344?hl=en
  1310. * The channel ID is the 24 character alphanumeric string that starts with 'UC' in the channel URL.
  1311. */
  1312.  
  1313. const isChannelId = (x) => {
  1314. if (typeof x === 'string' && x.length === 24) {
  1315. return /UC[-_a-zA-Z0-9+=.]{22}/.test(x);
  1316. }
  1317. return false;
  1318. }
  1319.  
  1320.  
  1321. const infoFix = (lockId) => {
  1322. if (lockId !== null && lockGet['infoFixLock'] !== lockId) return;
  1323. // console.log('((infoFix))')
  1324. const infoExpander = elements.infoExpander;
  1325. const infoContainer = (infoExpander ? infoExpander.parentNode : null) || document.querySelector('#tab-info');
  1326. const ytdFlexyElm = elements.flexy;
  1327. if (!infoContainer || !ytdFlexyElm) return;
  1328. // console.log(386, infoExpander, infoExpander.matches('#tab-info > [class]'))
  1329. if (infoExpander) {
  1330. const match = infoExpander.matches('#tab-info > [class]') || infoExpander.matches('#tab-info > [tyt-main-info]');
  1331. if (!match) return;
  1332. }
  1333. // const elms = [...document.querySelectorAll('ytd-watch-metadata.ytd-watch-flexy div[slot="extra-content"], ytd-watch-metadata.ytd-watch-flexy ytd-metadata-row-container-renderer')].filter(elm=>{
  1334. // if(elm.parentNode.closest('div[slot="extra-content"], ytd-metadata-row-container-renderer')) return false;
  1335. // return true;
  1336. // });
  1337.  
  1338. const requireElements = [...document.querySelectorAll('ytd-watch-metadata.ytd-watch-flexy div[slot="extra-content"] > *, ytd-watch-metadata.ytd-watch-flexy #extra-content > *')].filter(elm => {
  1339. return typeof elm.is == 'string'
  1340. }).map(elm => {
  1341. const is = elm.is;
  1342. while (elm instanceof HTMLElement_) {
  1343. const q = [...elm.querySelectorAll(is)].filter(e => insp(e).data);
  1344. if (q.length >= 1) return q[0];
  1345. elm = elm.parentNode;
  1346. }
  1347. }).filter(elm => !!elm && typeof elm.is === 'string');
  1348. // console.log(9162, requireElements)
  1349.  
  1350. // if (!infoExpander && !requireElements.length) return;
  1351.  
  1352. const source = requireElements.map(entry => {
  1353. const inst = insp(entry);
  1354. return {
  1355. data: inst.data,
  1356. tag: inst.is,
  1357. elm: entry
  1358. };
  1359. });
  1360.  
  1361. let noscript_ = document.querySelector('noscript#aythl');
  1362. if (!noscript_) {
  1363. noscript_ = document.createElement('noscript')
  1364. noscript_.id = 'aythl';
  1365.  
  1366. inPageRearrange = true;
  1367. ytdFlexyElm.insertBefore000(noscript_, ytdFlexyElm.firstChild);
  1368. inPageRearrange = false;
  1369. }
  1370. const noscript = noscript_;
  1371.  
  1372.  
  1373. let requiredUpdate = false;
  1374. const mirrorElmSet = new Set();
  1375. const targetParent = infoContainer;
  1376. for (const { data, tag: tag, elm: s } of source) {
  1377.  
  1378. let mirrorNode = mirrorNodeWS.get(s)
  1379. mirrorNode = mirrorNode ? kRef(mirrorNode) : mirrorNode;
  1380. if (!mirrorNode) {
  1381. const cnt = insp(s);
  1382. const cProto = cnt.constructor.prototype;
  1383.  
  1384. const element = document.createElement(tag);
  1385. noscript.appendChild(element); // appendChild to trigger .attached()
  1386. mirrorNode = element
  1387. mirrorNode[__j5744__] = mWeakRef(s);
  1388.  
  1389. const nodeWR = mWeakRef(mirrorNode);
  1390. // if(!(insp(s)._dataChanged438)){
  1391. // insp(s)._dataChanged438 = async function(){
  1392.  
  1393. // await Promise.resolve(); // required for making sufficient delay for data rendering
  1394. // attributeInc(originElement, 'tyt-data-change-counter'); // next macro task
  1395. // moChangeReflection.call(nodeWR);
  1396. // }
  1397. // }
  1398.  
  1399.  
  1400.  
  1401.  
  1402. new MutationObserver(moChangeReflection.bind(nodeWR)).observe(s, { attributes: true, attributeFilter: ['tyt-clone-refresh-count', 'tyt-data-change-counter'] });
  1403.  
  1404.  
  1405. s.jy8432 = 1;
  1406. if (!(cProto instanceof Node) && !cProto._dataChanged496 && typeof cProto._createPropertyObserver === 'function') {
  1407.  
  1408.  
  1409. cProto._dataChanged496 = function () {
  1410. const cnt = this;
  1411. const node = cnt.hostElement || cnt;
  1412. if (node.jy8432) {
  1413.  
  1414. // console.log('hello _dataChanged496', this.is);
  1415. // await Promise.resolve(); // required for making sufficient delay for data rendering
  1416. attributeInc(node, 'tyt-data-change-counter'); // next macro task
  1417. }
  1418.  
  1419.  
  1420. }
  1421.  
  1422. cProto._createPropertyObserver('data', '_dataChanged496', undefined)
  1423.  
  1424. } else if (!(cProto instanceof Node) && !cProto._dataChanged496 && cProto.useSignals === true && insp(s).signalProxy) {
  1425.  
  1426. const dataSignal = cnt?.signalProxy?.signalCache?.data;
  1427. if (dataSignal && typeof dataSignal.setWithPath === 'function' && !dataSignal.setWithPath573 && !dataSignal.controller573) {
  1428. dataSignal.controller573 = mWeakRef(cnt);
  1429. dataSignal.setWithPath573 = dataSignal.setWithPath;
  1430. dataSignal.setWithPath = function () {
  1431. const cnt = (kRef(this.controller573 || null) || null);
  1432. cnt && typeof cnt._dataChanged496k === 'function' && Promise.resolve(cnt).then(cnt._dataChanged496k).catch(console.warn);
  1433. return this.setWithPath573(...arguments)
  1434. }
  1435. cProto._dataChanged496 = function () {
  1436. const cnt = this;
  1437. const node = cnt.hostElement || cnt;
  1438. if (node.jy8432) {
  1439. // console.log('hello _dataChanged496', this.is);
  1440. // await Promise.resolve(); // required for making sufficient delay for data rendering
  1441. attributeInc(node, 'tyt-data-change-counter'); // next macro task
  1442. }
  1443. }
  1444. cProto._dataChanged496k = ((cnt) => cnt._dataChanged496());
  1445.  
  1446. }
  1447.  
  1448. }
  1449.  
  1450.  
  1451. if (!cProto._dataChanged496) {
  1452.  
  1453. new MutationObserver(monitorDataChangedByDOMMutation.bind(mirrorNode[__j5744__])).observe(s, { attributes: true, childList: true, subtree: true });
  1454.  
  1455. }
  1456.  
  1457.  
  1458. // new MutationObserver(moChangeReflection.bind(nodeWR)).observe(s, {attributes: true, childList: true, subtree: true});
  1459.  
  1460. mirrorNodeWS.set(s, nodeWR);
  1461. requiredUpdate = true;
  1462. } else {
  1463.  
  1464. if (mirrorNode.parentNode !== targetParent) {
  1465. requiredUpdate = true;
  1466. }
  1467. }
  1468. if (!requiredUpdate) {
  1469. const cloneNodeCnt = insp(mirrorNode);
  1470. if (cloneNodeCnt.data !== data) {
  1471. // if(mirrorNode.parentNode !== noscript){
  1472. // noscript.appendChild(mirrorNode);
  1473. // }
  1474. // mirrorNode.replaceWith(dummyNode);
  1475. // cloneNodeCnt.data = data;
  1476. // dummyNode.replaceWith(mirrorNode);
  1477. requiredUpdate = true;
  1478. }
  1479. }
  1480.  
  1481.  
  1482. mirrorElmSet.add(mirrorNode);
  1483. source.mirrored = mirrorNode;
  1484.  
  1485. }
  1486.  
  1487. const mirroElmArr = [...mirrorElmSet];
  1488. mirrorElmSet.clear();
  1489.  
  1490. if (!requiredUpdate) {
  1491. let e = infoExpander ? -1 : 0;
  1492. // DOM Tree Check
  1493. for (let n = targetParent.firstChild; n instanceof Node; n = n.nextSibling) {
  1494. let target = e < 0 ? infoExpander : mirroElmArr[e];
  1495. e++;
  1496. if (n !== target) {
  1497. // target can be undefined if index overflow
  1498. requiredUpdate = true;
  1499. break;
  1500. }
  1501. }
  1502. if (!requiredUpdate && e !== mirroElmArr.length + 1) requiredUpdate = true;
  1503. }
  1504.  
  1505. if (requiredUpdate) {
  1506. if (infoExpander) {
  1507. targetParent.assignChildern111(null, infoExpander, mirroElmArr);
  1508. } else {
  1509. targetParent.replaceChildren000(...mirroElmArr);
  1510. }
  1511. for (const mirrorElm of mirroElmArr) {
  1512. // trigger data assignment and record refresh count by manual update
  1513. const j = attributeInc(mirrorElm, 'tyt-clone-refresh-count');
  1514. const oriElm = kRef(mirrorElm[__j5744__] || null) || null;
  1515. if (oriElm) {
  1516. oriElm.setAttribute111('tyt-clone-refresh-count', j)
  1517. }
  1518. }
  1519. }
  1520.  
  1521. mirroElmArr.length = 0;
  1522. source.length = 0;
  1523.  
  1524. }
  1525.  
  1526. const layoutFix = (lockId) => {
  1527. if (lockGet['layoutFixLock'] !== lockId) return;
  1528. // console.log('((layoutFix))')
  1529.  
  1530. const secondaryWrapper = document.querySelector('#secondary-inner.style-scope.ytd-watch-flexy > secondary-wrapper');
  1531. // console.log(3838, !!chatContainer, !!(secondaryWrapper && secondaryInner), secondaryInner?.firstChild, secondaryInner?.lastChild , secondaryWrapper?.parentNode === secondaryInner)
  1532. if (secondaryWrapper) {
  1533. const secondaryInner = secondaryWrapper.parentNode;
  1534.  
  1535. const chatContainer = document.querySelector('#columns.style-scope.ytd-watch-flexy [tyt-chat-container]');
  1536. if (secondaryInner.firstChild !== secondaryInner.lastChild || (chatContainer && !chatContainer.closest('secondary-wrapper'))) {
  1537. // console.log(38381)
  1538. let w = [];
  1539. let w2 = [];
  1540. for (let node = secondaryInner.firstChild; node instanceof Node; node = node.nextSibling) {
  1541. if (node === chatContainer && chatContainer) {
  1542.  
  1543. } else if (node === secondaryWrapper) {
  1544.  
  1545. for (let node2 = secondaryWrapper.firstChild; node2 instanceof Node; node2 = node2.nextSibling) {
  1546. if (node2 === chatContainer && chatContainer) {
  1547. } else {
  1548. if (node2.id === 'right-tabs' && chatContainer) {
  1549. w2.push(chatContainer);
  1550. }
  1551. w2.push(node2);
  1552. }
  1553. }
  1554. } else {
  1555. w.push(node);
  1556. }
  1557. }
  1558. // console.log('qww', w, w2)
  1559.  
  1560. inPageRearrange = true;
  1561. secondaryWrapper.replaceChildren000(...w, ...w2);
  1562. inPageRearrange = false;
  1563. const chatElm = elements.chat;
  1564. const chatCnt = insp(chatElm);
  1565. if (chatCnt && typeof chatCnt.urlChanged === 'function' && secondaryWrapper.contains(chatElm)) {
  1566.  
  1567. // setTimeout(() => chatCnt.urlChanged, 136);
  1568. if (typeof chatCnt.urlChangedAsync12 === 'function') {
  1569. console.log('elements.chat urlChangedAsync12', 61);
  1570. chatCnt.urlChanged();
  1571. } else {
  1572. console.log('elements.chat urlChangedAsync12', 62);
  1573. setTimeout(() => chatCnt.urlChanged(), 136);
  1574. }
  1575. }
  1576. }
  1577. }
  1578.  
  1579. }
  1580.  
  1581. let lastPanel = '';
  1582. let lastTab = '';
  1583. // let fixInitialTabState = 0;
  1584.  
  1585. const aoEgmPanels = new MutationObserver(() => {
  1586. // console.log(5094,3);
  1587. Promise.resolve(lockSet['updateEgmPanelsLock']).then(updateEgmPanels).catch(console.warn);
  1588. });
  1589.  
  1590. const removeKeepCommentsScroller = async (lockId) => {
  1591. if (lockGet['removeKeepCommentsScrollerLock'] !== lockId) return;
  1592. await Promise.resolve();
  1593. if (lockGet['removeKeepCommentsScrollerLock'] !== lockId) return;
  1594. const ytdFlexyFlm = elements.flexy;
  1595. if (ytdFlexyFlm) {
  1596. ytdFlexyFlm.removeAttribute000('keep-comments-scroller');
  1597. }
  1598. }
  1599.  
  1600. const updateEgmPanels = async (lockId) => {
  1601. if (lockId !== lockGet['updateEgmPanelsLock']) return;
  1602. await navigateFinishedPromise.then().catch(console.warn);
  1603. if (lockId !== lockGet['updateEgmPanelsLock']) return;
  1604. // console.log('updateEgmPanels::called');
  1605. const ytdFlexyElm = elements.flexy;
  1606. if (!ytdFlexyElm) return;
  1607. let newVisiblePanels = [];
  1608. let newHiddenPanels = [];
  1609. let allVisiblePanels = [];
  1610. for (const panelElm of document.querySelectorAll('[tyt-egm-panel][target-id][visibility]')) {
  1611. const visibility = panelElm.getAttribute000('visibility');
  1612.  
  1613. if (visibility === 'ENGAGEMENT_PANEL_VISIBILITY_HIDDEN' || panelElm.closest('[hidden]')) {
  1614. if (panelElm.hasAttribute000('tyt-visible-at')) {
  1615. panelElm.removeAttribute000('tyt-visible-at');
  1616. newHiddenPanels.push(panelElm);
  1617. }
  1618.  
  1619. } else if (visibility === 'ENGAGEMENT_PANEL_VISIBILITY_EXPANDED' && !panelElm.closest('[hidden]')) {
  1620. let visibleAt = panelElm.getAttribute000('tyt-visible-at');
  1621. if (!visibleAt) {
  1622. panelElm.setAttribute111('tyt-visible-at', Date.now());
  1623. newVisiblePanels.push(panelElm);
  1624. }
  1625. allVisiblePanels.push(panelElm);
  1626. }
  1627. }
  1628. if (newVisiblePanels.length >= 1 && allVisiblePanels.length >= 2) {
  1629. const targetVisible = newVisiblePanels[newVisiblePanels.length - 1];
  1630.  
  1631. const actions = [];
  1632. for (const panelElm of allVisiblePanels) {
  1633. if (panelElm === targetVisible) continue;
  1634. actions.push({
  1635. panelId: panelElm.getAttribute000('target-id'),
  1636. toHide: true
  1637. });
  1638. }
  1639.  
  1640. if (actions.length >= 1) {
  1641. ytBtnEgmPanelCore(actions);
  1642. }
  1643.  
  1644. }
  1645. if (allVisiblePanels.length >= 1) {
  1646. ytdFlexyElm.setAttribute111('tyt-egm-panel_', '');
  1647. } else {
  1648. ytdFlexyElm.removeAttribute000('tyt-egm-panel_');
  1649. }
  1650. newVisiblePanels.length = 0;
  1651. newVisiblePanels = null;
  1652. newHiddenPanels.length = 0;
  1653. newHiddenPanels = null;
  1654. allVisiblePanels.length = 0;
  1655. allVisiblePanels = null;
  1656. }
  1657.  
  1658. const checkElementExist = (css, exclude) => {
  1659. for (const p of document.querySelectorAll(css)) {
  1660. if (!p.closest(exclude)) return p;
  1661. }
  1662. return null;
  1663. }
  1664.  
  1665. let fixInitialTabStateK = 0;
  1666.  
  1667. const { handleNavigateFactory } = (() => {
  1668.  
  1669.  
  1670. let isLoadStartListened = false;
  1671.  
  1672. function findLcComment(lc) {
  1673. if (arguments.length === 1) {
  1674.  
  1675. let element = document.querySelector(`#tab-comments ytd-comments ytd-comment-renderer #header-author a[href*="lc=${lc}"]`);
  1676. if (element) {
  1677. let commentRendererElm = closestFromAnchor.call(element, 'ytd-comment-renderer');
  1678. if (commentRendererElm && lc) {
  1679. return {
  1680. lc,
  1681. commentRendererElm
  1682. }
  1683. }
  1684. }
  1685. } else if (arguments.length === 0) {
  1686.  
  1687. let element = document.querySelector(`#tab-comments ytd-comments ytd-comment-renderer > #linked-comment-badge span:not(:empty)`);
  1688. if (element) {
  1689. let commentRendererElm = closestFromAnchor.call(element, 'ytd-comment-renderer');
  1690. if (commentRendererElm) {
  1691.  
  1692. let header = _querySelector.call(commentRendererElm, '#header-author');
  1693. if (header) {
  1694.  
  1695. let anchor = _querySelector.call(header, 'a[href*="lc="]');
  1696. if (anchor) {
  1697. let href = (anchor.getAttribute('href') || '');
  1698. let m = /[&?]lc=([\w_.-]+)/.exec(href); // dot = sub-comment
  1699. if (m) {
  1700. lc = m[1];
  1701. }
  1702. }
  1703. }
  1704.  
  1705. }
  1706. if (commentRendererElm && lc) {
  1707. return {
  1708. lc,
  1709. commentRendererElm
  1710. }
  1711. }
  1712. }
  1713. }
  1714.  
  1715. return null;
  1716.  
  1717. }
  1718.  
  1719.  
  1720. function lcSwapFuncA(targetLcId, currentLcId) {
  1721.  
  1722.  
  1723. let done = 0;
  1724. try {
  1725. // console.log(currentLcId, targetLcId)
  1726.  
  1727. let r1 = findLcComment(currentLcId).commentRendererElm;
  1728. let r2 = findLcComment(targetLcId).commentRendererElm;
  1729.  
  1730.  
  1731. if (typeof insp(r1).data.linkedCommentBadge === 'object' && typeof insp(r2).data.linkedCommentBadge === 'undefined') {
  1732.  
  1733. let p = Object.assign({}, insp(r1).data.linkedCommentBadge)
  1734.  
  1735. if (((p || 0).metadataBadgeRenderer || 0).trackingParams) {
  1736. delete p.metadataBadgeRenderer.trackingParams;
  1737. }
  1738.  
  1739. const v1 = findContentsRenderer(r1)
  1740. const v2 = findContentsRenderer(r2)
  1741.  
  1742.  
  1743. if (v1.parent === v2.parent && (v2.parent.nodeName === 'YTD-COMMENTS' || v2.parent.nodeName === 'YTD-ITEM-SECTION-RENDERER')) {
  1744.  
  1745. } else {
  1746. // currently not supported
  1747. return false;
  1748. }
  1749.  
  1750.  
  1751.  
  1752. if (v2.index >= 0) {
  1753. if (v2.parent.nodeName === 'YTD-COMMENT-REPLIES-RENDERER') {
  1754.  
  1755.  
  1756. if (lcSwapFuncB(targetLcId, currentLcId, p)) {
  1757. done = 1;
  1758. }
  1759.  
  1760. done = 1;
  1761. } else {
  1762. const v2pCnt = insp(v2.parent);
  1763. const v2Conents = (v2pCnt.data || 0).contents || 0;
  1764. if (!v2Conents) console.warn('v2Conents is not found');
  1765.  
  1766. v2pCnt.data = Object.assign({}, v2pCnt.data, { contents: [].concat([v2Conents[v2.index]], v2Conents.slice(0, v2.index), v2Conents.slice(v2.index + 1)) });
  1767.  
  1768. if (lcSwapFuncB(targetLcId, currentLcId, p)) {
  1769. done = 1;
  1770. }
  1771. }
  1772.  
  1773.  
  1774. }
  1775.  
  1776.  
  1777.  
  1778. }
  1779.  
  1780.  
  1781.  
  1782. } catch (e) {
  1783. console.warn(e)
  1784. }
  1785. return done === 1;
  1786. }
  1787.  
  1788.  
  1789. function lcSwapFuncB(targetLcId, currentLcId, _p) {
  1790.  
  1791. let done = 0;
  1792. try {
  1793.  
  1794. let r1 = findLcComment(currentLcId).commentRendererElm;
  1795. let r1cnt = insp(r1);
  1796. let r2 = findLcComment(targetLcId).commentRendererElm;
  1797. let r2cnt = insp(r2);
  1798.  
  1799. const r1d = r1cnt.data;
  1800. let p = Object.assign({}, _p)
  1801. r1d.linkedCommentBadge = null;
  1802. delete r1d.linkedCommentBadge;
  1803.  
  1804. let q = Object.assign({}, r1d);
  1805. q.linkedCommentBadge = null;
  1806. delete q.linkedCommentBadge;
  1807.  
  1808. r1cnt.data = Object.assign({}, q);
  1809. r2cnt.data = Object.assign({}, r2cnt.data, { linkedCommentBadge: p });
  1810.  
  1811. done = 1;
  1812.  
  1813. } catch (e) {
  1814. console.warn(e)
  1815. }
  1816. return done === 1;
  1817. }
  1818.  
  1819. const loadStartFx = async (evt) => {
  1820.  
  1821. let media = (evt || 0).target || 0;
  1822. if (media.nodeName === 'VIDEO' || media.nodeName === 'AUDIO') { }
  1823. else return;
  1824.  
  1825. const newMedia = media;
  1826.  
  1827. const media1 = common.getMediaElement(0); // document.querySelector('#movie_player video[src]');
  1828. const media2 = common.getMediaElements(2); // document.querySelectorAll('ytd-browse[role="main"] video[src]');
  1829.  
  1830. if (media1 !== null && media2.length > 0) {
  1831. if (newMedia !== media1 && media1.paused === false) {
  1832. if (isVideoPlaying(media1)) {
  1833. Promise.resolve(newMedia).then(video => video.paused === false && video.pause()).catch(console.warn);
  1834. }
  1835. } else if (newMedia === media1) {
  1836. for (const s of media2) {
  1837. if (s.paused === false) {
  1838. Promise.resolve(s).then(s => s.paused === false && s.pause()).catch(console.warn);
  1839. break;
  1840. }
  1841. }
  1842. } else {
  1843. Promise.resolve(media1).then(video1 => video1.paused === false && video1.pause()).catch(console.warn);
  1844. }
  1845. }
  1846.  
  1847. }
  1848.  
  1849. const getBrowsableEndPoint = (req) => {
  1850.  
  1851. let valid = false;
  1852. let endpoint = req ? req.command : null;
  1853. if (endpoint && (endpoint.commandMetadata || 0).webCommandMetadata && endpoint.watchEndpoint) {
  1854. let videoId = endpoint.watchEndpoint.videoId;
  1855. let url = endpoint.commandMetadata.webCommandMetadata.url;
  1856.  
  1857. if (typeof videoId === 'string' && typeof url === 'string' && url.indexOf('lc=') > 0) {
  1858.  
  1859. let m = /^\/watch\?v=([\w_-]+)&lc=([\w_.-]+)$/.exec(url); // dot = sub-comment
  1860. if (m && m[1] === videoId) {
  1861.  
  1862.  
  1863. /*
  1864. {
  1865. "style": "BADGE_STYLE_TYPE_SIMPLE",
  1866. "label": "注目のコメント",
  1867. "trackingParams": "XXXXXX"
  1868. }
  1869. */
  1870.  
  1871. let targetLc = findLcComment(m[2])
  1872. let currentLc = targetLc ? findLcComment() : null;
  1873.  
  1874. if (targetLc && currentLc) {
  1875.  
  1876.  
  1877. let done = targetLc.lc === currentLc.lc ? 1 : lcSwapFuncA(targetLc.lc, currentLc.lc) ? 1 : 0
  1878.  
  1879. if (done === 1) {
  1880.  
  1881. common.xReplaceState(history.state, url);
  1882. return;
  1883. }
  1884. }
  1885. }
  1886.  
  1887. }
  1888.  
  1889. }
  1890.  
  1891.  
  1892.  
  1893. /*
  1894. {
  1895. "type": 0,
  1896. "command": endpoint,
  1897. "form": {
  1898. "tempData": {},
  1899. "reload": false
  1900. }
  1901. }
  1902. */
  1903.  
  1904. if (endpoint && (endpoint.commandMetadata || 0).webCommandMetadata && endpoint.browseEndpoint && isChannelId(endpoint.browseEndpoint.browseId)) {
  1905. valid = true;
  1906.  
  1907. } else if (endpoint && (endpoint.browseEndpoint || endpoint.searchEndpoint) && !endpoint.urlEndpoint && !endpoint.watchEndpoint) {
  1908.  
  1909. if (endpoint.browseEndpoint && endpoint.browseEndpoint.browseId === "FEwhat_to_watch") {
  1910. // valid = false;
  1911. const playerMedia = common.getMediaElement(1);
  1912. if (playerMedia && playerMedia.paused === false) valid = true; // home page
  1913. } else if (endpoint.commandMetadata && endpoint.commandMetadata.webCommandMetadata) {
  1914.  
  1915. let meta = endpoint.commandMetadata.webCommandMetadata
  1916. if (meta && /*meta.apiUrl &&*/ meta.url && meta.webPageType) {
  1917. valid = true;
  1918. }
  1919.  
  1920. }
  1921. }
  1922.  
  1923. if (!valid) endpoint = null;
  1924.  
  1925. return endpoint;
  1926. }
  1927.  
  1928. const shouldUseMiniPlayer = ()=>{
  1929.  
  1930. const isSubTypeExist = document.querySelector('ytd-page-manager#page-manager > ytd-browse[page-subtype]');
  1931.  
  1932. if(isSubTypeExist) return true;
  1933.  
  1934. const movie_player = [...document.querySelectorAll('#movie_player')].filter(e => !e.closest('[hidden]'))[0];
  1935. if (movie_player) {
  1936. const media = qsOne(movie_player, 'video[class], audio[class]');
  1937. if (media && media.currentTime > 3 && media.duration - media.currentTime > 3 && media.paused === false) {
  1938. return true;
  1939. }
  1940. }
  1941. return false;
  1942. // return true;
  1943. // return !!document.querySelector('ytd-page-manager#page-manager > ytd-browse[page-subtype]');
  1944. }
  1945.  
  1946. const conditionFulfillment = (req) => {
  1947. const endpoint = req ? req.command : null;
  1948. if (!endpoint) return;
  1949.  
  1950. if (endpoint && (endpoint.commandMetadata || 0).webCommandMetadata && endpoint.watchEndpoint) {
  1951. } else if (endpoint && (endpoint.commandMetadata || 0).webCommandMetadata && endpoint.browseEndpoint && isChannelId(endpoint.browseEndpoint.browseId)) {
  1952. } else if (endpoint && (endpoint.browseEndpoint || endpoint.searchEndpoint) && !endpoint.urlEndpoint && !endpoint.watchEndpoint) {
  1953. } else {
  1954. return false;
  1955. }
  1956.  
  1957.  
  1958. if (!shouldUseMiniPlayer()) return false;
  1959.  
  1960. /*
  1961. // user would like to switch page immediately without playing the video;
  1962. // attribute appear after playing video for more than 2s
  1963. if (!document.head.dataset.viTime) return false;
  1964. else {
  1965. let currentVideo = common.getMediaElement(0);
  1966. if (currentVideo && currentVideo.readyState > currentVideo.HAVE_CURRENT_DATA && currentVideo.currentTime > 2.2 && currentVideo.duration - 2.2 < currentVideo.currentTime) {
  1967. // disable miniview browsing if the media is near to the end
  1968. return false;
  1969. }
  1970. }
  1971. */
  1972.  
  1973.  
  1974. if (pageType !== "watch") return false;
  1975.  
  1976.  
  1977. if (!checkElementExist('ytd-watch-flexy #player button.ytp-miniplayer-button.ytp-button', '[hidden]')) {
  1978. return false;
  1979. }
  1980.  
  1981. return true;
  1982. }
  1983.  
  1984. let u38 = 0;
  1985. const fixChannelAboutPopup = async (t38)=>{
  1986.  
  1987. let promise = new PromiseExternal();
  1988. const f = () => {
  1989. promise && promise.resolve();
  1990. promise = null;
  1991. }
  1992. document.addEventListener('yt-navigate-finish', f, false);
  1993. await promise.then();
  1994. promise = null;
  1995. document.removeEventListener('yt-navigate-finish', f, false);
  1996. if (t38 !== u38) return;
  1997. setTimeout(() => {
  1998. const currentAbout = [...document.querySelectorAll('ytd-about-channel-renderer')].filter(e => !e.closest('[hidden]'))[0];
  1999. let okay = false;
  2000. if (!currentAbout) okay = true;
  2001. else {
  2002. const popupContainer = currentAbout.closest('ytd-popup-container');
  2003. if (popupContainer) {
  2004. const cnt = insp(popupContainer);
  2005. let arr = null;
  2006. try {
  2007. arr = cnt.handleGetOpenedPopupsAction_()
  2008. } catch (e) {
  2009.  
  2010. }
  2011. if (arr && arr.length === 0) okay = true;
  2012. } else {
  2013. okay = false;
  2014. }
  2015. }
  2016. if (okay) {
  2017. const descriptionModel = [...document.querySelectorAll('yt-description-preview-view-model')].filter(e => !e.closest('[hidden]'))[0];
  2018. if (descriptionModel) {
  2019. const button = [...descriptionModel.querySelectorAll('button')].filter(e => !e.closest('[hidden]') && `${e.textContent}`.trim().length > 0)[0];
  2020. if (button) {
  2021. button.click();
  2022. }
  2023. }
  2024. }
  2025. }, 80);
  2026.  
  2027. }
  2028. const handleNavigateFactory = (handleNavigate) => {
  2029.  
  2030. return function (req) {
  2031.  
  2032. if (u38 > 1e9) u38 = 9;
  2033. const t38 = ++u38;
  2034.  
  2035. const $this = this;
  2036. const $arguments = arguments;
  2037.  
  2038. let endpoint = null;
  2039.  
  2040.  
  2041. if (conditionFulfillment(req)) {
  2042.  
  2043.  
  2044. endpoint = getBrowsableEndPoint(req);
  2045.  
  2046. }
  2047.  
  2048.  
  2049. if (!endpoint || !shouldUseMiniPlayer()) return handleNavigate.apply($this, $arguments);
  2050.  
  2051. // console.log('tabview-script-handleNavigate')
  2052.  
  2053. const ytdAppElm = document.querySelector('ytd-app');
  2054. const ytdAppCnt = insp(ytdAppElm);
  2055.  
  2056. let object = null;
  2057. try {
  2058. object = ytdAppCnt.data.response.currentVideoEndpoint.watchEndpoint || null;
  2059. } catch (e) {
  2060. object = null;
  2061. }
  2062.  
  2063. if (typeof object !== 'object') object = null;
  2064.  
  2065. const once = { once: true }; // browsers supporting async function can also use once option.
  2066.  
  2067. if (object !== null && !('playlistId' in object)) {
  2068.  
  2069. let wObject = mWeakRef(object)
  2070.  
  2071. const N = 3;
  2072.  
  2073. let count = 0;
  2074.  
  2075. /*
  2076. rcb(b) => a = playlistId = undefinded
  2077. var scb = function(a, b, c, d) {
  2078. a.isInitialized() && (B("kevlar_miniplayer_navigate_to_shorts_killswitch") ? c || d ? ("watch" !== Xu(b) && "shorts" !== Xu(b) && os(a.miniplayerEl, "yt-cache-miniplayer-page-action", [b]),
  2079. qs(a.miniplayerEl, "yt-deactivate-miniplayer-action")) : "watch" === Xu(b) && rcb(b) && (qt.getInstance().playlistWatchPageActivation = !0,
  2080. a.activateMiniplayer(b)) : c ? ("watch" !== Xu(b) && os(a.miniplayerEl, "yt-cache-miniplayer-page-action", [b]),
  2081. qs(a.miniplayerEl, "yt-deactivate-miniplayer-action")) : d ? qs(a.miniplayerEl, "yt-pause-miniplayer-action") : "watch" === Xu(b) && rcb(b) && (qt.getInstance().playlistWatchPageActivation = !0,
  2082. a.activateMiniplayer(b)))
  2083. };
  2084. */
  2085.  
  2086. Object.defineProperty((kRef(wObject) || {}), 'playlistId', {
  2087. get() {
  2088. count++;
  2089. if (count === N) {
  2090. delete this.playlistId;
  2091. }
  2092. return '*';
  2093. },
  2094. set(value) {
  2095. delete this.playlistId; // remove property definition
  2096. this.playlistId = value; // assign as normal property
  2097. },
  2098. enumerable: false,
  2099. configurable: true
  2100. });
  2101.  
  2102. let playlistClearout = null;
  2103.  
  2104. let timeoutid = 0;
  2105. Promise.race([
  2106. new Promise(r => {
  2107. timeoutid = setTimeout(r, 4000)
  2108. }),
  2109. new Promise(r => {
  2110. playlistClearout = () => {
  2111. if (timeoutid > 0) {
  2112. clearTimeout(timeoutid);
  2113. timeoutid = 0;
  2114. }
  2115. r();
  2116. }
  2117. document.addEventListener('yt-page-type-changed', playlistClearout, once);
  2118. })
  2119. ]).then(() => {
  2120.  
  2121. if (timeoutid !== 0) {
  2122. playlistClearout && document.removeEventListener('yt-page-type-changed', playlistClearout, once);
  2123. timeoutid = 0;
  2124. }
  2125. playlistClearout = null;
  2126. count = N - 1;
  2127. let object = kRef(wObject)
  2128. wObject = null;
  2129. return object ? object.playlistId : null;
  2130. }).catch(console.warn);
  2131.  
  2132. }
  2133.  
  2134. if (!isLoadStartListened) {
  2135. isLoadStartListened = true;
  2136. document.addEventListener('loadstart', loadStartFx, true)
  2137. }
  2138.  
  2139. const endpointURL = `${(endpoint?.commandMetadata?.webCommandMetadata?.url || '' )}`;
  2140.  
  2141. if (endpointURL && endpointURL.endsWith('/about') && /\/channel\/UC[-_a-zA-Z0-9+=.]{22}\/about/.test(endpointURL)) {
  2142. fixChannelAboutPopup(t38);
  2143. }
  2144.  
  2145. handleNavigate.apply($this, $arguments);
  2146.  
  2147.  
  2148. }
  2149.  
  2150. };
  2151.  
  2152. return { handleNavigateFactory };
  2153.  
  2154.  
  2155. })();
  2156.  
  2157. const common = (() => {
  2158.  
  2159.  
  2160. let mediaModeLock = 0;
  2161. const _getMediaElement = (i) => {
  2162. if (mediaModeLock === 0) {
  2163. let e = document.querySelector('.video-stream.html5-main-video') || document.querySelector('#movie_player video, #movie_player audio') || document.querySelector('body video[src], body audio[src]');
  2164. if (e) {
  2165. if (e.nodeName === 'VIDEO') mediaModeLock = 1;
  2166. else if (e.nodeName === 'AUDIO') mediaModeLock = 2;
  2167. }
  2168. }
  2169. if (!mediaModeLock) return null;
  2170. if (mediaModeLock === 1) {
  2171. switch (i) {
  2172. case 1:
  2173. return ('ytd-player#ytd-player video[src]');
  2174. case 2:
  2175. return ('ytd-browse[role="main"] video[src]');
  2176. case 0:
  2177. default:
  2178. return ('#movie_player video[src]');
  2179. }
  2180. } else if (mediaModeLock === 2) {
  2181. switch (i) {
  2182. case 1:
  2183. return ('ytd-player#ytd-player audio.video-stream.html5-main-video[src]');
  2184. case 2:
  2185. return ('ytd-browse[role="main"] audio.video-stream.html5-main-video[src]');
  2186. case 0:
  2187. default:
  2188. return ('#movie_player audio.video-stream.html5-main-video[src]');
  2189. }
  2190. }
  2191. return null;
  2192. }
  2193.  
  2194. return {
  2195.  
  2196.  
  2197. xReplaceState(s, u) {
  2198. try {
  2199. history.replaceState(s, '', u);
  2200. } catch (e) {
  2201. // in case error occurs if replaceState is replaced by any external script / extension
  2202. }
  2203. if (s.endpoint) {
  2204. try {
  2205. const ytdAppElm = document.querySelector('ytd-app');
  2206. const ytdAppCnt = insp(ytdAppElm);
  2207. ytdAppCnt.replaceState(s.endpoint, '', u)
  2208. } catch (e) {
  2209. }
  2210. }
  2211. },
  2212. getMediaElement(i) {
  2213. let s = _getMediaElement(i) || '';
  2214. if (s) return document.querySelector(s);
  2215. return null;
  2216. },
  2217. getMediaElements(i) {
  2218. let s = _getMediaElement(i) || '';
  2219. if (s) return document.querySelectorAll(s);
  2220. return [];
  2221. }
  2222. };
  2223. })();
  2224.  
  2225. let inPageRearrange = false;
  2226. let tmpLastVideoId = '';
  2227. // const nsMap = new Map();
  2228.  
  2229. const getCurrentVideoId = ()=>{
  2230. const ytdFlexyElm = elements.flexy;
  2231. const ytdFlexyCnt = insp(ytdFlexyElm);
  2232. if(ytdFlexyCnt && typeof ytdFlexyCnt.videoId === 'string') return ytdFlexyCnt.videoId;
  2233. if(ytdFlexyElm && typeof ytdFlexyElm.videoId === 'string') return ytdFlexyElm.videoId;
  2234. console.log('video id not found');
  2235. return '';
  2236. };
  2237.  
  2238. const holdInlineExpanderAlwaysExpanded = (inlineExpanderCnt) => {
  2239. console.log('holdInlineExpanderAlwaysExpanded')
  2240. if (inlineExpanderCnt.alwaysShowExpandButton === true) inlineExpanderCnt.alwaysShowExpandButton = false;
  2241. if (typeof (inlineExpanderCnt.collapseLabel || 0) === 'string') inlineExpanderCnt.collapseLabel = '';
  2242. if (typeof (inlineExpanderCnt.expandLabel || 0) === 'string') inlineExpanderCnt.expandLabel = '';
  2243. if (inlineExpanderCnt.showCollapseButton === true) inlineExpanderCnt.showCollapseButton = false;
  2244. if (inlineExpanderCnt.showExpandButton === true) inlineExpanderCnt.showExpandButton = false;
  2245. if (inlineExpanderCnt.expandButton instanceof HTMLElement_) {
  2246. inlineExpanderCnt.expandButton = null;
  2247. inlineExpanderCnt.expandButton.remove();
  2248. }
  2249. };
  2250.  
  2251. const fixInlineExpanderDisplay = (inlineExpanderCnt) => {
  2252. try {
  2253. inlineExpanderCnt.updateIsAttributedExpanded();
  2254. } catch (e) { }
  2255. try {
  2256. inlineExpanderCnt.updateIsFormattedExpanded();
  2257. } catch (e) { }
  2258. try {
  2259. inlineExpanderCnt.updateTextOnSnippetTypeChange();
  2260. } catch (e) { }
  2261. try {
  2262. inlineExpanderCnt.updateStyles();
  2263. } catch (e) { }
  2264. };
  2265.  
  2266. const fixInlineExpanderMethods = (inlineExpanderCnt) => {
  2267. if (inlineExpanderCnt && !inlineExpanderCnt.__$$idncjk8487$$__) {
  2268. inlineExpanderCnt.__$$idncjk8487$$__ = true;
  2269. inlineExpanderCnt.updateTextOnSnippetTypeChange = function () {
  2270. true || this.isResetMutation && this.mutationCallback();
  2271. }
  2272. // inlineExpanderCnt.hasAttributedStringText = true;
  2273. inlineExpanderCnt.isResetMutation = true;
  2274. fixInlineExpanderDisplay(inlineExpanderCnt); // do the initial fix
  2275. }
  2276. };
  2277.  
  2278. const fixInlineExpanderContent = () => {
  2279. // console.log(21886,1)
  2280. const mainInfo = getMainInfo();
  2281. if (!mainInfo) return;
  2282. // console.log(21886,2)
  2283. const inlineExpanderElm = mainInfo.querySelector('ytd-text-inline-expander');
  2284. const inlineExpanderCnt = insp(inlineExpanderElm);
  2285. fixInlineExpanderMethods(inlineExpanderCnt);
  2286.  
  2287. // console.log(21886, 3)
  2288. // if (inlineExpanderCnt && inlineExpanderCnt.isExpanded === true && plugin.autoExpandInfoDesc.activated) {
  2289. // // inlineExpanderCnt.isExpandedChanged();
  2290. // // holdInlineExpanderAlwaysExpanded(inlineExpanderCnt);
  2291. // }
  2292. // if(inlineExpanderCnt){
  2293. // // console.log(21886,4, inlineExpanderCnt.isExpanded, inlineExpanderCnt.isTruncated)
  2294. // if (inlineExpanderCnt.isExpanded === false && inlineExpanderCnt.isTruncated === true) {
  2295. // // console.log(21881)
  2296. // inlineExpanderCnt.isTruncated = false;
  2297. // }
  2298. // }
  2299. }
  2300.  
  2301. const plugin = {
  2302. 'minibrowser': {
  2303. activated: false,
  2304. toUse: true, // depends on shouldUseMiniPlayer()
  2305. activate() {
  2306.  
  2307. if (this.activated) return;
  2308.  
  2309. const isPassiveArgSupport = (typeof IntersectionObserver === 'function');
  2310. // https://caniuse.com/?search=observer
  2311. // https://caniuse.com/?search=addEventListener%20passive
  2312.  
  2313. if (!isPassiveArgSupport) return;
  2314.  
  2315. this.activated = true;
  2316.  
  2317. const ytdAppElm = document.querySelector('ytd-app');
  2318. const ytdAppCnt = insp(ytdAppElm);
  2319.  
  2320.  
  2321. if (!ytdAppCnt) return;
  2322.  
  2323. const cProto = ytdAppCnt.constructor.prototype;
  2324.  
  2325. if (!cProto.handleNavigate) return;
  2326.  
  2327. if (cProto.handleNavigate.__ma355__) return;
  2328.  
  2329. cProto.handleNavigate = handleNavigateFactory(cProto.handleNavigate);
  2330.  
  2331. cProto.handleNavigate.__ma355__ = 1;
  2332. }
  2333. },
  2334. 'autoExpandInfoDesc': {
  2335. activated: false,
  2336. toUse: false, // false by default; once the expand is clicked, maintain the feature until the browser is closed.
  2337. /** @type { MutationObserver | null } */
  2338. mo: null,
  2339. promiseReady: new PromiseExternal(),
  2340. moFn(lockId) {
  2341.  
  2342. if (lockGet['autoExpandInfoDescAttrAsyncLock'] !== lockId) return;
  2343.  
  2344. const mainInfo = getMainInfo();
  2345.  
  2346. if (!mainInfo) return;
  2347. switch (((mainInfo || 0).nodeName || '').toLowerCase()) {
  2348. case 'ytd-expander':
  2349. if (mainInfo.hasAttribute000('collapsed')) {
  2350. let success = false;
  2351. try {
  2352. insp(mainInfo).handleMoreTap(new Event("tap"));
  2353. success = true;
  2354. } catch (e) {
  2355. }
  2356. if (success) mainInfo.setAttribute111('tyt-no-less-btn', '');
  2357. }
  2358. break;
  2359. case 'ytd-expandable-video-description-body-renderer':
  2360. const inlineExpanderElm = mainInfo.querySelector('ytd-text-inline-expander');
  2361. const inlineExpanderCnt = insp(inlineExpanderElm);
  2362. if (inlineExpanderCnt && inlineExpanderCnt.isExpanded === false) {
  2363. inlineExpanderCnt.isExpanded = true;
  2364. inlineExpanderCnt.isExpandedChanged();
  2365. // holdInlineExpanderAlwaysExpanded(inlineExpanderCnt);
  2366. }
  2367. break;
  2368. }
  2369.  
  2370.  
  2371.  
  2372. },
  2373. activate() {
  2374. if (this.activated) return;
  2375.  
  2376. this.moFn = this.moFn.bind(this);
  2377. this.mo = new MutationObserver(() => {
  2378. Promise.resolve(lockSet['autoExpandInfoDescAttrAsyncLock']).then(this.moFn).catch(console.warn);
  2379. });
  2380. this.activated = true;
  2381. this.promiseReady.resolve();
  2382. },
  2383. async onMainInfoSet(mainInfo){
  2384. await this.promiseReady.then();
  2385. if (mainInfo.nodeName.toLowerCase() === 'ytd-expander') {
  2386. this.mo.observe(mainInfo, { attributes: true, attributeFilter: ['collapsed', 'attr-8ifv7'] });
  2387. } else {
  2388. this.mo.observe(mainInfo, { attributes: true, attributeFilter: ['attr-8ifv7'] });
  2389. }
  2390. mainInfo.incAttribute111('attr-8ifv7');
  2391. }
  2392. },
  2393. 'fullChannelNameOnHover': {
  2394. activated: false,
  2395. toUse: true,
  2396. /** @type { MutationObserver | null } */
  2397. mo: null,
  2398. /** @type { ResizeObserver | null} */
  2399. ro: null,
  2400. promiseReady: new PromiseExternal(),
  2401. checkResize: 0,
  2402. mouseEnterFn(evt) {
  2403.  
  2404. const target = evt ? evt.target : null;
  2405. if (!(target instanceof HTMLElement_)) return;
  2406. const metaDataElm = target.closest('ytd-watch-metadata');
  2407. metaDataElm.classList.remove('tyt-metadata-hover-resized');
  2408. this.checkResize = Date.now() + 300;
  2409. metaDataElm.classList.add('tyt-metadata-hover');
  2410. // console.log('mouseEnter')
  2411.  
  2412. },
  2413. mouseLeaveFn(evt) {
  2414. const target = evt ? evt.target : null;
  2415. if (!(target instanceof HTMLElement_)) return;
  2416. const metaDataElm = target.closest('ytd-watch-metadata');
  2417. metaDataElm.classList.remove('tyt-metadata-hover-resized');
  2418. metaDataElm.classList.remove('tyt-metadata-hover');
  2419. // console.log('mouseLeaveFn')
  2420.  
  2421. },
  2422. moFn(lockId) {
  2423.  
  2424. if (lockGet['fullChannelNameOnHoverAttrAsyncLock'] !== lockId) return;
  2425.  
  2426. const uploadInfo = document.querySelector('#primary.ytd-watch-flexy ytd-watch-metadata #upload-info');
  2427. if (!uploadInfo) return;
  2428.  
  2429. const evtOpt = { passive: true, capture: false };
  2430. uploadInfo.removeEventListener('pointerenter', this.mouseEnterFn, evtOpt);
  2431. uploadInfo.removeEventListener('pointerleave', this.mouseLeaveFn, evtOpt);
  2432.  
  2433. uploadInfo.addEventListener('pointerenter', this.mouseEnterFn, evtOpt);
  2434. uploadInfo.addEventListener('pointerleave', this.mouseLeaveFn, evtOpt);
  2435.  
  2436.  
  2437.  
  2438. },
  2439. async onNavigateFinish() {
  2440. await this.promiseReady.then();
  2441. const uploadInfo = document.querySelector('#primary.ytd-watch-flexy ytd-watch-metadata #upload-info');
  2442. if (!uploadInfo) return;
  2443. this.mo.observe(uploadInfo, { attributes: true, attributeFilter: ['hidden', 'attr-3wb0k'] });
  2444. uploadInfo.incAttribute111('attr-3wb0k');
  2445. this.ro.observe(uploadInfo);
  2446. },
  2447. activate() {
  2448.  
  2449. if (this.activated) return;
  2450.  
  2451. const isPassiveArgSupport = (typeof IntersectionObserver === 'function');
  2452. // https://caniuse.com/?search=observer
  2453. // https://caniuse.com/?search=addEventListener%20passive
  2454.  
  2455. if (!isPassiveArgSupport) return;
  2456.  
  2457. this.activated = true;
  2458.  
  2459. this.mouseEnterFn = this.mouseEnterFn.bind(this);
  2460. this.mouseLeaveFn = this.mouseLeaveFn.bind(this);
  2461.  
  2462. this.moFn = this.moFn.bind(this);
  2463. this.mo = new MutationObserver(() => {
  2464. Promise.resolve(lockSet['fullChannelNameOnHoverAttrAsyncLock']).then(this.moFn).catch(console.warn);
  2465. });
  2466. this.ro = new ResizeObserver((mutations) => {
  2467.  
  2468. if (Date.now() > this.checkResize) return;
  2469. for (const mutation of mutations) {
  2470. const uploadInfo = mutation.target;
  2471. if (uploadInfo && mutation.contentRect.width > 0 && mutation.contentRect.height > 0) {
  2472.  
  2473. const metaDataElm = uploadInfo.closest('ytd-watch-metadata');
  2474. if (metaDataElm.classList.contains('tyt-metadata-hover')) {
  2475.  
  2476. metaDataElm.classList.add('tyt-metadata-hover-resized');
  2477. }
  2478.  
  2479. break;
  2480.  
  2481. }
  2482. }
  2483. });
  2484. this.promiseReady.resolve();
  2485. }
  2486. }
  2487. }
  2488.  
  2489. if (sessionStorage.__$$tmp_UseAutoExpandInfoDesc$$__) plugin.autoExpandInfoDesc.toUse = true;
  2490.  
  2491. // let shouldFixInfo = false;
  2492. const __attachedSymbol__ = Symbol();
  2493.  
  2494. const makeInitAttached = (tag)=>{
  2495. const inPageRearrange_ = inPageRearrange;
  2496. inPageRearrange = false;
  2497. for (const elm of document.querySelectorAll(`${tag}`)) {
  2498. const cnt = insp(elm) || 0;
  2499. if (typeof cnt.attached498 === 'function' && !elm[__attachedSymbol__]) Promise.resolve(elm).then(eventMap[`${tag}::attached`]).catch(console.warn);
  2500. }
  2501. inPageRearrange = inPageRearrange_;
  2502. };
  2503.  
  2504. const getGeneralChatElement = async () => {
  2505. for (let i = 2; i-- > 0;) {
  2506. let t = document.querySelector('#columns.style-scope.ytd-watch-flexy ytd-live-chat-frame#chat');
  2507. if (t instanceof Element) return t;
  2508. if (i > 0) {
  2509. // try later
  2510. console.log('ytd-live-chat-frame::attached - delayPn(200)')
  2511. await delayPn(200);
  2512. }
  2513. }
  2514. return null;
  2515. };
  2516.  
  2517. const nsTemplateObtain = () => {
  2518. let nsTemplate = document.querySelector('ytd-watch-flexy noscript[ns-template]');
  2519. if (!nsTemplate) {
  2520. nsTemplate = document.createElement('noscript');
  2521. nsTemplate.setAttribute('ns-template', '');
  2522. document.querySelector('ytd-watch-flexy').appendChild(nsTemplate);
  2523. }
  2524. return nsTemplate;
  2525. };
  2526.  
  2527. const isPageDOM = (elm, selector) => {
  2528. if (!elm || !(elm instanceof Element) || !(elm.nodeName)) return false;
  2529. if (!elm.closest(selector)) return false;
  2530. if (elm.isConnected !== true) return false;
  2531. return true;
  2532. };
  2533.  
  2534. const invalidFlexyParent = (hostElement)=>{
  2535. if (hostElement instanceof HTMLElement) {
  2536. const hasFlexyParent = HTMLElement.prototype.closest.call(hostElement, 'ytd-watch-flexy'); // eg short
  2537. if (!hasFlexyParent) return true;
  2538. const currentFlexy = elements.flexy;
  2539. if (currentFlexy && currentFlexy !== hasFlexyParent) return true;
  2540. }
  2541. return false;
  2542. }
  2543.  
  2544. const eventMap = {
  2545.  
  2546. 'ceHack': () => {
  2547. mLoaded.flag |= 2;
  2548. document.documentElement.setAttribute111('tabview-loaded', mLoaded.makeString());
  2549.  
  2550. retrieveCE('ytd-watch-flexy').then(eventMap['ytd-watch-flexy::defined']).catch(console.warn);
  2551. retrieveCE('ytd-expander').then(eventMap['ytd-expander::defined']).catch(console.warn);
  2552. retrieveCE('ytd-watch-next-secondary-results-renderer').then(eventMap['ytd-watch-next-secondary-results-renderer::defined']).catch(console.warn);
  2553. retrieveCE('ytd-comments-header-renderer').then(eventMap['ytd-comments-header-renderer::defined']).catch(console.warn);
  2554. retrieveCE('ytd-live-chat-frame').then(eventMap['ytd-live-chat-frame::defined']).catch(console.warn);
  2555. retrieveCE('ytd-comments').then(eventMap['ytd-comments::defined']).catch(console.warn);
  2556. retrieveCE('ytd-engagement-panel-section-list-renderer').then(eventMap['ytd-engagement-panel-section-list-renderer::defined']).catch(console.warn);
  2557. retrieveCE('ytd-watch-metadata').then(eventMap['ytd-watch-metadata::defined']).catch(console.warn);
  2558. retrieveCE('ytd-playlist-panel-renderer').then(eventMap['ytd-playlist-panel-renderer::defined']).catch(console.warn);
  2559. retrieveCE('ytd-expandable-video-description-body-renderer').then(eventMap['ytd-expandable-video-description-body-renderer::defined']).catch(console.warn);
  2560.  
  2561. },
  2562.  
  2563. 'fixForTabDisplay': (isResize) => {
  2564. // isResize is true if the layout is resized (not due to tab switching)
  2565. // youtube components shall handle the resize issue. can skip some checkings.
  2566.  
  2567. bFixForResizedTabLater = false;
  2568. for (const element of document.querySelectorAll('[io-intersected]')) {
  2569. const cnt = insp(element);
  2570. if (element instanceof HTMLElement_ && typeof cnt.calculateCanCollapse === 'function') {
  2571. try {
  2572. cnt.calculateCanCollapse(true);
  2573. } catch (e) { }
  2574. }
  2575. }
  2576.  
  2577. if (!isResize && lastTab === '#tab-info') {
  2578. // #tab-info is now shown.
  2579. // to fix the sizing issue (description info cards in tab info)
  2580. for (const element of document.querySelectorAll('#tab-info ytd-video-description-infocards-section-renderer, #tab-info yt-chip-cloud-renderer, #tab-info ytd-horizontal-card-list-renderer')) {
  2581. const cnt = insp(element);
  2582. if (element instanceof HTMLElement_ && typeof cnt.notifyResize === 'function') {
  2583. try {
  2584. cnt.notifyResize();
  2585. } catch (e) { }
  2586. }
  2587. }
  2588. // to fix expand/collapse sizing issue (inline-expander in tab info)
  2589. // for example, expand button is required but not shown as it was rendered in the hidden state
  2590. for (const element of document.querySelectorAll('#tab-info ytd-text-inline-expander')) {
  2591. const cnt = insp(element);
  2592. if (element instanceof HTMLElement_ && typeof cnt.resize === 'function') {
  2593. cnt.resize(false); // reflow due to offsetWidth calling
  2594. }
  2595. fixInlineExpanderDisplay(cnt); // just in case
  2596. }
  2597. }
  2598.  
  2599. },
  2600.  
  2601. 'ytd-watch-flexy::defined': (cProto) => {
  2602.  
  2603. if (!cProto.updateChatLocation498 && typeof cProto.updateChatLocation === 'function' && cProto.updateChatLocation.length === 0) {
  2604. cProto.updateChatLocation498 = cProto.updateChatLocation;
  2605. cProto.updateChatLocation = updateChatLocation498;
  2606. }
  2607.  
  2608. },
  2609.  
  2610.  
  2611.  
  2612. 'ytd-watch-next-secondary-results-renderer::defined': (cProto) => {
  2613. if (!cProto.attached498 && typeof cProto.attached === 'function') {
  2614. cProto.attached498 = cProto.attached;
  2615. cProto.attached = function () {
  2616. if (!inPageRearrange) Promise.resolve(this.hostElement).then(eventMap['ytd-watch-next-secondary-results-renderer::attached']).catch(console.warn);
  2617. return this.attached498();
  2618. }
  2619. }
  2620. if (!cProto.detached498 && typeof cProto.detached === 'function') {
  2621. cProto.detached498 = cProto.detached;
  2622. cProto.detached = function () {
  2623. if (!inPageRearrange) Promise.resolve(this.hostElement).then(eventMap['ytd-watch-next-secondary-results-renderer::detached']).catch(console.warn);
  2624. return this.detached498();
  2625. }
  2626. }
  2627.  
  2628. makeInitAttached('ytd-watch-next-secondary-results-renderer');
  2629.  
  2630. },
  2631.  
  2632. 'ytd-watch-next-secondary-results-renderer::attached': (hostElement) => {
  2633.  
  2634. if (invalidFlexyParent(hostElement)) return;
  2635.  
  2636. // if (inPageRearrange) return;
  2637. console.log(5084, 'ytd-watch-next-secondary-results-renderer::attached');
  2638. if (hostElement instanceof Element) hostElement[__attachedSymbol__] = true;
  2639. if (!(hostElement instanceof HTMLElement_) || !(hostElement.classList.length > 0) || hostElement.closest('noscript')) return;
  2640. if (hostElement.isConnected !== true) return;
  2641. // if (hostElement.__connectedFlg__ !== 4) return;
  2642. // hostElement.__connectedFlg__ = 5;
  2643. if (hostElement instanceof HTMLElement_ && hostElement.matches('#columns #related ytd-watch-next-secondary-results-renderer') && !hostElement.matches('#right-tabs ytd-watch-next-secondary-results-renderer, [hidden] ytd-watch-next-secondary-results-renderer')) {
  2644. elements.related = hostElement.closest('#related');
  2645. hostElement.setAttribute111('tyt-videos-list', '');
  2646. }
  2647. // console.log('ytd-watch-next-secondary-results-renderer::attached', hostElement);
  2648. },
  2649.  
  2650. 'ytd-watch-next-secondary-results-renderer::detached': (hostElement) => {
  2651. // if (inPageRearrange) return;
  2652. console.log(5084, 'ytd-watch-next-secondary-results-renderer::detached');
  2653. if (!(hostElement instanceof HTMLElement_) || hostElement.closest('noscript')) return;
  2654. if (hostElement.isConnected !== false) return;
  2655. // if (hostElement.__connectedFlg__ !== 8) return;
  2656. // hostElement.__connectedFlg__ = 9;
  2657. if (hostElement.hasAttribute000('tyt-videos-list')) {
  2658. elements.related = null;
  2659. hostElement.removeAttribute000('tyt-videos-list');
  2660. }
  2661. console.log('ytd-watch-next-secondary-results-renderer::detached', hostElement);
  2662. },
  2663.  
  2664.  
  2665. 'settingCommentsVideoId': (hostElement) => {
  2666. if (!(hostElement instanceof HTMLElement_) || !(hostElement.classList.length > 0) || hostElement.closest('noscript')) return;
  2667. const cnt = insp(hostElement);
  2668. const commentsArea = elements.comments;
  2669. if (commentsArea !== hostElement || hostElement.isConnected !== true || cnt.isAttached !== true || !cnt.data || cnt.hidden !== false) return;
  2670. const ytdFlexyElm = elements.flexy;
  2671. const ytdFlexyCnt = ytdFlexyElm ? insp(ytdFlexyElm) : null;
  2672. if (ytdFlexyCnt && ytdFlexyCnt.videoId) {
  2673. hostElement.setAttribute111('tyt-comments-video-id', ytdFlexyCnt.videoId)
  2674. } else {
  2675. hostElement.removeAttribute000('tyt-comments-video-id')
  2676. }
  2677. },
  2678. 'checkCommentsShouldBeHidden': (lockId) => {
  2679.  
  2680. if (lockGet['checkCommentsShouldBeHiddenLock'] !== lockId) return;
  2681.  
  2682. // commentsArea's attribute: tyt-comments-video-id
  2683. // ytdFlexyElm's attribute: video-id
  2684.  
  2685.  
  2686. const commentsArea = elements.comments;
  2687. const ytdFlexyElm = elements.flexy;
  2688. if (commentsArea && ytdFlexyElm && !commentsArea.hasAttribute000('hidden')) {
  2689. const ytdFlexyCnt = insp(ytdFlexyElm);
  2690. if (typeof ytdFlexyCnt.videoId === 'string') {
  2691. const commentsVideoId = commentsArea.getAttribute('tyt-comments-video-id');
  2692. if (commentsVideoId && commentsVideoId !== ytdFlexyCnt.videoId) {
  2693. commentsArea.setAttribute111('hidden', '');
  2694. // removeKeepCommentsScroller();
  2695. }
  2696. }
  2697. }
  2698.  
  2699. },
  2700. 'ytd-comments::defined': (cProto) => {
  2701.  
  2702. if (!cProto.attached498 && typeof cProto.attached === 'function') {
  2703. cProto.attached498 = cProto.attached;
  2704. cProto.attached = function () {
  2705. if (!inPageRearrange) Promise.resolve(this.hostElement).then(eventMap['ytd-comments::attached']).catch(console.warn);
  2706. // Promise.resolve(this.hostElement).then(eventMap['ytd-comments::dataChanged_']).catch(console.warn);
  2707. return this.attached498();
  2708. }
  2709. }
  2710. if (!cProto.detached498 && typeof cProto.detached === 'function') {
  2711. cProto.detached498 = cProto.detached;
  2712. cProto.detached = function () {
  2713. if (!inPageRearrange) Promise.resolve(this.hostElement).then(eventMap['ytd-comments::detached']).catch(console.warn);
  2714. // Promise.resolve(this.hostElement).then(eventMap['ytd-comments::dataChanged_']).catch(console.warn);
  2715. return this.detached498();
  2716. }
  2717. }
  2718.  
  2719. cProto._createPropertyObserver('data', '_dataChanged498', undefined)
  2720. cProto._dataChanged498 = function () {
  2721. // console.log('_dataChanged498', this.hostElement)
  2722. Promise.resolve(this.hostElement).then(eventMap['ytd-comments::_dataChanged498']).catch(console.warn);
  2723. }
  2724.  
  2725.  
  2726. // if (!cProto.dataChanged498_ && typeof cProto.dataChanged_ === 'function') {
  2727. // cProto.dataChanged498_ = cProto.dataChanged_;
  2728. // cProto.dataChanged_ = function () {
  2729. // Promise.resolve(this.hostElement).then(eventMap['ytd-comments::dataChanged_']).catch(console.warn);
  2730. // return this.dataChanged498_();
  2731. // }
  2732. // }
  2733.  
  2734. makeInitAttached('ytd-comments');
  2735.  
  2736. },
  2737.  
  2738. 'ytd-comments::_dataChanged498': (hostElement) => {
  2739. // console.log(18984, hostElement.hasAttribute('tyt-comments-area'))
  2740. if (!hostElement.hasAttribute000('tyt-comments-area')) return;
  2741. let commentsDataStatus = 0;
  2742. const cnt = insp(hostElement);
  2743. const data = cnt ? cnt.data : null
  2744. const contents = data ? data.contents : null;
  2745. if (data) {
  2746. if (contents && contents.length === 1 && contents[0].messageRenderer) {
  2747. commentsDataStatus = 2;
  2748. }
  2749. if (contents && contents.length > 1 && contents[0].commentThreadRenderer) {
  2750. commentsDataStatus = 1;
  2751. }
  2752. }
  2753. if (commentsDataStatus) {
  2754. hostElement.setAttribute111('tyt-comments-data-status', commentsDataStatus);
  2755. // ytdFlexyElm.setAttribute111('tyt-comment-disabled', '')
  2756. } else {
  2757. // ytdFlexyElm.removeAttribute000('tyt-comment-disabled')
  2758. hostElement.removeAttribute000('tyt-comments-data-status')
  2759. }
  2760. Promise.resolve(hostElement).then(eventMap['settingCommentsVideoId']).catch(console.warn);
  2761. },
  2762.  
  2763. 'ytd-comments::attached': async (hostElement) => {
  2764.  
  2765. if (invalidFlexyParent(hostElement)) return;
  2766.  
  2767. // if (inPageRearrange) return;
  2768. console.log(5084, 'ytd-comments::attached');
  2769. if (hostElement instanceof Element) hostElement[__attachedSymbol__] = true;
  2770. if (!(hostElement instanceof HTMLElement_) || !(hostElement.classList.length > 0) || hostElement.closest('noscript')) return;
  2771. if (hostElement.isConnected !== true) return;
  2772. // if (hostElement.__connectedFlg__ !== 4) return;
  2773. // hostElement.__connectedFlg__ = 5;
  2774. if (!hostElement || hostElement.id !== 'comments') return;
  2775. // if (!hostElement || hostElement.closest('[hidden]')) return;
  2776. elements.comments = hostElement;
  2777. console.log('ytd-comments::attached')
  2778. Promise.resolve(hostElement).then(eventMap['settingCommentsVideoId']).catch(console.warn);
  2779.  
  2780. aoComment.observe(hostElement, { attributes: true });
  2781. hostElement.setAttribute111('tyt-comments-area', '');
  2782.  
  2783. const lockId = lockSet['rightTabReadyLock02'];
  2784. await rightTabsProvidedPromise.then();
  2785. if (lockGet['rightTabReadyLock02'] !== lockId) return;
  2786.  
  2787. if (elements.comments !== hostElement) return;
  2788. if (hostElement.isConnected === false) return;
  2789. console.log(7932, 'comments');
  2790.  
  2791. // if(!elements.comments || elements.comments.isConnected === false) return;
  2792. if (hostElement && !hostElement.closest('#right-tabs')) {
  2793. document.querySelector('#tab-comments').assignChildern111(null, hostElement, null);
  2794. } else {
  2795.  
  2796. const shouldTabVisible = elements.comments && elements.comments.closest('#tab-comments') && !elements.comments.closest('[hidden]');
  2797.  
  2798. document.querySelector('[tyt-tab-content="#tab-comments"]').classList.toggle('tab-btn-hidden', !shouldTabVisible);
  2799.  
  2800. // document.querySelector('#tab-comments').classList.remove('tab-content-hidden')
  2801. // document.querySelector('[tyt-tab-content="#tab-comments"]').classList.remove('tab-btn-hidden')
  2802.  
  2803. Promise.resolve(lockSet['removeKeepCommentsScrollerLock']).then(removeKeepCommentsScroller).catch(console.warn);
  2804.  
  2805. }
  2806.  
  2807. },
  2808. 'ytd-comments::detached': (hostElement) => {
  2809. // if (inPageRearrange) return;
  2810. console.log(5084, 'ytd-comments::detached');
  2811. // console.log(858, hostElement)
  2812. if (!(hostElement instanceof HTMLElement_) || hostElement.closest('noscript')) return;
  2813. if (hostElement.isConnected !== false) return;
  2814. // if (hostElement.__connectedFlg__ !== 8) return;
  2815. // hostElement.__connectedFlg__ = 9;
  2816.  
  2817. if (hostElement.hasAttribute000('tyt-comments-area')) {
  2818. // foComments.disconnect();
  2819. // foComments.takeRecords();
  2820. hostElement.removeAttribute000('tyt-comments-area');
  2821. // document.querySelector('#tab-comments').classList.add('tab-content-hidden')
  2822. // document.querySelector('[tyt-tab-content="#tab-comments"]').classList.add('tab-btn-hidden')
  2823.  
  2824.  
  2825. aoComment.disconnect();
  2826. aoComment.takeRecords();
  2827. elements.comments = null;
  2828.  
  2829. document.querySelector('[tyt-tab-content="#tab-comments"]').classList.add('tab-btn-hidden');
  2830.  
  2831. Promise.resolve(lockSet['removeKeepCommentsScrollerLock']).then(removeKeepCommentsScroller).catch(console.warn);
  2832. }
  2833.  
  2834.  
  2835. },
  2836.  
  2837.  
  2838. 'ytd-comments-header-renderer::defined': (cProto) => {
  2839.  
  2840. if (!cProto.attached498 && typeof cProto.attached === 'function') {
  2841. cProto.attached498 = cProto.attached;
  2842. cProto.attached = function () {
  2843. if (!inPageRearrange) Promise.resolve(this.hostElement).then(eventMap['ytd-comments-header-renderer::attached']).catch(console.warn);
  2844. Promise.resolve(this.hostElement).then(eventMap['ytd-comments-header-renderer::dataChanged']).catch(console.warn); // force dataChanged on attached
  2845. return this.attached498();
  2846. }
  2847. }
  2848. if (!cProto.detached498 && typeof cProto.detached === 'function') {
  2849. cProto.detached498 = cProto.detached;
  2850. cProto.detached = function () {
  2851. if (!inPageRearrange) Promise.resolve(this.hostElement).then(eventMap['ytd-comments-header-renderer::detached']).catch(console.warn);
  2852. return this.detached498();
  2853. }
  2854. }
  2855.  
  2856. if (!cProto.dataChanged498 && typeof cProto.dataChanged === 'function') {
  2857. cProto.dataChanged498 = cProto.dataChanged;
  2858. cProto.dataChanged = function () {
  2859. Promise.resolve(this.hostElement).then(eventMap['ytd-comments-header-renderer::dataChanged']).catch(console.warn);
  2860. return this.dataChanged498();
  2861. }
  2862. }
  2863.  
  2864.  
  2865. makeInitAttached('ytd-comments-header-renderer');
  2866.  
  2867.  
  2868. },
  2869.  
  2870.  
  2871. 'ytd-comments-header-renderer::attached': (hostElement) => {
  2872.  
  2873. if (invalidFlexyParent(hostElement)) return;
  2874.  
  2875. // if (inPageRearrange) return;
  2876. console.log(5084, 'ytd-comments-header-renderer::attached');
  2877. if (hostElement instanceof Element) hostElement[__attachedSymbol__] = true;
  2878. if (!(hostElement instanceof HTMLElement_) || !(hostElement.classList.length > 0) || hostElement.closest('noscript')) return;
  2879. if (hostElement.isConnected !== true) return;
  2880. // if (hostElement.__connectedFlg__ !== 4) return;
  2881. // hostElement.__connectedFlg__ = 5;
  2882. if (!hostElement || !hostElement.classList.contains('ytd-item-section-renderer')) return;
  2883. console.log(12991, 'ytd-comments-header-renderer::attached')
  2884. const targetElement = document.querySelector('[tyt-comments-area] ytd-comments-header-renderer');
  2885. if (hostElement === targetElement) {
  2886. hostElement.setAttribute111('tyt-comments-header-field', '');
  2887. } else {
  2888. const parentNode = hostElement.parentNode;
  2889. if (parentNode instanceof HTMLElement_ && parentNode.querySelector('[tyt-comments-header-field]')) {
  2890. hostElement.setAttribute111('tyt-comments-header-field', '')
  2891. }
  2892. }
  2893.  
  2894. },
  2895.  
  2896. 'ytd-comments-header-renderer::detached': (hostElement) => {
  2897. // if (inPageRearrange) return;
  2898. console.log(5084, 'ytd-comments-header-renderer::detached');
  2899.  
  2900. if (!(hostElement instanceof HTMLElement_) || hostElement.closest('noscript')) return;
  2901. if (hostElement.isConnected !== false) return;
  2902. // if (hostElement.__connectedFlg__ !== 8) return;
  2903. // hostElement.__connectedFlg__ = 9;
  2904. console.log(12992, 'ytd-comments-header-renderer::detached')
  2905. if (hostElement.hasAttribute000('field-of-cm-count')) {
  2906.  
  2907. const cmCount = document.querySelector('#tyt-cm-count');
  2908. if (cmCount) {
  2909. cmCount.textContent = '';
  2910. hostElement.removeAttribute000('field-of-cm-count');
  2911.  
  2912. }
  2913. }
  2914. if (hostElement.hasAttribute000('tyt-comments-header-field')) {
  2915. hostElement.removeAttribute000('tyt-comments-header-field');
  2916. }
  2917.  
  2918. },
  2919.  
  2920. 'ytd-comments-header-renderer::dataChanged': (hostElement) => {
  2921.  
  2922. if (!(hostElement instanceof HTMLElement_) || !(hostElement.classList.length > 0) || hostElement.closest('noscript')) return;
  2923.  
  2924. const ytdFlexyElm = elements.flexy;
  2925.  
  2926. let b = false;
  2927. const cnt = insp(hostElement);
  2928. if (cnt && hostElement.closest('#tab-comments') && document.querySelector('#tab-comments ytd-comments-header-renderer') === hostElement) {
  2929. b = true;
  2930. } else if (hostElement instanceof HTMLElement_ && hostElement.parentNode instanceof HTMLElement_ && hostElement.parentNode.querySelector('[tyt-comments-header-field]')) {
  2931. b = true;
  2932. }
  2933. if (b) {
  2934. hostElement.setAttribute111('tyt-comments-header-field', '')
  2935. ytdFlexyElm && ytdFlexyElm.removeAttribute000('tyt-comment-disabled');
  2936. }
  2937.  
  2938. // console.log(1841, [...document.querySelectorAll('#tab-comments ytd-comments-header-renderer')], document.querySelector('#tab-comments ytd-comments-header-renderer') === hostElement, !!hostElement?.parentNode?.querySelector('[tyt-comments-header-field]'))
  2939.  
  2940. if (hostElement.hasAttribute000('tyt-comments-header-field') && hostElement.isConnected === true) {
  2941.  
  2942. // console.log(1842, [...document.querySelectorAll('#tab-comments ytd-comments-header-renderer')], document.querySelector('#tab-comments ytd-comments-header-renderer') === hostElement, !!hostElement?.parentNode?.querySelector('[tyt-comments-header-field]'))
  2943.  
  2944. const data = cnt.data;
  2945. let ez = '';
  2946. if (data.commentsCount && data.commentsCount.runs && data.commentsCount.runs.length >= 1) {
  2947. let max = -1;
  2948. const z = data.commentsCount.runs.map(e => {
  2949. let c = e.text.replace(/\D+/g, '').length;
  2950. if (c > max) max = c;
  2951. return [e.text, c];
  2952. }).filter(a => a[1] === max);
  2953. if (z.length >= 1) {
  2954. ez = z[0][0];
  2955. }
  2956. } else if (data.countText && data.countText.runs && data.countText.runs.length >= 1) {
  2957. let max = -1;
  2958. const z = data.countText.runs.map(e => {
  2959. let c = e.text.replace(/\D+/g, '').length;
  2960. if (c > max) max = c;
  2961. return [e.text, c];
  2962. }).filter(a => a[1] === max);
  2963. if (z.length >= 1) {
  2964. ez = z[0][0];
  2965. }
  2966. }
  2967. const cmCount = document.querySelector('#tyt-cm-count');
  2968. if (ez) {
  2969. hostElement.setAttribute111('field-of-cm-count', '');
  2970. cmCount && (cmCount.textContent = ez.trim());
  2971. } else {
  2972. hostElement.removeAttribute000('field-of-cm-count');
  2973. cmCount && (cmCount.textContent = '');
  2974. console.warn('no text for #tyt-cm-count')
  2975. }
  2976. }
  2977. },
  2978.  
  2979. 'ytd-expander::defined': (cProto) => {
  2980. if (!cProto.attached498 && typeof cProto.attached === 'function') {
  2981. cProto.attached498 = cProto.attached;
  2982. cProto.attached = function () {
  2983. if (!inPageRearrange) Promise.resolve(this.hostElement).then(eventMap['ytd-expander::attached']).catch(console.warn);
  2984. return this.attached498();
  2985. }
  2986. }
  2987. if (!cProto.detached498 && typeof cProto.detached === 'function') {
  2988. cProto.detached498 = cProto.detached;
  2989. cProto.detached = function () {
  2990. if (!inPageRearrange) Promise.resolve(this.hostElement).then(eventMap['ytd-expander::detached']).catch(console.warn);
  2991. return this.detached498();
  2992. }
  2993. }
  2994. if (!cProto.calculateCanCollapse498 && typeof cProto.calculateCanCollapse === 'function') {
  2995. cProto.calculateCanCollapse498 = cProto.calculateCanCollapse;
  2996. cProto.calculateCanCollapse = funcCanCollapse;
  2997.  
  2998.  
  2999. }
  3000.  
  3001. if (!cProto.childrenChanged498 && typeof cProto.childrenChanged === 'function') {
  3002. cProto.childrenChanged498 = cProto.childrenChanged;
  3003. cProto.childrenChanged = function () {
  3004. Promise.resolve(this.hostElement).then(eventMap['ytd-expander::childrenChanged']).catch(console.warn);
  3005. return this.childrenChanged498();
  3006. }
  3007. }
  3008.  
  3009. /*
  3010.  
  3011. console.log('ytd-expander::defined 01');
  3012. CustomElementRegistry.prototype.get.call(customElements, 'ytd-expander').prototype.connectedCallback = connectedCallbackY(CustomElementRegistry.prototype.get.call(customElements, 'ytd-expander').prototype.connectedCallback)
  3013. CustomElementRegistry.prototype.get.call(customElements, 'ytd-expander').prototype.disconnectedCallback = disconnectedCallbackY(CustomElementRegistry.prototype.get.call(customElements, 'ytd-expander').prototype.disconnectedCallback)
  3014. console.log('ytd-expander::defined 02');
  3015.  
  3016. */
  3017.  
  3018. makeInitAttached('ytd-expander');
  3019.  
  3020. },
  3021.  
  3022.  
  3023. 'ytd-expander::childrenChanged': (hostElement) => {
  3024.  
  3025. if (hostElement instanceof Node && hostElement.hasAttribute000('hidden') && hostElement.hasAttribute000('tyt-main-info') && hostElement.firstElementChild) {
  3026. hostElement.removeAttribute('hidden');
  3027. }
  3028. },
  3029.  
  3030. 'ytd-expandable-video-description-body-renderer::defined': (cProto) => {
  3031.  
  3032.  
  3033. if (!cProto.attached498 && typeof cProto.attached === 'function') {
  3034. cProto.attached498 = cProto.attached;
  3035. cProto.attached = function () {
  3036. if (!inPageRearrange) Promise.resolve(this.hostElement).then(eventMap['ytd-expandable-video-description-body-renderer::attached']).catch(console.warn);
  3037. return this.attached498();
  3038. }
  3039. }
  3040. if (!cProto.detached498 && typeof cProto.detached === 'function') {
  3041. cProto.detached498 = cProto.detached;
  3042. cProto.detached = function () {
  3043. if (!inPageRearrange) Promise.resolve(this.hostElement).then(eventMap['ytd-expandable-video-description-body-renderer::detached']).catch(console.warn);
  3044. return this.detached498();
  3045. }
  3046. }
  3047.  
  3048. makeInitAttached('ytd-expandable-video-description-body-renderer')
  3049.  
  3050.  
  3051. },
  3052.  
  3053. 'ytd-expandable-video-description-body-renderer::attached': async (hostElement)=>{
  3054.  
  3055.  
  3056. if(hostElement instanceof HTMLElement_ && isPageDOM(hostElement,'[tyt-info-renderer]') && !hostElement.matches('[tyt-main-info]')){
  3057.  
  3058. elements.infoExpander = hostElement;
  3059. console.log(128384, elements.infoExpander)
  3060.  
  3061.  
  3062. // console.log(1299, hostElement.parentNode, isRightTabsInserted)
  3063.  
  3064. infoExpanderElementProvidedPromise.resolve();
  3065. hostElement.setAttribute111('tyt-main-info', '');
  3066. if (plugin.autoExpandInfoDesc.toUse) {
  3067. plugin.autoExpandInfoDesc.onMainInfoSet(hostElement);
  3068. }
  3069.  
  3070. const lockId = lockSet['rightTabReadyLock03'];
  3071. await rightTabsProvidedPromise.then();
  3072. if (lockGet['rightTabReadyLock03'] !== lockId) return;
  3073.  
  3074. if (elements.infoExpander !== hostElement) return;
  3075. if (hostElement.isConnected === false) return;
  3076. console.log(7932, 'infoExpander');
  3077.  
  3078. elements.infoExpander.classList.add('tyt-main-info'); // add a classname for it
  3079.  
  3080. const infoExpander = elements.infoExpander;
  3081. // const infoExpanderBack = elements.infoExpanderBack;
  3082.  
  3083. // console.log(5438,infoExpander, qt);
  3084. // const dummy = document.createElement('noscript');
  3085. // dummy.setAttribute000('id', 'info-expander-vid');
  3086. // dummy.setAttribute000('video-id', getCurrentVideoId());
  3087. // infoExpander.insertBefore000(dummy, infoExpander.firstChild);
  3088.  
  3089. // aoInfo.observe(infoExpander, { attributes: true, attributeFilter: ['tyt-display-for', 'tyt-video-id'] });
  3090. // zoInfo.observe(infoExpanderBack, { attributes: true, attributeFilter: ['hidden', 'attr-w20ts'], childList: true, subtree: true});
  3091. // new MutationObserver(()=>{
  3092. // console.log(591499)
  3093. // }).observe(infoExpanderBack, {childList: true, subtree: true})
  3094.  
  3095. const inlineExpanderElm = infoExpander.querySelector('ytd-text-inline-expander');
  3096. if (inlineExpanderElm) {
  3097. const mo = new MutationObserver(() => {
  3098. const p = document.querySelector('#tab-info ytd-text-inline-expander');
  3099. sessionStorage.__$$tmp_UseAutoExpandInfoDesc$$__ = p && p.hasAttribute('is-expanded') ? '1' : '';
  3100. if (p) fixInlineExpanderContent();
  3101. });
  3102. mo.observe(inlineExpanderElm, { attributes: ['is-expanded', 'attr-6v8qu', 'hidden'], subtree: true }); // hidden + subtree to trigger the fn by delayedUpdate
  3103. inlineExpanderElm.incAttribute111('attr-6v8qu');
  3104. const cnt = insp(inlineExpanderElm);
  3105.  
  3106. if (cnt) fixInlineExpanderDisplay(cnt);
  3107.  
  3108. }
  3109.  
  3110.  
  3111. if (infoExpander && !infoExpander.closest('#right-tabs')) {
  3112. document.querySelector('#tab-info').assignChildern111(null, infoExpander, null);
  3113. } else {
  3114.  
  3115. if (document.querySelector('[tyt-tab-content="#tab-info"]')) {
  3116. const shouldTabVisible = elements.infoExpander && elements.infoExpander.closest('#tab-info');
  3117. document.querySelector('[tyt-tab-content="#tab-info"]').classList.toggle('tab-btn-hidden', !shouldTabVisible);
  3118. }
  3119. }
  3120.  
  3121. Promise.resolve(lockSet['infoFixLock']).then(infoFix).catch(console.warn); // required when the page is switched from channel to watch
  3122.  
  3123. // if (infoExpander && infoExpander.closest('#right-tabs')) Promise.resolve(lockSet['infoFixLock']).then(infoFix).catch(console.warn);
  3124.  
  3125. // infoExpanderBack.incAttribute111('attr-w20ts');
  3126.  
  3127. // return;
  3128. }
  3129.  
  3130.  
  3131. console.log(5084, 'ytd-expandable-video-description-body-renderer::attached');
  3132. if (hostElement instanceof Element) hostElement[__attachedSymbol__] = true;
  3133. if (!(hostElement instanceof HTMLElement_) || !(hostElement.classList.length > 0) || hostElement.closest('noscript')) return;
  3134. if (hostElement.isConnected !== true) return;
  3135.  
  3136. if (isPageDOM(hostElement, '#tab-info [tyt-main-info]')) {
  3137.  
  3138. // const cnt = insp(hostElement);
  3139. // if(cnt.data){
  3140. // cnt.data = Object.assign({}, cnt.data);
  3141. // }
  3142.  
  3143.  
  3144. } else if (!hostElement.closest('#tab-info')) {
  3145.  
  3146.  
  3147. const bodyRenderer = hostElement;
  3148. let bodyRendererNew = document.querySelector('ytd-expandable-video-description-body-renderer[tyt-info-renderer]');
  3149. if (!bodyRendererNew) {
  3150. bodyRendererNew = document.createElement('ytd-expandable-video-description-body-renderer');
  3151. bodyRendererNew.setAttribute('tyt-info-renderer', '');
  3152. nsTemplateObtain().appendChild(bodyRendererNew);
  3153. }
  3154. // document.querySelector('#tab-info').assignChildern111(null, bodyRendererNew, null);
  3155.  
  3156. const cnt = insp(bodyRendererNew);
  3157. cnt.data = Object.assign({}, insp(bodyRenderer).data);
  3158.  
  3159. const inlineExpanderElm = bodyRendererNew.querySelector('ytd-text-inline-expander');
  3160. const inlineExpanderCnt = insp(inlineExpanderElm);
  3161. fixInlineExpanderMethods(inlineExpanderCnt);
  3162.  
  3163. // insp(bodyRendererNew).data = insp(bodyRenderer).data;
  3164.  
  3165. // if((bodyRendererNew.hasAttribute('hidden')?1:0)^(bodyRenderer.hasAttribute('hidden')?1:0)){
  3166. // if(bodyRenderer.hasAttribute('hidden')) bodyRendererNew.setAttribute('hidden', '');
  3167. // else bodyRendererNew.removeAttribute('hidden');
  3168. // }
  3169.  
  3170. elements.infoExpanderRendererBack = bodyRenderer;
  3171. elements.infoExpanderRendererFront = bodyRendererNew;
  3172. bodyRenderer.setAttribute('tyt-info-renderer-back', '');
  3173. bodyRendererNew.setAttribute('tyt-info-renderer-front', '');
  3174.  
  3175. // elements.infoExpanderBack = {{ytd-expander}};
  3176.  
  3177.  
  3178. }
  3179.  
  3180.  
  3181. },
  3182.  
  3183. 'ytd-expandable-video-description-body-renderer::detached': async ()=>{
  3184. if (!(hostElement instanceof HTMLElement_) || hostElement.closest('noscript')) return;
  3185. if (hostElement.isConnected !== false) return;
  3186. // if (hostElement.__connectedFlg__ !== 8) return;
  3187. // hostElement.__connectedFlg__ = 9;
  3188. // console.log(5992, hostElement)
  3189. if (hostElement.hasAttribute000('tyt-main-info')) {
  3190. console.log(5084, 'ytd-expandable-video-description-body-renderer::detached');
  3191. elements.infoExpander = null;
  3192. hostElement.removeAttribute000('tyt-main-info');
  3193. }
  3194. },
  3195.  
  3196. 'ytd-expander::attached': async (hostElement) => {
  3197.  
  3198. if (invalidFlexyParent(hostElement)) return;
  3199.  
  3200. // if (inPageRearrange) return;
  3201. if (hostElement instanceof Element) hostElement[__attachedSymbol__] = true;
  3202. if (!(hostElement instanceof HTMLElement_) || !(hostElement.classList.length > 0) || hostElement.closest('noscript')) return;
  3203. if (hostElement.isConnected !== true) return;
  3204. // if (hostElement.__connectedFlg__ !== 4) return;
  3205. // hostElement.__connectedFlg__ = 5;
  3206. // console.log(4959, hostElement)
  3207. if (hostElement instanceof HTMLElement_ && hostElement.matches('[tyt-comments-area] #contents ytd-expander#expander') && !hostElement.matches('[hidden] ytd-expander#expander')) {
  3208.  
  3209. hostElement.setAttribute111('tyt-content-comment-entry', '')
  3210. ioComment.observe(hostElement);
  3211. }
  3212. // --------------
  3213.  
  3214. // else if (hostElement instanceof HTMLElement_ && hostElement.matches('ytd-expander#expander.style-scope.ytd-expandable-video-description-body-renderer')) {
  3215. // // && !hostElement.matches('#right-tabs ytd-expander#expander, [hidden] ytd-expander#expander')
  3216.  
  3217. // console.log(5084, 'ytd-expander::attached');
  3218. // const bodyRenderer = hostElement.closest('ytd-expandable-video-description-body-renderer');
  3219. // let bodyRendererNew = document.querySelector('ytd-expandable-video-description-body-renderer[tyt-info-renderer]');
  3220. // if (!bodyRendererNew) {
  3221. // bodyRendererNew = document.createElement('ytd-expandable-video-description-body-renderer');
  3222. // bodyRendererNew.setAttribute('tyt-info-renderer', '');
  3223. // nsTemplateObtain().appendChild(bodyRendererNew);
  3224. // }
  3225. // // document.querySelector('#tab-info').assignChildern111(null, bodyRendererNew, null);
  3226.  
  3227. // insp(bodyRendererNew).data = insp(bodyRenderer).data;
  3228. // // if((bodyRendererNew.hasAttribute('hidden')?1:0)^(bodyRenderer.hasAttribute('hidden')?1:0)){
  3229. // // if(bodyRenderer.hasAttribute('hidden')) bodyRendererNew.setAttribute('hidden', '');
  3230. // // else bodyRendererNew.removeAttribute('hidden');
  3231. // // }
  3232.  
  3233. // elements.infoExpanderRendererBack = bodyRenderer;
  3234. // elements.infoExpanderRendererFront = bodyRendererNew;
  3235. // bodyRenderer.setAttribute('tyt-info-renderer-back','')
  3236. // bodyRendererNew.setAttribute('tyt-info-renderer-front','')
  3237.  
  3238. // elements.infoExpanderBack = hostElement;
  3239. // }
  3240.  
  3241. // --------------
  3242.  
  3243. // console.log('ytd-expander::attached', hostElement);
  3244.  
  3245.  
  3246.  
  3247. },
  3248.  
  3249. 'ytd-expander::detached': (hostElement) => {
  3250. // if (inPageRearrange) return;
  3251. if (!(hostElement instanceof HTMLElement_) || hostElement.closest('noscript')) return;
  3252. if (hostElement.isConnected !== false) return;
  3253. // if (hostElement.__connectedFlg__ !== 8) return;
  3254. // hostElement.__connectedFlg__ = 9;
  3255. // console.log(5992, hostElement)
  3256. if (hostElement.hasAttribute000('tyt-content-comment-entry')) {
  3257. ioComment.unobserve(hostElement);
  3258. hostElement.removeAttribute000('tyt-content-comment-entry')
  3259. } else if (hostElement.hasAttribute000('tyt-main-info')) {
  3260. console.log(5084, 'ytd-expander::detached');
  3261. elements.infoExpander = null;
  3262. hostElement.removeAttribute000('tyt-main-info');
  3263. }
  3264. // console.log('ytd-expander::detached', hostElement);
  3265. },
  3266.  
  3267.  
  3268. 'ytd-live-chat-frame::defined': (cProto) => {
  3269.  
  3270. let lastDomAction = 0;
  3271.  
  3272. if (!cProto.attached498 && typeof cProto.attached === 'function') {
  3273. cProto.attached498 = cProto.attached;
  3274. cProto.attached = function () {
  3275. lastDomAction = Date.now();
  3276. // console.log('chat868-attached', Date.now());
  3277. if (!inPageRearrange) Promise.resolve(this.hostElement).then(eventMap['ytd-live-chat-frame::attached']).catch(console.warn);
  3278. return this.attached498();
  3279. }
  3280. }
  3281. if (!cProto.detached498 && typeof cProto.detached === 'function') {
  3282. cProto.detached498 = cProto.detached;
  3283. cProto.detached = function () {
  3284. lastDomAction = Date.now();
  3285. // console.log('chat868-detached', Date.now());
  3286. if (!inPageRearrange) Promise.resolve(this.hostElement).then(eventMap['ytd-live-chat-frame::detached']).catch(console.warn);
  3287. return this.detached498();
  3288. }
  3289. }
  3290.  
  3291. if (typeof cProto.urlChanged === 'function' && !cProto.urlChanged66 && !cProto.urlChangedAsync12 && cProto.urlChanged.length === 0) {
  3292. cProto.urlChanged66 = cProto.urlChanged;
  3293. let ath = 0;
  3294. cProto.urlChangedAsync12 = async function () {
  3295. const t = ath = (ath & 1073741823) + 1;
  3296. const chatframe = this.chatframe || (this.$ || 0).chatframe || 0;
  3297. if (chatframe instanceof HTMLIFrameElement) {
  3298. if (chatframe.contentDocument === null) {
  3299. await Promise.resolve('#').catch(console.warn);
  3300. if (t !== ath) return;
  3301. }
  3302. await new Promise(resolve => setTimeout_(resolve, 1)).catch(console.warn); // neccessary for Brave
  3303. if (t !== ath) return;
  3304. const isBlankPage = !this.data || this.collapsed;
  3305. const p1 = new Promise(resolve => setTimeout_(resolve, 706)).catch(console.warn);
  3306. const p2 = new Promise(resolve => {
  3307. (new IntersectionObserver((entries, observer) => {
  3308. for (const entry of entries) {
  3309. const rect = entry.boundingClientRect || 0;
  3310. if (isBlankPage || (rect.width > 0 && rect.height > 0)) {
  3311. observer.disconnect();
  3312. resolve('#');
  3313. break;
  3314. }
  3315. }
  3316. })).observe(chatframe);
  3317. }).catch(console.warn);
  3318. await Promise.race([p1, p2]);
  3319. if (t !== ath) return;
  3320. }
  3321. this.urlChanged66();
  3322. }
  3323. cProto.urlChanged = function () {
  3324. this.urlChangedAsync12();
  3325. }
  3326. }
  3327.  
  3328. makeInitAttached('ytd-live-chat-frame');
  3329.  
  3330. },
  3331.  
  3332. 'ytd-live-chat-frame::attached': async (hostElement) => {
  3333.  
  3334. if (invalidFlexyParent(hostElement)) return;
  3335.  
  3336. // if (inPageRearrange) return;
  3337. console.log(5084, 'ytd-live-chat-frame::attached');
  3338. if (hostElement instanceof Element) hostElement[__attachedSymbol__] = true;
  3339. if (!(hostElement instanceof HTMLElement_) || !(hostElement.classList.length > 0) || hostElement.closest('noscript')) return;
  3340. if (hostElement.isConnected !== true) return;
  3341. // if (hostElement.__connectedFlg__ !== 4) return;
  3342. // hostElement.__connectedFlg__ = 5;
  3343. if (!hostElement || hostElement.id !== 'chat') return;
  3344. console.log('ytd-live-chat-frame::attached')
  3345.  
  3346. const lockId = lockSet['ytdLiveAttachedLock'];
  3347. const chatElem = await getGeneralChatElement();
  3348. if (lockGet['ytdLiveAttachedLock'] !== lockId) return;
  3349.  
  3350. if (chatElem === hostElement) {
  3351. elements.chat = chatElem;
  3352. aoChat.observe(chatElem, { attributes: true });
  3353. const isFlexyReady = (elements.flexy instanceof Element);
  3354. chatElem.setAttribute111('tyt-active-chat-frame', isFlexyReady ? 'CF': 'C');
  3355.  
  3356. const chatContainer = chatElem ? (chatElem.closest('#chat-container') || chatElem) : null;
  3357. if (chatContainer && !chatContainer.hasAttribute000('tyt-chat-container')) {
  3358. for (const p of document.querySelectorAll('[tyt-chat-container]')) {
  3359. p.removeAttribute000('[tyt-chat-container]');
  3360. }
  3361. chatContainer.setAttribute111('tyt-chat-container', '')
  3362. }
  3363. Promise.resolve(lockSet['layoutFixLock']).then(layoutFix);
  3364. } else {
  3365. console.log('Issue found in ytd-live-chat-frame::attached', chatElem, hostElement);
  3366. }
  3367. },
  3368.  
  3369. 'ytd-live-chat-frame::detached': (hostElement) => {
  3370. // if (inPageRearrange) return;
  3371. console.log(5084, 'ytd-live-chat-frame::detached');
  3372.  
  3373. if (!(hostElement instanceof HTMLElement_) || hostElement.closest('noscript')) return;
  3374. if (hostElement.isConnected !== false) return;
  3375. // if (hostElement.__connectedFlg__ !== 8) return;
  3376. // hostElement.__connectedFlg__ = 9;
  3377. console.log('ytd-live-chat-frame::detached')
  3378. if (hostElement.hasAttribute000('tyt-active-chat-frame')) {
  3379. aoChat.disconnect();
  3380. aoChat.takeRecords();
  3381. hostElement.removeAttribute000('tyt-active-chat-frame');
  3382. elements.chat = null;
  3383.  
  3384. const ytdFlexyElm = elements.flexy;
  3385. if (ytdFlexyElm) {
  3386. ytdFlexyElm.removeAttribute000('tyt-chat-collapsed')
  3387. ytdFlexyElm.setAttribute111('tyt-chat', '');
  3388. }
  3389. }
  3390.  
  3391. },
  3392.  
  3393. 'ytd-engagement-panel-section-list-renderer::defined': (cProto) => {
  3394.  
  3395. if (!cProto.attached498 && typeof cProto.attached === 'function') {
  3396. cProto.attached498 = cProto.attached;
  3397. cProto.attached = function () {
  3398. if (!inPageRearrange) Promise.resolve(this.hostElement).then(eventMap['ytd-engagement-panel-section-list-renderer::attached']).catch(console.warn);
  3399. return this.attached498();
  3400. }
  3401. }
  3402. if (!cProto.detached498 && typeof cProto.detached === 'function') {
  3403. cProto.detached498 = cProto.detached;
  3404. cProto.detached = function () {
  3405. if (!inPageRearrange) Promise.resolve(this.hostElement).then(eventMap['ytd-engagement-panel-section-list-renderer::detached']).catch(console.warn);
  3406. return this.detached498();
  3407. }
  3408. }
  3409. makeInitAttached('ytd-engagement-panel-section-list-renderer');
  3410. },
  3411.  
  3412. 'ytd-engagement-panel-section-list-renderer::bindTarget': (hostElement) => {
  3413.  
  3414.  
  3415. if (hostElement.matches('#panels.ytd-watch-flexy > ytd-engagement-panel-section-list-renderer[target-id][visibility]')) {
  3416. hostElement.setAttribute111('tyt-egm-panel', '');
  3417. Promise.resolve(lockSet['updateEgmPanelsLock']).then(updateEgmPanels).catch(console.warn);
  3418. aoEgmPanels.observe(hostElement, { attributes: true, attributeFilter: ['visibility', 'hidden'] });
  3419.  
  3420. // console.log(5094, 2, 'ytd-engagement-panel-section-list-renderer::attached', hostElement);
  3421. }
  3422.  
  3423. },
  3424.  
  3425.  
  3426. 'ytd-engagement-panel-section-list-renderer::attached': (hostElement) => {
  3427.  
  3428. if (invalidFlexyParent(hostElement)) return;
  3429.  
  3430. // if (inPageRearrange) return;
  3431.  
  3432. console.log(5084, 'ytd-engagement-panel-section-list-renderer::attached');
  3433. if (hostElement instanceof Element) hostElement[__attachedSymbol__] = true;
  3434. if (!(hostElement instanceof HTMLElement_) || !(hostElement.classList.length > 0) || hostElement.closest('noscript')) return;
  3435. if (hostElement.isConnected !== true) return;
  3436. // if (hostElement.__connectedFlg__ !== 4) return;
  3437. // hostElement.__connectedFlg__ = 5;
  3438. // console.log('ytd-engagement-panel-section-list-renderer::attached', hostElement)
  3439. // console.log(5094, 1, 'ytd-engagement-panel-section-list-renderer::attached', hostElement);
  3440.  
  3441. if (!hostElement.matches('#panels.ytd-watch-flexy > ytd-engagement-panel-section-list-renderer')) return;
  3442.  
  3443.  
  3444. if (hostElement.hasAttribute000('target-id') && hostElement.hasAttribute000('visibility')) {
  3445.  
  3446. Promise.resolve(hostElement).then(eventMap['ytd-engagement-panel-section-list-renderer::bindTarget']).catch(console.warn);
  3447. } else {
  3448.  
  3449. hostElement.setAttribute000('tyt-egm-panel-jclmd', '');
  3450. moEgmPanelReady.observe(hostElement, { attributes: true, attributeFilter: ['visibility', 'target-id'] });
  3451.  
  3452. }
  3453. },
  3454.  
  3455. 'ytd-engagement-panel-section-list-renderer::detached': (hostElement) => {
  3456. // if (inPageRearrange) return;
  3457.  
  3458. console.log(5084, 'ytd-engagement-panel-section-list-renderer::detached');
  3459. if (!(hostElement instanceof HTMLElement_) || hostElement.closest('noscript')) return;
  3460. if (hostElement.isConnected !== false) return;
  3461. // if (hostElement.__connectedFlg__ !== 8) return;
  3462. // hostElement.__connectedFlg__ = 9;
  3463. if (hostElement.hasAttribute000('tyt-egm-panel')) {
  3464. hostElement.removeAttribute000('tyt-egm-panel');
  3465. Promise.resolve(lockSet['updateEgmPanelsLock']).then(updateEgmPanels).catch(console.warn);
  3466. } else if (hostElement.hasAttribute000('tyt-egm-panel-jclmd')) {
  3467. hostElement.removeAttribute000('tyt-egm-panel-jclmd');
  3468. moEgmPanelReadyClearFn();
  3469. }
  3470. },
  3471.  
  3472. 'ytd-watch-metadata::defined': (cProto) => {
  3473.  
  3474. if (!cProto.attached498 && typeof cProto.attached === 'function') {
  3475. cProto.attached498 = cProto.attached;
  3476. cProto.attached = function () {
  3477. if (!inPageRearrange) Promise.resolve(this.hostElement).then(eventMap['ytd-watch-metadata::attached']).catch(console.warn);
  3478. return this.attached498();
  3479. }
  3480. }
  3481. if (!cProto.detached498 && typeof cProto.detached === 'function') {
  3482. cProto.detached498 = cProto.detached;
  3483. cProto.detached = function () {
  3484. if (!inPageRearrange) Promise.resolve(this.hostElement).then(eventMap['ytd-watch-metadata::detached']).catch(console.warn);
  3485. return this.detached498();
  3486. }
  3487. }
  3488.  
  3489. makeInitAttached('ytd-watch-metadata');
  3490. },
  3491.  
  3492.  
  3493.  
  3494. 'ytd-watch-metadata::attached': (hostElement) => {
  3495.  
  3496. if (invalidFlexyParent(hostElement)) return;
  3497.  
  3498. // if (inPageRearrange) return;
  3499.  
  3500. console.log(5084, 'ytd-watch-metadata::attached');
  3501. if (hostElement instanceof Element) hostElement[__attachedSymbol__] = true;
  3502. if (!(hostElement instanceof HTMLElement_) || !(hostElement.classList.length > 0) || hostElement.closest('noscript')) return;
  3503. if (hostElement.isConnected !== true) return;
  3504. // if (hostElement.__connectedFlg__ !== 4) return;
  3505. // hostElement.__connectedFlg__ = 5;
  3506.  
  3507. if (plugin.fullChannelNameOnHover.activated) plugin.fullChannelNameOnHover.onNavigateFinish();
  3508. },
  3509.  
  3510. 'ytd-watch-metadata::detached': (hostElement) => {
  3511. // if (inPageRearrange) return;
  3512.  
  3513. console.log(5084, 'ytd-watch-metadata::detached');
  3514. if (!(hostElement instanceof HTMLElement_) || hostElement.closest('noscript')) return;
  3515. if (hostElement.isConnected !== false) return;
  3516. // if (hostElement.__connectedFlg__ !== 8) return;
  3517. // hostElement.__connectedFlg__ = 9;
  3518.  
  3519. },
  3520.  
  3521.  
  3522.  
  3523. 'ytd-playlist-panel-renderer::defined': (cProto) => {
  3524.  
  3525. if (!cProto.attached498 && typeof cProto.attached === 'function') {
  3526. cProto.attached498 = cProto.attached;
  3527. cProto.attached = function () {
  3528. if (!inPageRearrange) Promise.resolve(this.hostElement).then(eventMap['ytd-playlist-panel-renderer::attached']).catch(console.warn);
  3529. return this.attached498();
  3530. }
  3531. }
  3532. if (!cProto.detached498 && typeof cProto.detached === 'function') {
  3533. cProto.detached498 = cProto.detached;
  3534. cProto.detached = function () {
  3535. if (!inPageRearrange) Promise.resolve(this.hostElement).then(eventMap['ytd-playlist-panel-renderer::detached']).catch(console.warn);
  3536. return this.detached498();
  3537. }
  3538. }
  3539.  
  3540. makeInitAttached('ytd-playlist-panel-renderer');
  3541. },
  3542.  
  3543.  
  3544.  
  3545. 'ytd-playlist-panel-renderer::attached': (hostElement) => {
  3546.  
  3547. if (invalidFlexyParent(hostElement)) return;
  3548.  
  3549. // if (inPageRearrange) return;
  3550.  
  3551. console.log(5084, 'ytd-playlist-panel-renderer::attached');
  3552. if (hostElement instanceof Element) hostElement[__attachedSymbol__] = true;
  3553. if (!(hostElement instanceof HTMLElement_) || !(hostElement.classList.length > 0) || hostElement.closest('noscript')) return;
  3554. if (hostElement.isConnected !== true) return;
  3555. // if (hostElement.__connectedFlg__ !== 4) return;
  3556. // hostElement.__connectedFlg__ = 5;
  3557.  
  3558. elements.playlist = hostElement;
  3559.  
  3560. aoPlayList.observe(hostElement, { attributes: true, attributeFilter: ['hidden', 'collapsed', 'attr-1y6nu'] });
  3561. hostElement.incAttribute111('attr-1y6nu')
  3562.  
  3563.  
  3564. },
  3565.  
  3566. 'ytd-playlist-panel-renderer::detached': (hostElement) => {
  3567. // if (inPageRearrange) return;
  3568.  
  3569. console.log(5084, 'ytd-playlist-panel-renderer::detached');
  3570. if (!(hostElement instanceof HTMLElement_) || hostElement.closest('noscript')) return;
  3571. if (hostElement.isConnected !== false) return;
  3572. // if (hostElement.__connectedFlg__ !== 8) return;
  3573. // hostElement.__connectedFlg__ = 9;
  3574.  
  3575. },
  3576.  
  3577.  
  3578.  
  3579.  
  3580.  
  3581. '_yt_playerProvided': () => {
  3582. mLoaded.flag |= 4;
  3583. document.documentElement.setAttribute111('tabview-loaded', mLoaded.makeString());
  3584. },
  3585. 'relatedElementProvided': (target) => {
  3586. if (target.closest('[hidden]')) return;
  3587. elements.related = target;
  3588. console.log('relatedElementProvided')
  3589. videosElementProvidedPromise.resolve();
  3590. },
  3591. 'onceInfoExpanderElementProvidedPromised': () => {
  3592. console.log('hide-default-text-inline-expander');
  3593. const ytdFlexyElm = elements.flexy;
  3594. if (ytdFlexyElm) {
  3595. ytdFlexyElm.setAttribute111('hide-default-text-inline-expander', '');
  3596. }
  3597. },
  3598.  
  3599. 'refreshSecondaryInner': (lockId) => {
  3600.  
  3601.  
  3602. if (lockGet['refreshSecondaryInnerLock'] !== lockId) return;
  3603. /*
  3604. ytd-watch-flexy:not([panels-beside-player]):not([fixed-panels]) #panels-full-bleed-container.ytd-watch-flexy{
  3605. display: none;}
  3606. #player-full-bleed-container.ytd-watch-flexy{
  3607. position: relative;
  3608. flex: 1;}
  3609. */
  3610.  
  3611. const ytdFlexyElm = elements.flexy;
  3612. // if(ytdFlexyElm && ytdFlexyElm.matches('ytd-watch-flexy[fixed-panels][theater]')){
  3613. // // ytdFlexyElm.fixedPanels = true;
  3614. // ytdFlexyElm.removeAttribute000('fixed-panels');
  3615. // }
  3616.  
  3617. if (ytdFlexyElm && ytdFlexyElm.matches('ytd-watch-flexy[theater][flexy][full-bleed-player]:not([full-bleed-no-max-width-columns])')) {
  3618. // ytdFlexyElm.fullBleedNoMaxWidthColumns = true;
  3619. ytdFlexyElm.setAttribute111('full-bleed-no-max-width-columns', '');
  3620. }
  3621.  
  3622. const related = elements.related;
  3623. if (related && related.isConnected && !related.closest('#right-tabs #tab-videos')) {
  3624. document.querySelector('#tab-videos').assignChildern111(null, related, null);
  3625. }
  3626. const infoExpander = elements.infoExpander;
  3627. if (infoExpander && infoExpander.isConnected && !infoExpander.closest('#right-tabs #tab-info')) {
  3628. document.querySelector('#tab-info').assignChildern111(null, infoExpander, null);
  3629. } else {
  3630. // if (infoExpander && ytdFlexyElm && shouldFixInfo) {
  3631. // shouldFixInfo = false;
  3632. // Promise.resolve(lockSet['infoFixLock']).then(infoFix).catch(console.warn);
  3633. // }
  3634. }
  3635.  
  3636. const commentsArea = elements.comments;
  3637. if (commentsArea) {
  3638. const isConnected = commentsArea.isConnected;
  3639. if (isConnected && !commentsArea.closest('#right-tabs #tab-comments')) {
  3640. const tab = document.querySelector('#tab-comments');
  3641. tab.assignChildern111(null, commentsArea, null);
  3642. } else {
  3643. // if (!isConnected || tab.classList.contains('tab-content-hidden')) removeKeepCommentsScroller();
  3644. }
  3645. }
  3646.  
  3647.  
  3648.  
  3649.  
  3650.  
  3651.  
  3652.  
  3653. },
  3654.  
  3655. 'yt-navigate-finish': (evt) => {
  3656.  
  3657. const ytdAppElm = document.querySelector('ytd-page-manager#page-manager.style-scope.ytd-app');
  3658. const ytdAppCnt = insp(ytdAppElm);
  3659. pageType = ytdAppCnt ? (ytdAppCnt.data || 0).page : null;
  3660.  
  3661. if (!document.querySelector('ytd-watch-flexy #player')) return;
  3662. // shouldFixInfo = true;
  3663. // console.log('yt-navigate-finish')
  3664. const flexyArr = [...document.querySelectorAll('ytd-watch-flexy')].filter(e => !e.closest('[hidden]') && e.querySelector('#player'));
  3665. if (flexyArr.length === 1) {
  3666. // const lockId = lockSet['yt-navigate-finish-videos'];
  3667. elements.flexy = flexyArr[0];
  3668. if (isRightTabsInserted) {
  3669. Promise.resolve(lockSet['refreshSecondaryInnerLock']).then(eventMap['refreshSecondaryInner']).catch(console.warn);
  3670. Promise.resolve(lockSet['removeKeepCommentsScrollerLock']).then(removeKeepCommentsScroller).catch(console.warn);
  3671. } else {
  3672. navigateFinishedPromise.resolve();
  3673. if (plugin.minibrowser.toUse) plugin.minibrowser.activate();
  3674. if (plugin.autoExpandInfoDesc.toUse) plugin.autoExpandInfoDesc.activate();
  3675. if (plugin.fullChannelNameOnHover.toUse) plugin.fullChannelNameOnHover.activate();
  3676. }
  3677. const chat = elements.chat;
  3678. if (chat instanceof Element) {
  3679. chat.setAttribute111('tyt-active-chat-frame', 'CF'); // chat and flexy ready
  3680. }
  3681. const infoExpander = elements.infoExpander;
  3682. if (infoExpander && infoExpander.closest('#right-tabs')){
  3683. Promise.resolve(lockSet['infoFixLock']).then(infoFix).catch(console.warn);
  3684. }
  3685. Promise.resolve(lockSet['layoutFixLock']).then(layoutFix);
  3686. if (plugin.fullChannelNameOnHover.activated) plugin.fullChannelNameOnHover.onNavigateFinish();
  3687. }
  3688. },
  3689.  
  3690. 'onceInsertRightTabs': () => {
  3691.  
  3692.  
  3693. // if(lockId !== lockGet['yt-navigate-finish-videos']) return;
  3694. const related = elements.related;
  3695. let rightTabs = document.querySelector('#right-tabs');
  3696. if (!document.querySelector('#right-tabs') && related) {
  3697. getLangForPage();
  3698. let docTmp = document.createElement('template');
  3699. docTmp.innerHTML = createHTML(getTabsHTML());
  3700. let newElm = docTmp.content.firstElementChild;
  3701. if (newElm !== null) {
  3702. inPageRearrange = true;
  3703. related.parentNode.insertBefore000(newElm, related);
  3704. inPageRearrange = false;
  3705. }
  3706. rightTabs = newElm;
  3707. rightTabs.querySelector('[tyt-tab-content="#tab-comments"]').classList.add('tab-btn-hidden');
  3708.  
  3709. const secondaryWrapper = document.createElement('secondary-wrapper');
  3710. const secondaryInner = document.querySelector('#secondary-inner.style-scope.ytd-watch-flexy');
  3711. inPageRearrange = true;
  3712. secondaryWrapper.replaceChildren000(...secondaryInner.childNodes);
  3713. secondaryInner.insertBefore000(secondaryWrapper, secondaryInner.firstChild);
  3714. inPageRearrange = false;
  3715.  
  3716. rightTabs.querySelector('#material-tabs').addEventListener('click', eventMap['tabs-btn-click'], true)
  3717.  
  3718. inPageRearrange = true;
  3719. if (!rightTabs.closest('secondary-wrapper')) secondaryWrapper.appendChild000(rightTabs);
  3720. inPageRearrange = false;
  3721.  
  3722. }
  3723. if (rightTabs) {
  3724. isRightTabsInserted = true;
  3725. const ioTabBtns = new IntersectionObserver((entries) => {
  3726. for (const entry of entries) {
  3727. const rect = entry.boundingClientRect;
  3728. entry.target.classList.toggle('tab-btn-visible', rect.width && rect.height)
  3729. }
  3730. }, { rootMargin: '0px' });
  3731. for (const btn of document.querySelectorAll('.tab-btn[tyt-tab-content]')) {
  3732. ioTabBtns.observe(btn);
  3733. }
  3734. if (!related.closest('#right-tabs')) {
  3735. document.querySelector('#tab-videos').assignChildern111(null, related, null);
  3736. }
  3737. const infoExpander = elements.infoExpander;
  3738. if (infoExpander && !infoExpander.closest('#right-tabs')) {
  3739. document.querySelector('#tab-info').assignChildern111(null, infoExpander, null);
  3740. }
  3741. const commentsArea = elements.comments;
  3742. if (commentsArea && !commentsArea.closest('#right-tabs')) {
  3743. document.querySelector('#tab-comments').assignChildern111(null, commentsArea, null);
  3744. }
  3745. rightTabsProvidedPromise.resolve();
  3746. roRightTabs.disconnect();
  3747. roRightTabs.observe(rightTabs);
  3748. const ytdFlexyElm = elements.flexy;
  3749. const aoFlexy = new MutationObserver(eventMap['aoFlexyFn']);
  3750. aoFlexy.observe(ytdFlexyElm, { attributes: true });
  3751. // Promise.resolve(lockSet['tabsStatusCorrectionLock']).then(eventMap['tabsStatusCorrection']).catch(console.warn);
  3752.  
  3753. Promise.resolve(lockSet['fixInitialTabStateLock']).then(eventMap['fixInitialTabStateFn']).catch(console.warn);
  3754.  
  3755. ytdFlexyElm.incAttribute111('attr-7qlsy'); // tabsStatusCorrectionLock and video-id
  3756.  
  3757.  
  3758. }
  3759.  
  3760. },
  3761.  
  3762. 'aoFlexyFn': () => {
  3763.  
  3764. Promise.resolve(lockSet['checkCommentsShouldBeHiddenLock']).then(eventMap['checkCommentsShouldBeHidden']).catch(console.warn);
  3765.  
  3766. Promise.resolve(lockSet['refreshSecondaryInnerLock']).then(eventMap['refreshSecondaryInner']).catch(console.warn);
  3767.  
  3768. Promise.resolve(lockSet['tabsStatusCorrectionLock']).then(eventMap['tabsStatusCorrection']).catch(console.warn);
  3769.  
  3770. const videoId = getCurrentVideoId();
  3771. if (videoId !== tmpLastVideoId) {
  3772. tmpLastVideoId = videoId;
  3773. Promise.resolve(lockSet['updateOnVideoIdChangedLock']).then(eventMap['updateOnVideoIdChanged']).catch(console.warn);
  3774. }
  3775.  
  3776. },
  3777.  
  3778. 'twoColumnChanged10': (lockId) => {
  3779.  
  3780. if (lockId !== lockGet['twoColumnChanged10Lock']) return;
  3781. for (const continuation of document.querySelectorAll('#tab-videos ytd-watch-next-secondary-results-renderer ytd-continuation-item-renderer')) {
  3782. if (continuation.closest('[hidden]')) continue;
  3783. const cnt = insp(continuation);
  3784. if (typeof cnt.showButton === 'boolean') {
  3785. if (cnt.showButton === false) continue;
  3786. cnt.showButton = false;
  3787. const behavior = (cnt.ytRendererBehavior || cnt);
  3788. if (typeof behavior.invalidate === 'function') {
  3789. behavior.invalidate(!1);
  3790. }
  3791. }
  3792. }
  3793.  
  3794. },
  3795.  
  3796. 'tabsStatusCorrection': (lockId) => {
  3797. if (lockId !== lockGet['tabsStatusCorrectionLock']) return;
  3798. const ytdFlexyElm = elements.flexy;
  3799. if (!ytdFlexyElm) return;
  3800. const p = tabAStatus;
  3801. const q = calculationFn(p, 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128);
  3802.  
  3803. let resetForPanelDisappeared = false;
  3804. if (p !== q) {
  3805. console.log(388, p, q)
  3806. let actioned = false;
  3807. if ((p & 128) === 0 && (q & 128) === 128) {
  3808. lastPanel = 'playlist'
  3809. } else if ((p & 8) === 0 && (q & 8) === 8) {
  3810. lastPanel = 'chat'
  3811. } else if ((((p & 4) == 4 && (q & (4 | 8)) == (0 | 0)) || ((p & 8) == 8 && (q & (4 | 8)) === (0 | 0))) && lastPanel === 'chat') {
  3812. // 24 -> 16 = -8; 'd'
  3813. lastPanel = (lastTab || '');
  3814. resetForPanelDisappeared = true;
  3815. } else if ((p & (4 | 8)) === 8 && (q & (4 | 8)) === 4 && lastPanel === 'chat') {
  3816. // click close
  3817. lastPanel = (lastTab || '');
  3818. resetForPanelDisappeared = true;
  3819. } else if ((p & 128) === 128 && (q & 128) === 0 && lastPanel === 'playlist') {
  3820.  
  3821. lastPanel = (lastTab || '');
  3822. resetForPanelDisappeared = true;
  3823. }
  3824. tabAStatus = q;
  3825.  
  3826. let bFixForResizedTab = false;
  3827.  
  3828. if ((q ^ 2) === 2 && bFixForResizedTabLater) {
  3829. bFixForResizedTab = true;
  3830. }
  3831.  
  3832. if ((p & 16) === 16 & (q & 16) === 0) {
  3833. Promise.resolve(lockSet['twoColumnChanged10Lock']).then(eventMap['twoColumnChanged10']).catch(console.warn);
  3834. }
  3835.  
  3836. if ((((p & 2) === 2) ^ ((q & 2) === 2)) && ((q & 2) === 2)) {
  3837. bFixForResizedTab = true;
  3838. }
  3839.  
  3840. // p->q +2
  3841. if ((p & 2) === 0 && (q & 2) === 2 && (p & 128) === 128 && (q & 128) === 128) {
  3842. lastPanel = (lastTab || '');
  3843. ytBtnClosePlaylist();
  3844. actioned = true;
  3845. }
  3846.  
  3847. // p->q +8
  3848. if ((p & (8 | 128)) === (0 | 128) && (q & (8 | 128)) === (8 | 128) && lastPanel === 'chat') {
  3849. lastPanel = (lastTab || '');
  3850. ytBtnClosePlaylist();
  3851. actioned = true;
  3852. }
  3853.  
  3854. // p->q +128
  3855. if ((p & (2 | 128)) === (2 | 0) && (q & (2 | 128)) === (2 | 128) && lastPanel === 'playlist') {
  3856. switchToTab(null);
  3857. actioned = true;
  3858. }
  3859.  
  3860. // p->q +128
  3861. if ((p & (8 | 128)) === (8 | 0) && (q & (8 | 128)) === (8 | 128) && lastPanel === 'playlist') {
  3862. lastPanel = (lastTab || '');
  3863. ytBtnCollapseChat();
  3864. actioned = true;
  3865. }
  3866.  
  3867.  
  3868. // p->q +128
  3869. if ((p & (1 | 16 | 128)) == (1 | 16) && (q & (1 | 16 | 128)) == (1 | 16 | 128)) {
  3870. ytBtnCancelTheater();
  3871. actioned = true;
  3872. }
  3873.  
  3874. // p->q +1
  3875. if ((p & (1 | 16 | 128)) == (16 | 128) && (q & (1 | 16 | 128)) == (1 | 16 | 128)) {
  3876. lastPanel = (lastTab || '');
  3877. ytBtnClosePlaylist();
  3878. actioned = true;
  3879. }
  3880.  
  3881. if ((q & 64) === 64) {
  3882. actioned = false;
  3883. } else if ((p & 64) == 64 && (q & 64) === 0) {
  3884. // p->q -64
  3885.  
  3886. if ((q & 32) === 32) {
  3887. ytBtnCloseEngagementPanels();
  3888. }
  3889.  
  3890. if ((q & (2 | 8)) === (2 | 8)) {
  3891. if (lastPanel === 'chat') {
  3892.  
  3893. switchToTab(null);
  3894. actioned = true;
  3895. } else if (lastPanel) {
  3896. ytBtnCollapseChat();
  3897. actioned = true;
  3898. }
  3899. }
  3900.  
  3901. } else if ((p & (1 | 2 | 8 | 16 | 32)) === (1 | 0 | 0 | 16 | 0) && (q & (1 | 2 | 8 | 16 | 32)) === (1 | 0 | 8 | 16 | 0)) {
  3902. // p->q +8
  3903. ytBtnCancelTheater();
  3904. actioned = true;
  3905. } else if ((p & (1 | 16 | 32)) === (0 | 16 | 0) && (q & (1 | 16 | 32)) === (0 | 16 | 32) && (q & (2 | 8)) > 0) {
  3906. // p->q +32
  3907. if (q & 2) {
  3908. switchToTab(null);
  3909. actioned = true;
  3910. }
  3911. if (q & 8) {
  3912. ytBtnCollapseChat();
  3913. actioned = true;
  3914. }
  3915. } else if ((p & (1 | 16 | 8 | 2)) === (16 | 8) && (q & (1 | 16 | 8 | 2)) === (16) && (q & 128) === 0) {
  3916. // p->q -8
  3917. if (lastTab) {
  3918. switchToTab(lastTab)
  3919. actioned = true;
  3920. }
  3921.  
  3922. } else if ((p & 1) === 0 && (q & 1) === 1) {
  3923. // p->q +1
  3924. if ((q & 32) === 32) {
  3925. ytBtnCloseEngagementPanels();
  3926. }
  3927. if ((p & 9) === 8 && (q & 9) === 9) {
  3928. ytBtnCollapseChat();
  3929. }
  3930. switchToTab(null)
  3931. actioned = true;
  3932.  
  3933. } else if ((p & 3) === 1 && (q & 3) === 3) {
  3934. // p->q +2
  3935. ytBtnCancelTheater();
  3936. actioned = true;
  3937. } else if ((p & 10) === 2 && (q & 10) === 10) {
  3938. // p->q +8
  3939. switchToTab(null)
  3940. actioned = true;
  3941.  
  3942. } else if ((p & (8 | 32)) === (0 | 32) && (q & (8 | 32)) === (8 | 32)) {
  3943. // p->q +8
  3944. ytBtnCloseEngagementPanels();
  3945. actioned = true;
  3946.  
  3947.  
  3948. } else if ((p & (2 | 32)) === (0 | 32) && (q & (2 | 32)) === (2 | 32)) {
  3949. // p->q +2
  3950. ytBtnCloseEngagementPanels();
  3951. actioned = true;
  3952.  
  3953. } else if ((p & (2 | 8)) === (0 | 8) && (q & (2 | 8)) === (2 | 8)) {
  3954. // p->q +2
  3955. ytBtnCollapseChat();
  3956. actioned = true;
  3957. // if( lastPanel && (p & (1|16) === 16) && (q & (1 | 16 | 8 | 2)) === (16) ){
  3958. // switchToTab(lastTab)
  3959. // actioned = true;
  3960. // }
  3961. } else if ((p & 1) === 1 && (q & (1 | 32)) === (0 | 0)) {
  3962. // p->q -1
  3963. if (lastPanel === 'chat') {
  3964. ytBtnExpandChat()
  3965. actioned = true;
  3966. } else if (lastPanel === lastTab && lastTab) {
  3967. switchToTab(lastTab)
  3968. actioned = true;
  3969. }
  3970. }
  3971.  
  3972.  
  3973. // 24 20
  3974. // 8 16 4 16
  3975.  
  3976. if (!actioned && (q & 128) === 128) {
  3977. lastPanel = 'playlist'
  3978. if ((q & 2) === 2) {
  3979. switchToTab(null)
  3980. actioned = true;
  3981. }
  3982. }
  3983.  
  3984. if ((p & 2) === 2 && (q & (2 | 128)) === (0 | 128)) {
  3985. // p->q -2
  3986.  
  3987. } else if ((p & 8) === 8 && (q & (8 | 128)) === (0 | 128)) {
  3988. // p->q -8
  3989.  
  3990. } else if (!actioned && (p & (1 | 16)) === 16 && (q & (1 | 16 | 8 | 2 | 32 | 64)) === (16 | 0 | 0)) {
  3991. console.log(388, 'd')
  3992. if (lastPanel === 'chat') {
  3993. console.log(388, 'd1c')
  3994. ytBtnExpandChat()
  3995. actioned = true;
  3996.  
  3997. } else if (lastPanel === 'playlist') {
  3998. console.log(388, 'd1p')
  3999. ytBtnOpenPlaylist()
  4000. actioned = true;
  4001.  
  4002. } else if (lastTab) {
  4003. console.log(388, 'd2t')
  4004. switchToTab(lastTab)
  4005. actioned = true;
  4006. } else if (resetForPanelDisappeared) {
  4007. // if lastTab is undefined
  4008. console.log(388, 'd2d')
  4009. Promise.resolve(lockSet['fixInitialTabStateLock']).then(eventMap['fixInitialTabStateFn']).catch(console.warn);
  4010. actioned = true;
  4011. }
  4012. }
  4013.  
  4014.  
  4015. if (bFixForResizedTab) {
  4016. bFixForResizedTabLater = false;
  4017. Promise.resolve(0).then(eventMap['fixForTabDisplay']).catch(console.warn);
  4018. }
  4019.  
  4020. if (((p & 16) === 16) ^ ((q & 16) === 16)) {
  4021. Promise.resolve(lockSet['infoFixLock']).then(infoFix).catch(console.warn);
  4022. Promise.resolve(lockSet['removeKeepCommentsScrollerLock']).then(removeKeepCommentsScroller).catch(console.warn);
  4023. Promise.resolve(lockSet['layoutFixLock']).then(layoutFix).catch(console.warn);
  4024. }
  4025. }
  4026.  
  4027. },
  4028.  
  4029. 'updateOnVideoIdChanged': (lockId) => {
  4030. if (lockId !== lockGet['updateOnVideoIdChangedLock']) return;
  4031. const videoId = tmpLastVideoId;
  4032. if (!videoId) return;
  4033. const bodyRenderer = elements.infoExpanderRendererBack;
  4034. const bodyRendererNew = elements.infoExpanderRendererFront;
  4035.  
  4036. if(bodyRendererNew && bodyRenderer){
  4037.  
  4038. insp(bodyRendererNew).data = insp(bodyRenderer).data;
  4039. // if ((bodyRendererNew.hasAttribute('hidden') ? 1 : 0) ^ (bodyRenderer.hasAttribute('hidden') ? 1 : 0)) {
  4040. // if (bodyRenderer.hasAttribute('hidden')) bodyRendererNew.setAttribute('hidden', '');
  4041. // else bodyRendererNew.removeAttribute('hidden');
  4042. // }
  4043.  
  4044. }
  4045.  
  4046.  
  4047. Promise.resolve(lockSet['infoFixLock']).then(infoFix).catch(console.warn);
  4048. },
  4049.  
  4050. 'fixInitialTabStateFn': async (lockId) => {
  4051. // console.log('fixInitialTabStateFn 0a');
  4052. if (lockGet['fixInitialTabStateLock'] !== lockId) return;
  4053. // console.log('fixInitialTabStateFn 0b');
  4054. const delayTime = fixInitialTabStateK > 0 ? 200 : 1;
  4055. await delayPn(delayTime);
  4056. if (lockGet['fixInitialTabStateLock'] !== lockId) return;
  4057. // console.log('fixInitialTabStateFn 0c');
  4058. const kTab = document.querySelector('[tyt-tab]');
  4059. const qTab = (!kTab || kTab.getAttribute('tyt-tab') === '') ? checkElementExist('ytd-watch-flexy[is-two-columns_]', '[hidden]') : null;
  4060. if (checkElementExist('ytd-playlist-panel-renderer#playlist', '[hidden], [collapsed]')) {
  4061. console.log('fixInitialTabStateFn 1p');
  4062. switchToTab(null);
  4063. } else if (checkElementExist('ytd-live-chat-frame#chat', '[hidden], [collapsed]')) {
  4064. console.log('fixInitialTabStateFn 1a');
  4065. switchToTab(null);
  4066. if (checkElementExist('ytd-watch-flexy[theater]', '[hidden]')) {
  4067. ytBtnCollapseChat();
  4068. }
  4069. } else if (qTab) {
  4070. const hasTheater = qTab.hasAttribute('theater');
  4071. if (!hasTheater) {
  4072. console.log('fixInitialTabStateFn 1b');
  4073. const btn0 = document.querySelector('.tab-btn-visible') // or default button
  4074. if (btn0) {
  4075. switchToTab(btn0);
  4076. } else {
  4077. switchToTab(null);
  4078. }
  4079. } else {
  4080. console.log('fixInitialTabStateFn 1c');
  4081. switchToTab(null);
  4082. }
  4083. } else {
  4084. console.log('fixInitialTabStateFn 1z');
  4085. }
  4086. // console.log('fixInitialTabStateFn 0d');
  4087. fixInitialTabStateK++;
  4088. },
  4089.  
  4090. 'tabs-btn-click': (evt) => {
  4091.  
  4092. const target = evt.target;
  4093. if (target instanceof HTMLElement_ && target.classList.contains('tab-btn') && target.hasAttribute000('tyt-tab-content')) {
  4094.  
  4095. evt.preventDefault();
  4096. evt.stopPropagation();
  4097. evt.stopImmediatePropagation();
  4098.  
  4099.  
  4100. const activeLink = target;
  4101.  
  4102. switchToTab(activeLink);
  4103.  
  4104. }
  4105.  
  4106. }
  4107.  
  4108. }
  4109.  
  4110. Promise.all([videosElementProvidedPromise, navigateFinishedPromise]).then(eventMap['onceInsertRightTabs']).catch(console.warn);
  4111. Promise.all([navigateFinishedPromise, infoExpanderElementProvidedPromise]).then(eventMap['onceInfoExpanderElementProvidedPromised']).catch(console.warn);
  4112.  
  4113. const isCustomElementsProvided = typeof customElements !== "undefined" && typeof (customElements || 0).whenDefined === "function";
  4114.  
  4115. const promiseForCustomYtElementsReady = isCustomElementsProvided ? Promise.resolve(0) : new Promise((callback) => {
  4116. const EVENT_KEY_ON_REGISTRY_READY = "ytI-ce-registry-created";
  4117. if (typeof customElements === 'undefined') {
  4118. if (!('__CE_registry' in document)) {
  4119. // https://github.com/webcomponents/polyfills/
  4120. Object.defineProperty(document, '__CE_registry', {
  4121. get() {
  4122. // return undefined
  4123. },
  4124. set(nv) {
  4125. if (typeof nv == 'object') {
  4126. delete this.__CE_registry;
  4127. this.__CE_registry = nv;
  4128. this.dispatchEvent(new CustomEvent(EVENT_KEY_ON_REGISTRY_READY));
  4129. }
  4130. return true;
  4131. },
  4132. enumerable: false,
  4133. configurable: true
  4134. })
  4135. }
  4136. let eventHandler = (evt) => {
  4137. document.removeEventListener(EVENT_KEY_ON_REGISTRY_READY, eventHandler, false);
  4138. const f = callback;
  4139. callback = null;
  4140. eventHandler = null;
  4141. f();
  4142. };
  4143. document.addEventListener(EVENT_KEY_ON_REGISTRY_READY, eventHandler, false);
  4144. } else {
  4145. callback();
  4146. }
  4147. });
  4148.  
  4149. const _retrieveCE = async (nodeName) => {
  4150. try {
  4151. isCustomElementsProvided || (await promiseForCustomYtElementsReady);
  4152. await customElements.whenDefined(nodeName);
  4153. } catch (e) {
  4154. console.warn(e);
  4155. }
  4156. }
  4157.  
  4158.  
  4159. const retrieveCE = async (nodeName) => {
  4160. try {
  4161. isCustomElementsProvided || (await promiseForCustomYtElementsReady);
  4162. await customElements.whenDefined(nodeName);
  4163. const dummy = document.querySelector(nodeName) || document.createElement(nodeName);
  4164. const cProto = insp(dummy).constructor.prototype;
  4165. return cProto;
  4166. } catch (e) {
  4167. console.warn(e);
  4168. }
  4169. }
  4170.  
  4171.  
  4172. const moOverallRes = {
  4173. _yt_playerProvided: () => (((window || 0)._yt_player || 0) || 0)
  4174. }
  4175.  
  4176. let promiseWaitNext = null;
  4177. const moOverall = new MutationObserver(() => {
  4178. if (promiseWaitNext) {
  4179. promiseWaitNext.resolve();
  4180. promiseWaitNext = null;
  4181. }
  4182.  
  4183. if (typeof moOverallRes._yt_playerProvided === 'function') {
  4184. const r = moOverallRes._yt_playerProvided();
  4185. if (r) {
  4186. moOverallRes._yt_playerProvided = r;
  4187. eventMap._yt_playerProvided();
  4188. }
  4189. }
  4190. });
  4191.  
  4192. moOverall.observe(document, { subtree: true, childList: true });
  4193.  
  4194.  
  4195. const moEgmPanelReady = new MutationObserver(mutations => {
  4196. for (const mutation of mutations) {
  4197. const target = mutation.target;
  4198. if (!target.hasAttribute000('tyt-egm-panel-jclmd')) continue;
  4199. if (target.hasAttribute000('target-id') && target.hasAttribute000('visibility')) {
  4200. target.removeAttribute000('tyt-egm-panel-jclmd');
  4201. moEgmPanelReadyClearFn();
  4202. Promise.resolve(target).then(eventMap['ytd-engagement-panel-section-list-renderer::bindTarget']).catch(console.warn);
  4203. }
  4204. }
  4205. });
  4206.  
  4207. const moEgmPanelReadyClearFn = () => {
  4208.  
  4209. if (document.querySelector('[tyt-egm-panel-jclmd]') === null) {
  4210. moEgmPanelReady.takeRecords();
  4211. moEgmPanelReady.disconnect();
  4212. }
  4213.  
  4214. };
  4215.  
  4216. document.addEventListener('yt-navigate-finish', eventMap['yt-navigate-finish'], false);
  4217.  
  4218. document.addEventListener('animationstart', evt => {
  4219. const f = eventMap[evt.animationName];
  4220. if (typeof f === 'function') f(evt.target);
  4221. }, capturePassive);
  4222.  
  4223. // console.log('hi122')
  4224.  
  4225.  
  4226. mLoaded.flag |= 1;
  4227. document.documentElement.setAttribute111('tabview-loaded', mLoaded.makeString());
  4228.  
  4229. promiseForCustomYtElementsReady.then(eventMap['ceHack']).catch(console.warn);
  4230.  
  4231.  
  4232. executionFinished = 1;
  4233.  
  4234.  
  4235.  
  4236. } catch (e) {
  4237. console.log('error 0xF491');
  4238. console.error(e);
  4239. }
  4240.  
  4241. };
  4242. const styles = {
  4243. 'main': `
  4244.  
  4245.  
  4246. @keyframes relatedElementProvided {
  4247. 0% {
  4248. background-position-x: 3px;
  4249. }
  4250. 100% {
  4251. background-position-x: 4px;
  4252. }
  4253. }
  4254. html[tabview-loaded="icp"] #related.ytd-watch-flexy {
  4255. animation: relatedElementProvided 1ms linear 0s 1 normal forwards;
  4256. }
  4257. html[tabview-loaded="icp"] #right-tabs #related.ytd-watch-flexy,
  4258. html[tabview-loaded="icp"] [hidden] #related.ytd-watch-flexy {
  4259. animation: initial;
  4260. }
  4261.  
  4262.  
  4263.  
  4264. html[tabview-loaded="icp"] #right-tabs ytd-expander#expander,
  4265. html[tabview-loaded="icp"] [hidden] ytd-expander#expander,
  4266. html[tabview-loaded="icp"] ytd-comments ytd-expander#expander{
  4267. animation: initial;
  4268. }
  4269.  
  4270.  
  4271.  
  4272.  
  4273.  
  4274. #secondary.ytd-watch-flexy {
  4275. position: relative;
  4276. }
  4277.  
  4278. #secondary-inner.style-scope.ytd-watch-flexy {
  4279. height: 100%;
  4280. }
  4281.  
  4282. /*
  4283. ytd-watch-flexy[tyt-tab^="#"] #secondary-inner.style-scope.ytd-watch-flexy::after {
  4284. display: block;
  4285. content:'';
  4286. height: 100vh;
  4287. }
  4288. */
  4289.  
  4290. secondary-wrapper {
  4291. display: flex;
  4292. flex-direction: column;
  4293. flex-wrap: nowrap;
  4294. box-sizing: border-box;
  4295. padding: 0;
  4296. margin: 0;
  4297. border: 0;
  4298. height: 100%;
  4299. max-height: calc(100vh - var(--ytd-toolbar-height, 56px));
  4300. position: absolute;
  4301. top: 0;
  4302. right: 0;
  4303. left: 0;
  4304. contain: strict;
  4305.  
  4306. /* border-right: var(--ytd-margin-6x) solid transparent; */
  4307. padding-top: var(--ytd-margin-6x);
  4308. padding-right: var(--ytd-margin-6x);
  4309. padding-bottom: var(--ytd-margin-6x);
  4310. }
  4311.  
  4312.  
  4313.  
  4314. #right-tabs {
  4315. position: relative;
  4316. display: flex;
  4317. padding: 0;
  4318. margin: 0;
  4319. flex-grow: 1;
  4320. flex-direction: column;
  4321. }
  4322.  
  4323. [tyt-tab=""] #right-tabs{
  4324. flex-grow: 0;
  4325. }
  4326.  
  4327. [tyt-tab=""] #right-tabs .tab-content{
  4328. border: 0;
  4329. }
  4330.  
  4331. #right-tabs .tab-content {
  4332. flex-grow: 1;
  4333. }
  4334.  
  4335. ytd-watch-flexy[hide-default-text-inline-expander] #primary.style-scope.ytd-watch-flexy ytd-text-inline-expander {
  4336. display: none;
  4337. }
  4338.  
  4339.  
  4340. ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden {
  4341. --comment-pre-load-sizing: 90px;
  4342. visibility: collapse;
  4343. z-index: -1;
  4344. position: fixed !important;
  4345. left: 2px;
  4346. top: 2px;
  4347. width: var(--comment-pre-load-sizing) !important;
  4348. height: var(--comment-pre-load-sizing) !important;
  4349. display: block !important;
  4350. pointer-events: none !important;
  4351. overflow:hidden;
  4352. contain:strict;
  4353. border: 0;
  4354. margin: 0;
  4355. padding: 0;
  4356. }
  4357.  
  4358. ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments > * {
  4359. display: none !important;
  4360. }
  4361.  
  4362. ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments > ytd-item-section-renderer#sections {
  4363. display: block !important;
  4364. overflow:hidden;
  4365. height: var(--comment-pre-load-sizing);
  4366. width: var(--comment-pre-load-sizing);
  4367. contain:strict;
  4368. border: 0;
  4369. margin: 0;
  4370. padding: 0;
  4371. }
  4372.  
  4373. ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments > ytd-item-section-renderer#sections > * {
  4374. display: none !important;
  4375. }
  4376. ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments > ytd-item-section-renderer#sections > #contents {
  4377. display: flex !important;
  4378. flex-direction: row;
  4379. gap: 60px;
  4380. overflow:hidden;
  4381. height: var(--comment-pre-load-sizing);
  4382. width: var(--comment-pre-load-sizing);
  4383. contain:strict;
  4384. border: 0;
  4385. margin: 0;
  4386. padding: 0;
  4387. }
  4388. ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments > ytd-item-section-renderer#sections > #contents > * {
  4389. display: block !important;
  4390. visibility: collapse !important;
  4391. overflow: hidden;
  4392. margin: calc(2 * var(--comment-pre-load-sizing)) !important;
  4393. width: var(--comment-pre-load-sizing);
  4394. height: var(--comment-pre-load-sizing);
  4395. box-sizing: content-box;
  4396. contain:strict;
  4397. border: 0;
  4398. padding: 0;
  4399. }
  4400.  
  4401. ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments > ytd-item-section-renderer#sections > #contents > *:empty {
  4402. display: none !important;
  4403. visibility: collapse !important;
  4404. overflow: hidden;
  4405. margin: 0px !important;
  4406. width: 0px;
  4407. height: 0px;
  4408. box-sizing: content-box;
  4409. contain:strict;
  4410. }
  4411. ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments > ytd-item-section-renderer#sections > #contents > ytd-continuation-item-renderer {
  4412. display: block !important;
  4413. visibility: collapse !important;
  4414. overflow: initial;
  4415. margin: 0px !important;
  4416. width: 1px;
  4417. height: 1px;
  4418. box-sizing: initial;
  4419. contain:strict;
  4420. }
  4421.  
  4422. ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments > ytd-item-section-renderer#sections > #contents > * > * {
  4423. display: none !important;
  4424. visibility: collapse !important;
  4425. overflow: hidden;
  4426. margin: 0px !important;
  4427. width: 0px;
  4428. height: 0px;
  4429. box-sizing: content-box;
  4430. contain:strict;
  4431. }
  4432.  
  4433.  
  4434. #right-tabs #material-tabs {
  4435. position: relative;
  4436. display: flex;
  4437. padding: 0;
  4438. /*outline: 1px solid var(--tyt-x-border-color);*/
  4439. /*outline: 1px solid var(--ytd-searchbox-legacy-border-color);*/
  4440. /* 2023/05/05 chaged from outline to border */
  4441. border: 1px solid var(--ytd-searchbox-legacy-border-color);
  4442. /* border-bottom:0; */
  4443. overflow: hidden;
  4444. }
  4445.  
  4446. [tyt-tab] #right-tabs #material-tabs {
  4447. border-radius: var(--tyt-rounded-a1) var(--tyt-rounded-a1) var(--tyt-rounded-a1) var(--tyt-rounded-a1);
  4448. }
  4449.  
  4450. [tyt-tab^="#"] #right-tabs #material-tabs {
  4451. border-radius: var(--tyt-rounded-a1) var(--tyt-rounded-a1) 0 0;
  4452. }
  4453.  
  4454. ytd-watch-flexy[flexy]:not([is-two-columns_]) #right-tabs #material-tabs {
  4455. outline: 0;
  4456. }
  4457.  
  4458. #right-tabs #material-tabs a.tab-btn[tyt-tab-content] > * {
  4459. pointer-events: none;
  4460. }
  4461.  
  4462. #right-tabs #material-tabs a.tab-btn[tyt-tab-content] > .font-size-right {
  4463. pointer-events: initial;
  4464. display: none; /* not yet supported */
  4465. }
  4466.  
  4467. ytd-watch-flexy #right-tabs .tab-content {
  4468. padding: 0;
  4469. box-sizing: border-box;
  4470. display: block;
  4471. /*--yt-spec-brand-background-primary:var(--yt-spec-general-background-a);*/
  4472. /*outline: 1px solid var(--tyt-x-border-color);*/
  4473. /* outline: 1px solid var(--ytd-searchbox-legacy-border-color); */
  4474. /* 2023/05/05 chaged from outline to border */
  4475. border: 1px solid var(--ytd-searchbox-legacy-border-color);
  4476. border-top:0;
  4477. position: relative;
  4478. top: 0;
  4479. display: flex;
  4480. flex-direction: row;
  4481. overflow: hidden;
  4482. border-radius: 0 0 var(--tyt-rounded-a1) var(--tyt-rounded-a1);
  4483. }
  4484.  
  4485. ytd-watch-flexy[is-two-columns_] #right-tabs .tab-content {
  4486. /*
  4487. height: var(--tyt-tabs-content-height);
  4488. contain: size layout paint;
  4489. */
  4490. }
  4491.  
  4492. ytd-watch-flexy:not([is-two-columns_]) #right-tabs .tab-content {
  4493. height: 100%;
  4494. }
  4495.  
  4496. ytd-watch-flexy #right-tabs .tab-content-cld {
  4497. box-sizing: border-box;
  4498. position: relative;
  4499. display: block;
  4500. width: 100%;
  4501. overflow: auto;
  4502. --tab-content-padding: var(--ytd-margin-4x);
  4503. padding: var(--tab-content-padding);
  4504. contain: layout paint;
  4505.  
  4506. }
  4507.  
  4508. .tab-content-cld,
  4509. #right-tabs,
  4510. .tab-content {
  4511. transition: none;
  4512. animation: none;
  4513. }
  4514.  
  4515. ytd-watch-flexy[is-two-columns_] #right-tabs .tab-content-cld {
  4516. height: 100%;
  4517. width: 100%;
  4518. contain: size layout paint style;
  4519. position: absolute;
  4520. }
  4521.  
  4522. ytd-watch-flexy #right-tabs .tab-content-cld.tab-content-hidden {
  4523. display: none;
  4524. width: 100%;
  4525. /* width fix */
  4526. contain: size layout paint style;
  4527. }
  4528.  
  4529.  
  4530.  
  4531.  
  4532.  
  4533.  
  4534. @supports (color: var(--tabview-tab-btn-define)) {
  4535.  
  4536. /* give background color; otherwise it will be transparent in dark mode, single column*/
  4537. ytd-watch-flexy #right-tabs .tab-btn {
  4538. background: var(--yt-spec-general-background-a);
  4539. }
  4540.  
  4541. html {
  4542. --tyt-tab-btn-flex-grow: 1;
  4543. --tyt-tab-btn-flex-basis: 0%;
  4544. --tyt-tab-bar-color-1-def: #ff4533;
  4545. --tyt-tab-bar-color-2-def: var(--yt-brand-light-red);
  4546. --tyt-tab-bar-color-1:var(--main-color, var(--tyt-tab-bar-color-1-def));
  4547. --tyt-tab-bar-color-2:var(--main-color, var(--tyt-tab-bar-color-2-def));
  4548. }
  4549.  
  4550. ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content] {
  4551.  
  4552. flex-grow: 1;
  4553. flex-shrink: 1;
  4554. flex-basis: 0%;
  4555. flex-grow: var(--tyt-tab-btn-flex-grow);
  4556. flex-basis: var(--tyt-tab-btn-flex-basis);
  4557. position: relative;
  4558. display: inline-block;
  4559. text-decoration: none;
  4560. text-transform: uppercase;
  4561. --tyt-tab-btn-color: var(--yt-spec-text-secondary);
  4562. color: var(--tyt-tab-btn-color);
  4563. text-align: center;
  4564. padding: 14px 8px 10px;
  4565. border: 0;
  4566. border-bottom: 4px solid transparent;
  4567. font-weight: 500;
  4568. font-size: 12px;
  4569. line-height: 18px;
  4570. cursor: pointer;
  4571. transition: border 200ms linear 100ms;
  4572. background-color: var(--ytd-searchbox-legacy-button-color);
  4573. text-transform: var(--yt-button-text-transform, inherit);
  4574. user-select: none !important;
  4575.  
  4576. overflow: hidden;
  4577. white-space: nowrap;
  4578. /*text-overflow: ellipsis;*/
  4579. text-overflow: clip;
  4580.  
  4581. }
  4582.  
  4583.  
  4584. /* .tab-btn[tyt-tab-content] */
  4585.  
  4586. ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content]>svg {
  4587. height: 18px;
  4588. padding-right: 0px;
  4589. vertical-align: bottom;
  4590. opacity: .5;
  4591. margin-right: 0px;
  4592. color: var(--yt-button-color, inherit);
  4593. fill: var(--iron-icon-fill-color, currentcolor);
  4594. stroke: var(--iron-icon-stroke-color, none);
  4595. }
  4596.  
  4597. ytd-watch-flexy #right-tabs .tab-btn {
  4598. --tabview-btn-txt-ml: 8px;
  4599. }
  4600. ytd-watch-flexy[tyt-comment-disabled] #right-tabs .tab-btn[tyt-tab-content="#tab-comments"] {
  4601. --tabview-btn-txt-ml: 0px;
  4602. }
  4603.  
  4604. ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content]>svg+span {
  4605. margin-left: var(--tabview-btn-txt-ml);
  4606. }
  4607.  
  4608. ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content] svg {
  4609. pointer-events: none;
  4610. }
  4611.  
  4612. ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content].active {
  4613. font-weight: 500;
  4614. outline: 0;
  4615. --tyt-tab-btn-color: var(--yt-spec-text-primary);
  4616. background-color: var(--ytd-searchbox-legacy-button-focus-color);
  4617. border-bottom: 4px var(--tyt-tab-bar-color-1) solid;
  4618. border-bottom-color: var(--tyt-tab-bar-color-2);
  4619. }
  4620.  
  4621. ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content].active svg {
  4622. opacity: .9
  4623. }
  4624.  
  4625. ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content]:not(.active):hover {
  4626. background-color: var(--ytd-searchbox-legacy-button-hover-color);
  4627. --tyt-tab-btn-color: var(--yt-spec-text-primary);
  4628. }
  4629.  
  4630. ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content]:not(.active):hover svg {
  4631. opacity: .9
  4632. }
  4633.  
  4634. ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content] {
  4635. user-select: none !important;
  4636. }
  4637.  
  4638. ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content].tab-btn-hidden {
  4639. display: none;
  4640. }
  4641.  
  4642. ytd-watch-flexy[tyt-comment-disabled] #right-tabs .tab-btn[tyt-tab-content="#tab-comments"],
  4643. ytd-watch-flexy[tyt-comment-disabled] #right-tabs .tab-btn[tyt-tab-content="#tab-comments"]:hover {
  4644. --tyt-tab-btn-color: var(--yt-spec-icon-disabled);
  4645. }
  4646.  
  4647. ytd-watch-flexy[tyt-comment-disabled] #right-tabs .tab-btn[tyt-tab-content="#tab-comments"] span#tyt-cm-count:empty{
  4648. display:none;
  4649. }
  4650.  
  4651.  
  4652. ytd-watch-flexy #right-tabs .tab-btn span#tyt-cm-count:empty::after {
  4653. display: inline-block;
  4654. width: 4em;
  4655. text-align: left;
  4656. font-size: inherit;
  4657. color: currentColor;
  4658. transform: scaleX(0.8);
  4659. }
  4660.  
  4661. }
  4662.  
  4663. @supports (color: var(--tyt-cm-count-define)){
  4664.  
  4665. ytd-watch-flexy {
  4666. --tyt-x-loading-content-letter-spacing: 2px;
  4667. }
  4668.  
  4669. html {
  4670. --tabview-text-loading: "Loading";
  4671. --tabview-text-fetching: "Fetching";
  4672. --tabview-panel-loading: var(--tabview-text-loading);
  4673. }
  4674.  
  4675. html:lang(ja) {
  4676. --tabview-text-loading: "読み込み中";
  4677. --tabview-text-fetching: "フェッチ..";
  4678. }
  4679.  
  4680. html:lang(ko) {
  4681. --tabview-text-loading: "로딩..";
  4682. --tabview-text-fetching: "가져오기..";
  4683. }
  4684.  
  4685. html:lang(zh-Hant) {
  4686. /* 資訊科技名詞 @ https://terms.naer.edu.tw/ */
  4687. --tabview-text-loading: "載入中";
  4688. --tabview-text-fetching: "擷取中";
  4689. }
  4690.  
  4691. html:lang(zh-Hans) {
  4692. --tabview-text-loading: "加载中";
  4693. --tabview-text-fetching: "抓取中";
  4694. }
  4695.  
  4696. html:lang(ru) {
  4697. --tabview-text-loading: "Загрузка";
  4698. --tabview-text-fetching: "Получение";
  4699. }
  4700.  
  4701. ytd-watch-flexy #right-tabs .tab-btn span#tyt-cm-count:empty::after {
  4702. content: var(--tabview-text-loading);
  4703. letter-spacing: var(--tyt-x-loading-content-letter-spacing);
  4704. }
  4705.  
  4706. }
  4707.  
  4708.  
  4709. @supports (color: var(--tabview-font-size-btn-define)) {
  4710.  
  4711. .font-size-right {
  4712. display: inline-flex;
  4713. flex-direction: column;
  4714. position: absolute;
  4715. right: 0;
  4716. top: 0;
  4717. bottom: 0;
  4718. width: 16px;
  4719. padding: 4px 0;
  4720. justify-content: space-evenly;
  4721. align-content: space-evenly;
  4722. pointer-events: none;
  4723. }
  4724.  
  4725. html body ytd-watch-flexy.style-scope .font-size-btn {
  4726. user-select: none !important;
  4727. }
  4728.  
  4729. .font-size-btn {
  4730. --tyt-font-size-btn-display: none;
  4731. display: var(--tyt-font-size-btn-display, none);
  4732. /* hide zoom btn for FireFox */
  4733. width: 12px;
  4734. height: 12px;
  4735. color: var(--yt-spec-text-secondary);
  4736. background-color: var(--yt-spec-badge-chip-background);
  4737. box-sizing: border-box;
  4738. cursor: pointer;
  4739. transform-origin: left top;
  4740. margin: 0;
  4741. padding: 0;
  4742. position: relative;
  4743. font-family: 'Menlo', 'Lucida Console', 'Monaco', 'Consolas', monospace;
  4744. line-height: 100%;
  4745. font-weight: 900;
  4746. transition: background-color 90ms linear, color 90ms linear;
  4747. pointer-events: all;
  4748. }
  4749.  
  4750. .font-size-btn:hover {
  4751. background-color: var(--yt-spec-text-primary);
  4752. color: var(--yt-spec-general-background-a);
  4753. }
  4754.  
  4755. @supports (zoom: 0.5) {
  4756.  
  4757. .tab-btn .font-size-btn {
  4758. --tyt-font-size-btn-display: none;
  4759. }
  4760.  
  4761. .tab-btn.active:hover .font-size-btn {
  4762. --tyt-font-size-btn-display: inline-block;
  4763. }
  4764.  
  4765. }
  4766.  
  4767. }
  4768.  
  4769.  
  4770. body ytd-watch-flexy:not([is-two-columns_]) #columns.ytd-watch-flexy{
  4771. flex-direction: column;
  4772. }
  4773.  
  4774. body ytd-watch-flexy:not([is-two-columns_]) #secondary.ytd-watch-flexy {
  4775. display: block;
  4776. width: 100%;
  4777. box-sizing: border-box;
  4778. }
  4779.  
  4780. body ytd-watch-flexy:not([is-two-columns_]) #secondary.ytd-watch-flexy secondary-wrapper {
  4781.  
  4782. padding-left: var(--ytd-margin-6x);
  4783. contain: content;
  4784. height: initial;
  4785.  
  4786.  
  4787. }
  4788.  
  4789. body ytd-watch-flexy:not([is-two-columns_]) #secondary.ytd-watch-flexy secondary-wrapper #right-tabs {
  4790. overflow: auto;
  4791.  
  4792. }
  4793.  
  4794. [tyt-chat="+"] secondary-wrapper > [tyt-chat-container]{
  4795. flex-grow: 1;
  4796. flex-shrink: 0;
  4797. display: flex;
  4798. flex-direction: column;
  4799. }
  4800.  
  4801. [tyt-chat="+"] secondary-wrapper > [tyt-chat-container] > #chat{
  4802. flex-grow: 1;
  4803. }
  4804.  
  4805. ytd-watch-flexy[is-two-columns_]:not([theater]) #columns.style-scope.ytd-watch-flexy {
  4806. min-height: calc(100vh - var(--ytd-toolbar-height, 56px));
  4807. }
  4808.  
  4809. ytd-watch-flexy[is-two-columns_] ytd-live-chat-frame#chat {
  4810. min-height: initial !important;
  4811. height: initial !important;
  4812. }
  4813.  
  4814. ytd-watch-flexy[tyt-tab^="#"]:not([is-two-columns_]):not([tyt-chat="+"]) #right-tabs {
  4815. min-height: var(--ytd-watch-flexy-chat-max-height)
  4816. }
  4817.  
  4818. body ytd-watch-flexy:not([is-two-columns_]) #chat.ytd-watch-flexy {
  4819. margin-top: 0;
  4820.  
  4821. }
  4822.  
  4823. body ytd-watch-flexy:not([is-two-columns_]) ytd-watch-metadata.ytd-watch-flexy {
  4824. margin-bottom: 0;
  4825. }
  4826.  
  4827. ytd-watch-metadata.ytd-watch-flexy ytd-metadata-row-container-renderer {
  4828. display: none;
  4829. }
  4830.  
  4831. /*
  4832. #tab-info #items.style-scope.ytd-video-description-infocards-section-renderer {
  4833.  
  4834. display: inline-flex;
  4835. flex-wrap: wrap;
  4836. row-gap: 8px;
  4837. }
  4838.  
  4839. #tab-info #left-arrow-container.style-scope.ytd-video-description-infocards-section-renderer,
  4840. #tab-info #left-arrow.style-scope.ytd-video-description-infocards-section-renderer,
  4841. #tab-info #right-arrow-container.style-scope.ytd-video-description-infocards-section-renderer,
  4842. #tab-info #right-arrow.style-scope.ytd-video-description-infocards-section-renderer {
  4843. visibility: collapse;
  4844. }
  4845. */
  4846.  
  4847. /*
  4848. #tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer > #left-arrow-container.ytd-video-description-infocards-section-renderer{
  4849. left:0;
  4850. }
  4851. #tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer > #right-arrow-container.ytd-video-description-infocards-section-renderer{
  4852. right:0;
  4853. }
  4854.  
  4855. #tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer > #scroll-container.ytd-video-description-infocards-section-renderer{
  4856. margin: 0 32px;
  4857. }
  4858. */
  4859.  
  4860. #tab-info [show-expand-button] #expand-sizer.ytd-text-inline-expander{
  4861. visibility: initial;
  4862. }
  4863.  
  4864.  
  4865. #tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer > #left-arrow-container.ytd-video-description-infocards-section-renderer > #left-arrow{
  4866. border: 6px solid transparent;
  4867. opacity: 0.65;
  4868. }
  4869. #tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer > #right-arrow-container.ytd-video-description-infocards-section-renderer >#right-arrow{
  4870. border: 6px solid transparent;
  4871. opacity: 0.65;
  4872. }
  4873.  
  4874.  
  4875.  
  4876. #tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer > #left-arrow-container.ytd-video-description-infocards-section-renderer > #left-arrow:hover{
  4877. opacity: 1;
  4878. }
  4879. #tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer > #right-arrow-container.ytd-video-description-infocards-section-renderer >#right-arrow:hover{
  4880.  
  4881. opacity: 1;
  4882. }
  4883.  
  4884.  
  4885. #tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer > div#left-arrow-container::before {
  4886. content: '';
  4887. background: transparent;
  4888. width: 40px;
  4889. display: block;
  4890. height: 40px;
  4891. position: absolute;
  4892. left: -20px;
  4893. top: 0;
  4894. z-index: -1;
  4895. }
  4896. #tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer > div#right-arrow-container::before {
  4897. content: '';
  4898. background: transparent;
  4899. width: 40px;
  4900. display: block;
  4901. height: 40px;
  4902. position: absolute;
  4903. right: -20px;
  4904. top: 0;
  4905. z-index: -1;
  4906. }
  4907.  
  4908.  
  4909.  
  4910. body ytd-watch-flexy[is-two-columns_][tyt-egm-panel_] #columns.style-scope.ytd-watch-flexy #panels.style-scope.ytd-watch-flexy{
  4911. flex-grow: 1;
  4912. flex-shrink: 0;
  4913. display: flex;
  4914. flex-direction: column;
  4915. }
  4916.  
  4917.  
  4918. body ytd-watch-flexy[is-two-columns_][tyt-egm-panel_] #columns.style-scope.ytd-watch-flexy #panels.style-scope.ytd-watch-flexy ytd-engagement-panel-section-list-renderer[target-id][visibility="ENGAGEMENT_PANEL_VISIBILITY_EXPANDED"]{
  4919.  
  4920. height: initial;
  4921. max-height: initial;
  4922. min-height: initial;
  4923. flex-grow: 1;
  4924. flex-shrink: 0;
  4925. display: flex;
  4926. flex-direction: column;
  4927.  
  4928. }
  4929.  
  4930.  
  4931. body ytd-watch-flexy[is-two-columns_][tyt-egm-panel_] #columns.style-scope.ytd-watch-flexy #panels.style-scope.ytd-watch-flexy ytd-engagement-panel-section-list-renderer[target-id][visibility="ENGAGEMENT_PANEL_VISIBILITY_EXPANDED"] #content.style-scope.ytd-engagement-panel-section-list-renderer{
  4932.  
  4933. /*
  4934. height: initial;
  4935. max-height: initial;
  4936. min-height: initial;
  4937. flex-grow: 1;
  4938. flex-shrink: 0;
  4939. margin: 0;
  4940. padding: 0;
  4941. border: 0;
  4942. display: flex;
  4943. flex-direction: column;
  4944. */
  4945. }
  4946.  
  4947.  
  4948. body ytd-watch-flexy[is-two-columns_][tyt-egm-panel_] #columns.style-scope.ytd-watch-flexy #panels.style-scope.ytd-watch-flexy ytd-engagement-panel-section-list-renderer[target-id][visibility="ENGAGEMENT_PANEL_VISIBILITY_EXPANDED"] #content.style-scope.ytd-engagement-panel-section-list-renderer > [panel-target-id]{
  4949.  
  4950. /*
  4951. height: initial;
  4952. max-height: initial;
  4953. min-height: initial;
  4954. flex-grow: 1;
  4955. flex-shrink: 0;
  4956. margin: 0;
  4957. padding: 0;
  4958. border: 0;
  4959. */
  4960. }
  4961.  
  4962.  
  4963. secondary-wrapper [visibility="ENGAGEMENT_PANEL_VISIBILITY_EXPANDED"] ytd-transcript-renderer:not(:empty),
  4964. secondary-wrapper [visibility="ENGAGEMENT_PANEL_VISIBILITY_EXPANDED"] #body.ytd-transcript-renderer:not(:empty),
  4965. secondary-wrapper [visibility="ENGAGEMENT_PANEL_VISIBILITY_EXPANDED"] #content.ytd-transcript-renderer:not(:empty){
  4966.  
  4967. flex-grow: 1;
  4968. height: initial;
  4969. max-height: initial;
  4970. min-height: initial;
  4971. }
  4972.  
  4973. secondary-wrapper #content.ytd-engagement-panel-section-list-renderer{
  4974.  
  4975. position: relative;
  4976. }
  4977.  
  4978. /*
  4979. @supports (contain: strict) {
  4980.  
  4981. secondary-wrapper #content.ytd-engagement-panel-section-list-renderer > [panel-target-id]:only-child{
  4982.  
  4983. contain: strict;
  4984. max-height: 100%;
  4985. }
  4986.  
  4987. }
  4988.  
  4989.  
  4990. @supports not (contain: strict) {
  4991.  
  4992. secondary-wrapper #content.ytd-engagement-panel-section-list-renderer > [panel-target-id]:only-child{
  4993.  
  4994. position: absolute;
  4995. max-height: 100%;
  4996. }
  4997.  
  4998. }
  4999. */
  5000.  
  5001.  
  5002. secondary-wrapper #content.ytd-engagement-panel-section-list-renderer > [panel-target-id]:only-child{
  5003. /* https://www.youtube.com/watch?v=zLak0dxBKpM Transcript Panel Language Toggle */
  5004. contain: style size;
  5005. }
  5006.  
  5007. secondary-wrapper #content.ytd-engagement-panel-section-list-renderer ytd-transcript-segment-list-renderer.ytd-transcript-search-panel-renderer {
  5008. flex-grow: 1;
  5009. contain: strict;
  5010. }
  5011.  
  5012. secondary-wrapper #content.ytd-engagement-panel-section-list-renderer ytd-transcript-segment-renderer.style-scope.ytd-transcript-segment-list-renderer {
  5013. contain: layout paint style;
  5014. }
  5015.  
  5016. secondary-wrapper #content.ytd-engagement-panel-section-list-renderer ytd-transcript-segment-renderer.style-scope.ytd-transcript-segment-list-renderer > .segment {
  5017. contain: layout paint style;
  5018. }
  5019.  
  5020.  
  5021.  
  5022.  
  5023.  
  5024.  
  5025. body ytd-watch-flexy[theater] #secondary.ytd-watch-flexy {
  5026. margin-top: var(--ytd-margin-3x);
  5027. padding-top: 0;
  5028. }
  5029.  
  5030. body ytd-watch-flexy[theater] secondary-wrapper {
  5031. margin-top: 0;
  5032. padding-top: 0;
  5033. }
  5034.  
  5035. body ytd-watch-flexy[theater] #chat.ytd-watch-flexy{
  5036. margin-bottom: var(--ytd-margin-2x);
  5037. }
  5038.  
  5039. #tab-comments ytd-comments#comments [field-of-cm-count]{
  5040. margin-top:0;
  5041. }
  5042. /*
  5043.  
  5044. #tab-info #social-links.ytd-video-description-infocards-section-renderer {
  5045. margin-bottom:0;
  5046. }
  5047. #tab-info #social-links.ytd-video-description-infocards-section-renderer ~ #infocards-section {
  5048. margin-top: 16px;
  5049. }
  5050.  
  5051. #tab-info ytd-structured-description-content-renderer ytd-video-description-infocards-section-renderer.ytd-structured-description-content-renderer{
  5052. padding-bottom:0;
  5053. }
  5054. */
  5055.  
  5056. #tab-info > ytd-expandable-video-description-body-renderer {
  5057. margin-bottom: var(--ytd-margin-3x);
  5058. }
  5059.  
  5060. #tab-info [class]:last-child {
  5061. margin-bottom: 0;
  5062. padding-bottom: 0;
  5063. }
  5064.  
  5065.  
  5066. #tab-info ytd-rich-metadata-row-renderer ytd-rich-metadata-renderer {
  5067. max-width: initial;
  5068. }
  5069.  
  5070. ytd-watch-flexy[is-two-columns_] secondary-wrapper #chat.ytd-watch-flexy {
  5071. margin-bottom: var(--ytd-margin-3x);
  5072. }
  5073.  
  5074. ytd-watch-flexy[tyt-tab] tp-yt-paper-tooltip {
  5075. white-space: nowrap;
  5076. contain: content;
  5077. }
  5078.  
  5079.  
  5080. ytd-watch-info-text tp-yt-paper-tooltip.style-scope.ytd-watch-info-text{
  5081. margin-bottom: -300px;
  5082. margin-top: -96px;
  5083. }
  5084.  
  5085.  
  5086. [hide-default-text-inline-expander] #bottom-row #description.ytd-watch-metadata {
  5087. font-size: 1.2rem;
  5088. line-height: 1.8rem;
  5089.  
  5090. }
  5091.  
  5092. [hide-default-text-inline-expander] #bottom-row #description.ytd-watch-metadata yt-animated-rolling-number{
  5093. font-size: inherit;
  5094. }
  5095.  
  5096.  
  5097. [hide-default-text-inline-expander] #bottom-row #description.ytd-watch-metadata #info-container.style-scope.ytd-watch-info-text{
  5098. align-items: center;
  5099. }
  5100.  
  5101.  
  5102. ytd-watch-flexy[hide-default-text-inline-expander]{
  5103. --tyt-bottom-watch-metadata-margin: 6px;
  5104. }
  5105.  
  5106. [hide-default-text-inline-expander] #bottom-row #description.ytd-watch-metadata > #description-inner.ytd-watch-metadata{
  5107.  
  5108. margin: 6px 12px;
  5109.  
  5110. }
  5111.  
  5112. [hide-default-text-inline-expander] ytd-watch-metadata[title-headline-xs] h1.ytd-watch-metadata {
  5113.  
  5114. font-size: 1.8rem;
  5115. }
  5116.  
  5117.  
  5118.  
  5119. ytd-watch-flexy[is-two-columns_][hide-default-text-inline-expander] #below.style-scope.ytd-watch-flexy ytd-merch-shelf-renderer{
  5120. padding: 0;
  5121. border: 0;
  5122. margin:0;
  5123. }
  5124.  
  5125.  
  5126. ytd-watch-flexy[is-two-columns_][hide-default-text-inline-expander] #below.style-scope.ytd-watch-flexy ytd-watch-metadata.ytd-watch-flexy {
  5127. margin-bottom: 6px;
  5128. }
  5129.  
  5130. #tab-info yt-video-attribute-view-model .yt-video-attribute-view-model--horizontal .yt-video-attribute-view-model__link-container .yt-video-attribute-view-model__hero-section {
  5131. flex-shrink:0;
  5132. }
  5133.  
  5134.  
  5135. #tab-info yt-video-attribute-view-model .yt-video-attribute-view-model__overflow-menu{
  5136. background: var(--yt-emoji-picker-category-background-color);
  5137. border-radius: 99px;
  5138. }
  5139.  
  5140. #tab-info yt-video-attribute-view-model .yt-video-attribute-view-model--image-square.yt-video-attribute-view-model--image-large .yt-video-attribute-view-model__hero-section{
  5141.  
  5142. max-height: 128px;
  5143. }
  5144.  
  5145. #tab-info yt-video-attribute-view-model .yt-video-attribute-view-model--image-large .yt-video-attribute-view-model__hero-section{
  5146.  
  5147. max-width: 128px;
  5148. }
  5149.  
  5150. #tab-info ytd-reel-shelf-renderer #items.yt-horizontal-list-renderer ytd-reel-item-renderer.yt-horizontal-list-renderer {
  5151. max-width: 142px;
  5152. }
  5153.  
  5154. ytd-watch-info-text#ytd-watch-info-text.style-scope.ytd-watch-metadata #view-count.style-scope.ytd-watch-info-text{
  5155. align-items: center;
  5156. }
  5157.  
  5158.  
  5159. ytd-watch-info-text#ytd-watch-info-text.style-scope.ytd-watch-metadata #date-text.style-scope.ytd-watch-info-text{
  5160. align-items: center;
  5161. }
  5162.  
  5163.  
  5164. ytd-watch-info-text:not([detailed]) #info.ytd-watch-info-text a.yt-simple-endpoint.yt-formatted-string {
  5165.  
  5166. pointer-events: none;
  5167. }
  5168.  
  5169.  
  5170. body ytd-app > ytd-popup-container > tp-yt-iron-dropdown > #contentWrapper > [slot="dropdown-content"] {
  5171.  
  5172. backdrop-filter: none ;
  5173. }
  5174.  
  5175. #tab-info [tyt-clone-refresh-count] {
  5176. overflow: visible !important;
  5177. }
  5178.  
  5179. /* css unknown sizing bug */
  5180. #tab-info #items.ytd-horizontal-card-list-renderer yt-video-attribute-view-model.ytd-horizontal-card-list-renderer {
  5181. contain: layout;
  5182. }
  5183.  
  5184.  
  5185. /* https://www.youtube.com/watch?v=2h3pbdTPu6Q */
  5186.  
  5187. #tab-info #thumbnail-container.ytd-structured-description-channel-lockup-renderer {
  5188. flex-shrink: 0;
  5189. }
  5190. #tab-info ytd-media-lockup-renderer[is-compact] #thumbnail-container.ytd-media-lockup-renderer {
  5191. flex-shrink: 0;
  5192. }
  5193.  
  5194. /* https://www.youtube.com/watch?v=cV2gBU6hKfY */
  5195. secondary-wrapper ytd-donation-unavailable-renderer{
  5196. --ytd-margin-6x:var(--ytd-margin-2x);
  5197. --ytd-margin-5x:var(--ytd-margin-2x);
  5198. --ytd-margin-4x:var(--ytd-margin-2x);
  5199. --ytd-margin-3x:var(--ytd-margin-2x);
  5200. }
  5201.  
  5202.  
  5203. [tyt-no-less-btn] #less{
  5204. display: none;
  5205. }
  5206.  
  5207. .tyt-metadata-hover-resized #purchase-button,
  5208. .tyt-metadata-hover-resized #sponsor-button,
  5209. .tyt-metadata-hover-resized #analytics-button,
  5210. .tyt-metadata-hover-resized #subscribe-button
  5211. {
  5212. display: none !important;
  5213. }
  5214.  
  5215. .tyt-metadata-hover #upload-info {
  5216. max-width: max-content;
  5217. min-width: max-content;
  5218. flex-basis: 100vw;
  5219. flex-shrink: 0;
  5220. }
  5221.  
  5222. #tab-info ytd-structured-description-playlist-lockup-renderer[collections] #playlist-thumbnail.style-scope.ytd-structured-description-playlist-lockup-renderer {
  5223. max-width: 100%;
  5224. }
  5225.  
  5226. #tab-info ytd-structured-description-playlist-lockup-renderer[collections] #lockup-container.ytd-structured-description-playlist-lockup-renderer{
  5227. padding: 1px;
  5228. }
  5229.  
  5230. #tab-info ytd-structured-description-playlist-lockup-renderer[collections] #thumbnail.ytd-structured-description-playlist-lockup-renderer {
  5231. outline: 1px solid rgba(127, 127, 127, 0.5);
  5232. }
  5233.  
  5234. /* minor spacing fix */
  5235.  
  5236. /* https://www.youtube.com/watch?v=wAcY2fx0UWQ */
  5237. ytd-live-chat-frame#chat[collapsed] ytd-message-renderer ~ #show-hide-button.ytd-live-chat-frame>ytd-toggle-button-renderer.ytd-live-chat-frame
  5238. {
  5239. padding:0;
  5240. }
  5241.  
  5242. .tyt-info-invisible {
  5243. display: none;
  5244. }
  5245.  
  5246. [tyt-playlist-expanded] secondary-wrapper > ytd-playlist-panel-renderer#playlist {
  5247. overflow: auto;
  5248. flex-shrink: 1;
  5249. flex-grow: 1;
  5250. max-height: unset !important;
  5251. }
  5252.  
  5253. [tyt-playlist-expanded] secondary-wrapper > ytd-playlist-panel-renderer#playlist > #container {
  5254. max-height: unset !important;
  5255. }
  5256.  
  5257. secondary-wrapper ytd-playlist-panel-renderer{
  5258. --ytd-margin-6x: var(--ytd-margin-3x);
  5259. }
  5260.  
  5261. ytd-watch-flexy[theater] ytd-playlist-panel-renderer[collapsible][collapsed] .header.ytd-playlist-panel-renderer {
  5262. padding: 6px 8px;
  5263. }
  5264. ytd-watch-flexy[theater] #playlist.ytd-watch-flexy {
  5265. margin-bottom: var(--ytd-margin-2x);
  5266. }
  5267.  
  5268. ytd-watch-flexy[theater] #right-tabs .tab-btn[tyt-tab-content] {
  5269. padding: 8px 4px 6px;
  5270. border-bottom: 0px solid transparent;
  5271. }
  5272.  
  5273. ytd-watch-flexy {
  5274. --tyt-bottom-watch-metadata-margin: 12px;
  5275. }
  5276. ytd-watch-flexy[rounded-info-panel],
  5277. ytd-watch-flexy[rounded-player-large] {
  5278. --tyt-rounded-a1: ${VAL_ROUNDED_A1}px;
  5279. }
  5280.  
  5281. #bottom-row.style-scope.ytd-watch-metadata .item.ytd-watch-metadata {
  5282. margin-right: var(--tyt-bottom-watch-metadata-margin, 12px);
  5283. margin-top: var(--tyt-bottom-watch-metadata-margin, 12px);
  5284. }
  5285.  
  5286. /* fix cinematics lighting issue */
  5287. #cinematics {
  5288. contain: layout style size;
  5289. }
  5290.  
  5291. `
  5292. };
  5293. (async () => {
  5294. const communicationKey = `ck-${Date.now()}-${Math.floor(Math.random() * 314159265359 + 314159265359).toString(36)}`;
  5295.  
  5296. /** @type {globalThis.PromiseConstructor} */
  5297. const Promise = (async () => { })().constructor; // YouTube hacks Promise in WaterFox Classic and "Promise.resolve(0)" nevers resolve.
  5298.  
  5299. if (!document.documentElement) {
  5300. await Promise.resolve(0);
  5301. while (!document.documentElement) {
  5302. await new Promise(resolve => nextBrowserTick(resolve)).then().catch(console.warn);
  5303. }
  5304. }
  5305. const sourceURL = 'debug://tabview-youtube/tabview.execution.js'
  5306. const textContent = `(${executionScript})("${communicationKey}");${"\n\n"}//# sourceURL=${sourceURL}${'\n'}`
  5307.  
  5308. // const isMyScriptInChromeRuntime = () => typeof GM === 'undefined' && typeof ((((window || 0).chrome || 0).runtime || 0).getURL) === 'function';
  5309. // const isGMAvailable = () => typeof GM !== 'undefined' && !isMyScriptInChromeRuntime();
  5310.  
  5311. // if(isMyScriptInChromeRuntime()){
  5312. // let button = document.createElement('button');
  5313. // button.setAttribute('onclick', textContent);
  5314. // button.click();
  5315. // button = null;
  5316. // }else{
  5317. // GM_addElement('script', {
  5318. // textContent: textContent
  5319. // });
  5320. // }
  5321.  
  5322. let button = document.createElement('button');
  5323. button.setAttribute('onclick', createHTML(textContent)); // max size 10 million bytes
  5324. button.click();
  5325. button = null;
  5326.  
  5327.  
  5328. let style = document.createElement('style');
  5329. const sourceURLMainCSS = 'debug://tabview-youtube/tabview.main.css';
  5330. style.textContent = `${styles['main'].trim()}${'\n\n'}/*# sourceURL=${sourceURLMainCSS} */${'\n'}`;
  5331. document.documentElement.appendChild(style);
  5332.  
  5333.  
  5334. })();