Tabview YouTube Totara

制作信息、评论、视频和播放列表的标签

当前为 2024-08-03 提交的版本,查看 最新版本

  1. /*
  2.  
  3. MIT License
  4.  
  5. Copyright (c) 2024 cyfung1031
  6.  
  7. Permission is hereby granted, free of charge, to any person obtaining a copy
  8. of this software and associated documentation files (the "Software"), to deal
  9. in the Software without restriction, including without limitation the rights
  10. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. copies of the Software, and to permit persons to whom the Software is
  12. furnished to do so, subject to the following conditions:
  13.  
  14. The above copyright notice and this permission notice shall be included in all
  15. copies or substantial portions of the Software.
  16.  
  17. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  23. SOFTWARE.
  24.  
  25. */
  26. // ==UserScript==
  27. // @name Tabview YouTube Totara
  28. // @namespace https://www.youtube.com/
  29. // @author CY Fung
  30. // @license MIT
  31. // @match https://www.youtube.com/*
  32. // @exclude /^https?://\w+\.youtube\.com\/live_chat.*$/
  33. // @exclude /^https?://\S+\.(txt|png|jpg|jpeg|gif|xml|svg|manifest|log|ini)[^\/]*$/
  34.  
  35. // @version 5.0.009
  36. // @author CY Fung
  37. // @description To make tabs for Info, Comments, Videos and Playlist
  38.  
  39. // @description:es Para crear pestañas para Información, Comentarios, Videos y Lista de reproducción
  40. // @description:fr Pour créer des onglets pour Infos, Commentaires, Vidéos et Playlist
  41. // @description:de Um Tabs für Informationen, Kommentare, Videos und Playlist zu erstellen
  42. // @description:zh 制作信息、评论、视频和播放列表的标签
  43. // @description:zh-CN 制作信息、评论、视频和播放列表的标签
  44. // @description:zh-TW 製作資訊、評論、影片和播放列表的標籤
  45. // @description:zh-HK 製作資訊、評論、影片視頻和播放列表的標籤
  46. // @description:ja 情報、コメント、動画、および再生リストのタブを作成するために
  47. // @description:ko 정보, 댓글, 동영상 및 재생 목록에 대한 탭 만들기
  48. // @description:ru Чтобы создать вкладки для Информации, Комментариев, Видео и Плейлиста
  49. // @description:pt Para fazer abas para Informações, Comentários, Vídeos e Playlist
  50. // @description:ar لإنشاء علامات تبويب للمعلومات والتعليقات والفيديو وقائمة التشغيل
  51.  
  52. // @icon https://raw.githubusercontent.com/tabview-youtube/Tabview-YouTube-Totara/main/images/icon128p.png
  53. // @supportURL https://github.com/tabview-youtube/Tabview-YouTube-Totara
  54. // @run-at document-start
  55. // @grant GM_getResourceText
  56. // @grant GM.getResourceText
  57. // @grant GM_registerMenuCommand
  58. // @grant GM_addElement
  59. // @noframes
  60. // @require https://cdn.jsdelivr.net/gh/cyfung1031/userscript-supports@7221a4efffd49d852de0074ec503d4febb99f28b/library/nextBrowserTick.min.js
  61. //
  62. // ==/UserScript==
  63.  
  64.  
  65. !window.TTP && (() => {
  66. // credit to Benjamin Philipp
  67. // original source: https://greasyfork.org/en/scripts/433051-trusted-types-helper
  68.  
  69. // --------------------------------------------------- Trusted Types Helper ---------------------------------------------------
  70.  
  71. const overwrite_default = false; // If a default policy already exists, it might be best not to overwrite it, but to try and set a custom policy and use it to manually generate trusted types. Try at your own risk
  72. const prefix = `TTP`;
  73. var passThroughFunc = function (string, sink) {
  74. return string; // Anything passing through this function will be returned without change
  75. }
  76. var TTPName = "passthrough";
  77. var TTP_default, TTP = { createHTML: passThroughFunc, createScript: passThroughFunc, createScriptURL: passThroughFunc }; // We can use TTP.createHTML for all our assignments even if we don't need or even have Trusted Types; this should make fallbacks and polyfills easy
  78. var needsTrustedHTML = false;
  79. function doit() {
  80. try {
  81. if (typeof window.isSecureContext !== 'undefined' && window.isSecureContext) {
  82. if (window.trustedTypes && window.trustedTypes.createPolicy) {
  83. needsTrustedHTML = true;
  84. if (trustedTypes.defaultPolicy) {
  85. log("TT Default Policy exists");
  86. if (overwrite_default)
  87. TTP = window.trustedTypes.createPolicy("default", TTP);
  88. else
  89. TTP = window.trustedTypes.createPolicy(TTPName, TTP); // Is the default policy permissive enough? If it already exists, best not to overwrite it
  90. TTP_default = trustedTypes.defaultPolicy;
  91.  
  92. log("Created custom passthrough policy, in case the default policy is too restrictive: Use Policy '" + TTPName + "' in var 'TTP':", TTP);
  93. }
  94. else {
  95. TTP_default = TTP = window.trustedTypes.createPolicy("default", TTP);
  96. }
  97. log("Trusted-Type Policies: TTP:", TTP, "TTP_default:", TTP_default);
  98. }
  99. }
  100. } catch (e) {
  101. log(e);
  102. }
  103. }
  104.  
  105. function log(...args) {
  106. if ("undefined" != typeof (prefix) && !!prefix)
  107. args = [prefix + ":", ...args];
  108. if ("undefined" != typeof (debugging) && !!debugging)
  109. args = [...args, new Error().stack.replace(/^\s*(Error|Stack trace):?\n/gi, "").replace(/^([^\n]*\n)/, "\n")];
  110. console.log(...args);
  111. }
  112.  
  113. doit();
  114.  
  115. // --------------------------------------------------- Trusted Types Helper ---------------------------------------------------
  116.  
  117. window.TTP = TTP;
  118.  
  119. })();
  120.  
  121. function createHTML(s) {
  122. if (typeof TTP !== 'undefined' && typeof TTP.createHTML === 'function') return TTP.createHTML(s);
  123. return s;
  124. }
  125.  
  126. let trustHTMLErr = null;
  127. try {
  128. document.createElement('div').innerHTML = createHTML('1');
  129. } catch (e) {
  130. trustHTMLErr = e;
  131. }
  132.  
  133. if (trustHTMLErr) {
  134. console.log(`trustHTMLErr`, trustHTMLErr);
  135. trustHTMLErr(); // exit userscript
  136. }
  137.  
  138.  
  139. // -----------------------------------------------------------------------------------------------------------------------------
  140.  
  141. const executionScript = (communicationKey) => {
  142.  
  143.  
  144.  
  145. !window.TTP && (() => {
  146. // credit to Benjamin Philipp
  147. // original source: https://greasyfork.org/en/scripts/433051-trusted-types-helper
  148.  
  149. // --------------------------------------------------- Trusted Types Helper ---------------------------------------------------
  150.  
  151. const overwrite_default = false; // If a default policy already exists, it might be best not to overwrite it, but to try and set a custom policy and use it to manually generate trusted types. Try at your own risk
  152. const prefix = `TTP`;
  153. var passThroughFunc = function (string, sink) {
  154. return string; // Anything passing through this function will be returned without change
  155. }
  156. var TTPName = "passthrough";
  157. var TTP_default, TTP = { createHTML: passThroughFunc, createScript: passThroughFunc, createScriptURL: passThroughFunc }; // We can use TTP.createHTML for all our assignments even if we don't need or even have Trusted Types; this should make fallbacks and polyfills easy
  158. var needsTrustedHTML = false;
  159. function doit() {
  160. try {
  161. if (typeof window.isSecureContext !== 'undefined' && window.isSecureContext) {
  162. if (window.trustedTypes && window.trustedTypes.createPolicy) {
  163. needsTrustedHTML = true;
  164. if (trustedTypes.defaultPolicy) {
  165. log("TT Default Policy exists");
  166. if (overwrite_default)
  167. TTP = window.trustedTypes.createPolicy("default", TTP);
  168. else
  169. TTP = window.trustedTypes.createPolicy(TTPName, TTP); // Is the default policy permissive enough? If it already exists, best not to overwrite it
  170. TTP_default = trustedTypes.defaultPolicy;
  171.  
  172. log("Created custom passthrough policy, in case the default policy is too restrictive: Use Policy '" + TTPName + "' in var 'TTP':", TTP);
  173. }
  174. else {
  175. TTP_default = TTP = window.trustedTypes.createPolicy("default", TTP);
  176. }
  177. log("Trusted-Type Policies: TTP:", TTP, "TTP_default:", TTP_default);
  178. }
  179. }
  180. } catch (e) {
  181. log(e);
  182. }
  183. }
  184.  
  185. function log(...args) {
  186. if ("undefined" != typeof (prefix) && !!prefix)
  187. args = [prefix + ":", ...args];
  188. if ("undefined" != typeof (debugging) && !!debugging)
  189. args = [...args, new Error().stack.replace(/^\s*(Error|Stack trace):?\n/gi, "").replace(/^([^\n]*\n)/, "\n")];
  190. console.log(...args);
  191. }
  192.  
  193. doit();
  194.  
  195. // --------------------------------------------------- Trusted Types Helper ---------------------------------------------------
  196.  
  197. window.TTP = TTP;
  198.  
  199. })();
  200.  
  201. function createHTML(s) {
  202. if (typeof TTP !== 'undefined' && typeof TTP.createHTML === 'function') return TTP.createHTML(s);
  203. return s;
  204. }
  205.  
  206. let trustHTMLErr = null;
  207. try {
  208. document.createElement('div').innerHTML = createHTML('1');
  209. } catch (e) {
  210. trustHTMLErr = e;
  211. }
  212.  
  213. if (trustHTMLErr) {
  214. console.log(`trustHTMLErr`, trustHTMLErr);
  215. trustHTMLErr(); // exit userscript
  216. }
  217.  
  218. try {
  219.  
  220. executionFinished = 0;
  221. // const connectedCallbackX = function () {
  222. // console.log(59391, this.is, 'connectedCallbackX');
  223. // if (typeof this.connectedCallback000 === 'function') {
  224. // return this.connectedCallback000(...arguments);
  225. // }
  226. // }
  227. // const disconnectedCallbackX = function () {
  228. // console.log(59392, this.is, 'disconnectedCallbackX');
  229. // if (typeof this.disconnectedCallback000 === 'function') {
  230. // return this.disconnectedCallback000(...arguments);
  231. // }
  232. // }
  233.  
  234.  
  235. const connectedCallbackY = function (callback) {
  236. return function () {
  237. // console.log(59391, this.is, 'connectedCallbackY');
  238. if (executionFinished && typeof (this || 0).is === 'string') {
  239. const f = eventMap[`${this.is}::connectedCallback`];
  240. if (f) {
  241. const hostElement = this.hostElement || this;
  242. if (hostElement instanceof HTMLElement) {
  243. hostElement.__connectedFlg__ = 4;
  244. hostElement && Promise.resolve(hostElement).then(f).catch(console.warn);
  245. }
  246. }
  247. }
  248. if (typeof callback === 'function') {
  249. return callback.call(this, ...arguments);
  250. }
  251. }
  252. }
  253. const disconnectedCallbackY = function (callback) {
  254. return function () {
  255. // console.log(59392, this.is, 'disconnectedCallbackY');
  256. if (executionFinished && typeof (this || 0).is === 'string') {
  257. const f = eventMap[`${this.is}::disconnectedCallback`];
  258. if (f) {
  259. const hostElement = this.hostElement || this;
  260. if (hostElement instanceof HTMLElement) {
  261. hostElement.__connectedFlg__ = 8;
  262. hostElement && Promise.resolve(hostElement).then(f).catch(console.warn);
  263. }
  264. }
  265. }
  266. if (typeof callback === 'function') {
  267. return callback.call(this, ...arguments);
  268. }
  269. }
  270. }
  271.  
  272. if (typeof CustomElementRegistry === 'undefined') return;
  273. if (CustomElementRegistry.prototype.define000) return;
  274. if (typeof CustomElementRegistry.prototype.define !== 'function') return;
  275. CustomElementRegistry.prototype.define000 = CustomElementRegistry.prototype.define;
  276. CustomElementRegistry.prototype.define = function (a, b, ...args) {
  277. // b.prototype.connectedCallback000 =b.prototype.connectedCallback;
  278. // b.prototype.disconnectedCallback000 =b.prototype.disconnectedCallback;
  279. b.prototype.connectedCallback = connectedCallbackY(b.prototype.connectedCallback);
  280. b.prototype.disconnectedCallback = disconnectedCallbackY(b.prototype.disconnectedCallback);
  281. // b.prototype.__ce_tag__ = a;
  282. // b.__ce_tag__ = a;
  283. if (this instanceof CustomElementRegistry) {
  284. return this.define000(a, b, ...args);
  285. } else {
  286. return customElements.define000(a, b, ...args);
  287. }
  288. }
  289.  
  290. const pdsBaseDF = Object.getOwnPropertyDescriptors(DocumentFragment.prototype);
  291.  
  292. Object.defineProperties(DocumentFragment.prototype, {
  293. replaceChildren000: pdsBaseDF.replaceChildren,
  294. });
  295.  
  296. const pdsBaseNode = Object.getOwnPropertyDescriptors(Node.prototype);
  297. // console.log(pdsBaseElement.setAttribute, pdsBaseElement.getAttribute)
  298.  
  299. Object.defineProperties(Node.prototype, {
  300. removeChild000: pdsBaseNode.removeChild,
  301. appendChild000: pdsBaseNode.appendChild,
  302. insertBefore000: pdsBaseNode.insertBefore
  303. });
  304.  
  305. // class BaseElement extends Element{
  306.  
  307. // }
  308. const pdsBaseElement = Object.getOwnPropertyDescriptors(Element.prototype);
  309. // console.log(pdsBaseElement.setAttribute, pdsBaseElement.getAttribute)
  310.  
  311. Object.defineProperties(Element.prototype, {
  312. setAttribute000: pdsBaseElement.setAttribute,
  313. getAttribute000: pdsBaseElement.getAttribute,
  314. hasAttribute000: pdsBaseElement.hasAttribute,
  315. removeAttribute000: pdsBaseElement.removeAttribute,
  316. querySelector000: pdsBaseElement.querySelector,
  317. replaceChildren000: pdsBaseElement.replaceChildren,
  318. remove000: pdsBaseElement.remove
  319. });
  320.  
  321. Element.prototype.setAttribute111 = function (p, v) {
  322. v = `${v}`;
  323. if (this.getAttribute000(p) === v) return;
  324. this.setAttribute000(p, v)
  325. }
  326.  
  327. Element.prototype.assignChildern111 = function (previousSiblings, node, nextSiblings) {
  328. if (node.parentNode === this) {
  329. let nodeList = [];
  330. for (let t = this.firstChild; t instanceof Node; t = t.nextSibling) {
  331. if (t === node) continue;
  332. nodeList.push(t);
  333. }
  334. let fm = new DocumentFragment();
  335. if (nodeList.length > 0) {
  336. fm.replaceChildren000(...nodeList);
  337. nodeList.length = 0;
  338. }
  339. nodeList = null;
  340. if (previousSiblings && previousSiblings.length > 0) {
  341. fm.replaceChildren000(...previousSiblings);
  342. this.insertBefore000(fm, node);
  343. }
  344. if (nextSiblings && nextSiblings.length > 0) {
  345. fm.replaceChildren000(...nextSiblings);
  346. this.appendChild000(fm);
  347. }
  348. fm.replaceChildren000();
  349. fm = null;
  350. } else {
  351. if (!previousSiblings) previousSiblings = [];
  352. if (!nextSiblings) nextSiblings = [];
  353. this.replaceChildren000(...previousSiblings, node, ...nextSiblings);
  354. }
  355. }
  356.  
  357.  
  358. // ==============================================================================================================================================================================================================================================================================
  359.  
  360. const DISABLE_FLAGS_SHADYDOM_FREE = true;
  361.  
  362. /**
  363. *
  364. * Minified Code from https://greasyfork.org/en/scripts/475632-ytconfighacks/code (ytConfigHacks)
  365. * Date: 2024.04.17
  366. * Minifier: https://www.toptal.com/developers/javascript-minifier
  367. *
  368. */
  369. (() => {
  370. let e = "undefined" != typeof unsafeWindow ? unsafeWindow : this instanceof Window ?
  371. this : window; if (!e._ytConfigHacks) {
  372. let t = 4; class n extends Set {
  373. add(e) {
  374. if (t <= 0) return console.warn(
  375. "yt.config_ is already applied on the page."); "function" == typeof e && super.add(e)
  376. }
  377. } let a = (async () => { })()
  378. .constructor, i = e._ytConfigHacks = new n, l = () => { let t = e.ytcsi.originalYtcsi; t && (e.ytcsi = t, l = null) },
  379. c = null, o = () => {
  380. if (t >= 1) {
  381. let n = (e.yt || 0).config_ || (e.ytcfg || 0).data_ || 0; if ("string" == typeof n.
  382. INNERTUBE_API_KEY && "object" == typeof n.EXPERIMENT_FLAGS) for (let a of (--t <= 0 && l && l(), c = !0, i)) a(n)
  383. }
  384. }, f = 1,
  385. d = t => {
  386. 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]) })
  387. , !0
  388. }; d() || Object.defineProperty(e, "ytcsi", {
  389. get() { }, set: t => (t && (delete e.ytcsi, d(t)), !0), enumerable: !1, configurable: !0
  390. }); let { addEventListener: s, removeEventListener: y } = Document.prototype; function r(t) {
  391. o(),
  392. t && e.removeEventListener("DOMContentLoaded", r, !1)
  393. } new a(e => {
  394. if ("undefined" != typeof AbortSignal) s.call(document,
  395. "yt-page-data-fetched", e, { once: !0 }), s.call(document, "yt-navigate-finish", e, { once: !0 }), s.call(document, "spfdone", e,
  396. { once: !0 }); else {
  397. let t = () => {
  398. e(), y.call(document, "yt-page-data-fetched", t, !1), y.call(document, "yt-navigate-finish", t, !1),
  399. y.call(document, "spfdone", t, !1)
  400. }; s.call(document, "yt-page-data-fetched", t, !1), s.call(document, "yt-navigate-finish", t, !1),
  401. s.call(document, "spfdone", t, !1)
  402. }
  403. }).then(o), new a(e => {
  404. if ("undefined" != typeof AbortSignal) s.call(document, "yt-action", e,
  405. { once: !0, capture: !0 }); else { let t = () => { e(), y.call(document, "yt-action", t, !0) }; s.call(document, "yt-action", t, !0) }
  406. }).then(o),
  407. a.resolve().then(() => { "loading" !== document.readyState ? r() : e.addEventListener("DOMContentLoaded", r, !1) })
  408. }
  409. })();
  410.  
  411. let configOnce = false;
  412. window._ytConfigHacks.add((config_) => {
  413. if (configOnce) return;
  414. configOnce = true;
  415.  
  416. const EXPERIMENT_FLAGS = config_.EXPERIMENT_FLAGS || 0;
  417. const EXPERIMENTS_FORCED_FLAGS = config_.EXPERIMENTS_FORCED_FLAGS || 0;
  418. for (const flags of [EXPERIMENT_FLAGS, EXPERIMENTS_FORCED_FLAGS]) {
  419. if (flags) {
  420. // flags.kevlar_watch_metadata_refresh_no_old_secondary_data = false;
  421. // flags.live_chat_overflow_hide_chat = false;
  422. flags.web_watch_chat_hide_button_killswitch = false;
  423. flags.web_watch_theater_chat = false; // for re-openable chat (ytd-watch-flexy's liveChatCollapsed is always undefined)
  424. flags.suppress_error_204_logging = true;
  425. flags.kevlar_watch_grid = false; // A/B testing for watch grid
  426.  
  427. if (DISABLE_FLAGS_SHADYDOM_FREE) {
  428. flags.enable_shadydom_free_scoped_node_methods = false;
  429. flags.enable_shadydom_free_scoped_query_methods = false;
  430. flags.enable_shadydom_free_scoped_readonly_properties_batch_one = false;
  431. flags.enable_shadydom_free_parent_node = false;
  432. flags.enable_shadydom_free_children = false;
  433. flags.enable_shadydom_free_last_child = false;
  434. }
  435. }
  436. }
  437.  
  438. });
  439.  
  440. // ==============================================================================================================================================================================================================================================================================
  441.  
  442.  
  443. /* globals WeakRef:false */
  444.  
  445. /** @type {(o: Object | null) => WeakRef | null} */
  446. const mWeakRef = typeof WeakRef === 'function' ? (o => o ? new WeakRef(o) : null) : (o => o || null); // typeof InvalidVar == 'undefined'
  447.  
  448. /** @type {(wr: Object | null) => Object | null} */
  449. const kRef = (wr => (wr && wr.deref) ? wr.deref() : wr);
  450.  
  451.  
  452. /** @type {globalThis.PromiseConstructor} */
  453. const Promise = (async () => { })().constructor; // YouTube hacks Promise in WaterFox Classic and "Promise.resolve(0)" nevers resolve.
  454.  
  455. const delayPn = delay => new Promise((fn => setTimeout(fn, delay)));
  456.  
  457. const insp = o => o ? (o.polymerController || o.inst || o || 0) : (o || 0);
  458.  
  459. const PromiseExternal = ((resolve_, reject_) => {
  460. const h = (resolve, reject) => { resolve_ = resolve; reject_ = reject };
  461. return class PromiseExternal extends Promise {
  462. constructor(cb = h) {
  463. super(cb);
  464. if (cb === h) {
  465. /** @type {(value: any) => void} */
  466. this.resolve = resolve_;
  467. /** @type {(reason?: any) => void} */
  468. this.reject = reject_;
  469. }
  470. }
  471. };
  472. })();
  473.  
  474. // ------------------------------------------------------------------------ nextBrowserTick ------------------------------------------------------------------------
  475. !function (e) {
  476. "use strict"; if (e.nextBrowserTick) return; if (!function () {
  477. if (e.postMessage && !e.importScripts && e.addEventListener) {
  478. let t = !0, s = () => { t = !1 };
  479. return e.addEventListener("message", s, !1), e.postMessage("", "*"), e.removeEventListener("message", s, !1), t
  480. }
  481. }())
  482. return void console.warn("Your browser environment cannot use nextBrowserTick"); const t = (async () => { })().constructor,
  483. s = ((e, s) => { const n = (t, n) => { e = t, s = n }; return class extends t { constructor(t = n) { super(t), t === n && (this.resolve = e, this.reject = s) } } })();
  484. let n, r = null; do { n = `$$nextBrowserTick$$${(Math.random() + 8).toString().slice(2)}$$` } while (n in e); const o = n; e[o] = 1; e.addEventListener("message",
  485. (e => { (null !== r ? (e || 0).data : 0) === o && e.source === (e.target || 1) && r.resolve(r = null) }), !1), e.nextBrowserTick = t => {
  486. r || (r = new s, e.postMessage(o, "*")),
  487. r.then(t).catch(console.warn)
  488. }
  489. }("undefined" == typeof self ? "undefined" == typeof global ? this : global : self);
  490.  
  491. // ------------------------------------------------------------------------ nextBrowserTick ------------------------------------------------------------------------
  492.  
  493. const isPassiveArgSupport = (typeof IntersectionObserver === 'function');
  494. const bubblePassive = isPassiveArgSupport ? { capture: false, passive: true } : false;
  495. const capturePassive = isPassiveArgSupport ? { capture: true, passive: true } : true;
  496.  
  497.  
  498.  
  499. class Attributer {
  500. constructor(list) {
  501. this.list = list;
  502. this.flag = 0;
  503. }
  504. makeString() {
  505. let k = 1;
  506. let s = '';
  507. let i = 0;
  508. while (this.flag >= k) {
  509. if (this.flag & k) {
  510. s += this.list[i];
  511. }
  512. i++;
  513. k <<= 1;
  514. }
  515. return s;
  516. }
  517. }
  518.  
  519. const mLoaded = new Attributer('icp');
  520.  
  521. const wrSelfMap = new WeakMap();
  522.  
  523. /** @type {Object.<string, Element | null>} */
  524. const elements = new Proxy({
  525. related: null,
  526. comments: null,
  527. infoExpander: null,
  528. }, {
  529. get(target, prop) {
  530. return kRef(target[prop]);
  531. },
  532. set(target, prop, value) {
  533. if (value) {
  534. let wr = wrSelfMap.get(value);
  535. if (!wr) {
  536. wr = mWeakRef(value);
  537. wrSelfMap.set(value, wr);
  538. }
  539. target[prop] = wr;
  540. } else {
  541. target[prop] = null;
  542. }
  543. return true;
  544. }
  545. });
  546.  
  547.  
  548. let pageType = null;
  549.  
  550. let pageLang = 'en';
  551. const langWords = {
  552. 'en': {
  553. //'share':'Share',
  554. 'info': 'Info',
  555. 'videos': 'Videos',
  556. 'playlist': 'Playlist'
  557. },
  558. 'jp': {
  559. //'share':'共有',
  560. 'info': '情報',
  561. 'videos': '動画',
  562. 'playlist': '再生リスト'
  563. },
  564. 'tw': {
  565. //'share':'分享',
  566. 'info': '資訊',
  567. 'videos': '影片',
  568. 'playlist': '播放清單'
  569. },
  570. 'cn': {
  571. //'share':'分享',
  572. 'info': '资讯',
  573. 'videos': '视频',
  574. 'playlist': '播放列表'
  575. },
  576. 'du': {
  577. //'share':'Teilen',
  578. 'info': 'Info',
  579. 'videos': 'Videos',
  580. 'playlist': 'Playlist'
  581. },
  582. 'fr': {
  583. //'share':'Partager',
  584. 'info': 'Info',
  585. 'videos': 'Vidéos',
  586. 'playlist': 'Playlist'
  587. },
  588. 'kr': {
  589. //'share':'공유',
  590. 'info': '정보',
  591. 'videos': '동영상',
  592. 'playlist': '재생목록'
  593. },
  594. 'ru': {
  595. //'share':'Поделиться',
  596. 'info': 'Описание',
  597. 'videos': 'Видео',
  598. 'playlist': 'Плейлист'
  599. }
  600. };
  601.  
  602. 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
  603. 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
  604. 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
  605. 0 0 3-1V71h2a12 12 90 0 0 12-12V17a12 12 90 0 0-12-12z"/>`.trim();
  606.  
  607. 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
  608. 66H9V68h9v10zm0-56H9V12h9v10zm22 56H27V68h13v10zm-3-25V36c0-2 2-3 4-2l12 8c2 1 2 4 0 5l-12 8c-2 1-4 0-4-2zm25
  609. 25H49V68h13v10zm0-56H49V12h13v10zm18 56h-9V68h9v10zm0-56h-9V12h9v10z"/>`.trim();
  610.  
  611. 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
  612. 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
  613. .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
  614. .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
  615. 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
  616. 0 0 1.4-.4l-.6 2.2zm-3.8-35.2a1 1 0 010 8.6 1 1 0 010-8.6z"/>`.trim();
  617.  
  618. const svgPlayList = `<path d="M0 3h12v2H0zm0 4h12v2H0zm0 4h8v2H0zm16 0V7h-2v4h-4v2h4v4h2v-4h4v-2z"/>`.trim();
  619.  
  620. const svgDiag1 = `<svg stroke="currentColor" fill="none"><path d="M8 2h2v2M7 5l3-3m-6 8H2V8m0 2l3-3"/></svg>`;
  621. const svgDiag2 = `<svg stroke="currentColor" fill="none"><path d="M7 3v2h2M7 5l3-3M5 9V7H3m-1 3l3-3"/></svg>`;
  622.  
  623.  
  624. const getGMT = () => {
  625. let m = new Date('2023-01-01T00:00:00Z');
  626. return m.getDate() === 1 ? `+${m.getHours()}` : `-${24 - m.getHours()}`;
  627. };
  628.  
  629. function getWord(tag) {
  630. return langWords[pageLang][tag] || langWords['en'][tag] || '';
  631. }
  632.  
  633. 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>`
  634.  
  635. let hiddenTabsByUserCSS = 0;
  636.  
  637. function getTabsHTML() {
  638.  
  639. const sTabBtnVideos = `${svgElm(16, 16, 90, 90, svgVideos)}<span>${getWord('videos')}</span>`;
  640. const sTabBtnInfo = `${svgElm(16, 16, 60, 60, svgInfo)}<span>${getWord('info')}</span>`;
  641. const sTabBtnPlayList = `${svgElm(16, 16, 20, 20, svgPlayList)}<span>${getWord('playlist')}</span>`;
  642.  
  643. let str1 = `
  644. <paper-ripple class="style-scope yt-icon-button">
  645. <div id="background" class="style-scope paper-ripple" style="opacity:0;"></div>
  646. <div id="waves" class="style-scope paper-ripple"></div>
  647. </paper-ripple>
  648. `;
  649.  
  650. let str_fbtns = `
  651. <div class="font-size-right">
  652. <div class="font-size-btn font-size-plus" tyt-di="8rdLQ">
  653. <svg width="12" height="12" viewbox="0 0 50 50" preserveAspectRatio="xMidYMid meet"
  654. stroke="currentColor" stroke-width="6" stroke-linecap="round" vector-effect="non-scaling-size">
  655. <path d="M12 25H38M25 12V38"/>
  656. </svg>
  657. </div><div class="font-size-btn font-size-minus" tyt-di="8rdLQ">
  658. <svg width="12" height="12" viewbox="0 0 50 50" preserveAspectRatio="xMidYMid meet"
  659. stroke="currentColor" stroke-width="6" stroke-linecap="round" vector-effect="non-scaling-size">
  660. <path d="M12 25h26"/>
  661. </svg>
  662. </div>
  663. </div>
  664. `.replace(/[\r\n]+/g, '');
  665.  
  666. const str_tabs = [
  667. `<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>`,
  668. `<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>`,
  669. `<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>`,
  670. `<a id="tab-btn5" tyt-di="q9Kjc" tyt-tab-content="#tab-list" class="tab-btn tab-btn-hidden">${sTabBtnPlayList}${str1}${str_fbtns}</a>`
  671. ].join('');
  672.  
  673. let addHTML = `
  674. <div id="right-tabs">
  675. <tabview-view-pos-thead></tabview-view-pos-thead>
  676. <header>
  677. <div id="material-tabs">
  678. ${str_tabs}
  679. </div>
  680. </header>
  681. <div class="tab-content">
  682. <div id="tab-info" class="tab-content-cld tab-content-hidden" tyt-hidden userscript-scrollbar-render></div>
  683. <div id="tab-comments" class="tab-content-cld tab-content-hidden" tyt-hidden userscript-scrollbar-render></div>
  684. <div id="tab-videos" class="tab-content-cld tab-content-hidden" tyt-hidden userscript-scrollbar-render></div>
  685. <div id="tab-list" class="tab-content-cld tab-content-hidden" tyt-hidden userscript-scrollbar-render></div>
  686. </div>
  687. </div>
  688. `;
  689.  
  690. return addHTML;
  691.  
  692. }
  693.  
  694.  
  695. function getLang() {
  696.  
  697. let lang = 'en';
  698. let htmlLang = ((document || 0).documentElement || 0).lang || '';
  699. switch (htmlLang) {
  700. case 'en':
  701. case 'en-GB':
  702. lang = 'en';
  703. break;
  704. case 'de':
  705. case 'de-DE':
  706. lang = 'du';
  707. break;
  708. case 'fr':
  709. case 'fr-CA':
  710. case 'fr-FR':
  711. lang = 'fr';
  712. break;
  713. case 'zh-Hant':
  714. case 'zh-Hant-HK':
  715. case 'zh-Hant-TW':
  716. lang = 'tw';
  717. break;
  718. case 'zh-Hans':
  719. case 'zh-Hans-CN':
  720. lang = 'cn';
  721. break;
  722. case 'ja':
  723. case 'ja-JP':
  724. lang = 'jp';
  725. break;
  726. case 'ko':
  727. case 'ko-KR':
  728. lang = 'kr';
  729. break;
  730. case 'ru':
  731. case 'ru-RU':
  732. lang = 'ru';
  733. break;
  734. default:
  735. lang = 'en';
  736. }
  737.  
  738. return lang;
  739.  
  740. }
  741.  
  742. function getLangForPage() {
  743.  
  744. let lang = getLang();
  745.  
  746. if (langWords[lang]) pageLang = lang; else pageLang = 'en';
  747.  
  748. }
  749.  
  750. /** @type {Object.<string, number>} */
  751. const _locks = {}
  752.  
  753. const lockGet = new Proxy(_locks,
  754. {
  755. get(target, prop) {
  756. return (target[prop] || 0);
  757. },
  758. set(target, prop, val) {
  759. return true;
  760. }
  761. }
  762. );
  763.  
  764. const lockSet = new Proxy(_locks,
  765. {
  766. get(target, prop) {
  767. if (target[prop] > 1e9) target[prop] = 9;
  768. return (target[prop] = (target[prop] || 0) + 1);
  769. },
  770. set(target, prop, val) {
  771. return true;
  772. }
  773. }
  774. );
  775.  
  776. const videosElementProvidedPromise = new PromiseExternal();
  777. const navigateFinishedPromise = new PromiseExternal();
  778.  
  779. let isRightTabsInserted = false;
  780. const rightTabsProvidedPromise = new PromiseExternal();
  781.  
  782. const infoExpanderElementProvidedPromise = new PromiseExternal();
  783.  
  784.  
  785. const funcCanCollapse = function (s) {
  786. if (!s) return;
  787. this.canToggle = this.shouldUseNumberOfLines && (this.alwaysCollapsed || this.collapsed)
  788. ? this.alwaysToggleable || this.$.content.offsetHeight < this.$.content.scrollHeight
  789. : this.alwaysToggleable || this.$.content.scrollHeight > this.collapsedHeight
  790. };
  791.  
  792. const aoChat = new MutationObserver(() => {
  793. const chatElm = elements.chat;
  794. const ytdFlexyElm = elements.flexy;
  795. // console.log(1882, chatElm, ytdFlexyElm)
  796. if (chatElm && ytdFlexyElm) {
  797. if (chatElm.hasAttribute000('collapsed')) {
  798.  
  799. ytdFlexyElm.setAttribute111('tyt-chat-collapsed', '')
  800. } else {
  801.  
  802. ytdFlexyElm.removeAttribute000('tyt-chat-collapsed')
  803. }
  804.  
  805. ytdFlexyElm.setAttribute111('tyt-chat', chatElm.hasAttribute000('collapsed') ? '-' : '+');
  806.  
  807. }
  808. });
  809.  
  810. const aoComment = new MutationObserver((mutations) => {
  811. const commentsArea = elements.comments;
  812. const ytdFlexyElm = elements.flexy;
  813.  
  814. //tyt-comments-video-id //tyt-comments-data-status // hidden
  815. if (!commentsArea) return;
  816. let bfHidden = false;
  817. let bfCommentsVideoId = false;
  818. let bfCommentDisabled = false;
  819. for (const mutation of mutations) {
  820. if (mutation.attributeName === 'hidden' && mutation.target === commentsArea) {
  821. bfHidden = true;
  822. } else if (mutation.attributeName === 'tyt-comments-video-id' && mutation.target === commentsArea) {
  823. bfCommentsVideoId = true;
  824. } else if (mutation.attributeName === 'tyt-comments-data-status' && mutation.target === commentsArea) {
  825. bfCommentDisabled = true;
  826. }
  827. }
  828.  
  829. if (bfHidden) {
  830.  
  831. if (!commentsArea.hasAttribute000('hidden')) {
  832. Promise.resolve(commentsArea).then(eventMap['settingCommentsVideoId']).catch(console.warn);
  833. }
  834.  
  835. Promise.resolve(lockSet['removeKeepCommentsScrollerLock']).then(removeKeepCommentsScroller).catch(console.warn);
  836. }
  837.  
  838. if ((bfHidden || bfCommentsVideoId || bfCommentDisabled) && ytdFlexyElm) {
  839.  
  840. const commentsDataStatus = +commentsArea.getAttribute000('tyt-comments-data-status');
  841. if (commentsDataStatus === 2) {
  842. ytdFlexyElm.setAttribute111('tyt-comment-disabled', '')
  843. } else if (commentsDataStatus === 1) {
  844. ytdFlexyElm.removeAttribute000('tyt-comment-disabled')
  845. }
  846.  
  847. Promise.resolve(lockSet['checkCommentsShouldBeHiddenLock']).then(eventMap['checkCommentsShouldBeHidden']).catch(console.warn);
  848.  
  849.  
  850. if (isRightTabsInserted && commentsArea.closest('#tab-comments')) {
  851. if (commentsArea.closest('[hidden]')) {
  852. // document.querySelector('#tab-comments').classList.add('tab-content-hidden')
  853. document.querySelector('[tyt-tab-content="#tab-comments"]').classList.add('tab-btn-hidden')
  854. } else {
  855. // document.querySelector('#tab-comments').classList.remove('tab-content-hidden')
  856. document.querySelector('[tyt-tab-content="#tab-comments"]').classList.remove('tab-btn-hidden')
  857. }
  858. }
  859.  
  860. }
  861.  
  862.  
  863. });
  864.  
  865. const ioComment = new IntersectionObserver((entries) => {
  866.  
  867. for (const entry of entries) {
  868. const target = entry.target;
  869. const cnt = insp(target);
  870. if (entry.isIntersecting && target instanceof HTMLElement && typeof cnt.calculateCanCollapse === 'function') {
  871. lockSet['removeKeepCommentsScrollerLock'];
  872. cnt.calculateCanCollapse(true);
  873. target.setAttribute111('io-intersected', '');
  874. const ytdFlexyElm = elements.flexy;
  875. if (ytdFlexyElm && !ytdFlexyElm.hasAttribute000('keep-comments-scroller')) {
  876. ytdFlexyElm.setAttribute111('keep-comments-scroller', '');
  877. }
  878. } else if (target.hasAttribute000('io-intersected')) {
  879.  
  880. target.removeAttribute000('io-intersected');
  881. }
  882. }
  883.  
  884. }, {
  885. threshold: [0],
  886. rootMargin: "32px" // enlarging viewport for getting intersection earlier
  887. });
  888.  
  889.  
  890. let bFixForResizedTabLater = false;
  891. let lastRoRightTabsWidth = 0;
  892. const roRightTabs = new ResizeObserver((entries) => {
  893. const entry = entries[entries.length - 1];
  894. const width = Math.round(entry.borderBoxSize.inlineSize);
  895. if (lastRoRightTabsWidth !== width) {
  896. lastRoRightTabsWidth = width;
  897. if ((tabAStatus & 2) === 2) {
  898. bFixForResizedTabLater = false;
  899. Promise.resolve(1).then(eventMap['fixForTabDisplay']);
  900. } else {
  901. bFixForResizedTabLater = true;
  902. }
  903. }
  904. console.log('resize')
  905. });
  906.  
  907. const switchToTab = (activeLink) => {
  908.  
  909. if (typeof activeLink === 'string') {
  910. activeLink = document.querySelector(`a[tyt-tab-content="${activeLink}"]`) || null;
  911. }
  912.  
  913. const ytdFlexyElm = elements.flexy;
  914.  
  915.  
  916. const links = document.querySelectorAll('#material-tabs a[tyt-tab-content]');
  917.  
  918. //console.log(701, activeLink)
  919.  
  920. for (const link of links) {
  921. const content = document.querySelector(link.getAttribute000('tyt-tab-content'));
  922. if (link && content) {
  923. if (link !== activeLink) {
  924. link.classList.remove("active");
  925. content.classList.add("tab-content-hidden");
  926. if (!content.hasAttribute000("tyt-hidden")) {
  927. content.setAttribute111("tyt-hidden", ""); // for https://greasyfork.org/en/scripts/456108
  928. }
  929. } else {
  930. link.classList.add("active");
  931. if (content.hasAttribute000("tyt-hidden")) {
  932. content.removeAttribute000("tyt-hidden"); // for https://greasyfork.org/en/scripts/456108
  933. }
  934. content.classList.remove("tab-content-hidden");
  935. }
  936. }
  937. }
  938.  
  939. const switchingTo = activeLink ? activeLink.getAttribute000('tyt-tab-content') : '';
  940. if (switchingTo) {
  941. lastTab = lastPanel = switchingTo
  942. }
  943.  
  944. ytdFlexyElm.setAttribute111('tyt-tab', switchingTo);
  945.  
  946. if (switchingTo) {
  947. bFixForResizedTabLater = false;
  948. Promise.resolve(0).then(eventMap['fixForTabDisplay']);
  949. }
  950.  
  951. }
  952.  
  953. let tabAStatus = 0;
  954. const calculationFn = (r = 0, flag) => {
  955. const ytdFlexyElm = elements.flexy;
  956. if (!ytdFlexyElm) return r;
  957. if (flag & 1) {
  958. r |= 1;
  959. if (!ytdFlexyElm.hasAttribute000('theater')) r -= 1;
  960. }
  961. if (flag & 2) {
  962. r |= 2;
  963. if (!ytdFlexyElm.getAttribute000('tyt-tab')) r -= 2;
  964. }
  965. if (flag & 4) {
  966. r |= 4;
  967. if (ytdFlexyElm.getAttribute000('tyt-chat') !== '-') r -= 4;
  968. }
  969. if (flag & 8) {
  970. r |= 8;
  971. if (ytdFlexyElm.getAttribute000('tyt-chat') !== '+') r -= 8;
  972. }
  973. if (flag & 16) {
  974. r |= 16;
  975. if (!ytdFlexyElm.hasAttribute000('is-two-columns_')) r -= 16;
  976. }
  977. if (flag & 32) {
  978. r |= 32;
  979. if (!ytdFlexyElm.hasAttribute000('tyt-egm-panel_')) r -= 32;
  980. }
  981. if (flag & 64) {
  982.  
  983. r |= 64;
  984. if (!document.fullscreenElement) r -= 64;
  985. }
  986. return r;
  987.  
  988. }
  989.  
  990. function isTheater() {
  991. const ytdFlexyElm = elements.flexy;
  992. return (ytdFlexyElm && ytdFlexyElm.hasAttribute000('theater'))
  993. }
  994.  
  995. function ytBtnSetTheater() {
  996. if (!isTheater()) {
  997. const sizeBtn = document.querySelector('ytd-watch-flexy #ytd-player button.ytp-size-button')
  998. if (sizeBtn) sizeBtn.click();
  999. }
  1000. }
  1001.  
  1002. function ytBtnCancelTheater() {
  1003. if (isTheater()) {
  1004. const sizeBtn = document.querySelector('ytd-watch-flexy #ytd-player button.ytp-size-button')
  1005. if (sizeBtn) sizeBtn.click();
  1006. }
  1007. }
  1008.  
  1009.  
  1010. function ytBtnExpandChat() {
  1011. let button = document.querySelector('ytd-live-chat-frame#chat[collapsed] > .ytd-live-chat-frame#show-hide-button')
  1012. if (button) {
  1013. button =
  1014. button.querySelector000('div.yt-spec-touch-feedback-shape') ||
  1015. button.querySelector000('ytd-toggle-button-renderer');
  1016. if (button) button.click();
  1017. }
  1018. }
  1019.  
  1020. function ytBtnCollapseChat() {
  1021. let button = document.querySelector('ytd-live-chat-frame#chat:not([collapsed]) > .ytd-live-chat-frame#show-hide-button')
  1022. if (button) {
  1023. button =
  1024. button.querySelector000('div.yt-spec-touch-feedback-shape') ||
  1025. button.querySelector000('ytd-toggle-button-renderer');
  1026. if (button) button.click();
  1027. }
  1028. }
  1029.  
  1030. function ytBtnEgmPanelCore(arr) {
  1031.  
  1032. if (!arr) return
  1033. if (!('length' in arr)) arr = [arr]
  1034.  
  1035. const ytdFlexyElm = elements.flexy;
  1036. if (!ytdFlexyElm) return;
  1037.  
  1038. let actions = []
  1039.  
  1040. for (const entry of arr) {
  1041.  
  1042. if (!entry) continue;
  1043.  
  1044. let panelId = entry.panelId
  1045.  
  1046. let toHide = entry.toHide
  1047. let toShow = entry.toShow
  1048.  
  1049. if (toHide === true && !toShow) {
  1050.  
  1051. actions.push({
  1052. "changeEngagementPanelVisibilityAction": {
  1053. "targetId": panelId,
  1054. "visibility": "ENGAGEMENT_PANEL_VISIBILITY_HIDDEN"
  1055. }
  1056. })
  1057.  
  1058. } else if (toShow === true && !toHide) {
  1059.  
  1060. actions.push({
  1061. "showEngagementPanelEndpoint": {
  1062. "panelIdentifier": panelId
  1063. }
  1064. })
  1065.  
  1066. }
  1067.  
  1068. if (actions.length > 0) {
  1069. const cnt = insp(ytdFlexyElm);
  1070.  
  1071. cnt.resolveCommand(
  1072. {
  1073. "signalServiceEndpoint": {
  1074. "signal": "CLIENT_SIGNAL",
  1075. "actions": actions
  1076. }
  1077. },
  1078.  
  1079. {},
  1080. false);
  1081. }
  1082. actions = null;
  1083.  
  1084. }
  1085. }
  1086.  
  1087. /*
  1088. function ytBtnCloseEngagementPanel( s) {
  1089. //ePanel.setAttribute('visibility',"ENGAGEMENT_PANEL_VISIBILITY_HIDDEN");
  1090. let panelId = s.getAttribute('target-id')
  1091. scriptletDeferred.debounce(() => {
  1092. document.dispatchEvent(new CustomEvent('tyt-engagement-panel-visibility-change', {
  1093. detail: {
  1094. panelId,
  1095. toHide: true
  1096. }
  1097. }))
  1098. })
  1099. }
  1100. function ytBtnCloseEngagementPanels() {
  1101. if (isEngagementPanelExpanded()) {
  1102. for (const s of document.querySelectorAll(
  1103. `ytd-watch-flexy[flexy][tyt-tab] #panels.ytd-watch-flexy ytd-engagement-panel-section-list-renderer[target-id][visibility]:not([hidden])`
  1104. )) {
  1105. if (s.getAttribute('visibility') == "ENGAGEMENT_PANEL_VISIBILITY_EXPANDED") ytBtnCloseEngagementPanel(s);
  1106. }
  1107. }
  1108. }
  1109. */
  1110.  
  1111.  
  1112. function ytBtnCloseEngagementPanels() {
  1113.  
  1114. const actions = [];
  1115. for (const panelElm of document.querySelectorAll(
  1116. `ytd-watch-flexy[flexy][tyt-tab] #panels.ytd-watch-flexy ytd-engagement-panel-section-list-renderer[target-id][visibility]:not([hidden])`
  1117. )) {
  1118. if (panelElm.getAttribute('visibility') == "ENGAGEMENT_PANEL_VISIBILITY_EXPANDED" && !panelElm.closest('[hidden]')) {
  1119. actions.push({
  1120. panelId: panelElm.getAttribute000('target-id'),
  1121. toHide: true
  1122. });
  1123. }
  1124. }
  1125. ytBtnEgmPanelCore(actions);
  1126. }
  1127.  
  1128. const updateChatLocation498 = function () {
  1129. /*
  1130. updateChatLocation: function() {
  1131. if (this.is !== "ytd-watch-grid" && y("web_watch_theater_chat")) {
  1132. var a = T(this.hostElement).querySelector("#chat-container")
  1133. , b = this.theater && (!this.fullscreen || y("web_watch_fullscreen_panels"));
  1134. this.watchWhileWindowSizeSufficient && this.liveChatPresentAndExpanded && b ? y("web_watch_theater_chat_beside_player") ? (b = T(this.hostElement).querySelector("#panels-full-bleed-container"),
  1135. (a == null ? void 0 : a.parentElement) !== b && b.append(a),
  1136. this.panelsBesidePlayer = !0) : y("web_watch_theater_fixed_chat") && (b = T(this.hostElement).querySelector("#columns"),
  1137. (a == null ? void 0 : a.parentElement) !== b && b.append(a),
  1138. this.fixedPanels = !0) : (y("web_watch_theater_chat_beside_player") ? this.panelsBesidePlayer = !1 : y("web_watch_theater_fixed_chat") && (this.fixedPanels = !1),
  1139. b = T(this.hostElement).querySelector("#playlist"),
  1140. a && b ? Fh(a, b) : Gm(new zk("Missing element when updating chat location",{
  1141. "chatContainer defined": !!a,
  1142. "playlist defined": !!b
  1143. })));
  1144. this.updatePageMediaQueries();
  1145. this.schedulePlayerSizeUpdate_()
  1146. }
  1147. },
  1148. */
  1149.  
  1150. console.log('updateChatLocation498')
  1151. if (this.is !== "ytd-watch-grid") {
  1152. this.updatePageMediaQueries();
  1153. this.schedulePlayerSizeUpdate_()
  1154. }
  1155.  
  1156. }
  1157.  
  1158. const mirrorNodeWS = new WeakMap();
  1159.  
  1160. /*
  1161. const infoFix = () => {
  1162. const infoExpander = elements.infoExpander;
  1163. const ytdFlexyElm = elements.flexy;
  1164. if (!infoExpander || !ytdFlexyElm) return;
  1165. console.log(386, infoExpander, infoExpander.matches('#tab-info > [class]'))
  1166. if (!infoExpander.matches('#tab-info > [class]')) return;
  1167. // 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=>{
  1168. // if(elm.parentNode.closest('div[slot="extra-content"], ytd-metadata-row-container-renderer')) return false;
  1169. // return true;
  1170. // });
  1171. const requireElements = [...document.querySelectorAll('ytd-watch-metadata.ytd-watch-flexy div[slot="extra-content"] > *, ytd-watch-metadata.ytd-watch-flexy #extra-content > *')].filter(elm => {
  1172. return typeof elm.is == 'string'
  1173. }).map(elm => {
  1174. const is = elm.is;
  1175. while (elm instanceof HTMLElement) {
  1176. const q = [...elm.querySelectorAll(is)].filter(e => insp(e).data);
  1177. if (q.length >= 1) return q[0];
  1178. elm = elm.parentNode;
  1179. }
  1180. }).filter(elm => !!elm && typeof elm.is === 'string');
  1181. console.log(requireElements)
  1182. const source = requireElements.map(entry=>({
  1183. data: insp(entry).data,
  1184. tag: insp(entry).is,
  1185. elm: entry
  1186. }))
  1187. if (!document.querySelector('noscript#aythl')) {
  1188. const noscript = document.createElement('noscript')
  1189. noscript.id = 'aythl';
  1190. ytdFlexyElm.insertBefore000(noscript, ytdFlexyElm.firstChild);
  1191. }
  1192. const noscript = document.querySelector('noscript#aythl');
  1193. const clones = new Set();
  1194. for (const {data, tag, elm} of source) {
  1195. // const cloneNode = document.createElement(tag);
  1196. let cloneNode = elm.cloneNode(true);
  1197. // noscript.appendChild(cloneNode);
  1198. // insp(cloneNode).data = null;
  1199. insp(cloneNode).data = data;
  1200. source.clone = cloneNode;
  1201. clones.add(cloneNode);
  1202. }
  1203. // const elms = [...document.querySelectorAll('ytd-watch-metadata.ytd-watch-flexy div[slot="extra-content"]')].filter(elm => {
  1204. // if (elm.parentNode.closest('div[slot="extra-content"], ytd-metadata-row-container-renderer')) return false;
  1205. // return true;
  1206. // });
  1207. // let arr = [];
  1208. // for(const elm of elms){
  1209. // if(elm.hasAttribute('slot')) arr.push(...elm.childNodes);
  1210. // else arr.push(elm);
  1211. // }
  1212. // arr = arr.filter(e=>e && e.nodeType === 1);
  1213. // console.log(386,arr)
  1214. // const clones = arr.map(e=>e.cloneNode(true));
  1215. // for(let node = infoExpander.nextSibling; node instanceof Node; node = node.nextSibling) node.remove();
  1216. // infoExpander.parentNode.assignChildern111(null, infoExpander, [...clones]);
  1217. let removal = [];
  1218. for(let node = infoExpander.nextSibling; node instanceof Node; node = node.nextSibling)removal.push(node);
  1219. for(const node of removal) node.remove();
  1220. for(const node of clones) infoExpander.parentNode.appendChild(node);
  1221. for (const {data, tag, elm, clone} of source) {
  1222. insp(clone).data = null;
  1223. insp(clone).data = data;
  1224. }
  1225. // console.log(infoExpander.parentNode.childNodes)
  1226. }
  1227. */
  1228.  
  1229. const dummyNode = document.createElement('noscript');
  1230.  
  1231. // const __j4838__ = Symbol();
  1232. const __j4836__ = Symbol();
  1233. const __j5744__ = Symbol(); // original element
  1234. const __j5733__ = Symbol(); // __lastChanged__
  1235.  
  1236. const monitorDataChangedByDOMMutation = async function (mutations) {
  1237.  
  1238. const nodeWR = this;
  1239. const node = kRef(nodeWR);
  1240. if (!node) return;
  1241.  
  1242. const cnt = insp(node);
  1243. const __lastChanged__ = cnt[__j5733__];
  1244.  
  1245.  
  1246. const val = cnt.data ? (cnt.data[__j4836__] || 1) : 0;
  1247.  
  1248. if (__lastChanged__ !== val) {
  1249. cnt[__j5733__] = val > 0 ? (cnt.data[__j4836__] = Date.now()) : 0;
  1250.  
  1251. await Promise.resolve(); // required for making sufficient delay for data rendering
  1252. attributeInc(node, 'tyt-data-change-counter'); // next macro task
  1253.  
  1254. }
  1255.  
  1256. }
  1257.  
  1258. const moChangeReflection = function (mutations) {
  1259.  
  1260. const nodeWR = this;
  1261. const node = kRef(nodeWR);
  1262. if (!node) return;
  1263. const originElement = kRef(node[__j5744__] || null) || null;
  1264. if (!originElement) return;
  1265.  
  1266. const cnt = insp(node);
  1267. const oriCnt = insp(originElement);
  1268.  
  1269. if (mutations) {
  1270.  
  1271. let bfDataChangeCounter = false;
  1272. for (const mutation of mutations) {
  1273.  
  1274. if (mutation.attributeName === 'tyt-clone-refresh-count' && mutation.target === originElement) {
  1275. bfDataChangeCounter = true;
  1276. } else if (mutation.attributeName === 'tyt-data-change-counter' && mutation.target === originElement) {
  1277. bfDataChangeCounter = true;
  1278. }
  1279. }
  1280. if (bfDataChangeCounter && oriCnt.data) {
  1281. node.replaceWith(dummyNode);
  1282. cnt.data = Object.assign({}, oriCnt.data);
  1283. dummyNode.replaceWith(node);
  1284. }
  1285.  
  1286. }
  1287. }
  1288.  
  1289. /*
  1290. const moChangeReflection = async function (mutations) {
  1291. const nodeWR = this;
  1292. const node = kRef(nodeWR);
  1293. if (!node) return;
  1294. const originElement = kRef(node[__j5744__] || null) || null;
  1295. if (!originElement) return;
  1296. const cnt = insp(node);
  1297. const oriCnt = insp(originElement);
  1298. if(mutations){
  1299. let bfDataChangeCounter = false;
  1300. for (const mutation of mutations) {
  1301. if (mutation.attributeName === 'tyt-data-change-counter' && mutation.target === originElement) {
  1302. bfDataChangeCounter = true;
  1303. }
  1304. }
  1305. if(bfDataChangeCounter && oriCnt.data){
  1306. node.replaceWith(dummyNode);
  1307. cnt.data = Object.assign({}, oriCnt.data);
  1308. dummyNode.replaceWith(node);
  1309. }
  1310. }
  1311. // console.log(8348, originElement)
  1312. if (cnt.isAttached === false) {
  1313. // do nothing
  1314. // don't call infoFix() as it shall be only called in ytd-expander::attached and yt-navigate-finish
  1315. } else if (oriCnt.isAttached === false && cnt.isAttached === true) {
  1316. if (node.isConnected && node.parentNode instanceof HTMLElement) {
  1317. node.parentNode.removeChild(node);
  1318. } else {
  1319. node.remove();
  1320. }
  1321. if (oriCnt.data !== null) {
  1322. cnt.data = null;
  1323. }
  1324. } else if (oriCnt.isAttached === true && cnt.isAttached === true) {
  1325. if (!oriCnt.data) {
  1326. if(cnt.data){
  1327. cnt.data = null;
  1328. }
  1329. } else if (!cnt.data || oriCnt.data[__j4838__] !== cnt.data[__j4838__]) {
  1330. oriCnt.data[__j4838__] = Date.now();
  1331. await Promise.resolve(); // required for making sufficient delay for data rendering
  1332. attributeInc(originElement, 'tyt-data-change-counter'); // next macro task
  1333. }
  1334. }
  1335. };
  1336. */
  1337.  
  1338. const attributeInc = (elm, prop) => {
  1339. let v = (+elm.getAttribute000(prop) || 0) + 1;
  1340. if (v > 1e9) v = 9;
  1341. elm.setAttribute000(prop, v);
  1342. return v;
  1343. }
  1344.  
  1345.  
  1346.  
  1347. const infoFix = (lockId) => {
  1348. if (lockGet['infoFixLock'] !== lockId) return;
  1349. console.log('((infoFix))')
  1350. const infoExpander = elements.infoExpander;
  1351. const ytdFlexyElm = elements.flexy;
  1352. if (!infoExpander || !ytdFlexyElm) return;
  1353. // console.log(386, infoExpander, infoExpander.matches('#tab-info > [class]'))
  1354. if (!infoExpander.matches('#tab-info > [class]')) return;
  1355. // 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=>{
  1356. // if(elm.parentNode.closest('div[slot="extra-content"], ytd-metadata-row-container-renderer')) return false;
  1357. // return true;
  1358. // });
  1359.  
  1360.  
  1361.  
  1362. const requireElements = [...document.querySelectorAll('ytd-watch-metadata.ytd-watch-flexy div[slot="extra-content"] > *, ytd-watch-metadata.ytd-watch-flexy #extra-content > *')].filter(elm => {
  1363. return typeof elm.is == 'string'
  1364. }).map(elm => {
  1365. const is = elm.is;
  1366. while (elm instanceof HTMLElement) {
  1367. const q = [...elm.querySelectorAll(is)].filter(e => insp(e).data);
  1368. if (q.length >= 1) return q[0];
  1369. elm = elm.parentNode;
  1370. }
  1371. }).filter(elm => !!elm && typeof elm.is === 'string');
  1372. // console.log(9162, requireElements)
  1373.  
  1374. const source = requireElements.map(entry => ({
  1375. data: insp(entry).data,
  1376. tag: insp(entry).is,
  1377. elm: entry
  1378. }));
  1379.  
  1380. if (!document.querySelector('noscript#aythl')) {
  1381. const noscript = document.createElement('noscript')
  1382. noscript.id = 'aythl';
  1383. ytdFlexyElm.insertBefore000(noscript, ytdFlexyElm.firstChild);
  1384.  
  1385. }
  1386. const noscript = document.querySelector('noscript#aythl');
  1387.  
  1388.  
  1389. let requiredUpdate = false;
  1390. const mirrorElmSet = new Set();
  1391. const targetParent = infoExpander.parentNode;
  1392. for (const { data, tag: tag, elm: s } of source) {
  1393.  
  1394. let mirrorNode = mirrorNodeWS.get(s)
  1395. mirrorNode = mirrorNode ? kRef(mirrorNode) : mirrorNode;
  1396. if (!mirrorNode) {
  1397. const cnt = insp(s);
  1398. const cProto = cnt.constructor.prototype;
  1399.  
  1400. const element = document.createElement(tag);
  1401. noscript.appendChild(element); // appendChild to trigger .attached()
  1402. mirrorNode = element
  1403. mirrorNode[__j5744__] = mWeakRef(s);
  1404.  
  1405. const nodeWR = mWeakRef(mirrorNode);
  1406. // if(!(insp(s)._dataChanged438)){
  1407. // insp(s)._dataChanged438 = async function(){
  1408.  
  1409. // await Promise.resolve(); // required for making sufficient delay for data rendering
  1410. // attributeInc(originElement, 'tyt-data-change-counter'); // next macro task
  1411. // moChangeReflection.call(nodeWR);
  1412. // }
  1413. // }
  1414.  
  1415.  
  1416.  
  1417.  
  1418. new MutationObserver(moChangeReflection.bind(nodeWR)).observe(s, { attributes: true, attributeFilter: ['tyt-clone-refresh-count', 'tyt-data-change-counter'] });
  1419.  
  1420.  
  1421. s.jy8432 = 1;
  1422. if (!(cProto instanceof Node) && !cProto._dataChanged496 && typeof cProto._createPropertyObserver === 'function') {
  1423.  
  1424.  
  1425. cProto._dataChanged496 = function () {
  1426. const cnt = this;
  1427. const node = cnt.hostElement || cnt;
  1428. if (node.jy8432) {
  1429.  
  1430. console.log('hello _dataChanged496', this.is);
  1431. // await Promise.resolve(); // required for making sufficient delay for data rendering
  1432. attributeInc(node, 'tyt-data-change-counter'); // next macro task
  1433. }
  1434.  
  1435.  
  1436. }
  1437.  
  1438. cProto._createPropertyObserver('data', '_dataChanged496', undefined)
  1439.  
  1440. } else if (!(cProto instanceof Node) && !cProto._dataChanged496 && cProto.useSignals === true && insp(s).signalProxy) {
  1441.  
  1442. const dataSignal = cnt?.signalProxy?.signalCache?.data;
  1443. if (dataSignal && typeof dataSignal.setWithPath === 'function' && !dataSignal.setWithPath573 && !dataSignal.controller573) {
  1444. dataSignal.controller573 = mWeakRef(cnt);
  1445. dataSignal.setWithPath573 = dataSignal.setWithPath;
  1446. dataSignal.setWithPath = function () {
  1447. const cnt = (kRef(this.controller573 || null) || null);
  1448. cnt && typeof cnt._dataChanged496k === 'function' && Promise.resolve(cnt).then(cnt._dataChanged496k).catch(console.warn);
  1449. return this.setWithPath573(...arguments)
  1450. }
  1451. cProto._dataChanged496 = function () {
  1452. const cnt = this;
  1453. const node = cnt.hostElement || cnt;
  1454. if (node.jy8432) {
  1455. console.log('hello _dataChanged496', this.is);
  1456. // await Promise.resolve(); // required for making sufficient delay for data rendering
  1457. attributeInc(node, 'tyt-data-change-counter'); // next macro task
  1458. }
  1459. }
  1460. cProto._dataChanged496k = (cnt) => cnt._dataChanged496();
  1461.  
  1462. }
  1463.  
  1464. }
  1465.  
  1466.  
  1467. if (!cProto._dataChanged496) {
  1468.  
  1469.  
  1470. new MutationObserver(monitorDataChangedByDOMMutation.bind(mirrorNode[__j5744__])).observe(s, { attributes: true, childList: true, subtree: true });
  1471.  
  1472. }
  1473.  
  1474.  
  1475. // new MutationObserver(moChangeReflection.bind(nodeWR)).observe(s, {attributes: true, childList: true, subtree: true});
  1476.  
  1477. mirrorNodeWS.set(s, nodeWR);
  1478. requiredUpdate = true;
  1479. } else {
  1480.  
  1481. if (mirrorNode.parentNode !== targetParent) {
  1482. requiredUpdate = true;
  1483. }
  1484. }
  1485. if (!requiredUpdate) {
  1486. const cloneNodeCnt = insp(mirrorNode);
  1487. if (cloneNodeCnt.data !== data) {
  1488. // if(mirrorNode.parentNode !== noscript){
  1489. // noscript.appendChild(mirrorNode);
  1490. // }
  1491. // mirrorNode.replaceWith(dummyNode);
  1492. // cloneNodeCnt.data = data;
  1493. // dummyNode.replaceWith(mirrorNode);
  1494. requiredUpdate = true;
  1495. }
  1496. }
  1497.  
  1498.  
  1499. mirrorElmSet.add(mirrorNode);
  1500. source.mirrored = mirrorNode;
  1501.  
  1502. }
  1503.  
  1504. const mirroElmArr = [...mirrorElmSet];
  1505. mirrorElmSet.clear();
  1506.  
  1507.  
  1508. if (!requiredUpdate) {
  1509. // DOM Tree Check
  1510. let e = 0;
  1511. for (let n = targetParent.firstChild; n instanceof Node; n = n.nextSibling) {
  1512. let target = e === 0 ? infoExpander : mirroElmArr[e - 1];
  1513. e++;
  1514. if (n !== target) {
  1515. // target can be undefined if index overflow
  1516. requiredUpdate = true;
  1517. break;
  1518. }
  1519. }
  1520. if (!requiredUpdate && e !== mirroElmArr.length + 1) requiredUpdate = true;
  1521. }
  1522.  
  1523. if (requiredUpdate) {
  1524. targetParent.assignChildern111(null, infoExpander, mirroElmArr);
  1525. for (const mirrorElm of mirroElmArr) {
  1526. // trigger data assignment and record refresh count by manual update
  1527. const j = attributeInc(mirrorElm, 'tyt-clone-refresh-count');
  1528. const oriElm = kRef(mirrorElm[__j5744__] || null) || null;
  1529. if (oriElm) {
  1530. oriElm.setAttribute111('tyt-clone-refresh-count', j)
  1531. }
  1532. }
  1533. }
  1534.  
  1535. mirroElmArr.length = 0;
  1536. source.length = 0;
  1537.  
  1538. }
  1539.  
  1540. const layoutFix = (lockId) => {
  1541. if (lockGet['layoutFixLock'] !== lockId) return;
  1542. console.log('((layoutFix))')
  1543.  
  1544. const secondaryWrapper = document.querySelector('#secondary-inner.style-scope.ytd-watch-flexy > secondary-wrapper');
  1545. // console.log(3838, !!chatContainer, !!(secondaryWrapper && secondaryInner), secondaryInner?.firstChild, secondaryInner?.lastChild , secondaryWrapper?.parentNode === secondaryInner)
  1546. if (secondaryWrapper) {
  1547. const secondaryInner = secondaryWrapper.parentNode;
  1548.  
  1549. const chatContainer = document.querySelector('#columns.style-scope.ytd-watch-flexy [tyt-chat-container]');
  1550. if (secondaryInner.firstChild !== secondaryInner.lastChild || (chatContainer && !chatContainer.closest('secondary-wrapper'))) {
  1551. console.log(38381)
  1552. let w = [];
  1553. let w2 = [];
  1554. for (let node = secondaryInner.firstChild; node instanceof Node; node = node.nextSibling) {
  1555. if (node === chatContainer && chatContainer) {
  1556.  
  1557. } else if (node === secondaryWrapper) {
  1558.  
  1559. for (let node2 = secondaryWrapper.firstChild; node2 instanceof Node; node2 = node2.nextSibling) {
  1560. if (node2 === chatContainer && chatContainer) {
  1561. } else {
  1562. if (node2.id === 'right-tabs' && chatContainer) {
  1563. w2.push(chatContainer);
  1564. }
  1565. w2.push(node2);
  1566. }
  1567. }
  1568. } else {
  1569. w.push(node);
  1570. }
  1571. }
  1572. secondaryWrapper.replaceChildren000(...w, ...w2);
  1573. // if(chatCnt && typeof chatCnt.urlChanged === 'function'){
  1574. // setTimeout(()=>chatCnt.urlChanged, 100);
  1575. // }
  1576. }
  1577. }
  1578.  
  1579. }
  1580.  
  1581. let lastPanel = '';
  1582. let lastTab = '';
  1583. // let fixInitialTabState = 0;
  1584.  
  1585. const aoEgmPanels = new MutationObserver(() => {
  1586. Promise.resolve(lockSet['updateEgmPanelsLock']).then(updateEgmPanels).catch(console.warn);
  1587. });
  1588.  
  1589. const removeKeepCommentsScroller = async (lockId) => {
  1590. if (lockGet['removeKeepCommentsScrollerLock'] !== lockId) return;
  1591. await Promise.resolve();
  1592. if (lockGet['removeKeepCommentsScrollerLock'] !== lockId) return;
  1593. const ytdFlexyFlm = elements.flexy;
  1594. if (ytdFlexyFlm) {
  1595. ytdFlexyFlm.removeAttribute000('keep-comments-scroller');
  1596. }
  1597. }
  1598.  
  1599. const updateEgmPanels = async (lockId) => {
  1600. if (lockId !== lockGet['updateEgmPanelsLock']) return;
  1601. await navigateFinishedPromise.then().catch(console.warn);
  1602. if (lockId !== lockGet['updateEgmPanelsLock']) return;
  1603. const ytdFlexyElm = elements.flexy;
  1604. if (!ytdFlexyElm) return;
  1605. let newVisiblePanels = [];
  1606. let newHiddenPanels = [];
  1607. let allVisiblePanels = [];
  1608. for (const panelElm of document.querySelectorAll('[tyt-egm-panel][target-id][visibility]')) {
  1609. const visibility = panelElm.getAttribute000('visibility');
  1610.  
  1611. if (visibility === 'ENGAGEMENT_PANEL_VISIBILITY_HIDDEN' || panelElm.closest('[hidden]')) {
  1612. if (panelElm.hasAttribute000('tyt-visible-at')) {
  1613. panelElm.removeAttribute000('tyt-visible-at');
  1614. newHiddenPanels.push(panelElm);
  1615. }
  1616.  
  1617. } else if (visibility === 'ENGAGEMENT_PANEL_VISIBILITY_EXPANDED' && !panelElm.closest('[hidden]')) {
  1618. let visibleAt = panelElm.getAttribute000('tyt-visible-at');
  1619. if (!visibleAt) {
  1620. panelElm.setAttribute111('tyt-visible-at', Date.now());
  1621. newVisiblePanels.push(panelElm);
  1622. }
  1623. allVisiblePanels.push(panelElm);
  1624. }
  1625. }
  1626. if (newVisiblePanels.length >= 1 && allVisiblePanels.length >= 2) {
  1627. const targetVisible = newVisiblePanels[newVisiblePanels.length - 1];
  1628.  
  1629. const actions = [];
  1630. for (const panelElm of allVisiblePanels) {
  1631. if (panelElm === targetVisible) continue;
  1632. actions.push({
  1633. panelId: panelElm.getAttribute000('target-id'),
  1634. toHide: true
  1635. });
  1636. }
  1637.  
  1638. if (actions.length >= 1) {
  1639. ytBtnEgmPanelCore(actions);
  1640. }
  1641.  
  1642. }
  1643. if (allVisiblePanels.length >= 1) {
  1644. ytdFlexyElm.setAttribute111('tyt-egm-panel_', '');
  1645. } else {
  1646. ytdFlexyElm.removeAttribute000('tyt-egm-panel_');
  1647. }
  1648. newVisiblePanels.length = 0;
  1649. newVisiblePanels = null;
  1650. newHiddenPanels.length = 0;
  1651. newHiddenPanels = null;
  1652. allVisiblePanels.length = 0;
  1653. allVisiblePanels = null;
  1654. }
  1655.  
  1656. const checkElementExist = (css, exclude) => {
  1657. for (const p of document.querySelectorAll(css)) {
  1658. if (!p.closest(exclude)) return true;
  1659. }
  1660. return false;
  1661. }
  1662.  
  1663. const { handleNavigateFactory } = (() => {
  1664.  
  1665.  
  1666. let isLoadStartListened = false;
  1667.  
  1668. function findLcComment(lc) {
  1669. if (arguments.length === 1) {
  1670.  
  1671. let element = document.querySelector(`#tab-comments ytd-comments ytd-comment-renderer #header-author a[href*="lc=${lc}"]`);
  1672. if (element) {
  1673. let commentRendererElm = closestFromAnchor.call(element, 'ytd-comment-renderer');
  1674. if (commentRendererElm && lc) {
  1675. return {
  1676. lc,
  1677. commentRendererElm
  1678. }
  1679. }
  1680. }
  1681. } else if (arguments.length === 0) {
  1682.  
  1683. let element = document.querySelector(`#tab-comments ytd-comments ytd-comment-renderer > #linked-comment-badge span:not(:empty)`);
  1684. if (element) {
  1685. let commentRendererElm = closestFromAnchor.call(element, 'ytd-comment-renderer');
  1686. if (commentRendererElm) {
  1687.  
  1688. let header = _querySelector.call(commentRendererElm, '#header-author');
  1689. if (header) {
  1690.  
  1691. let anchor = _querySelector.call(header, 'a[href*="lc="]');
  1692. if (anchor) {
  1693. let href = (anchor.getAttribute('href') || '');
  1694. let m = /[&?]lc=([\w_.-]+)/.exec(href); // dot = sub-comment
  1695. if (m) {
  1696. lc = m[1];
  1697. }
  1698. }
  1699. }
  1700.  
  1701. }
  1702. if (commentRendererElm && lc) {
  1703. return {
  1704. lc,
  1705. commentRendererElm
  1706. }
  1707. }
  1708. }
  1709. }
  1710.  
  1711. return null;
  1712.  
  1713. }
  1714.  
  1715.  
  1716. function lcSwapFuncA(targetLcId, currentLcId) {
  1717.  
  1718.  
  1719. let done = 0;
  1720. try {
  1721. // console.log(currentLcId, targetLcId)
  1722.  
  1723. let r1 = findLcComment(currentLcId).commentRendererElm;
  1724. let r2 = findLcComment(targetLcId).commentRendererElm;
  1725.  
  1726.  
  1727. if (typeof insp(r1).data.linkedCommentBadge === 'object' && typeof insp(r2).data.linkedCommentBadge === 'undefined') {
  1728.  
  1729. let p = Object.assign({}, insp(r1).data.linkedCommentBadge)
  1730.  
  1731. if (((p || 0).metadataBadgeRenderer || 0).trackingParams) {
  1732. delete p.metadataBadgeRenderer.trackingParams;
  1733. }
  1734.  
  1735. const v1 = findContentsRenderer(r1)
  1736. const v2 = findContentsRenderer(r2)
  1737.  
  1738.  
  1739. if (v1.parent === v2.parent && (v2.parent.nodeName === 'YTD-COMMENTS' || v2.parent.nodeName === 'YTD-ITEM-SECTION-RENDERER')) {
  1740.  
  1741. } else {
  1742. // currently not supported
  1743. return false;
  1744. }
  1745.  
  1746.  
  1747.  
  1748. if (v2.index >= 0) {
  1749. if (v2.parent.nodeName === 'YTD-COMMENT-REPLIES-RENDERER') {
  1750.  
  1751.  
  1752. if (lcSwapFuncB(targetLcId, currentLcId, p)) {
  1753. done = 1;
  1754. }
  1755.  
  1756. done = 1;
  1757. } else {
  1758. const v2pCnt = insp(v2.parent);
  1759. const v2Conents = (v2pCnt.data || 0).contents || 0;
  1760. if (!v2Conents) console.warn('v2Conents is not found');
  1761.  
  1762. v2pCnt.data = Object.assign({}, v2pCnt.data, { contents: [].concat([v2Conents[v2.index]], v2Conents.slice(0, v2.index), v2Conents.slice(v2.index + 1)) });
  1763.  
  1764. if (lcSwapFuncB(targetLcId, currentLcId, p)) {
  1765. done = 1;
  1766. }
  1767. }
  1768.  
  1769.  
  1770. }
  1771.  
  1772.  
  1773.  
  1774. }
  1775.  
  1776.  
  1777.  
  1778. } catch (e) {
  1779. console.warn(e)
  1780. }
  1781. return done === 1;
  1782. }
  1783.  
  1784.  
  1785. function lcSwapFuncB(targetLcId, currentLcId, _p) {
  1786.  
  1787. let done = 0;
  1788. try {
  1789.  
  1790. let r1 = findLcComment(currentLcId).commentRendererElm;
  1791. let r1cnt = insp(r1);
  1792. let r2 = findLcComment(targetLcId).commentRendererElm;
  1793. let r2cnt = insp(r2);
  1794.  
  1795. const r1d = r1cnt.data;
  1796. let p = Object.assign({}, _p)
  1797. r1d.linkedCommentBadge = null;
  1798. delete r1d.linkedCommentBadge;
  1799.  
  1800. let q = Object.assign({}, r1d);
  1801. q.linkedCommentBadge = null;
  1802. delete q.linkedCommentBadge;
  1803.  
  1804. r1cnt.data = Object.assign({}, q);
  1805. r2cnt.data = Object.assign({}, r2cnt.data, { linkedCommentBadge: p });
  1806.  
  1807. done = 1;
  1808.  
  1809. } catch (e) {
  1810. console.warn(e)
  1811. }
  1812. return done === 1;
  1813. }
  1814.  
  1815. const loadStartFx = async (evt) => {
  1816.  
  1817. let media = (evt || 0).target || 0;
  1818. if (media.nodeName === 'VIDEO' || media.nodeName === 'AUDIO') { }
  1819. else return;
  1820.  
  1821. const newMedia = media;
  1822.  
  1823. const media1 = getMediaElement(0); // document.querySelector('#movie_player video[src]');
  1824. const media2 = getMediaElements(2); // document.querySelectorAll('ytd-browse[role="main"] video[src]');
  1825.  
  1826. if (media1 !== null && media2.length > 0) {
  1827. if (newMedia !== media1 && media1.paused === false) {
  1828. if (isVideoPlaying(media1)) {
  1829. Promise.resolve(newMedia).then(video => video.paused === false && video.pause()).catch(console.warn);
  1830. }
  1831. } else if (newMedia === media1) {
  1832. for (const s of media2) {
  1833. if (s.paused === false) {
  1834. Promise.resolve(s).then(s => s.paused === false && s.pause()).catch(console.warn);
  1835. break;
  1836. }
  1837. }
  1838. } else {
  1839. Promise.resolve(media1).then(video1 => video1.paused === false && video1.pause()).catch(console.warn);
  1840. }
  1841. }
  1842.  
  1843. }
  1844.  
  1845. const getBrowsableEndPoint = (req) => {
  1846.  
  1847. let valid = false;
  1848. let endpoint = req ? req.command : null;
  1849. if (endpoint && (endpoint.commandMetadata || 0).webCommandMetadata && endpoint.watchEndpoint) {
  1850. let videoId = endpoint.watchEndpoint.videoId;
  1851. let url = endpoint.commandMetadata.webCommandMetadata.url;
  1852.  
  1853. if (typeof videoId === 'string' && typeof url === 'string' && url.indexOf('lc=') > 0) {
  1854.  
  1855. let m = /^\/watch\?v=([\w_-]+)&lc=([\w_.-]+)$/.exec(url); // dot = sub-comment
  1856. if (m && m[1] === videoId) {
  1857.  
  1858.  
  1859. /*
  1860. {
  1861. "style": "BADGE_STYLE_TYPE_SIMPLE",
  1862. "label": "注目のコメント",
  1863. "trackingParams": "XXXXXX"
  1864. }
  1865. */
  1866.  
  1867. let targetLc = findLcComment(m[2])
  1868. let currentLc = targetLc ? findLcComment() : null;
  1869.  
  1870. if (targetLc && currentLc) {
  1871.  
  1872.  
  1873. let done = targetLc.lc === currentLc.lc ? 1 : lcSwapFuncA(targetLc.lc, currentLc.lc) ? 1 : 0
  1874.  
  1875. if (done === 1) {
  1876.  
  1877. common.xReplaceState(history.state, url);
  1878. return;
  1879. }
  1880. }
  1881. }
  1882.  
  1883. }
  1884.  
  1885. }
  1886.  
  1887. /*
  1888. {
  1889. "type": 0,
  1890. "command": endpoint,
  1891. "form": {
  1892. "tempData": {},
  1893. "reload": false
  1894. }
  1895. }
  1896. */
  1897.  
  1898.  
  1899. if (endpoint && (endpoint.browseEndpoint || endpoint.searchEndpoint) && !endpoint.urlEndpoint && !endpoint.watchEndpoint) {
  1900.  
  1901. if (endpoint.browseEndpoint && endpoint.browseEndpoint.browseId === "FEwhat_to_watch") {
  1902. // valid = false;
  1903. const playerMedia = common.getMediaElement(1);
  1904. if (playerMedia && playerMedia.paused === false) valid = true; // home page
  1905. } else if (endpoint.commandMetadata && endpoint.commandMetadata.webCommandMetadata) {
  1906.  
  1907. let meta = endpoint.commandMetadata.webCommandMetadata
  1908. if (meta && /*meta.apiUrl &&*/ meta.url && meta.webPageType) {
  1909. valid = true;
  1910. }
  1911.  
  1912. }
  1913. }
  1914.  
  1915. if (!valid) endpoint = null;
  1916.  
  1917. return endpoint;
  1918. }
  1919.  
  1920. const conditionFulfillment = (req) => {
  1921. const endpoint = req ? req.command : null;
  1922. if (!endpoint) return;
  1923.  
  1924. if (endpoint && (endpoint.commandMetadata || 0).webCommandMetadata && endpoint.watchEndpoint) {
  1925. } else if (endpoint && (endpoint.browseEndpoint || endpoint.searchEndpoint) && !endpoint.urlEndpoint && !endpoint.watchEndpoint) {
  1926. } else {
  1927. return false;
  1928. }
  1929.  
  1930.  
  1931. if (!document.querySelector('ytd-page-manager#page-manager > ytd-browse[page-subtype]')) return false;
  1932.  
  1933.  
  1934. /*
  1935. // user would like to switch page immediately without playing the video;
  1936. // attribute appear after playing video for more than 2s
  1937. if (!document.head.dataset.viTime) return false;
  1938. else {
  1939. let currentVideo = common.getMediaElement(0);
  1940. if (currentVideo && currentVideo.readyState > currentVideo.HAVE_CURRENT_DATA && currentVideo.currentTime > 2.2 && currentVideo.duration - 2.2 < currentVideo.currentTime) {
  1941. // disable miniview browsing if the media is near to the end
  1942. return false;
  1943. }
  1944. }
  1945. */
  1946.  
  1947.  
  1948. if (pageType !== "watch") return false;
  1949.  
  1950.  
  1951. if (!checkElementExist('ytd-watch-flexy #player button.ytp-miniplayer-button.ytp-button', '[hidden]')) {
  1952. return false;
  1953. }
  1954.  
  1955. return true;
  1956. }
  1957.  
  1958. const handleNavigateFactory = (handleNavigate) => {
  1959.  
  1960. return function (req) {
  1961.  
  1962. const $this = this;
  1963. const $arguments = arguments;
  1964.  
  1965. let endpoint = null;
  1966.  
  1967.  
  1968. if (conditionFulfillment(req)) {
  1969.  
  1970.  
  1971. endpoint = getBrowsableEndPoint(req);
  1972.  
  1973. }
  1974.  
  1975.  
  1976. if (!endpoint || !document.querySelector('ytd-page-manager#page-manager > ytd-browse[page-subtype]')) return handleNavigate.apply($this, $arguments);
  1977.  
  1978. // console.log('tabview-script-handleNavigate')
  1979.  
  1980. const ytdAppElm = document.querySelector('ytd-app');
  1981. const ytdAppCnt = insp(ytdAppElm);
  1982.  
  1983. let object = null;
  1984. try {
  1985. object = ytdAppCnt.data.response.currentVideoEndpoint.watchEndpoint || null;
  1986. } catch (e) {
  1987. object = null;
  1988. }
  1989.  
  1990. if (typeof object !== 'object') object = null;
  1991.  
  1992. const once = { once: true }; // browsers supporting async function can also use once option.
  1993.  
  1994. if (object !== null && !('playlistId' in object)) {
  1995.  
  1996. let wObject = mWeakRef(object)
  1997.  
  1998. const N = 3;
  1999.  
  2000. let count = 0;
  2001.  
  2002. /*
  2003. rcb(b) => a = playlistId = undefinded
  2004. var scb = function(a, b, c, d) {
  2005. 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]),
  2006. qs(a.miniplayerEl, "yt-deactivate-miniplayer-action")) : "watch" === Xu(b) && rcb(b) && (qt.getInstance().playlistWatchPageActivation = !0,
  2007. a.activateMiniplayer(b)) : c ? ("watch" !== Xu(b) && os(a.miniplayerEl, "yt-cache-miniplayer-page-action", [b]),
  2008. qs(a.miniplayerEl, "yt-deactivate-miniplayer-action")) : d ? qs(a.miniplayerEl, "yt-pause-miniplayer-action") : "watch" === Xu(b) && rcb(b) && (qt.getInstance().playlistWatchPageActivation = !0,
  2009. a.activateMiniplayer(b)))
  2010. };
  2011. */
  2012.  
  2013. Object.defineProperty((kRef(wObject) || {}), 'playlistId', {
  2014. get() {
  2015. count++;
  2016. if (count === N) {
  2017. delete this.playlistId;
  2018. }
  2019. return '*';
  2020. },
  2021. set(value) {
  2022. delete this.playlistId; // remove property definition
  2023. this.playlistId = value; // assign as normal property
  2024. },
  2025. enumerable: false,
  2026. configurable: true
  2027. });
  2028.  
  2029. let playlistClearout = null;
  2030.  
  2031. let timeoutid = 0;
  2032. Promise.race([
  2033. new Promise(r => {
  2034. timeoutid = setTimeout(r, 4000)
  2035. }),
  2036. new Promise(r => {
  2037. playlistClearout = () => {
  2038. if (timeoutid > 0) {
  2039. clearTimeout(timeoutid);
  2040. timeoutid = 0;
  2041. }
  2042. r();
  2043. }
  2044. document.addEventListener('yt-page-type-changed', playlistClearout, once);
  2045. })
  2046. ]).then(() => {
  2047.  
  2048. if (timeoutid !== 0) {
  2049. playlistClearout && document.removeEventListener('yt-page-type-changed', playlistClearout, once);
  2050. timeoutid = 0;
  2051. }
  2052. playlistClearout = null;
  2053. count = N - 1;
  2054. let object = kRef(wObject)
  2055. wObject = null;
  2056. return object ? object.playlistId : null;
  2057. }).catch(console.warn);
  2058.  
  2059. }
  2060.  
  2061. if (!isLoadStartListened) {
  2062. isLoadStartListened = true;
  2063. document.addEventListener('loadstart', loadStartFx, true)
  2064. }
  2065.  
  2066. handleNavigate.apply($this, $arguments);
  2067.  
  2068. }
  2069.  
  2070. };
  2071.  
  2072. return { handleNavigateFactory };
  2073.  
  2074.  
  2075. })();
  2076.  
  2077. const common = (() => {
  2078.  
  2079.  
  2080. let mediaModeLock = 0;
  2081. const _getMediaElement = (i) => {
  2082. if (mediaModeLock === 0) {
  2083. 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]');
  2084. if (e) {
  2085. if (e.nodeName === 'VIDEO') mediaModeLock = 1;
  2086. else if (e.nodeName === 'AUDIO') mediaModeLock = 2;
  2087. }
  2088. }
  2089. if (!mediaModeLock) return null;
  2090. if (mediaModeLock === 1) {
  2091. switch (i) {
  2092. case 1:
  2093. return ('ytd-player#ytd-player video[src]');
  2094. case 2:
  2095. return ('ytd-browse[role="main"] video[src]');
  2096. case 0:
  2097. default:
  2098. return ('#movie_player video[src]');
  2099. }
  2100. } else if (mediaModeLock === 2) {
  2101. switch (i) {
  2102. case 1:
  2103. return ('ytd-player#ytd-player audio.video-stream.html5-main-video[src]');
  2104. case 2:
  2105. return ('ytd-browse[role="main"] audio.video-stream.html5-main-video[src]');
  2106. case 0:
  2107. default:
  2108. return ('#movie_player audio.video-stream.html5-main-video[src]');
  2109. }
  2110. }
  2111. return null;
  2112. }
  2113.  
  2114. return {
  2115.  
  2116.  
  2117. xReplaceState(s, u) {
  2118. try {
  2119. history.replaceState(s, '', u);
  2120. } catch (e) {
  2121. // in case error occurs if replaceState is replaced by any external script / extension
  2122. }
  2123. if (s.endpoint) {
  2124. try {
  2125. const ytdAppElm = document.querySelector('ytd-app');
  2126. const ytdAppCnt = insp(ytdAppElm);
  2127. ytdAppCnt.replaceState(s.endpoint, '', u)
  2128. } catch (e) {
  2129. }
  2130. }
  2131. },
  2132. getMediaElement(i) {
  2133. let s = _getMediaElement(i) || '';
  2134. if (s) return document.querySelector(s);
  2135. return null;
  2136. },
  2137. getMediaElements(i) {
  2138. let s = _getMediaElement(i) || '';
  2139. if (s) return document.querySelectorAll(s);
  2140. return [];
  2141. }
  2142. };
  2143. })();
  2144.  
  2145.  
  2146. const plugin = {
  2147. 'minibrowser': {
  2148. enabled: false,
  2149. enable() {
  2150.  
  2151. if (plugin.minibrowser.enabled) return;
  2152.  
  2153. const isPassiveArgSupport = (typeof IntersectionObserver === 'function');
  2154. // https://caniuse.com/?search=observer
  2155. // https://caniuse.com/?search=addEventListener%20passive
  2156.  
  2157. if (!isPassiveArgSupport) return;
  2158.  
  2159. plugin.minibrowser.enabled = true;
  2160.  
  2161. const ytdAppElm = document.querySelector('ytd-app');
  2162. const ytdAppCnt = insp(ytdAppElm);
  2163.  
  2164.  
  2165. if (!ytdAppCnt) return;
  2166.  
  2167. const cProto = ytdAppCnt.constructor.prototype;
  2168.  
  2169. if (!cProto.handleNavigate) return;
  2170.  
  2171. if (cProto.handleNavigate.__ma355__) return;
  2172.  
  2173. cProto.handleNavigate = handleNavigateFactory(cProto.handleNavigate);
  2174.  
  2175. cProto.handleNavigate.__ma355__ = 1;
  2176. }
  2177. }
  2178. }
  2179.  
  2180. let shouldFixInfo = false;
  2181.  
  2182. const eventMap = {
  2183.  
  2184. 'ceHack': () => {
  2185. mLoaded.flag |= 2;
  2186. document.documentElement.setAttribute111('tabview-loaded', mLoaded.makeString());
  2187.  
  2188. retrieveCE('ytd-watch-flexy').then(eventMap['ytd-watch-flexy::defined']).catch(console.warn);
  2189. retrieveCE('ytd-expander').then(eventMap['ytd-expander::defined']).catch(console.warn);
  2190. retrieveCE('ytd-watch-next-secondary-results-renderer').then(eventMap['ytd-watch-next-secondary-results-renderer::defined']).catch(console.warn);
  2191. retrieveCE('ytd-comments-header-renderer').then(eventMap['ytd-comments-header-renderer::defined']).catch(console.warn);
  2192. retrieveCE('ytd-live-chat-frame').then(eventMap['ytd-live-chat-frame::defined']).catch(console.warn);
  2193. retrieveCE('ytd-comments').then(eventMap['ytd-comments::defined']).catch(console.warn);
  2194. retrieveCE('ytd-engagement-panel-section-list-renderer').then(eventMap['ytd-engagement-panel-section-list-renderer:defined']).catch(console.warn);
  2195.  
  2196. },
  2197.  
  2198. 'fixForTabDisplay': (isResize) => {
  2199.  
  2200. bFixForResizedTabLater = false;
  2201. for (const element of document.querySelectorAll('[io-intersected]')) {
  2202. const cnt = insp(element);
  2203. if (element instanceof HTMLElement && typeof cnt.calculateCanCollapse === 'function') {
  2204. try {
  2205. cnt.calculateCanCollapse(true);
  2206. } catch (e) { }
  2207. }
  2208. }
  2209.  
  2210. if (!isResize) {
  2211. for (const element of document.querySelectorAll('ytd-video-description-infocards-section-renderer, yt-chip-cloud-renderer, ytd-horizontal-card-list-renderer')) {
  2212. const cnt = insp(element);
  2213. if (element instanceof HTMLElement && typeof cnt.notifyResize === 'function') {
  2214. try {
  2215. cnt.notifyResize();
  2216. } catch (e) { }
  2217. }
  2218. }
  2219. }
  2220.  
  2221. },
  2222.  
  2223. 'ytd-watch-flexy::defined': (cProto) => {
  2224.  
  2225. if (!cProto.updateChatLocation498 && typeof cProto.updateChatLocation === 'function' && cProto.updateChatLocation.length === 0) {
  2226. cProto.updateChatLocation498 = cProto.updateChatLocation;
  2227. cProto.updateChatLocation = updateChatLocation498;
  2228. }
  2229.  
  2230. },
  2231.  
  2232.  
  2233.  
  2234. 'ytd-watch-next-secondary-results-renderer::defined': (cProto) => {
  2235. // if (!cProto.attached498 && typeof cProto.attached === 'function') {
  2236. // cProto.attached498 = cProto.attached;
  2237. // cProto.attached = function () {
  2238. // Promise.resolve(this.hostElement).then(eventMap['ytd-watch-next-secondary-results-renderer::attached']).catch(console.warn);
  2239. // return this.attached498();
  2240. // }
  2241. // }
  2242. // if (!cProto.detached498 && typeof cProto.detached === 'function') {
  2243. // cProto.detached498 = cProto.detached;
  2244. // cProto.detached = function () {
  2245. // Promise.resolve(this.hostElement).then(eventMap['ytd-watch-next-secondary-results-renderer::detached']).catch(console.warn);
  2246. // return this.detached498();
  2247. // }
  2248. // }
  2249. },
  2250.  
  2251. 'ytd-watch-next-secondary-results-renderer::connectedCallback': (hostElement) => {
  2252. if (!(hostElement instanceof HTMLElement) || !(hostElement.classList.length > 0) || hostElement.closest('noscript')) return;
  2253. if (hostElement.isConnected !== true) return;
  2254. if (hostElement.__connectedFlg__ !== 4) return;
  2255. hostElement.__connectedFlg__ = 5;
  2256. 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')) {
  2257. elements.related = hostElement.closest('#related');
  2258. hostElement.setAttribute111('tyt-videos-list', '');
  2259. }
  2260. console.log('ytd-watch-next-secondary-results-renderer::attached', hostElement);
  2261. },
  2262.  
  2263. 'ytd-watch-next-secondary-results-renderer::disconnectedCallback': (hostElement) => {
  2264. if (!(hostElement instanceof HTMLElement) || hostElement.closest('noscript')) return;
  2265. if (hostElement.isConnected !== false) return;
  2266. if (hostElement.__connectedFlg__ !== 8) return;
  2267. hostElement.__connectedFlg__ = 9;
  2268. if (hostElement.hasAttribute000('tyt-videos-list')) {
  2269. elements.related = null;
  2270. hostElement.removeAttribute000('tyt-videos-list');
  2271. }
  2272. console.log('ytd-watch-next-secondary-results-renderer::detached', hostElement);
  2273. },
  2274.  
  2275.  
  2276. 'settingCommentsVideoId': (hostElement) => {
  2277. if (!(hostElement instanceof HTMLElement) || !(hostElement.classList.length > 0) || hostElement.closest('noscript')) return;
  2278. const cnt = insp(hostElement);
  2279. const commentsArea = elements.comments;
  2280. if (commentsArea !== hostElement || hostElement.isConnected !== true || cnt.isAttached !== true || !cnt.data || cnt.hidden !== false) return;
  2281. const ytdFlexyElm = elements.flexy;
  2282. const ytdFlexyCnt = ytdFlexyElm ? insp(ytdFlexyElm) : null;
  2283. if (ytdFlexyCnt && ytdFlexyCnt.videoId) {
  2284. hostElement.setAttribute111('tyt-comments-video-id', ytdFlexyCnt.videoId)
  2285. } else {
  2286. hostElement.removeAttribute000('tyt-comments-video-id')
  2287. }
  2288. },
  2289. 'checkCommentsShouldBeHidden': (lockId) => {
  2290.  
  2291. if (lockGet['checkCommentsShouldBeHiddenLock'] !== lockId) return;
  2292.  
  2293. // commentsArea's attribute: tyt-comments-video-id
  2294. // ytdFlexyElm's attribute: video-id
  2295.  
  2296.  
  2297. const commentsArea = elements.comments;
  2298. const ytdFlexyElm = elements.flexy;
  2299. if (commentsArea && ytdFlexyElm && !commentsArea.hasAttribute000('hidden')) {
  2300. const ytdFlexyCnt = insp(ytdFlexyElm);
  2301. if (typeof ytdFlexyCnt.videoId === 'string') {
  2302. const commentsVideoId = commentsArea.getAttribute('tyt-comments-video-id');
  2303. if (commentsVideoId && commentsVideoId !== ytdFlexyCnt.videoId) {
  2304. commentsArea.setAttribute111('hidden', '');
  2305. // removeKeepCommentsScroller();
  2306. }
  2307. }
  2308. }
  2309.  
  2310. },
  2311. 'ytd-comments::defined': (cProto) => {
  2312.  
  2313. if (!cProto.attached498 && typeof cProto.attached === 'function') {
  2314. cProto.attached498 = cProto.attached;
  2315. cProto.attached = function () {
  2316. // Promise.resolve(this.hostElement).then(eventMap['ytd-comments::attached']).catch(console.warn);
  2317. // Promise.resolve(this.hostElement).then(eventMap['ytd-comments::dataChanged_']).catch(console.warn);
  2318. return this.attached498();
  2319. }
  2320. }
  2321. if (!cProto.detached498 && typeof cProto.detached === 'function') {
  2322. cProto.detached498 = cProto.detached;
  2323. cProto.detached = function () {
  2324. // Promise.resolve(this.hostElement).then(eventMap['ytd-comments::detached']).catch(console.warn);
  2325. // Promise.resolve(this.hostElement).then(eventMap['ytd-comments::dataChanged_']).catch(console.warn);
  2326. return this.detached498();
  2327. }
  2328. }
  2329.  
  2330. cProto._createPropertyObserver('data', '_dataChanged498', undefined)
  2331. cProto._dataChanged498 = function () {
  2332. console.log('_dataChanged498', this.hostElement)
  2333. Promise.resolve(this.hostElement).then(eventMap['ytd-comments::_dataChanged498']).catch(console.warn);
  2334. }
  2335.  
  2336.  
  2337. // if (!cProto.dataChanged498_ && typeof cProto.dataChanged_ === 'function') {
  2338. // cProto.dataChanged498_ = cProto.dataChanged_;
  2339. // cProto.dataChanged_ = function () {
  2340. // Promise.resolve(this.hostElement).then(eventMap['ytd-comments::dataChanged_']).catch(console.warn);
  2341. // return this.dataChanged498_();
  2342. // }
  2343. // }
  2344. },
  2345.  
  2346. 'ytd-comments::_dataChanged498': (hostElement) => {
  2347. // console.log(18984, hostElement.hasAttribute('tyt-comments-area'))
  2348. if (!hostElement.hasAttribute000('tyt-comments-area')) return;
  2349. let commentsDataStatus = 0;
  2350. const cnt = insp(hostElement);
  2351. const data = cnt ? cnt.data : null
  2352. const contents = data ? data.contents : null;
  2353. if (data) {
  2354. if (contents && contents.length === 1 && contents[0].messageRenderer) {
  2355. commentsDataStatus = 2;
  2356. }
  2357. if (contents && contents.length > 1 && contents[0].commentThreadRenderer) {
  2358. commentsDataStatus = 1;
  2359. }
  2360. }
  2361. if (commentsDataStatus) {
  2362. hostElement.setAttribute111('tyt-comments-data-status', commentsDataStatus);
  2363. // ytdFlexyElm.setAttribute111('tyt-comment-disabled', '')
  2364. } else {
  2365. // ytdFlexyElm.removeAttribute000('tyt-comment-disabled')
  2366. hostElement.removeAttribute000('tyt-comments-data-status')
  2367. }
  2368. Promise.resolve(hostElement).then(eventMap['settingCommentsVideoId']).catch(console.warn);
  2369. },
  2370.  
  2371. 'ytd-comments::connectedCallback': async (hostElement) => {
  2372. if (!(hostElement instanceof HTMLElement) || !(hostElement.classList.length > 0) || hostElement.closest('noscript')) return;
  2373. if (hostElement.isConnected !== true) return;
  2374. if (hostElement.__connectedFlg__ !== 4) return;
  2375. hostElement.__connectedFlg__ = 5;
  2376. if (!hostElement || hostElement.id !== 'comments') return;
  2377. // if (!hostElement || hostElement.closest('[hidden]')) return;
  2378. elements.comments = hostElement;
  2379. console.log('ytd-comments::attached')
  2380. Promise.resolve(hostElement).then(eventMap['settingCommentsVideoId']).catch(console.warn);
  2381. if (isRightTabsInserted) {
  2382.  
  2383. if (elements.comments !== hostElement) return;
  2384. if (hostElement.isConnected === false) return;
  2385. // if(!elements.comments || elements.comments.isConnected === false) return;
  2386. if (hostElement && !hostElement.closest('#right-tabs')) {
  2387. document.querySelector('#tab-comments').assignChildern111(null, hostElement, null);
  2388. } else {
  2389.  
  2390. if (elements.comments && elements.comments.closest('#tab-comments') && !elements.comments.closest('[hidden]')) {
  2391. document.querySelector('[tyt-tab-content="#tab-comments"]').classList.remove('tab-btn-hidden');
  2392. } else {
  2393. document.querySelector('[tyt-tab-content="#tab-comments"]').classList.add('tab-btn-hidden');
  2394. }
  2395.  
  2396. // document.querySelector('#tab-comments').classList.remove('tab-content-hidden')
  2397. // document.querySelector('[tyt-tab-content="#tab-comments"]').classList.remove('tab-btn-hidden')
  2398.  
  2399. Promise.resolve(lockSet['removeKeepCommentsScrollerLock']).then(removeKeepCommentsScroller).catch(console.warn);
  2400.  
  2401. }
  2402.  
  2403.  
  2404.  
  2405.  
  2406. }
  2407.  
  2408. aoComment.observe(hostElement, { attributes: true });
  2409. hostElement.setAttribute111('tyt-comments-area', '');
  2410.  
  2411.  
  2412. },
  2413. 'ytd-comments::disconnectedCallback': (hostElement) => {
  2414. // console.log(858, hostElement)
  2415. if (!(hostElement instanceof HTMLElement) || hostElement.closest('noscript')) return;
  2416. if (hostElement.isConnected !== false) return;
  2417. if (hostElement.__connectedFlg__ !== 8) return;
  2418. hostElement.__connectedFlg__ = 9;
  2419.  
  2420. if (hostElement.hasAttribute000('tyt-comments-area')) {
  2421. foComments.disconnect();
  2422. foComments.takeRecords();
  2423. hostElement.removeAttribute000('tyt-comments-area');
  2424. // document.querySelector('#tab-comments').classList.add('tab-content-hidden')
  2425. // document.querySelector('[tyt-tab-content="#tab-comments"]').classList.add('tab-btn-hidden')
  2426.  
  2427.  
  2428. aoComment.disconnect();
  2429. aoComment.takeRecords();
  2430. elements.comments = null;
  2431.  
  2432. document.querySelector('[tyt-tab-content="#tab-comments"]').classList.add('tab-btn-hidden');
  2433.  
  2434. Promise.resolve(lockSet['removeKeepCommentsScrollerLock']).then(removeKeepCommentsScroller).catch(console.warn);
  2435. }
  2436.  
  2437.  
  2438. },
  2439.  
  2440.  
  2441. 'ytd-comments-header-renderer::defined': (cProto) => {
  2442.  
  2443. if (!cProto.attached498 && typeof cProto.attached === 'function') {
  2444. cProto.attached498 = cProto.attached;
  2445. cProto.attached = function () {
  2446. // Promise.resolve(this.hostElement).then(eventMap['ytd-comments-header-renderer::attached']).catch(console.warn);
  2447. Promise.resolve(this.hostElement).then(eventMap['ytd-comments-header-renderer::dataChanged']).catch(console.warn); // force dataChanged on attached
  2448. return this.attached498();
  2449. }
  2450. }
  2451. if (!cProto.detached498 && typeof cProto.detached === 'function') {
  2452. cProto.detached498 = cProto.detached;
  2453. cProto.detached = function () {
  2454. // Promise.resolve(this.hostElement).then(eventMap['ytd-comments-header-renderer::detached']).catch(console.warn);
  2455. return this.detached498();
  2456. }
  2457. }
  2458.  
  2459. if (!cProto.dataChanged498 && typeof cProto.dataChanged === 'function') {
  2460. cProto.dataChanged498 = cProto.dataChanged;
  2461. cProto.dataChanged = function () {
  2462. Promise.resolve(this.hostElement).then(eventMap['ytd-comments-header-renderer::dataChanged']).catch(console.warn);
  2463. return this.dataChanged498();
  2464. }
  2465. }
  2466.  
  2467. },
  2468.  
  2469.  
  2470. 'ytd-comments-header-renderer::connectedCallback': (hostElement) => {
  2471.  
  2472. if (!(hostElement instanceof HTMLElement) || !(hostElement.classList.length > 0) || hostElement.closest('noscript')) return;
  2473. if (hostElement.isConnected !== true) return;
  2474. if (hostElement.__connectedFlg__ !== 4) return;
  2475. hostElement.__connectedFlg__ = 5;
  2476. if (!hostElement || !hostElement.classList.contains('ytd-item-section-renderer')) return;
  2477. console.log(12991, 'ytd-comments-header-renderer::connectedCallback')
  2478. const targetElement = document.querySelector('[tyt-comments-area] ytd-comments-header-renderer');
  2479. if (hostElement === targetElement) {
  2480. hostElement.setAttribute111('tyt-comments-header-field', '');
  2481. } else {
  2482. const parentNode = hostElement.parentNode;
  2483. if (parentNode instanceof HTMLElement && parentNode.querySelector('[tyt-comments-header-field]')) {
  2484. hostElement.setAttribute111('tyt-comments-header-field', '')
  2485. }
  2486. }
  2487.  
  2488. },
  2489.  
  2490. 'ytd-comments-header-renderer::disconnectedCallback': (hostElement) => {
  2491.  
  2492. if (!(hostElement instanceof HTMLElement) || hostElement.closest('noscript')) return;
  2493. if (hostElement.isConnected !== false) return;
  2494. if (hostElement.__connectedFlg__ !== 8) return;
  2495. hostElement.__connectedFlg__ = 9;
  2496. console.log(12992, 'ytd-comments-header-renderer::disconnectedCallback')
  2497. if (hostElement.hasAttribute000('field-of-cm-count')) {
  2498.  
  2499. const cmCount = document.querySelector('#tyt-cm-count');
  2500. if (cmCount) {
  2501. cmCount.textContent = '';
  2502. hostElement.removeAttribute000('field-of-cm-count');
  2503.  
  2504. }
  2505. }
  2506. if (hostElement.hasAttribute000('tyt-comments-header-field')) {
  2507. hostElement.removeAttribute000('tyt-comments-header-field');
  2508. }
  2509.  
  2510. },
  2511.  
  2512. 'ytd-comments-header-renderer::dataChanged': (hostElement) => {
  2513.  
  2514. if (!(hostElement instanceof HTMLElement) || !(hostElement.classList.length > 0) || hostElement.closest('noscript')) return;
  2515.  
  2516. const ytdFlexyElm = elements.flexy;
  2517.  
  2518. let b = false;
  2519. const cnt = insp(hostElement);
  2520. if (cnt && hostElement.closest('#tab-comments') && document.querySelector('#tab-comments ytd-comments-header-renderer') === hostElement) {
  2521. b = true;
  2522. } else if (hostElement instanceof HTMLElement && hostElement.parentNode instanceof HTMLElement && hostElement.parentNode.querySelector('[tyt-comments-header-field]')) {
  2523. b = true;
  2524. }
  2525. if (b) {
  2526. hostElement.setAttribute111('tyt-comments-header-field', '')
  2527. ytdFlexyElm && ytdFlexyElm.removeAttribute000('tyt-comment-disabled');
  2528. }
  2529.  
  2530. // console.log(1841, [...document.querySelectorAll('#tab-comments ytd-comments-header-renderer')], document.querySelector('#tab-comments ytd-comments-header-renderer') === hostElement, !!hostElement?.parentNode?.querySelector('[tyt-comments-header-field]'))
  2531.  
  2532. if (hostElement.hasAttribute000('tyt-comments-header-field') && hostElement.isConnected === true) {
  2533.  
  2534. // console.log(1842, [...document.querySelectorAll('#tab-comments ytd-comments-header-renderer')], document.querySelector('#tab-comments ytd-comments-header-renderer') === hostElement, !!hostElement?.parentNode?.querySelector('[tyt-comments-header-field]'))
  2535.  
  2536. const data = cnt.data;
  2537. let ez = '';
  2538. if (data.commentsCount && data.commentsCount.runs && data.commentsCount.runs.length >= 1) {
  2539. let max = -1;
  2540. const z = data.commentsCount.runs.map(e => {
  2541. let c = e.text.replace(/\D+/g, '').length;
  2542. if (c > max) max = c;
  2543. return [e.text, c];
  2544. }).filter(a => a[1] === max);
  2545. if (z.length >= 1) {
  2546. ez = z[0][0];
  2547. }
  2548. } else if (data.countText && data.countText.runs && data.countText.runs.length >= 1) {
  2549. let max = -1;
  2550. const z = data.countText.runs.map(e => {
  2551. let c = e.text.replace(/\D+/g, '').length;
  2552. if (c > max) max = c;
  2553. return [e.text, c];
  2554. }).filter(a => a[1] === max);
  2555. if (z.length >= 1) {
  2556. ez = z[0][0];
  2557. }
  2558. }
  2559. const cmCount = document.querySelector('#tyt-cm-count');
  2560. if (ez) {
  2561. hostElement.setAttribute111('field-of-cm-count', '');
  2562. cmCount && (cmCount.textContent = ez.trim());
  2563. } else {
  2564. hostElement.removeAttribute000('field-of-cm-count');
  2565. cmCount && (cmCount.textContent = '');
  2566. console.warn('no text for #tyt-cm-count')
  2567. }
  2568. }
  2569. },
  2570.  
  2571. 'ytd-expander::defined': (cProto) => {
  2572. // if (!cProto.attached498 && typeof cProto.attached === 'function') {
  2573. // cProto.attached498 = cProto.attached;
  2574. // cProto.attached = function () {
  2575. // Promise.resolve(this.hostElement).then(eventMap['ytd-expander::attached']).catch(console.warn);
  2576. // return this.attached498();
  2577. // }
  2578. // }
  2579. // if (!cProto.detached498 && typeof cProto.detached === 'function') {
  2580. // cProto.detached498 = cProto.detached;
  2581. // cProto.detached = function () {
  2582. // Promise.resolve(this.hostElement).then(eventMap['ytd-expander::detached']).catch(console.warn);
  2583. // return this.detached498();
  2584. // }
  2585. // }
  2586. if (!cProto.calculateCanCollapse498 && typeof cProto.calculateCanCollapse === 'function') {
  2587. cProto.calculateCanCollapse498 = cProto.calculateCanCollapse;
  2588. cProto.calculateCanCollapse = funcCanCollapse;
  2589.  
  2590.  
  2591. }
  2592. },
  2593.  
  2594. 'ytd-expander::connectedCallback': (hostElement) => {
  2595. if (!(hostElement instanceof HTMLElement) || !(hostElement.classList.length > 0) || hostElement.closest('noscript')) return;
  2596. if (hostElement.isConnected !== true) return;
  2597. if (hostElement.__connectedFlg__ !== 4) return;
  2598. hostElement.__connectedFlg__ = 5;
  2599. // console.log(4959, hostElement)
  2600.  
  2601. if (hostElement instanceof HTMLElement && hostElement.matches('[tyt-comments-area] #contents ytd-expander#expander') && !hostElement.matches('[hidden] ytd-expander#expander')) {
  2602.  
  2603. hostElement.setAttribute111('tyt-content-comment-entry', '')
  2604. ioComment.observe(hostElement);
  2605. } else if (hostElement instanceof HTMLElement && hostElement.matches('ytd-expander#expander.style-scope.ytd-expandable-video-description-body-renderer')) {
  2606. // && !hostElement.matches('#right-tabs ytd-expander#expander, [hidden] ytd-expander#expander')
  2607.  
  2608. elements.infoExpander = hostElement
  2609. // console.log(1299, hostElement.parentNode, isRightTabsInserted)
  2610. if (isRightTabsInserted) {
  2611. const infoExpander = elements.infoExpander;
  2612. if (infoExpander && !infoExpander.closest('#right-tabs')) {
  2613. document.querySelector('#tab-info').assignChildern111(null, infoExpander, null);
  2614. } else {
  2615.  
  2616. if (document.querySelector('[tyt-tab-content="#tab-info"]')) {
  2617. if (elements.infoExpander && elements.infoExpander.closest('#tab-info')) {
  2618. document.querySelector('[tyt-tab-content="#tab-info"]').classList.remove('tab-btn-hidden');
  2619. } else {
  2620. document.querySelector('[tyt-tab-content="#tab-info"]').classList.add('tab-btn-hidden');
  2621. }
  2622. }
  2623. if (infoExpander) Promise.resolve(lockSet['infoFixLock']).then(infoFix).catch(console.warn);
  2624. }
  2625. infoExpanderElementProvidedPromise.resolve();
  2626. }
  2627. hostElement.setAttribute111('tyt-main-info', '');
  2628. }
  2629. // console.log('ytd-expander::attached', hostElement);
  2630.  
  2631.  
  2632.  
  2633. },
  2634.  
  2635. 'ytd-expander::disconnectedCallback': (hostElement) => {
  2636. if (!(hostElement instanceof HTMLElement) || hostElement.closest('noscript')) return;
  2637. if (hostElement.isConnected !== false) return;
  2638. if (hostElement.__connectedFlg__ !== 8) return;
  2639. hostElement.__connectedFlg__ = 9;
  2640. // console.log(5992, hostElement)
  2641. if (hostElement.hasAttribute000('tyt-content-comment-entry')) {
  2642. ioComment.unobserve(hostElement);
  2643. hostElement.removeAttribute000('tyt-content-comment-entry')
  2644. } else if (hostElement.hasAttribute000('tyt-main-info')) {
  2645. elements.infoExpander = null;
  2646. hostElement.removeAttribute000('tyt-main-info');
  2647. }
  2648. // console.log('ytd-expander::detached', hostElement);
  2649. },
  2650.  
  2651.  
  2652. 'ytd-live-chat-frame::defined': (cProto) => {
  2653.  
  2654. // if (!cProto.attached498 && typeof cProto.attached === 'function') {
  2655. // cProto.attached498 = cProto.attached;
  2656. // cProto.attached = function () {
  2657. // Promise.resolve(this.hostElement).then(eventMap['ytd-live-chat-frame::attached']).catch(console.warn);
  2658. // return this.attached498();
  2659. // }
  2660. // }
  2661. // if (!cProto.detached498 && typeof cProto.detached === 'function') {
  2662. // cProto.detached498 = cProto.detached;
  2663. // cProto.detached = function () {
  2664. // Promise.resolve(this.hostElement).then(eventMap['ytd-live-chat-frame::detached']).catch(console.warn);
  2665. // return this.detached498();
  2666. // }
  2667. // }
  2668.  
  2669. if (typeof cProto.urlChanged === 'function' && !cProto.urlChanged66 && !cProto.urlChangedAsync12 && cProto.urlChanged.length === 0) {
  2670. cProto.urlChanged66 = cProto.urlChanged;
  2671. let ath = 0;
  2672. cProto.urlChangedAsync12 = async function () {
  2673. if (ath > 1e9) ath = 9;
  2674. const t = ++ath;
  2675. const chatframe = this.chatframe || (this.$ || 0).chatframe || 0;
  2676. if (chatframe) {
  2677. if (chatframe.contentDocument === null) await Promise.resolve();
  2678. if (t !== ath) return;
  2679. try {
  2680. let win = chatframe.contentWindow;
  2681. win && await (new Promise(r => win.setTimeout(r)).catch(console.warn));
  2682. win = null;
  2683. } catch (e) { }
  2684. win = null;
  2685. if (t !== ath) return;
  2686. }
  2687. this.urlChanged66();
  2688. }
  2689. cProto.urlChanged = function () {
  2690. this.urlChangedAsync12();
  2691. }
  2692. }
  2693. },
  2694.  
  2695. 'ytd-live-chat-frame::connectedCallback': (hostElement) => {
  2696.  
  2697. if (!(hostElement instanceof HTMLElement) || !(hostElement.classList.length > 0) || hostElement.closest('noscript')) return;
  2698. if (hostElement.isConnected !== true) return;
  2699. if (hostElement.__connectedFlg__ !== 4) return;
  2700. hostElement.__connectedFlg__ = 5;
  2701. if (!hostElement || hostElement.id !== 'chat') return;
  2702. console.log('ytd-live-chat-frame::attached')
  2703. const chatElem = document.querySelector('#columns.style-scope.ytd-watch-flexy ytd-live-chat-frame#chat');
  2704. if (chatElem === hostElement) {
  2705. elements.chat = chatElem;
  2706. aoChat.observe(hostElement, { attributes: true });
  2707. hostElement.setAttribute111('tyt-active-chat-frame', '');
  2708.  
  2709. const chatContainer = chatElem ? (chatElem.closest('#chat-container') || chatElem) : null;
  2710. if (chatContainer && !chatContainer.hasAttribute000('tyt-chat-container')) {
  2711. for (const p of document.querySelectorAll('[tyt-chat-container]')) {
  2712. p.removeAttribute000('[tyt-chat-container]');
  2713. }
  2714. chatContainer.setAttribute111('tyt-chat-container', '')
  2715. }
  2716. Promise.resolve(lockSet['layoutFixLock']).then(layoutFix);
  2717. }
  2718. },
  2719.  
  2720. 'ytd-live-chat-frame::disconnectedCallback': (hostElement) => {
  2721.  
  2722. if (!(hostElement instanceof HTMLElement) || hostElement.closest('noscript')) return;
  2723. if (hostElement.isConnected !== false) return;
  2724. if (hostElement.__connectedFlg__ !== 8) return;
  2725. hostElement.__connectedFlg__ = 9;
  2726. console.log('ytd-live-chat-frame::detached')
  2727. if (hostElement.hasAttribute000('tyt-active-chat-frame')) {
  2728. aoChat.disconnect();
  2729. aoChat.takeRecords();
  2730. hostElement.removeAttribute000('tyt-active-chat-frame');
  2731. elements.chat = null;
  2732.  
  2733. const ytdFlexyElm = elements.flexy;
  2734. if (ytdFlexyElm) {
  2735. ytdFlexyElm.removeAttribute000('tyt-chat-collapsed')
  2736. ytdFlexyElm.setAttribute111('tyt-chat', '');
  2737. }
  2738. }
  2739.  
  2740. },
  2741.  
  2742. 'ytd-engagement-panel-section-list-renderer:defined': (cProto) => {
  2743.  
  2744. // if (!cProto.attached498 && typeof cProto.attached === 'function') {
  2745. // cProto.attached498 = cProto.attached;
  2746. // cProto.attached = function () {
  2747. // Promise.resolve(this.hostElement).then(eventMap['ytd-engagement-panel-section-list-renderer::attached']).catch(console.warn);
  2748. // return this.attached498();
  2749. // }
  2750. // }
  2751. // if (!cProto.detached498 && typeof cProto.detached === 'function') {
  2752. // cProto.detached498 = cProto.detached;
  2753. // cProto.detached = function () {
  2754. // Promise.resolve(this.hostElement).then(eventMap['ytd-engagement-panel-section-list-renderer::detached']).catch(console.warn);
  2755. // return this.detached498();
  2756. // }
  2757. // }
  2758. },
  2759.  
  2760. 'ytd-engagement-panel-section-list-renderer::connectedCallback': (hostElement) => {
  2761. if (!(hostElement instanceof HTMLElement) || !(hostElement.classList.length > 0) || hostElement.closest('noscript')) return;
  2762. if (hostElement.isConnected !== true) return;
  2763. if (hostElement.__connectedFlg__ !== 4) return;
  2764. hostElement.__connectedFlg__ = 5;
  2765. // console.log('ytd-engagement-panel-section-list-renderer::attached', hostElement)
  2766. if (hostElement.matches('#panels.ytd-watch-flexy > ytd-engagement-panel-section-list-renderer[target-id][visibility]')) {
  2767. hostElement.setAttribute111('tyt-egm-panel', '');
  2768. Promise.resolve(lockSet['updateEgmPanelsLock']).then(updateEgmPanels).catch(console.warn);
  2769. aoEgmPanels.observe(hostElement, { attributes: true, attributeFilter: ['visibility', 'hidden'] });
  2770. }
  2771. },
  2772.  
  2773. 'ytd-engagement-panel-section-list-renderer::disconnectedCallback': (hostElement) => {
  2774. if (!(hostElement instanceof HTMLElement) || hostElement.closest('noscript')) return;
  2775. if (hostElement.isConnected !== false) return;
  2776. if (hostElement.__connectedFlg__ !== 8) return;
  2777. hostElement.__connectedFlg__ = 9;
  2778. hostElement.removeAttribute('tyt-egm-panel', '');
  2779. Promise.resolve(lockSet['updateEgmPanelsLock']).then(updateEgmPanels).catch(console.warn);
  2780. },
  2781.  
  2782. '_yt_playerProvided': () => {
  2783. mLoaded.flag |= 4;
  2784. document.documentElement.setAttribute111('tabview-loaded', mLoaded.makeString());
  2785. },
  2786. 'relatedElementProvided': (target) => {
  2787. if (target.closest('[hidden]')) return;
  2788. elements.related = target;
  2789. console.log('relatedElementProvided')
  2790. videosElementProvidedPromise.resolve();
  2791. },
  2792. 'onceInfoExpanderElementProvidedPromised': () => {
  2793. const ytdFlexyElm = elements.flexy;
  2794. if (ytdFlexyElm) {
  2795. ytdFlexyElm.setAttribute111('hide-default-text-inline-expander', '');
  2796. }
  2797. },
  2798.  
  2799. 'refreshSecondaryInner': (lockId) => {
  2800.  
  2801.  
  2802. if (lockGet['refreshSecondaryInnerLock'] !== lockId) return;
  2803. /*
  2804. ytd-watch-flexy:not([panels-beside-player]):not([fixed-panels]) #panels-full-bleed-container.ytd-watch-flexy{
  2805. display: none;}
  2806. #player-full-bleed-container.ytd-watch-flexy{
  2807. position: relative;
  2808. flex: 1;}
  2809. */
  2810.  
  2811. const ytdFlexyElm = elements.flexy;
  2812. // if(ytdFlexyElm && ytdFlexyElm.matches('ytd-watch-flexy[fixed-panels][theater]')){
  2813. // // ytdFlexyElm.fixedPanels = true;
  2814. // ytdFlexyElm.removeAttribute000('fixed-panels');
  2815. // }
  2816.  
  2817. if (ytdFlexyElm && ytdFlexyElm.matches('ytd-watch-flexy[theater][flexy][full-bleed-player]:not([full-bleed-no-max-width-columns])')) {
  2818. // ytdFlexyElm.fullBleedNoMaxWidthColumns = true;
  2819. ytdFlexyElm.setAttribute111('full-bleed-no-max-width-columns', '');
  2820. }
  2821.  
  2822. const related = elements.related;
  2823. if (related && related.isConnected && !related.closest('#right-tabs #tab-videos')) {
  2824. document.querySelector('#tab-videos').assignChildern111(null, related, null);
  2825. }
  2826. const infoExpander = elements.infoExpander;
  2827. if (infoExpander && infoExpander.isConnected && !infoExpander.closest('#right-tabs #tab-info')) {
  2828. document.querySelector('#tab-info').assignChildern111(null, infoExpander, null);
  2829. } else {
  2830. if (infoExpander && ytdFlexyElm && shouldFixInfo) {
  2831. shouldFixInfo = false;
  2832. Promise.resolve(lockSet['infoFixLock']).then(infoFix).catch(console.warn);
  2833. }
  2834. }
  2835.  
  2836. const commentsArea = elements.comments;
  2837. if (commentsArea) {
  2838. const isConnected = commentsArea.isConnected;
  2839. if (isConnected && !commentsArea.closest('#right-tabs #tab-comments')) {
  2840. const tab = document.querySelector('#tab-comments');
  2841. tab.assignChildern111(null, commentsArea, null);
  2842. } else {
  2843. // if (!isConnected || tab.classList.contains('tab-content-hidden')) removeKeepCommentsScroller();
  2844. }
  2845. }
  2846.  
  2847.  
  2848.  
  2849.  
  2850.  
  2851.  
  2852.  
  2853. },
  2854.  
  2855. 'yt-navigate-finish': (evt) => {
  2856.  
  2857. const ytdAppElm = document.querySelector('ytd-page-manager#page-manager.style-scope.ytd-app');
  2858. const ytdAppCnt = insp(ytdAppElm);
  2859. pageType = ytdAppCnt ? (ytdAppCnt.data || 0).page : null;
  2860.  
  2861. if (!document.querySelector('ytd-watch-flexy #player')) return;
  2862. shouldFixInfo = true;
  2863. console.log('yt-navigate-finish')
  2864. const flexyArr = [...document.querySelectorAll('ytd-watch-flexy')].filter(e => !e.closest('[hidden]') && e.querySelector('#player'));
  2865. if (flexyArr.length === 1) {
  2866. // const lockId = lockSet['yt-navigate-finish-videos'];
  2867. elements.flexy = flexyArr[0];
  2868. if (isRightTabsInserted) {
  2869. Promise.resolve(lockSet['refreshSecondaryInnerLock']).then(eventMap['refreshSecondaryInner']).catch(console.warn);
  2870. Promise.resolve(lockSet['removeKeepCommentsScrollerLock']).then(removeKeepCommentsScroller).catch(console.warn);
  2871. } else {
  2872. navigateFinishedPromise.resolve();
  2873. plugin.minibrowser.enable();
  2874. }
  2875. }
  2876. shouldFixInfo = true;
  2877. Promise.resolve(lockSet['layoutFixLock']).then(layoutFix);
  2878. },
  2879.  
  2880. 'onceInsertRightTabs': () => {
  2881.  
  2882.  
  2883. // if(lockId !== lockGet['yt-navigate-finish-videos']) return;
  2884. const related = elements.related;
  2885. let rightTabs = document.querySelector('#right-tabs');
  2886. if (!document.querySelector('#right-tabs') && related) {
  2887. getLangForPage();
  2888. let docTmp = document.createElement('template');
  2889. docTmp.innerHTML = createHTML(getTabsHTML());
  2890. let newElm = docTmp.content.firstElementChild;
  2891. if (newElm !== null) {
  2892. related.parentNode.insertBefore000(newElm, related);
  2893. }
  2894. rightTabs = newElm;
  2895. rightTabs.querySelector('[tyt-tab-content="#tab-comments"]').classList.add('tab-btn-hidden');
  2896.  
  2897. const secondaryWrapper = document.createElement('secondary-wrapper');
  2898. const secondaryInner = document.querySelector('#secondary-inner.style-scope.ytd-watch-flexy');
  2899. secondaryWrapper.replaceChildren000(...secondaryInner.childNodes);
  2900. secondaryInner.insertBefore000(secondaryWrapper, secondaryInner.firstChild);
  2901.  
  2902. rightTabs.querySelector('#material-tabs').addEventListener('click', eventMap['tabs-btn-click'], true)
  2903.  
  2904. if (!rightTabs.closest('secondary-wrapper')) secondaryWrapper.appendChild000(rightTabs);
  2905.  
  2906. }
  2907. if (rightTabs) {
  2908. isRightTabsInserted = true;
  2909. const ioTabBtns = new IntersectionObserver((entries) => {
  2910. for (const entry of entries) {
  2911. const rect = entry.boundingClientRect;
  2912. entry.target.classList.toggle('tab-btn-visible', rect.width && rect.height)
  2913. }
  2914. }, { rootMargin: '0px' });
  2915. for (const btn of document.querySelectorAll('.tab-btn[tyt-tab-content]')) {
  2916. ioTabBtns.observe(btn);
  2917. }
  2918. if (!related.closest('#right-tabs')) {
  2919. document.querySelector('#tab-videos').assignChildern111(null, related, null);
  2920. }
  2921. const infoExpander = elements.infoExpander;
  2922. if (infoExpander && !infoExpander.closest('#right-tabs')) {
  2923. document.querySelector('#tab-info').assignChildern111(null, infoExpander, null);
  2924. }
  2925. const commentsArea = elements.comments;
  2926. if (commentsArea && !commentsArea.closest('#right-tabs')) {
  2927. document.querySelector('#tab-comments').assignChildern111(null, commentsArea, null);
  2928. }
  2929. rightTabsProvidedPromise.resolve();
  2930. roRightTabs.disconnect();
  2931. roRightTabs.observe(rightTabs);
  2932. const ytdFlexyElm = elements.flexy;
  2933. const ao = new MutationObserver(eventMap['aoFlexyFn']);
  2934. ao.observe(ytdFlexyElm, { attributes: true });
  2935. Promise.resolve(lockSet['tabsStatusCorrectionLock']).then(eventMap['tabsStatusCorrection']).catch(console.warn);
  2936.  
  2937. delayPn(1).then(eventMap['fixInitialTabStateFn']).catch(console.warn);
  2938. }
  2939.  
  2940. },
  2941.  
  2942. 'aoFlexyFn': () => {
  2943.  
  2944. Promise.resolve(lockSet['checkCommentsShouldBeHiddenLock']).then(eventMap['checkCommentsShouldBeHidden']).catch(console.warn);
  2945.  
  2946. Promise.resolve(lockSet['refreshSecondaryInnerLock']).then(eventMap['refreshSecondaryInner']).catch(console.warn);
  2947.  
  2948. Promise.resolve(lockSet['tabsStatusCorrectionLock']).then(eventMap['tabsStatusCorrection']).catch(console.warn);
  2949.  
  2950. },
  2951.  
  2952. 'twoColumnChanged10': (lockId) => {
  2953.  
  2954. if (lockId !== lockGet['twoColumnChanged10Lock']) return;
  2955. for (const continuation of document.querySelectorAll('#tab-videos ytd-watch-next-secondary-results-renderer ytd-continuation-item-renderer')) {
  2956. if (continuation.closest('[hidden]')) continue;
  2957. const cnt = insp(continuation);
  2958. if (typeof cnt.showButton === 'boolean') {
  2959. if (cnt.showButton === false) continue;
  2960. cnt.showButton = false;
  2961. const behavior = (cnt.ytRendererBehavior || cnt);
  2962. if (typeof behavior.invalidate === 'function') {
  2963. behavior.invalidate(!1);
  2964. }
  2965. }
  2966. }
  2967.  
  2968. },
  2969.  
  2970. 'tabsStatusCorrection': (lockId) => {
  2971. if (lockId !== lockGet['tabsStatusCorrectionLock']) return;
  2972. const ytdFlexyElm = elements.flexy;
  2973. if (!ytdFlexyElm) return;
  2974. const p = tabAStatus;
  2975. const q = calculationFn(p, 3 | 4 | 8 | 16 | 32 | 64);
  2976.  
  2977. if (p !== q) {
  2978. console.log(388, p, q)
  2979. let actioned = false;
  2980. if ((p & 8) === 0 && (q & 8) === 8) {
  2981. lastPanel = 'chat'
  2982. }
  2983. tabAStatus = q;
  2984.  
  2985. let bFixForResizedTab = false;
  2986.  
  2987. if ((q ^ 2) === 2 && bFixForResizedTabLater) {
  2988. bFixForResizedTab = true;
  2989. }
  2990.  
  2991. if ((p & 16) === 16 & (q & 16) === 0) {
  2992. Promise.resolve(lockSet['twoColumnChanged10Lock']).then(eventMap['twoColumnChanged10']).catch(console.warn);
  2993. }
  2994.  
  2995. if ((((p & 2) === 2) ^ ((q & 2) === 2)) && ((q & 2) === 2)) {
  2996. bFixForResizedTab = true;
  2997. }
  2998.  
  2999. if ((q & 64) === 64) {
  3000. actioned = false;
  3001. } else if ((p & 64) == 64 && (q & 64) === 0) {
  3002.  
  3003. if ((q & 32) === 32) {
  3004. ytBtnCloseEngagementPanels();
  3005. }
  3006.  
  3007. if ((q & (2 | 8)) === (2 | 8)) {
  3008. if (lastPanel === 'chat') {
  3009.  
  3010. switchToTab(null);
  3011. actioned = true;
  3012. } else if (lastPanel) {
  3013. ytBtnCollapseChat();
  3014. actioned = true;
  3015. }
  3016. }
  3017.  
  3018. } else if ((p & (1 | 2 | 8 | 16 | 32)) === (1 | 0 | 0 | 16 | 0) && (q & (1 | 2 | 8 | 16 | 32)) === (1 | 0 | 8 | 16 | 0)) {
  3019. ytBtnCancelTheater();
  3020. actioned = true;
  3021. } else if ((p & (1 | 16 | 32)) === (0 | 16 | 0) && (q & (1 | 16 | 32)) === (0 | 16 | 32) && (q & (2 | 8)) > 0) {
  3022. if (q & 2) {
  3023. switchToTab(null);
  3024. actioned = true;
  3025. }
  3026. if (q & 8) {
  3027. ytBtnCollapseChat();
  3028. actioned = true;
  3029. }
  3030. } else if ((p & (1 | 16 | 8 | 2)) === (16 | 8) && (q & (1 | 16 | 8 | 2)) === (16)) {
  3031. if (lastTab) {
  3032. switchToTab(lastTab)
  3033. actioned = true;
  3034. }
  3035.  
  3036. } else if ((p & 1) === 0 && (q & 1) === 1) {
  3037. if ((q & 32) === 32) {
  3038. ytBtnCloseEngagementPanels();
  3039. }
  3040. if ((p & 9) === 8 && (q & 9) === 9) {
  3041. ytBtnCollapseChat();
  3042. }
  3043. switchToTab(null)
  3044. actioned = true;
  3045.  
  3046. } else if ((p & 3) === 1 && (q & 3) === 3) {
  3047. ytBtnCancelTheater();
  3048. actioned = true;
  3049. } else if ((p & 10) === 2 && (q & 10) === 10) {
  3050.  
  3051. switchToTab(null)
  3052. actioned = true;
  3053.  
  3054. } else if ((p & (8 | 32)) === (0 | 32) && (q & (8 | 32)) === (8 | 32)) {
  3055.  
  3056. ytBtnCloseEngagementPanels();
  3057. actioned = true;
  3058.  
  3059.  
  3060. } else if ((p & (2 | 32)) === (0 | 32) && (q & (2 | 32)) === (2 | 32)) {
  3061.  
  3062. ytBtnCloseEngagementPanels();
  3063. actioned = true;
  3064.  
  3065. } else if ((p & (2 | 8)) === (0 | 8) && (q & (2 | 8)) === (2 | 8)) {
  3066.  
  3067. ytBtnCollapseChat();
  3068. actioned = true;
  3069. // if( lastPanel && (p & (1|16) === 16) && (q & (1 | 16 | 8 | 2)) === (16) ){
  3070. // switchToTab(lastTab)
  3071. // actioned = true;
  3072. // }
  3073. } else if ((p & 1) === 1 && (q & (1 | 32)) === (0 | 0)) {
  3074. if (lastPanel === 'chat') {
  3075. ytBtnExpandChat()
  3076. actioned = true;
  3077. } else if (lastPanel === lastTab && lastTab) {
  3078. switchToTab(lastTab)
  3079. actioned = true;
  3080. }
  3081. }
  3082.  
  3083.  
  3084. // 24 20
  3085. // 8 16 4 16
  3086.  
  3087.  
  3088. if (!actioned && (p & (1 | 16)) === 16 && (q & (1 | 16 | 8 | 2 | 32 | 64)) === (16 | 0 | 0)) {
  3089. console.log(388, 'd')
  3090. if (lastPanel === 'chat') {
  3091. ytBtnExpandChat()
  3092. actioned = true;
  3093. } else if (lastTab) {
  3094. switchToTab(lastTab)
  3095. actioned = true;
  3096. }
  3097. }
  3098.  
  3099.  
  3100. if (bFixForResizedTab) {
  3101. bFixForResizedTabLater = false;
  3102. Promise.resolve(0).then(eventMap['fixForTabDisplay']).catch(console.warn);
  3103. }
  3104.  
  3105. if (((p & 16) === 16) ^ ((q & 16) === 16)) {
  3106. Promise.resolve(lockSet['infoFixLock']).then(infoFix).catch(console.warn);
  3107. Promise.resolve(lockSet['removeKeepCommentsScrollerLock']).then(removeKeepCommentsScroller).catch(console.warn);
  3108. Promise.resolve(lockSet['layoutFixLock']).then(layoutFix).catch(console.warn);
  3109. }
  3110. }
  3111.  
  3112. },
  3113.  
  3114. 'fixInitialTabStateFn': () => {
  3115. if (checkElementExist('ytd-live-chat-frame#chat', '[hidden], [collapsed]')) {
  3116. switchToTab(null);
  3117. if (checkElementExist('ytd-watch-flexy[theater]', '[hidden]')) {
  3118. ytBtnCollapseChat();
  3119. }
  3120. } else if (checkElementExist('ytd-watch-flexy[is-two-columns_]:not([theater])', '[hidden]') && !document.querySelector('[tyt-tab]')) {
  3121. let btn0 = document.querySelector('.tab-btn-visible') // or default button
  3122. if (btn0) {
  3123. switchToTab(btn0);
  3124. } else {
  3125. switchToTab(null);
  3126. }
  3127. } else if (checkElementExist('ytd-watch-flexy[is-two-columns_][theater]', '[hidden]') && !document.querySelector('[tyt-tab]')) {
  3128. switchToTab(null);
  3129. }
  3130. },
  3131.  
  3132. 'tabs-btn-click': (evt) => {
  3133.  
  3134. const target = evt.target;
  3135. if (target instanceof HTMLElement && target.classList.contains('tab-btn') && target.hasAttribute000('tyt-tab-content')) {
  3136.  
  3137. evt.preventDefault();
  3138. evt.stopPropagation();
  3139. evt.stopImmediatePropagation();
  3140.  
  3141.  
  3142. const activeLink = target;
  3143.  
  3144. switchToTab(activeLink);
  3145.  
  3146. }
  3147.  
  3148. }
  3149.  
  3150. }
  3151.  
  3152. Promise.all([videosElementProvidedPromise, navigateFinishedPromise]).then(eventMap['onceInsertRightTabs']).catch(console.warn);
  3153. Promise.all([navigateFinishedPromise, infoExpanderElementProvidedPromise]).then(eventMap['onceInfoExpanderElementProvidedPromised']).catch(console.warn);
  3154.  
  3155. const isCustomElementsProvided = typeof customElements !== "undefined" && typeof (customElements || 0).whenDefined === "function";
  3156.  
  3157. const promiseForCustomYtElementsReady = isCustomElementsProvided ? Promise.resolve(0) : new Promise((callback) => {
  3158. const EVENT_KEY_ON_REGISTRY_READY = "ytI-ce-registry-created";
  3159. if (typeof customElements === 'undefined') {
  3160. if (!('__CE_registry' in document)) {
  3161. // https://github.com/webcomponents/polyfills/
  3162. Object.defineProperty(document, '__CE_registry', {
  3163. get() {
  3164. // return undefined
  3165. },
  3166. set(nv) {
  3167. if (typeof nv == 'object') {
  3168. delete this.__CE_registry;
  3169. this.__CE_registry = nv;
  3170. this.dispatchEvent(new CustomEvent(EVENT_KEY_ON_REGISTRY_READY));
  3171. }
  3172. return true;
  3173. },
  3174. enumerable: false,
  3175. configurable: true
  3176. })
  3177. }
  3178. let eventHandler = (evt) => {
  3179. document.removeEventListener(EVENT_KEY_ON_REGISTRY_READY, eventHandler, false);
  3180. const f = callback;
  3181. callback = null;
  3182. eventHandler = null;
  3183. f();
  3184. };
  3185. document.addEventListener(EVENT_KEY_ON_REGISTRY_READY, eventHandler, false);
  3186. } else {
  3187. callback();
  3188. }
  3189. });
  3190.  
  3191. const _retrieveCE = async (nodeName) => {
  3192. try {
  3193. isCustomElementsProvided || (await promiseForCustomYtElementsReady);
  3194. await customElements.whenDefined(nodeName);
  3195. } catch (e) {
  3196. console.warn(e);
  3197. }
  3198. }
  3199.  
  3200.  
  3201. const retrieveCE = async (nodeName) => {
  3202. try {
  3203. isCustomElementsProvided || (await promiseForCustomYtElementsReady);
  3204. await customElements.whenDefined(nodeName);
  3205. const dummy = document.querySelector(nodeName) || document.createElement(nodeName);
  3206. const cProto = insp(dummy).constructor.prototype;
  3207. return cProto;
  3208. } catch (e) {
  3209. console.warn(e);
  3210. }
  3211. }
  3212.  
  3213.  
  3214. const moOverallRes = {
  3215. _yt_playerProvided: () => (((window || 0)._yt_player || 0) || 0)
  3216. }
  3217.  
  3218. const moOverall = new MutationObserver(() => {
  3219.  
  3220. if (typeof moOverallRes._yt_playerProvided === 'function') {
  3221. const r = moOverallRes._yt_playerProvided();
  3222. if (r) {
  3223. moOverallRes._yt_playerProvided = r;
  3224. eventMap._yt_playerProvided();
  3225. }
  3226. }
  3227. });
  3228.  
  3229. moOverall.observe(document, { subtree: true, childList: true });
  3230.  
  3231. document.addEventListener('yt-navigate-finish', eventMap['yt-navigate-finish'], false);
  3232.  
  3233. document.addEventListener('animationstart', evt => {
  3234. const f = eventMap[evt.animationName];
  3235. if (typeof f === 'function') f(evt.target);
  3236. }, capturePassive);
  3237.  
  3238. console.log('hi122')
  3239.  
  3240.  
  3241. mLoaded.flag |= 1;
  3242. document.documentElement.setAttribute111('tabview-loaded', mLoaded.makeString());
  3243.  
  3244. promiseForCustomYtElementsReady.then(eventMap['ceHack']).catch(console.warn);
  3245.  
  3246.  
  3247. executionFinished = 1;
  3248.  
  3249.  
  3250.  
  3251. } catch (e) {
  3252. console.log('error 0xF491');
  3253. console.error(e);
  3254. }
  3255.  
  3256. };
  3257. const styles = {
  3258. 'main': `
  3259.  
  3260.  
  3261. @keyframes relatedElementProvided {
  3262. 0% {
  3263. background-position-x: 3px;
  3264. }
  3265. 100% {
  3266. background-position-x: 4px;
  3267. }
  3268. }
  3269. html[tabview-loaded="icp"] #related.ytd-watch-flexy {
  3270. animation: relatedElementProvided 1ms linear 0s 1 normal forwards;
  3271. }
  3272. html[tabview-loaded="icp"] #right-tabs #related.ytd-watch-flexy,
  3273. html[tabview-loaded="icp"] [hidden] #related.ytd-watch-flexy {
  3274. animation: initial;
  3275. }
  3276.  
  3277.  
  3278.  
  3279. html[tabview-loaded="icp"] #right-tabs ytd-expander#expander,
  3280. html[tabview-loaded="icp"] [hidden] ytd-expander#expander,
  3281. html[tabview-loaded="icp"] ytd-comments ytd-expander#expander{
  3282. animation: initial;
  3283. }
  3284.  
  3285.  
  3286.  
  3287.  
  3288.  
  3289. #secondary.ytd-watch-flexy {
  3290. position: relative;
  3291. }
  3292.  
  3293. #secondary-inner.style-scope.ytd-watch-flexy {
  3294. height: 100%;
  3295. }
  3296.  
  3297. /*
  3298. ytd-watch-flexy[tyt-tab^="#"] #secondary-inner.style-scope.ytd-watch-flexy::after {
  3299. display: block;
  3300. content:'';
  3301. height: 100vh;
  3302. }
  3303. */
  3304.  
  3305. secondary-wrapper {
  3306. display: flex;
  3307. flex-direction: column;
  3308. flex-wrap: nowrap;
  3309. box-sizing: border-box;
  3310. padding: 0;
  3311. margin: 0;
  3312. border: 0;
  3313. height: 100%;
  3314. max-height: calc(100vh - var(--ytd-toolbar-height, 56px));
  3315. position: absolute;
  3316. top: 0;
  3317. right: 0;
  3318. left: 0;
  3319. contain: strict;
  3320.  
  3321. /* border-right: var(--ytd-margin-6x) solid transparent; */
  3322. padding-top: var(--ytd-margin-6x);
  3323. padding-right: var(--ytd-margin-6x);
  3324. padding-bottom: var(--ytd-margin-6x);
  3325. }
  3326.  
  3327.  
  3328.  
  3329. #right-tabs {
  3330. position: relative;
  3331. display: flex;
  3332. padding: 0;
  3333. margin: 0;
  3334. flex-grow: 1;
  3335. flex-direction: column;
  3336. }
  3337.  
  3338. [tyt-tab=""] #right-tabs{
  3339. flex-grow: 0;
  3340. }
  3341.  
  3342. [tyt-tab=""] #right-tabs .tab-content{
  3343. border: 0;
  3344. }
  3345.  
  3346. #right-tabs .tab-content {
  3347. flex-grow: 1;
  3348. }
  3349.  
  3350. ytd-watch-flexy[hide-default-text-inline-expander] #primary.style-scope.ytd-watch-flexy ytd-text-inline-expander {
  3351. display: none;
  3352. }
  3353.  
  3354.  
  3355. ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden {
  3356. --comment-pre-load-sizing: 90px;
  3357. visibility: collapse;
  3358. z-index: -1;
  3359. position: fixed !important;
  3360. left: 2px;
  3361. top: 2px;
  3362. width: var(--comment-pre-load-sizing) !important;
  3363. height: var(--comment-pre-load-sizing) !important;
  3364. display: block !important;
  3365. pointer-events: none !important;
  3366. overflow:hidden;
  3367. contain:strict;
  3368. border: 0;
  3369. margin: 0;
  3370. padding: 0;
  3371. }
  3372.  
  3373. ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments > * {
  3374. display: none !important;
  3375. }
  3376.  
  3377. ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments > ytd-item-section-renderer#sections {
  3378. display: block !important;
  3379. overflow:hidden;
  3380. height: var(--comment-pre-load-sizing);
  3381. width: var(--comment-pre-load-sizing);
  3382. contain:strict;
  3383. border: 0;
  3384. margin: 0;
  3385. padding: 0;
  3386. }
  3387.  
  3388. ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments > ytd-item-section-renderer#sections > * {
  3389. display: none !important;
  3390. }
  3391. ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments > ytd-item-section-renderer#sections > #contents {
  3392. display: flex !important;
  3393. flex-direction: row;
  3394. gap: 60px;
  3395. overflow:hidden;
  3396. height: var(--comment-pre-load-sizing);
  3397. width: var(--comment-pre-load-sizing);
  3398. contain:strict;
  3399. border: 0;
  3400. margin: 0;
  3401. padding: 0;
  3402. }
  3403. ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments > ytd-item-section-renderer#sections > #contents > * {
  3404. display: block !important;
  3405. visibility: collapse !important;
  3406. overflow: hidden;
  3407. margin: calc(2 * var(--comment-pre-load-sizing)) !important;
  3408. width: var(--comment-pre-load-sizing);
  3409. height: var(--comment-pre-load-sizing);
  3410. box-sizing: content-box;
  3411. contain:strict;
  3412. border: 0;
  3413. padding: 0;
  3414. }
  3415.  
  3416. ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments > ytd-item-section-renderer#sections > #contents > *:empty {
  3417. display: none !important;
  3418. visibility: collapse !important;
  3419. overflow: hidden;
  3420. margin: 0px !important;
  3421. width: 0px;
  3422. height: 0px;
  3423. box-sizing: content-box;
  3424. contain:strict;
  3425. }
  3426. ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments > ytd-item-section-renderer#sections > #contents > ytd-continuation-item-renderer {
  3427. display: block !important;
  3428. visibility: collapse !important;
  3429. overflow: initial;
  3430. margin: 0px !important;
  3431. width: 1px;
  3432. height: 1px;
  3433. box-sizing: initial;
  3434. contain:strict;
  3435. }
  3436.  
  3437. ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments > ytd-item-section-renderer#sections > #contents > * > * {
  3438. display: none !important;
  3439. visibility: collapse !important;
  3440. overflow: hidden;
  3441. margin: 0px !important;
  3442. width: 0px;
  3443. height: 0px;
  3444. box-sizing: content-box;
  3445. contain:strict;
  3446. }
  3447.  
  3448.  
  3449. #right-tabs #material-tabs {
  3450. position: relative;
  3451. display: flex;
  3452. padding: 0;
  3453. /*outline: 1px solid var(--tyt-x-border-color);*/
  3454. /*outline: 1px solid var(--ytd-searchbox-legacy-border-color);*/
  3455. /* 2023/05/05 chaged from outline to border */
  3456. border: 1px solid var(--ytd-searchbox-legacy-border-color);
  3457. /* border-bottom:0; */
  3458. }
  3459.  
  3460. ytd-watch-flexy[flexy]:not([is-two-columns_]) #right-tabs #material-tabs {
  3461. outline: 0;
  3462. }
  3463.  
  3464. #right-tabs #material-tabs a.tab-btn[tyt-tab-content] > * {
  3465. pointer-events: none;
  3466. }
  3467.  
  3468. #right-tabs #material-tabs a.tab-btn[tyt-tab-content] > .font-size-right {
  3469. pointer-events: initial;
  3470. display: none; /* not yet supported */
  3471. }
  3472.  
  3473. ytd-watch-flexy #right-tabs .tab-content {
  3474. padding: 0;
  3475. box-sizing: border-box;
  3476. display: block;
  3477. /*--yt-spec-brand-background-primary:var(--yt-spec-general-background-a);*/
  3478. /*outline: 1px solid var(--tyt-x-border-color);*/
  3479. /* outline: 1px solid var(--ytd-searchbox-legacy-border-color); */
  3480. /* 2023/05/05 chaged from outline to border */
  3481. border: 1px solid var(--ytd-searchbox-legacy-border-color);
  3482. border-top:0;
  3483. position: relative;
  3484. top: 0;
  3485. display: flex;
  3486. flex-direction: row;
  3487. overflow: hidden;
  3488. }
  3489.  
  3490. ytd-watch-flexy[is-two-columns_] #right-tabs .tab-content {
  3491. /*
  3492. height: var(--tyt-tabs-content-height);
  3493. contain: size layout paint;
  3494. */
  3495. }
  3496.  
  3497. ytd-watch-flexy:not([is-two-columns_]) #right-tabs .tab-content {
  3498. height: 100%;
  3499. }
  3500.  
  3501. ytd-watch-flexy #right-tabs .tab-content-cld {
  3502. box-sizing: border-box;
  3503. position: relative;
  3504. display: block;
  3505. width: 100%;
  3506. overflow: auto;
  3507. --tab-content-padding: var(--ytd-margin-4x);
  3508. padding: var(--tab-content-padding);
  3509. contain: layout paint;
  3510.  
  3511. }
  3512.  
  3513. .tab-content-cld,
  3514. #right-tabs,
  3515. .tab-content {
  3516. transition: none;
  3517. animation: none;
  3518. }
  3519.  
  3520. ytd-watch-flexy[is-two-columns_] #right-tabs .tab-content-cld {
  3521. height: 100%;
  3522. width: 100%;
  3523. contain: size layout paint style;
  3524. position: absolute;
  3525. }
  3526.  
  3527. ytd-watch-flexy #right-tabs .tab-content-cld.tab-content-hidden {
  3528. display: none;
  3529. width: 100%;
  3530. /* width fix */
  3531. contain: size layout paint style;
  3532. }
  3533.  
  3534.  
  3535.  
  3536.  
  3537.  
  3538.  
  3539. @supports (color: var(--tabview-tab-btn-define)) {
  3540.  
  3541. /* give background color; otherwise it will be transparent in dark mode, single column*/
  3542. ytd-watch-flexy #right-tabs .tab-btn {
  3543. background: var(--yt-spec-general-background-a);
  3544. }
  3545.  
  3546. html {
  3547. --tyt-tab-btn-flex-grow: 1;
  3548. --tyt-tab-btn-flex-basis: 0%;
  3549. --tyt-tab-bar-color-1-def: #ff4533;
  3550. --tyt-tab-bar-color-2-def: var(--yt-brand-light-red);
  3551. --tyt-tab-bar-color-1:var(--main-color, var(--tyt-tab-bar-color-1-def));
  3552. --tyt-tab-bar-color-2:var(--main-color, var(--tyt-tab-bar-color-2-def));
  3553. }
  3554.  
  3555. ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content] {
  3556.  
  3557. flex-grow: 1;
  3558. flex-shrink: 1;
  3559. flex-basis: 0%;
  3560. flex-grow: var(--tyt-tab-btn-flex-grow);
  3561. flex-basis: var(--tyt-tab-btn-flex-basis);
  3562. position: relative;
  3563. display: inline-block;
  3564. text-decoration: none;
  3565. text-transform: uppercase;
  3566. --tyt-tab-btn-color: var(--yt-spec-text-secondary);
  3567. color: var(--tyt-tab-btn-color);
  3568. text-align: center;
  3569. padding: 14px 8px 10px;
  3570. border: 0;
  3571. border-bottom: 4px solid transparent;
  3572. font-weight: 500;
  3573. font-size: 12px;
  3574. line-height: 18px;
  3575. cursor: pointer;
  3576. transition: border 200ms linear 100ms;
  3577. background-color: var(--ytd-searchbox-legacy-button-color);
  3578. text-transform: var(--yt-button-text-transform, inherit);
  3579. user-select: none !important;
  3580.  
  3581. overflow: hidden;
  3582. white-space: nowrap;
  3583. /*text-overflow: ellipsis;*/
  3584. text-overflow: clip;
  3585.  
  3586. }
  3587.  
  3588.  
  3589. /* .tab-btn[tyt-tab-content] */
  3590.  
  3591. ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content]>svg {
  3592. height: 18px;
  3593. padding-right: 0px;
  3594. vertical-align: bottom;
  3595. opacity: .5;
  3596. margin-right: 0px;
  3597. color: var(--yt-button-color, inherit);
  3598. fill: var(--iron-icon-fill-color, currentcolor);
  3599. stroke: var(--iron-icon-stroke-color, none);
  3600. }
  3601.  
  3602. ytd-watch-flexy #right-tabs .tab-btn {
  3603. --tabview-btn-txt-ml: 8px;
  3604. }
  3605. ytd-watch-flexy[tyt-comment-disabled] #right-tabs .tab-btn[tyt-tab-content="#tab-comments"] {
  3606. --tabview-btn-txt-ml: 0px;
  3607. }
  3608.  
  3609. ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content]>svg+span {
  3610. margin-left: var(--tabview-btn-txt-ml);
  3611. }
  3612.  
  3613. ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content] svg {
  3614. pointer-events: none;
  3615. }
  3616.  
  3617. ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content].active {
  3618. font-weight: 500;
  3619. outline: 0;
  3620. --tyt-tab-btn-color: var(--yt-spec-text-primary);
  3621. background-color: var(--ytd-searchbox-legacy-button-focus-color);
  3622. border-bottom: 4px var(--tyt-tab-bar-color-1) solid;
  3623. border-bottom-color: var(--tyt-tab-bar-color-2);
  3624. }
  3625.  
  3626. ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content].active svg {
  3627. opacity: .9
  3628. }
  3629.  
  3630. ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content]:not(.active):hover {
  3631. background-color: var(--ytd-searchbox-legacy-button-hover-color);
  3632. --tyt-tab-btn-color: var(--yt-spec-text-primary);
  3633. }
  3634.  
  3635. ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content]:not(.active):hover svg {
  3636. opacity: .9
  3637. }
  3638.  
  3639. ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content] {
  3640. user-select: none !important;
  3641. }
  3642.  
  3643. ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content].tab-btn-hidden {
  3644. display: none;
  3645. }
  3646.  
  3647. ytd-watch-flexy[tyt-comment-disabled] #right-tabs .tab-btn[tyt-tab-content="#tab-comments"],
  3648. ytd-watch-flexy[tyt-comment-disabled] #right-tabs .tab-btn[tyt-tab-content="#tab-comments"]:hover {
  3649. --tyt-tab-btn-color: var(--yt-spec-icon-disabled);
  3650. }
  3651.  
  3652. ytd-watch-flexy[tyt-comment-disabled] #right-tabs .tab-btn[tyt-tab-content="#tab-comments"] span#tyt-cm-count:empty{
  3653. display:none;
  3654. }
  3655.  
  3656.  
  3657. ytd-watch-flexy #right-tabs .tab-btn span#tyt-cm-count:empty::after {
  3658. display: inline-block;
  3659. width: 4em;
  3660. text-align: left;
  3661. font-size: inherit;
  3662. color: currentColor;
  3663. transform: scaleX(0.8);
  3664. }
  3665.  
  3666. }
  3667.  
  3668. @supports (color: var(--tyt-cm-count-define)){
  3669.  
  3670. ytd-watch-flexy {
  3671. --tyt-x-loading-content-letter-spacing: 2px;
  3672. }
  3673.  
  3674. html {
  3675. --tabview-text-loading: "Loading";
  3676. --tabview-text-fetching: "Fetching";
  3677. --tabview-panel-loading: var(--tabview-text-loading);
  3678. }
  3679.  
  3680. html:lang(ja) {
  3681. --tabview-text-loading: "読み込み中";
  3682. --tabview-text-fetching: "フェッチ..";
  3683. }
  3684.  
  3685. html:lang(ko) {
  3686. --tabview-text-loading: "로딩..";
  3687. --tabview-text-fetching: "가져오기..";
  3688. }
  3689.  
  3690. html:lang(zh-Hant) {
  3691. /* 資訊科技名詞 @ https://terms.naer.edu.tw/ */
  3692. --tabview-text-loading: "載入中";
  3693. --tabview-text-fetching: "擷取中";
  3694. }
  3695.  
  3696. html:lang(zh-Hans) {
  3697. --tabview-text-loading: "加载中";
  3698. --tabview-text-fetching: "抓取中";
  3699. }
  3700.  
  3701. html:lang(ru) {
  3702. --tabview-text-loading: "Загрузка";
  3703. --tabview-text-fetching: "Получение";
  3704. }
  3705.  
  3706. ytd-watch-flexy #right-tabs .tab-btn span#tyt-cm-count:empty::after {
  3707. content: var(--tabview-text-loading);
  3708. letter-spacing: var(--tyt-x-loading-content-letter-spacing);
  3709. }
  3710.  
  3711. }
  3712.  
  3713.  
  3714. @supports (color: var(--tabview-font-size-btn-define)) {
  3715.  
  3716. .font-size-right {
  3717. display: inline-flex;
  3718. flex-direction: column;
  3719. position: absolute;
  3720. right: 0;
  3721. top: 0;
  3722. bottom: 0;
  3723. width: 16px;
  3724. padding: 4px 0;
  3725. justify-content: space-evenly;
  3726. align-content: space-evenly;
  3727. pointer-events: none;
  3728. }
  3729.  
  3730. html body ytd-watch-flexy.style-scope .font-size-btn {
  3731. user-select: none !important;
  3732. }
  3733.  
  3734. .font-size-btn {
  3735. --tyt-font-size-btn-display: none;
  3736. display: var(--tyt-font-size-btn-display, none);
  3737. /* hide zoom btn for FireFox */
  3738. width: 12px;
  3739. height: 12px;
  3740. color: var(--yt-spec-text-secondary);
  3741. background-color: var(--yt-spec-badge-chip-background);
  3742. box-sizing: border-box;
  3743. cursor: pointer;
  3744. transform-origin: left top;
  3745. margin: 0;
  3746. padding: 0;
  3747. position: relative;
  3748. font-family: 'Menlo', 'Lucida Console', 'Monaco', 'Consolas', monospace;
  3749. line-height: 100%;
  3750. font-weight: 900;
  3751. transition: background-color 90ms linear, color 90ms linear;
  3752. pointer-events: all;
  3753. }
  3754.  
  3755. .font-size-btn:hover {
  3756. background-color: var(--yt-spec-text-primary);
  3757. color: var(--yt-spec-general-background-a);
  3758. }
  3759.  
  3760. @supports (zoom: 0.5) {
  3761.  
  3762. .tab-btn .font-size-btn {
  3763. --tyt-font-size-btn-display: none;
  3764. }
  3765.  
  3766. .tab-btn.active:hover .font-size-btn {
  3767. --tyt-font-size-btn-display: inline-block;
  3768. }
  3769.  
  3770. }
  3771.  
  3772. }
  3773.  
  3774.  
  3775. body ytd-watch-flexy:not([is-two-columns_]) #columns.ytd-watch-flexy{
  3776. flex-direction: column;
  3777. }
  3778.  
  3779. body ytd-watch-flexy:not([is-two-columns_]) #secondary.ytd-watch-flexy {
  3780. display: block;
  3781. width: 100%;
  3782. box-sizing: border-box;
  3783. }
  3784.  
  3785. body ytd-watch-flexy:not([is-two-columns_]) #secondary.ytd-watch-flexy secondary-wrapper {
  3786.  
  3787. padding-left: var(--ytd-margin-6x);
  3788. contain: content;
  3789. height: initial;
  3790.  
  3791.  
  3792. }
  3793.  
  3794. body ytd-watch-flexy:not([is-two-columns_]) #secondary.ytd-watch-flexy secondary-wrapper #right-tabs {
  3795. overflow: auto;
  3796.  
  3797. }
  3798.  
  3799. [tyt-chat="+"] secondary-wrapper > [tyt-chat-container]{
  3800. flex-grow: 1;
  3801. flex-shrink: 0;
  3802. display: flex;
  3803. flex-direction: column;
  3804. }
  3805.  
  3806. [tyt-chat="+"] secondary-wrapper > [tyt-chat-container] > #chat{
  3807. flex-grow: 1;
  3808. }
  3809.  
  3810. ytd-watch-flexy[is-two-columns_]:not([theater]) #columns.style-scope.ytd-watch-flexy {
  3811. min-height: calc(100vh - var(--ytd-toolbar-height, 56px));
  3812. }
  3813.  
  3814. ytd-watch-flexy[is-two-columns_] ytd-live-chat-frame#chat {
  3815. min-height: initial !important;
  3816. height: initial !important;
  3817. }
  3818.  
  3819. ytd-watch-flexy[tyt-tab^="#"]:not([is-two-columns_]):not([tyt-chat="+"]) #right-tabs {
  3820. min-height: var(--ytd-watch-flexy-chat-max-height)
  3821. }
  3822.  
  3823. body ytd-watch-flexy:not([is-two-columns_]) #chat.ytd-watch-flexy {
  3824. margin-top: 0;
  3825.  
  3826. }
  3827.  
  3828. body ytd-watch-flexy:not([is-two-columns_]) ytd-watch-metadata.ytd-watch-flexy {
  3829. margin-bottom: 0;
  3830. }
  3831.  
  3832. ytd-watch-metadata.ytd-watch-flexy ytd-metadata-row-container-renderer {
  3833. display: none;
  3834. }
  3835.  
  3836. /*
  3837. #tab-info #items.style-scope.ytd-video-description-infocards-section-renderer {
  3838.  
  3839. display: inline-flex;
  3840. flex-wrap: wrap;
  3841. row-gap: 8px;
  3842. }
  3843.  
  3844. #tab-info #left-arrow-container.style-scope.ytd-video-description-infocards-section-renderer,
  3845. #tab-info #left-arrow.style-scope.ytd-video-description-infocards-section-renderer,
  3846. #tab-info #right-arrow-container.style-scope.ytd-video-description-infocards-section-renderer,
  3847. #tab-info #right-arrow.style-scope.ytd-video-description-infocards-section-renderer {
  3848. visibility: collapse;
  3849. }
  3850. */
  3851.  
  3852. /*
  3853. #tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer > #left-arrow-container.ytd-video-description-infocards-section-renderer{
  3854. left:0;
  3855. }
  3856. #tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer > #right-arrow-container.ytd-video-description-infocards-section-renderer{
  3857. right:0;
  3858. }
  3859.  
  3860. #tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer > #scroll-container.ytd-video-description-infocards-section-renderer{
  3861. margin: 0 32px;
  3862. }
  3863. */
  3864.  
  3865.  
  3866. #tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer > #left-arrow-container.ytd-video-description-infocards-section-renderer > #left-arrow{
  3867. border: 6px solid transparent;
  3868. opacity: 0.65;
  3869. }
  3870. #tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer > #right-arrow-container.ytd-video-description-infocards-section-renderer >#right-arrow{
  3871. border: 6px solid transparent;
  3872. opacity: 0.65;
  3873. }
  3874.  
  3875.  
  3876.  
  3877. #tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer > #left-arrow-container.ytd-video-description-infocards-section-renderer > #left-arrow:hover{
  3878. opacity: 1;
  3879. }
  3880. #tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer > #right-arrow-container.ytd-video-description-infocards-section-renderer >#right-arrow:hover{
  3881.  
  3882. opacity: 1;
  3883. }
  3884.  
  3885.  
  3886. #tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer > div#left-arrow-container::before {
  3887. content: '';
  3888. background: transparent;
  3889. width: 40px;
  3890. display: block;
  3891. height: 40px;
  3892. position: absolute;
  3893. left: -20px;
  3894. top: 0;
  3895. z-index: -1;
  3896. }
  3897. #tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer > div#right-arrow-container::before {
  3898. content: '';
  3899. background: transparent;
  3900. width: 40px;
  3901. display: block;
  3902. height: 40px;
  3903. position: absolute;
  3904. right: -20px;
  3905. top: 0;
  3906. z-index: -1;
  3907. }
  3908.  
  3909.  
  3910.  
  3911. body ytd-watch-flexy[is-two-columns_][tyt-egm-panel_] #columns.style-scope.ytd-watch-flexy #panels.style-scope.ytd-watch-flexy{
  3912. flex-grow: 1;
  3913. flex-shrink: 0;
  3914. display: flex;
  3915. flex-direction: column;
  3916. }
  3917.  
  3918.  
  3919. 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"]{
  3920.  
  3921. height: initial;
  3922. max-height: initial;
  3923. min-height: initial;
  3924. flex-grow: 1;
  3925. flex-shrink: 0;
  3926. display: flex;
  3927. flex-direction: column;
  3928.  
  3929. }
  3930.  
  3931.  
  3932. 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{
  3933.  
  3934. /*
  3935. height: initial;
  3936. max-height: initial;
  3937. min-height: initial;
  3938. flex-grow: 1;
  3939. flex-shrink: 0;
  3940. margin: 0;
  3941. padding: 0;
  3942. border: 0;
  3943. display: flex;
  3944. flex-direction: column;
  3945. */
  3946. }
  3947.  
  3948.  
  3949. 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]{
  3950.  
  3951. /*
  3952. height: initial;
  3953. max-height: initial;
  3954. min-height: initial;
  3955. flex-grow: 1;
  3956. flex-shrink: 0;
  3957. margin: 0;
  3958. padding: 0;
  3959. border: 0;
  3960. */
  3961. }
  3962.  
  3963.  
  3964. secondary-wrapper [visibility="ENGAGEMENT_PANEL_VISIBILITY_EXPANDED"] ytd-transcript-renderer:not(:empty),
  3965. secondary-wrapper [visibility="ENGAGEMENT_PANEL_VISIBILITY_EXPANDED"] #body.ytd-transcript-renderer:not(:empty),
  3966. secondary-wrapper [visibility="ENGAGEMENT_PANEL_VISIBILITY_EXPANDED"] #content.ytd-transcript-renderer:not(:empty){
  3967.  
  3968. flex-grow: 1;
  3969. height: initial;
  3970. max-height: initial;
  3971. min-height: initial;
  3972. }
  3973.  
  3974. secondary-wrapper #content.ytd-engagement-panel-section-list-renderer{
  3975.  
  3976. position: relative;
  3977. }
  3978.  
  3979. @supports (contain: strict) {
  3980.  
  3981. secondary-wrapper #content.ytd-engagement-panel-section-list-renderer > [panel-target-id]:only-child{
  3982.  
  3983. contain: strict;
  3984. max-height: 100%;
  3985. }
  3986.  
  3987. }
  3988.  
  3989.  
  3990. @supports not (contain: strict) {
  3991.  
  3992. secondary-wrapper #content.ytd-engagement-panel-section-list-renderer > [panel-target-id]:only-child{
  3993.  
  3994. position: absolute;
  3995. max-height: 100%;
  3996. }
  3997.  
  3998. }
  3999.  
  4000.  
  4001. body ytd-watch-flexy[theater] #secondary.ytd-watch-flexy {
  4002. margin-top: 0;
  4003. padding-top: var(--ytd-margin-2x);
  4004. }
  4005.  
  4006. body ytd-watch-flexy[theater] secondary-wrapper {
  4007. padding-top: var(--ytd-margin-2x);
  4008. }
  4009.  
  4010. body ytd-watch-flexy[theater] #chat.ytd-watch-flexy{
  4011.  
  4012. margin-bottom: var(--ytd-margin-2x);
  4013. }
  4014.  
  4015. #tab-comments ytd-comments#comments [field-of-cm-count]{
  4016. margin-top:0;
  4017. }
  4018. /*
  4019.  
  4020. #tab-info #social-links.ytd-video-description-infocards-section-renderer {
  4021. margin-bottom:0;
  4022. }
  4023. #tab-info #social-links.ytd-video-description-infocards-section-renderer ~ #infocards-section {
  4024. margin-top: 16px;
  4025. }
  4026.  
  4027. #tab-info ytd-structured-description-content-renderer ytd-video-description-infocards-section-renderer.ytd-structured-description-content-renderer{
  4028. padding-bottom:0;
  4029. }
  4030. */
  4031.  
  4032. #tab-info [class]:last-child {
  4033. margin-bottom:0;
  4034. padding-bottom:0;
  4035. }
  4036.  
  4037.  
  4038. #tab-info ytd-rich-metadata-row-renderer ytd-rich-metadata-renderer {
  4039. max-width: initial;
  4040. }
  4041.  
  4042. ytd-watch-flexy[is-two-columns_] secondary-wrapper #chat.ytd-watch-flexy {
  4043. margin-bottom: var(--ytd-margin-3x);
  4044. }
  4045.  
  4046. ytd-watch-flexy[tyt-tab] tp-yt-paper-tooltip {
  4047. white-space: nowrap;
  4048. contain: content;
  4049. }
  4050.  
  4051.  
  4052. ytd-watch-info-text tp-yt-paper-tooltip.style-scope.ytd-watch-info-text{
  4053. margin-bottom: -300px;
  4054. margin-top: -96px;
  4055. }
  4056.  
  4057.  
  4058. [hide-default-text-inline-expander] #bottom-row #description.ytd-watch-metadata {
  4059. font-size: 1.2rem;
  4060. line-height: 1.8rem;
  4061.  
  4062. }
  4063.  
  4064. [hide-default-text-inline-expander] #bottom-row #description.ytd-watch-metadata yt-animated-rolling-number{
  4065. font-size: inherit;
  4066. }
  4067.  
  4068.  
  4069. [hide-default-text-inline-expander] #bottom-row #description.ytd-watch-metadata #info-container.style-scope.ytd-watch-info-text{
  4070. align-items: center;
  4071. }
  4072.  
  4073. [hide-default-text-inline-expander] #bottom-row #description.ytd-watch-metadata.item.ytd-watch-metadata{
  4074. margin-top: 6px;
  4075. }
  4076.  
  4077. [hide-default-text-inline-expander] #bottom-row #description.ytd-watch-metadata > #description-inner.ytd-watch-metadata{
  4078.  
  4079. margin: 6px 12px;
  4080.  
  4081. }
  4082.  
  4083. [hide-default-text-inline-expander] ytd-watch-metadata[title-headline-xs] h1.ytd-watch-metadata {
  4084.  
  4085. font-size: 1.8rem;
  4086. }
  4087.  
  4088.  
  4089.  
  4090. ytd-watch-flexy[is-two-columns_][hide-default-text-inline-expander] #below.style-scope.ytd-watch-flexy ytd-merch-shelf-renderer{
  4091. padding: 0;
  4092. border: 0;
  4093. margin:0;
  4094. }
  4095.  
  4096.  
  4097. ytd-watch-flexy[is-two-columns_][hide-default-text-inline-expander] #below.style-scope.ytd-watch-flexy ytd-watch-metadata.ytd-watch-flexy {
  4098. margin-bottom: 6px;
  4099. }
  4100.  
  4101. #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 {
  4102. flex-shrink:0;
  4103. }
  4104.  
  4105.  
  4106. #tab-info yt-video-attribute-view-model .yt-video-attribute-view-model__overflow-menu{
  4107. background: var(--yt-emoji-picker-category-background-color);
  4108. border-radius: 99px;
  4109. }
  4110.  
  4111. #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{
  4112.  
  4113. max-height: 128px;
  4114. }
  4115.  
  4116. #tab-info yt-video-attribute-view-model .yt-video-attribute-view-model--image-large .yt-video-attribute-view-model__hero-section{
  4117.  
  4118. max-width: 128px;
  4119. }
  4120.  
  4121. #tab-info ytd-reel-shelf-renderer #items.yt-horizontal-list-renderer ytd-reel-item-renderer.yt-horizontal-list-renderer {
  4122. max-width: 142px;
  4123. }
  4124.  
  4125. ytd-watch-info-text#ytd-watch-info-text.style-scope.ytd-watch-metadata #view-count.style-scope.ytd-watch-info-text{
  4126. align-items: center;
  4127. }
  4128.  
  4129.  
  4130. ytd-watch-info-text#ytd-watch-info-text.style-scope.ytd-watch-metadata #date-text.style-scope.ytd-watch-info-text{
  4131. align-items: center;
  4132. }
  4133.  
  4134.  
  4135. ytd-watch-info-text:not([detailed]) #info.ytd-watch-info-text a.yt-simple-endpoint.yt-formatted-string {
  4136.  
  4137. pointer-events: none;
  4138. }
  4139.  
  4140.  
  4141. body ytd-app > ytd-popup-container > tp-yt-iron-dropdown > #contentWrapper > [slot="dropdown-content"] {
  4142.  
  4143. backdrop-filter: none ;
  4144. }
  4145.  
  4146. #tab-info [tyt-clone-refresh-count] {
  4147. overflow: visible !important;
  4148. }
  4149.  
  4150. /* css unknown sizing bug */
  4151. #tab-info #items.ytd-horizontal-card-list-renderer yt-video-attribute-view-model.ytd-horizontal-card-list-renderer {
  4152. contain: layout;
  4153. }
  4154.  
  4155.  
  4156. /* https://www.youtube.com/watch?v=2h3pbdTPu6Q */
  4157.  
  4158. #tab-info #thumbnail-container.ytd-structured-description-channel-lockup-renderer {
  4159. flex-shrink: 0;
  4160. }
  4161. #tab-info ytd-media-lockup-renderer[is-compact] #thumbnail-container.ytd-media-lockup-renderer {
  4162. flex-shrink: 0;
  4163. }
  4164.  
  4165. /* https://www.youtube.com/watch?v=cV2gBU6hKfY */
  4166. secondary-wrapper ytd-donation-unavailable-renderer{
  4167. --ytd-margin-6x:var(--ytd-margin-2x);
  4168. --ytd-margin-5x:var(--ytd-margin-2x);
  4169. --ytd-margin-4x:var(--ytd-margin-2x);
  4170. --ytd-margin-3x:var(--ytd-margin-2x);
  4171. }
  4172.  
  4173.  
  4174. `
  4175. };
  4176. (async () => {
  4177. const communicationKey = `ck-${Date.now()}-${Math.floor(Math.random() * 314159265359 + 314159265359).toString(36)}`;
  4178.  
  4179. /** @type {globalThis.PromiseConstructor} */
  4180. const Promise = (async () => { })().constructor; // YouTube hacks Promise in WaterFox Classic and "Promise.resolve(0)" nevers resolve.
  4181.  
  4182. if (!document.documentElement) {
  4183. await Promise.resolve(0);
  4184. while (!document.documentElement) {
  4185. await new Promise(resolve => nextBrowserTick(resolve)).then().catch(console.warn);
  4186. }
  4187. }
  4188. const sourceURL = 'debug://tabview-youtube/tabview.execution.js'
  4189. const textContent = `(${executionScript})("${communicationKey}");${"\n\n"}//# sourceURL=${sourceURL}${'\n'}`
  4190.  
  4191. // const isMyScriptInChromeRuntime = () => typeof GM === 'undefined' && typeof ((((window || 0).chrome || 0).runtime || 0).getURL) === 'function';
  4192. // const isGMAvailable = () => typeof GM !== 'undefined' && !isMyScriptInChromeRuntime();
  4193.  
  4194. // if(isMyScriptInChromeRuntime()){
  4195. // let button = document.createElement('button');
  4196. // button.setAttribute('onclick', textContent);
  4197. // button.click();
  4198. // button = null;
  4199. // }else{
  4200. // GM_addElement('script', {
  4201. // textContent: textContent
  4202. // });
  4203. // }
  4204.  
  4205. let button = document.createElement('button');
  4206. button.setAttribute('onclick', createHTML(textContent));
  4207. button.click();
  4208. button = null;
  4209.  
  4210.  
  4211. let style = document.createElement('style');
  4212. const sourceURLMainCSS = 'debug://tabview-youtube/tabview.main.css';
  4213. style.textContent = `${styles['main'].trim()}${'\n\n'}/*# sourceURL=${sourceURLMainCSS} */${'\n'}`;
  4214. document.documentElement.appendChild(style);
  4215.  
  4216.  
  4217. })();