Tabview YouTube Totara

To make tabs for Info, Comments, Videos and Playlist

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