Youtubeᴾˡᵘˢ(油管)超級助手 - 視頻下載 & 🚫去廣告 & 布局優化,使用更舒服

這個腳本是一個增強器,用於提升您的YouTube觀看體驗!包含新功能和新佈局。介紹:1.優化的影片詳細頁面介面。2.截圖。3.深色/淺色主題切換。4.影片快轉。等等。

  1. // ==UserScript==
  2. // @name Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  3. // @name:zh-CN Youtubeᴾˡᵘˢ(油管)超级助手 - 视频下载 & 🚫去广告 & 布局优化,使用更舒服
  4. // @name:zh-TW Youtubeᴾˡᵘˢ(油管)超級助手 - 視頻下載 & 🚫去廣告 & 布局優化,使用更舒服
  5. // @name:ar Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  6. // @name:bg Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  7. // @name:cs Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  8. // @name:da Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  9. // @name:de Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  10. // @name:el Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  11. // @name:en Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  12. // @name:eo Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  13. // @name:es Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  14. // @name:es-419 Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  15. // @name:fi Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  16. // @name:fr Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  17. // @name:fr-CA Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  18. // @name:he Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  19. // @name:hr Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  20. // @name:hu Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  21. // @name:id Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!))
  22. // @name:it Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  23. // @name:ja Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  24. // @name:ka Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  25. // @name:ko Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  26. // @name:nb Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  27. // @name:nl Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  28. // @name:pl Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  29. // @name:pt-BR Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  30. // @name:ro Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  31. // @name:ru Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  32. // @name:sv Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  33. // @name:th Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  34. // @name:tr Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  35. // @name:uk Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  36. // @name:ug Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  37. // @name:vi Youtubeᴾˡᵘˢ Super Assistant(Video Downloader & 🚫 No ads & New Layout For YT!)
  38. // @description The script is an Enhancer for Youtube to improve your watching experience!Contains features & new layout. Introduction: 1.Optimized Video Detail Page Interface. 2.Screenshot. 3.Dark/Light Theme Switch. 4.Video Fast Forward. etc.
  39. // @description:zh-CN 这个脚本是一个增强器,用于提升您的YouTube观看体验!包含新功能和新布局。介绍:1.优化的视频详情页面界面。2.截图。3.深色/浅色主题切换。4.视频快进。等等。
  40. // @description:zh-TW 這個腳本是一個增強器,用於提升您的YouTube觀看體驗!包含新功能和新佈局。介紹:1.優化的影片詳細頁面介面。2.截圖。3.深色/淺色主題切換。4.影片快轉。等等。
  41. // @description:ar البرنامج هو معزز لتحسين تجربة المشاهدة على يوتيوب! يحتوي على ميزات وتصميم جديد. المقدمة: 1. واجهة صفحة تفاصيل الفيديو المحسنة. 2. لقطة الشاشة. 3. التبديل بين الوضع الداكن/الفاتح. 4. تسريع الفيديو. إلخ.
  42. // @description:bg Скриптът е усилвател за подобряване на вашето изживяване в YouTube! Съдържа функции и нов дизайн. Въведение: 1. Оптимизирана страница с детайли за видео. 2. Снимка на екрана. 3. Превключване между тъмна/светла тема. 4. Бързо превъртане на видеото. и др.
  43. // @description:cs Skript je vylepšovač pro zlepšení vaší sledovací zkušenosti na YouTube! Obsahuje funkce a nový vzhled. Úvod: 1. Optimalizované rozhraní stránky s podrobnostmi o videu. 2. Snímek obrazovky. 3. Přepínač tmavého/světlého režimu. 4. Rychlé přetáčení videa. atd.
  44. // @description:da Scriptet er en forbedrer til at forbedre din seeroplevelse på YouTube! Indeholder funktioner og nyt layout. Introduktion: 1. Optimeret video detajtside interface. 2. Skærmbillede. 3. Mørk/lys tema skift. 4. Hurtig fremspoling af video. osv.
  45. // @description:de Das Skript ist ein Enhancer, um dein YouTube-Erlebnis zu verbessern! Es enthält Funktionen und ein neues Layout. Einführung: 1. Optimierte Video-Detail-Seitenoberfläche. 2. Screenshot. 3. Dunkel-/Helle-Themen-Schalter. 4. Video-Schnellvorlauf. usw.
  46. // @description:el Το σενάριο είναι ένας ενισχυτής για να βελτιώσετε την εμπειρία παρακολούθησης στο YouTube! Περιλαμβάνει δυνατότητες και νέο σχέδιο. Εισαγωγή: 1. Βελτιστοποιημένο interface σελίδας λεπτομερειών βίντεο. 2. Στιγμιότυπο οθόνης. 3. Εναλλαγή σκοτεινού/φωτεινού θέματος. 4. Γρήγορη προώθηση βίντεο. κ.ά.
  47. // @description:en The script is an Enhancer for YouTube to improve your watching experience! Contains features & new layout. Introduction: 1. Optimized Video Detail Page Interface. 2. Screenshot. 3. Dark/Light Theme Switch. 4. Video Fast Forward. etc.
  48. // @description:eo La skripto estas plibonigilo por YouTube por plibonigi vian spekton. Ĝi enhavas funkciojn kaj novan aranĝon. Enkonduko: 1. Optimumigita Videodetalpa Paĝa Interfaco. 2. Ekranbildo. 3. Ŝanĝo de Malluma/Luma Temoj. 4. Rapida Antaŭenŝovo de Video. ktp.
  49. // @description:es ¡El script es un mejorador para YouTube para mejorar tu experiencia de visualización! Contiene características y un diseño nuevo. Introducción: 1. Interfaz optimizada de la página de detalles del video. 2. Captura de pantalla. 3. Cambio de tema oscuro/claro. 4. Avance rápido de video. etc.
  50. // @description:fi Skripti on parannus, joka parantaa YouTube-kokemustasi! Sisältää ominaisuuksia ja uuden ulkoasun. Johdanto: 1. Optimoitu videon yksityiskohdasivun käyttöliittymä. 2. Kuvakaappaus. 3. Tumma/vaalea teema-vaihto. 4. Videon nopea eteenpäin siirto. jne.
  51. // @description:fr Le script est un amplificateur pour améliorer votre expérience de visionnage sur YouTube ! Il contient des fonctionnalités et une nouvelle mise en page. Introduction : 1. Interface optimisée de la page de détails de la vidéo. 2. Capture d'écran. 3. Commutateur de thème sombre/claire. 4. Avance rapide de la vidéo. etc.
  52. // @description:fr-CA Le script est un amplificateur pour améliorer votre expérience de visionnage sur YouTube ! Il comprend des fonctionnalités et une nouvelle interface. Introduction : 1. Interface optimisée de la page de détails de la vidéo. 2. Capture d'écran. 3. Changement de thème sombre/clair. 4. Avance rapide de vidéo. etc.
  53. // @description:he הסקריפט הוא משפר לשיפור חווית הצפייה שלך ב-YouTube! מכיל תכונות ועיצוב חדש. הצגה: 1. ממשק מעודכן לדף פרטי וידאו. 2. צילום מסך. 3. מתחלף נושא כהה/בהיר. 4. קפיצה קדימה של וידאו. וכו'.
  54. // @description:hr Skripta je pojačivač za poboljšanje vašeg iskustva gledanja na YouTubeu! Sadrži značajke i novi izgled. Uvod: 1. Optimizirani sučelje stranice s detaljima videa. 2. Slikovni prikaz. 3. Prebacivanje između tamne/svijetle teme. 4. Brzo premotavanje videa. itd.
  55. // @description:hu A szkript egy enhancer a YouTube-élményed javítására! Tartalmaz funkciókat és új elrendezést. Bevezetés: 1. Optimalizált videó részletes oldal elrendezés. 2. Képernyőfotó. 3. Sötét/fényes téma váltás. 4. Videó gyors előretekerés. stb.
  56. // @description:id Skriptnya adalah Enhancer untuk meningkatkan pengalaman menonton YouTube Anda! Berisi fitur dan tata letak baru. Pengenalan: 1. Antarmuka Halaman Detail Video yang Dioptimalkan. 2. Tangkapan layar. 3. Tombol Switch Tema Gelap/Terang. 4. Pencarian Cepat Video. dll.
  57. // @description:it Lo script è un miglioratore per migliorare la tua esperienza di visione su YouTube! Contiene funzionalità e un nuovo layout. Introduzione: 1. Interfaccia della pagina dei dettagli video ottimizzata. 2. Screenshot. 3. Switch tra tema scuro/chiaro. 4. Avanzamento rapido del video. ecc.
  58. // @description:ja このスクリプトは、YouTubeの視聴体験を向上させるためのエンハンサーです!新しいレイアウトと機能が含まれています。紹介: 1. 最適化された動画詳細ページインターフェース。 2. スクリーンショット。 3. ダーク/ライトテーマの切り替え。 4. 動画の早送り。など。
  59. // @description:ka ეს სკრიპტი არის YouTube-ის დამხმარე პროგრამა თქვენი ყურების გამოცდილების გასაუმჯობესებლად! შეიცავს ფუნქციებს და ახალ დიზაინს. შესავალი: 1. ოპტიმიზებული ვიდეო დეტალების გვერდის ინტერფეისი. 2. ეკრანული სურათი. 3. ბნელ/ღია თემის გადართვა. 4. ვიდეოს სწრაფი გადახვევა. და სხვ.
  60. // @description:ko 이 스크립트는 YouTube 시청 경험을 개선하는 향상기입니다! 기능과 새로운 레이아웃을 포함합니다. 소개: 1. 최적화된 비디오 세부 페이지 인터페이스. 2. 스크린샷. 3. 어두운/밝은 테마 전환. 4. 비디오 빠른 되감기. 등.
  61. // @description:nb Skriptet er en forsterker for å forbedre din YouTube-opplevelse! Inneholder funksjoner og nytt layout. Introduksjon: 1. Optimalisert videodetaljside-grensesnitt. 2. Skjermbilde. 3. Mørk/lys tema-bytte. 4. Video rask fremover. osv.
  62. // @description:nl Het script is een enhancer om je kijkervaring op YouTube te verbeteren! Bevat functies en een nieuwe lay-out. Inleiding: 1. Geoptimaliseerde interface voor videodetailpagina. 2. Screenshot. 3. Donker/licht thema wisselen. 4. Video snel vooruit spoelen. enz.
  63. // @description:pl Skrypt to wzmacniacz poprawiający twoje doświadczenie oglądania na YouTube! Zawiera funkcje i nowy układ. Wprowadzenie: 1. Optymalizowany interfejs strony szczegółów wideo. 2. Zrzut ekranu. 3. Przełącznik motywu ciemnego/jasnego. 4. Szybkie przewijanie wideo. itd.
  64. // @description:pt-BR O script é um aprimorador para melhorar sua experiência de visualização no YouTube! Contém recursos e um novo layout. Introdução: 1. Interface otimizada da página de detalhes do vídeo. 2. Captura de tela. 3. Alternância entre tema escuro/ claro. 4. Avanço rápido de vídeo. etc.
  65. // @description:ro Scriptul este un îmbunătățitor pentru a-ți îmbunătăți experiența de vizionare pe YouTube! Conține funcții și un nou design. Introducere: 1. Interfața optimizată a paginii detaliilor video. 2. Captură de ecran. 3. Schimbător de temă închis/deschis. 4. Derulare rapidă video. etc.
  66. // @description:ru Скрипт — это усилитель для улучшения вашего опыта просмотра на YouTube! Содержит функции и новый макет. Введение: 1. Оптимизированный интерфейс страницы с деталями видео. 2. Скриншот. 3. Переключатель темной/светлой темы. 4. Быстрое перематывание видео. и т. д.
  67. // @description:sv Scriptet är en förstärkare för att förbättra din tittarupplevelse på YouTube! Innehåller funktioner och en ny layout. Introduktion: 1. Optimerat video detaljsida gränssnitt. 2. Skärmdump. 3. Växla mellan mörkt/ljus tema. 4. Snabbspola video. osv.
  68. // @description:th สคริปต์นี้คือเครื่องมือเสริมเพื่อปรับปรุงประสบการณ์การดูของคุณบน YouTube! มีฟีเจอร์และเลย์เอาต์ใหม่ๆ แนะนำ: 1. อินเตอร์เฟซหน้ารายละเอียดวิดีโอที่ได้รับการปรับแต่ง. 2. ถ่ายภาพหน้าจอ. 3. สลับโหมดมืด/สว่าง. 4. การเลื่อนวิดีโออย่างรวดเร็ว. เป็นต้น.
  69. // @description:tr Bu script, YouTube izleme deneyiminizi geliştirmek için bir Enhancer'dır! Özellikler ve yeni bir tasarım içerir. Tanıtım: 1. Optimize edilmiş Video Detay Sayfası Arayüzü. 2. Ekran Görüntüsü. 3. Karanlık/Aydınlık Tema Geçişi. 4. Video Hızlı İleri Sarma. vb.
  70. // @description:uk Скрипт — це посилювач для покращення вашого досвіду перегляду на YouTube! Включає функції та новий макет. Вступ: 1. Оптимізований інтерфейс сторінки деталей відео. 2. Знімок екрана. 3. Перемикач темної/світлої теми. 4. Швидке перемотування відео. тощо.
  71. // @description:ug بۇ سكرىپت YouTube كۆرۈش تەجرىبەڭىزنى ياخشىلايدىغان كۈچەيتكۈچ! خۇسۇسىيەتلەر ۋە يېڭى تۈزۈلۈشنى ئۆز ئىچىگە ئالىدۇ. كىرۈش: 1. ۋىدىئو تەپسىلاتلىرى بەت ئىنتېرەيسىنى مۇۋاپىقلاش. 2. سكرىن رەسىمى. 3. قارا/ئاق تېما ئالماشتۇرۇش. 4. ۋىدىئونى تېز ئىلگىرى سۈرۈش. قاتارلىقلار.
  72. // @description:vi Kịch bản là một công cụ tăng cường để cải thiện trải nghiệm xem YouTube của bạn! Bao gồm các tính năng và giao diện mới. Giới thiệu: 1. Giao diện trang chi tiết video tối ưu. 2. Chụp màn hình. 3. Chuyển đổi giữa chủ đề tối/ sáng. 4. Tua nhanh video. v.v.
  73. // @namespace FunnyMonkey_NameScope
  74. // @version 2.0.6
  75. // @author FunnyMonkey
  76. // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAAAwRJREFUaEPtWUtOAzEMTQZRcQkqlnCKlpO1PRnlFLBEcAkEao0c4siTyceTDNMG6AraJPbL8z9aNf7Rjeuv/gaAp5urtToe17Oy1XX7u5f3fU5mkoGn5WKrldrkDvnJ30Gp3d3rxzYmIwgAb1wfDhul9by3HtMSYA8XF7sQI0EAz9eXDznloevu8UC3FmB/+/Z5b8Afjw+Ts2LP988dABCbjacwUS3eX4AwZE4DAM/LBYjO9gEQI9L9IiHDRbevHz2de/+Mpd+Z0XIBdLC7AGu3GL1cILDfkX/hflRxjMmRTILWBzA26hALy8UWIwWZjzOnm6s1+om7GLYeQQ1AC1jxzWgSACSXHJozw/9WZwdAKcUpJfPBm6Vbpxsz4JRSJlJZpk/PAAPAo09bAGym/AcgcGBcMq0TswN/FQPk2AiKCjHj4Cz5YX7o/XZODJCipJNjh9UzGKWoOBNn/58wIaMkwHfdzqtX+s7/ntbj2tC+DBOT+4CQ+cmW1QPAekbrR9V10W4p1kmZzi70Yd1eroGqAuAXUpNdq3dQqh8pBpBr7aYEk6qKywB44S+kbKxvdQMBYZPuF4a+rCIA2W4r0u6hcL/EljIVM6M6AHa8ogFWJmQyh446rq08x5pgrDWtAuAnJolSEgZ4UnMyIsOBMgC2300B4KUC0W/KauryMGnZRNfrIdgEhCsXc+STAsD8YeK815mhUmSWro46NwZcZ8aKuh5TVuEmAZjphJ1e8IFAaFpxMhNKMcBDa5MA/GGVyR9N+sDhsKEh7ux5gMIoKkC2y8NoyoSCPhAZspX5gDejDyWnUFfVywOskUnZOW9HQ6V1EYBBi2jfDzCuUxFnQAGskAETUQBWbtyOpoE9BDZtdg2VHrTP4GNvAGW1UGy2nyjWpMXZ2HWxPjk53EUh0Y2Zp56xCqbWp94YkuN1Xv6GBEiKt1ogKeVFDxyGhdwTk50mkF3XKG1qIPqk3uSkT0wuibT8yOeXzTU3XLs3Z7ail/pmH7prb2+O/SIG5lCkVEbzAL4A07+gbQ8x85sAAAAASUVORK5CYII=
  77. // @include https://www.youtube.com
  78. // @include *://*.youtube.com/**
  79. // @exclude *://accounts.youtube.com/*
  80. // @exclude *://www.youtube.com/live_chat_replay*
  81. // @exclude *://www.youtube.com/persist_identity*
  82. // @license MIT
  83. // @run-at document-start
  84. // @grant GM_registerMenuCommand
  85. // @grant GM_openInTab
  86. // @grant GM.openInTab
  87. // @grant GM_addStyle
  88. // @grant GM_setValue
  89. // @grant GM_getValue
  90. // @grant GM_xmlhttpRequest
  91. // @grant unsafeWindow
  92. // ==/UserScript==
  93. (function () {
  94. 'use strict';
  95.  
  96. /*!
  97. * Copyright (c) 2024 - 2025, FunnyMonkey. All rights reserved.
  98. *
  99. * Permission is hereby granted, free of charge, to any person obtaining a copy
  100. * of this software and associated documentation files (the "Software"), to deal
  101. * in the Software without restriction, including without limitation the rights
  102. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  103. * copies of the Software, and to permit persons to whom the Software is
  104. * furnished to do so, subject to the following conditions:
  105. *
  106. * The above copyright notice and this permission notice shall be included in
  107. * all copies or substantial portions of the Software.
  108. *
  109. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  110. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  111. *
  112. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  113. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  114. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  115. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  116. * SOFTWARE.
  117. */
  118.  
  119.  
  120. var css_248z$1 = "@keyframes relatedElementProvided{0%{background-position-x:3px}to{background-position-x:4px}}html[tabview-loaded=icp] #related.ytd-watch-flexy{animation:relatedElementProvided 1ms linear 0s 1 normal forwards}html[tabview-loaded=icp] #right-tabs #related.ytd-watch-flexy,html[tabview-loaded=icp] #right-tabs ytd-expander#expander,html[tabview-loaded=icp] [hidden] #related.ytd-watch-flexy,html[tabview-loaded=icp] [hidden] ytd-expander#expander,html[tabview-loaded=icp] ytd-comments ytd-expander#expander{animation:initial}#secondary.ytd-watch-flexy{position:relative}#secondary-inner.style-scope.ytd-watch-flexy{height:100%}secondary-wrapper{border:0;box-sizing:border-box;contain:strict;flex-wrap:nowrap;height:100%;left:0;max-height:calc(100vh - var(--ytd-toolbar-height, 56px));padding:0;padding-bottom:var(--ytd-margin-6x);padding-right:var(--ytd-margin-6x);padding-top:var(--ytd-margin-6x);position:absolute;right:0;top:0}#right-tabs,secondary-wrapper{display:flex;flex-direction:column;margin:0}#right-tabs{flex-grow:1;padding:0;position:relative}[tyt-tab=\"\"] #right-tabs{flex-grow:0}[tyt-tab=\"\"] #right-tabs .tab-content{border:0}#right-tabs .tab-content{flex-grow:1}ytd-watch-flexy[hide-default-text-inline-expander] #primary.style-scope.ytd-watch-flexy ytd-text-inline-expander{display:none}ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden{--comment-pre-load-sizing:90px;border:0;contain:strict;display:block!important;height:var(--comment-pre-load-sizing)!important;left:2px;margin:0;overflow:hidden;padding:0;pointer-events:none!important;position:fixed!important;top:2px;visibility:collapse;width:var(--comment-pre-load-sizing)!important;z-index:-1}ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments>*{display:none!important}ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments>ytd-item-section-renderer#sections{border:0;contain:strict;display:block!important;height:var(--comment-pre-load-sizing);margin:0;overflow:hidden;padding:0;width:var(--comment-pre-load-sizing)}ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments>ytd-item-section-renderer#sections>*{display:none!important}ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments>ytd-item-section-renderer#sections>#contents{border:0;contain:strict;display:flex!important;flex-direction:row;gap:60px;height:var(--comment-pre-load-sizing);margin:0;overflow:hidden;padding:0;width:var(--comment-pre-load-sizing)}ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments>ytd-item-section-renderer#sections>#contents>*{border:0;box-sizing:content-box;contain:strict;display:block!important;height:var(--comment-pre-load-sizing);margin:calc(var(--comment-pre-load-sizing)*2)!important;overflow:hidden;padding:0;visibility:collapse!important;width:var(--comment-pre-load-sizing)}ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments>ytd-item-section-renderer#sections>#contents>:empty{box-sizing:content-box;contain:strict;display:none!important;height:0;margin:0!important;overflow:hidden;visibility:collapse!important;width:0}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{box-sizing:initial;contain:strict;display:block!important;height:1px;margin:0!important;overflow:initial;visibility:collapse!important;width:1px}ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments>ytd-item-section-renderer#sections>#contents>*>*{box-sizing:content-box;contain:strict;display:none!important;height:0;margin:0!important;overflow:hidden;visibility:collapse!important;width:0}#right-tabs #material-tabs{border:1px solid var(--ytd-searchbox-legacy-border-color);display:flex;overflow:hidden;padding:0;position:relative}[tyt-tab] #right-tabs #material-tabs{border-radius:var(--tyt-rounded-a1) var(--tyt-rounded-a1) var(--tyt-rounded-a1) var(--tyt-rounded-a1)}[tyt-tab^=\"#\"] #right-tabs #material-tabs{border-radius:var(--tyt-rounded-a1) var(--tyt-rounded-a1) 0 0}ytd-watch-flexy[flexy]:not([is-two-columns_]) #right-tabs #material-tabs{outline:0}#right-tabs #material-tabs a.tab-btn[tyt-tab-content]>*{pointer-events:none}#right-tabs #material-tabs a.tab-btn[tyt-tab-content]>.font-size-right{display:none;pointer-events:auto}ytd-watch-flexy #right-tabs .tab-content{border:1px solid var(--ytd-searchbox-legacy-border-color);border-radius:0 0 var(--tyt-rounded-a1) var(--tyt-rounded-a1);border-top:0;box-sizing:border-box;display:block;display:flex;flex-direction:row;overflow:hidden;padding:0;position:relative;top:0}ytd-watch-flexy:not([is-two-columns_]) #right-tabs .tab-content{height:100%}ytd-watch-flexy #right-tabs .tab-content-cld{--tab-content-padding:var(--ytd-margin-4x);box-sizing:border-box;contain:layout paint;display:block;overflow:auto;padding:var(--tab-content-padding);position:relative;width:100%}#right-tabs,.tab-content,.tab-content-cld{animation:none;transition:none}ytd-watch-flexy[is-two-columns_] #right-tabs .tab-content-cld{contain:size layout paint style;height:100%;position:absolute;width:100%}ytd-watch-flexy #right-tabs .tab-content-cld.tab-content-hidden{contain:size layout paint style;display:none;width:100%}@supports (color:var(--tabview-tab-btn-define )){ytd-watch-flexy #right-tabs .tab-btn{background:var(--yt-spec-general-background-a)}html{--tyt-tab-btn-flex-grow:1;--tyt-tab-btn-flex-basis:0%;--tyt-tab-bar-color-1-def:#ff4533;--tyt-tab-bar-color-2-def:var(--yt-brand-light-red);--tyt-tab-bar-color-1:var(--main-color,var(--tyt-tab-bar-color-1-def));--tyt-tab-bar-color-2:var(--main-color,var(--tyt-tab-bar-color-2-def))}ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content]{--tyt-tab-btn-color:var(--yt-spec-text-secondary);background-color:var(--ytd-searchbox-legacy-button-color);border:0;border-bottom:4px solid transparent;color:var(--tyt-tab-btn-color);cursor:pointer;display:inline-block;flex-basis:0%;flex-basis:var(--tyt-tab-btn-flex-basis);flex-grow:1;flex-grow:var(--tyt-tab-btn-flex-grow);flex-shrink:1;font-size:12px;font-weight:500;line-height:18px;overflow:hidden;padding:14px 8px 10px;position:relative;text-align:center;text-decoration:none;text-overflow:clip;text-transform:uppercase;text-transform:var(--yt-button-text-transform,inherit);transition:border .2s linear .1s;white-space:nowrap}ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content]>svg{fill:var(--iron-icon-fill-color,currentcolor);stroke:var(--iron-icon-stroke-color,none);color:var(--yt-button-color,inherit);height:18px;margin-right:0;opacity:.5;padding-right:0;vertical-align:bottom}ytd-watch-flexy #right-tabs .tab-btn{--tabview-btn-txt-ml:8px}ytd-watch-flexy[tyt-comment-disabled] #right-tabs .tab-btn[tyt-tab-content=\"#tab-comments\"]{--tabview-btn-txt-ml:0px}ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content]>svg+span{margin-left:var(--tabview-btn-txt-ml)}ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content] svg{pointer-events:none}ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content].active{--tyt-tab-btn-color:var(--yt-spec-text-primary);background-color:var(--ytd-searchbox-legacy-button-focus-color);border-bottom-color:var(--tyt-tab-bar-color-1);border-bottom:2px solid var(--tyt-tab-bar-color-2);font-weight:500;outline:0}ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content].active svg{opacity:.9}ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content]:not(.active):hover{--tyt-tab-btn-color:var(--yt-spec-text-primary);background-color:var(--ytd-searchbox-legacy-button-hover-color)}ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content]:not(.active):hover svg{opacity:.9}ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content]{user-select:none!important}ytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content].tab-btn-hidden{display:none}ytd-watch-flexy[tyt-comment-disabled] #right-tabs .tab-btn[tyt-tab-content=\"#tab-comments\"],ytd-watch-flexy[tyt-comment-disabled] #right-tabs .tab-btn[tyt-tab-content=\"#tab-comments\"]:hover{--tyt-tab-btn-color:var(--yt-spec-icon-disabled)}ytd-watch-flexy[tyt-comment-disabled] #right-tabs .tab-btn[tyt-tab-content=\"#tab-comments\"] span#tyt-cm-count:empty{display:none}ytd-watch-flexy #right-tabs .tab-btn span#tyt-cm-count:empty:after{color:currentColor;display:inline-block;font-size:inherit;text-align:left;transform:scaleX(.8);width:4em}}@supports (color:var(--tyt-cm-count-define )){ytd-watch-flexy{--tyt-x-loading-content-letter-spacing:2px}html{--tabview-text-loading:\"Loading\";--tabview-text-fetching:\"Fetching\";--tabview-panel-loading:var(--tabview-text-loading)}html:lang(ja){--tabview-text-loading:\"読み込み中\";--tabview-text-fetching:\"フェッチ..\"}html:lang(ko){--tabview-text-loading:\"로딩..\";--tabview-text-fetching:\"가져오기..\"}html:lang(zh-Hant){--tabview-text-loading:\"載入中\";--tabview-text-fetching:\"擷取中\"}html:lang(zh-Hans){--tabview-text-loading:\"加载中\";--tabview-text-fetching:\"抓取中\"}html:lang(ru){--tabview-text-loading:\"Загрузка\";--tabview-text-fetching:\"Получение\"}ytd-watch-flexy #right-tabs .tab-btn span#tyt-cm-count:empty:after{content:var(--tabview-text-loading);letter-spacing:var(--tyt-x-loading-content-letter-spacing)}}@supports (color:var(--tabview-font-size-btn-define )){.font-size-right{align-content:space-evenly;bottom:0;display:inline-flex;flex-direction:column;justify-content:space-evenly;padding:4px 0;pointer-events:none;position:absolute;right:0;top:0;width:16px}html body ytd-watch-flexy.style-scope .font-size-btn{user-select:none!important}.font-size-btn{--tyt-font-size-btn-display:none;background-color:var(--yt-spec-badge-chip-background);box-sizing:border-box;color:var(--yt-spec-text-secondary);cursor:pointer;display:var(--tyt-font-size-btn-display,none);font-family:Menlo,Lucida Console,Monaco,Consolas,monospace;font-weight:900;height:12px;line-height:100%;margin:0;padding:0;pointer-events:all;position:relative;transform-origin:left top;transition:background-color 90ms linear,color 90ms linear;width:12px}.font-size-btn:hover{background-color:var(--yt-spec-text-primary);color:var(--yt-spec-general-background-a)}@supports (zoom:0.5){.tab-btn .font-size-btn{--tyt-font-size-btn-display:none}.tab-btn.active:hover .font-size-btn{--tyt-font-size-btn-display:inline-block}}}body ytd-watch-flexy:not([is-two-columns_]) #columns.ytd-watch-flexy{flex-direction:column}body ytd-watch-flexy:not([is-two-columns_]) #secondary.ytd-watch-flexy{box-sizing:border-box;display:block;width:100%}body ytd-watch-flexy:not([is-two-columns_]) #secondary.ytd-watch-flexy secondary-wrapper{contain:content;height:auto;padding-left:var(--ytd-margin-6x)}body ytd-watch-flexy:not([is-two-columns_]) #secondary.ytd-watch-flexy secondary-wrapper #right-tabs{overflow:auto}[tyt-chat=\"+\"] secondary-wrapper>[tyt-chat-container]{display:flex;flex-direction:column;flex-grow:1;flex-shrink:0}[tyt-chat=\"+\"] secondary-wrapper>[tyt-chat-container]>#chat{flex-grow:1}ytd-watch-flexy[is-two-columns_]:not([theater]) #columns.style-scope.ytd-watch-flexy{min-height:calc(100vh - var(--ytd-toolbar-height, 56px))}ytd-watch-flexy[is-two-columns_] ytd-live-chat-frame#chat{height:auto!important;min-height:auto!important}ytd-watch-flexy[tyt-tab^=\"#\"]:not([is-two-columns_]):not([tyt-chat=\"+\"]) #right-tabs{min-height:var(--ytd-watch-flexy-chat-max-height)}body ytd-watch-flexy:not([is-two-columns_]) #chat.ytd-watch-flexy{margin-top:0}body ytd-watch-flexy:not([is-two-columns_]) ytd-watch-metadata.ytd-watch-flexy{margin-bottom:0}ytd-watch-metadata.ytd-watch-flexy ytd-metadata-row-container-renderer{display:none}#tab-info [show-expand-button] #expand-sizer.ytd-text-inline-expander{visibility:initial}#tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer>#left-arrow-container.ytd-video-description-infocards-section-renderer>#left-arrow,#tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer>#right-arrow-container.ytd-video-description-infocards-section-renderer>#right-arrow{border:6px solid transparent;opacity:.65}#tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer>#left-arrow-container.ytd-video-description-infocards-section-renderer>#left-arrow:hover,#tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer>#right-arrow-container.ytd-video-description-infocards-section-renderer>#right-arrow:hover{opacity:1}#tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer>div#left-arrow-container:before{background:transparent;content:\"\";display:block;height:40px;left:-20px;position:absolute;top:0;width:40px;z-index:-1}#tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer>div#right-arrow-container:before{background:transparent;content:\"\";display:block;height:40px;position:absolute;right:-20px;top:0;width:40px;z-index:-1}body ytd-watch-flexy[is-two-columns_][tyt-egm-panel_] #columns.style-scope.ytd-watch-flexy #panels.style-scope.ytd-watch-flexy{display:flex;flex-direction:column;flex-grow:1;flex-shrink:0}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]{display:flex;flex-direction:column;flex-grow:1;flex-shrink:0;height:auto;max-height:none;min-height:auto}secondary-wrapper [visibility=ENGAGEMENT_PANEL_VISIBILITY_EXPANDED] #body.ytd-transcript-renderer:not(:empty),secondary-wrapper [visibility=ENGAGEMENT_PANEL_VISIBILITY_EXPANDED] #content.ytd-transcript-renderer:not(:empty),secondary-wrapper [visibility=ENGAGEMENT_PANEL_VISIBILITY_EXPANDED] ytd-transcript-renderer:not(:empty){flex-grow:1;height:auto;max-height:none;min-height:auto}secondary-wrapper #content.ytd-engagement-panel-section-list-renderer{position:relative}secondary-wrapper #content.ytd-engagement-panel-section-list-renderer>[panel-target-id]:only-child{contain:style size}secondary-wrapper #content.ytd-engagement-panel-section-list-renderer ytd-transcript-segment-list-renderer.ytd-transcript-search-panel-renderer{contain:strict;flex-grow:1}secondary-wrapper #content.ytd-engagement-panel-section-list-renderer ytd-transcript-segment-renderer.style-scope.ytd-transcript-segment-list-renderer,secondary-wrapper #content.ytd-engagement-panel-section-list-renderer ytd-transcript-segment-renderer.style-scope.ytd-transcript-segment-list-renderer>.segment{contain:layout paint style}body ytd-watch-flexy[theater] #secondary.ytd-watch-flexy{margin-top:var(--ytd-margin-3x);padding-top:0}body ytd-watch-flexy[theater] secondary-wrapper{margin-top:0;padding-top:0}body ytd-watch-flexy[theater] #chat.ytd-watch-flexy{margin-bottom:var(--ytd-margin-2x)}#tab-comments ytd-comments#comments [field-of-cm-count]{margin-top:0}#tab-info>ytd-expandable-video-description-body-renderer{margin-bottom:var(--ytd-margin-3x)}#tab-info [class]:last-child{margin-bottom:0;padding-bottom:0}#tab-info ytd-rich-metadata-row-renderer ytd-rich-metadata-renderer{max-width:none}ytd-watch-flexy[is-two-columns_] secondary-wrapper #chat.ytd-watch-flexy{margin-bottom:var(--ytd-margin-3x)}ytd-watch-flexy[tyt-tab] tp-yt-paper-tooltip{contain:content;white-space:nowrap}ytd-watch-info-text tp-yt-paper-tooltip.style-scope.ytd-watch-info-text{margin-bottom:-300px;margin-top:-96px}[hide-default-text-inline-expander] #bottom-row #description.ytd-watch-metadata{font-size:1.2rem;line-height:1.8rem}[hide-default-text-inline-expander] #bottom-row #description.ytd-watch-metadata yt-animated-rolling-number{font-size:inherit}[hide-default-text-inline-expander] #bottom-row #description.ytd-watch-metadata #info-container.style-scope.ytd-watch-info-text{align-items:center}ytd-watch-flexy[hide-default-text-inline-expander]{--tyt-bottom-watch-metadata-margin:6px}[hide-default-text-inline-expander] #bottom-row #description.ytd-watch-metadata>#description-inner.ytd-watch-metadata{margin:6px 12px}[hide-default-text-inline-expander] ytd-watch-metadata[title-headline-xs] h1.ytd-watch-metadata{font-size:1.8rem}ytd-watch-flexy[is-two-columns_][hide-default-text-inline-expander] #below.style-scope.ytd-watch-flexy ytd-merch-shelf-renderer{border:0;margin:0;padding:0}ytd-watch-flexy[is-two-columns_][hide-default-text-inline-expander] #below.style-scope.ytd-watch-flexy ytd-watch-metadata.ytd-watch-flexy{margin-bottom:6px}#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{flex-shrink:0}#tab-info yt-video-attribute-view-model .yt-video-attribute-view-model__overflow-menu{background:var(--yt-emoji-picker-category-background-color);border-radius:99px}#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{max-height:128px}#tab-info yt-video-attribute-view-model .yt-video-attribute-view-model--image-large .yt-video-attribute-view-model__hero-section{max-width:128px}#tab-info ytd-reel-shelf-renderer #items.yt-horizontal-list-renderer ytd-reel-item-renderer.yt-horizontal-list-renderer{max-width:142px}ytd-watch-info-text#ytd-watch-info-text.style-scope.ytd-watch-metadata #date-text.style-scope.ytd-watch-info-text,ytd-watch-info-text#ytd-watch-info-text.style-scope.ytd-watch-metadata #view-count.style-scope.ytd-watch-info-text{align-items:center}ytd-watch-info-text:not([detailed]) #info.ytd-watch-info-text a.yt-simple-endpoint.yt-formatted-string{pointer-events:none}body ytd-app>ytd-popup-container>tp-yt-iron-dropdown>#contentWrapper>[slot=dropdown-content]{backdrop-filter:none}#tab-info [tyt-clone-refresh-count]{overflow:visible!important}#tab-info #items.ytd-horizontal-card-list-renderer yt-video-attribute-view-model.ytd-horizontal-card-list-renderer{contain:layout}#tab-info #thumbnail-container.ytd-structured-description-channel-lockup-renderer,#tab-info ytd-media-lockup-renderer[is-compact] #thumbnail-container.ytd-media-lockup-renderer{flex-shrink:0}secondary-wrapper ytd-donation-unavailable-renderer{--ytd-margin-6x:var(--ytd-margin-2x);--ytd-margin-5x:var(--ytd-margin-2x);--ytd-margin-4x:var(--ytd-margin-2x);--ytd-margin-3x:var(--ytd-margin-2x)}[tyt-no-less-btn] #less{display:none}.tyt-metadata-hover-resized #analytics-button,.tyt-metadata-hover-resized #purchase-button,.tyt-metadata-hover-resized #sponsor-button,.tyt-metadata-hover-resized #subscribe-button{display:none!important}.tyt-metadata-hover #upload-info{flex-basis:100vw;flex-shrink:0;max-width:max-content;min-width:max-content}#tab-info ytd-structured-description-playlist-lockup-renderer[collections] #playlist-thumbnail.style-scope.ytd-structured-description-playlist-lockup-renderer{max-width:100%}#tab-info ytd-structured-description-playlist-lockup-renderer[collections] #lockup-container.ytd-structured-description-playlist-lockup-renderer{padding:1px}#tab-info ytd-structured-description-playlist-lockup-renderer[collections] #thumbnail.ytd-structured-description-playlist-lockup-renderer{outline:1px solid hsla(0,0%,50%,.5)}ytd-live-chat-frame#chat[collapsed] ytd-message-renderer~#show-hide-button.ytd-live-chat-frame>ytd-toggle-button-renderer.ytd-live-chat-frame{padding:0}.tyt-info-invisible{display:none}[tyt-playlist-expanded] secondary-wrapper>ytd-playlist-panel-renderer#playlist{flex-grow:1;flex-shrink:1;max-height:unset!important;overflow:auto}[tyt-playlist-expanded] secondary-wrapper>ytd-playlist-panel-renderer#playlist>#container{max-height:unset!important}secondary-wrapper ytd-playlist-panel-renderer{--ytd-margin-6x:var(--ytd-margin-3x)}ytd-watch-flexy[theater] ytd-playlist-panel-renderer[collapsible][collapsed] .header.ytd-playlist-panel-renderer{padding:6px 8px}ytd-watch-flexy[theater] #playlist.ytd-watch-flexy{margin-bottom:var(--ytd-margin-2x)}ytd-watch-flexy[theater] #right-tabs .tab-btn[tyt-tab-content]{border-bottom:0 solid transparent;padding:8px 4px 6px}ytd-watch-flexy{--tyt-bottom-watch-metadata-margin:12px}ytd-watch-flexy[rounded-info-panel],ytd-watch-flexy[rounded-player-large]{--tyt-rounded-a1:${VAL_ROUNDED_A1}px}#bottom-row.style-scope.ytd-watch-metadata .item.ytd-watch-metadata{margin-right:var(--tyt-bottom-watch-metadata-margin,12px);margin-top:var(--tyt-bottom-watch-metadata-margin,12px)}#cinematics{contain:layout style size}";
  121.  
  122. const VAL_ROUNDED_A1 = 12;
  123. const styles = {
  124. main: css_248z$1.replace("${VAL_ROUNDED_A1}", VAL_ROUNDED_A1)
  125. };
  126.  
  127. const StorageUtil = {
  128. keys: {
  129. youtube: {
  130. videoPlaySpeed: "yt/videoPlaySpeed",
  131. functionState: "yt/functionState",
  132. theme: "yt/theme"
  133. }
  134. },
  135. getValue: function(key, defaultValue) {
  136. return GM_getValue(key, defaultValue);
  137. },
  138. setValue: function(key, value) {
  139. GM_setValue(key, value);
  140. }
  141. };
  142.  
  143. /*!
  144. * table function
  145. * MIT, https://github.com/tabview-youtube/Tabview-Youtube
  146. * @param {*} communicationKey
  147. * Optimize project structure to make it more reliable
  148. */
  149. const executionScript = (communicationKey) => {
  150. if (typeof trustedTypes !== "undefined" && trustedTypes.defaultPolicy === null) {
  151. let s = (s2) => s2;
  152. trustedTypes.createPolicy("default", { createHTML: s, createScriptURL: s, createScript: s });
  153. }
  154. const defaultPolicy = typeof trustedTypes !== "undefined" && trustedTypes.defaultPolicy || { createHTML: (s) => s };
  155. function createHTML(s) {
  156. return defaultPolicy.createHTML(s);
  157. }
  158. let trustHTMLErr = null;
  159. try {
  160. document.createElement("div").innerHTML = createHTML("1");
  161. } catch (e) {
  162. trustHTMLErr = e;
  163. }
  164. if (trustHTMLErr) {
  165. trustHTMLErr();
  166. }
  167. try {
  168. let getWord = function(tag) {
  169. return langWords[pageLang][tag] || langWords["en"][tag] || "";
  170. }, getTabsHTML = function() {
  171. const sTabBtnVideos = `${svgElm(16, 16, 90, 90, svgVideos)}<span>${getWord("videos")}</span>`;
  172. const sTabBtnInfo = `${svgElm(16, 16, 60, 60, svgInfo)}<span>${getWord("info")}</span>`;
  173. const sTabBtnPlayList = `${svgElm(16, 16, 20, 20, svgPlayList)}<span>${getWord("playlist")}</span>`;
  174. let str1 = `
  175. <paper-ripple class="style-scope yt-icon-button">
  176. <div id="background" class="style-scope paper-ripple" style="opacity:0;"></div>
  177. <div id="waves" class="style-scope paper-ripple"></div>
  178. </paper-ripple>
  179. `;
  180. let str_fbtns = `
  181. <div class="font-size-right">
  182. <div class="font-size-btn font-size-plus" tyt-di="8rdLQ">
  183. <svg width="12" height="12" viewbox="0 0 50 50" preserveAspectRatio="xMidYMid meet"
  184. stroke="currentColor" stroke-width="6" stroke-linecap="round" vector-effect="non-scaling-size">
  185. <path d="M12 25H38M25 12V38"/>
  186. </svg>
  187. </div><div class="font-size-btn font-size-minus" tyt-di="8rdLQ">
  188. <svg width="12" height="12" viewbox="0 0 50 50" preserveAspectRatio="xMidYMid meet"
  189. stroke="currentColor" stroke-width="6" stroke-linecap="round" vector-effect="non-scaling-size">
  190. <path d="M12 25h26"/>
  191. </svg>
  192. </div>
  193. </div>
  194. `.replace(/[\r\n]+/g, "");
  195. const str_tabs = [
  196. `<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>`,
  197. `<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>`,
  198. `<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>`,
  199. `<a id="tab-btn5" tyt-di="q9Kjc" tyt-tab-content="#tab-list" class="tab-btn tab-btn-hidden">${sTabBtnPlayList}${str1}${str_fbtns}</a>`
  200. ].join("");
  201. let addHTML = `
  202. <div id="right-tabs">
  203. <tabview-view-pos-thead></tabview-view-pos-thead>
  204. <header>
  205. <div id="material-tabs">
  206. ${str_tabs}
  207. </div>
  208. </header>
  209. <div class="tab-content">
  210. <div id="tab-info" class="tab-content-cld tab-content-hidden" tyt-hidden userscript-scrollbar-render></div>
  211. <div id="tab-comments" class="tab-content-cld tab-content-hidden" tyt-hidden userscript-scrollbar-render></div>
  212. <div id="tab-videos" class="tab-content-cld tab-content-hidden" tyt-hidden userscript-scrollbar-render></div>
  213. <div id="tab-list" class="tab-content-cld tab-content-hidden" tyt-hidden userscript-scrollbar-render></div>
  214. </div>
  215. </div>
  216. `;
  217. return addHTML;
  218. }, getLang = function() {
  219. let lang = "en";
  220. let htmlLang = ((document || 0).documentElement || 0).lang || "";
  221. switch (htmlLang) {
  222. case "en":
  223. case "en-GB":
  224. lang = "en";
  225. break;
  226. case "de":
  227. case "de-DE":
  228. lang = "du";
  229. break;
  230. case "fr":
  231. case "fr-CA":
  232. case "fr-FR":
  233. lang = "fr";
  234. break;
  235. case "zh-Hant":
  236. case "zh-Hant-HK":
  237. case "zh-Hant-TW":
  238. lang = "tw";
  239. break;
  240. case "zh-Hans":
  241. case "zh-Hans-CN":
  242. lang = "cn";
  243. break;
  244. case "ja":
  245. case "ja-JP":
  246. lang = "jp";
  247. break;
  248. case "ko":
  249. case "ko-KR":
  250. lang = "kr";
  251. break;
  252. case "ru":
  253. case "ru-RU":
  254. lang = "ru";
  255. break;
  256. default:
  257. lang = "en";
  258. }
  259. return lang;
  260. }, getLangForPage = function() {
  261. let lang = getLang();
  262. if (langWords[lang])
  263. pageLang = lang;
  264. else
  265. pageLang = "en";
  266. }, isTheater = function() {
  267. const ytdFlexyElm = elements.flexy;
  268. return ytdFlexyElm && ytdFlexyElm.hasAttribute000("theater");
  269. }, ytBtnSetTheater = function() {
  270. if (!isTheater()) {
  271. const sizeBtn = document.querySelector("ytd-watch-flexy #ytd-player button.ytp-size-button");
  272. if (sizeBtn)
  273. sizeBtn.click();
  274. }
  275. }, ytBtnCancelTheater = function() {
  276. if (isTheater()) {
  277. const sizeBtn = document.querySelector("ytd-watch-flexy #ytd-player button.ytp-size-button");
  278. if (sizeBtn)
  279. sizeBtn.click();
  280. }
  281. }, ytBtnExpandChat = function() {
  282. let button = document.querySelector("ytd-live-chat-frame#chat[collapsed] > .ytd-live-chat-frame#show-hide-button");
  283. if (button) {
  284. button = button.querySelector000("div.yt-spec-touch-feedback-shape") || button.querySelector000("ytd-toggle-button-renderer");
  285. if (button)
  286. button.click();
  287. }
  288. }, ytBtnCollapseChat = function() {
  289. let button = document.querySelector("ytd-live-chat-frame#chat:not([collapsed]) > .ytd-live-chat-frame#show-hide-button");
  290. if (button) {
  291. button = button.querySelector000("div.yt-spec-touch-feedback-shape") || button.querySelector000("ytd-toggle-button-renderer");
  292. if (button)
  293. button.click();
  294. }
  295. }, ytBtnEgmPanelCore = function(arr) {
  296. if (!arr)
  297. return;
  298. if (!("length" in arr))
  299. arr = [arr];
  300. const ytdFlexyElm = elements.flexy;
  301. if (!ytdFlexyElm)
  302. return;
  303. let actions = [];
  304. for (const entry of arr) {
  305. if (!entry)
  306. continue;
  307. let panelId = entry.panelId;
  308. let toHide = entry.toHide;
  309. let toShow = entry.toShow;
  310. if (toHide === true && !toShow) {
  311. actions.push({
  312. "changeEngagementPanelVisibilityAction": {
  313. "targetId": panelId,
  314. "visibility": "ENGAGEMENT_PANEL_VISIBILITY_HIDDEN"
  315. }
  316. });
  317. } else if (toShow === true && !toHide) {
  318. actions.push({
  319. "showEngagementPanelEndpoint": {
  320. "panelIdentifier": panelId
  321. }
  322. });
  323. }
  324. if (actions.length > 0) {
  325. const cnt = insp(ytdFlexyElm);
  326. cnt.resolveCommand(
  327. {
  328. "signalServiceEndpoint": {
  329. "signal": "CLIENT_SIGNAL",
  330. "actions": actions
  331. }
  332. },
  333. {},
  334. false
  335. );
  336. }
  337. actions = null;
  338. }
  339. }, ytBtnCloseEngagementPanels = function() {
  340. const actions = [];
  341. for (const panelElm of document.querySelectorAll(
  342. `ytd-watch-flexy[flexy][tyt-tab] #panels.ytd-watch-flexy ytd-engagement-panel-section-list-renderer[target-id][visibility]:not([hidden])`
  343. )) {
  344. if (panelElm.getAttribute("visibility") == "ENGAGEMENT_PANEL_VISIBILITY_EXPANDED" && !panelElm.closest("[hidden]")) {
  345. actions.push({
  346. panelId: panelElm.getAttribute000("target-id"),
  347. toHide: true
  348. });
  349. }
  350. }
  351. ytBtnEgmPanelCore(actions);
  352. }, ytBtnOpenPlaylist = function() {
  353. const cnt = insp(elements.playlist);
  354. if (cnt && typeof cnt.collapsed === "boolean") {
  355. cnt.collapsed = false;
  356. }
  357. }, ytBtnClosePlaylist = function() {
  358. const cnt = insp(elements.playlist);
  359. if (cnt && typeof cnt.collapsed === "boolean") {
  360. cnt.collapsed = true;
  361. }
  362. };
  363. let executionFinished = 0;
  364. if (typeof CustomElementRegistry === "undefined")
  365. return;
  366. if (CustomElementRegistry.prototype.define000)
  367. return;
  368. if (typeof CustomElementRegistry.prototype.define !== "function")
  369. return;
  370. const HTMLElement_ = HTMLElement.prototype.constructor;
  371. const qsOne = (elm, selector) => {
  372. return HTMLElement_.prototype.querySelector.call(elm, selector);
  373. };
  374. const qsAll = (elm, selector) => {
  375. return HTMLElement_.prototype.querySelectorAll.call(elm, selector);
  376. };
  377. const pdsBaseDF = Object.getOwnPropertyDescriptors(DocumentFragment.prototype);
  378. Object.defineProperties(DocumentFragment.prototype, {
  379. replaceChildren000: pdsBaseDF.replaceChildren
  380. });
  381. const pdsBaseNode = Object.getOwnPropertyDescriptors(Node.prototype);
  382. Object.defineProperties(Node.prototype, {
  383. appendChild000: pdsBaseNode.appendChild,
  384. insertBefore000: pdsBaseNode.insertBefore
  385. });
  386. const pdsBaseElement = Object.getOwnPropertyDescriptors(Element.prototype);
  387. Object.defineProperties(Element.prototype, {
  388. setAttribute000: pdsBaseElement.setAttribute,
  389. getAttribute000: pdsBaseElement.getAttribute,
  390. hasAttribute000: pdsBaseElement.hasAttribute,
  391. removeAttribute000: pdsBaseElement.removeAttribute,
  392. querySelector000: pdsBaseElement.querySelector,
  393. replaceChildren000: pdsBaseElement.replaceChildren
  394. });
  395. Element.prototype.setAttribute111 = function(p, v) {
  396. v = `${v}`;
  397. if (this.getAttribute000(p) === v)
  398. return;
  399. this.setAttribute000(p, v);
  400. };
  401. Element.prototype.incAttribute111 = function(p) {
  402. let v = +this.getAttribute000(p) || 0;
  403. v = v > 1e9 ? v + 1 : 9;
  404. this.setAttribute000(p, `${v}`);
  405. return v;
  406. };
  407. Element.prototype.assignChildern111 = function(previousSiblings, node, nextSiblings) {
  408. let nodeList = [];
  409. for (let t = this.firstChild; t instanceof Node; t = t.nextSibling) {
  410. if (t === node)
  411. continue;
  412. nodeList.push(t);
  413. }
  414. inPageRearrange = true;
  415. if (node.parentNode === this) {
  416. let fm = new DocumentFragment();
  417. if (nodeList.length > 0) {
  418. fm.replaceChildren000(...nodeList);
  419. }
  420. if (previousSiblings && previousSiblings.length > 0) {
  421. fm.replaceChildren000(...previousSiblings);
  422. this.insertBefore000(fm, node);
  423. }
  424. if (nextSiblings && nextSiblings.length > 0) {
  425. fm.replaceChildren000(...nextSiblings);
  426. this.appendChild000(fm);
  427. }
  428. fm.replaceChildren000();
  429. fm = null;
  430. } else {
  431. if (!previousSiblings)
  432. previousSiblings = [];
  433. if (!nextSiblings)
  434. nextSiblings = [];
  435. this.replaceChildren000(...previousSiblings, node, ...nextSiblings);
  436. }
  437. inPageRearrange = false;
  438. if (nodeList.length > 0) {
  439. for (const t of nodeList) {
  440. if (t instanceof Element && t.isConnected === false)
  441. t.remove();
  442. }
  443. }
  444. nodeList.length = 0;
  445. nodeList = null;
  446. };
  447. const DISABLE_FLAGS_SHADYDOM_FREE = true;
  448. (() => {
  449. let e = "undefined" != typeof unsafeWindow ? unsafeWindow : void 0 instanceof Window ? void 0 : window;
  450. if (!e._ytConfigHacks) {
  451. let r = function(t2) {
  452. o(), t2 && e.removeEventListener("DOMContentLoaded", r, false);
  453. };
  454. let t = 4;
  455. class n extends Set {
  456. add(e2) {
  457. if (t <= 0)
  458. return void 0;
  459. "function" == typeof e2 && super.add(e2);
  460. }
  461. }
  462. let a = (async () => {
  463. })().constructor, i = e._ytConfigHacks = new n(), l = () => {
  464. let t2 = e.ytcsi.originalYtcsi;
  465. t2 && (e.ytcsi = t2, l = null);
  466. }, c = null, o = () => {
  467. if (t >= 1) {
  468. let n2 = (e.yt || 0).config_ || (e.ytcfg || 0).data_ || 0;
  469. if ("string" == typeof n2.INNERTUBE_API_KEY && "object" == typeof n2.EXPERIMENT_FLAGS)
  470. for (let a2 of (--t <= 0 && l && l(), c = true, i))
  471. a2(n2);
  472. }
  473. }, f = 1, d = (t2) => {
  474. if (t2 = t2 || e.ytcsi)
  475. return e.ytcsi = new Proxy(t2, { get: (e2, t3, n2) => "originalYtcsi" === t3 ? e2 : (o(), c && --f <= 0 && l && l(), e2[t3]) }), true;
  476. };
  477. d() || Object.defineProperty(e, "ytcsi", {
  478. get() {
  479. },
  480. set: (t2) => (t2 && (delete e.ytcsi, d(t2)), true),
  481. enumerable: false,
  482. configurable: true
  483. });
  484. let { addEventListener: s, removeEventListener: y } = Document.prototype;
  485. new a((e2) => {
  486. if ("undefined" != typeof AbortSignal)
  487. s.call(
  488. document,
  489. "yt-page-data-fetched",
  490. e2,
  491. { once: true }
  492. ), s.call(document, "yt-navigate-finish", e2, { once: true }), s.call(
  493. document,
  494. "spfdone",
  495. e2,
  496. { once: true }
  497. );
  498. else {
  499. let t2 = () => {
  500. e2(), y.call(document, "yt-page-data-fetched", t2, false), y.call(document, "yt-navigate-finish", t2, false), y.call(document, "spfdone", t2, false);
  501. };
  502. s.call(document, "yt-page-data-fetched", t2, false), s.call(document, "yt-navigate-finish", t2, false), s.call(document, "spfdone", t2, false);
  503. }
  504. }).then(o), new a((e2) => {
  505. if ("undefined" != typeof AbortSignal)
  506. s.call(
  507. document,
  508. "yt-action",
  509. e2,
  510. { once: true, capture: true }
  511. );
  512. else {
  513. let t2 = () => {
  514. e2(), y.call(document, "yt-action", t2, true);
  515. };
  516. s.call(document, "yt-action", t2, true);
  517. }
  518. }).then(o), a.resolve().then(() => {
  519. "loading" !== document.readyState ? r() : e.addEventListener("DOMContentLoaded", r, false);
  520. });
  521. }
  522. })();
  523. let configOnce = false;
  524. window._ytConfigHacks.add((config_) => {
  525. if (configOnce)
  526. return;
  527. configOnce = true;
  528. const EXPERIMENT_FLAGS = config_.EXPERIMENT_FLAGS || 0;
  529. const EXPERIMENTS_FORCED_FLAGS = config_.EXPERIMENTS_FORCED_FLAGS || 0;
  530. for (const flags of [EXPERIMENT_FLAGS, EXPERIMENTS_FORCED_FLAGS]) {
  531. if (flags) {
  532. flags.web_watch_chat_hide_button_killswitch = false;
  533. flags.web_watch_theater_chat = false;
  534. flags.suppress_error_204_logging = true;
  535. flags.kevlar_watch_grid = false;
  536. if (DISABLE_FLAGS_SHADYDOM_FREE) {
  537. flags.enable_shadydom_free_scoped_node_methods = false;
  538. flags.enable_shadydom_free_scoped_query_methods = false;
  539. flags.enable_shadydom_free_scoped_readonly_properties_batch_one = false;
  540. flags.enable_shadydom_free_parent_node = false;
  541. flags.enable_shadydom_free_children = false;
  542. flags.enable_shadydom_free_last_child = false;
  543. }
  544. }
  545. }
  546. });
  547. const mWeakRef = typeof WeakRef === "function" ? (o) => o ? new WeakRef(o) : null : (o) => o || null;
  548. const kRef = (wr) => wr && wr.deref ? wr.deref() : wr;
  549. const Promise = (async () => {
  550. })().constructor;
  551. const delayPn = (delay) => new Promise((fn) => setTimeout(fn, delay));
  552. const insp = (o) => o ? o.polymerController || o.inst || o || 0 : o || 0;
  553. const setTimeout_ = setTimeout.bind(window);
  554. const PromiseExternal = ((resolve_, reject_) => {
  555. const h = (resolve, reject) => {
  556. resolve_ = resolve;
  557. reject_ = reject;
  558. };
  559. return class PromiseExternal extends Promise {
  560. constructor(cb = h) {
  561. super(cb);
  562. if (cb === h) {
  563. this.resolve = resolve_;
  564. this.reject = reject_;
  565. }
  566. }
  567. };
  568. })();
  569. !function(e) {
  570. "use strict";
  571. if (e.nextBrowserTick)
  572. return;
  573. if (!function() {
  574. if (e.postMessage && !e.importScripts && e.addEventListener) {
  575. let t2 = true, s2 = () => {
  576. t2 = false;
  577. };
  578. return e.addEventListener("message", s2, false), e.postMessage("", "*"), e.removeEventListener("message", s2, false), t2;
  579. }
  580. }())
  581. return void 0;
  582. const t = (async () => {
  583. })().constructor, s = ((e2, s2) => {
  584. const n2 = (t2, n3) => {
  585. e2 = t2, s2 = n3;
  586. };
  587. return class extends t {
  588. constructor(t2 = n2) {
  589. super(t2), t2 === n2 && (this.resolve = e2, this.reject = s2);
  590. }
  591. };
  592. })();
  593. let n, r = null;
  594. do {
  595. n = `$nextBrowserTick$${(Math.random() + 8).toString().slice(2)}$`;
  596. } while (n in e);
  597. const o = n;
  598. e[o] = 1;
  599. e.addEventListener(
  600. "message",
  601. (e2) => {
  602. (null !== r ? (e2 || 0).data : 0) === o && e2.source === (e2.target || 1) && r.resolve(r = null);
  603. },
  604. false
  605. ), e.nextBrowserTick = (t2) => {
  606. r || (r = new s(), e.postMessage(o, "*")), r.then(t2).catch(console.warn);
  607. };
  608. }("undefined" == typeof self ? "undefined" == typeof global ? void 0 : global : self);
  609. const isPassiveArgSupport = typeof IntersectionObserver === "function";
  610. const bubblePassive = isPassiveArgSupport ? { capture: false, passive: true } : false;
  611. const capturePassive = isPassiveArgSupport ? { capture: true, passive: true } : true;
  612. class Attributer {
  613. constructor(list) {
  614. this.list = list;
  615. this.flag = 0;
  616. }
  617. makeString() {
  618. let k = 1;
  619. let s = "";
  620. let i = 0;
  621. while (this.flag >= k) {
  622. if (this.flag & k) {
  623. s += this.list[i];
  624. }
  625. i++;
  626. k <<= 1;
  627. }
  628. return s;
  629. }
  630. }
  631. const mLoaded = new Attributer("icp");
  632. const wrSelfMap = /* @__PURE__ */ new WeakMap();
  633. const elements = new Proxy({
  634. related: null,
  635. comments: null,
  636. infoExpander: null
  637. }, {
  638. get(target, prop) {
  639. return kRef(target[prop]);
  640. },
  641. set(target, prop, value) {
  642. if (value) {
  643. let wr = wrSelfMap.get(value);
  644. if (!wr) {
  645. wr = mWeakRef(value);
  646. wrSelfMap.set(value, wr);
  647. }
  648. target[prop] = wr;
  649. } else {
  650. target[prop] = null;
  651. }
  652. return true;
  653. }
  654. });
  655. const getMainInfo = () => {
  656. const infoExpander = elements.infoExpander;
  657. if (!infoExpander)
  658. return null;
  659. const mainInfo = infoExpander.matches("[tyt-main-info]") ? infoExpander : infoExpander.querySelector000("[tyt-main-info]");
  660. return mainInfo || null;
  661. };
  662. const asyncWrap = (asyncFn) => {
  663. return () => {
  664. Promise.resolve().then(asyncFn);
  665. };
  666. };
  667. let pageType = null;
  668. let pageLang = "en";
  669. const langWords = {
  670. "en": {
  671. "info": "Info",
  672. "videos": "Videos",
  673. "playlist": "Playlist"
  674. },
  675. "jp": {
  676. "info": "情報",
  677. "videos": "動画",
  678. "playlist": "再生リスト"
  679. },
  680. "tw": {
  681. "info": "資訊",
  682. "videos": "影片",
  683. "playlist": "播放清單"
  684. },
  685. "cn": {
  686. "info": "资讯",
  687. "videos": "视频",
  688. "playlist": "播放列表"
  689. },
  690. "du": {
  691. "info": "Info",
  692. "videos": "Videos",
  693. "playlist": "Playlist"
  694. },
  695. "fr": {
  696. "info": "Info",
  697. "videos": "Vidéos",
  698. "playlist": "Playlist"
  699. },
  700. "kr": {
  701. "info": "정보",
  702. "videos": "동영상",
  703. "playlist": "재생목록"
  704. },
  705. "ru": {
  706. "info": "Описание",
  707. "videos": "Видео",
  708. "playlist": "Плейлист"
  709. }
  710. };
  711. 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
  712. 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
  713. 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
  714. 0 0 3-1V71h2a12 12 90 0 0 12-12V17a12 12 90 0 0-12-12z"/>`.trim();
  715. 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
  716. 66H9V68h9v10zm0-56H9V12h9v10zm22 56H27V68h13v10zm-3-25V36c0-2 2-3 4-2l12 8c2 1 2 4 0 5l-12 8c-2 1-4 0-4-2zm25
  717. 25H49V68h13v10zm0-56H49V12h13v10zm18 56h-9V68h9v10zm0-56h-9V12h9v10z"/>`.trim();
  718. 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
  719. 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
  720. .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
  721. .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
  722. 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
  723. 0 0 1.4-.4l-.6 2.2zm-3.8-35.2a1 1 0 010 8.6 1 1 0 010-8.6z"/>`.trim();
  724. const svgPlayList = `<path d="M0 3h12v2H0zm0 4h12v2H0zm0 4h8v2H0zm16 0V7h-2v4h-4v2h4v4h2v-4h4v-2z"/>`.trim();
  725. const svgDiag1 = `<svg stroke="currentColor" fill="none"><path d="M8 2h2v2M7 5l3-3m-6 8H2V8m0 2l3-3"/></svg>`;
  726. const svgDiag2 = `<svg stroke="currentColor" fill="none"><path d="M7 3v2h2M7 5l3-3M5 9V7H3m-1 3l3-3"/></svg>`;
  727. const getGMT = () => {
  728. let m = new Date("2023-01-01T00:00:00Z");
  729. return m.getDate() === 1 ? `+${m.getHours()}` : `-${24 - m.getHours()}`;
  730. };
  731. 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>`;
  732. let hiddenTabsByUserCSS = 0;
  733. const _locks = {};
  734. const lockGet = new Proxy(
  735. _locks,
  736. {
  737. get(target, prop) {
  738. return target[prop] || 0;
  739. },
  740. set(target, prop, val) {
  741. return true;
  742. }
  743. }
  744. );
  745. const lockSet = new Proxy(
  746. _locks,
  747. {
  748. get(target, prop) {
  749. if (target[prop] > 1e9)
  750. target[prop] = 9;
  751. return target[prop] = (target[prop] || 0) + 1;
  752. },
  753. set(target, prop, val) {
  754. return true;
  755. }
  756. }
  757. );
  758. const videosElementProvidedPromise = new PromiseExternal();
  759. const navigateFinishedPromise = new PromiseExternal();
  760. let isRightTabsInserted = false;
  761. const rightTabsProvidedPromise = new PromiseExternal();
  762. const infoExpanderElementProvidedPromise = new PromiseExternal();
  763. const funcCanCollapse = function(s) {
  764. if (!s)
  765. return;
  766. this.canToggle = this.shouldUseNumberOfLines && (this.alwaysCollapsed || this.collapsed) ? this.alwaysToggleable || this.$.content.offsetHeight < this.$.content.scrollHeight : this.alwaysToggleable || this.$.content.scrollHeight > this.collapsedHeight;
  767. };
  768. const aoChatAttrChangeFn = async (lockId) => {
  769. if (lockGet["aoChatAttrAsyncLock"] !== lockId)
  770. return;
  771. const chatElm = elements.chat;
  772. const ytdFlexyElm = elements.flexy;
  773. if (chatElm && ytdFlexyElm) {
  774. const isChatCollapsed = chatElm.hasAttribute000("collapsed");
  775. if (isChatCollapsed) {
  776. ytdFlexyElm.setAttribute111("tyt-chat-collapsed", "");
  777. } else {
  778. ytdFlexyElm.removeAttribute000("tyt-chat-collapsed");
  779. }
  780. ytdFlexyElm.setAttribute111("tyt-chat", isChatCollapsed ? "-" : "+");
  781. }
  782. };
  783. const aoPlayListAttrChangeFn = async (lockId) => {
  784. if (lockGet["aoPlayListAttrAsyncLock"] !== lockId)
  785. return;
  786. const playlistElm = elements.playlist;
  787. const ytdFlexyElm = elements.flexy;
  788. if (playlistElm && ytdFlexyElm) {
  789. if (playlistElm.hasAttribute000("collapsed")) {
  790. ytdFlexyElm.removeAttribute000("tyt-playlist-expanded");
  791. } else {
  792. ytdFlexyElm.setAttribute111("tyt-playlist-expanded", "");
  793. }
  794. } else if (ytdFlexyElm) {
  795. ytdFlexyElm.removeAttribute000("tyt-playlist-expanded");
  796. }
  797. };
  798. const aoChat = new MutationObserver(() => {
  799. Promise.resolve(lockSet["aoChatAttrAsyncLock"]).then(aoChatAttrChangeFn).catch(console.warn);
  800. });
  801. const aoPlayList = new MutationObserver(() => {
  802. Promise.resolve(lockSet["aoPlayListAttrAsyncLock"]).then(aoPlayListAttrChangeFn).catch(console.warn);
  803. });
  804. const aoComment = new MutationObserver(async (mutations) => {
  805. const commentsArea = elements.comments;
  806. const ytdFlexyElm = elements.flexy;
  807. if (!commentsArea)
  808. return;
  809. let bfHidden = false;
  810. let bfCommentsVideoId = false;
  811. let bfCommentDisabled = false;
  812. for (const mutation of mutations) {
  813. if (mutation.attributeName === "hidden" && mutation.target === commentsArea) {
  814. bfHidden = true;
  815. } else if (mutation.attributeName === "tyt-comments-video-id" && mutation.target === commentsArea) {
  816. bfCommentsVideoId = true;
  817. } else if (mutation.attributeName === "tyt-comments-data-status" && mutation.target === commentsArea) {
  818. bfCommentDisabled = true;
  819. }
  820. }
  821. if (bfHidden) {
  822. if (!commentsArea.hasAttribute000("hidden")) {
  823. Promise.resolve(commentsArea).then(eventMap["settingCommentsVideoId"]).catch(console.warn);
  824. }
  825. Promise.resolve(lockSet["removeKeepCommentsScrollerLock"]).then(removeKeepCommentsScroller).catch(console.warn);
  826. }
  827. if ((bfHidden || bfCommentsVideoId || bfCommentDisabled) && ytdFlexyElm) {
  828. const commentsDataStatus = +commentsArea.getAttribute000("tyt-comments-data-status");
  829. if (commentsDataStatus === 2) {
  830. ytdFlexyElm.setAttribute111("tyt-comment-disabled", "");
  831. } else if (commentsDataStatus === 1) {
  832. ytdFlexyElm.removeAttribute000("tyt-comment-disabled");
  833. }
  834. Promise.resolve(lockSet["checkCommentsShouldBeHiddenLock"]).then(eventMap["checkCommentsShouldBeHidden"]).catch(console.warn);
  835. const lockId = lockSet["rightTabReadyLock01"];
  836. await rightTabsProvidedPromise.then();
  837. if (lockGet["rightTabReadyLock01"] !== lockId)
  838. return;
  839. if (elements.comments !== commentsArea)
  840. return;
  841. if (commentsArea.isConnected === false)
  842. return;
  843. if (commentsArea.closest("#tab-comments")) {
  844. const shouldTabVisible = !commentsArea.closest("[hidden]");
  845. document.querySelector('[tyt-tab-content="#tab-comments"]').classList.toggle("tab-btn-hidden", !shouldTabVisible);
  846. }
  847. }
  848. });
  849. const ioComment = new IntersectionObserver((entries) => {
  850. for (const entry of entries) {
  851. const target = entry.target;
  852. const cnt = insp(target);
  853. if (entry.isIntersecting && target instanceof HTMLElement_ && typeof cnt.calculateCanCollapse === "function") {
  854. lockSet["removeKeepCommentsScrollerLock"];
  855. cnt.calculateCanCollapse(true);
  856. target.setAttribute111("io-intersected", "");
  857. const ytdFlexyElm = elements.flexy;
  858. if (ytdFlexyElm && !ytdFlexyElm.hasAttribute000("keep-comments-scroller")) {
  859. ytdFlexyElm.setAttribute111("keep-comments-scroller", "");
  860. }
  861. } else if (target.hasAttribute000("io-intersected")) {
  862. target.removeAttribute000("io-intersected");
  863. }
  864. }
  865. }, {
  866. threshold: [0],
  867. rootMargin: "32px"
  868. });
  869. let bFixForResizedTabLater = false;
  870. let lastRoRightTabsWidth = 0;
  871. const roRightTabs = new ResizeObserver((entries) => {
  872. const entry = entries[entries.length - 1];
  873. const width = Math.round(entry.borderBoxSize.inlineSize);
  874. if (lastRoRightTabsWidth !== width) {
  875. lastRoRightTabsWidth = width;
  876. if ((tabAStatus & 2) === 2) {
  877. bFixForResizedTabLater = false;
  878. Promise.resolve(1).then(eventMap["fixForTabDisplay"]);
  879. } else {
  880. bFixForResizedTabLater = true;
  881. }
  882. }
  883. });
  884. const switchToTab = (activeLink) => {
  885. if (typeof activeLink === "string") {
  886. activeLink = document.querySelector(`a[tyt-tab-content="${activeLink}"]`) || null;
  887. }
  888. const ytdFlexyElm = elements.flexy;
  889. const links = document.querySelectorAll("#material-tabs a[tyt-tab-content]");
  890. for (const link of links) {
  891. const content = document.querySelector(link.getAttribute000("tyt-tab-content"));
  892. if (link && content) {
  893. if (link !== activeLink) {
  894. link.classList.remove("active");
  895. content.classList.add("tab-content-hidden");
  896. if (!content.hasAttribute000("tyt-hidden")) {
  897. content.setAttribute111("tyt-hidden", "");
  898. }
  899. } else {
  900. link.classList.add("active");
  901. if (content.hasAttribute000("tyt-hidden")) {
  902. content.removeAttribute000("tyt-hidden");
  903. }
  904. content.classList.remove("tab-content-hidden");
  905. }
  906. }
  907. }
  908. const switchingTo = activeLink ? activeLink.getAttribute000("tyt-tab-content") : "";
  909. if (switchingTo) {
  910. lastTab = lastPanel = switchingTo;
  911. }
  912. if (ytdFlexyElm.getAttribute000("tyt-chat") === "")
  913. ytdFlexyElm.removeAttribute000("tyt-chat");
  914. ytdFlexyElm.setAttribute111("tyt-tab", switchingTo);
  915. if (switchingTo) {
  916. bFixForResizedTabLater = false;
  917. Promise.resolve(0).then(eventMap["fixForTabDisplay"]);
  918. }
  919. };
  920. let tabAStatus = 0;
  921. const calculationFn = (r = 0, flag) => {
  922. const ytdFlexyElm = elements.flexy;
  923. if (!ytdFlexyElm)
  924. return r;
  925. if (flag & 1) {
  926. r |= 1;
  927. if (!ytdFlexyElm.hasAttribute000("theater"))
  928. r -= 1;
  929. }
  930. if (flag & 2) {
  931. r |= 2;
  932. if (!ytdFlexyElm.getAttribute000("tyt-tab"))
  933. r -= 2;
  934. }
  935. if (flag & 4) {
  936. r |= 4;
  937. if (ytdFlexyElm.getAttribute000("tyt-chat") !== "-")
  938. r -= 4;
  939. }
  940. if (flag & 8) {
  941. r |= 8;
  942. if (ytdFlexyElm.getAttribute000("tyt-chat") !== "+")
  943. r -= 8;
  944. }
  945. if (flag & 16) {
  946. r |= 16;
  947. if (!ytdFlexyElm.hasAttribute000("is-two-columns_"))
  948. r -= 16;
  949. }
  950. if (flag & 32) {
  951. r |= 32;
  952. if (!ytdFlexyElm.hasAttribute000("tyt-egm-panel_"))
  953. r -= 32;
  954. }
  955. if (flag & 64) {
  956. r |= 64;
  957. if (!document.fullscreenElement)
  958. r -= 64;
  959. }
  960. if (flag & 128) {
  961. r |= 128;
  962. if (!ytdFlexyElm.hasAttribute000("tyt-playlist-expanded"))
  963. r -= 128;
  964. }
  965. return r;
  966. };
  967. const updateChatLocation498 = function() {
  968. if (this.is !== "ytd-watch-grid") {
  969. this.updatePageMediaQueries();
  970. this.schedulePlayerSizeUpdate_();
  971. }
  972. };
  973. const mirrorNodeWS = /* @__PURE__ */ new WeakMap();
  974. const dummyNode = document.createElement("noscript");
  975. const __j4836__ = Symbol();
  976. const __j5744__ = Symbol();
  977. const __j5733__ = Symbol();
  978. const monitorDataChangedByDOMMutation = async function(mutations) {
  979. const nodeWR = this;
  980. const node = kRef(nodeWR);
  981. if (!node)
  982. return;
  983. const cnt = insp(node);
  984. const __lastChanged__ = cnt[__j5733__];
  985. const val = cnt.data ? cnt.data[__j4836__] || 1 : 0;
  986. if (__lastChanged__ !== val) {
  987. cnt[__j5733__] = val > 0 ? cnt.data[__j4836__] = Date.now() : 0;
  988. await Promise.resolve();
  989. attributeInc(node, "tyt-data-change-counter");
  990. }
  991. };
  992. const moChangeReflection = function(mutations) {
  993. const nodeWR = this;
  994. const node = kRef(nodeWR);
  995. if (!node)
  996. return;
  997. const originElement = kRef(node[__j5744__] || null) || null;
  998. if (!originElement)
  999. return;
  1000. const cnt = insp(node);
  1001. const oriCnt = insp(originElement);
  1002. if (mutations) {
  1003. let bfDataChangeCounter = false;
  1004. for (const mutation of mutations) {
  1005. if (mutation.attributeName === "tyt-clone-refresh-count" && mutation.target === originElement) {
  1006. bfDataChangeCounter = true;
  1007. } else if (mutation.attributeName === "tyt-data-change-counter" && mutation.target === originElement) {
  1008. bfDataChangeCounter = true;
  1009. }
  1010. }
  1011. if (bfDataChangeCounter && oriCnt.data) {
  1012. node.replaceWith(dummyNode);
  1013. cnt.data = Object.assign({}, oriCnt.data);
  1014. dummyNode.replaceWith(node);
  1015. }
  1016. }
  1017. };
  1018. const attributeInc = (elm, prop) => {
  1019. let v = (+elm.getAttribute000(prop) || 0) + 1;
  1020. if (v > 1e9)
  1021. v = 9;
  1022. elm.setAttribute000(prop, v);
  1023. return v;
  1024. };
  1025. const isChannelId = (x) => {
  1026. if (typeof x === "string" && x.length === 24) {
  1027. return /UC[-_a-zA-Z0-9+=.]{22}/.test(x);
  1028. }
  1029. return false;
  1030. };
  1031. const infoFix = (lockId) => {
  1032. if (lockId !== null && lockGet["infoFixLock"] !== lockId)
  1033. return;
  1034. const infoExpander = elements.infoExpander;
  1035. const infoContainer = (infoExpander ? infoExpander.parentNode : null) || document.querySelector("#tab-info");
  1036. const ytdFlexyElm = elements.flexy;
  1037. if (!infoContainer || !ytdFlexyElm)
  1038. return;
  1039. if (infoExpander) {
  1040. const match = infoExpander.matches("#tab-info > [class]") || infoExpander.matches("#tab-info > [tyt-main-info]");
  1041. if (!match)
  1042. return;
  1043. }
  1044. const requireElements = [...document.querySelectorAll('ytd-watch-metadata.ytd-watch-flexy div[slot="extra-content"] > *, ytd-watch-metadata.ytd-watch-flexy #extra-content > *')].filter((elm) => {
  1045. return typeof elm.is == "string";
  1046. }).map((elm) => {
  1047. const is = elm.is;
  1048. while (elm instanceof HTMLElement_) {
  1049. const q = [...elm.querySelectorAll(is)].filter((e) => insp(e).data);
  1050. if (q.length >= 1)
  1051. return q[0];
  1052. elm = elm.parentNode;
  1053. }
  1054. }).filter((elm) => !!elm && typeof elm.is === "string");
  1055. const source = requireElements.map((entry) => {
  1056. const inst = insp(entry);
  1057. return {
  1058. data: inst.data,
  1059. tag: inst.is,
  1060. elm: entry
  1061. };
  1062. });
  1063. let noscript_ = document.querySelector("noscript#aythl");
  1064. if (!noscript_) {
  1065. noscript_ = document.createElement("noscript");
  1066. noscript_.id = "aythl";
  1067. inPageRearrange = true;
  1068. ytdFlexyElm.insertBefore000(noscript_, ytdFlexyElm.firstChild);
  1069. inPageRearrange = false;
  1070. }
  1071. const noscript = noscript_;
  1072. let requiredUpdate = false;
  1073. const mirrorElmSet = /* @__PURE__ */ new Set();
  1074. const targetParent = infoContainer;
  1075. for (const { data, tag, elm: s } of source) {
  1076. let mirrorNode = mirrorNodeWS.get(s);
  1077. mirrorNode = mirrorNode ? kRef(mirrorNode) : mirrorNode;
  1078. if (!mirrorNode) {
  1079. const cnt = insp(s);
  1080. const cProto = cnt.constructor.prototype;
  1081. const element = document.createElement(tag);
  1082. noscript.appendChild(element);
  1083. mirrorNode = element;
  1084. mirrorNode[__j5744__] = mWeakRef(s);
  1085. const nodeWR = mWeakRef(mirrorNode);
  1086. new MutationObserver(moChangeReflection.bind(nodeWR)).observe(s, { attributes: true, attributeFilter: ["tyt-clone-refresh-count", "tyt-data-change-counter"] });
  1087. s.jy8432 = 1;
  1088. if (!(cProto instanceof Node) && !cProto._dataChanged496 && typeof cProto._createPropertyObserver === "function") {
  1089. cProto._dataChanged496 = function() {
  1090. const cnt2 = this;
  1091. const node = cnt2.hostElement || cnt2;
  1092. if (node.jy8432) {
  1093. attributeInc(node, "tyt-data-change-counter");
  1094. }
  1095. };
  1096. cProto._createPropertyObserver("data", "_dataChanged496", void 0);
  1097. } else if (!(cProto instanceof Node) && !cProto._dataChanged496 && cProto.useSignals === true && insp(s).signalProxy) {
  1098. const dataSignal = cnt?.signalProxy?.signalCache?.data;
  1099. if (dataSignal && typeof dataSignal.setWithPath === "function" && !dataSignal.setWithPath573 && !dataSignal.controller573) {
  1100. dataSignal.controller573 = mWeakRef(cnt);
  1101. dataSignal.setWithPath573 = dataSignal.setWithPath;
  1102. dataSignal.setWithPath = function() {
  1103. const cnt2 = kRef(this.controller573 || null) || null;
  1104. cnt2 && typeof cnt2._dataChanged496k === "function" && Promise.resolve(cnt2).then(cnt2._dataChanged496k).catch(console.warn);
  1105. return this.setWithPath573(...arguments);
  1106. };
  1107. cProto._dataChanged496 = function() {
  1108. const cnt2 = this;
  1109. const node = cnt2.hostElement || cnt2;
  1110. if (node.jy8432) {
  1111. attributeInc(node, "tyt-data-change-counter");
  1112. }
  1113. };
  1114. cProto._dataChanged496k = (cnt2) => cnt2._dataChanged496();
  1115. }
  1116. }
  1117. if (!cProto._dataChanged496) {
  1118. new MutationObserver(monitorDataChangedByDOMMutation.bind(mirrorNode[__j5744__])).observe(s, { attributes: true, childList: true, subtree: true });
  1119. }
  1120. mirrorNodeWS.set(s, nodeWR);
  1121. requiredUpdate = true;
  1122. } else {
  1123. if (mirrorNode.parentNode !== targetParent) {
  1124. requiredUpdate = true;
  1125. }
  1126. }
  1127. if (!requiredUpdate) {
  1128. const cloneNodeCnt = insp(mirrorNode);
  1129. if (cloneNodeCnt.data !== data) {
  1130. requiredUpdate = true;
  1131. }
  1132. }
  1133. mirrorElmSet.add(mirrorNode);
  1134. source.mirrored = mirrorNode;
  1135. }
  1136. const mirroElmArr = [...mirrorElmSet];
  1137. mirrorElmSet.clear();
  1138. if (!requiredUpdate) {
  1139. let e = infoExpander ? -1 : 0;
  1140. for (let n = targetParent.firstChild; n instanceof Node; n = n.nextSibling) {
  1141. let target = e < 0 ? infoExpander : mirroElmArr[e];
  1142. e++;
  1143. if (n !== target) {
  1144. requiredUpdate = true;
  1145. break;
  1146. }
  1147. }
  1148. if (!requiredUpdate && e !== mirroElmArr.length + 1)
  1149. requiredUpdate = true;
  1150. }
  1151. if (requiredUpdate) {
  1152. if (infoExpander) {
  1153. targetParent.assignChildern111(null, infoExpander, mirroElmArr);
  1154. } else {
  1155. targetParent.replaceChildren000(...mirroElmArr);
  1156. }
  1157. for (const mirrorElm of mirroElmArr) {
  1158. const j = attributeInc(mirrorElm, "tyt-clone-refresh-count");
  1159. const oriElm = kRef(mirrorElm[__j5744__] || null) || null;
  1160. if (oriElm) {
  1161. oriElm.setAttribute111("tyt-clone-refresh-count", j);
  1162. }
  1163. }
  1164. }
  1165. mirroElmArr.length = 0;
  1166. source.length = 0;
  1167. };
  1168. const layoutFix = (lockId) => {
  1169. if (lockGet["layoutFixLock"] !== lockId)
  1170. return;
  1171. const secondaryWrapper = document.querySelector("#secondary-inner.style-scope.ytd-watch-flexy > secondary-wrapper");
  1172. if (secondaryWrapper) {
  1173. const secondaryInner = secondaryWrapper.parentNode;
  1174. const chatContainer = document.querySelector("#columns.style-scope.ytd-watch-flexy [tyt-chat-container]");
  1175. if (secondaryInner.firstChild !== secondaryInner.lastChild || chatContainer && !chatContainer.closest("secondary-wrapper")) {
  1176. let w = [];
  1177. let w2 = [];
  1178. for (let node = secondaryInner.firstChild; node instanceof Node; node = node.nextSibling) {
  1179. if (node === chatContainer && chatContainer) {
  1180. } else if (node === secondaryWrapper) {
  1181. for (let node2 = secondaryWrapper.firstChild; node2 instanceof Node; node2 = node2.nextSibling) {
  1182. if (node2 === chatContainer && chatContainer) {
  1183. } else {
  1184. if (node2.id === "right-tabs" && chatContainer) {
  1185. w2.push(chatContainer);
  1186. }
  1187. w2.push(node2);
  1188. }
  1189. }
  1190. } else {
  1191. w.push(node);
  1192. }
  1193. }
  1194. inPageRearrange = true;
  1195. secondaryWrapper.replaceChildren000(...w, ...w2);
  1196. inPageRearrange = false;
  1197. const chatElm = elements.chat;
  1198. const chatCnt = insp(chatElm);
  1199. if (chatCnt && typeof chatCnt.urlChanged === "function" && secondaryWrapper.contains(chatElm)) {
  1200. if (typeof chatCnt.urlChangedAsync12 === "function") {
  1201. chatCnt.urlChanged();
  1202. } else {
  1203. setTimeout(() => chatCnt.urlChanged(), 136);
  1204. }
  1205. }
  1206. }
  1207. }
  1208. };
  1209. let lastPanel = "";
  1210. let lastTab = "";
  1211. const aoEgmPanels = new MutationObserver(() => {
  1212. Promise.resolve(lockSet["updateEgmPanelsLock"]).then(updateEgmPanels).catch(console.warn);
  1213. });
  1214. const removeKeepCommentsScroller = async (lockId) => {
  1215. if (lockGet["removeKeepCommentsScrollerLock"] !== lockId)
  1216. return;
  1217. await Promise.resolve();
  1218. if (lockGet["removeKeepCommentsScrollerLock"] !== lockId)
  1219. return;
  1220. const ytdFlexyFlm = elements.flexy;
  1221. if (ytdFlexyFlm) {
  1222. ytdFlexyFlm.removeAttribute000("keep-comments-scroller");
  1223. }
  1224. };
  1225. const updateEgmPanels = async (lockId) => {
  1226. if (lockId !== lockGet["updateEgmPanelsLock"])
  1227. return;
  1228. await navigateFinishedPromise.then().catch(console.warn);
  1229. if (lockId !== lockGet["updateEgmPanelsLock"])
  1230. return;
  1231. const ytdFlexyElm = elements.flexy;
  1232. if (!ytdFlexyElm)
  1233. return;
  1234. let newVisiblePanels = [];
  1235. let newHiddenPanels = [];
  1236. let allVisiblePanels = [];
  1237. for (const panelElm of document.querySelectorAll("[tyt-egm-panel][target-id][visibility]")) {
  1238. const visibility = panelElm.getAttribute000("visibility");
  1239. if (visibility === "ENGAGEMENT_PANEL_VISIBILITY_HIDDEN" || panelElm.closest("[hidden]")) {
  1240. if (panelElm.hasAttribute000("tyt-visible-at")) {
  1241. panelElm.removeAttribute000("tyt-visible-at");
  1242. newHiddenPanels.push(panelElm);
  1243. }
  1244. } else if (visibility === "ENGAGEMENT_PANEL_VISIBILITY_EXPANDED" && !panelElm.closest("[hidden]")) {
  1245. let visibleAt = panelElm.getAttribute000("tyt-visible-at");
  1246. if (!visibleAt) {
  1247. panelElm.setAttribute111("tyt-visible-at", Date.now());
  1248. newVisiblePanels.push(panelElm);
  1249. }
  1250. allVisiblePanels.push(panelElm);
  1251. }
  1252. }
  1253. if (newVisiblePanels.length >= 1 && allVisiblePanels.length >= 2) {
  1254. const targetVisible = newVisiblePanels[newVisiblePanels.length - 1];
  1255. const actions = [];
  1256. for (const panelElm of allVisiblePanels) {
  1257. if (panelElm === targetVisible)
  1258. continue;
  1259. actions.push({
  1260. panelId: panelElm.getAttribute000("target-id"),
  1261. toHide: true
  1262. });
  1263. }
  1264. if (actions.length >= 1) {
  1265. ytBtnEgmPanelCore(actions);
  1266. }
  1267. }
  1268. if (allVisiblePanels.length >= 1) {
  1269. ytdFlexyElm.setAttribute111("tyt-egm-panel_", "");
  1270. } else {
  1271. ytdFlexyElm.removeAttribute000("tyt-egm-panel_");
  1272. }
  1273. newVisiblePanels.length = 0;
  1274. newVisiblePanels = null;
  1275. newHiddenPanels.length = 0;
  1276. newHiddenPanels = null;
  1277. allVisiblePanels.length = 0;
  1278. allVisiblePanels = null;
  1279. };
  1280. const checkElementExist = (css, exclude) => {
  1281. for (const p of document.querySelectorAll(css)) {
  1282. if (!p.closest(exclude))
  1283. return p;
  1284. }
  1285. return null;
  1286. };
  1287. let fixInitialTabStateK = 0;
  1288. const { handleNavigateFactory } = (() => {
  1289. let isLoadStartListened = false;
  1290. function findLcComment(lc) {
  1291. if (arguments.length === 1) {
  1292. let element = document.querySelector(`#tab-comments ytd-comments ytd-comment-renderer #header-author a[href*="lc=${lc}"]`);
  1293. if (element) {
  1294. let commentRendererElm = closestFromAnchor.call(element, "ytd-comment-renderer");
  1295. if (commentRendererElm && lc) {
  1296. return {
  1297. lc,
  1298. commentRendererElm
  1299. };
  1300. }
  1301. }
  1302. } else if (arguments.length === 0) {
  1303. let element = document.querySelector(`#tab-comments ytd-comments ytd-comment-renderer > #linked-comment-badge span:not(:empty)`);
  1304. if (element) {
  1305. let commentRendererElm = closestFromAnchor.call(element, "ytd-comment-renderer");
  1306. if (commentRendererElm) {
  1307. let header = _querySelector.call(commentRendererElm, "#header-author");
  1308. if (header) {
  1309. let anchor = _querySelector.call(header, 'a[href*="lc="]');
  1310. if (anchor) {
  1311. let href = anchor.getAttribute("href") || "";
  1312. let m = /[&?]lc=([\w_.-]+)/.exec(href);
  1313. if (m) {
  1314. lc = m[1];
  1315. }
  1316. }
  1317. }
  1318. }
  1319. if (commentRendererElm && lc) {
  1320. return {
  1321. lc,
  1322. commentRendererElm
  1323. };
  1324. }
  1325. }
  1326. }
  1327. return null;
  1328. }
  1329. function lcSwapFuncA(targetLcId, currentLcId) {
  1330. let done = 0;
  1331. try {
  1332. let r1 = findLcComment(currentLcId).commentRendererElm;
  1333. let r2 = findLcComment(targetLcId).commentRendererElm;
  1334. if (typeof insp(r1).data.linkedCommentBadge === "object" && typeof insp(r2).data.linkedCommentBadge === "undefined") {
  1335. let p = Object.assign({}, insp(r1).data.linkedCommentBadge);
  1336. if (((p || 0).metadataBadgeRenderer || 0).trackingParams) {
  1337. delete p.metadataBadgeRenderer.trackingParams;
  1338. }
  1339. const v1 = findContentsRenderer(r1);
  1340. const v2 = findContentsRenderer(r2);
  1341. if (v1.parent === v2.parent && (v2.parent.nodeName === "YTD-COMMENTS" || v2.parent.nodeName === "YTD-ITEM-SECTION-RENDERER")) {
  1342. } else {
  1343. return false;
  1344. }
  1345. if (v2.index >= 0) {
  1346. if (v2.parent.nodeName === "YTD-COMMENT-REPLIES-RENDERER") {
  1347. if (lcSwapFuncB(targetLcId, currentLcId, p)) {
  1348. done = 1;
  1349. }
  1350. done = 1;
  1351. } else {
  1352. const v2pCnt = insp(v2.parent);
  1353. const v2Conents = (v2pCnt.data || 0).contents || 0;
  1354. if (!v2Conents)
  1355. ;
  1356. v2pCnt.data = Object.assign({}, v2pCnt.data, { contents: [].concat([v2Conents[v2.index]], v2Conents.slice(0, v2.index), v2Conents.slice(v2.index + 1)) });
  1357. if (lcSwapFuncB(targetLcId, currentLcId, p)) {
  1358. done = 1;
  1359. }
  1360. }
  1361. }
  1362. }
  1363. } catch (e) {
  1364. }
  1365. return done === 1;
  1366. }
  1367. function lcSwapFuncB(targetLcId, currentLcId, _p) {
  1368. let done = 0;
  1369. try {
  1370. let r1 = findLcComment(currentLcId).commentRendererElm;
  1371. let r1cnt = insp(r1);
  1372. let r2 = findLcComment(targetLcId).commentRendererElm;
  1373. let r2cnt = insp(r2);
  1374. const r1d = r1cnt.data;
  1375. let p = Object.assign({}, _p);
  1376. r1d.linkedCommentBadge = null;
  1377. delete r1d.linkedCommentBadge;
  1378. let q = Object.assign({}, r1d);
  1379. q.linkedCommentBadge = null;
  1380. delete q.linkedCommentBadge;
  1381. r1cnt.data = Object.assign({}, q);
  1382. r2cnt.data = Object.assign({}, r2cnt.data, { linkedCommentBadge: p });
  1383. done = 1;
  1384. } catch (e) {
  1385. }
  1386. return done === 1;
  1387. }
  1388. const loadStartFx = async (evt) => {
  1389. let media = (evt || 0).target || 0;
  1390. if (media.nodeName === "VIDEO" || media.nodeName === "AUDIO") {
  1391. } else
  1392. return;
  1393. const newMedia = media;
  1394. const media1 = common.getMediaElement(0);
  1395. const media2 = common.getMediaElements(2);
  1396. if (media1 !== null && media2.length > 0) {
  1397. if (newMedia !== media1 && media1.paused === false) {
  1398. if (isVideoPlaying(media1)) {
  1399. Promise.resolve(newMedia).then((video) => video.paused === false && video.pause()).catch(console.warn);
  1400. }
  1401. } else if (newMedia === media1) {
  1402. for (const s of media2) {
  1403. if (s.paused === false) {
  1404. Promise.resolve(s).then((s2) => s2.paused === false && s2.pause()).catch(console.warn);
  1405. break;
  1406. }
  1407. }
  1408. } else {
  1409. Promise.resolve(media1).then((video1) => video1.paused === false && video1.pause()).catch(console.warn);
  1410. }
  1411. }
  1412. };
  1413. const getBrowsableEndPoint = (req) => {
  1414. let valid = false;
  1415. let endpoint = req ? req.command : null;
  1416. if (endpoint && (endpoint.commandMetadata || 0).webCommandMetadata && endpoint.watchEndpoint) {
  1417. let videoId = endpoint.watchEndpoint.videoId;
  1418. let url = endpoint.commandMetadata.webCommandMetadata.url;
  1419. if (typeof videoId === "string" && typeof url === "string" && url.indexOf("lc=") > 0) {
  1420. let m = /^\/watch\?v=([\w_-]+)&lc=([\w_.-]+)$/.exec(url);
  1421. if (m && m[1] === videoId) {
  1422. let targetLc = findLcComment(m[2]);
  1423. let currentLc = targetLc ? findLcComment() : null;
  1424. if (targetLc && currentLc) {
  1425. let done = targetLc.lc === currentLc.lc ? 1 : lcSwapFuncA(targetLc.lc, currentLc.lc) ? 1 : 0;
  1426. if (done === 1) {
  1427. common.xReplaceState(history.state, url);
  1428. return;
  1429. }
  1430. }
  1431. }
  1432. }
  1433. }
  1434. if (endpoint && (endpoint.commandMetadata || 0).webCommandMetadata && endpoint.browseEndpoint && isChannelId(endpoint.browseEndpoint.browseId)) {
  1435. valid = true;
  1436. } else if (endpoint && (endpoint.browseEndpoint || endpoint.searchEndpoint) && !endpoint.urlEndpoint && !endpoint.watchEndpoint) {
  1437. if (endpoint.browseEndpoint && endpoint.browseEndpoint.browseId === "FEwhat_to_watch") {
  1438. const playerMedia = common.getMediaElement(1);
  1439. if (playerMedia && playerMedia.paused === false)
  1440. valid = true;
  1441. } else if (endpoint.commandMetadata && endpoint.commandMetadata.webCommandMetadata) {
  1442. let meta = endpoint.commandMetadata.webCommandMetadata;
  1443. if (meta && meta.url && meta.webPageType) {
  1444. valid = true;
  1445. }
  1446. }
  1447. }
  1448. if (!valid)
  1449. endpoint = null;
  1450. return endpoint;
  1451. };
  1452. const shouldUseMiniPlayer = () => {
  1453. const isSubTypeExist = document.querySelector("ytd-page-manager#page-manager > ytd-browse[page-subtype]");
  1454. if (isSubTypeExist)
  1455. return true;
  1456. const movie_player = [...document.querySelectorAll("#movie_player")].filter((e) => !e.closest("[hidden]"))[0];
  1457. if (movie_player) {
  1458. const media = qsOne(movie_player, "video[class], audio[class]");
  1459. if (media && media.currentTime > 3 && media.duration - media.currentTime > 3 && media.paused === false) {
  1460. return true;
  1461. }
  1462. }
  1463. return false;
  1464. };
  1465. const conditionFulfillment = (req) => {
  1466. const endpoint = req ? req.command : null;
  1467. if (!endpoint)
  1468. return;
  1469. if (endpoint && (endpoint.commandMetadata || 0).webCommandMetadata && endpoint.watchEndpoint) {
  1470. } else if (endpoint && (endpoint.commandMetadata || 0).webCommandMetadata && endpoint.browseEndpoint && isChannelId(endpoint.browseEndpoint.browseId)) {
  1471. } else if (endpoint && (endpoint.browseEndpoint || endpoint.searchEndpoint) && !endpoint.urlEndpoint && !endpoint.watchEndpoint) {
  1472. } else {
  1473. return false;
  1474. }
  1475. if (!shouldUseMiniPlayer())
  1476. return false;
  1477. if (pageType !== "watch")
  1478. return false;
  1479. if (!checkElementExist("ytd-watch-flexy #player button.ytp-miniplayer-button.ytp-button", "[hidden]")) {
  1480. return false;
  1481. }
  1482. return true;
  1483. };
  1484. let u38 = 0;
  1485. const fixChannelAboutPopup = async (t38) => {
  1486. let promise = new PromiseExternal();
  1487. const f = () => {
  1488. promise && promise.resolve();
  1489. promise = null;
  1490. };
  1491. document.addEventListener("yt-navigate-finish", f, false);
  1492. await promise.then();
  1493. promise = null;
  1494. document.removeEventListener("yt-navigate-finish", f, false);
  1495. if (t38 !== u38)
  1496. return;
  1497. setTimeout(() => {
  1498. const currentAbout = [...document.querySelectorAll("ytd-about-channel-renderer")].filter((e) => !e.closest("[hidden]"))[0];
  1499. let okay = false;
  1500. if (!currentAbout)
  1501. okay = true;
  1502. else {
  1503. const popupContainer = currentAbout.closest("ytd-popup-container");
  1504. if (popupContainer) {
  1505. const cnt = insp(popupContainer);
  1506. let arr = null;
  1507. try {
  1508. arr = cnt.handleGetOpenedPopupsAction_();
  1509. } catch (e) {
  1510. }
  1511. if (arr && arr.length === 0)
  1512. okay = true;
  1513. } else {
  1514. okay = false;
  1515. }
  1516. }
  1517. if (okay) {
  1518. const descriptionModel = [...document.querySelectorAll("yt-description-preview-view-model")].filter((e) => !e.closest("[hidden]"))[0];
  1519. if (descriptionModel) {
  1520. const button = [...descriptionModel.querySelectorAll("button")].filter((e) => !e.closest("[hidden]") && `${e.textContent}`.trim().length > 0)[0];
  1521. if (button) {
  1522. button.click();
  1523. }
  1524. }
  1525. }
  1526. }, 80);
  1527. };
  1528. const handleNavigateFactory2 = (handleNavigate) => {
  1529. return function(req) {
  1530. if (u38 > 1e9)
  1531. u38 = 9;
  1532. const t38 = ++u38;
  1533. const $this = this;
  1534. const $arguments = arguments;
  1535. let endpoint = null;
  1536. if (conditionFulfillment(req)) {
  1537. endpoint = getBrowsableEndPoint(req);
  1538. }
  1539. if (!endpoint || !shouldUseMiniPlayer())
  1540. return handleNavigate.apply($this, $arguments);
  1541. const ytdAppElm = document.querySelector("ytd-app");
  1542. const ytdAppCnt = insp(ytdAppElm);
  1543. let object = null;
  1544. try {
  1545. object = ytdAppCnt.data.response.currentVideoEndpoint.watchEndpoint || null;
  1546. } catch (e) {
  1547. object = null;
  1548. }
  1549. if (typeof object !== "object")
  1550. object = null;
  1551. const once = { once: true };
  1552. if (object !== null && !("playlistId" in object)) {
  1553. let wObject = mWeakRef(object);
  1554. const N = 3;
  1555. let count = 0;
  1556. Object.defineProperty(kRef(wObject) || {}, "playlistId", {
  1557. get() {
  1558. count++;
  1559. if (count === N) {
  1560. delete this.playlistId;
  1561. }
  1562. return "*";
  1563. },
  1564. set(value) {
  1565. delete this.playlistId;
  1566. this.playlistId = value;
  1567. },
  1568. enumerable: false,
  1569. configurable: true
  1570. });
  1571. let playlistClearout = null;
  1572. let timeoutid = 0;
  1573. Promise.race([
  1574. new Promise((r) => {
  1575. timeoutid = setTimeout(r, 4e3);
  1576. }),
  1577. new Promise((r) => {
  1578. playlistClearout = () => {
  1579. if (timeoutid > 0) {
  1580. clearTimeout(timeoutid);
  1581. timeoutid = 0;
  1582. }
  1583. r();
  1584. };
  1585. document.addEventListener("yt-page-type-changed", playlistClearout, once);
  1586. })
  1587. ]).then(() => {
  1588. if (timeoutid !== 0) {
  1589. playlistClearout && document.removeEventListener("yt-page-type-changed", playlistClearout, once);
  1590. timeoutid = 0;
  1591. }
  1592. playlistClearout = null;
  1593. count = N - 1;
  1594. let object2 = kRef(wObject);
  1595. wObject = null;
  1596. return object2 ? object2.playlistId : null;
  1597. }).catch(console.warn);
  1598. }
  1599. if (!isLoadStartListened) {
  1600. isLoadStartListened = true;
  1601. document.addEventListener("loadstart", loadStartFx, true);
  1602. }
  1603. const endpointURL = `${endpoint?.commandMetadata?.webCommandMetadata?.url || ""}`;
  1604. if (endpointURL && endpointURL.endsWith("/about") && /\/channel\/UC[-_a-zA-Z0-9+=.]{22}\/about/.test(endpointURL)) {
  1605. fixChannelAboutPopup(t38);
  1606. }
  1607. handleNavigate.apply($this, $arguments);
  1608. };
  1609. };
  1610. return { handleNavigateFactory: handleNavigateFactory2 };
  1611. })();
  1612. const common = (() => {
  1613. let mediaModeLock = 0;
  1614. const _getMediaElement = (i) => {
  1615. if (mediaModeLock === 0) {
  1616. 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]");
  1617. if (e) {
  1618. if (e.nodeName === "VIDEO")
  1619. mediaModeLock = 1;
  1620. else if (e.nodeName === "AUDIO")
  1621. mediaModeLock = 2;
  1622. }
  1623. }
  1624. if (!mediaModeLock)
  1625. return null;
  1626. if (mediaModeLock === 1) {
  1627. switch (i) {
  1628. case 1:
  1629. return "ytd-player#ytd-player video[src]";
  1630. case 2:
  1631. return 'ytd-browse[role="main"] video[src]';
  1632. case 0:
  1633. default:
  1634. return "#movie_player video[src]";
  1635. }
  1636. } else if (mediaModeLock === 2) {
  1637. switch (i) {
  1638. case 1:
  1639. return "ytd-player#ytd-player audio.video-stream.html5-main-video[src]";
  1640. case 2:
  1641. return 'ytd-browse[role="main"] audio.video-stream.html5-main-video[src]';
  1642. case 0:
  1643. default:
  1644. return "#movie_player audio.video-stream.html5-main-video[src]";
  1645. }
  1646. }
  1647. return null;
  1648. };
  1649. return {
  1650. xReplaceState(s, u) {
  1651. try {
  1652. history.replaceState(s, "", u);
  1653. } catch (e) {
  1654. }
  1655. if (s.endpoint) {
  1656. try {
  1657. const ytdAppElm = document.querySelector("ytd-app");
  1658. const ytdAppCnt = insp(ytdAppElm);
  1659. ytdAppCnt.replaceState(s.endpoint, "", u);
  1660. } catch (e) {
  1661. }
  1662. }
  1663. },
  1664. getMediaElement(i) {
  1665. let s = _getMediaElement(i) || "";
  1666. if (s)
  1667. return document.querySelector(s);
  1668. return null;
  1669. },
  1670. getMediaElements(i) {
  1671. let s = _getMediaElement(i) || "";
  1672. if (s)
  1673. return document.querySelectorAll(s);
  1674. return [];
  1675. }
  1676. };
  1677. })();
  1678. let inPageRearrange = false;
  1679. let tmpLastVideoId = "";
  1680. const getCurrentVideoId = () => {
  1681. const ytdFlexyElm = elements.flexy;
  1682. const ytdFlexyCnt = insp(ytdFlexyElm);
  1683. if (ytdFlexyCnt && typeof ytdFlexyCnt.videoId === "string")
  1684. return ytdFlexyCnt.videoId;
  1685. if (ytdFlexyElm && typeof ytdFlexyElm.videoId === "string")
  1686. return ytdFlexyElm.videoId;
  1687. return "";
  1688. };
  1689. const holdInlineExpanderAlwaysExpanded = (inlineExpanderCnt) => {
  1690. if (inlineExpanderCnt.alwaysShowExpandButton === true)
  1691. inlineExpanderCnt.alwaysShowExpandButton = false;
  1692. if (typeof (inlineExpanderCnt.collapseLabel || 0) === "string")
  1693. inlineExpanderCnt.collapseLabel = "";
  1694. if (typeof (inlineExpanderCnt.expandLabel || 0) === "string")
  1695. inlineExpanderCnt.expandLabel = "";
  1696. if (inlineExpanderCnt.showCollapseButton === true)
  1697. inlineExpanderCnt.showCollapseButton = false;
  1698. if (inlineExpanderCnt.showExpandButton === true)
  1699. inlineExpanderCnt.showExpandButton = false;
  1700. if (inlineExpanderCnt.expandButton instanceof HTMLElement_) {
  1701. inlineExpanderCnt.expandButton = null;
  1702. inlineExpanderCnt.expandButton.remove();
  1703. }
  1704. };
  1705. const fixInlineExpanderDisplay = (inlineExpanderCnt) => {
  1706. try {
  1707. inlineExpanderCnt.updateIsAttributedExpanded();
  1708. } catch (e) {
  1709. }
  1710. try {
  1711. inlineExpanderCnt.updateIsFormattedExpanded();
  1712. } catch (e) {
  1713. }
  1714. try {
  1715. inlineExpanderCnt.updateTextOnSnippetTypeChange();
  1716. } catch (e) {
  1717. }
  1718. try {
  1719. inlineExpanderCnt.updateStyles();
  1720. } catch (e) {
  1721. }
  1722. };
  1723. const fixInlineExpanderMethods = (inlineExpanderCnt) => {
  1724. if (inlineExpanderCnt && !inlineExpanderCnt.__$idncjk8487$__) {
  1725. inlineExpanderCnt.__$idncjk8487$__ = true;
  1726. inlineExpanderCnt.updateTextOnSnippetTypeChange = function() {
  1727. };
  1728. inlineExpanderCnt.isResetMutation = true;
  1729. fixInlineExpanderDisplay(inlineExpanderCnt);
  1730. }
  1731. };
  1732. const fixInlineExpanderContent = () => {
  1733. const mainInfo = getMainInfo();
  1734. if (!mainInfo)
  1735. return;
  1736. const inlineExpanderElm = mainInfo.querySelector("ytd-text-inline-expander");
  1737. const inlineExpanderCnt = insp(inlineExpanderElm);
  1738. fixInlineExpanderMethods(inlineExpanderCnt);
  1739. };
  1740. const plugin = {
  1741. "minibrowser": {
  1742. activated: false,
  1743. toUse: true,
  1744. activate() {
  1745. if (this.activated)
  1746. return;
  1747. const isPassiveArgSupport2 = typeof IntersectionObserver === "function";
  1748. if (!isPassiveArgSupport2)
  1749. return;
  1750. this.activated = true;
  1751. const ytdAppElm = document.querySelector("ytd-app");
  1752. const ytdAppCnt = insp(ytdAppElm);
  1753. if (!ytdAppCnt)
  1754. return;
  1755. const cProto = ytdAppCnt.constructor.prototype;
  1756. if (!cProto.handleNavigate)
  1757. return;
  1758. if (cProto.handleNavigate.__ma355__)
  1759. return;
  1760. cProto.handleNavigate = handleNavigateFactory(cProto.handleNavigate);
  1761. cProto.handleNavigate.__ma355__ = 1;
  1762. }
  1763. },
  1764. "autoExpandInfoDesc": {
  1765. activated: false,
  1766. toUse: false,
  1767. mo: null,
  1768. promiseReady: new PromiseExternal(),
  1769. moFn(lockId) {
  1770. if (lockGet["autoExpandInfoDescAttrAsyncLock"] !== lockId)
  1771. return;
  1772. const mainInfo = getMainInfo();
  1773. if (!mainInfo)
  1774. return;
  1775. switch (((mainInfo || 0).nodeName || "").toLowerCase()) {
  1776. case "ytd-expander":
  1777. if (mainInfo.hasAttribute000("collapsed")) {
  1778. let success = false;
  1779. try {
  1780. insp(mainInfo).handleMoreTap(new Event("tap"));
  1781. success = true;
  1782. } catch (e) {
  1783. }
  1784. if (success)
  1785. mainInfo.setAttribute111("tyt-no-less-btn", "");
  1786. }
  1787. break;
  1788. case "ytd-expandable-video-description-body-renderer":
  1789. const inlineExpanderElm = mainInfo.querySelector("ytd-text-inline-expander");
  1790. const inlineExpanderCnt = insp(inlineExpanderElm);
  1791. if (inlineExpanderCnt && inlineExpanderCnt.isExpanded === false) {
  1792. inlineExpanderCnt.isExpanded = true;
  1793. inlineExpanderCnt.isExpandedChanged();
  1794. }
  1795. break;
  1796. }
  1797. },
  1798. activate() {
  1799. if (this.activated)
  1800. return;
  1801. this.moFn = this.moFn.bind(this);
  1802. this.mo = new MutationObserver(() => {
  1803. Promise.resolve(lockSet["autoExpandInfoDescAttrAsyncLock"]).then(this.moFn).catch(console.warn);
  1804. });
  1805. this.activated = true;
  1806. this.promiseReady.resolve();
  1807. },
  1808. async onMainInfoSet(mainInfo) {
  1809. await this.promiseReady.then();
  1810. if (mainInfo.nodeName.toLowerCase() === "ytd-expander") {
  1811. this.mo.observe(mainInfo, { attributes: true, attributeFilter: ["collapsed", "attr-8ifv7"] });
  1812. } else {
  1813. this.mo.observe(mainInfo, { attributes: true, attributeFilter: ["attr-8ifv7"] });
  1814. }
  1815. mainInfo.incAttribute111("attr-8ifv7");
  1816. }
  1817. },
  1818. "fullChannelNameOnHover": {
  1819. activated: false,
  1820. toUse: true,
  1821. mo: null,
  1822. ro: null,
  1823. promiseReady: new PromiseExternal(),
  1824. checkResize: 0,
  1825. mouseEnterFn(evt) {
  1826. const target = evt ? evt.target : null;
  1827. if (!(target instanceof HTMLElement_))
  1828. return;
  1829. const metaDataElm = target.closest("ytd-watch-metadata");
  1830. metaDataElm.classList.remove("tyt-metadata-hover-resized");
  1831. this.checkResize = Date.now() + 300;
  1832. metaDataElm.classList.add("tyt-metadata-hover");
  1833. },
  1834. mouseLeaveFn(evt) {
  1835. const target = evt ? evt.target : null;
  1836. if (!(target instanceof HTMLElement_))
  1837. return;
  1838. const metaDataElm = target.closest("ytd-watch-metadata");
  1839. metaDataElm.classList.remove("tyt-metadata-hover-resized");
  1840. metaDataElm.classList.remove("tyt-metadata-hover");
  1841. },
  1842. moFn(lockId) {
  1843. if (lockGet["fullChannelNameOnHoverAttrAsyncLock"] !== lockId)
  1844. return;
  1845. const uploadInfo = document.querySelector("#primary.ytd-watch-flexy ytd-watch-metadata #upload-info");
  1846. if (!uploadInfo)
  1847. return;
  1848. const evtOpt = { passive: true, capture: false };
  1849. uploadInfo.removeEventListener("pointerenter", this.mouseEnterFn, evtOpt);
  1850. uploadInfo.removeEventListener("pointerleave", this.mouseLeaveFn, evtOpt);
  1851. uploadInfo.addEventListener("pointerenter", this.mouseEnterFn, evtOpt);
  1852. uploadInfo.addEventListener("pointerleave", this.mouseLeaveFn, evtOpt);
  1853. },
  1854. async onNavigateFinish() {
  1855. await this.promiseReady.then();
  1856. const uploadInfo = document.querySelector("#primary.ytd-watch-flexy ytd-watch-metadata #upload-info");
  1857. if (!uploadInfo)
  1858. return;
  1859. this.mo.observe(uploadInfo, { attributes: true, attributeFilter: ["hidden", "attr-3wb0k"] });
  1860. uploadInfo.incAttribute111("attr-3wb0k");
  1861. this.ro.observe(uploadInfo);
  1862. },
  1863. activate() {
  1864. if (this.activated)
  1865. return;
  1866. const isPassiveArgSupport2 = typeof IntersectionObserver === "function";
  1867. if (!isPassiveArgSupport2)
  1868. return;
  1869. this.activated = true;
  1870. this.mouseEnterFn = this.mouseEnterFn.bind(this);
  1871. this.mouseLeaveFn = this.mouseLeaveFn.bind(this);
  1872. this.moFn = this.moFn.bind(this);
  1873. this.mo = new MutationObserver(() => {
  1874. Promise.resolve(lockSet["fullChannelNameOnHoverAttrAsyncLock"]).then(this.moFn).catch(console.warn);
  1875. });
  1876. this.ro = new ResizeObserver((mutations) => {
  1877. if (Date.now() > this.checkResize)
  1878. return;
  1879. for (const mutation of mutations) {
  1880. const uploadInfo = mutation.target;
  1881. if (uploadInfo && mutation.contentRect.width > 0 && mutation.contentRect.height > 0) {
  1882. const metaDataElm = uploadInfo.closest("ytd-watch-metadata");
  1883. if (metaDataElm.classList.contains("tyt-metadata-hover")) {
  1884. metaDataElm.classList.add("tyt-metadata-hover-resized");
  1885. }
  1886. break;
  1887. }
  1888. }
  1889. });
  1890. this.promiseReady.resolve();
  1891. }
  1892. }
  1893. };
  1894. if (sessionStorage.__$tmp_UseAutoExpandInfoDesc$__)
  1895. plugin.autoExpandInfoDesc.toUse = true;
  1896. const __attachedSymbol__ = Symbol();
  1897. const makeInitAttached = (tag) => {
  1898. const inPageRearrange_ = inPageRearrange;
  1899. inPageRearrange = false;
  1900. for (const elm of document.querySelectorAll(`${tag}`)) {
  1901. const cnt = insp(elm) || 0;
  1902. if (typeof cnt.attached498 === "function" && !elm[__attachedSymbol__])
  1903. Promise.resolve(elm).then(eventMap[`${tag}::attached`]).catch(console.warn);
  1904. }
  1905. inPageRearrange = inPageRearrange_;
  1906. };
  1907. const getGeneralChatElement = async () => {
  1908. for (let i = 2; i-- > 0; ) {
  1909. let t = document.querySelector("#columns.style-scope.ytd-watch-flexy ytd-live-chat-frame#chat");
  1910. if (t instanceof Element)
  1911. return t;
  1912. if (i > 0) {
  1913. await delayPn(200);
  1914. }
  1915. }
  1916. return null;
  1917. };
  1918. const nsTemplateObtain = () => {
  1919. let nsTemplate = document.querySelector("ytd-watch-flexy noscript[ns-template]");
  1920. if (!nsTemplate) {
  1921. nsTemplate = document.createElement("noscript");
  1922. nsTemplate.setAttribute("ns-template", "");
  1923. document.querySelector("ytd-watch-flexy").appendChild(nsTemplate);
  1924. }
  1925. return nsTemplate;
  1926. };
  1927. const isPageDOM = (elm, selector) => {
  1928. if (!elm || !(elm instanceof Element) || !elm.nodeName)
  1929. return false;
  1930. if (!elm.closest(selector))
  1931. return false;
  1932. if (elm.isConnected !== true)
  1933. return false;
  1934. return true;
  1935. };
  1936. const invalidFlexyParent = (hostElement2) => {
  1937. if (hostElement2 instanceof HTMLElement) {
  1938. const hasFlexyParent = HTMLElement.prototype.closest.call(hostElement2, "ytd-watch-flexy");
  1939. if (!hasFlexyParent)
  1940. return true;
  1941. const currentFlexy = elements.flexy;
  1942. if (currentFlexy && currentFlexy !== hasFlexyParent)
  1943. return true;
  1944. }
  1945. return false;
  1946. };
  1947. const eventMap = {
  1948. "ceHack": () => {
  1949. mLoaded.flag |= 2;
  1950. document.documentElement.setAttribute111("tabview-loaded", mLoaded.makeString());
  1951. retrieveCE("ytd-watch-flexy").then(eventMap["ytd-watch-flexy::defined"]).catch(console.warn);
  1952. retrieveCE("ytd-expander").then(eventMap["ytd-expander::defined"]).catch(console.warn);
  1953. retrieveCE("ytd-watch-next-secondary-results-renderer").then(eventMap["ytd-watch-next-secondary-results-renderer::defined"]).catch(console.warn);
  1954. retrieveCE("ytd-comments-header-renderer").then(eventMap["ytd-comments-header-renderer::defined"]).catch(console.warn);
  1955. retrieveCE("ytd-live-chat-frame").then(eventMap["ytd-live-chat-frame::defined"]).catch(console.warn);
  1956. retrieveCE("ytd-comments").then(eventMap["ytd-comments::defined"]).catch(console.warn);
  1957. retrieveCE("ytd-engagement-panel-section-list-renderer").then(eventMap["ytd-engagement-panel-section-list-renderer::defined"]).catch(console.warn);
  1958. retrieveCE("ytd-watch-metadata").then(eventMap["ytd-watch-metadata::defined"]).catch(console.warn);
  1959. retrieveCE("ytd-playlist-panel-renderer").then(eventMap["ytd-playlist-panel-renderer::defined"]).catch(console.warn);
  1960. retrieveCE("ytd-expandable-video-description-body-renderer").then(eventMap["ytd-expandable-video-description-body-renderer::defined"]).catch(console.warn);
  1961. },
  1962. "fixForTabDisplay": (isResize) => {
  1963. bFixForResizedTabLater = false;
  1964. for (const element of document.querySelectorAll("[io-intersected]")) {
  1965. const cnt = insp(element);
  1966. if (element instanceof HTMLElement_ && typeof cnt.calculateCanCollapse === "function") {
  1967. try {
  1968. cnt.calculateCanCollapse(true);
  1969. } catch (e) {
  1970. }
  1971. }
  1972. }
  1973. if (!isResize && lastTab === "#tab-info") {
  1974. for (const element of document.querySelectorAll("#tab-info ytd-video-description-infocards-section-renderer, #tab-info yt-chip-cloud-renderer, #tab-info ytd-horizontal-card-list-renderer")) {
  1975. const cnt = insp(element);
  1976. if (element instanceof HTMLElement_ && typeof cnt.notifyResize === "function") {
  1977. try {
  1978. cnt.notifyResize();
  1979. } catch (e) {
  1980. }
  1981. }
  1982. }
  1983. for (const element of document.querySelectorAll("#tab-info ytd-text-inline-expander")) {
  1984. const cnt = insp(element);
  1985. if (element instanceof HTMLElement_ && typeof cnt.resize === "function") {
  1986. cnt.resize(false);
  1987. }
  1988. fixInlineExpanderDisplay(cnt);
  1989. }
  1990. }
  1991. },
  1992. "ytd-watch-flexy::defined": (cProto) => {
  1993. if (!cProto.updateChatLocation498 && typeof cProto.updateChatLocation === "function" && cProto.updateChatLocation.length === 0) {
  1994. cProto.updateChatLocation498 = cProto.updateChatLocation;
  1995. cProto.updateChatLocation = updateChatLocation498;
  1996. }
  1997. },
  1998. "ytd-watch-next-secondary-results-renderer::defined": (cProto) => {
  1999. if (!cProto.attached498 && typeof cProto.attached === "function") {
  2000. cProto.attached498 = cProto.attached;
  2001. cProto.attached = function() {
  2002. if (!inPageRearrange)
  2003. Promise.resolve(this.hostElement).then(eventMap["ytd-watch-next-secondary-results-renderer::attached"]).catch(console.warn);
  2004. return this.attached498();
  2005. };
  2006. }
  2007. if (!cProto.detached498 && typeof cProto.detached === "function") {
  2008. cProto.detached498 = cProto.detached;
  2009. cProto.detached = function() {
  2010. if (!inPageRearrange)
  2011. Promise.resolve(this.hostElement).then(eventMap["ytd-watch-next-secondary-results-renderer::detached"]).catch(console.warn);
  2012. return this.detached498();
  2013. };
  2014. }
  2015. makeInitAttached("ytd-watch-next-secondary-results-renderer");
  2016. },
  2017. "ytd-watch-next-secondary-results-renderer::attached": (hostElement2) => {
  2018. if (invalidFlexyParent(hostElement2))
  2019. return;
  2020. if (hostElement2 instanceof Element)
  2021. hostElement2[__attachedSymbol__] = true;
  2022. if (!(hostElement2 instanceof HTMLElement_) || !(hostElement2.classList.length > 0) || hostElement2.closest("noscript"))
  2023. return;
  2024. if (hostElement2.isConnected !== true)
  2025. return;
  2026. if (hostElement2 instanceof HTMLElement_ && hostElement2.matches("#columns #related ytd-watch-next-secondary-results-renderer") && !hostElement2.matches("#right-tabs ytd-watch-next-secondary-results-renderer, [hidden] ytd-watch-next-secondary-results-renderer")) {
  2027. elements.related = hostElement2.closest("#related");
  2028. hostElement2.setAttribute111("tyt-videos-list", "");
  2029. }
  2030. },
  2031. "ytd-watch-next-secondary-results-renderer::detached": (hostElement2) => {
  2032. if (!(hostElement2 instanceof HTMLElement_) || hostElement2.closest("noscript"))
  2033. return;
  2034. if (hostElement2.isConnected !== false)
  2035. return;
  2036. if (hostElement2.hasAttribute000("tyt-videos-list")) {
  2037. elements.related = null;
  2038. hostElement2.removeAttribute000("tyt-videos-list");
  2039. }
  2040. },
  2041. "settingCommentsVideoId": (hostElement2) => {
  2042. if (!(hostElement2 instanceof HTMLElement_) || !(hostElement2.classList.length > 0) || hostElement2.closest("noscript"))
  2043. return;
  2044. const cnt = insp(hostElement2);
  2045. const commentsArea = elements.comments;
  2046. if (commentsArea !== hostElement2 || hostElement2.isConnected !== true || cnt.isAttached !== true || !cnt.data || cnt.hidden !== false)
  2047. return;
  2048. const ytdFlexyElm = elements.flexy;
  2049. const ytdFlexyCnt = ytdFlexyElm ? insp(ytdFlexyElm) : null;
  2050. if (ytdFlexyCnt && ytdFlexyCnt.videoId) {
  2051. hostElement2.setAttribute111("tyt-comments-video-id", ytdFlexyCnt.videoId);
  2052. } else {
  2053. hostElement2.removeAttribute000("tyt-comments-video-id");
  2054. }
  2055. },
  2056. "checkCommentsShouldBeHidden": (lockId) => {
  2057. if (lockGet["checkCommentsShouldBeHiddenLock"] !== lockId)
  2058. return;
  2059. const commentsArea = elements.comments;
  2060. const ytdFlexyElm = elements.flexy;
  2061. if (commentsArea && ytdFlexyElm && !commentsArea.hasAttribute000("hidden")) {
  2062. const ytdFlexyCnt = insp(ytdFlexyElm);
  2063. if (typeof ytdFlexyCnt.videoId === "string") {
  2064. const commentsVideoId = commentsArea.getAttribute("tyt-comments-video-id");
  2065. if (commentsVideoId && commentsVideoId !== ytdFlexyCnt.videoId) {
  2066. commentsArea.setAttribute111("hidden", "");
  2067. }
  2068. }
  2069. }
  2070. },
  2071. "ytd-comments::defined": (cProto) => {
  2072. if (!cProto.attached498 && typeof cProto.attached === "function") {
  2073. cProto.attached498 = cProto.attached;
  2074. cProto.attached = function() {
  2075. if (!inPageRearrange)
  2076. Promise.resolve(this.hostElement).then(eventMap["ytd-comments::attached"]).catch(console.warn);
  2077. return this.attached498();
  2078. };
  2079. }
  2080. if (!cProto.detached498 && typeof cProto.detached === "function") {
  2081. cProto.detached498 = cProto.detached;
  2082. cProto.detached = function() {
  2083. if (!inPageRearrange)
  2084. Promise.resolve(this.hostElement).then(eventMap["ytd-comments::detached"]).catch(console.warn);
  2085. return this.detached498();
  2086. };
  2087. }
  2088. cProto._createPropertyObserver("data", "_dataChanged498", void 0);
  2089. cProto._dataChanged498 = function() {
  2090. Promise.resolve(this.hostElement).then(eventMap["ytd-comments::_dataChanged498"]).catch(console.warn);
  2091. };
  2092. makeInitAttached("ytd-comments");
  2093. },
  2094. "ytd-comments::_dataChanged498": (hostElement2) => {
  2095. if (!hostElement2.hasAttribute000("tyt-comments-area"))
  2096. return;
  2097. let commentsDataStatus = 0;
  2098. const cnt = insp(hostElement2);
  2099. const data = cnt ? cnt.data : null;
  2100. const contents = data ? data.contents : null;
  2101. if (data) {
  2102. if (contents && contents.length === 1 && contents[0].messageRenderer) {
  2103. commentsDataStatus = 2;
  2104. }
  2105. if (contents && contents.length > 1 && contents[0].commentThreadRenderer) {
  2106. commentsDataStatus = 1;
  2107. }
  2108. }
  2109. if (commentsDataStatus) {
  2110. hostElement2.setAttribute111("tyt-comments-data-status", commentsDataStatus);
  2111. } else {
  2112. hostElement2.removeAttribute000("tyt-comments-data-status");
  2113. }
  2114. Promise.resolve(hostElement2).then(eventMap["settingCommentsVideoId"]).catch(console.warn);
  2115. },
  2116. "ytd-comments::attached": async (hostElement2) => {
  2117. if (invalidFlexyParent(hostElement2))
  2118. return;
  2119. if (hostElement2 instanceof Element)
  2120. hostElement2[__attachedSymbol__] = true;
  2121. if (!(hostElement2 instanceof HTMLElement_) || !(hostElement2.classList.length > 0) || hostElement2.closest("noscript"))
  2122. return;
  2123. if (hostElement2.isConnected !== true)
  2124. return;
  2125. if (!hostElement2 || hostElement2.id !== "comments")
  2126. return;
  2127. elements.comments = hostElement2;
  2128. Promise.resolve(hostElement2).then(eventMap["settingCommentsVideoId"]).catch(console.warn);
  2129. aoComment.observe(hostElement2, { attributes: true });
  2130. hostElement2.setAttribute111("tyt-comments-area", "");
  2131. const lockId = lockSet["rightTabReadyLock02"];
  2132. await rightTabsProvidedPromise.then();
  2133. if (lockGet["rightTabReadyLock02"] !== lockId)
  2134. return;
  2135. if (elements.comments !== hostElement2)
  2136. return;
  2137. if (hostElement2.isConnected === false)
  2138. return;
  2139. if (hostElement2 && !hostElement2.closest("#right-tabs")) {
  2140. document.querySelector("#tab-comments").assignChildern111(null, hostElement2, null);
  2141. } else {
  2142. const shouldTabVisible = elements.comments && elements.comments.closest("#tab-comments") && !elements.comments.closest("[hidden]");
  2143. document.querySelector('[tyt-tab-content="#tab-comments"]').classList.toggle("tab-btn-hidden", !shouldTabVisible);
  2144. Promise.resolve(lockSet["removeKeepCommentsScrollerLock"]).then(removeKeepCommentsScroller).catch(console.warn);
  2145. }
  2146. },
  2147. "ytd-comments::detached": (hostElement2) => {
  2148. if (!(hostElement2 instanceof HTMLElement_) || hostElement2.closest("noscript"))
  2149. return;
  2150. if (hostElement2.isConnected !== false)
  2151. return;
  2152. if (hostElement2.hasAttribute000("tyt-comments-area")) {
  2153. hostElement2.removeAttribute000("tyt-comments-area");
  2154. aoComment.disconnect();
  2155. aoComment.takeRecords();
  2156. elements.comments = null;
  2157. document.querySelector('[tyt-tab-content="#tab-comments"]').classList.add("tab-btn-hidden");
  2158. Promise.resolve(lockSet["removeKeepCommentsScrollerLock"]).then(removeKeepCommentsScroller).catch(console.warn);
  2159. }
  2160. },
  2161. "ytd-comments-header-renderer::defined": (cProto) => {
  2162. if (!cProto.attached498 && typeof cProto.attached === "function") {
  2163. cProto.attached498 = cProto.attached;
  2164. cProto.attached = function() {
  2165. if (!inPageRearrange)
  2166. Promise.resolve(this.hostElement).then(eventMap["ytd-comments-header-renderer::attached"]).catch(console.warn);
  2167. Promise.resolve(this.hostElement).then(eventMap["ytd-comments-header-renderer::dataChanged"]).catch(console.warn);
  2168. return this.attached498();
  2169. };
  2170. }
  2171. if (!cProto.detached498 && typeof cProto.detached === "function") {
  2172. cProto.detached498 = cProto.detached;
  2173. cProto.detached = function() {
  2174. if (!inPageRearrange)
  2175. Promise.resolve(this.hostElement).then(eventMap["ytd-comments-header-renderer::detached"]).catch(console.warn);
  2176. return this.detached498();
  2177. };
  2178. }
  2179. if (!cProto.dataChanged498 && typeof cProto.dataChanged === "function") {
  2180. cProto.dataChanged498 = cProto.dataChanged;
  2181. cProto.dataChanged = function() {
  2182. Promise.resolve(this.hostElement).then(eventMap["ytd-comments-header-renderer::dataChanged"]).catch(console.warn);
  2183. return this.dataChanged498();
  2184. };
  2185. }
  2186. makeInitAttached("ytd-comments-header-renderer");
  2187. },
  2188. "ytd-comments-header-renderer::attached": (hostElement2) => {
  2189. if (invalidFlexyParent(hostElement2))
  2190. return;
  2191. if (hostElement2 instanceof Element)
  2192. hostElement2[__attachedSymbol__] = true;
  2193. if (!(hostElement2 instanceof HTMLElement_) || !(hostElement2.classList.length > 0) || hostElement2.closest("noscript"))
  2194. return;
  2195. if (hostElement2.isConnected !== true)
  2196. return;
  2197. if (!hostElement2 || !hostElement2.classList.contains("ytd-item-section-renderer"))
  2198. return;
  2199. const targetElement = document.querySelector("[tyt-comments-area] ytd-comments-header-renderer");
  2200. if (hostElement2 === targetElement) {
  2201. hostElement2.setAttribute111("tyt-comments-header-field", "");
  2202. } else {
  2203. const parentNode = hostElement2.parentNode;
  2204. if (parentNode instanceof HTMLElement_ && parentNode.querySelector("[tyt-comments-header-field]")) {
  2205. hostElement2.setAttribute111("tyt-comments-header-field", "");
  2206. }
  2207. }
  2208. },
  2209. "ytd-comments-header-renderer::detached": (hostElement2) => {
  2210. if (!(hostElement2 instanceof HTMLElement_) || hostElement2.closest("noscript"))
  2211. return;
  2212. if (hostElement2.isConnected !== false)
  2213. return;
  2214. if (hostElement2.hasAttribute000("field-of-cm-count")) {
  2215. const cmCount = document.querySelector("#tyt-cm-count");
  2216. if (cmCount) {
  2217. cmCount.textContent = "";
  2218. hostElement2.removeAttribute000("field-of-cm-count");
  2219. }
  2220. }
  2221. if (hostElement2.hasAttribute000("tyt-comments-header-field")) {
  2222. hostElement2.removeAttribute000("tyt-comments-header-field");
  2223. }
  2224. },
  2225. "ytd-comments-header-renderer::dataChanged": (hostElement2) => {
  2226. if (!(hostElement2 instanceof HTMLElement_) || !(hostElement2.classList.length > 0) || hostElement2.closest("noscript"))
  2227. return;
  2228. const ytdFlexyElm = elements.flexy;
  2229. let b = false;
  2230. const cnt = insp(hostElement2);
  2231. if (cnt && hostElement2.closest("#tab-comments") && document.querySelector("#tab-comments ytd-comments-header-renderer") === hostElement2) {
  2232. b = true;
  2233. } else if (hostElement2 instanceof HTMLElement_ && hostElement2.parentNode instanceof HTMLElement_ && hostElement2.parentNode.querySelector("[tyt-comments-header-field]")) {
  2234. b = true;
  2235. }
  2236. if (b) {
  2237. hostElement2.setAttribute111("tyt-comments-header-field", "");
  2238. ytdFlexyElm && ytdFlexyElm.removeAttribute000("tyt-comment-disabled");
  2239. }
  2240. if (hostElement2.hasAttribute000("tyt-comments-header-field") && hostElement2.isConnected === true) {
  2241. const data = cnt.data;
  2242. let ez = "";
  2243. if (data.commentsCount && data.commentsCount.runs && data.commentsCount.runs.length >= 1) {
  2244. let max = -1;
  2245. const z = data.commentsCount.runs.map((e) => {
  2246. let c = e.text.replace(/\D+/g, "").length;
  2247. if (c > max)
  2248. max = c;
  2249. return [e.text, c];
  2250. }).filter((a) => a[1] === max);
  2251. if (z.length >= 1) {
  2252. ez = z[0][0];
  2253. }
  2254. } else if (data.countText && data.countText.runs && data.countText.runs.length >= 1) {
  2255. let max = -1;
  2256. const z = data.countText.runs.map((e) => {
  2257. let c = e.text.replace(/\D+/g, "").length;
  2258. if (c > max)
  2259. max = c;
  2260. return [e.text, c];
  2261. }).filter((a) => a[1] === max);
  2262. if (z.length >= 1) {
  2263. ez = z[0][0];
  2264. }
  2265. }
  2266. const cmCount = document.querySelector("#tyt-cm-count");
  2267. if (ez) {
  2268. hostElement2.setAttribute111("field-of-cm-count", "");
  2269. cmCount && (cmCount.textContent = ez.trim());
  2270. } else {
  2271. hostElement2.removeAttribute000("field-of-cm-count");
  2272. cmCount && (cmCount.textContent = "");
  2273. }
  2274. }
  2275. },
  2276. "ytd-expander::defined": (cProto) => {
  2277. if (!cProto.attached498 && typeof cProto.attached === "function") {
  2278. cProto.attached498 = cProto.attached;
  2279. cProto.attached = function() {
  2280. if (!inPageRearrange)
  2281. Promise.resolve(this.hostElement).then(eventMap["ytd-expander::attached"]).catch(console.warn);
  2282. return this.attached498();
  2283. };
  2284. }
  2285. if (!cProto.detached498 && typeof cProto.detached === "function") {
  2286. cProto.detached498 = cProto.detached;
  2287. cProto.detached = function() {
  2288. if (!inPageRearrange)
  2289. Promise.resolve(this.hostElement).then(eventMap["ytd-expander::detached"]).catch(console.warn);
  2290. return this.detached498();
  2291. };
  2292. }
  2293. if (!cProto.calculateCanCollapse498 && typeof cProto.calculateCanCollapse === "function") {
  2294. cProto.calculateCanCollapse498 = cProto.calculateCanCollapse;
  2295. cProto.calculateCanCollapse = funcCanCollapse;
  2296. }
  2297. if (!cProto.childrenChanged498 && typeof cProto.childrenChanged === "function") {
  2298. cProto.childrenChanged498 = cProto.childrenChanged;
  2299. cProto.childrenChanged = function() {
  2300. Promise.resolve(this.hostElement).then(eventMap["ytd-expander::childrenChanged"]).catch(console.warn);
  2301. return this.childrenChanged498();
  2302. };
  2303. }
  2304. makeInitAttached("ytd-expander");
  2305. },
  2306. "ytd-expander::childrenChanged": (hostElement2) => {
  2307. if (hostElement2 instanceof Node && hostElement2.hasAttribute000("hidden") && hostElement2.hasAttribute000("tyt-main-info") && hostElement2.firstElementChild) {
  2308. hostElement2.removeAttribute("hidden");
  2309. }
  2310. },
  2311. "ytd-expandable-video-description-body-renderer::defined": (cProto) => {
  2312. if (!cProto.attached498 && typeof cProto.attached === "function") {
  2313. cProto.attached498 = cProto.attached;
  2314. cProto.attached = function() {
  2315. if (!inPageRearrange)
  2316. Promise.resolve(this.hostElement).then(eventMap["ytd-expandable-video-description-body-renderer::attached"]).catch(console.warn);
  2317. return this.attached498();
  2318. };
  2319. }
  2320. if (!cProto.detached498 && typeof cProto.detached === "function") {
  2321. cProto.detached498 = cProto.detached;
  2322. cProto.detached = function() {
  2323. if (!inPageRearrange)
  2324. Promise.resolve(this.hostElement).then(eventMap["ytd-expandable-video-description-body-renderer::detached"]).catch(console.warn);
  2325. return this.detached498();
  2326. };
  2327. }
  2328. makeInitAttached("ytd-expandable-video-description-body-renderer");
  2329. },
  2330. "ytd-expandable-video-description-body-renderer::attached": async (hostElement2) => {
  2331. if (hostElement2 instanceof HTMLElement_ && isPageDOM(hostElement2, "[tyt-info-renderer]") && !hostElement2.matches("[tyt-main-info]")) {
  2332. elements.infoExpander = hostElement2;
  2333. infoExpanderElementProvidedPromise.resolve();
  2334. hostElement2.setAttribute111("tyt-main-info", "");
  2335. if (plugin.autoExpandInfoDesc.toUse) {
  2336. plugin.autoExpandInfoDesc.onMainInfoSet(hostElement2);
  2337. }
  2338. const lockId = lockSet["rightTabReadyLock03"];
  2339. await rightTabsProvidedPromise.then();
  2340. if (lockGet["rightTabReadyLock03"] !== lockId)
  2341. return;
  2342. if (elements.infoExpander !== hostElement2)
  2343. return;
  2344. if (hostElement2.isConnected === false)
  2345. return;
  2346. elements.infoExpander.classList.add("tyt-main-info");
  2347. const infoExpander = elements.infoExpander;
  2348. const inlineExpanderElm = infoExpander.querySelector("ytd-text-inline-expander");
  2349. if (inlineExpanderElm) {
  2350. const mo = new MutationObserver(() => {
  2351. const p = document.querySelector("#tab-info ytd-text-inline-expander");
  2352. sessionStorage.__$tmp_UseAutoExpandInfoDesc$__ = p && p.hasAttribute("is-expanded") ? "1" : "";
  2353. if (p)
  2354. fixInlineExpanderContent();
  2355. });
  2356. mo.observe(inlineExpanderElm, { attributes: ["is-expanded", "attr-6v8qu", "hidden"], subtree: true });
  2357. inlineExpanderElm.incAttribute111("attr-6v8qu");
  2358. const cnt = insp(inlineExpanderElm);
  2359. if (cnt)
  2360. fixInlineExpanderDisplay(cnt);
  2361. }
  2362. if (infoExpander && !infoExpander.closest("#right-tabs")) {
  2363. document.querySelector("#tab-info").assignChildern111(null, infoExpander, null);
  2364. } else {
  2365. if (document.querySelector('[tyt-tab-content="#tab-info"]')) {
  2366. const shouldTabVisible = elements.infoExpander && elements.infoExpander.closest("#tab-info");
  2367. document.querySelector('[tyt-tab-content="#tab-info"]').classList.toggle("tab-btn-hidden", !shouldTabVisible);
  2368. }
  2369. }
  2370. Promise.resolve(lockSet["infoFixLock"]).then(infoFix).catch(console.warn);
  2371. }
  2372. if (hostElement2 instanceof Element)
  2373. hostElement2[__attachedSymbol__] = true;
  2374. if (!(hostElement2 instanceof HTMLElement_) || !(hostElement2.classList.length > 0) || hostElement2.closest("noscript"))
  2375. return;
  2376. if (hostElement2.isConnected !== true)
  2377. return;
  2378. if (isPageDOM(hostElement2, "#tab-info [tyt-main-info]")) {
  2379. } else if (!hostElement2.closest("#tab-info")) {
  2380. const bodyRenderer = hostElement2;
  2381. let bodyRendererNew = document.querySelector("ytd-expandable-video-description-body-renderer[tyt-info-renderer]");
  2382. if (!bodyRendererNew) {
  2383. bodyRendererNew = document.createElement("ytd-expandable-video-description-body-renderer");
  2384. bodyRendererNew.setAttribute("tyt-info-renderer", "");
  2385. nsTemplateObtain().appendChild(bodyRendererNew);
  2386. }
  2387. const cnt = insp(bodyRendererNew);
  2388. cnt.data = Object.assign({}, insp(bodyRenderer).data);
  2389. const inlineExpanderElm = bodyRendererNew.querySelector("ytd-text-inline-expander");
  2390. const inlineExpanderCnt = insp(inlineExpanderElm);
  2391. fixInlineExpanderMethods(inlineExpanderCnt);
  2392. elements.infoExpanderRendererBack = bodyRenderer;
  2393. elements.infoExpanderRendererFront = bodyRendererNew;
  2394. bodyRenderer.setAttribute("tyt-info-renderer-back", "");
  2395. bodyRendererNew.setAttribute("tyt-info-renderer-front", "");
  2396. }
  2397. },
  2398. "ytd-expandable-video-description-body-renderer::detached": async () => {
  2399. if (!(hostElement instanceof HTMLElement_) || hostElement.closest("noscript"))
  2400. return;
  2401. if (hostElement.isConnected !== false)
  2402. return;
  2403. if (hostElement.hasAttribute000("tyt-main-info")) {
  2404. elements.infoExpander = null;
  2405. hostElement.removeAttribute000("tyt-main-info");
  2406. }
  2407. },
  2408. "ytd-expander::attached": async (hostElement2) => {
  2409. if (invalidFlexyParent(hostElement2))
  2410. return;
  2411. if (hostElement2 instanceof Element)
  2412. hostElement2[__attachedSymbol__] = true;
  2413. if (!(hostElement2 instanceof HTMLElement_) || !(hostElement2.classList.length > 0) || hostElement2.closest("noscript"))
  2414. return;
  2415. if (hostElement2.isConnected !== true)
  2416. return;
  2417. if (hostElement2 instanceof HTMLElement_ && hostElement2.matches("[tyt-comments-area] #contents ytd-expander#expander") && !hostElement2.matches("[hidden] ytd-expander#expander")) {
  2418. hostElement2.setAttribute111("tyt-content-comment-entry", "");
  2419. ioComment.observe(hostElement2);
  2420. }
  2421. },
  2422. "ytd-expander::detached": (hostElement2) => {
  2423. if (!(hostElement2 instanceof HTMLElement_) || hostElement2.closest("noscript"))
  2424. return;
  2425. if (hostElement2.isConnected !== false)
  2426. return;
  2427. if (hostElement2.hasAttribute000("tyt-content-comment-entry")) {
  2428. ioComment.unobserve(hostElement2);
  2429. hostElement2.removeAttribute000("tyt-content-comment-entry");
  2430. } else if (hostElement2.hasAttribute000("tyt-main-info")) {
  2431. elements.infoExpander = null;
  2432. hostElement2.removeAttribute000("tyt-main-info");
  2433. }
  2434. },
  2435. "ytd-live-chat-frame::defined": (cProto) => {
  2436. let lastDomAction = 0;
  2437. if (!cProto.attached498 && typeof cProto.attached === "function") {
  2438. cProto.attached498 = cProto.attached;
  2439. cProto.attached = function() {
  2440. lastDomAction = Date.now();
  2441. if (!inPageRearrange)
  2442. Promise.resolve(this.hostElement).then(eventMap["ytd-live-chat-frame::attached"]).catch(console.warn);
  2443. return this.attached498();
  2444. };
  2445. }
  2446. if (!cProto.detached498 && typeof cProto.detached === "function") {
  2447. cProto.detached498 = cProto.detached;
  2448. cProto.detached = function() {
  2449. lastDomAction = Date.now();
  2450. if (!inPageRearrange)
  2451. Promise.resolve(this.hostElement).then(eventMap["ytd-live-chat-frame::detached"]).catch(console.warn);
  2452. return this.detached498();
  2453. };
  2454. }
  2455. if (typeof cProto.urlChanged === "function" && !cProto.urlChanged66 && !cProto.urlChangedAsync12 && cProto.urlChanged.length === 0) {
  2456. cProto.urlChanged66 = cProto.urlChanged;
  2457. let ath = 0;
  2458. cProto.urlChangedAsync12 = async function() {
  2459. const t = ath = (ath & 1073741823) + 1;
  2460. const chatframe = this.chatframe || (this.$ || 0).chatframe || 0;
  2461. if (chatframe instanceof HTMLIFrameElement) {
  2462. if (chatframe.contentDocument === null) {
  2463. await Promise.resolve("#").catch(console.warn);
  2464. if (t !== ath)
  2465. return;
  2466. }
  2467. await new Promise((resolve) => setTimeout_(resolve, 1)).catch(console.warn);
  2468. if (t !== ath)
  2469. return;
  2470. const isBlankPage = !this.data || this.collapsed;
  2471. const p1 = new Promise((resolve) => setTimeout_(resolve, 706)).catch(console.warn);
  2472. const p2 = new Promise((resolve) => {
  2473. new IntersectionObserver((entries, observer) => {
  2474. for (const entry of entries) {
  2475. const rect = entry.boundingClientRect || 0;
  2476. if (isBlankPage || rect.width > 0 && rect.height > 0) {
  2477. observer.disconnect();
  2478. resolve("#");
  2479. break;
  2480. }
  2481. }
  2482. }).observe(chatframe);
  2483. }).catch(console.warn);
  2484. await Promise.race([p1, p2]);
  2485. if (t !== ath)
  2486. return;
  2487. }
  2488. this.urlChanged66();
  2489. };
  2490. cProto.urlChanged = function() {
  2491. this.urlChangedAsync12();
  2492. };
  2493. }
  2494. makeInitAttached("ytd-live-chat-frame");
  2495. },
  2496. "ytd-live-chat-frame::attached": async (hostElement2) => {
  2497. if (invalidFlexyParent(hostElement2))
  2498. return;
  2499. if (hostElement2 instanceof Element)
  2500. hostElement2[__attachedSymbol__] = true;
  2501. if (!(hostElement2 instanceof HTMLElement_) || !(hostElement2.classList.length > 0) || hostElement2.closest("noscript"))
  2502. return;
  2503. if (hostElement2.isConnected !== true)
  2504. return;
  2505. if (!hostElement2 || hostElement2.id !== "chat")
  2506. return;
  2507. const lockId = lockSet["ytdLiveAttachedLock"];
  2508. const chatElem = await getGeneralChatElement();
  2509. if (lockGet["ytdLiveAttachedLock"] !== lockId)
  2510. return;
  2511. if (chatElem === hostElement2) {
  2512. elements.chat = chatElem;
  2513. aoChat.observe(chatElem, { attributes: true });
  2514. const isFlexyReady = elements.flexy instanceof Element;
  2515. chatElem.setAttribute111("tyt-active-chat-frame", isFlexyReady ? "CF" : "C");
  2516. const chatContainer = chatElem ? chatElem.closest("#chat-container") || chatElem : null;
  2517. if (chatContainer && !chatContainer.hasAttribute000("tyt-chat-container")) {
  2518. for (const p of document.querySelectorAll("[tyt-chat-container]")) {
  2519. p.removeAttribute000("[tyt-chat-container]");
  2520. }
  2521. chatContainer.setAttribute111("tyt-chat-container", "");
  2522. }
  2523. Promise.resolve(lockSet["layoutFixLock"]).then(layoutFix);
  2524. } else {
  2525. }
  2526. },
  2527. "ytd-live-chat-frame::detached": (hostElement2) => {
  2528. if (!(hostElement2 instanceof HTMLElement_) || hostElement2.closest("noscript"))
  2529. return;
  2530. if (hostElement2.isConnected !== false)
  2531. return;
  2532. if (hostElement2.hasAttribute000("tyt-active-chat-frame")) {
  2533. aoChat.disconnect();
  2534. aoChat.takeRecords();
  2535. hostElement2.removeAttribute000("tyt-active-chat-frame");
  2536. elements.chat = null;
  2537. const ytdFlexyElm = elements.flexy;
  2538. if (ytdFlexyElm) {
  2539. ytdFlexyElm.removeAttribute000("tyt-chat-collapsed");
  2540. ytdFlexyElm.setAttribute111("tyt-chat", "");
  2541. }
  2542. }
  2543. },
  2544. "ytd-engagement-panel-section-list-renderer::defined": (cProto) => {
  2545. if (!cProto.attached498 && typeof cProto.attached === "function") {
  2546. cProto.attached498 = cProto.attached;
  2547. cProto.attached = function() {
  2548. if (!inPageRearrange)
  2549. Promise.resolve(this.hostElement).then(eventMap["ytd-engagement-panel-section-list-renderer::attached"]).catch(console.warn);
  2550. return this.attached498();
  2551. };
  2552. }
  2553. if (!cProto.detached498 && typeof cProto.detached === "function") {
  2554. cProto.detached498 = cProto.detached;
  2555. cProto.detached = function() {
  2556. if (!inPageRearrange)
  2557. Promise.resolve(this.hostElement).then(eventMap["ytd-engagement-panel-section-list-renderer::detached"]).catch(console.warn);
  2558. return this.detached498();
  2559. };
  2560. }
  2561. makeInitAttached("ytd-engagement-panel-section-list-renderer");
  2562. },
  2563. "ytd-engagement-panel-section-list-renderer::bindTarget": (hostElement2) => {
  2564. if (hostElement2.matches("#panels.ytd-watch-flexy > ytd-engagement-panel-section-list-renderer[target-id][visibility]")) {
  2565. hostElement2.setAttribute111("tyt-egm-panel", "");
  2566. Promise.resolve(lockSet["updateEgmPanelsLock"]).then(updateEgmPanels).catch(console.warn);
  2567. aoEgmPanels.observe(hostElement2, { attributes: true, attributeFilter: ["visibility", "hidden"] });
  2568. }
  2569. },
  2570. "ytd-engagement-panel-section-list-renderer::attached": (hostElement2) => {
  2571. if (invalidFlexyParent(hostElement2))
  2572. return;
  2573. if (hostElement2 instanceof Element)
  2574. hostElement2[__attachedSymbol__] = true;
  2575. if (!(hostElement2 instanceof HTMLElement_) || !(hostElement2.classList.length > 0) || hostElement2.closest("noscript"))
  2576. return;
  2577. if (hostElement2.isConnected !== true)
  2578. return;
  2579. if (!hostElement2.matches("#panels.ytd-watch-flexy > ytd-engagement-panel-section-list-renderer"))
  2580. return;
  2581. if (hostElement2.hasAttribute000("target-id") && hostElement2.hasAttribute000("visibility")) {
  2582. Promise.resolve(hostElement2).then(eventMap["ytd-engagement-panel-section-list-renderer::bindTarget"]).catch(console.warn);
  2583. } else {
  2584. hostElement2.setAttribute000("tyt-egm-panel-jclmd", "");
  2585. moEgmPanelReady.observe(hostElement2, { attributes: true, attributeFilter: ["visibility", "target-id"] });
  2586. }
  2587. },
  2588. "ytd-engagement-panel-section-list-renderer::detached": (hostElement2) => {
  2589. if (!(hostElement2 instanceof HTMLElement_) || hostElement2.closest("noscript"))
  2590. return;
  2591. if (hostElement2.isConnected !== false)
  2592. return;
  2593. if (hostElement2.hasAttribute000("tyt-egm-panel")) {
  2594. hostElement2.removeAttribute000("tyt-egm-panel");
  2595. Promise.resolve(lockSet["updateEgmPanelsLock"]).then(updateEgmPanels).catch(console.warn);
  2596. } else if (hostElement2.hasAttribute000("tyt-egm-panel-jclmd")) {
  2597. hostElement2.removeAttribute000("tyt-egm-panel-jclmd");
  2598. moEgmPanelReadyClearFn();
  2599. }
  2600. },
  2601. "ytd-watch-metadata::defined": (cProto) => {
  2602. if (!cProto.attached498 && typeof cProto.attached === "function") {
  2603. cProto.attached498 = cProto.attached;
  2604. cProto.attached = function() {
  2605. if (!inPageRearrange)
  2606. Promise.resolve(this.hostElement).then(eventMap["ytd-watch-metadata::attached"]).catch(console.warn);
  2607. return this.attached498();
  2608. };
  2609. }
  2610. if (!cProto.detached498 && typeof cProto.detached === "function") {
  2611. cProto.detached498 = cProto.detached;
  2612. cProto.detached = function() {
  2613. if (!inPageRearrange)
  2614. Promise.resolve(this.hostElement).then(eventMap["ytd-watch-metadata::detached"]).catch(console.warn);
  2615. return this.detached498();
  2616. };
  2617. }
  2618. makeInitAttached("ytd-watch-metadata");
  2619. },
  2620. "ytd-watch-metadata::attached": (hostElement2) => {
  2621. if (invalidFlexyParent(hostElement2))
  2622. return;
  2623. if (hostElement2 instanceof Element)
  2624. hostElement2[__attachedSymbol__] = true;
  2625. if (!(hostElement2 instanceof HTMLElement_) || !(hostElement2.classList.length > 0) || hostElement2.closest("noscript"))
  2626. return;
  2627. if (hostElement2.isConnected !== true)
  2628. return;
  2629. if (plugin.fullChannelNameOnHover.activated)
  2630. plugin.fullChannelNameOnHover.onNavigateFinish();
  2631. },
  2632. "ytd-watch-metadata::detached": (hostElement2) => {
  2633. if (!(hostElement2 instanceof HTMLElement_) || hostElement2.closest("noscript"))
  2634. return;
  2635. if (hostElement2.isConnected !== false)
  2636. return;
  2637. },
  2638. "ytd-playlist-panel-renderer::defined": (cProto) => {
  2639. if (!cProto.attached498 && typeof cProto.attached === "function") {
  2640. cProto.attached498 = cProto.attached;
  2641. cProto.attached = function() {
  2642. if (!inPageRearrange)
  2643. Promise.resolve(this.hostElement).then(eventMap["ytd-playlist-panel-renderer::attached"]).catch(console.warn);
  2644. return this.attached498();
  2645. };
  2646. }
  2647. if (!cProto.detached498 && typeof cProto.detached === "function") {
  2648. cProto.detached498 = cProto.detached;
  2649. cProto.detached = function() {
  2650. if (!inPageRearrange)
  2651. Promise.resolve(this.hostElement).then(eventMap["ytd-playlist-panel-renderer::detached"]).catch(console.warn);
  2652. return this.detached498();
  2653. };
  2654. }
  2655. makeInitAttached("ytd-playlist-panel-renderer");
  2656. },
  2657. "ytd-playlist-panel-renderer::attached": (hostElement2) => {
  2658. if (invalidFlexyParent(hostElement2))
  2659. return;
  2660. if (hostElement2 instanceof Element)
  2661. hostElement2[__attachedSymbol__] = true;
  2662. if (!(hostElement2 instanceof HTMLElement_) || !(hostElement2.classList.length > 0) || hostElement2.closest("noscript"))
  2663. return;
  2664. if (hostElement2.isConnected !== true)
  2665. return;
  2666. elements.playlist = hostElement2;
  2667. aoPlayList.observe(hostElement2, { attributes: true, attributeFilter: ["hidden", "collapsed", "attr-1y6nu"] });
  2668. hostElement2.incAttribute111("attr-1y6nu");
  2669. },
  2670. "ytd-playlist-panel-renderer::detached": (hostElement2) => {
  2671. if (!(hostElement2 instanceof HTMLElement_) || hostElement2.closest("noscript"))
  2672. return;
  2673. if (hostElement2.isConnected !== false)
  2674. return;
  2675. },
  2676. "_yt_playerProvided": () => {
  2677. mLoaded.flag |= 4;
  2678. document.documentElement.setAttribute111("tabview-loaded", mLoaded.makeString());
  2679. },
  2680. "relatedElementProvided": (target) => {
  2681. if (target.closest("[hidden]"))
  2682. return;
  2683. elements.related = target;
  2684. videosElementProvidedPromise.resolve();
  2685. },
  2686. "onceInfoExpanderElementProvidedPromised": () => {
  2687. const ytdFlexyElm = elements.flexy;
  2688. if (ytdFlexyElm) {
  2689. ytdFlexyElm.setAttribute111("hide-default-text-inline-expander", "");
  2690. }
  2691. },
  2692. "refreshSecondaryInner": (lockId) => {
  2693. if (lockGet["refreshSecondaryInnerLock"] !== lockId)
  2694. return;
  2695. const ytdFlexyElm = elements.flexy;
  2696. if (ytdFlexyElm && ytdFlexyElm.matches("ytd-watch-flexy[theater][flexy][full-bleed-player]:not([full-bleed-no-max-width-columns])")) {
  2697. ytdFlexyElm.setAttribute111("full-bleed-no-max-width-columns", "");
  2698. }
  2699. const related = elements.related;
  2700. if (related && related.isConnected && !related.closest("#right-tabs #tab-videos")) {
  2701. document.querySelector("#tab-videos").assignChildern111(null, related, null);
  2702. }
  2703. const infoExpander = elements.infoExpander;
  2704. if (infoExpander && infoExpander.isConnected && !infoExpander.closest("#right-tabs #tab-info")) {
  2705. document.querySelector("#tab-info").assignChildern111(null, infoExpander, null);
  2706. } else {
  2707. }
  2708. const commentsArea = elements.comments;
  2709. if (commentsArea) {
  2710. const isConnected = commentsArea.isConnected;
  2711. if (isConnected && !commentsArea.closest("#right-tabs #tab-comments")) {
  2712. const tab = document.querySelector("#tab-comments");
  2713. tab.assignChildern111(null, commentsArea, null);
  2714. } else {
  2715. }
  2716. }
  2717. },
  2718. "yt-navigate-finish": (evt) => {
  2719. const ytdAppElm = document.querySelector("ytd-page-manager#page-manager.style-scope.ytd-app");
  2720. const ytdAppCnt = insp(ytdAppElm);
  2721. pageType = ytdAppCnt ? (ytdAppCnt.data || 0).page : null;
  2722. if (!document.querySelector("ytd-watch-flexy #player"))
  2723. return;
  2724. const flexyArr = [...document.querySelectorAll("ytd-watch-flexy")].filter((e) => !e.closest("[hidden]") && e.querySelector("#player"));
  2725. if (flexyArr.length === 1) {
  2726. elements.flexy = flexyArr[0];
  2727. if (isRightTabsInserted) {
  2728. Promise.resolve(lockSet["refreshSecondaryInnerLock"]).then(eventMap["refreshSecondaryInner"]).catch(console.warn);
  2729. Promise.resolve(lockSet["removeKeepCommentsScrollerLock"]).then(removeKeepCommentsScroller).catch(console.warn);
  2730. } else {
  2731. navigateFinishedPromise.resolve();
  2732. if (plugin.minibrowser.toUse)
  2733. plugin.minibrowser.activate();
  2734. if (plugin.autoExpandInfoDesc.toUse)
  2735. plugin.autoExpandInfoDesc.activate();
  2736. if (plugin.fullChannelNameOnHover.toUse)
  2737. plugin.fullChannelNameOnHover.activate();
  2738. }
  2739. const chat = elements.chat;
  2740. if (chat instanceof Element) {
  2741. chat.setAttribute111("tyt-active-chat-frame", "CF");
  2742. }
  2743. const infoExpander = elements.infoExpander;
  2744. if (infoExpander && infoExpander.closest("#right-tabs")) {
  2745. Promise.resolve(lockSet["infoFixLock"]).then(infoFix).catch(console.warn);
  2746. }
  2747. Promise.resolve(lockSet["layoutFixLock"]).then(layoutFix);
  2748. if (plugin.fullChannelNameOnHover.activated)
  2749. plugin.fullChannelNameOnHover.onNavigateFinish();
  2750. }
  2751. },
  2752. "onceInsertRightTabs": () => {
  2753. const related = elements.related;
  2754. let rightTabs = document.querySelector("#right-tabs");
  2755. if (!document.querySelector("#right-tabs") && related) {
  2756. getLangForPage();
  2757. let docTmp = document.createElement("template");
  2758. docTmp.innerHTML = createHTML(getTabsHTML());
  2759. let newElm = docTmp.content.firstElementChild;
  2760. if (newElm !== null) {
  2761. inPageRearrange = true;
  2762. related.parentNode.insertBefore000(newElm, related);
  2763. inPageRearrange = false;
  2764. }
  2765. rightTabs = newElm;
  2766. rightTabs.querySelector('[tyt-tab-content="#tab-comments"]').classList.add("tab-btn-hidden");
  2767. const secondaryWrapper = document.createElement("secondary-wrapper");
  2768. const secondaryInner = document.querySelector("#secondary-inner.style-scope.ytd-watch-flexy");
  2769. inPageRearrange = true;
  2770. secondaryWrapper.replaceChildren000(...secondaryInner.childNodes);
  2771. secondaryInner.insertBefore000(secondaryWrapper, secondaryInner.firstChild);
  2772. inPageRearrange = false;
  2773. rightTabs.querySelector("#material-tabs").addEventListener("click", eventMap["tabs-btn-click"], true);
  2774. inPageRearrange = true;
  2775. if (!rightTabs.closest("secondary-wrapper"))
  2776. secondaryWrapper.appendChild000(rightTabs);
  2777. inPageRearrange = false;
  2778. }
  2779. if (rightTabs) {
  2780. isRightTabsInserted = true;
  2781. const ioTabBtns = new IntersectionObserver((entries) => {
  2782. for (const entry of entries) {
  2783. const rect = entry.boundingClientRect;
  2784. entry.target.classList.toggle("tab-btn-visible", rect.width && rect.height);
  2785. }
  2786. }, { rootMargin: "0px" });
  2787. for (const btn of document.querySelectorAll(".tab-btn[tyt-tab-content]")) {
  2788. ioTabBtns.observe(btn);
  2789. }
  2790. if (!related.closest("#right-tabs")) {
  2791. document.querySelector("#tab-videos").assignChildern111(null, related, null);
  2792. }
  2793. const infoExpander = elements.infoExpander;
  2794. if (infoExpander && !infoExpander.closest("#right-tabs")) {
  2795. document.querySelector("#tab-info").assignChildern111(null, infoExpander, null);
  2796. }
  2797. const commentsArea = elements.comments;
  2798. if (commentsArea && !commentsArea.closest("#right-tabs")) {
  2799. document.querySelector("#tab-comments").assignChildern111(null, commentsArea, null);
  2800. }
  2801. rightTabsProvidedPromise.resolve();
  2802. roRightTabs.disconnect();
  2803. roRightTabs.observe(rightTabs);
  2804. const ytdFlexyElm = elements.flexy;
  2805. const aoFlexy = new MutationObserver(eventMap["aoFlexyFn"]);
  2806. aoFlexy.observe(ytdFlexyElm, { attributes: true });
  2807. Promise.resolve(lockSet["fixInitialTabStateLock"]).then(eventMap["fixInitialTabStateFn"]).catch(console.warn);
  2808. ytdFlexyElm.incAttribute111("attr-7qlsy");
  2809. }
  2810. },
  2811. "aoFlexyFn": () => {
  2812. Promise.resolve(lockSet["checkCommentsShouldBeHiddenLock"]).then(eventMap["checkCommentsShouldBeHidden"]).catch(console.warn);
  2813. Promise.resolve(lockSet["refreshSecondaryInnerLock"]).then(eventMap["refreshSecondaryInner"]).catch(console.warn);
  2814. Promise.resolve(lockSet["tabsStatusCorrectionLock"]).then(eventMap["tabsStatusCorrection"]).catch(console.warn);
  2815. const videoId = getCurrentVideoId();
  2816. if (videoId !== tmpLastVideoId) {
  2817. tmpLastVideoId = videoId;
  2818. Promise.resolve(lockSet["updateOnVideoIdChangedLock"]).then(eventMap["updateOnVideoIdChanged"]).catch(console.warn);
  2819. }
  2820. },
  2821. "twoColumnChanged10": (lockId) => {
  2822. if (lockId !== lockGet["twoColumnChanged10Lock"])
  2823. return;
  2824. for (const continuation of document.querySelectorAll("#tab-videos ytd-watch-next-secondary-results-renderer ytd-continuation-item-renderer")) {
  2825. if (continuation.closest("[hidden]"))
  2826. continue;
  2827. const cnt = insp(continuation);
  2828. if (typeof cnt.showButton === "boolean") {
  2829. if (cnt.showButton === false)
  2830. continue;
  2831. cnt.showButton = false;
  2832. const behavior = cnt.ytRendererBehavior || cnt;
  2833. if (typeof behavior.invalidate === "function") {
  2834. behavior.invalidate(false);
  2835. }
  2836. }
  2837. }
  2838. },
  2839. "tabsStatusCorrection": (lockId) => {
  2840. if (lockId !== lockGet["tabsStatusCorrectionLock"])
  2841. return;
  2842. const ytdFlexyElm = elements.flexy;
  2843. if (!ytdFlexyElm)
  2844. return;
  2845. const p = tabAStatus;
  2846. const q = calculationFn(p, 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128);
  2847. let resetForPanelDisappeared = false;
  2848. if (p !== q) {
  2849. let actioned = false;
  2850. if ((p & 128) === 0 && (q & 128) === 128) {
  2851. lastPanel = "playlist";
  2852. } else if ((p & 8) === 0 && (q & 8) === 8) {
  2853. lastPanel = "chat";
  2854. } else if (((p & 4) == 4 && (q & (4 | 8)) == (0 | 0) || (p & 8) == 8 && (q & (4 | 8)) === (0 | 0)) && lastPanel === "chat") {
  2855. lastPanel = lastTab || "";
  2856. resetForPanelDisappeared = true;
  2857. } else if ((p & (4 | 8)) === 8 && (q & (4 | 8)) === 4 && lastPanel === "chat") {
  2858. lastPanel = lastTab || "";
  2859. resetForPanelDisappeared = true;
  2860. } else if ((p & 128) === 128 && (q & 128) === 0 && lastPanel === "playlist") {
  2861. lastPanel = lastTab || "";
  2862. resetForPanelDisappeared = true;
  2863. }
  2864. tabAStatus = q;
  2865. let bFixForResizedTab = false;
  2866. if ((q ^ 2) === 2 && bFixForResizedTabLater) {
  2867. bFixForResizedTab = true;
  2868. }
  2869. if ((p & 16) === 16 & (q & 16) === 0) {
  2870. Promise.resolve(lockSet["twoColumnChanged10Lock"]).then(eventMap["twoColumnChanged10"]).catch(console.warn);
  2871. }
  2872. if ((p & 2) === 2 ^ (q & 2) === 2 && (q & 2) === 2) {
  2873. bFixForResizedTab = true;
  2874. }
  2875. if ((p & 2) === 0 && (q & 2) === 2 && (p & 128) === 128 && (q & 128) === 128) {
  2876. lastPanel = lastTab || "";
  2877. ytBtnClosePlaylist();
  2878. actioned = true;
  2879. }
  2880. if ((p & (8 | 128)) === (0 | 128) && (q & (8 | 128)) === (8 | 128) && lastPanel === "chat") {
  2881. lastPanel = lastTab || "";
  2882. ytBtnClosePlaylist();
  2883. actioned = true;
  2884. }
  2885. if ((p & (2 | 128)) === (2 | 0) && (q & (2 | 128)) === (2 | 128) && lastPanel === "playlist") {
  2886. switchToTab(null);
  2887. actioned = true;
  2888. }
  2889. if ((p & (8 | 128)) === (8 | 0) && (q & (8 | 128)) === (8 | 128) && lastPanel === "playlist") {
  2890. lastPanel = lastTab || "";
  2891. ytBtnCollapseChat();
  2892. actioned = true;
  2893. }
  2894. if ((p & (1 | 16 | 128)) == (1 | 16) && (q & (1 | 16 | 128)) == (1 | 16 | 128)) {
  2895. ytBtnCancelTheater();
  2896. actioned = true;
  2897. }
  2898. if ((p & (1 | 16 | 128)) == (16 | 128) && (q & (1 | 16 | 128)) == (1 | 16 | 128)) {
  2899. lastPanel = lastTab || "";
  2900. ytBtnClosePlaylist();
  2901. actioned = true;
  2902. }
  2903. if ((q & 64) === 64) {
  2904. actioned = false;
  2905. } else if ((p & 64) == 64 && (q & 64) === 0) {
  2906. if ((q & 32) === 32) {
  2907. ytBtnCloseEngagementPanels();
  2908. }
  2909. if ((q & (2 | 8)) === (2 | 8)) {
  2910. if (lastPanel === "chat") {
  2911. switchToTab(null);
  2912. actioned = true;
  2913. } else if (lastPanel) {
  2914. ytBtnCollapseChat();
  2915. actioned = true;
  2916. }
  2917. }
  2918. } else if ((p & (1 | 2 | 8 | 16 | 32)) === (1 | 0 | 0 | 16 | 0) && (q & (1 | 2 | 8 | 16 | 32)) === (1 | 0 | 8 | 16 | 0)) {
  2919. ytBtnCancelTheater();
  2920. actioned = true;
  2921. } else if ((p & (1 | 16 | 32)) === (0 | 16 | 0) && (q & (1 | 16 | 32)) === (0 | 16 | 32) && (q & (2 | 8)) > 0) {
  2922. if (q & 2) {
  2923. switchToTab(null);
  2924. actioned = true;
  2925. }
  2926. if (q & 8) {
  2927. ytBtnCollapseChat();
  2928. actioned = true;
  2929. }
  2930. } else if ((p & (1 | 16 | 8 | 2)) === (16 | 8) && (q & (1 | 16 | 8 | 2)) === 16 && (q & 128) === 0) {
  2931. if (lastTab) {
  2932. switchToTab(lastTab);
  2933. actioned = true;
  2934. }
  2935. } else if ((p & 1) === 0 && (q & 1) === 1) {
  2936. if ((q & 32) === 32) {
  2937. ytBtnCloseEngagementPanels();
  2938. }
  2939. if ((p & 9) === 8 && (q & 9) === 9) {
  2940. ytBtnCollapseChat();
  2941. }
  2942. switchToTab(null);
  2943. actioned = true;
  2944. } else if ((p & 3) === 1 && (q & 3) === 3) {
  2945. ytBtnCancelTheater();
  2946. actioned = true;
  2947. } else if ((p & 10) === 2 && (q & 10) === 10) {
  2948. switchToTab(null);
  2949. actioned = true;
  2950. } else if ((p & (8 | 32)) === (0 | 32) && (q & (8 | 32)) === (8 | 32)) {
  2951. ytBtnCloseEngagementPanels();
  2952. actioned = true;
  2953. } else if ((p & (2 | 32)) === (0 | 32) && (q & (2 | 32)) === (2 | 32)) {
  2954. ytBtnCloseEngagementPanels();
  2955. actioned = true;
  2956. } else if ((p & (2 | 8)) === (0 | 8) && (q & (2 | 8)) === (2 | 8)) {
  2957. ytBtnCollapseChat();
  2958. actioned = true;
  2959. } else if ((p & 1) === 1 && (q & (1 | 32)) === (0 | 0)) {
  2960. if (lastPanel === "chat") {
  2961. ytBtnExpandChat();
  2962. actioned = true;
  2963. } else if (lastPanel === lastTab && lastTab) {
  2964. switchToTab(lastTab);
  2965. actioned = true;
  2966. }
  2967. }
  2968. if (!actioned && (q & 128) === 128) {
  2969. lastPanel = "playlist";
  2970. if ((q & 2) === 2) {
  2971. switchToTab(null);
  2972. actioned = true;
  2973. }
  2974. }
  2975. if ((p & 2) === 2 && (q & (2 | 128)) === (0 | 128)) {
  2976. } else if ((p & 8) === 8 && (q & (8 | 128)) === (0 | 128)) {
  2977. } else if (!actioned && (p & (1 | 16)) === 16 && (q & (1 | 16 | 8 | 2 | 32 | 64)) === (16 | 0 | 0)) {
  2978. if (lastPanel === "chat") {
  2979. ytBtnExpandChat();
  2980. actioned = true;
  2981. } else if (lastPanel === "playlist") {
  2982. ytBtnOpenPlaylist();
  2983. actioned = true;
  2984. } else if (lastTab) {
  2985. switchToTab(lastTab);
  2986. actioned = true;
  2987. } else if (resetForPanelDisappeared) {
  2988. Promise.resolve(lockSet["fixInitialTabStateLock"]).then(eventMap["fixInitialTabStateFn"]).catch(console.warn);
  2989. actioned = true;
  2990. }
  2991. }
  2992. if (bFixForResizedTab) {
  2993. bFixForResizedTabLater = false;
  2994. Promise.resolve(0).then(eventMap["fixForTabDisplay"]).catch(console.warn);
  2995. }
  2996. if ((p & 16) === 16 ^ (q & 16) === 16) {
  2997. Promise.resolve(lockSet["infoFixLock"]).then(infoFix).catch(console.warn);
  2998. Promise.resolve(lockSet["removeKeepCommentsScrollerLock"]).then(removeKeepCommentsScroller).catch(console.warn);
  2999. Promise.resolve(lockSet["layoutFixLock"]).then(layoutFix).catch(console.warn);
  3000. }
  3001. }
  3002. },
  3003. "updateOnVideoIdChanged": (lockId) => {
  3004. if (lockId !== lockGet["updateOnVideoIdChangedLock"])
  3005. return;
  3006. const videoId = tmpLastVideoId;
  3007. if (!videoId)
  3008. return;
  3009. const bodyRenderer = elements.infoExpanderRendererBack;
  3010. const bodyRendererNew = elements.infoExpanderRendererFront;
  3011. if (bodyRendererNew && bodyRenderer) {
  3012. insp(bodyRendererNew).data = insp(bodyRenderer).data;
  3013. }
  3014. Promise.resolve(lockSet["infoFixLock"]).then(infoFix).catch(console.warn);
  3015. },
  3016. "fixInitialTabStateFn": async (lockId) => {
  3017. if (lockGet["fixInitialTabStateLock"] !== lockId)
  3018. return;
  3019. const delayTime = fixInitialTabStateK > 0 ? 200 : 1;
  3020. await delayPn(delayTime);
  3021. if (lockGet["fixInitialTabStateLock"] !== lockId)
  3022. return;
  3023. const kTab = document.querySelector("[tyt-tab]");
  3024. const qTab = !kTab || kTab.getAttribute("tyt-tab") === "" ? checkElementExist("ytd-watch-flexy[is-two-columns_]", "[hidden]") : null;
  3025. if (checkElementExist("ytd-playlist-panel-renderer#playlist", "[hidden], [collapsed]")) {
  3026. switchToTab(null);
  3027. } else if (checkElementExist("ytd-live-chat-frame#chat", "[hidden], [collapsed]")) {
  3028. switchToTab(null);
  3029. if (checkElementExist("ytd-watch-flexy[theater]", "[hidden]")) {
  3030. ytBtnCollapseChat();
  3031. }
  3032. } else if (qTab) {
  3033. const hasTheater = qTab.hasAttribute("theater");
  3034. if (!hasTheater) {
  3035. const btn0 = document.querySelector(".tab-btn-visible");
  3036. if (btn0) {
  3037. switchToTab(btn0);
  3038. } else {
  3039. switchToTab(null);
  3040. }
  3041. } else {
  3042. switchToTab(null);
  3043. }
  3044. } else {
  3045. }
  3046. fixInitialTabStateK++;
  3047. },
  3048. "tabs-btn-click": (evt) => {
  3049. const target = evt.target;
  3050. if (target instanceof HTMLElement_ && target.classList.contains("tab-btn") && target.hasAttribute000("tyt-tab-content")) {
  3051. evt.preventDefault();
  3052. evt.stopPropagation();
  3053. evt.stopImmediatePropagation();
  3054. const activeLink = target;
  3055. switchToTab(activeLink);
  3056. }
  3057. }
  3058. };
  3059. Promise.all([videosElementProvidedPromise, navigateFinishedPromise]).then(eventMap["onceInsertRightTabs"]).catch(console.warn);
  3060. Promise.all([navigateFinishedPromise, infoExpanderElementProvidedPromise]).then(eventMap["onceInfoExpanderElementProvidedPromised"]).catch(console.warn);
  3061. const isCustomElementsProvided = typeof customElements !== "undefined" && typeof (customElements || 0).whenDefined === "function";
  3062. const promiseForCustomYtElementsReady = isCustomElementsProvided ? Promise.resolve(0) : new Promise((callback) => {
  3063. const EVENT_KEY_ON_REGISTRY_READY = "ytI-ce-registry-created";
  3064. if (typeof customElements === "undefined") {
  3065. if (!("__CE_registry" in document)) {
  3066. Object.defineProperty(document, "__CE_registry", {
  3067. get() {
  3068. },
  3069. set(nv) {
  3070. if (typeof nv == "object") {
  3071. delete this.__CE_registry;
  3072. this.__CE_registry = nv;
  3073. this.dispatchEvent(new CustomEvent(EVENT_KEY_ON_REGISTRY_READY));
  3074. }
  3075. return true;
  3076. },
  3077. enumerable: false,
  3078. configurable: true
  3079. });
  3080. }
  3081. let eventHandler = (evt) => {
  3082. document.removeEventListener(EVENT_KEY_ON_REGISTRY_READY, eventHandler, false);
  3083. const f = callback;
  3084. callback = null;
  3085. eventHandler = null;
  3086. f();
  3087. };
  3088. document.addEventListener(EVENT_KEY_ON_REGISTRY_READY, eventHandler, false);
  3089. } else {
  3090. callback();
  3091. }
  3092. });
  3093. const _retrieveCE = async (nodeName) => {
  3094. try {
  3095. isCustomElementsProvided || await promiseForCustomYtElementsReady;
  3096. await customElements.whenDefined(nodeName);
  3097. } catch (e) {
  3098. }
  3099. };
  3100. const retrieveCE = async (nodeName) => {
  3101. try {
  3102. isCustomElementsProvided || await promiseForCustomYtElementsReady;
  3103. await customElements.whenDefined(nodeName);
  3104. const dummy = document.querySelector(nodeName) || document.createElement(nodeName);
  3105. const cProto = insp(dummy).constructor.prototype;
  3106. return cProto;
  3107. } catch (e) {
  3108. }
  3109. };
  3110. const moOverallRes = {
  3111. _yt_playerProvided: () => (window || 0)._yt_player || 0 || 0
  3112. };
  3113. let promiseWaitNext = null;
  3114. const moOverall = new MutationObserver(() => {
  3115. if (promiseWaitNext) {
  3116. promiseWaitNext.resolve();
  3117. promiseWaitNext = null;
  3118. }
  3119. if (typeof moOverallRes._yt_playerProvided === "function") {
  3120. const r = moOverallRes._yt_playerProvided();
  3121. if (r) {
  3122. moOverallRes._yt_playerProvided = r;
  3123. eventMap._yt_playerProvided();
  3124. }
  3125. }
  3126. });
  3127. moOverall.observe(document, { subtree: true, childList: true });
  3128. const moEgmPanelReady = new MutationObserver((mutations) => {
  3129. for (const mutation of mutations) {
  3130. const target = mutation.target;
  3131. if (!target.hasAttribute000("tyt-egm-panel-jclmd"))
  3132. continue;
  3133. if (target.hasAttribute000("target-id") && target.hasAttribute000("visibility")) {
  3134. target.removeAttribute000("tyt-egm-panel-jclmd");
  3135. moEgmPanelReadyClearFn();
  3136. Promise.resolve(target).then(eventMap["ytd-engagement-panel-section-list-renderer::bindTarget"]).catch(console.warn);
  3137. }
  3138. }
  3139. });
  3140. const moEgmPanelReadyClearFn = () => {
  3141. if (document.querySelector("[tyt-egm-panel-jclmd]") === null) {
  3142. moEgmPanelReady.takeRecords();
  3143. moEgmPanelReady.disconnect();
  3144. }
  3145. };
  3146. document.addEventListener("yt-navigate-finish", eventMap["yt-navigate-finish"], false);
  3147. document.addEventListener("animationstart", (evt) => {
  3148. const f = eventMap[evt.animationName];
  3149. if (typeof f === "function")
  3150. f(evt.target);
  3151. }, capturePassive);
  3152. mLoaded.flag |= 1;
  3153. document.documentElement.setAttribute111("tabview-loaded", mLoaded.makeString());
  3154. promiseForCustomYtElementsReady.then(eventMap["ceHack"]).catch(console.warn);
  3155. executionFinished = 1;
  3156. } catch (e) {
  3157. }
  3158. };
  3159.  
  3160. var css_248z = ".html5-play-progress,.ytp-play-progress{background:url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAMCAIAAAAs6UAAAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QUNCQzIyREQ0QjdEMTFFMzlEMDM4Qzc3MEY0NzdGMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QUNCQzIyREU0QjdEMTFFMzlEMDM4Qzc3MEY0NzdGMDgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBQ0JDMjJEQjRCN0QxMUUzOUQwMzhDNzcwRjQ3N0YwOCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBQ0JDMjJEQzRCN0QxMUUzOUQwMzhDNzcwRjQ3N0YwOCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PovDFgYAAAAmSURBVHjaYvjPwMAAxjMZmBhA9H8INv4P4TPM/A+m04zBNECAAQBCWQv9SUQpVgAAAABJRU5ErkJggg==\") repeat-x!important;background:linear-gradient(180deg,red 0,red 16.5%,#f90 0,#f90 33%,#ff0 0,#ff0 50%,#3f0 0,#3f0 66%,#09f 0,#09f 83.5%,#63f 0,#63f)!important;background:-webkit-linear-gradient(top,red,red 16.5%,#f90 0,#f90 33%,#ff0 0,#ff0 50%,#3f0 0,#3f0 66%,#09f 0,#09f 83.5%,#63f 0,#63f)!important;background:-moz-linear-gradient(top,red 0,red 16.5%,#f90 16.5%,#f90 33%,#ff0 33%,#ff0 50%,#3f0 50%,#3f0 66%,#09f 66%,#09f 83.5%,#63f 83.5%,#63f 100%)!important}.html5-load-progress,.ytp-load-progress{background:url(\"data:image/gif;base64,R0lGODlhMAAMAIAAAAxBd////yH/C05FVFNDQVBFMi4wAwEAAAAh+QQECgAAACwAAAAAMAAMAAACJYSPqcvtD6MKstpLr24Z9A2GYvJ544mhXQmxoesElIyCcB3dRgEAIfkEBAoAAAAsAQACAC0ACgAAAiGEj6nLHG0enNQdWbPefOHYhSLydVhJoSYXPO04qrAmJwUAIfkEBAoAAAAsBQABACkACwAAAiGEj6nLwQ8jcC5ViW3evHt1GaE0flxpphn6BNTEqvI8dQUAIfkEBAoAAAAsAQABACoACwAAAiGEj6nLwQ+jcU5VidPNvPtvad0GfmSJeicUUECbxnK0RgUAIfkEBAoAAAAsAAAAACcADAAAAiCEj6mbwQ+ji5QGd6t+c/v2hZzYiVpXmuoKIikLm6hXAAAh+QQECgAAACwAAAAALQAMAAACI4SPqQvBD6NysloTXL480g4uX0iW1Wg21oem7ismLUy/LFwAACH5BAQKAAAALAkAAAAkAAwAAAIghI8Joe0Po0yBWTaz3g/z7UXhMX7kYmplmo0rC8cyUgAAIfkEBAoAAAAsBQAAACUACgAAAh2Ejwmh7Q+jbIFZNrPeEXPudU74IVa5kSiYqOtRAAAh+QQECgAAACwEAAAAIgAKAAACHISPELfpD6OcqTGKs4bWRp+B36YFi0mGaVmtWQEAIfkEBAoAAAAsAAAAACMACgAAAh2EjxC36Q+jnK8xirOW1kavgd+2BYtJhmnpiGtUAAAh+QQECgAAACwAAAAALgALAAACIYSPqcvtD+MKicqLn82c7e6BIhZQ5jem6oVKbfdqQLzKBQAh+QQECgAAACwCAAIALAAJAAACHQx+hsvtD2OStDplKc68r2CEm0eW5uSN6aqe1lgAADs=\")!important}.html5-scrubber-button,.ytp-scrubber-button{background:url(\"data:image/gif;base64,R0lGODlhIgAVAKIHAL3/9/+Zmf8zmf/MmZmZmf+Z/wAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpDMkJBNjY5RTU1NEJFMzExOUM4QUM2MDAwNDQzRERBQyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpCREIzOEIzMzRCN0IxMUUzODhEQjgwOTYzMTgyNTE0QiIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpCREIzOEIzMjRCN0IxMUUzODhEQjgwOTYzMTgyNTE0QiIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChXaW5kb3dzKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkM1QkE2NjlFNTU0QkUzMTE5QzhBQzYwMDA0NDNEREFDIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkMyQkE2NjlFNTU0QkUzMTE5QzhBQzYwMDA0NDNEREFDIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+Af/+/fz7+vn49/b19PPy8fDv7u3s6+rp6Ofm5eTj4uHg397d3Nva2djX1tXU09LR0M/OzczLysnIx8bFxMPCwcC/vr28u7q5uLe2tbSzsrGwr66trKuqqainpqWko6KhoJ+enZybmpmYl5aVlJOSkZCPjo2Mi4qJiIeGhYSDgoGAf359fHt6eXh3dnV0c3JxcG9ubWxramloZ2ZlZGNiYWBfXl1cW1pZWFdWVVRTUlFQT05NTEtKSUhHRkVEQ0JBQD8+PTw7Ojk4NzY1NDMyMTAvLi0sKyopKCcmJSQjIiEgHx4dHBsaGRgXFhUUExIREA8ODQwLCgkIBwYFBAMCAQAAIfkECQcABwAsAAAAACIAFQAAA6J4umv+MDpG6zEj682zsRaWFWRpltoHMuJZCCRseis7xG5eDGp93bqCA7f7TFaYoIFAMMwczB5EkTzJllEUttmIGoG5bfPBjDawD7CsJC67uWcv2CRov929C/q2ZpcBbYBmLGk6W1BRY4MUDnMvJEsBAXdlknk2fCeRk2iJliAijpBlEmigjR0plKSgpKWvEUheF4tUZqZID1RHjEe8PsDBBwkAIfkECQcABwAsAAAAACIAFQAAA6B4umv+MDpG6zEj682zsRaWFWRpltoHMuJZCCRseis7xG5eDGp93TqS40XiKSYgTLBgIBAMqE/zmQSaZEzns+jQ9pC/5dQJ0VIv5KMVWxqb36opxHrNvu9ptPfGbmsBbgSAeRdydCdjXWRPchQPh1hNAQF4TpM9NnwukpRyi5chGjqJEoSOIh0plaYsZBKvsCuNjY5ptElgDyFIuj6+vwcJACH5BAkHAAcALAAAAAAiABUAAAOfeLrc/vCZSaudUY7Nu99GxhhcYZ7oyYXiQQ5pIZgzCrYuLMd8MbAiUu802flYGIhwaCAQDKpQ86nUoWqF6dP00wIby572SXE6vyMrlmhuu9GKifWaddvNQAtszXYCxgR/Zy5jYTFeXmSDiIZGdQEBd06QSBQ5e4cEkE9nnZQaG2J4F4MSLx8rkqUSZBeurhlTUqsLsi60DpZxSWBJugcJACH5BAkHAAcALAAAAAAiABUAAAOgeLrc/vCZSaudUY7Nu99GxhhcYZ7oyYXiQQ5pIZgzCrYuLMd8MbAiUu802flYGIhwaCAQDKpQ86nUoWqF6dP00wIby572SXE6vyMrlmhuu9GuifWaddvNwMkZtmY7AWMEgGcKY2ExXl5khFMVc0Z1AQF3TpJShDl8iASST2efloV5JTyJFpgOch8dgW9KZxexshGNLqgLtbW0SXFwvaJfCQAh+QQJBwAHACwAAAAAIgAVAAADoXi63P7wmUmrnVGOzbvfRsYYXGGe6MmF4kEOaSGYMwq2LizHfDGwIlLPNKGZfi6gZmggEAy2iVPZEKZqzakq+1xUFFYe90lxTsHmim6HGpvf3eR7skYJ3PC5tyystc0AboFnVXQ9XFJTZIQOYUYFTQEBeWaSVF4bbCeRk1meBJYSL3WbaReMIxQfHXh6jaYXsbEQni6oaF21ERR7l0ksvA0JACH5BAkHAAcALAAAAAAiABUAAAOeeLrc/vCZSaudUY7Nu99GxhhcYZ7oyYXiQQ5pIZgzCrYuLMfFlA4hTITEMxkIBMOuADwmhzqeM6mashTCXKw2TVKQyKuTRSx2wegnNkyJ1ozpOFiMLqcEU8BZHx6NYW8nVlZefQ1tZgQBAXJIi1eHUTRwi0lhl48QL0sogxaGDhMlUo2gh14fHhcVmnOrrxNqrU9joX21Q0IUElm7DQkAIfkECQcABwAsAAAAACIAFQAAA6J4umv+MDpG6zEj682zsRaWFWRpltoHMuJZCCRseis7xG5eDGp93bqCA7f7TFaYoIFAMMwczB5EkTzJllEUttmIGoG5bfPBjDawD7CsJC67uWcv2CRov929C/q2ZpcBbYBmLGk6W1BRY4MUDnMvJEsBAXdlknk2fCeRk2iJliAijpBlEmigjR0plKSgpKWvEUheF4tUZqZID1RHjEe8PsDBBwkAIfkECQcABwAsAAAAACIAFQAAA6B4umv+MDpG6zEj682zsRaWFWRpltoHMuJZCCRseis7xG5eDGp93TqS40XiKSYgTLBgIBAMqE/zmQSaZEzns+jQ9pC/5dQJ0VIv5KMVWxqb36opxHrNvu9ptPfGbmsBbgSAeRdydCdjXWRPchQPh1hNAQF4TpM9NnwukpRyi5chGjqJEoSOIh0plaYsZBKvsCuNjY5ptElgDyFIuj6+vwcJACH5BAkHAAcALAAAAAAiABUAAAOfeLrc/vCZSaudUY7Nu99GxhhcYZ7oyYXiQQ5pIZgzCrYuLMd8MbAiUu802flYGIhwaCAQDKpQ86nUoWqF6dP00wIby572SXE6vyMrlmhuu9GKifWaddvNQAtszXYCxgR/Zy5jYTFeXmSDiIZGdQEBd06QSBQ5e4cEkE9nnZQaG2J4F4MSLx8rkqUSZBeurhlTUqsLsi60DpZxSWBJugcJACH5BAkHAAcALAAAAAAiABUAAAOgeLrc/vCZSaudUY7Nu99GxhhcYZ7oyYXiQQ5pIZgzCrYuLMd8MbAiUu802flYGIhwaCAQDKpQ86nUoWqF6dP00wIby572SXE6vyMrlmhuu9GuifWaddvNwMkZtmY7AWMEgGcKY2ExXl5khFMVc0Z1AQF3TpJShDl8iASST2efloV5JTyJFpgOch8dgW9KZxexshGNLqgLtbW0SXFwvaJfCQAh+QQJBwAHACwAAAAAIgAVAAADoXi63P7wmUmrnVGOzbvfRsYYXGGe6MmF4kEOaSGYMwq2LizHfDGwIlLPNKGZfi6gZmggEAy2iVPZEKZqzakq+1xUFFYe90lxTsHmim6HGpvf3eR7skYJ3PC5tyystc0AboFnVXQ9XFJTZIQOYUYFTQEBeWaSVF4bbCeRk1meBJYSL3WbaReMIxQfHXh6jaYXsbEQni6oaF21ERR7l0ksvA0JACH5BAkHAAcALAAAAAAiABUAAAOeeLrc/vCZSaudUY7Nu99GxhhcYZ7oyYXiQQ5pIZgzCrYuLMfFlA4hTITEMxkIBMOuADwmhzqeM6mashTCXKw2TVKQyKuTRSx2wegnNkyJ1ozpOFiMLqcEU8BZHx6NYW8nVlZefQ1tZgQBAXJIi1eHUTRwi0lhl48QL0sogxaGDhMlUo2gh14fHhcVmnOrrxNqrU9joX21Q0IUElm7DQkAOw==\")!important;border:none!important;height:21px!important;margin-left:-18px!important;margin-top:0!important;transform:scale(.8);-webkit-transform:scale(.8);-moz-transform:scale(.8);-ms-transform:scale(.8);width:34px!important}.ytp-progress-bar-container:hover .ytp-load-progress,.ytp-progress-bar-container:hover .ytp-scrubber-button{image-rendering:pixelated}.html5-progress-bar-container,.ytp-progress-bar-container{height:12px!important}.html5-progress-bar,.ytp-progress-bar{margin-top:12px!important}.html5-progress-list,.video-ads .html5-progress-list.html5-ad-progress-list,.video-ads .ytp-progress-list.ytp-ad-progress-list,.ytp-progress-list{height:12px!important}.ytp-volume-slider-track{background:#0c4177!important}";
  3161.  
  3162. const ThemeProgressbar = {
  3163. start: function() {
  3164. if (!/youtube\.com/.test(window.location.host)) {
  3165. return;
  3166. }
  3167. GM_addStyle(css_248z);
  3168. }
  3169. };
  3170.  
  3171. const commonUtil = {
  3172. onPageLoad: function(callback) {
  3173. if (document.readyState === "complete") {
  3174. callback();
  3175. } else {
  3176. window.addEventListener("DOMContentLoaded", callback, { once: true });
  3177. window.addEventListener("load", callback, { once: true });
  3178. }
  3179. },
  3180. addStyle: function(style) {
  3181. GM_addStyle(style);
  3182. },
  3183. openInTab: function(url, options = { "active": true, "insert": true, "setParent": true }) {
  3184. if (typeof GM_openInTab === "function") {
  3185. GM_openInTab(url, options);
  3186. } else {
  3187. GM.openInTab(url, options);
  3188. }
  3189. },
  3190. waitForElementByInterval: function(selector, target = document.body, allowEmpty = true, delay = 10, maxDelay = 10 * 1e3) {
  3191. return new Promise((resolve, reject) => {
  3192. let totalDelay = 0;
  3193. let element = target.querySelector(selector);
  3194. let result = allowEmpty ? !!element : !!element && !!element.innerHTML;
  3195. if (result) {
  3196. resolve(element);
  3197. }
  3198. const elementInterval = setInterval(() => {
  3199. if (totalDelay >= maxDelay) {
  3200. clearInterval(elementInterval);
  3201. resolve(null);
  3202. }
  3203. element = target.querySelector(selector);
  3204. result = allowEmpty ? !!element : !!element && !!element.innerHTML;
  3205. if (result) {
  3206. clearInterval(elementInterval);
  3207. resolve(element);
  3208. } else {
  3209. totalDelay += delay;
  3210. }
  3211. }, delay);
  3212. });
  3213. }
  3214. };
  3215.  
  3216. const SpeedControl = {
  3217. currentSpeed: 1,
  3218. activeAnimationId: null,
  3219. run: function() {
  3220. if (!/youtube\.com/.test(window.location.host)) {
  3221. return new Promise((resolve) => {
  3222. resolve();
  3223. });
  3224. }
  3225. return new Promise((resolve) => {
  3226. const speedControl = StorageUtil.getValue(StorageUtil.keys.youtube.functionState.speedControl, true);
  3227. if (!speedControl) {
  3228. resolve();
  3229. return;
  3230. }
  3231. const storageSpeed = StorageUtil.getValue(StorageUtil.keys.youtube.videoPlaySpeed, 1);
  3232. this.currentSpeed = parseFloat(storageSpeed);
  3233. this.insertStyle();
  3234. commonUtil.onPageLoad(async () => {
  3235. await this.genrate();
  3236. this.setVideoRate(storageSpeed);
  3237. this.videoObserver();
  3238. resolve();
  3239. });
  3240. });
  3241. },
  3242. insertStyle: function() {
  3243. const speedBtnStyle = `
  3244. .SpeedControl_Extension_Btn_X{
  3245. width: 4em !important;
  3246. float: left;
  3247. text-align: center !important;
  3248. border-radius: 0.5em;
  3249. font-size:13px;
  3250. }
  3251. .SpeedControl_Extension_Btn_X:hover{
  3252. color:red;
  3253. font-weight: bold;
  3254. }
  3255. `;
  3256. const speedShowStyle = `
  3257. #youtube-extension-text-box {
  3258. position: absolute!important;
  3259. margin: auto!important;
  3260. top: 0px!important;
  3261. right: 0px!important;
  3262. bottom: 0px!important;
  3263. left: 0px!important;
  3264. border-radius: 20px!important;
  3265. font-size: 30px!important;
  3266. background-color: #303031!important;
  3267. color: #f3f3f3!important;
  3268. z-index: 99999999999999999!important;
  3269. opacity: 0.8!important;
  3270. width: 80px!important;
  3271. height: 80px!important;
  3272. line-height: 80px!important;
  3273. text-align: center!important;
  3274. padding: 0px!important;
  3275. }
  3276. `;
  3277. const speedOptionsStyle = `
  3278. .SpeedControl_Extension_Speed-Options {
  3279. position: absolute!important;
  3280. background: #303031!important;
  3281. color: white!important;
  3282. border-radius: 5px!important;
  3283. display: none;
  3284. bottom: calc(100% + 10px)!important;
  3285. width:48px!important;
  3286. }
  3287. .SpeedControl_Extension_Speed-Options >.SpeedControl_Extension_Speed-Option-Item {
  3288. cursor: pointer!important;
  3289. height: 25px!important;
  3290. line-height: 25px!important;
  3291. font-size:12px!important;
  3292. text-align: center!important;
  3293. }
  3294. .SpeedControl_Extension_Speed-Options >.SpeedControl_Extension_Speed-Option-Item-Active,
  3295. .SpeedControl_Extension_Speed-Options >.SpeedControl_Extension_Speed-Option-Item:hover {
  3296. color: red!important;
  3297. }
  3298. `;
  3299. commonUtil.addStyle(speedBtnStyle + speedShowStyle + speedOptionsStyle);
  3300. },
  3301. genrate: async function() {
  3302. const speedControlBtn = document.createElement("div");
  3303. speedControlBtn.className = "ytp-button SpeedControl_Extension_Btn_X";
  3304. const speedText = document.createElement("span");
  3305. speedText.textContent = "" + this.currentSpeed + "×";
  3306. speedControlBtn.appendChild(speedText);
  3307. const player = await commonUtil.waitForElementByInterval("#player-container-outer .html5-video-player");
  3308. if (player) {
  3309. const rightControls = player.querySelector(".ytp-right-controls");
  3310. const ScreenShot_Codehemu_Btn = document.querySelector(".SpeedControl_Extension_Btn_X");
  3311. if (rightControls && !ScreenShot_Codehemu_Btn) {
  3312. rightControls.prepend(speedControlBtn);
  3313. this.genrateOptions(speedControlBtn);
  3314. }
  3315. }
  3316. },
  3317. genrateOptions: function(speedControl) {
  3318. const speedOptions = document.createElement("div");
  3319. speedOptions.classList.add("SpeedControl_Extension_Speed-Options");
  3320. speedControl.appendChild(speedOptions);
  3321. const speeds = ["0.5", "0.75", "1.0", "1.5", "2.0", "3.0"];
  3322. speeds.forEach((speed) => {
  3323. const option = document.createElement("div");
  3324. option.className = "SpeedControl_Extension_Speed-Option-Item";
  3325. option.textContent = `${speed}x`;
  3326. option.dataset.speed = speed;
  3327. if (parseFloat(speed) === this.currentSpeed) {
  3328. option.classList.add("SpeedControl_Extension_Speed-Option-Item-Active");
  3329. }
  3330. speedOptions.appendChild(option);
  3331. });
  3332. let isHovering = false;
  3333. speedControl.addEventListener("mouseenter", () => {
  3334. isHovering = true;
  3335. speedOptions.style.display = "block";
  3336. });
  3337. speedControl.addEventListener("mouseleave", () => {
  3338. isHovering = false;
  3339. setTimeout(() => {
  3340. if (!isHovering) {
  3341. speedOptions.style.display = "none";
  3342. }
  3343. }, 150);
  3344. });
  3345. speedOptions.addEventListener("mouseenter", () => {
  3346. isHovering = true;
  3347. });
  3348. speedOptions.addEventListener("mouseleave", () => {
  3349. isHovering = false;
  3350. speedOptions.style.display = "none";
  3351. });
  3352. speedOptions.addEventListener("click", (event) => {
  3353. speedOptions.style.display = "none";
  3354. const speedValue = parseFloat(event.target.dataset.speed);
  3355. this.speedDisplayText("" + speedValue + "×");
  3356. this.setVideoRate(speedValue);
  3357. this.currentSpeed = speedValue;
  3358. this.updateVideoPlaySpeedStorage(speedValue);
  3359. speedControl.querySelector("span").textContent = "" + speedValue + "×";
  3360. speedOptions.querySelectorAll(".SpeedControl_Extension_Speed-Option-Item").forEach((option) => {
  3361. option.classList.remove("SpeedControl_Extension_Speed-Option-Item-Active");
  3362. });
  3363. event.target.classList.add("SpeedControl_Extension_Speed-Option-Item-Active");
  3364. });
  3365. },
  3366. updateVideoPlaySpeedStorage: function(speedValue) {
  3367. StorageUtil.setValue(StorageUtil.keys.youtube.videoPlaySpeed, speedValue);
  3368. },
  3369. speedDisplayText: function(speedText) {
  3370. let elementId = "youtube-extension-text-box";
  3371. let element = document.getElementById(elementId);
  3372. if (!element) {
  3373. let mediaElement = document.getElementById("movie_player");
  3374. mediaElement.insertAdjacentHTML("afterbegin", `<div id="${elementId}">${speedText}</div>`);
  3375. element = document.getElementById(elementId);
  3376. } else {
  3377. element.textContent = speedText;
  3378. }
  3379. element.style.display = "block";
  3380. element.style.opacity = 0.8;
  3381. element.style.filter = `alpha(opacity=${0.8 * 100})`;
  3382. this.startFadeoutAnimation(element);
  3383. },
  3384. startFadeoutAnimation: function(element, startOpacity = 0.9, duration = 1500) {
  3385. let opacity = startOpacity;
  3386. const startTime = performance.now();
  3387. if (this.activeAnimationId) {
  3388. cancelAnimationFrame(this.activeAnimationId);
  3389. }
  3390. const fadeStep = (timestamp) => {
  3391. const elapsed = timestamp - startTime;
  3392. const progress = Math.min(elapsed / duration, 1);
  3393. opacity = startOpacity * (1 - progress);
  3394. element.style.opacity = opacity;
  3395. element.style.filter = `alpha(opacity=${opacity * 100})`;
  3396. if (progress < 1) {
  3397. this.activeAnimationId = requestAnimationFrame(fadeStep);
  3398. } else {
  3399. element.style.display = "none";
  3400. this.activeAnimationId = null;
  3401. }
  3402. };
  3403. this.activeAnimationId = requestAnimationFrame(fadeStep);
  3404. },
  3405. setVideoRate: function(speed) {
  3406. const videoElement = document.querySelector("video");
  3407. if (!videoElement)
  3408. return;
  3409. videoElement.playbackRate = speed;
  3410. },
  3411. videoObserver: function() {
  3412. const checkVideoInterval = setInterval(() => {
  3413. const videoElement = document.querySelector("video");
  3414. if (videoElement) {
  3415. clearInterval(checkVideoInterval);
  3416. const observer = new MutationObserver((mutationsList) => {
  3417. for (const mutation of mutationsList) {
  3418. if (mutation.type === "attributes" && mutation.attributeName === "src") {
  3419. videoElement.playbackRate = this.currentSpeed;
  3420. }
  3421. }
  3422. });
  3423. observer.observe(videoElement, {
  3424. attributes: true
  3425. });
  3426. }
  3427. }, 1500);
  3428. }
  3429. };
  3430.  
  3431. const MarkOrRemoveAd = {
  3432. generateRemoveAdElementId: "removeADHTMLElement_" + Math.ceil(Math.random() * 1e8),
  3433. markADHTMLElement: function() {
  3434. if (document.querySelector(this.generateRemoveAdElementId)) {
  3435. return;
  3436. }
  3437. let cssMarkSelectorArr = [
  3438. `#masthead-ad`,
  3439. `ytd-rich-item-renderer.style-scope.ytd-rich-grid-row #content:has(.ytd-display-ad-renderer)`,
  3440. `.video-ads.ytp-ad-module`,
  3441. `tp-yt-paper-dialog:has(yt-mealbar-promo-renderer)`,
  3442. `ytd-engagement-panel-section-list-renderer[target-id="engagement-panel-ads"]`,
  3443. `#related #player-ads`,
  3444. `#related ytd-ad-slot-renderer`,
  3445. `ytd-ad-slot-renderer`,
  3446. `yt-mealbar-promo-renderer`,
  3447. `ytd-popup-container:has(a[href="/premium"])`,
  3448. `ad-slot-renderer`,
  3449. `ytm-companion-ad-renderer`
  3450. ];
  3451. cssMarkSelectorArr.forEach((selector, index) => {
  3452. cssMarkSelectorArr[index] = `${selector} *{text-decoration:line-through!important;text-decoration-thickness:2px!important;}`;
  3453. });
  3454. const cssText = cssMarkSelectorArr.join(" ");
  3455. const style = document.createElement(`style`);
  3456. style.id = this.generateRemoveAdElementId;
  3457. (document.head || document.body).appendChild(style);
  3458. style.appendChild(document.createTextNode(cssText));
  3459. },
  3460. run: function() {
  3461. if (!/youtube\.com/.test(window.location.host)) {
  3462. return;
  3463. }
  3464. commonUtil.onPageLoad(() => {
  3465. this.markADHTMLElement();
  3466. });
  3467. }
  3468. };
  3469.  
  3470. const Theme = {
  3471. setTheme: function(theme = "light", isReload = true) {
  3472. if (theme === "light") {
  3473. this.setLight(isReload);
  3474. } else if (theme === "dark") {
  3475. this.setDark(isReload);
  3476. } else {
  3477. this.setLight(isReload);
  3478. }
  3479. },
  3480. setDark: function(isReload) {
  3481. this.isDarkTheme(true, isReload);
  3482. },
  3483. setLight: function(isReload) {
  3484. this.isDarkTheme(false, isReload);
  3485. },
  3486. reloadYouTube: function() {
  3487. location.reload();
  3488. },
  3489. isDarkTheme: function(enabled, isReload) {
  3490. const cookies = document.cookie.split("; ");
  3491. let prefCookie = cookies.find((cookie) => cookie.startsWith("PREF="));
  3492. let prefValue = prefCookie ? prefCookie.split("=")[1] : "f6=400";
  3493. prefValue = prefValue.replace(/&f6=\d+/, "").replace(/f6=\d+/, "");
  3494. const prefix = prefValue ? "&" : "";
  3495. if (enabled) {
  3496. prefValue += prefix + "f6=400";
  3497. } else {
  3498. prefValue += prefix + "f6=80000";
  3499. }
  3500. document.cookie = `PREF=${prefValue}; path=/; domain=.youtube.com; secure`;
  3501. if (isReload) {
  3502. this.reloadYouTube();
  3503. }
  3504. }
  3505. };
  3506.  
  3507. const Screenshot = {
  3508. start: function() {
  3509. var SF_Codhemeu = "png";
  3510. var extension = "png";
  3511. var appendixTitle = "screenshot." + extension;
  3512. var title;
  3513. var headerEls = document.querySelectorAll(
  3514. "h1.title.ytd-video-primary-info-renderer"
  3515. );
  3516. function SetTitle() {
  3517. if (headerEls.length > 0) {
  3518. title = headerEls[0].innerText.trim();
  3519. return true;
  3520. } else {
  3521. return false;
  3522. }
  3523. }
  3524. if (SetTitle() == false) {
  3525. headerEls = document.querySelectorAll("h1.watch-title-container");
  3526. if (SetTitle() == false)
  3527. title = "";
  3528. }
  3529. var player = document.getElementsByClassName("video-stream")[0];
  3530. var time = player.currentTime;
  3531. title += " ";
  3532. let minutes = Math.floor(time / 60);
  3533. time = Math.floor(time - minutes * 60);
  3534. if (minutes > 60) {
  3535. let hours = Math.floor(minutes / 60);
  3536. minutes -= hours * 60;
  3537. title += hours + "-";
  3538. }
  3539. title += minutes + "-" + time;
  3540. title += " " + appendixTitle;
  3541. var canvas = document.createElement("canvas");
  3542. canvas.width = player.videoWidth;
  3543. canvas.height = player.videoHeight;
  3544. canvas.getContext("2d").drawImage(player, 0, 0, canvas.width, canvas.height);
  3545. var downloadLink = document.createElement("a");
  3546. downloadLink.download = title;
  3547. function DownloadBlob(blob) {
  3548. downloadLink.href = URL.createObjectURL(blob);
  3549. downloadLink.click();
  3550. }
  3551. {
  3552. canvas.toBlob(async function(blob) {
  3553. DownloadBlob(blob);
  3554. }, "image/" + SF_Codhemeu);
  3555. }
  3556. }
  3557. };
  3558.  
  3559. const Dialog = function() {
  3560. class Dialog2 {
  3561. constructor() {
  3562. this.mask = document.createElement("div");
  3563. this.dialogStyle = document.createElement("style");
  3564. this.mask.classList.add("dialog-gcc-mask");
  3565. this.setStyle(this.mask, {
  3566. "width": "100%",
  3567. "height": "100%",
  3568. "backgroundColor": "rgba(0, 0, 0, .6)",
  3569. "position": "fixed",
  3570. "left": "0px",
  3571. "top": "0px",
  3572. "bottom": "0px",
  3573. "right": "0px",
  3574. "z-index": "9999999999999"
  3575. });
  3576. this.content = document.createElement("div");
  3577. this.content.classList.add("dialog-gcc-container");
  3578. this.setStyle(this.content, {
  3579. "max-width": "350px",
  3580. "width": "90%",
  3581. "backgroundColor": "#fff",
  3582. "boxShadow": "0 0 2px #999",
  3583. "position": "absolute",
  3584. "left": "50%",
  3585. "top": "50%",
  3586. "transform": "translate(-50%,-50%)",
  3587. "borderRadius": "5px"
  3588. });
  3589. this.mask.appendChild(this.content);
  3590. }
  3591. middleBox(param) {
  3592. this.content.innerHTML = "";
  3593. if (param.hasOwnProperty("direction")) {
  3594. this.content.setAttribute("data-extension-direction", param.direction);
  3595. }
  3596. let title = "";
  3597. if ({}.toString.call(param) === "[object String]") {
  3598. title = param;
  3599. } else if ({}.toString.call(param) === "[object Object]") {
  3600. title = param.title;
  3601. }
  3602. document.body.appendChild(this.mask);
  3603. this.title = document.createElement("div");
  3604. this.title.classList.add("dialog-gcc-title");
  3605. this.setStyle(this.title, {
  3606. "width": "100%",
  3607. "height": "40px",
  3608. "lineHeight": "40px",
  3609. "boxSizing": "border-box",
  3610. "background-color": "#dedede",
  3611. "color": "#000",
  3612. "text-align": "center",
  3613. "font-weight": "700",
  3614. "font-size": "17px",
  3615. "border-radius": "4px 4px 0px 0px"
  3616. });
  3617. const span = document.createElement("span");
  3618. span.innerText = title;
  3619. span.setAttribute("langue-extension-text", "setting_modal_title");
  3620. this.title.appendChild(span);
  3621. this.closeBtn = document.createElement("span");
  3622. this.closeBtn.innerText = "×";
  3623. this.setStyle(this.closeBtn, {
  3624. "textDecoration": "none",
  3625. "color": "#000",
  3626. "position": "absolute",
  3627. "inset-inline-end": "10px",
  3628. "top": "0px",
  3629. "fontSize": "25px",
  3630. "display": "inline-block",
  3631. "cursor": "pointer"
  3632. });
  3633. this.title.appendChild(this.closeBtn);
  3634. this.content.appendChild(this.title);
  3635. this.closeBtn.onclick = (e) => {
  3636. e.stopPropagation();
  3637. e.preventDefault();
  3638. this.close();
  3639. if (param.onClose) {
  3640. param.onClose();
  3641. }
  3642. };
  3643. }
  3644. showMake(param) {
  3645. if (param.hasOwnProperty("styleSheet")) {
  3646. this.dialogStyle.textContent = param.styleSheet;
  3647. }
  3648. document.querySelector("head").appendChild(this.dialogStyle);
  3649. this.middleBox(param);
  3650. this.dialogContent = document.createElement("div");
  3651. this.dialogContent.classList.add("dialog-gcc-content");
  3652. this.setStyle(this.dialogContent, {
  3653. "padding": "15px",
  3654. "max-height": "400px",
  3655. "overflow": "auto"
  3656. });
  3657. this.dialogContent.innerHTML = param.content;
  3658. this.content.appendChild(this.dialogContent);
  3659. param.onContentReady(this);
  3660. }
  3661. updateTitle(title) {
  3662. if (this.title) {
  3663. this.title.innerText = title;
  3664. }
  3665. }
  3666. close() {
  3667. document.body.removeChild(this.mask);
  3668. document.querySelector("head").removeChild(this.dialogStyle);
  3669. }
  3670. setStyle(ele, styleObj) {
  3671. for (let attr in styleObj) {
  3672. ele.style[attr] = styleObj[attr];
  3673. }
  3674. }
  3675. }
  3676. let dialog = null;
  3677. return function() {
  3678. if (!dialog) {
  3679. dialog = new Dialog2();
  3680. }
  3681. return dialog;
  3682. }();
  3683. }();
  3684.  
  3685. const LangueUtil = {
  3686. language: {
  3687. "en": {
  3688. direction: "ltr",
  3689. content: {
  3690. function_setting_title: "Setting",
  3691. function_is_comment_table_open: "Enable video details page interface optimization.",
  3692. function_is_theme_progress_bar_open: "Enable video playback progress bar beautification.",
  3693. function_is_speed_control_open: "Enable video fast forward (playback speed selectable).",
  3694. function_is_mark_or_remove_ad_open: "Enable page ad labeling."
  3695. }
  3696. },
  3697. "ja": {
  3698. direction: "ltr",
  3699. content: {
  3700. function_setting_title: "設定",
  3701. function_is_comment_table_open: "動画詳細ページのインターフェース最適化を有効にする。",
  3702. function_is_theme_progress_bar_open: "動画再生の進行状況バーの装飾を有効にする。",
  3703. function_is_speed_control_open: "動画の早送り(再生速度選択可能)を有効にする。",
  3704. function_is_mark_or_remove_ad_open: "ページ広告のラベリングを有効にする。"
  3705. }
  3706. },
  3707. "ko": {
  3708. direction: "ltr",
  3709. content: {
  3710. function_setting_title: "설정",
  3711. function_is_comment_table_open: "동영상 상세 페이지 인터페이스 최적화 활성화.",
  3712. function_is_theme_progress_bar_open: "동영상 재생 진행 바 장식 활성화.",
  3713. function_is_speed_control_open: "동영상 빨리감기(재생 속도 선택 가능) 활성화.",
  3714. function_is_mark_or_remove_ad_open: "페이지 광고 라벨링 활성화."
  3715. }
  3716. },
  3717. "ru": {
  3718. direction: "ltr",
  3719. content: {
  3720. function_setting_title: "Настройки",
  3721. function_is_comment_table_open: "Включить оптимизацию интерфейса страницы деталей видео.",
  3722. function_is_theme_progress_bar_open: "Включить улучшение панели прогресса воспроизведения видео.",
  3723. function_is_speed_control_open: "Включить перемотку видео (выбор скорости воспроизведения).",
  3724. function_is_mark_or_remove_ad_open: "Включить маркировку рекламы на странице."
  3725. }
  3726. },
  3727. "id": {
  3728. direction: "ltr",
  3729. content: {
  3730. "function_setting_title": "Pengaturan",
  3731. "function_is_comment_table_open": "Aktifkan pengoptimalan antarmuka halaman detail video.",
  3732. "function_is_theme_progress_bar_open": "Aktifkan pempercantik bilah progres pemutaran video.",
  3733. "function_is_speed_control_open": "Aktifkan percepatan video (kecepatan pemutaran dapat dipilih).",
  3734. "function_is_mark_or_remove_ad_open": "Aktifkan pelabelan iklan di halaman."
  3735. }
  3736. },
  3737. "fr": {
  3738. direction: "ltr",
  3739. content: {
  3740. "function_setting_title": "Paramètres",
  3741. "function_is_comment_table_open": "Activer l’optimisation de l’interface de la page de détails de la vidéo.",
  3742. "function_is_theme_progress_bar_open": "Activer l’embellissement de la barre de progression de la vidéo.",
  3743. "function_is_speed_control_open": "Activer l’avance rapide de la vidéo (vitesse de lecture sélectionnable).",
  3744. "function_is_mark_or_remove_ad_open": "Activer l’étiquetage des publicités sur la page."
  3745. }
  3746. },
  3747. "pt": {
  3748. direction: "ltr",
  3749. content: {
  3750. "function_setting_title": "Configurações",
  3751. "function_is_comment_table_open": "Ativar otimização da interface da página de detalhes do vídeo.",
  3752. "function_is_theme_progress_bar_open": "Ativar embelezamento da barra de progresso do vídeo.",
  3753. "function_is_speed_control_open": "Ativar avanço rápido do vídeo (velocidade de reprodução selecionável).",
  3754. "function_is_mark_or_remove_ad_open": "Ativar rotulagem de anúncios na página."
  3755. }
  3756. },
  3757. "tr": {
  3758. direction: "ltr",
  3759. content: {
  3760. "function_setting_title": "Ayarlar",
  3761. "function_is_comment_table_open": "Video detay sayfası arayüz optimizasyonunu etkinleştir.",
  3762. "function_is_theme_progress_bar_open": "Video oynatma ilerleme çubuğu güzelleştirmesini etkinleştir.",
  3763. "function_is_speed_control_open": "Video hızlı oynatmayı etkinleştir (oynatma hızı seçilebilir).",
  3764. "function_is_mark_or_remove_ad_open": "Sayfadaki reklam etiketlemesini etkinleştir."
  3765. }
  3766. }
  3767. },
  3768. getLang: function() {
  3769. let lang = (navigator.language || navigator.userLanguage).slice(0, 2).toLowerCase();
  3770. if (!lang) {
  3771. lang = "en";
  3772. }
  3773. return lang;
  3774. },
  3775. getLanguage: function() {
  3776. const lang = this.getLang();
  3777. return this.language[lang] ?? this.language.en;
  3778. }
  3779. };
  3780. const ToolBox = {
  3781. insertStyle: function() {
  3782. const speedOptionsStyle = `
  3783. .toolbox_extension_container {
  3784. position: absolute!important;
  3785. background: #303031!important;
  3786. color: white!important;
  3787. border-radius: 8px!important;
  3788. box-sizing: border-box!important;
  3789. z-index:999999999999!important;
  3790. display:none;
  3791. padding:13px!important;
  3792. }
  3793. .toolbox_extension_container .toolbox_extension_tools {
  3794. display: grid!important;
  3795. grid-template-columns: repeat(3, 1fr)!important;
  3796. gap: 8px!important;
  3797. }
  3798. .toolbox_extension_container .toolbox_extension_tool_btn {
  3799. width: 25px!important;
  3800. height: 25px!important;
  3801. background:#F4F4F4!important;
  3802. border: none!important;
  3803. cursor: pointer!important;
  3804. display: flex!important;
  3805. justify-content: center!important;
  3806. align-items: center!important;
  3807. border-radius:5px!important;
  3808. }
  3809. `;
  3810. commonUtil.addStyle(speedOptionsStyle);
  3811. },
  3812. genrateSettingSvg: function() {
  3813. const svgNS = "http://www.w3.org/2000/svg";
  3814. const svg = document.createElementNS(svgNS, "svg");
  3815. svg.setAttribute("viewBox", "0 0 1024 1024");
  3816. svg.setAttribute("width", "22");
  3817. svg.setAttribute("height", "22");
  3818. const path = document.createElementNS(svgNS, "path");
  3819. path.setAttribute("d", "M449.194667 82.346667a128 128 0 0 1 125.610666 0l284.16 160a128 128 0 0 1 65.194667 111.530666v316.245334a128 128 0 0 1-65.194667 111.530666l-284.16 160a128 128 0 0 1-125.610666 0l-284.16-160a128 128 0 0 1-65.194667-111.530666V353.877333A128 128 0 0 1 165.034667 242.346667z m83.754666 74.410666a42.666667 42.666667 0 0 0-41.898666 0L206.933333 316.714667a42.666667 42.666667 0 0 0-21.76 37.162666v316.245334a42.666667 42.666667 0 0 0 21.76 37.162666l284.16 160a42.666667 42.666667 0 0 0 41.898667 0l284.16-160a42.666667 42.666667 0 0 0 21.76-37.162666V353.877333a42.666667 42.666667 0 0 0-21.76-37.162666zM512 341.333333a170.666667 170.666667 0 1 1 0 341.333334 170.666667 170.666667 0 0 1 0-341.333334z m0 85.333334a85.333333 85.333333 0 1 0 0 170.666666 85.333333 85.333333 0 0 0 0-170.666666z");
  3820. path.setAttribute("fill", "#000000");
  3821. svg.appendChild(path);
  3822. return svg;
  3823. },
  3824. genrateToolSvg: function() {
  3825. const svgNS = "http://www.w3.org/2000/svg";
  3826. const svg = document.createElementNS(svgNS, "svg");
  3827. svg.setAttribute("viewBox", "0 0 1024 1024");
  3828. svg.setAttribute("width", "22");
  3829. svg.setAttribute("height", "22");
  3830. svg.setAttribute("class", "icon");
  3831. const path = document.createElementNS(svgNS, "path");
  3832. path.setAttribute("d", "M364.999 128.853H158.28c-52.383 0-95 42.617-95 95v206.719c0 52.383 42.617 95 95 95h206.719c52.383 0 95-42.617 95-95V223.853c0-52.384-42.617-95-95-95zM364.999 562.39H158.28c-52.383 0-95 42.617-95 95v206.719c0 52.383 42.617 95 95 95h206.719c52.383 0 95-42.617 95-95V657.39c0-52.383-42.617-95-95-95zM943.066 230.037L796.895 83.865c-17.943-17.943-41.8-27.825-67.175-27.825-25.376 0-49.232 9.881-67.175 27.825L516.372 230.037c-37.041 37.041-37.041 97.31 0 134.35l146.172 146.172c17.943 17.943 41.8 27.825 67.176 27.825 25.375 0 49.231-9.882 67.175-27.825l146.172-146.172c17.943-17.943 27.825-41.8 27.825-67.175s-9.882-49.233-27.826-67.175z m-21.212 113.137L775.682 489.346c-12.277 12.277-28.601 19.038-45.962 19.038-17.362 0-33.686-6.761-45.963-19.038L537.585 343.174c-25.343-25.344-25.343-66.581 0-91.924l146.173-146.172c12.276-12.277 28.6-19.038 45.962-19.038 17.361 0 33.685 6.761 45.962 19.038L921.854 251.25c12.276 12.277 19.038 28.6 19.038 45.962s-6.762 33.685-19.038 45.962zM798.887 562.39H592.168c-52.383 0-95 42.617-95 95v206.719c0 52.383 42.617 95 95 95h206.719c52.383 0 95-42.617 95-95V657.39c0-52.383-42.617-95-95-95z");
  3833. path.setAttribute("fill", "#ffffff");
  3834. svg.appendChild(path);
  3835. return svg;
  3836. },
  3837. genrateDownloadSvg: function(width = 20, height = 20) {
  3838. const svgNS = "http://www.w3.org/2000/svg";
  3839. const svg = document.createElementNS(svgNS, "svg");
  3840. svg.setAttribute("t", "1743576847386");
  3841. svg.setAttribute("class", "icon");
  3842. svg.setAttribute("viewBox", "0 0 1024 1024");
  3843. svg.setAttribute("version", "1.1");
  3844. svg.setAttribute("xmlns", svgNS);
  3845. svg.setAttribute("p-id", "1746");
  3846. svg.setAttribute("width", width);
  3847. svg.setAttribute("height", height);
  3848. const path1 = document.createElementNS(svgNS, "path");
  3849. path1.setAttribute("d", "M32 32h960v960H32z");
  3850. path1.setAttribute("fill", "#000000");
  3851. path1.setAttribute("fill-opacity", "0");
  3852. path1.setAttribute("p-id", "1747");
  3853. const path2 = document.createElementNS(svgNS, "path");
  3854. path2.setAttribute("d", "M852.00000031 476.54c21.07999969 0 38.35999969 16.51999969 39.9 37.5l0.09999938 3.01999969v212.80000031C891.99999969 819.42000031 820.35999969 891.99999969 732.00000031 891.99999969H291.99999969c-88.36000031 0-160.00000031-72.6-159.99999938-162.13999969v-212.80000031l0.09999938-3A40.21999969 40.21999969 0 0 1 171.99999969 476.52000031c21.07999969 0 38.35999969 16.51999969 39.9 37.5l0.10000031 3.01999969v212.80000031c0 44.77999969 35.80000031 81.07999969 79.99999969 81.07999969h440.00000062c44.20000031 0 79.99999969-36.3 79.99999969-81.07999969v-212.80000031l0.10000031-3A40.21999969 40.21999969 0 0 1 852.00000031 476.52000031zM512 132.00000031a40.00000031 40.00000031 0 0 1 40.00000031 39.99999938v342.24l99.63999938-104.13999938a45.94000031 45.94000031 0 0 1 66.46000031 0.06 50.4 50.4 0 0 1-0.06 69.6l-170.34 178.03999969a45.94000031 45.94000031 0 0 1-66.28000031 0.13999969 46.62 46.62 0 0 1-4.38-4.03999969l-170.34-178.02a50.4 50.4 0 0 1-0.06-69.6 45.94000031 45.94000031 0 0 1 64.96000031-1.57999969l1.5 1.5L471.99999969 509.55999969V171.99999969a40.00000031 40.00000031 0 0 1 40.00000031-39.99999938z");
  3855. path2.setAttribute("fill", "#000000");
  3856. path2.setAttribute("p-id", "1748");
  3857. svg.appendChild(path1);
  3858. svg.appendChild(path2);
  3859. return svg;
  3860. },
  3861. genrateScreenshotSvg: function() {
  3862. const svgNS = "http://www.w3.org/2000/svg";
  3863. const svg = document.createElementNS(svgNS, "svg");
  3864. svg.setAttribute("viewBox", "0 0 1024 1024");
  3865. svg.setAttribute("width", "20");
  3866. svg.setAttribute("height", "20");
  3867. svg.setAttribute("class", "icon");
  3868. const path1 = document.createElementNS(svgNS, "path");
  3869. path1.setAttribute("d", "M924.49999971 755.74999971h-93.74999942V287c0-52.49999971-41.24999971-93.75000029-93.75000029-93.75000029H268.25000029V99.50000029c0-22.5-15.00000029-37.50000029-37.50000029-37.50000029s-37.50000029 15.00000029-37.50000029 37.50000029v93.74999942H99.50000029c-22.5 0-37.50000029 15.00000029-37.50000029 37.50000029s15.00000029 37.50000029 37.50000029 37.50000029h93.74999942V737c0 52.49999971 41.24999971 93.75000029 93.75000029 93.75000029h468.74999971V924.49999971c0 22.5 15.00000029 37.50000029 37.50000029 37.50000029s37.50000029-15.00000029 37.50000029-37.50000029v-93.74999942H924.49999971c22.5 0 37.50000029-15.00000029 37.50000029-37.50000029s-15.00000029-37.50000029-37.50000029-37.50000029z m-187.49999971-487.49999942c11.25 0 18.74999971 7.49999971 18.74999971 18.74999971v299.99999971l-127.49999942-123.75c-15.00000029-15.00000029-37.50000029-15.00000029-52.50000058 0l-123.75 127.50000029L399.5 538.25000029c-15.00000029-15.00000029-33.75-15.00000029-48.75000029-3.75000029l-78.75 63.74999971V268.25000029H737z m-450 487.49999942c-11.25 0-18.74999971-7.49999971-18.74999971-18.74999971v-37.50000029l101.25-82.49999942 56.25 56.25c7.49999971 7.49999971 15.00000029 11.25 26.24999942 11.25s18.74999971-3.75000029 26.25000029-11.25l123.75-127.50000029 153.74999971 146.25v63.74999971H287z");
  3870. path1.setAttribute("fill", "#000000");
  3871. const path2 = document.createElementNS(svgNS, "path");
  3872. path2.setAttribute("d", "M399.5 485.74999971c45 0 82.50000029-37.50000029 82.50000029-82.49999942s-37.50000029-82.50000029-82.50000029-82.50000029-82.50000029 33.75-82.50000029 78.75 37.50000029 86.24999971 82.50000029 86.24999971z m0-112.5c15.00000029 0 29.99999971 11.25 29.99999971 30.00000058s-15.00000029 26.25000029-29.99999971 26.24999942-29.99999971-15.00000029-29.99999971-29.99999971 15.00000029-26.25000029 29.99999971-26.25000029z");
  3873. path2.setAttribute("fill", "#000000");
  3874. svg.appendChild(path1);
  3875. svg.appendChild(path2);
  3876. return svg;
  3877. },
  3878. genrateThemeExchageSvg: function() {
  3879. const svgNS = "http://www.w3.org/2000/svg";
  3880. const svg = document.createElementNS(svgNS, "svg");
  3881. svg.setAttribute("t", "1743577080138");
  3882. svg.setAttribute("class", "icon");
  3883. svg.setAttribute("viewBox", "0 0 1024 1024");
  3884. svg.setAttribute("version", "1.1");
  3885. svg.setAttribute("xmlns", svgNS);
  3886. svg.setAttribute("p-id", "1950");
  3887. svg.setAttribute("width", "20");
  3888. svg.setAttribute("height", "20");
  3889. const path = document.createElementNS(svgNS, "path");
  3890. path.setAttribute("d", "M873.91601563 358.72753906A393.42480469 393.42480469 0 0 0 512 118.25c-217.546875 0.47460938-393.75 176.57226563-393.75 393.75s176.203125 393.27539063 393.75 393.75a393.95214844 393.95214844 0 0 0 361.91601563-547.02246094zM749.77050781 750.65820313A335.27636719 335.27636719 0 0 1 512 849.5V174.5a337.5 337.5 0 0 1 237.77050781 576.15820313z");
  3891. path.setAttribute("p-id", "1951");
  3892. svg.appendChild(path);
  3893. return svg;
  3894. },
  3895. downloadVideo: function() {
  3896. const url = "https://www.tikfork.com/" + LangueUtil.getLang() + "/yt?s=1&url=" + window.location.href;
  3897. commonUtil.openInTab(url);
  3898. },
  3899. genrateTools: function(parent) {
  3900. const download = () => {
  3901. this.downloadVideo();
  3902. };
  3903. const themeExchage = () => {
  3904. let currentTheme = StorageUtil.getValue(StorageUtil.keys.youtube.theme, null);
  3905. if (currentTheme == "light" || !currentTheme) {
  3906. currentTheme = "dark";
  3907. } else {
  3908. currentTheme = "light";
  3909. }
  3910. StorageUtil.setValue(StorageUtil.keys.youtube.theme, currentTheme);
  3911. Theme.setTheme(currentTheme, true);
  3912. };
  3913. const screenshot = () => {
  3914. Screenshot.start();
  3915. };
  3916. const showSettingDialog = () => {
  3917. this.showSettingDialog();
  3918. };
  3919. const btns = [
  3920. {
  3921. "tagName": "div",
  3922. "classname": "toolbox_extension_tool_btn",
  3923. "onclick": showSettingDialog,
  3924. "icon": this.genrateSettingSvg()
  3925. },
  3926. {
  3927. "tagName": "div",
  3928. "classname": "toolbox_extension_tool_btn",
  3929. "onclick": themeExchage,
  3930. "icon": this.genrateThemeExchageSvg()
  3931. },
  3932. {
  3933. "tagName": "div",
  3934. "classname": "toolbox_extension_tool_btn",
  3935. "onclick": screenshot,
  3936. "icon": this.genrateScreenshotSvg()
  3937. },
  3938. {
  3939. "tagName": "div",
  3940. "classname": "toolbox_extension_tool_btn",
  3941. "onclick": download,
  3942. "icon": this.genrateDownloadSvg()
  3943. }
  3944. ];
  3945. for (let i = 0; i < btns.length; i++) {
  3946. let item = btns[i];
  3947. const element = document.createElement(item.tagName);
  3948. element.className = item.classname;
  3949. element.appendChild(item.icon);
  3950. element.onclick = item.onclick;
  3951. parent.appendChild(element);
  3952. }
  3953. },
  3954. genrateToolBox: function(button, player) {
  3955. const toolBoxContainer = document.createElement("div");
  3956. toolBoxContainer.id = "toolbox_extension_container";
  3957. toolBoxContainer.className = "toolbox_extension_container";
  3958. const tools = document.createElement("div");
  3959. tools.className = "toolbox_extension_tools";
  3960. this.genrateTools(tools);
  3961. toolBoxContainer.appendChild(tools);
  3962. player.appendChild(toolBoxContainer);
  3963. let isHovering = false;
  3964. button.addEventListener("mouseenter", () => {
  3965. toolBoxContainer.style.display = "block";
  3966. var containerRect = player.getBoundingClientRect();
  3967. var buttonRect = button.getBoundingClientRect();
  3968. var toolBoxContainerRect = toolBoxContainer.getBoundingClientRect();
  3969. var left = buttonRect.left - containerRect.left - toolBoxContainerRect.width / 2 + buttonRect.width / 2;
  3970. var top = buttonRect.top - containerRect.top - toolBoxContainer.clientHeight;
  3971. toolBoxContainer.style.left = `${left}px`;
  3972. toolBoxContainer.style.top = `${top}px`;
  3973. });
  3974. button.addEventListener("mouseleave", () => {
  3975. isHovering = false;
  3976. setTimeout(() => {
  3977. if (!isHovering) {
  3978. toolBoxContainer.style.display = "none";
  3979. }
  3980. }, 150);
  3981. });
  3982. toolBoxContainer.addEventListener("mouseenter", () => {
  3983. isHovering = true;
  3984. });
  3985. toolBoxContainer.addEventListener("mouseleave", () => {
  3986. isHovering = false;
  3987. toolBoxContainer.style.display = "none";
  3988. });
  3989. },
  3990. genrate: function() {
  3991. const buttonId = "toolBox_extension_codehemu_x";
  3992. const toolBoxOuter = document.createElement("div");
  3993. toolBoxOuter.className = "ytp-button";
  3994. toolBoxOuter.id = buttonId;
  3995. toolBoxOuter.setAttribute("style", `position: relative;display: inline-block;width: 48px;height: 100%;`);
  3996. const toolBoxInner = document.createElement("div");
  3997. toolBoxInner.setAttribute("style", `position: absolute;width: 100%;height: 100%; `);
  3998. const toolBoxButton = document.createElement("button");
  3999. toolBoxButton.setAttribute("style", `background-color: transparent;width: 100%;height: 100%;outline: none;flex: 1 1 0%;display: flex;-webkit-box-align: center;align-items: center;-webkit-box-pack: center;justify-content: center;border: none;padding: 0px;cursor: pointer;`);
  4000. toolBoxOuter.appendChild(toolBoxInner);
  4001. toolBoxInner.appendChild(toolBoxButton);
  4002. toolBoxButton.appendChild(this.genrateToolSvg());
  4003. const genrateHtml = () => {
  4004. const player = document.querySelector("#player-container-outer .html5-video-player");
  4005. if (player) {
  4006. const rightControls = player.querySelector(".ytp-right-controls");
  4007. if (rightControls) {
  4008. rightControls.prepend(toolBoxOuter);
  4009. this.genrateToolBox(toolBoxOuter, player);
  4010. }
  4011. }
  4012. };
  4013. const interval = setInterval(() => {
  4014. if (!document.querySelector("#" + buttonId)) {
  4015. genrateHtml();
  4016. } else {
  4017. clearInterval(interval);
  4018. }
  4019. }, 500);
  4020. },
  4021. genrateShorts: function() {
  4022. const svgNS = "http://www.w3.org/2000/svg";
  4023. const svg = document.createElementNS(svgNS, "svg");
  4024. svg.setAttribute("viewBox", "0 0 1024 1024");
  4025. svg.setAttribute("width", "32");
  4026. svg.setAttribute("height", "32");
  4027. const paths = [
  4028. {
  4029. d: "M0 0m512 0l0 0q512 0 512 512l0 0q0 512-512 512l0 0q-512 0-512-512l0 0q0-512 512-512Z",
  4030. opacity: ".7"
  4031. },
  4032. {
  4033. d: "M671.1552 727.2192H350.4128a95.7696 95.7696 0 0 1-96.2304-95.104v-190.2336a31.872 31.872 0 0 1 32.0768-31.7184 31.872 31.872 0 0 1 32.0768 31.7184v190.2336a31.9232 31.9232 0 0 0 32.0768 31.6928h320.7424a31.9232 31.9232 0 0 0 32.0768-31.6928v-190.2336a32.0768 32.0768 0 0 1 64.1536 0v190.2336a95.7696 95.7696 0 0 1-96.2304 95.104z",
  4034. fill: "#FFFFFF"
  4035. },
  4036. {
  4037. d: "M499.1232 563.7376a16.5632 16.5632 0 0 0 23.3472 0l108.7744-108.8256c6.4256-6.4256 4.2496-11.6736-4.8384-11.6736h-33.0496a16.5632 16.5632 0 0 1-16.512-16.5376v-66.0992a16.5376 16.5376 0 0 0-16.512-16.512h-99.0976a16.5632 16.5632 0 0 0-16.512 16.512v66.0992a16.5632 16.5632 0 0 1-16.512 16.5376h-33.1008c-9.088 0-11.264 5.248-4.8384 11.6736z",
  4038. fill: "#FFFFFF"
  4039. },
  4040. {
  4041. d: "M446.2336 294.5792a16.512 16.512 0 1 1 16.512 16.5376 16.5376 16.5376 0 0 1-16.512-16.5376z",
  4042. fill: "#FFFFFF"
  4043. },
  4044. {
  4045. d: "M542.2848 294.5792a16.512 16.512 0 1 1 16.512 16.5376 16.5376 16.5376 0 0 1-16.512-16.5376z",
  4046. fill: "#FFFFFF"
  4047. },
  4048. {
  4049. d: "M461.2352 277.9904h99.0976v33.0496h-99.0976z",
  4050. fill: "#FFFFFF"
  4051. }
  4052. ];
  4053. paths.forEach((attr) => {
  4054. const path = document.createElementNS(svgNS, "path");
  4055. for (let key in attr) {
  4056. path.setAttribute(key, attr[key]);
  4057. }
  4058. svg.appendChild(path);
  4059. });
  4060. const genrateHtml = () => {
  4061. if (window.location.href.indexOf("/shorts/") != -1) {
  4062. const navigationButtonDown = document.querySelector("#navigation-button-down");
  4063. if (navigationButtonDown) {
  4064. const download = document.createElement("div");
  4065. download.setAttribute("style", "cursor:pointer;display: flex;justify-content: center;align-items: center;");
  4066. download.id = "script_download_shorts";
  4067. download.className = "navigation-button style-scope ytd-shorts";
  4068. navigationButtonDown.after(download);
  4069. download.appendChild(svg);
  4070. download.addEventListener("click", () => {
  4071. this.downloadVideo();
  4072. });
  4073. }
  4074. }
  4075. };
  4076. setInterval(() => {
  4077. if (!document.querySelector("#script_download_shorts")) {
  4078. genrateHtml();
  4079. }
  4080. }, 800);
  4081. },
  4082. showSettingDialog: function() {
  4083. const functionState = StorageUtil.getValue(StorageUtil.keys.youtube.functionState, {
  4084. isOpenCommentTable: true,
  4085. isOpenThemeProgressBar: true,
  4086. isOpenSpeedControl: true,
  4087. isOpenMarkOrRemoveAd: true
  4088. });
  4089. const language = LangueUtil.getLanguage();
  4090. const styleSheet = `
  4091. .row-item{
  4092. background: #ffffff;
  4093. padding: 15px;
  4094. border-radius: 10px;
  4095. box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  4096. transition: background 0.3s;
  4097. margin-bottom: 10px;
  4098. }
  4099. .setting {
  4100. display: flex;
  4101. justify-content: space-between;
  4102. align-items: center;
  4103. }
  4104. .setting .setting-name{
  4105. flex: 1;
  4106. text-align: left;
  4107. font-size: 14px;
  4108. }
  4109. .setting .setting-switch{
  4110. width: 60px;
  4111. display: flex;
  4112. justify-content: end;
  4113. }
  4114. .recomment-item{
  4115. cursor: pointer;
  4116. }
  4117. .recomment-item:hover{
  4118. text-decoration: underline;
  4119. }
  4120. .ecomment-item-title{
  4121. font-size: 15px;
  4122. margin-bottom: 5px;
  4123. }
  4124. .ecomment-item-content{
  4125. font-size: 14px;
  4126. }
  4127. label {
  4128. font-size: 16px;
  4129. font-weight: bold;
  4130. }
  4131. .toggle {
  4132. width: 50px;
  4133. height: 25px;
  4134. background-color: #ccc;
  4135. border-radius: 15px;
  4136. position: relative;
  4137. cursor: pointer;
  4138. transition: background-color 0.3s;
  4139. display: inline-block;
  4140. }
  4141. .toggle:before {
  4142. content: '';
  4143. position: absolute;
  4144. width: 20px;
  4145. height: 20px;
  4146. background-color: white;
  4147. border-radius: 50%;
  4148. top: 50%;
  4149. left: 3px;
  4150. transform: translateY(-50%);
  4151. transition: 0.2s;
  4152. }
  4153. input:checked + .toggle {
  4154. background-color: #4CAF50;
  4155. }
  4156. input:checked + .toggle:before {
  4157. transform: translate(24px, -50%);
  4158. }
  4159. input {
  4160. display: none;
  4161. }
  4162. `;
  4163. const content = `
  4164. <div class="row-item setting">
  4165. <div class="setting-name" data-i18n="function_is_comment_table_open"></div>
  4166. <div class="setting-switch">
  4167. <input type="checkbox" id="isCommentTableOpen" /><label class="toggle" for="isCommentTableOpen"></label>
  4168. </div>
  4169. </div>
  4170. <div class="row-item setting">
  4171. <div class="setting-name" data-i18n="function_is_theme_progress_bar_open"></div>
  4172. <div class="setting-switch">
  4173. <input type="checkbox" id="isThemeProgressBarOpen" /><label class="toggle" for="isThemeProgressBarOpen"></label>
  4174. </div>
  4175. </div>
  4176. <div class="row-item setting">
  4177. <div class="setting-name" data-i18n="function_is_speed_control_open"></div>
  4178. <div class="setting-switch">
  4179. <input type="checkbox" id="isSpeedControlOpen" /><label class="toggle"for="isSpeedControlOpen"></label>
  4180. </div>
  4181. </div>
  4182. <div class="row-item setting">
  4183. <div class="setting-name" data-i18n="function_is_mark_or_remove_ad_open"></div>
  4184. <div class="setting-switch">
  4185. <input type="checkbox" id="isMarkOrRemoveAdOpen" /><label class="toggle"for="isMarkOrRemoveAdOpen"></label>
  4186. </div>
  4187. </div>
  4188. `;
  4189. Dialog.showMake({
  4190. title: language.content.function_setting_title,
  4191. content,
  4192. styleSheet,
  4193. direction: language.direction,
  4194. onContentReady: function($that) {
  4195. const commentTable = $that.dialogContent.querySelector("#isCommentTableOpen");
  4196. const themeProgressBar = $that.dialogContent.querySelector("#isThemeProgressBarOpen");
  4197. const speedControl = $that.dialogContent.querySelector("#isSpeedControlOpen");
  4198. const markOrRemoveAd = $that.dialogContent.querySelector("#isMarkOrRemoveAdOpen");
  4199. $that.dialogContent.querySelectorAll(".setting-name").forEach((element) => {
  4200. element.textContent = language.content[element.getAttribute("data-i18n")];
  4201. });
  4202. commentTable.checked = functionState.isOpenCommentTable;
  4203. themeProgressBar.checked = functionState.isOpenThemeProgressBar;
  4204. speedControl.checked = functionState.isOpenSpeedControl;
  4205. markOrRemoveAd.checked = functionState.isOpenMarkOrRemoveAd;
  4206. commentTable.addEventListener("change", (e) => {
  4207. functionState.isOpenCommentTable = e.target.checked;
  4208. StorageUtil.setValue(StorageUtil.keys.youtube.functionState, functionState);
  4209. });
  4210. themeProgressBar.addEventListener("change", (e) => {
  4211. functionState.isOpenThemeProgressBar = e.target.checked;
  4212. StorageUtil.setValue(StorageUtil.keys.youtube.functionState, functionState);
  4213. });
  4214. speedControl.addEventListener("change", (e) => {
  4215. functionState.isOpenSpeedControl = e.target.checked;
  4216. StorageUtil.setValue(StorageUtil.keys.youtube.functionState, functionState);
  4217. });
  4218. markOrRemoveAd.addEventListener("change", (e) => {
  4219. functionState.isOpenMarkOrRemoveAd = e.target.checked;
  4220. StorageUtil.setValue(StorageUtil.keys.youtube.functionState, functionState);
  4221. });
  4222. },
  4223. onClose: function() {
  4224. location.reload();
  4225. }
  4226. });
  4227. },
  4228. run: function() {
  4229. return new Promise((resolve) => {
  4230. if (/youtube\.com/.test(window.location.host)) {
  4231. GM_registerMenuCommand("Setting", () => {
  4232. this.showSettingDialog();
  4233. });
  4234. commonUtil.onPageLoad(() => {
  4235. const theme = StorageUtil.getValue(StorageUtil.keys.youtube.theme, null);
  4236. if (theme) {
  4237. Theme.setTheme(theme, false);
  4238. }
  4239. this.insertStyle();
  4240. this.genrate();
  4241. this.genrateShorts();
  4242. resolve();
  4243. });
  4244. } else {
  4245. resolve();
  4246. }
  4247. });
  4248. }
  4249. };
  4250.  
  4251. const {
  4252. isOpenCommentTable,
  4253. isOpenThemeProgressBar,
  4254. isOpenSpeedControl,
  4255. isOpenMarkOrRemoveAd
  4256. } = StorageUtil.getValue(StorageUtil.keys.youtube.functionState, {
  4257. isOpenCommentTable: true,
  4258. isOpenThemeProgressBar: true,
  4259. isOpenSpeedControl: true,
  4260. isOpenMarkOrRemoveAd: true
  4261. });
  4262. /*!
  4263. * credit to Benjamin Philipp
  4264. * MIT
  4265. * original source: https://gf.qytechs.cn/en/scripts/433051-trusted-types-helper
  4266. */
  4267. const overwrite_default = false;
  4268. const passThroughFunc = function(string, sink) {
  4269. return string;
  4270. };
  4271. var TTPName = "passthrough";
  4272. var TTP_default, TTP = { createHTML: passThroughFunc, createScript: passThroughFunc, createScriptURL: passThroughFunc };
  4273. var needsTrustedHTML = false;
  4274. !window.TTP && (() => {
  4275. try {
  4276. if (typeof window.isSecureContext !== "undefined" && window.isSecureContext) {
  4277. if (window.trustedTypes && window.trustedTypes.createPolicy) {
  4278. needsTrustedHTML = true;
  4279. if (trustedTypes.defaultPolicy) {
  4280. if (overwrite_default) ; else {
  4281. TTP = window.trustedTypes.createPolicy(TTPName, TTP);
  4282. }
  4283. TTP_default = trustedTypes.defaultPolicy;
  4284. } else {
  4285. TTP_default = TTP = window.trustedTypes.createPolicy(
  4286. "default",
  4287. TTP
  4288. );
  4289. }
  4290. }
  4291. }
  4292. } catch (e) {
  4293. } finally {
  4294. window.TTP = TTP;
  4295. }
  4296. })();
  4297. const createHTML = (s) => {
  4298. if (typeof TTP !== "undefined" && typeof TTP.createHTML === "function")
  4299. return TTP.createHTML(s);
  4300. return s;
  4301. };
  4302. (async () => {
  4303. if (!/youtube\.com/.test(window.location.host)) {
  4304. return;
  4305. }
  4306. if (!isOpenCommentTable) {
  4307. return;
  4308. }
  4309. const communicationKey = `ck-${Date.now()}-${Math.floor(Math.random() * 314159265359 + 314159265359).toString(36)}`;
  4310. const Promise = (async () => {
  4311. })().constructor;
  4312. if (!document.documentElement) {
  4313. await Promise.resolve(0);
  4314. while (!document.documentElement) {
  4315. await new Promise((resolve) => nextBrowserTick(resolve)).then().catch(console.warn);
  4316. }
  4317. }
  4318. const sourceURL = "debug://tabview-youtube/tabview.execution.js";
  4319. const textContent = `(${executionScript})("${communicationKey}");${"\n\n"}//# sourceURL=${sourceURL}${"\n"}`;
  4320. let button = document.createElement("button");
  4321. button.setAttribute("onclick", createHTML(textContent));
  4322. button.click();
  4323. button = null;
  4324. let style = document.createElement("style");
  4325. const sourceURLMainCSS = "debug://tabview-youtube/tabview.main.css";
  4326. style.textContent = `${styles["main"].trim()}${"\n\n"}/*# sourceURL=${sourceURLMainCSS} */${"\n"}`;
  4327. document.documentElement.appendChild(style);
  4328. })();
  4329. (async () => {
  4330. if (isOpenThemeProgressBar) {
  4331. ThemeProgressbar.start();
  4332. }
  4333. await ToolBox.run();
  4334. if (isOpenSpeedControl) {
  4335. await SpeedControl.run();
  4336. }
  4337. if (isOpenMarkOrRemoveAd) {
  4338. MarkOrRemoveAd.run();
  4339. }
  4340. })();
  4341.  
  4342. }());

QingJ © 2025

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