// ==UserScript== // @name YouTube™ Classic 📺 — (Remove rounded design + Return YouTube dislikes) // @name:af YouTube Klassiek // @name:am ዩቱብ ክላሲክ // @name:ar يوتيوب كلاسيك // @name:az YouTube Klassik // @name:be YouTube Класік // @name:bem YouTube Classic // @name:bg YouTube Класик // @name:bn ইউটিউব ক্লাসিক // @name:bo ཡུ་ཊུབ་སྲོལ་རྒྱུན། // @name:bs YouTube Klasični // @name:ca YouTube Clàssic // @name:ceb YouTube Klasiko // @name:ckb یوتیوب کلاسیک // @name:cs YouTube Klasický // @name:cy YouTube Clasurol // @name:da YouTube Klassisk // @name:de YouTube Classic // @name:dv ޔޫޓިއުބް ކްލަސިކް // @name:dz ཡུ་ཊུབ་སྲོལ་རྒྱུན། // @name:el YouTube Κλασικό // @name:eo YouTube Klasika // @name:es YouTube Clásico // @name:et YouTube Klassikaline // @name:eu YouTube Klasikoa // @name:fa یوتیوب کلاسیک // @name:fi YouTube Classic // @name:fo YouTube Classic // @name:fr YouTube Classique // @name:fr-CA YouTube Classique // @name:gd YouTube Clasaigeach // @name:gl YouTube Clásico // @name:gu યુટ્યુબ ક્લાસિક // @name:haw YouTube Kūmau // @name:he YouTube קלאסי // @name:hi यूट्यूब क्लासिक // @name:hr YouTube Klasični // @name:ht YouTube Klasik // @name:hu YouTube Klasszikus // @name:hy YouTube Դասական // @name:id YouTube Klasik // @name:is YouTube Sígilt // @name:it YouTube Classico // @name:ja YouTube クラシック // @name:jv YouTube Klasik // @name:ka YouTube კლასიკური // @name:kab YouTube Aklasik // @name:kk YouTube Классикалық // @name:km YouTube បុរាណ // @name:kn ಯೂಟ್ಯೂಬ್ ಕ್ಲಾಸಿಕ್ // @name:ko YouTube 클래식 // @name:ku YouTube Klasîk // @name:ky YouTube Классикалык // @name:la YouTube Classic // @name:lb YouTube Klassesch // @name:lo YouTube ຄລາສສິກ // @name:lt YouTube Klasikinis // @name:lv YouTube Klasiskais // @name:mg YouTube Klasika // @name:mi YouTube Matarohanga // @name:mk YouTube Класичен // @name:ml YouTube ക്ലാസിക് // @name:mn YouTube Сонгодог // @name:mr YouTube क्लासिक // @name:ms YouTube Klasik // @name:mt YouTube Klassiku // @name:my YouTube ဂန္ထဝင် // @name:ne YouTube क्लासिक // @name:nl YouTube Klassiek // @name:no YouTube Klassisk // @name:ny YouTube Yakale // @name:pa YouTube ਕਲਾਸਿਕ // @name:pl YouTube Klasyczny // @name:ps YouTube کلاسیک // @name:pt YouTube Clássico // @name:pt-BR YouTube Clássico // @name:ro YouTube Clasic // @name:ru YouTube Классический // @name:rw YouTube ya Kera // @name:sg YouTube Classique // @name:si YouTube සම්භාව්ය // @name:sk YouTube Klasický // @name:sl YouTube Klasični // @name:sm YouTube Fa'ata'atia // @name:sn YouTube Yekare // @name:so YouTube Qadiimiga // @name:sq YouTube Klasik // @name:sr YouTube Класични // @name:st YouTube ya Khale // @name:sv YouTube Klassisk // @name:sw YouTube ya Awali // @name:ta YouTube கிளாசிக் // @name:te YouTube క్లాసిక్ // @name:tg YouTube Классикӣ // @name:th YouTube คลาสสิก // @name:ti ዩቱብ ክላሲክ // @name:tk YouTube Klassiki // @name:tl YouTube Klasiko // @name:tn YouTube ya Bogologolo // @name:to YouTube Motu'a // @name:tr YouTube Klasik // @name:tt YouTube Классик // @name:ug YouTube كلاسسىك // @name:uk YouTube Класичний // @name:ur YouTube کلاسک // @name:uz YouTube Klassik // @name:vi YouTube Cổ Điển // @name:wo YouTube Xóot // @name:xh YouTube Yakudala // @name:yi YouTube קלאַסיש // @name:yo YouTube Ayebaye // @name:zh YouTube 经典 // @name:zh-CN YouTube 经典 // @name:zh-HK YouTube 經典 // @name:zh-SG YouTube 经典 // @name:zh-TW YouTube 經典 // @name:zu YouTube Yakudala // @version 2026.5.23.1 // @author Adam Lui, Magma_Craft // @namespace https://github.com/adamlui // @description Reverts YouTube to its classic design (before all the rounded corners & hidden dislikes) + redirects YouTube Shorts + blocks thumbnail ads // @description:af Keer YouTube terug na sy klassieke ontwerp (voor al die geronde hoeke en verborge dislikes) + herlei YouTube Shorts + blokkeer miniatuur advertensies // @description:am YouTubeን ወደ ክላሲክ ዲዛይኑ ይመልሳል (የተጠጋጉ ማዕዘኖች እና የተደበቁ አለመውደዶች በፊት) + YouTube Shortsን ያዛውራል + ድንክዬ ማስታወቂያዎችን ያግዳል // @description:ar يعيد YouTube إلى تصميمه الكلاسيكي (قبل كل الزوايا المستديرة وعدم الإعجابات المخفية) + إعادة توجيه YouTube Shorts + حظر إعلانات الصور المصغرة // @description:az YouTube-u klassik dizaynına qaytarır (bütün yuvarlaq künclər və gizli bəyənməmələrdən əvvəl) + YouTube Shorts-u yönləndirir + miniatür reklamlarını bloklayır // @description:be Вяртае YouTube да класічнага дызайну (да ўсіх закругленых кутоў і схаваных дызлайкаў) + перанакіроўвае YouTube Shorts + блакуе мініяцюрныя рэкламы // @description:bem Yubwekesha YouTube ku mushobo wayo wakale (pansela ya ma angle yonse ayendaula ne ma dislikes afisama) + ilolo kwa YouTube Shorts + blockinga ama thumbnail ads // @description:bg Връща YouTube към класическия му дизайн (преди всички заоблени ъгли и скрити нехаресвания) + пренасочва YouTube Shorts + блокира реклами с миниатюри // @description:bn ইউটিউবকে তার ক্লাসিক ডিজাইনে ফিরিয়ে আনে (সব গোলাকার কোণ এবং লুকানো ডিসলাইকের আগে) + ইউটিউব শর্টস রিডাইরেক্ট করে + থাম্বনেইল বিজ্ঞাপন ব্লক করে // @description:bo YouTubeའདི་དེའི་སྲོལ་རྒྱུན་དབྱིབས་དབྱངས་ལུང་བརྗེད་ཀྱི་སྐོར་ལ་སླར་གསོ་བྱེད་ཀྱིན་འདུག (ཟུར་ཟླུམ་མམ་བཞིན་དང་གསང་བའི་མི་འདོད་པ་རྣམས་ཀྱི་སྔོན་ལ) + YouTube Shortsབསྐྱར་ཁྲིད་བྱེད་ཀྱིན་འདུག + མཚོན་ཐུང་ཚོང་རྟགས་འགོག་བྱེད་ཀྱིན་འདུག // @description:bs Vraća YouTube na njegov klasični dizajn (prije svih zaobljenih uglova i skrivenih dislajkova) + preusmjerava YouTube Shorts + blokira minijaturne reklame // @description:ca Retorna YouTube al seu disseny clàssic (abans de totes les cantonades arrodonides i els dislikes amagats) + redirigeix YouTube Shorts + bloqueja anuncis de miniatures // @description:ceb Ibalik ang YouTube sa klasiko nga disenyo (sa wala pa ang tanang lingin nga mga suok ug gitago nga mga dislikes) + gi-redirect ang YouTube Shorts + gibabagan ang mga thumbnail ads // @description:ckb یوتیوب بۆ دیزاینی کلاسیکی خۆی دەگەڕێنێتەوە (پێش هەموو گۆشە خڕەکان و دڵنەکردنە شاراوەکان) + یوتیوب شۆرتس ڕەوانە دەکات + ڕیکلامی وێنە بچووکەکان بلۆک دەکات // @description:cs Vrací YouTube do klasického designu (před všemi zaoblenými rohy a skrytými dislikes) + přesměrovává YouTube Shorts + blokuje miniaturní reklamy // @description:cy Yn dychwelyd YouTube i'w ddyluniad clasurol (cyn yr holl gorneli crwn a dislikes cudd) + ailgyfeirio YouTube Shorts + blocio hysbysebion mân-luniau // @description:da Gendanner YouTube til dets klassiske design (før alle de afrundede hjørner og skjulte dislikes) + omdirigerer YouTube Shorts + blokerer miniatureannoncer // @description:de Stellt das klassische Design von YouTube wieder her (vor all den abgerundeten Ecken und versteckten Dislikes) + leitet YouTube Shorts um + blockiert Thumbnail-Werbung // @description:dv ޔޫޓިއުބް އޭގެ ކްލަސިކް ޑިޒައިން އަށް ރީޑިސައިން ކުރުން (ހުރިހާ ވަށްކޯނާއި ފޮރުވި ޑިސްލައިކްސް ގެ ކުރިން) + ޔޫޓިއުބް ޝޯޓްސް ރީޑައިރެކްޓް + ތަމްބްނެއިލް އިޝްތިހާރު ބްލޮކް // @description:dz ཡུ་ཊུབ་མོའི་སྲོལ་རྒྱུན་གྱི་དབྱིབས་རྩ་ལུ་སླར་ལོག་གཏང་དགོ (ཟུར་ཟླུམ་རང་བཞིན་མ་བྱུང་གོང་དང་གསང་བའི་མི་འདོད་པ་རྣམས་ཀྱི་སྔོན་ལ) + ཡུ་ཊུབ་ཐུང་ཐུང་དེ་ཚུ་ཁ་ཕྱོགས་བསྒྱུར་བ་ + མཚོན་ཐུང་ཚོང་རྟགས་དེ་ཚུ་འགོག་པ། // @description:el Επαναφέρει το YouTube στον κλασικό του σχεδιασμό (πριν από όλες τις στρογγυλεμένες γωνίες και τα κρυφά dislikes) + ανακατευθύνει τα YouTube Shorts + μπλοκάρει τις διαφημίσεις μικρογραφιών // @description:eo Reakiras YouTube al sia klasika dezajno (antaŭ ĉiuj rondigitaj anguloj kaj kaŝitaj mallaŭkoj) + alidirektas YouTube Shorts + blokas miniaturajn reklamojn // @description:es Revierte YouTube a su diseño clásico (antes de todas las esquinas redondeadas y dislikes ocultos) + redirige YouTube Shorts + bloquea anuncios en miniaturas // @description:et Taastab YouTube'i klassikalise disaini (enne kõiki ümaraid nurki ja peidetud dislikesid) + suunab YouTube Shorts ümber + blokeerib pisipildireklaamid // @description:eu YouTube bere diseinu klasikora itzultzen du (izkin biribildu guztiak eta ezkutuko dislikes-en aurretik) + YouTube Shorts berbideratzen du + miniaturazko iragarkiak blokeatzen ditu // @description:fa یوتیوب را به طراحی کلاسیک خود برمی‌گرداند (قبل از تمام گوشه‌های گرد و دیسلایک‌های پنهان) + یوتیوب شورتز را هدایت می‌کند + تبلیغات تصویر کوچک را مسدود می‌کند // @description:fi Palauttaa YouTuben klassiseen muotoiluun (ennen kaikkia pyöristettyjä kulmia ja piilotettuja dislikes) + ohjaa YouTube Shortsit uudelleen + estää pikkukuvamainokset // @description:fo Vendir YouTube aftur til sína klassiska snið (áðrenn øll rundu hornini og fjaldu dislikesini) + umstjórnar YouTube Shorts + forðar smámyndalýsingum // @description:fr Ramène YouTube à son design classique (avant tous les coins arrondis et les dislikes cachés) + redirige YouTube Shorts + bloque les publicités miniatures // @description:fr-CA Ramène YouTube à son design classique (avant tous les coins arrondis et les dislikes cachés) + redirige YouTube Shorts + bloque les publicités miniatures // @description:gd Tillidh YouTube chun a dhealbhachd clasaigeach (ro na h-uile ceàrnan cruinn agus dislikes falaichte) + ath-stiùiridh YouTube Shorts + bacadh shanasan dealbhagan // @description:gl Reverte YouTube ao seu deseño clásico (antes de todas as esquinas redondeadas e dislikes ocultos) + redirixe YouTube Shorts + bloquea anuncios en miniaturas // @description:gu યુટ્યુબને તેની ક્લાસિક ડિઝાઇનમાં પરત લાવે છે (બધા ગોળાકાર ખૂણા અને છુપાયેલા ડિસલાઇક્સ પહેલા) + યુટ્યુબ શોર્ટ્સ રીડાયરેક્ટ કરે છે + થંબનેઇલ જાહેરાતો બ્લોક કરે છે // @description:haw Hoʻihoʻi i YouTube i kona hoʻolālā kuʻuna (ma mua o nā kihi pōʻai a me nā dislikes huna) + hoʻihoʻi hou i YouTube Shorts + pāpā i nā hoʻolaha thumbnail // @description:he מחזיר את YouTube לעיצוב הקלאסי שלו (לפני כל הפינות המעוגלות והדיסלייקים המוסתרים) + מפנה מחדש YouTube Shorts + חוסם מודעות תמונות ממוזערות // @description:hi YouTube को उसके क्लासिक डिज़ाइन में वापस लाता है (सभी गोल कोनों और छिपे हुए डिसलाइक से पहले) + YouTube शॉर्ट्स को रीडायरेक्ट करता है + थंबनेल विज्ञापनों को ब्लॉक करता है // @description:hr Vraća YouTube na njegov klasični dizajn (prije svih zaobljenih uglova i skrivenih dislajkova) + preusmjerava YouTube Shorts + blokira minijaturne oglase // @description:ht Retounen YouTube nan konsepsyon klasik li (anvan tout kwen awondi ak dislikes kache yo) + redireksyon YouTube Shorts + bloke piblisite ti imaj yo // @description:hu Visszaállítja a YouTube-ot a klasszikus dizájnjára (az összes lekerekített sarok és a rejtett dislikes előtt) + átirányítja a YouTube Shorts-ot + blokkolja a miniatűr hirdetéseket // @description:hy YouTube-ը վերադարձնում է իր դասական ձևավորմանը (մինչ բոլոր կլորացված անկյունները և թաքցված դիզլայքերը) + վերաուղղորդում է YouTube Shorts-ը + արգելափակում է մանրապատկերի գովազդները // @description:id Mengembalikan YouTube ke desain klasiknya (sebelum semua sudut melengkung dan dislikes tersembunyi) + mengalihkan YouTube Shorts + memblokir iklan thumbnail // @description:is Endurheimtir YouTube í sína klassísku hönnun (fyrir öll rúnuðu hornin og földu dislikes) + endurbeina YouTube Shorts + lokar á smámyndaauglýsingar // @description:it Ripristina YouTube al suo design classico (prima di tutti gli angoli arrotondati e i dislikes nascosti) + reindirizza YouTube Shorts + blocca gli annunci miniatura // @description:ja YouTubeをクラシックデザインに戻します(丸みを帯びた角と非表示の低評価の前の状態)+ YouTubeショートをリダイレクト + サムネイル広告をブロック // @description:jv Mbalikake YouTube menyang desain klasik (sadurunge kabeh sudhut bunder lan dislikes sing didhelikake) + ngalihake YouTube Shorts + mblokir iklan gambar cilik // @description:ka YouTube-ს უბრუნებს კლასიკურ დიზაინს (ყველა მომრგვალებულ კუთხემდე და დამალულ dislikes-მდე) + გადამისამართებს YouTube Shorts-ს + ბლოკავს მინიატურულ რეკლამებს // @description:kab Yernu YouTube ɣer usebter-nnes aklasik (uqbel akk teɣmert iqejjiren akked dislikes ifferen) + yezzi YouTube Shorts + yessewḥal ads n thumbnail // @description:kk YouTube-ты классикалық дизайнына қайтарады (барлық дөңгеленген бұрыштар мен жасырын дизлайктарға дейін) + YouTube Shorts-ты қайта бағыттайды + нобай жарнамаларын бұғаттайды // @description:km ធ្វើអោយ YouTube ត្រឡប់ទៅរចនាបទបុរាណវិញ (មុនពេលជ្រុងមូលទាំងអស់ និង dislikes លាក់) + បញ្ជូនបន្ត YouTube Shorts + រារាំងពាណិជ្ជកម្មរូបភាពតូច // @description:kn YouTube ಅನ್ನು ಅದರ ಕ್ಲಾಸಿಕ್ ವಿನ್ಯಾಸಕ್ಕೆ ಹಿಂತಿರುಗಿಸುತ್ತದೆ (ಎಲ್ಲಾ ದುಂಡಾದ ಮೂಲೆಗಳು ಮತ್ತು ಅಡಗಿರುವ ಡಿಸ್‌ಲೈಕ್‌ಗಳ ಮೊದಲು) + YouTube ಶಾರ್ಟ್ಸ್‌ಗಳನ್ನು ಮರುನಿರ್ದೇಶಿಸುತ್ತದೆ + ಥಂಬ್‌ನೇಲ್ ಜಾಹೀರಾತುಗಳನ್ನು ನಿರ್ಬಂಧಿಸುತ್ತದೆ // @description:ko YouTube를 클래식 디자인으로 되돌립니다 (둥근 모서리와 숨겨진 싫어요 이전) + YouTube 쇼츠를 리디렉션 + 썸네일 광고 차단 // @description:ku YouTube-ê vedigerîne sêwirana xwe ya klasîk (berî hemî quncikên girover û dislikesên veşartî) + YouTube Shorts-ê rêve dike + reklamên thumbnail asteng dike // @description:ky YouTube'ду классикалык дизайнына кайтарат (бардык тегеректелген бурчтар жана жашырылган дизлайктарга чейин) + YouTube Shorts'ду багыттайт + эскиз жарнамаларын бөгөттөйт // @description:la YouTube ad classicum consilium suum revertit (ante omnes angulos rotundos et dislikes occultos) + YouTube Shorts redirigit + minutas tabulas impedit // @description:lb Setzt YouTube op säi klasseschen Design zréck (virun all de ronnen Ecker a verstoppten Dislikes) + leet YouTube Shorts ëm + blockéiert Miniatur Annoncen // @description:lo ເຮັດໃຫ້ YouTube ກັບຄືນສູ່ການອອກແບບຄລາສສິກ (ກ່ອນທີ່ຈະມີມຸມມົນທັງໝົດ ແລະການບໍ່ມັກທີ່ເຊື່ອງໄວ້) + ປ່ຽນເສັ້ນທາງ YouTube Shorts + ບລັອກໂຄສະນາຮູບພາບນ້ອຍ // @description:lt Grąžina YouTube į klasikinį dizainą (prieš visus užapvalintus kampus ir paslėptus dislikes) + nukreipia YouTube Shorts + blokuoja miniatiūrines reklamas // @description:lv Atgriež YouTube klasiskajā dizainā (pirms visiem noapaļotajiem stūriem un slēptajiem dislikes) + pārvirza YouTube Shorts + bloķē sīktēlu reklāmas // @description:mg Mamerina an'i YouTube amin'ny endriny klasika (alohan'ny zoro boribory rehetra sy ny dislikes miafina) + mamerina ny YouTube Shorts + manakana ny dokambarotra saritapaka // @description:mi Whakahokia a YouTube ki tana hoahoa matarohanga (i mua i ngā kokonga porowhita katoa me ngā dislikes huna) + whakaararua YouTube Shorts + aukati i ngā whakatairanga karakōnui // @description:mk Го враќа YouTube на неговиот класичен дизајн (пред сите заоблени агли и скриени dislikes) + пренасочува YouTube Shorts + блокира реклами со минијатури // @description:ml YouTube-നെ അതിന്റെ ക്ലാസിക് ഡിസൈനിലേക്ക് തിരികെ കൊണ്ടുവരുന്നു (എല്ലാ ഉരുണ്ട കോണുകളും മറഞ്ഞിരിക്കുന്ന ഡിസ്‌ലൈക്കുകളും മുമ്പ്) + YouTube ഷോർട്ട്സ് റീഡയറക്ട് ചെയ്യുന്നു + തംബ്നെയിൽ പരസ്യങ്ങൾ ബ്ലോക്ക് ചെയ്യുന്നു // @description:mn YouTube-г сонгодог загварт нь буцаана (бүх дугуйрсан булан болон нуугдсан дургүй байдлын өмнө) + YouTube Shorts-г дахин чиглүүлнэ + өнгөц зураг сурталчилгааг блоклоно // @description:mr YouTube ला त्याच्या क्लासिक डिझाइनवर परत आणते (सर्व गोलाकार कोपरे आणि लपविलेल्या डिसलाइकच्या आधी) + YouTube शॉर्ट्स रीडायरेक्ट करते + थंबनेल जाहिराती ब्लॉक करते // @description:ms Mengembalikan YouTube kepada reka bentuk klasiknya (sebelum semua sudut bulat dan dislikes tersembunyi) + mengalihkan YouTube Shorts + menyekat iklan lakaran kecil // @description:mt Ireġġa' lura YouTube għad-disinn klassiku tiegħu (qabel l-irkejjen kollha ttundjati u d-dislikes moħbija) + tirridirieġi YouTube Shorts + timblokka r-reklami tal-minjaturi // @description:my YouTube ကို ၎င်း၏ ဂန္ထဝင် ဒီဇိုင်းသို့ ပြန်ပြောင်းသည် (အဝိုင်းထောင့်များနှင့် ဝှက်ထားသော dislikes များ မတိုင်မီ) + YouTube Shorts ကို ပြန်ညွှန်းသည် + နမူနာပုံငယ် ကြော်ငြာများကို ပိတ်ဆို့သည် // @description:ne YouTube लाई यसको क्लासिक डिजाइनमा फर्काउँछ (सबै गोलाकार कुनाहरू र लुकाइएको डिसलाइकहरू अघि) + YouTube शर्ट्स रिडाइरेक्ट गर्दछ + थम्बनेल विज्ञापनहरू ब्लक गर्दछ // @description:nl Zet YouTube terug naar zijn klassieke ontwerp (vóór alle afgeronde hoeken en verborgen dislikes) + leidt YouTube Shorts om + blokkeert miniatuuradvertenties // @description:no Gjenoppretter YouTube til sitt klassiske design (før alle de avrundede hjørnene og skjulte dislikes) + omdirigerer YouTube Shorts + blokkerer miniatyrannonser // @description:ny Imabwezera YouTube ku mapangidwe ake akale (pamaso pa ngodya zonse zozungulira ndi dislikes zobisika) + imalowetsa YouTube Shorts + imatseka zotsatsa za thumbnail // @description:pa YouTube ਨੂੰ ਇਸਦੇ ਕਲਾਸਿਕ ਡਿਜ਼ਾਈਨ 'ਤੇ ਵਾਪਸ ਲਿਆਉਂਦਾ ਹੈ (ਸਾਰੇ ਗੋਲ ਕੋਨਿਆਂ ਅਤੇ ਲੁਕਵੇਂ ਡਿਸਲਾਈਕਸ ਤੋਂ ਪਹਿਲਾਂ) + YouTube ਸ਼ਾਰਟਸ ਨੂੰ ਰੀਡਾਇਰੈਕਟ ਕਰਦਾ ਹੈ + ਥੰਬਨੇਲ ਇਸ਼ਤਿਹਾਰਾਂ ਨੂੰ ਬਲਾਕ ਕਰਦਾ ਹੈ // @description:pl Przywraca YouTube do klasycznego wyglądu (sprzed wszystkich zaokrąglonych rogów i ukrytych dislikes) + przekierowuje YouTube Shorts + blokuje reklamy miniatur // @description:ps YouTube خپل کلاسیک ډیزاین ته بیرته ګرځوي (د ټولو ګردو کونجونو او پټو dislikes څخه مخکې) + YouTube Shorts ته لارښوونه کوي + د تمبنېل اعلانونه بلاک کوي // @description:pt Reverte o YouTube para o seu design clássico (antes de todos os cantos arredondados e dislikes ocultos) + redireciona YouTube Shorts + bloqueia anúncios em miniaturas // @description:pt-BR Reverte o YouTube para o seu design clássico (antes de todos os cantos arredondados e dislikes ocultos) + redireciona YouTube Shorts + bloqueia anúncios em miniaturas // @description:ro Revine YouTube la designul său clasic (înainte de toate colțurile rotunjite și dislikes ascunse) + redirecționează YouTube Shorts + blochează reclamele miniaturale // @description:ru Возвращает YouTube к классическому дизайну (до всех закругленных углов и скрытых дизлайков) + перенаправляет YouTube Shorts + блокирует миниатюрные рекламы // @description:rw Isubiza YouTube mu ishusho ryayo rya kera (mbere y'inguni zose z'umuzingi na dislikes zihishe) + yerekeza YouTube Shorts + ihagarika amatangazo ya thumbnail // @description:sg Ramène YouTube à son design classique (avant tous les coins arrondis et les dislikes cachés) + redirige YouTube Shorts + bloque les publicités miniatures // @description:si YouTube එහි සම්භාව්‍ය නිර්මාණයට ආපසු හරවයි (සියලු වටකුරු කොන් සහ සැඟවුණු dislikes වලට පෙර) + YouTube Shorts නැවත හරවා යවයි + සිඟිති රූප දැන්වීම් අවහිර කරයි // @description:sk Vracia YouTube do klasického dizajnu (pred všetkými zaoblenými rohmi a skrytými dislikes) + presmerováva YouTube Shorts + blokuje miniatúrne reklamy // @description:sl Povrne YouTube v klasično obliko (pred vsemi zaobljenimi vogali in skritimi dislikes) + preusmeri YouTube Shorts + blokira miniaturne oglase // @description:sm Toe fa'afo'i YouTube i lona fa'atusa masani (a'o le'i o'o i tulimanu lapotopoto uma ma dislikes natia) + toe fa'asino YouTube Shorts + poloka fa'asalalauga ata laiti // @description:sn Inodzosera YouTube kune dhizaini yayo yekare (pamberi pemakona ese akatenderera uye dislikes dzakavanzwa) + inodzosera YouTube Shorts + inodzivisa kushambadza kwemifananidzo midiki // @description:so Ku soo celinta YouTube qaabkeedii qadiiciga ahaa (ka hor dhammaan geesaha wareegsan iyo dislikes qarsoon) + u jiheeya YouTube Shorts + xannibaysa xayeysiisyada thumbnail // @description:sq E kthen YouTube në dizajnin e tij klasik (para të gjitha qosheve të rrumbullakosura dhe dislikes të fshehura) + ridrejton YouTube Shorts + bllokon reklamat e miniaturave // @description:sr Враћа YouTube на његов класични дизајн (пре свих заобљених углова и скривених дислајкова) + преусмерава YouTube Shorts + блокира рекламе са минијатурама // @description:st E khutlisetsa YouTube moetlong oa eona oa khale (pele ho li-angles tsohle tse chitja le dislikes tse patiloeng) + e lebisa YouTube Shorts + e thibela lipapatso tsa thumbnail // @description:sv Återställer YouTube till sin klassiska design (före alla rundade hörn och dolda dislikes) + omdirigerar YouTube Shorts + blockerar miniatyrannonser // @description:sw Inarejesha YouTube kwenye muundo wake wa awali (kabla ya pembe zote za mviringo na dislikes zilizofichwa) + inaelekeza YouTube Shorts + inazuia matangazo ya thumbnail // @description:ta YouTube-ஐ அதன் கிளாசிக் வடிவமைப்பிற்கு மாற்றியமைக்கிறது (அனைத்து வட்டமான மூலைகளும் மறைக்கப்பட்ட விருப்பமின்மைகளும் முன்பு) + YouTube Shorts-ஐ திருப்பிவிடுகிறது + சிறுபட விளம்பரங்களைத் தடுக்கிறது // @description:te YouTube ను దాని క్లాసిక్ డిజైన్‌కు తిరిగి మారుస్తుంది (అన్ని గుండ్రని మూలలు మరియు దాచిన డిస్‌లైక్‌ల ముందు) + YouTube షార్ట్‌లను రీడైరెక్ట్ చేస్తుంది + థంబ్‌నెయిల్ ప్రకటనలను బ్లాక్ చేస్తుంది // @description:tg YouTube-ро ба тарроҳии классикии худ бармегардонад (пеш аз ҳама гӯшаҳои мудаввар ва dislikes пинҳон) + YouTube Shorts-ро равона мекунад + рекламаҳои эскизиро манъ мекунад // @description:th คืน YouTube กลับสู่ดีไซน์คลาสสิก (ก่อนจะมีมุมโค้งมนและซ่อนดิสไลก์) + เปลี่ยนเส้นทาง YouTube Shorts + บล็อกโฆษณารูปขนาดย่อ // @description:ti ንYouTube ናብቲ ክላሲካዊ ዲዛይኑ ይመልሶ (ቅድሚ ኩለን እተዀረኻ ኩርናዕቲን ተሓቢኡ ዘሎ dislikesን) + ንYouTube Shorts ይመርሕ + ንምካንያዊ ረክላማታት ይዓግት // @description:tk YouTube-y öz klassiki dizaýnyna gaýtaryp berýär (ähli tegelek burçlardan we gizlenen dislikes-lerden öň) + YouTube Shorts-y gönükdirýär + miniatýura mahabatlaryny bloklaýar // @description:tl Ibinabalik ang YouTube sa klasikong disenyo nito (bago ang lahat ng bilugang sulok at nakatagong dislikes) + nire-redirect ang YouTube Shorts + hinaharang ang mga thumbnail ad // @description:tn E busetsa YouTube mo tlhamong ya yone ya bogologolo (pele ga dikhutlo tsotlhe tse di kgolokwe le dislikes tse di fitlhilweng) + e kganela YouTube Shorts + e thibela dipapatso tsa ditshwantsho tse dinnye // @description:to Fakafoki'i YouTube ki hono fa'u 'o e founga motu'a (ki mu'a 'a e ngaahi tuliki potupotu tatau mo e dislikes fufuu) + toe 'oatu YouTube Shorts + poloka'i e ngaahi fakamatala'i ki'i fakatata // @description:tr YouTube'u klasik tasarımına döndürür (tüm yuvarlatılmış köşeler ve gizlenmiş dislikelardan önce) + YouTube Shorts'u yönlendirir + küçük resim reklamlarını engeller // @description:tt YouTube'ны классик дизайнына кайтара (барлык түгәрәкләнгән почмаклар һәм яшерелгән dislikesлар алдыннан) + YouTube Shorts'ны юнәлтә + миниатюра рекламаларын блоклый // @description:ug YouTube نى كلاسسىك لايىھىسىگە قايتۇرىدۇ (بارلىق يۇمىلاق بۇلۇڭلار ۋە يوشۇرۇن dislikes دىن بۇرۇن) + YouTube Shorts نى قايتا نىشانلايدۇ + كىچىك رەسىملىك ئېلانلارنى بلوكلايدۇ // @description:uk Повертає YouTube до класичного дизайну (до всіх закруглених кутів і прихованих дизлайків) + перенаправляє YouTube Shorts + блокує мініатюрні реклами // @description:ur یوٹیوب کو اس کے کلاسک ڈیزائن پر واپس لاتا ہے (تمام گول کونوں اور چھپے ہوئے ڈس لائکس سے پہلے) + یوٹیوب شارٹس کو ری ڈائریکٹ کرتا ہے + تھمب نیل اشتہارات کو بلاک کرتا ہے // @description:uz YouTube'ni klassik dizayniga qaytaradi (barcha yumaloq burchaklar va yashirin dislikeslardan oldin) + YouTube Shorts'ni qayta yo'naltiradi + kichik rasmli reklamalarni bloklaydi // @description:vi Đưa YouTube trở lại thiết kế cổ điển (trước khi có tất cả các góc bo tròn và lượt không thích bị ẩn) + chuyển hướng YouTube Shorts + chặn quảng cáo hình thu nhỏ // @description:wo Jël YouTube ci nosukaayam bu xóot (laata ñu tase ko ak dislikes yu nëbbu) + yóbbu YouTube Shorts + fajj far // @description:xh Ibuyisela i-YouTube kuyilo lwayo lwakudala (phambi kwazo zonke iikona ezingqukuva kunye nee-dislikes ezifihliweyo) + yalathisa kwakhona i-YouTube Shorts + ivale iintengiso ze-thumbnail // @description:yi ברענגט YouTube צוריק צו זיין קלאַסישן דיזיין (פֿאַר אַלע די ראַונדיד עקן און באַהאַלטענע דיסלייקס) + רידערעקץ YouTube שאָרץ + בלאַקירט מיניאַטורע אַדס // @description:yo Mu YouTube pada si apẹrẹ ayeraye rẹ (ṣaaju gbogbo awọn igun yika ati awọn aifẹ ti o farapamọ) + awọn YouTube Shorts pada + dènà awọn ipolowo eekanna atampako // @description:zh 将 YouTube 恢复为经典设计(在圆角和隐藏的不喜欢之前)+ 重定向 YouTube Shorts + 屏蔽缩略图广告 // @description:zh-CN 将 YouTube 恢复为经典设计(在圆角和隐藏的不喜欢之前)+ 重定向 YouTube Shorts + 屏蔽缩略图广告 // @description:zh-HK 將 YouTube 還原為經典設計(在圓角與隱藏的不喜歡之前)+ 重新導向 YouTube Shorts + 封鎖縮圖廣告 // @description:zh-SG 将 YouTube 恢复为经典设计(在圆角和隐藏的不喜欢之前)+ 重定向 YouTube Shorts + 屏蔽缩略图广告 // @description:zh-TW 將 YouTube 還原為經典設計(在圓角與隱藏的不喜歡之前)+ 重新導向 YouTube Shorts + 封鎖縮圖廣告 // @description:zu Ibuyisela i-YouTube kumklamo wayo wakudala (ngaphambi kwawo wonke amakhona ayindilinga nama-dislikes afihliwe) + iqondisa kabusha i-YouTube Shorts + ivimba izikhangisi ze-thumbnail // @license MIT // @icon https://cdn.jsdelivr.net/gh/adamlui/youtube-classic@3bd207d/assets/images/icons/app/icon48.png // @icon64 https://cdn.jsdelivr.net/gh/adamlui/youtube-classic@3bd207d/assets/images/icons/app/icon64.png // @compatible chrome // @compatible firefox // @compatible opera // @compatible safari // @compatible edge // @match *://*.youtube.com/* // @connect cdn.jsdelivr.net // @connect gm.ytclassic.com // @connect scriptcat.org // @require https://cdn.jsdelivr.net/npm/json5@2.2.3/dist/index.min.js#sha256-S7ltnVPzgKyAGBlBG4wQhorJqYTehj5WQCrADCKJufE= // @require https://cdn.jsdelivr.net/gh/Anarios/return-youtube-dislike@v4.0.4/Extensions/UserScript/Return%20Youtube%20Dislike.user.js#sha256-BPRgJOQfxTUmr09fqGi1dlZ14jtZfdKHhKltqmf5B+Y= // @require https://cdn.jsdelivr.net/gh/adamlui/userscripts@ff2baba/assets/js/lib/css.js/dist/css.min.js#sha256-zf9s8C0cZ/i+gnaTIUxa0+RpDYpsJVlyuV5L2q4KUdA= // @require https://cdn.jsdelivr.net/gh/adamlui/userscripts@ff2baba/assets/js/lib/dom.js/dist/dom.min.js#sha256-nTc2by3ZAz6AR7B8fOqjloJNETvjAepe15t2qlghMDo= // @require https://cdn.jsdelivr.net/gh/adamlui/youtube-classic@6212e59/firefox/extension/components/modals.js#sha256-4iwF4PoLSZC3hB9WnnwXI5kJ+FkzzKPTIVEefZXG/64= // @require https://cdn.jsdelivr.net/gh/adamlui/youtube-classic@0101b2d/firefox/extension/lib/feedback.js#sha256-vOjy50gX+2neUSL3Cw7IzEoDBoVFu0JKFrBD+a5MpJg= // @require https://cdn.jsdelivr.net/gh/adamlui/youtube-classic@6212e59/firefox/extension/lib/i18n.js#sha256-x61c8yPOFawdFi+loDFZ8FGxzi5BqR3VZvboUyOtfgM= // @require https://cdn.jsdelivr.net/gh/adamlui/youtube-classic@6212e59/firefox/extension/lib/settings.js#sha256-AybZWDxw7XbZt1gkJmBJD/i/QeGs+YCGMP75/HOv12k= // @require https://cdn.jsdelivr.net/gh/adamlui/youtube-classic@1e645cc/firefox/extension/lib/styles.js#sha256-t5xeI85sVNdpbf2lOmpkbnuL+YNoEljMxa5LGalxujo= // @require https://cdn.jsdelivr.net/gh/adamlui/youtube-classic@9a1a22e/firefox/extension/lib/sync.js#sha256-GOCSq9bR84wsygpvDMF/7pMXtGVmhWVYr7P9gzqJ+5I= // @require https://cdn.jsdelivr.net/gh/adamlui/youtube-classic@6212e59/firefox/extension/lib/ui.js#sha256-jvubqzwniEJQQA8uyVbq8H3FVYBK3mPxjJxsnw5TwIs= // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @grant GM_getValue // @grant GM_setValue // @grant GM_xmlhttpRequest // @grant GM.xmlHttpRequest // @run-at document-start // @homepageURL https://www.ytclassic.com // @supportURL https://support.ytclassic.com // @contributionURL https://ko-fi.com/adamlui // ==/UserScript== (async () => { 'use strict' window.xhr = typeof GM != 'undefined' && GM.xmlHttpRequest || GM_xmlhttpRequest window.env = { browser: { language: navigator.languages[0] || navigator.language || navigator.browserLanguage || navigator.systemLanguage || navigator.userLanguage || '', isFF: navigator.userAgent.includes('Firefox'), isMobile: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) }, scriptManager: { name: (() => { try { return GM_info.scriptHandler } catch (err) { return 'unknown' }})(), version: (() => { try { return GM_info.version } catch (err) { return 'unknown' }})() } } env.scriptManager.supportsTooltips = env.scriptManager.name == 'Tampermonkey' && parseInt(env.scriptManager.version.split('.')[0]) >= 5 window.app = { name: 'YouTube Classic', symbol: '📺', slug: 'youtube-classic', configKeyPrefix: 'ytClassic', version: GM_info.script.version, authors: [ { name: 'Adam Lui', email: 'adam@kudoai.com', url: 'https://github.com/adamlui' }, { name: 'Magma_Craft', url: 'https://userstyles.org/user-profile/3460957' } ], commitHashes: { data: 'fa559e2', // for selectors.json5 images: '1b6e5d3', // for header logo locales: 'fbe770f' // for messages.json } } app.urls = { github: 'https://github.com/adamlui/youtube-classic', jsd: 'https://cdn.jsdelivr.net/gh/adamlui/youtube-classic', review: { scriptcat: 'https://scriptcat.org/script-show-page/6345/comment' }, support: 'https://support.ytclassic.com', update: { gm: 'https://scriptcat.org/scripts/code/6345/youtube-classic.meta.js' }, userscripts: 'https://github.com/adamlui/userscripts' } app.urls.data = `${app.urls.jsd}@${app.commitHashes.data}/assets/data` app.urls.images = `${app.urls.jsd}@${app.commitHashes.images}/assets/images` app.urls.locales = `${app.urls.jsd}@${app.commitHashes.locales}/firefox/extension/_locales` app.msgs = await new Promise(resolve => { const localeDir = `${ env.browser.language ? env.browser.language.replace('-', '_') : 'en' }` let msgURL = `${app.urls.locales}/${localeDir}/messages.json`, msgFetchesTried = 0 function fetchMsgs() { xhr({ method: 'GET', url: msgURL, onload: handleMsgs })} function handleMsgs(resp) { try { // to return localized messages.json const msgs = JSON.parse(resp.responseText), flatMsgs = {} for (const key in msgs) // remove need to ref nested keys if (typeof msgs[key] == 'object' && 'message' in msgs[key]) flatMsgs[key] = msgs[key].message resolve(flatMsgs) } catch (err) { msgFetchesTried++ ; if (msgFetchesTried == 3) return resolve({}) // try og/region-stripped/EN only msgURL = env.browser.language.includes('-') && msgFetchesTried == 1 ? // if regional lang on 1st try... msgURL.replace(/(_locales\/[^_]+)_[^_]+(\/)/, '$1$2') // ...strip region before retrying : `${app.urls.locales}/en/messages.json` // else use default English messages fetchMsgs() } } fetchMsgs() }) app.selectors = await new Promise(resolve => xhr({ // used in block modes method: 'GET', onload: ({ responseText }) => resolve(JSON5.parse(responseText)), url: `${app.urls.data}/selectors.json5` })) app.ui = { expFlags: { // used to apply overrides enable_channel_page_header_profile_section: false, enable_header_channel_handler_ui: false, kevlar_unavailable_video_error_ui_client: false, kevlar_refresh_on_theme_change: false, kevlar_modern_sd_v2: false, kevlar_watch_cinematics: false, kevlar_watch_comments_panel_button: false, kevlar_watch_grid: false, kevlar_watch_grid_hide_chips: false, kevlar_watch_metadata_refresh: false, kevlar_watch_metadata_refresh_no_old_secondary_data: false, kevlar_watch_modern_metapanel: false, kevlar_watch_modern_panels: false, kevlar_watch_panel_height_matches_player: false, smartimation_background: false, web_amsterdam_playlists: false, web_animated_actions: false, web_animated_like: false, web_button_rework: false, web_button_rework_with_live: false, web_darker_dark_theme: false, web_enable_youtab: false, web_guide_ui_refresh: false, web_modern_ads: false, web_modern_buttons: false, web_modern_chips: false, web_modern_collections_v2: false, web_modern_dialogs: false, web_modern_playlists: false, web_modern_subscribe: false, web_modern_tabs: false, web_rounded_containers: false, web_rounded_thumbnails: false, web_searchbar_style: 'default', web_segmented_like_dislike_button: false, web_sheets_ui_refresh: false, web_snackbar_ui_refresh: false, web_watch_rounded_player_large: false }} app.config ??= {} ; settings.load(Object.keys(settings.controls)) window.gmToolbarMenu = { state: { symbols: ['❌', '✔️'], separator: env.scriptManager.name == 'Tampermonkey' ? ' — ' : ': ', words: [app.msgs.state_off.toUpperCase(), app.msgs.state_on.toUpperCase()] }, refresh() { if (typeof GM_unregisterMenuCommand == 'undefined') return this.entryIDs.forEach(id => GM_unregisterMenuCommand(id)) this.register() }, register() { // Add mode/settings categories this.entryIDs = Object.entries(settings.categories) .map(([key, category]) => GM_registerMenuCommand( `${ category.symbol ? category.symbol + ' ' : '' }${category.label}`, () => modals.settings(key), env.scriptManager.supportsTooltips ? { title: app.msgs[`helptip_${key}`] } : undefined )) // Add About entry this.entryIDs.push(GM_registerMenuCommand( `💡 ${app.msgs.menuLabel_about} ${app.msgs.appName}`, () => modals.open('about'), env.scriptManager.supportsTooltips ? { title: ' ' } : undefined )) } } Object.assign(modals, { // userscript modals/utils settings(ctgKey) { // for categories // Stylize if (!modals.settings.style?.isConnected) document.head.append(modals.settings.style ||= dom.create.style()) modals.scheme = ui.getScheme() modals.settings.style.textContent = ` :root { --entry-highlighted-bg: rgba(100,149,237,0.88) ; ${ modals.scheme == 'dark' ? ` --track-filled-color: white ; --track-empty-color: #b2b2b2 ; --thumb-color: white ; --thumb-border: black` : ` /* light scheme */ --track-filled-color: #000 ; --track-empty-color: #e0e0e0 ; --thumb-color: #000 ; --thumb-border: #fff` } } .${app.slug}-settings-modal h2 { text-align: center } .${app.slug}-settings-modal ul { /* entries list */ cursor: pointer ; font-size: 18px ; margin: 16px 0 -10px ; list-style: none } .${app.slug}-settings-modal li { /* entry row */ color: ${ modals.scheme == 'dark' ? 'rgb(255,255,255,0.65)' : 'rgba(0,0,0,0.45)' }; height: 37px ; padding: 6px 10px 4px ; font-size: 15.5px ; align-content: center ; border-bottom: 1px dotted ${ modals.scheme == 'dark' ? 'white' : 'black' }; border-radius: 3px ; /* slightly round highlight strip */ transition: 0.1s ease ; /* for hover-zoom */ -webkit-transition: 0.1s ease ; -moz-transition: 0.1s ease ; o-transition: 0.1s ease ; -ms-transition: 0.1s ease } .${app.slug}-settings-modal li.active { color: ${ modals.scheme == 'dark' ? 'rgb(255,255,255)' : 'rgba(0,0,0)' }} .${app.slug}-settings-modal li:not(:has(input[type=range])):hover { padding: 4px 10px ; transform: scale(1.15) ; background: var(--entry-highlighted-bg) ; color: white } .${app.slug}-settings-modal li:last-of-type { border-bottom: none } // remove last bottom-border .${app.slug}-settings-modal li > label { cursor: pointer } .${app.slug}-settings-modal li > input[type=checkbox] { display: none } .${app.slug}-settings-modal .toggle-switch { position: relative ; left: -1px ; bottom: -4px ; float: right ; background-color: #ccc ; width: 26px ; height: 13px ; border-radius: 28px ; transition: 0.4s ; -webkit-transition: 0.4s ; -moz-transition: 0.4s ; -o-transition: 0.4s ; -ms-transition: 0.4s } .${app.slug}-settings-modal .toggle-knob { position: absolute ; left: 1px ; bottom: 1px ; content: "" ; background-color: white ; width: 11px ; height: 11px ; border-radius: 28px ; transition: 0.2s ; -webkit-transition: 0.2s ; -moz-transition: 0.2s ; -o-transition: 0.2s ; -ms-transition: 0.2s } .${app.slug}-settings-modal li:has(input[type=range]) { display: flex ; flex-wrap: wrap; padding: 32px 8px } .${app.slug}-settings-modal li > input[type=range] { --track-fill-percent: 100% ; width: 100% ; cursor: pointer ; margin: 7px 0 ; -webkit-appearance: none ; appearance: none ; background: none } .${app.slug}-settings-modal li > input[type=range]::-webkit-slider-runnable-track { height: 5px ; border-radius: 10px ; background: linear-gradient(to right, var(--track-filled-color) 0%, var(--track-filled-color) var(--track-fill-percent), var(--track-empty-color) var(--track-fill-percent), var(--track-empty-color) 100% ) } .${app.slug}-settings-modal li > input[type=range]::-moz-range-track { height: 5px ; border-radius: 10px ; background: linear-gradient(to right, var(--track-filled-color) 0%, var(--track-filled-color) var(--track-fill-percent), var(--track-empty-color) var(--track-fill-percent), var(--track-empty-color) 100% ) } .${app.slug}-settings-modal li > input[type=range]::-webkit-slider-thumb { -webkit-appearance: none ; width: 12px ; height: 26.5px ; background: var(--thumb-color) ; margin-top: -10.5px ; border: 4px solid var(--thumb-border) ; border-radius: 16px ; cursor: ew-resize ; transition: transform 0.05s ease } .${app.slug}-settings-modal li > input[type=range]::-moz-range-thumb { width: 4px ; height: 19px ; background: var(--thumb-color) ; margin-top: -11px ; border: 4px solid var(--thumb-border) ; border-radius: 16px ; cursor: ew-resize ; transition: transform 0.05s ease } .${app.slug}-settings-modal li > input[type=range]::-webkit-slider-thumb:hover { transform: scaleX(1.325) } .${app.slug}-settings-modal li > input[type=range]::-moz-range-thumb:hover { transform: scaleX(1.325) } .${app.slug}-settings-modal button { display: none } .${app.slug}-settings-modal .edit-link { text-transform: uppercase ; font-size: 0.65em ; margin-left: 0.75em ; opacity: 0.7 ; cursor: pointer } .${app.slug}-settings-modal .edit-link:hover { opacity: 1 }` // Create modal const category = settings.categories[ctgKey] const settingsModal = modals.alert( `${category.symbol} ${category.label}`, '', undefined, undefined, 365) settingsModal.classList.add(`${app.slug}-settings-modal`) settingsModal.style.cssText += 'padding-bottom: 10px !important' // Create entries const settingsUL = settingsModal.querySelector('ul') Object.entries(settings.controls).forEach(([key, entryData]) => { if (entryData.category != ctgKey) return // Create/append entry/label elems const entry = { row: dom.create.elem('li', { id: key, title: entryData.helptip || '' }), label: dom.create.elem('label') } entry.label.textContent = `${entryData.label}` entry.row.append(entry.label) ; settingsUL.append(entry.row) // Create/append toggles/listeners if (entryData.type == 'toggle') { // Create/append toggle elems entry.toggle = { input: dom.create.elem('input', { class: 'toggle-input', type: 'checkbox', disabled: true }), switch: dom.create.elem('span', { class: 'toggle-switch' }), knob: dom.create.elem('span', { class: 'toggle-knob' }) } entry.toggle.input.checked = settings.typeIsEnabled(key) entry.toggle.switch.append(entry.toggle.knob) entry.row.append(entry.toggle.input, entry.toggle.switch) // Update visual state w/ animation setTimeout(() => modals.toggleUtils.updateStyles(entry.toggle.input), 155) // Add click listener entry.row.onclick = () => { modals.toggleUtils.switchToggle(entry.toggle.input) settings.save(key, !app.config[key]) sync.configToUI({ key }) feedback.notify(`${entryData.label}: ${ gmToolbarMenu.state.words[+settings.typeIsEnabled(key)]}`) // Enable/disable dependent entries for (const [ctrlKey, ctrlData] of Object.entries( { ...settings.categories, ...settings.controls })) if (Object.values(ctrlData.dependencies || {}).flat().includes(key)) { const depDiv = document.querySelector(`li#${ctrlKey}`) ; if (!depDiv) continue depDiv.style.display = !settings.typeIsEnabled(key) ? 'none' : '' } } } else if (entryData.type == 'slider') { const minVal = entryData.min ?? 0, maxVal = entryData.max ?? 100 // Create/append slider elems entry.row.classList.add('active') entry.row.append(entry.slider = dom.create.elem('input', { type: 'range', min: minVal, max: maxVal, value: app.config[key] })) if (entryData.step || env.browser.isFF) // use val from ctrl data or default to 2% in FF for being laggy entry.slider.step = entryData.step || (0.02 * entry.slider.max - entry.slider.min) entry.label.textContent += `: ${entry.slider.value}${ entryData.labelSuffix || '' }` entry.label.append(entry.editLink = dom.create.elem('span', { class: 'edit-link', role: 'button', tabindex: '0', 'aria-label': entryData.helptip })) entry.editLink.textContent = app.msgs.promptLabel_edit entry.slider.style.setProperty( '--track-fill-percent', `${ entry.slider.value / entry.slider.max *100 }%`) // Add listeners entry.editLink.onclick = () => { const promptMsg = `${app.msgs.prompt_enterNewVal} ${entryData.label} (${ app.msgs.error_between} ${minVal}–${maxVal}):` const userVal = prompt(promptMsg, entry.slider.value) if (userVal == null) return // user cancelled so do nothing if (!/\d/.test(userVal)) return alert(`${ app.msgs.error_enterValidNum} ${app.msgs.error_between} ${ minVal} ${app.msgs.error_and} ${maxVal}!`) let validVal = parseInt(userVal.replace(/\D/g, '')) ; if (isNaN(validVal)) return validVal = Math.max(minVal, Math.min(maxVal, validVal)) entry.slider.value = validVal ; settings.save(entryData.key, validVal) sync.configToUI({ key: entryData.key }) entry.label.textContent = `${entryData.label}: ${validVal}${ entryData.labelSuffix || '' }` entry.label.append(entry.editLink) entry.slider.style.setProperty('--track-fill-percent', `${ validVal / entry.slider.max *100 }%`) } entry.slider.oninput = ({ target: { value }}) => { // update UI settings.save(key, parseInt(value)) ; sync.configToUI({ key }) entry.label.textContent = `${entryData.label}: ${value}${ entryData.labelSuffix || '' }` entry.label.append(entry.editLink) entry.slider.style.setProperty('--track-fill-percent', `${ value / entry.slider.max *100 }%`) } entry.row.onwheel = ({ deltaY }) => { // move slider by 2 steps entry.slider.value = parseInt(entry.slider.value) - Math.sign(deltaY) *2 entry.slider.dispatchEvent(new Event('input')) } } if (entryData.dependencies) { const toDisable = Object.values(entryData.dependencies).flat() .some(dep => !settings.typeIsEnabled(dep)) entry.row.style.display = toDisable ? 'none' : '' } }) return settingsModal }, toggleUtils: { switchToggle(toggleInput) { toggleInput.checked = !toggleInput.checked ; modals.toggleUtils.updateStyles(toggleInput) }, updateStyles(toggleInput) { // toggle show + staggered switch animations in const switchSpan = toggleInput.nextElementSibling, knobSpan = switchSpan.querySelector('span'), toggleRow = toggleInput.parentNode requestAnimationFrame(() => { switchSpan.style.backgroundColor = toggleInput.checked ? '#ad68ff' : '#ccc' switchSpan.style.boxShadow = toggleInput.checked ? '2px 1px 9px #d8a9ff' : 'none' knobSpan.style.transform = toggleInput.checked ? 'translateX(14px) translateY(0)' : 'translateX(0)' toggleRow.classList.toggle('active', toggleInput.checked) // dim/brighten entry }) // to trigger 1st transition fx } }, update: { width: 377, available() { // Show modal const updateAvailModal = modals.alert(`🚀 ${app.msgs.alert_updateAvail}!`, // title `${app.msgs.alert_newerVer} ${app.msgs.appName} ` // msg + `(v${app.latestVer}) ${app.msgs.alert_isAvail}! ` + '${app.msgs.link_viewChanges}`, function update() { // button modals.safeWinOpen(`${app.urls.update.gm}?t=${Date.now()}`) }, '', modals.update.width ) // Localize button labels if needed if (!env.browser.language.startsWith('en')) { const updateBtns = updateAvailModal.querySelectorAll('button') updateBtns[1].textContent = app.msgs.btnLabel_update updateBtns[0].textContent = app.msgs.btnLabel_dismiss } return updateAvailModal }, unavailable() { return modals.alert(`${app.msgs.alert_upToDate}!`, // title `${app.msgs.appName} (v${app.version}) ${app.msgs.alert_isUpToDate}!`, // msg '', '', modals.update.width ) } } }) window.updateCheck = () => xhr({ method: 'GET', url: `${app.urls.update.gm}?t=${Date.now()}`, headers: { 'Cache-Control': 'no-cache' }, onload: ({ responseText }) => { // Compare versions, alert if update found app.latestVer = /@version +(.*)/.exec(responseText)?.[1] if (app.latestVer) for (let i = 0 ; i < 4 ; i++) { // loop thru subver's const currentSubVer = parseInt(app.version.split('.')[i], 10) || 0, latestSubVer = parseInt(app.latestVer.split('.')[i], 10) || 0 if (currentSubVer > latestSubVer) break // out of comparison since not outdated else if (currentSubVer < latestSubVer) // if outdated return modals.open('update', 'available') } // Alert to no update found, nav back to About modals.open('update', 'unavailable') ; modals.open('about') } }) class YTP { static observer = new MutationObserver(this.onNewScript) static _config = {} static isObject(item) { return (item && typeof item == 'object' && !Array.isArray(item)) } static mergeDeep(target, ...sources) { if (!sources.length) return target const source = sources.shift() if (this.isObject(target) && this.isObject(source)) for (const key in source) if (this.isObject(source[key])) { if (!target[key]) Object.assign(target, { [key]: {} }) this.mergeDeep(target[key], source[key]) } else Object.assign(target, { [key]: source[key] }) return this.mergeDeep(target, ...sources) } static onNewScript(mutations) { if (mutations.some(mut => mut.addedNodes.length)) YTP.bruteforce() } static start() { this.observer.observe(document, { childList: true, subtree: true }) } static stop() { this.observer.disconnect() } static bruteforce() { if (!unsafeWindow.yt?.config_) return this.mergeDeep(unsafeWindow.yt.config_, this._config) } static setExpMulti(exps) { if (!('EXPERIMENT_FLAGS' in this._config)) this._config.EXPERIMENT_FLAGS = {} this.mergeDeep(this._config.EXPERIMENT_FLAGS, exps) } } // Run MAIN routine gmToolbarMenu.register() if (app.config.disableShorts) sync.redir.shorts() styles.update({ keys: Object.keys(styles).filter(key => styles[key].autoAppend) }) sync.headerLogo() dom.get.loadedElem('ytd-masthead').then(masthead => { new MutationObserver(sync.headerLogo).observe(masthead, { attributes: true, subtree: true, attributeFilter: ['dark'] }) }) // Tweak experimental flags YTP.start() Object.keys(app.ui.expFlags).filter(key => /_animated_/.test(key)) .forEach(animationKey => app.ui.expFlags[animationKey] = !app.config.reduceAnimations) YTP.setExpMulti(app.ui.expFlags) addEventListener('yt-page-data-updated', function handleDataUpdated() { YTP.stop() ; removeEventListener('yt-page-data-updated', handleDataUpdated) }) if (app.config.idlePrevention) sync.idle.prevent() })()