From 900a43999c4e160393d429a638a367f0f6ef71fc Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Thu, 4 Dec 2025 14:08:29 -0800 Subject: [PATCH 001/105] New default custom invidious url W combo, the cors proxy has the best ratelimits and the invidious instance has a non-disabled popular page --- app/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/settings.js b/app/settings.js index f1ad8ad1..c41385ea 100644 --- a/app/settings.js +++ b/app/settings.js @@ -636,7 +636,7 @@ function settingsPage() { "type": "text", "title": "APP_CUSTOM_INVIDIOUS_URL", "subtitle": "This loads your home page and comments. which should update and not be static
If you have your own invidious instance put it here
You should change CORS policy if you own your instance, otherwise use a CORS redirector", - "value": "https://api.allorigins.win/raw?url=https://yt.omada.cafe/", + "value": "https://api.codetabs.com/v1/proxy?quest=https://inv.perditum.com/", "placeholder": "", "disabled": false, "lsitem": "APP_CUSTOM_INVIDIOUS_URL" From 61eb8d40a1b69fc620dd5687619fc8ea7e46310b Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Fri, 5 Dec 2025 12:16:30 -0800 Subject: [PATCH 002/105] Advice for making invidious instance @MalsOfficial https://www.reddit.com/r/oldyoutubelayout/comments/1p7rpox/how_do_you_add_your_own_instance_of_indvious_to/ --- app/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/settings.js b/app/settings.js index c41385ea..53c0eaef 100644 --- a/app/settings.js +++ b/app/settings.js @@ -635,7 +635,7 @@ function settingsPage() { { "type": "text", "title": "APP_CUSTOM_INVIDIOUS_URL", - "subtitle": "This loads your home page and comments. which should update and not be static
If you have your own invidious instance put it here
You should change CORS policy if you own your instance, otherwise use a CORS redirector", + "subtitle": "This loads your home page and comments. which should update and not be static
If you have your own invidious instance put it here
You should change CORS policy if you own your instance, otherwise use a CORS redirector
If you want to setup an invidious instance, there is always google, however your average PC probably will lag out (the preset instance is probably fine for you)", "value": "https://api.codetabs.com/v1/proxy?quest=https://inv.perditum.com/", "placeholder": "", "disabled": false, From 4ea18919eaaf31c67a7b6266e5c67531984aee16 Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Fri, 5 Dec 2025 12:22:26 -0800 Subject: [PATCH 003/105] Add new invidious url to here too I accidentally did a open file search instead of a current project search in kate --- app/2015ytm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/2015ytm.js b/app/2015ytm.js index f1d0ebb8..6d706b35 100644 --- a/app/2015ytm.js +++ b/app/2015ytm.js @@ -148,7 +148,7 @@ APP_HELVETICA_NEUE_FONT_expflag = localStorage.getItem("APP_HELVETICA_NEUE_FONT" APP_NEW_ERROR_SCREEN_expflag = localStorage.getItem("APP_NEW_ERROR_SCREEN"); APP_CUSTOM_INVIDIOUS_URL_expflag = localStorage.getItem("APP_CUSTOM_INVIDIOUS_URL"); if (APP_CUSTOM_INVIDIOUS_URL_expflag == undefined) { - localStorage.setItem("APP_CUSTOM_INVIDIOUS_URL", "https://api.allorigins.win/raw?url=https://yt.omada.cafe/"); + localStorage.setItem("APP_CUSTOM_INVIDIOUS_URL", "https://api.codetabs.com/v1/proxy?quest=https://inv.perditum.com/"); APP_CUSTOM_INVIDIOUS_URL_expflag = localStorage.getItem("APP_CUSTOM_INVIDIOUS_URL"); } APP_DONT_AUTH_TO_INVIDIOUS_expflag = localStorage.getItem("APP_DONT_AUTH_TO_INVIDIOUS"); From adc7cae73a53526a373c13b5003073858b241f63 Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Mon, 8 Dec 2025 11:25:16 -0800 Subject: [PATCH 004/105] WATCH_UI_NO_LINES expflag Reddit post expflag 1 --- app/2015YTm.css | 3 +++ app/2015ytm.js | 7 +++++++ app/settings.js | 9 +++++++++ 3 files changed, 19 insertions(+) diff --git a/app/2015YTm.css b/app/2015YTm.css index 4421e7a8..a7610c2f 100644 --- a/app/2015YTm.css +++ b/app/2015YTm.css @@ -2591,6 +2591,9 @@ ytm15-menu-button { .compact-channel.shelf-item .media-item-menu { display: none; } +.no-lines .ytm15-video-owner,.no-lines .watch-next-results-content { + border:unset !important; +} /* About 2015YouTube */ .about-page-heading, .about-page-subheading { diff --git a/app/2015ytm.js b/app/2015ytm.js index 6d706b35..ffa993d3 100644 --- a/app/2015ytm.js +++ b/app/2015ytm.js @@ -168,6 +168,7 @@ if (APP_STOP_TEXT_SELECTION_expflag == undefined) { localStorage.setItem("APP_STOP_TEXT_SELECTION", "true"); APP_STOP_TEXT_SELECTION_expflag = localStorage.getItem("APP_STOP_TEXT_SELECTION"); } +WATCH_UI_NO_LINES_expflag = localStorage.getItem("WATCH_UI_NO_LINES"); newErrorHtml = `` + + const mtrlBtnContDownload = document.createElement("div"); + mtrlBtnContDownload.classList.add("material-button-container", "compact", "download-button"); + mtrlBtnContDownload.dataset.style = "DEFAULT"; + mtrlBtnContDownload.dataset.iconOnly = "true"; + mtrlBtnContDownload.setAttribute("is-busy", "false"); + mtrlBtnContDownload.ariaBusy = "false"; + mtrlBtnContDownload.setAttribute("disabled", "false"); + mtrlBtnContDownload.innerHTML = `` + + const mtrlBtnContSave = document.createElement("div"); + mtrlBtnContSave.classList.add("material-button-container", "compact", "save-button"); + mtrlBtnContSave.dataset.style = "DEFAULT"; + mtrlBtnContSave.dataset.iconOnly = "true"; + mtrlBtnContSave.setAttribute("is-busy", "false"); + mtrlBtnContSave.ariaBusy = "false"; + mtrlBtnContSave.setAttribute("disabled", "false"); + mtrlBtnContSave.innerHTML = `` if (WATCH_USE_MTRL_ICONS_expflag == "true") { @@ -448,6 +470,17 @@ function renderWatchPage(parent) { transform: scale(1.3); transform-origin: center; ">
${Share_text_string}
+` + + mtrlBtnContDownload.innerHTML = `` + + mtrlBtnContSave.innerHTML = `` metadataActions.classList.add("use-mtrl-icons"); @@ -456,6 +489,8 @@ function renderWatchPage(parent) { mtrlBtnCont.querySelector("button").appendChild(mtrlBtnCont.querySelector(".button-text")); mtrlBtnContDislike.querySelector("button").appendChild(mtrlBtnContDislike.querySelector(".button-text")); mtrlBtnContShare.querySelector("button").appendChild(mtrlBtnContShare.querySelector(".button-text")); + mtrlBtnContDownload.querySelector("button").appendChild(mtrlBtnContDownload.querySelector(".button-text")); + mtrlBtnContSave.querySelector("button").appendChild(mtrlBtnContSave.querySelector(".button-text")); }; const actionsSpacer = document.createElement("div"); @@ -465,6 +500,8 @@ function renderWatchPage(parent) { metadataActions.appendChild(mtrlBtnContDislike); metadataActions.appendChild(mtrlBtnContShare); metadataActions.appendChild(actionsSpacer); + if (WATCH_DOWNLOAD_BUTTON_expflag == "true") {metadataActions.appendChild(mtrlBtnContDownload);}; + if (WATCH_SAVE_BUTTON_expflag == "true" && WATCH_ENABLE_NEW_UI_expflag == "false") {metadataActions.appendChild(mtrlBtnContSave);}; const W2ndHalf = document.createElement("div"); W2ndHalf.classList.add("wnr-2nd-half", "watch-next-results-content"); From 01fae1055fe0c2e62d5e11a5aee7dc943e5b7d1e Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Mon, 15 Dec 2025 17:58:35 -0800 Subject: [PATCH 013/105] Update polyfill, i forgot to add this --- app/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/index.html b/app/index.html index cb80a8d0..534ca2b2 100644 --- a/app/index.html +++ b/app/index.html @@ -20,7 +20,7 @@ - + From 3be0b7fdb5ac4f259ade22072b6118bb707dcba0 Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Mon, 15 Dec 2025 18:25:54 -0800 Subject: [PATCH 014/105] Update download and save icons --- app/ic_download.png | Bin 2429 -> 2415 bytes app/ic_save.png | Bin 130 -> 495 bytes app/watch.js | 8 +++++--- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/ic_download.png b/app/ic_download.png index f38b16f2beae8bf4efae592959d463c60994f937..1985e62054160a61a0b60645c47f4f5ddc63dd2e 100644 GIT binary patch literal 2415 zcmZ8jcU05K7XAeiBs78WRtQKl1VzOlH7JHaC{daO44^~;1`<#RQp8X~3ss6DMG!suK`Df-%rkjg{ybN3h z004QsBhFpSemjts63=rbS1iN?ig0(Z0XRb%i(&&DgmuOOKy#k#1{or@p>#*@2mny{ z_YOb|uSh~zVB{6@WeVU%riDfty4ZPWn;IG!nrDxT(BhajiWfc*k2e6M z#Rdd`gCGD%tWJud{|gF94d0EO{SUeEU9nH!x|cn%5=|XzIkq5) z8T$6>MR|Kf*TN=mWMKYN%yG@Ue~4gmv!rRZuAu=Q_kOaOjB_CGQ6t1zL>rg^rvjMd z^k(GyUGGD@@%X{eEvBnMp^!)-C1iv^@K~rDfnZ$I*|`~9H9;;82xw|CQqLvN1f2K3 zqy6}6q-AGkW8-_*POtqcsX$?2VKu%|?agEv-67y!;+CWC* zx~amvUc5)5P$*0o{S-0y3 z^j47Mgw+9GBes@t1sY?>z7sf}ywZuIU9j6w>#&965_(&_T-nZoOZ6VX!B?+-!_GVOP;{S0-F&6y#q_0L6Q+23*sa1b z%GV*4OXz}GtBV&0STVyY_J^b0)35lO6dNm^&8A(_QE2lgysNM$ou%s}+PCLPkuFX> zE%r=)3l<^nP79D%&Sj)Srbc9uq0Ti1DGd$>&$LJ$IU|Us=~9y^37rB7kop-WR?%6mOeyxw=>%ze zH>okIt_l;Q=d+VK>^ z!;BIR<*(~sUoRDovq2M=dQouy!c@0OX?h3Lw;Eko+R)HYCOL69<7II#Gpp`$f`;6$ zfh~7m+N*=4ZlM&?+?5+1THC##q6u3Xzp;@xk(gY?Vp^60Np^A7$a zZ07^huFJgeRf79mNbVsOGYLczL*)ozudfy_+QiJP$i&?IVWkJH&u}mtJ0#w{H#IyW z7arKK?|#%P@#TBYX0vM_4ah_s2o<7oXg1`1iBd**qZ>=rxi?V!b@a&icw0&D1S85F z-CfAx;-pzQKz9l1fc^D+c`g*aik=JG1FIV-c=Ppfpj6BQWQDPrL|ljf(XM#bH7ZhI znh~`;UYNfQm#cqxC$hYoIsNErsU=igWTpf~<4SY*LQ4Pk?%LW~%XN_nyPScqHXgj& ztYoeK>@!OtEUeO*XF|_QL8&D#G!0ju-nD;0AK63nde1HQGPG;=us7CG0-W9 zHy6Xjs-E~cUfYohqAr>$Mlc+8B=!Vc#l+)Rwuf=H0R+gRBu0DP^kY`VohDHVHKq}) zit0Be8157#gE0AjbrRH92#yoc`T8psaMZ07{4|~4Y{=M*P!5~ z*BmG0h$`=O^A_E{w$yCe#bjw~`01dXh#WjsP-2Y(Ly&8)O_suF{qZ6U5x(M5j^f`I|k zd(_A&Ntjj$U)>8DWs&StAKctJaG_^I>p5&KW9|go$I-%yy@cRDU*vX>A3{j0X}u3G zw{5H9Vp# z!x!KeKifASrr+>lAej~0IKYnR&OB~P>?J{>`Y@0F+l?@=*5}GXzN|AY9`>ZHGUMWj z8@nyQZ=4f3Zn|qNdd5w-1OYe%F|bGES`z7Cj+v{rs%&%B{e+o=v6hyW_%AMwe-COz pMa9Z)1vUOpPu}U!eKvPaFeP6fDk52?EfRKq4R|{j9LL5l`A-wQDHH$z literal 2429 zcmZXVc{Ei0AII-JWQ(zleJEK%_MMD~Y%z?87LV-0h_THWWKEf|MjBbOONa_(n<6!K zB1`nxVl1I7Jqo}3dz>@JIepH#pYQ9wKJV|jf82Y%_nsBfn2kk{1pojxQxijLaD5A2 zZA^4vPf|Or4la-YYvc1kRWFs}%>_^%92`VOMpjf*fSp7lfjuoP4eUutNdy8R zI5-&OkdP3tgB2PY3ihzDFf0}ejzA9rSU4OGiwyah-9>Hh=hz!6x7`9pKaG*6RY zn8visA<+Dv8Cu{la~J@bR)@C_XMi^K zb}+<(?}-p-jl2Xv{-UEl#=ywLe4Gu+&c(~eFD5Q6r=)gP2XRhM|2)dZ*8b|Xza5?3 z(U{;6Tqr&)JmPj_R7`B#o%p-=5(vb^q~w&;`{@rdNm-Awb8_?Y3mz916_=Ejl~+8e zd|Fjq^Q^Y+d1F&cYa97($2&^j(8uA)sp*;7uM3ORrPXh1>l;6|ws(I1yZd{Ok;4xB zz!=s|4fSoX$$ z(Psqy{5`Z6IiWZ8t$9IfCpVzA6)(~f@vW`$KBpJ{oS&Mw_-HI%PE+$CJ5WwnP^V^%qcS?#kVnj;n$veh-N@!h35O%Np*ku ze7#o*S!E@3Pzb$jZjn(GcVbbeb0rz;!%Z3^CJKdcTUMRqJahlf=NW^7Q(V@pY*e%& zTwY9Re!V7_p>V)quFW^lMjpTM1ZR-Tv<_cf*F>4vL?)H3QYGkP#x60#-pPkK$m1r_X4;FHEk7`0 zT{}UfP!w)lUR6rQsSVAB~br^ZJ z@`n`shs^0n6fC9e)moejr*P76m?bg8%EXLv0y!c9OPA=VH>8h~cpS)CB41_TFqYQy zFBjo6_4cB?ybC%Gn_o~%`1qt)7X6I*_F@QM!HBE;fui%uS3!h3nA zZSyQ1xWT?aGVw{eQOcVC7*-4SrNN=aoJktbkx+#1@<8|%__lFl#LvZ<{;dE{ter^w zq*z#PiIl+JTGy{lkU^oI}EJf`i#c9fl4fIYe|#c&K> zBPXOHnP;#PSg~3X27OeThDS){(S=@(x1cPh_*k5+rYu^aO|k6xL@2+fh?-ofL4fQv zTV%Y~kSK=+g&OI*q`*iA&uTfPT&wLmg?!EK8l;I;f$Ti4gf507zFOdfr&iGOb3yN$ zb3Nf7mi+>iC;bYVpo?Ct)XXvR7k9q)Xm+y|JeZNIe6uH9x#*;ywvw5Fe_R?0BhDEV zutnxGx(@A`;sGtZA~LBB#{7zwN;|q8G5cI0(zC^$^(8`|*GkuU zZZ?PmdfB6pwXMqy210VZO_KeoubW{lC!xHq4v(mBK27rYUh4d=RFxVukJO0kdvBmM zHX?&xmuPieL3(FoeInv9ukWAF)@n|)wmwq{!%PQCbe}$rvilr{G1w~7(nwb} zwzC|}#uRUfw@G_A^j-WwrmjRLiQ{sn`#IUG>r{9BcV*d16<}5E4LNc{$=hZJXKJM@ zIkI0|--~>BZn$I3Z)C7aePJ5HQRr*hIz+M?_DE(6Wf5Mv>c#)97GN_huiRe{(wgcf0IzNCM4`Ht z*BzbrFYz}x$|*o!N6c+LDR)m84|Xq8VyZd$@=bJFXN-WCZ&ty!bQ`e&s*(`!(8B8Y zD61OD0wpv7Q=?d*&P=hY{jwN1ONJq2%?B>F!w?QY73IsdP8cG|e88ImL$sO?;Co<* zb@Ks2KMWyCW^L92!`6^W&Sw0uQ5k+XS|F4mMmkg@Mj+G^TuF3o9d1)BUDXn%VLAekN2mgUA?;)ZN%; Z1X2|xZ@3?imu9{{b~gdYJ$K diff --git a/app/ic_save.png b/app/ic_save.png index 15477ae129534114d5b0bbec6dfdc51657f25e82..4daed57795d199e4eb3ea9d5eca4d67d82d407a0 100644 GIT binary patch literal 495 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD3?#3*wSy!Wi-X*q7}lMWc?smOq&xaLGB9lH z=l+w(3goi|_=LF5oH-N7Yz`3R22xBVL4Lvi8J=!8@B;EU3p^r=85sBugD~Uq{1quc zL5ULAh?3y^w370~qEv=}#LT=BJwMkF1yemkJ@f8s-z|Y^wxvdRrg?g5F>nAmtPE0& ztPG4m7RXF#C>!Kj4Mt|LI1`X<$jHPX0HmXUIJ2DvES?2qgFpfhgY?5_G)ozP{++f0EH>p74%Y2Ke=E-t~1!t92nP2lPxX%*(RQIn&A|Ft$~q& Wsj1Ri>1!3pFa}RoKbLh*2~7Z5?jw2t diff --git a/app/watch.js b/app/watch.js index 03ce4ced..e60d5253 100644 --- a/app/watch.js +++ b/app/watch.js @@ -472,8 +472,10 @@ function renderWatchPage(parent) { ">
${Share_text_string}
` - mtrlBtnContDownload.innerHTML = `` mtrlBtnContSave.innerHTML = `` - mtrlBtnContDownload.innerHTML = ``); + } itemSectRelated.querySelector(".lazy-list").appendChild(autonavBar); data.relatedVideos.data.forEach(function(item) { From 307e9db6ed6b0a51d24911293bbfab013a9751cd Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Tue, 6 Jan 2026 12:47:06 -0800 Subject: [PATCH 032/105] Fix the overflow on the icons on a small phone by adding flex wrap when the save button is enabled --- app/watch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/watch.js b/app/watch.js index 5227da4c..59251d45 100644 --- a/app/watch.js +++ b/app/watch.js @@ -503,7 +503,7 @@ function renderWatchPage(parent) { metadataActions.appendChild(mtrlBtnContShare); metadataActions.appendChild(actionsSpacer); if (WATCH_DOWNLOAD_BUTTON_expflag == "true") {metadataActions.appendChild(mtrlBtnContDownload);}; - if (WATCH_SAVE_BUTTON_expflag == "true" && WATCH_ENABLE_NEW_UI_expflag == "true") {metadataActions.appendChild(mtrlBtnContSave);}; + if (WATCH_SAVE_BUTTON_expflag == "true" && WATCH_ENABLE_NEW_UI_expflag == "true") {metadataActions.appendChild(mtrlBtnContSave);metadataActions.style.flexWrap = "nowrap"}; const W2ndHalf = document.createElement("div"); W2ndHalf.classList.add("wnr-2nd-half", "watch-next-results-content"); From 01811fc4918384a2046dff084561c3b8cc86e121 Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Wed, 7 Jan 2026 11:45:44 -0800 Subject: [PATCH 033/105] Working camera icon for HEADER_CAST_ALTERNATE_ICON make it work --- app/header.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/header.js b/app/header.js index d27eb544..22164d54 100644 --- a/app/header.js +++ b/app/header.js @@ -255,7 +255,10 @@ function renderHeader() { castBtn.setAttribute("aria-haspopup", "false"); let alternateIcon = `` if (HEADER_CAST_ALTERNATE_ICON_expflag == "true") {alternateIcon = ``} - castBtn.innerHTML = `` + alternateIcon + ``; + if (HEADER_CAST_ALTERNATE_ICON_expflag == "Camera") { + castBtn.innerHTML = ``;} + else { + castBtn.innerHTML = `` + alternateIcon + ``;} if (window.location.pathname.split("/").slice(3, 4) == "results.html") { castBtn.setAttribute("hidden", ""); } From 5123a65f9eeb40543062f77ac10e56995dd37758 Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Wed, 7 Jan 2026 11:55:44 -0800 Subject: [PATCH 034/105] Add fun fact (Estimate) this is an estimate because I see people with this shadow on Reddit on these retina devices but the ipad mini 1 i have which is non-retina does not have it. This may be correct only for talking about 13.0+ versions of YouTube --- app/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/settings.js b/app/settings.js index 086758c0..4cfd7b2e 100644 --- a/app/settings.js +++ b/app/settings.js @@ -748,7 +748,7 @@ function settingsPage() { { "type": "boolean", "title": "HEADER_NO_SHADOW", - "subtitle": "", + "subtitle": "Fun fact: there was usually no shadow on non Retina (low-res) devices", "pressed": HEADER_NO_SHADOW_expflag == "true", "pressed-default": false, "disabled": false, From 68b7b906aa6bd498c22c1a225bec2db827765077 Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Fri, 9 Jan 2026 11:24:31 -0800 Subject: [PATCH 035/105] "comment-section" placed below "wnr-2nd-half" rather than in "ytm15-video-metadata" --- app/watch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/watch.js b/app/watch.js index 59251d45..6047bf19 100644 --- a/app/watch.js +++ b/app/watch.js @@ -614,7 +614,7 @@ function renderWatchPage(parent) { }); if (WATCH_COMMENT_SECTION_LEFT_expflag == "true") { - renderCommentSection(videoMetadata, "video", playerVideoId, false); + renderCommentSection(scwnr, "video", playerVideoId, false); } else { renderCommentSection(W2ndHalf, "video", playerVideoId, false); } From d1a641b0de06ab6849a8fc933568d5e89519af16 Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Fri, 9 Jan 2026 11:43:23 -0800 Subject: [PATCH 036/105] Update invidious subtitle APP_CUSTOM_INVIDIOUS_URL --- app/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/settings.js b/app/settings.js index 4cfd7b2e..e4ae791b 100644 --- a/app/settings.js +++ b/app/settings.js @@ -712,7 +712,7 @@ function settingsPage() { { "type": "text", "title": "APP_CUSTOM_INVIDIOUS_URL", - "subtitle": "This loads your home page and comments. which should update and not be static
If you have your own invidious instance put it here
You should change CORS policy if you own your instance, otherwise use a CORS redirector
If you want to setup an invidious instance, there is always google, however your average PC probably will lag out (the preset instance is probably fine for you)
Clear the text box to reset the url", + "subtitle": "This loads your home page and comments. which should update and not be static
If you have your own invidious instance put it here
You should change CORS policy if you own your instance, otherwise use a CORS redirector. If you can use a CORS disabler extension, you can also remove the starting proxy url, it will make it faster.
If you want to setup an invidious instance, there is always google, however your average PC probably will lag out (the preset instance is probably fine for you)
Clear the text box to reset the url", "value": "https://api.codetabs.com/v1/proxy?quest=https://inv.perditum.com/", "placeholder": "", "disabled": false, From 7e3a345c85e15f904eaf2047939b410616cea61d Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Fri, 9 Jan 2026 12:38:17 -0800 Subject: [PATCH 037/105] Add account icon and image link HEADER_USE_ACCOUNT_ICON and HEADER_ACCOUNT_ICON_LINK --- app/2015ytm.js | 2 ++ app/header.js | 12 ++++++++++++ app/settings.js | 18 ++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/app/2015ytm.js b/app/2015ytm.js index b1835959..f225ec88 100644 --- a/app/2015ytm.js +++ b/app/2015ytm.js @@ -187,6 +187,8 @@ if (HEADER_YOUTUBE_BRANDING_expflag == undefined) { HEADER_YOUTUBE_BRANDING_expflag = localStorage.getItem("HEADER_YOUTUBE_BRANDING"); } WATCH_AUTOPLAY_SWITCH_expflag = localStorage.getItem("WATCH_AUTOPLAY_SWITCH"); +HEADER_USE_ACCOUNT_ICON_expflag = localStorage.getItem("HEADER_USE_ACCOUNT_ICON"); +HEADER_ACCOUNT_ICON_LINK_expflag = localStorage.getItem("HEADER_ACCOUNT_ICON_LINK"); newErrorHtml = `
`; + const innerSettingsPageCont = document.createElement("div"); innerSettingsPageCont.classList.add("inner-settings-page-container"); innerSettingsPageCont.innerHTML = ` @@ -175,6 +178,7 @@ function settingsPage() { ytm15settings.appendChild(settingsOptCont); ytm15settings.appendChild(settingsPagesCont); settingsPagesCont.appendChild(settingsPageHeader); + settingsPagesCont.appendChild(settingsSaveAndLoad); settingsPagesCont.appendChild(innerSettingsPageCont); pageCont.appendChild(page); From 8262bad7b141b4396eb96c2316eb92d2d8107e40 Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Tue, 13 Jan 2026 14:12:19 -0800 Subject: [PATCH 043/105] Notifications part 2 (fixed css) now it is fixed completely --- app/2015YTm.css | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/app/2015YTm.css b/app/2015YTm.css index d319e87e..3bddeb73 100644 --- a/app/2015YTm.css +++ b/app/2015YTm.css @@ -6102,19 +6102,18 @@ html.style-2013.dark.dark-21 { } .notification { position: fixed; - bottom: 20px; + bottom: 0; left: 50%; transform: translate(-50%, 120%); - opacity: 0; transition: transform .35s cubic-bezier(.22,.9,.35,1), opacity .25s; display: inline-block; max-width: calc(100% - 40px); - padding: 12px 16px; - background: #fff; - color: #111; - border-radius: 10px; - border: 1px solid rgba(0,0,0,.08); - box-shadow: 0 10px 30px rgba(18, 25, 33, 0.08); + padding: 20px 32px; + background: #2e2e2e; + color: #f1f1f1; + border-radius: unset; + border: unset; + box-shadow: unset; box-sizing: border-box; line-height: 1.25; font-size: 15px; @@ -6123,5 +6122,4 @@ html.style-2013.dark.dark-21 { } .notification.notification-show { transform: translate(-50%, 0); - opacity: 1; } From 2bb5d86f289793b9ce7f14b20a73c3932d67a6d5 Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Wed, 14 Jan 2026 11:44:40 -0800 Subject: [PATCH 044/105] Fix save and load position it was not appearing on the correct pages --- app/settings.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/settings.js b/app/settings.js index 17590e1f..192b4f19 100644 --- a/app/settings.js +++ b/app/settings.js @@ -178,7 +178,6 @@ function settingsPage() { ytm15settings.appendChild(settingsOptCont); ytm15settings.appendChild(settingsPagesCont); settingsPagesCont.appendChild(settingsPageHeader); - settingsPagesCont.appendChild(settingsSaveAndLoad); settingsPagesCont.appendChild(innerSettingsPageCont); pageCont.appendChild(page); @@ -315,6 +314,8 @@ function settingsPage() { headerTitle.setAttribute("aria-label", ExpFlags_text_string); headerTitle.textContent = ExpFlags_text_string; title.textContent = ExpFlags_text_string + ' - 2015YouTube'; + settingsPage.appendChild(settingsSaveAndLoad); + settingBlocks = [ { From 1c8a314dddce311e0bcea53fa91261a72bfdc772 Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Wed, 14 Jan 2026 12:30:43 -0800 Subject: [PATCH 045/105] Clean settings page. make save and load semi work ing Kinda messy --- app/settings.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/settings.js b/app/settings.js index 192b4f19..4ee34cbd 100644 --- a/app/settings.js +++ b/app/settings.js @@ -167,7 +167,8 @@ function settingsPage() { settingsPageHeader.ariaLabel = settingsPageHeader.innerHTML; const settingsSaveAndLoad = document.createElement("div"); - settingsSaveAndLoad.innerHTML = `
`; + settingsSaveAndLoad.style.display = "flex"; + settingsSaveAndLoad.innerHTML = `
`; const innerSettingsPageCont = document.createElement("div"); innerSettingsPageCont.classList.add("inner-settings-page-container"); @@ -269,6 +270,7 @@ function settingsPage() { settingsPage.style.khtmlUserSelect = "unset"; settingsPage.style.webkitUserSelect = "unset"; settingsPage.style.webkitTouchCallout = "unset"; + settingsPage.style.letterSpacing = "1px"; innerSettingsPageCont.appendChild(settingsPage); settingsPageHeader.innerHTML = Feedback_text_string; settingsPageHeader.id = "feedback"; @@ -292,6 +294,7 @@ function settingsPage() { settingsPage.style.khtmlUserSelect = "unset"; settingsPage.style.webkitUserSelect = "unset"; settingsPage.style.webkitTouchCallout = "unset"; + settingsPage.style.letterSpacing = "1px"; innerSettingsPageCont.appendChild(settingsPage); settingsPageHeader.innerHTML = InstallYtm15_text_string; settingsPageHeader.id = "install"; @@ -299,7 +302,7 @@ function settingsPage() { headerTitle.textContent = InstallYtm15_text_string; title.textContent = InstallYtm15_text_string + ' - 2015YouTube'; - settingsPage.innerHTML=`
2015YouTube
ytm15.github.io
Get as a Webapp
  1. Open Safari (iOS)/Chrome (Android)
  2. Go to ytm15.github.io/app
  3. Press "share"/the three dots
  4. Press "Add to Home Screen"
`; + settingsPage.innerHTML=`
2015YouTube
ytm15.github.io
Get as a Webapp
Modern devices:
  1. Open Safari (iOS)/Chrome (Android)
  2. Go to https://ytm15.github.io/app
  3. Press "share"/the three dots
  4. Press "Add to Home Screen"
YTm15 is not supported on ≤iOS 9. Alternatively, there are websites online that claim to be able to insert a website into an APK.`; } if (window.location.hash.split("/").join(',').split("?").join(',').split(',').slice(1, 2)[0] == "expflags") { /* innerSettingsPageCont.innerHTML = ` From 437bfdc7966eff1b504d9cb7733ea70c62590763 Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Thu, 15 Jan 2026 12:09:39 -0800 Subject: [PATCH 046/105] Fix shorts not being clickable on channel sort When you select shorts --- app/2015ytm.js | 4 ++-- app/channel.js | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/2015ytm.js b/app/2015ytm.js index 472731df..f3a36df1 100644 --- a/app/2015ytm.js +++ b/app/2015ytm.js @@ -1240,7 +1240,7 @@ function renderCompactMediaItem(parent, parentName, itemVideoId, itemThumbnail, } else if (mediaType == "hashtag") { thumbnail.href = "#" + itemVideoId; } - if (mediaType == "video" || mediaType == "shortVideo") { + if (mediaType == "video" || mediaType == "shortVideo" || mediaType == "shorts") { thumbnail.onclick = function(){ if (!app.querySelector("#watchpageFrame_Container")) { app.insertAdjacentElement("afterbegin", watchContainer); @@ -1443,7 +1443,7 @@ function renderCompactMediaItem(parent, parentName, itemVideoId, itemThumbnail, } else if (mediaType == "hashtag") { metaContent.href = "#" + itemVideoId; } - if (mediaType == "video" || mediaType == "shortVideo") { + if (mediaType == "video" || mediaType == "shortVideo" || mediaType == "shorts") { metaContent.onclick = function(){ if (!app.querySelector("#watchpageFrame_Container")) { app.insertAdjacentElement("afterbegin", watchContainer); diff --git a/app/channel.js b/app/channel.js index 14163402..f51cb044 100644 --- a/app/channel.js +++ b/app/channel.js @@ -1205,6 +1205,7 @@ function channelPage() { compMediaItemAuthor = item.channelTitle; compMediaItemvidId = item.videoId; } + //console.log(item.type + compMediaItemvidId) renderCompactMediaItem(lazyList, "channel-lazy-list", compMediaItemvidId, compMediaItemThumb, compMediaItemLength, compMediaItemTitle, compMediaItemAuthor, item.channelId, item.publishedTimeText, item.viewCount, item.type); }); }; From 068d6e4dca4227b0112a2c2fd00786bd29b90f4d Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Thu, 15 Jan 2026 12:10:56 -0800 Subject: [PATCH 047/105] Update invidious instance once again y.com.sb --- app/2015ytm.js | 2 +- app/settings.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/2015ytm.js b/app/2015ytm.js index f3a36df1..4dd953ba 100644 --- a/app/2015ytm.js +++ b/app/2015ytm.js @@ -152,7 +152,7 @@ APP_HELVETICA_NEUE_FONT_expflag = localStorage.getItem("APP_HELVETICA_NEUE_FONT" APP_NEW_ERROR_SCREEN_expflag = localStorage.getItem("APP_NEW_ERROR_SCREEN"); APP_CUSTOM_INVIDIOUS_URL_expflag = localStorage.getItem("APP_CUSTOM_INVIDIOUS_URL"); if (APP_CUSTOM_INVIDIOUS_URL_expflag == undefined || APP_CUSTOM_INVIDIOUS_URL_expflag == "") { - localStorage.setItem("APP_CUSTOM_INVIDIOUS_URL", "https://api.codetabs.com/v1/proxy?quest=https://yt.omada.cafe/"); + localStorage.setItem("APP_CUSTOM_INVIDIOUS_URL", "https://api.codetabs.com/v1/proxy?quest=https://y.com.sb/"); APP_CUSTOM_INVIDIOUS_URL_expflag = localStorage.getItem("APP_CUSTOM_INVIDIOUS_URL"); } APP_DONT_AUTH_TO_INVIDIOUS_expflag = localStorage.getItem("APP_DONT_AUTH_TO_INVIDIOUS"); diff --git a/app/settings.js b/app/settings.js index 4ee34cbd..3e397c96 100644 --- a/app/settings.js +++ b/app/settings.js @@ -721,7 +721,7 @@ function settingsPage() { "type": "text", "title": "APP_CUSTOM_INVIDIOUS_URL", "subtitle": "This loads your home page and comments. which should update and not be static
If you have your own invidious instance put it here
You should change CORS policy if you own your instance, otherwise use a CORS redirector. If you can use a CORS disabler extension, you can also remove the starting proxy url, it will make it faster.
If you want to setup an invidious instance, there is always google, however your average PC probably will lag out (the preset instance is probably fine for you)
Clear the text box to reset the url", - "value": "https://api.codetabs.com/v1/proxy?quest=https://yt.omada.cafe/", + "value": "https://api.codetabs.com/v1/proxy?quest=https://y.com.sb/", "placeholder": "", "disabled": false, "lsitem": "APP_CUSTOM_INVIDIOUS_URL" From 8efc601ce01484af946e53108a2e86ca20dfc25f Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Thu, 15 Jan 2026 12:14:20 -0800 Subject: [PATCH 048/105] WATCH_SAVE_IS_ADD_TO Also optimize the notifications is activity expflag by 1ms because why not --- app/2015ytm.js | 10 ++++++++-- app/settings.js | 9 +++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/app/2015ytm.js b/app/2015ytm.js index 4dd953ba..e03b5a27 100644 --- a/app/2015ytm.js +++ b/app/2015ytm.js @@ -193,6 +193,7 @@ if (HEADER_ACCOUNT_ICON_LINK_expflag == undefined) { localStorage.setItem("HEADER_ACCOUNT_ICON_LINK", ""); HEADER_ACCOUNT_ICON_LINK_expflag = localStorage.getItem("HEADER_ACCOUNT_ICON_LINK"); } +WATCH_SAVE_IS_ADD_TO_expflag = localStorage.getItem("WATCH_SAVE_IS_ADD_TO"); newErrorHtml = `` + saveIconSvg = "M14 10H3v2h11v-2zm0-4H3v2h11V6zm4 8v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zM3 16h7v-2H3v2z" + if (WATCH_SAVE_UPDATED_ICON_expflag == "true") { + saveIconSvg = "M19,11H15V15H13V11H9V9H13V5H15V9H19M20,2H8A2,2 0 0,0 6,4V16A2,2 0 0,0 8,18H20A2,2 0 0,0 22,16V4A2,2 0 0,0 20,2M4,6H2V20A2,2 0 0,0 4,22H18V20H4V6Z" + } mtrlBtnContSave.innerHTML = `` - saveIconSvg = "M14 10H3v2h11v-2zm0-4H3v2h11V6zm4 8v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zM3 16h7v-2H3v2z" + saveIconSvg = "M14 10H3v2h11v-2zm0-4H3v2h11V6zm4 8v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zM3 16h7v-2H3v2z"; + saveIconScale = "3"; if (WATCH_SAVE_UPDATED_ICON_expflag == "true") { - saveIconSvg = "M19,11H15V15H13V11H9V9H13V5H15V9H19M20,2H8A2,2 0 0,0 6,4V16A2,2 0 0,0 8,18H20A2,2 0 0,0 22,16V4A2,2 0 0,0 20,2M4,6H2V20A2,2 0 0,0 4,22H18V20H4V6Z" + saveIconSvg = "M19,11H15V15H13V11H9V9H13V5H15V9H19M20,2H8A2,2 0 0,0 6,4V16A2,2 0 0,0 8,18H20A2,2 0 0,0 22,16V4A2,2 0 0,0 20,2M4,6H2V20A2,2 0 0,0 4,22H18V20H4V6Z"; + saveIconScale = "2"; } mtrlBtnContSave.innerHTML = `` From 3e0fdda994f21c7e66cea1fde779ce9fb6e772ec Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Fri, 23 Jan 2026 10:38:07 -0800 Subject: [PATCH 056/105] Fix not able2 switch cast icon(also foreshadowing) The foreshadowing is that there is ANOTHER cast icon in v10 --- app/2015ytm.js | 2 +- app/header.js | 2 +- app/settings.js | 9 +++++++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/app/2015ytm.js b/app/2015ytm.js index 90fa94f5..6d6f2f5a 100644 --- a/app/2015ytm.js +++ b/app/2015ytm.js @@ -168,7 +168,7 @@ APP_UNDERLINE_BUTTONS_expflag = localStorage.getItem("APP_UNDERLINE_BUTTONS"); HEADER_CAST_BUTTON_AS_URL_BOX_expflag = localStorage.getItem("HEADER_CAST_BUTTON_AS_URL_BOX"); HEADER_CAST_ALTERNATE_ICON_expflag = localStorage.getItem("HEADER_CAST_ALTERNATE_ICON"); if (HEADER_CAST_ALTERNATE_ICON_expflag == undefined) { - localStorage.setItem("HEADER_CAST_ALTERNATE_ICON", "true"); + localStorage.setItem("HEADER_CAST_ALTERNATE_ICON", "Material"); HEADER_CAST_ALTERNATE_ICON_expflag = localStorage.getItem("HEADER_CAST_ALTERNATE_ICON"); } APP_STOP_TEXT_SELECTION_expflag = localStorage.getItem("APP_STOP_TEXT_SELECTION"); diff --git a/app/header.js b/app/header.js index 531b67b6..b37e0117 100644 --- a/app/header.js +++ b/app/header.js @@ -255,7 +255,7 @@ function renderHeader() { castBtn.setAttribute("aria-label", SearchYT_text_string); castBtn.setAttribute("aria-haspopup", "false"); let alternateIcon = `` - if (HEADER_CAST_ALTERNATE_ICON_expflag == "true") {alternateIcon = ``} + if (HEADER_CAST_ALTERNATE_ICON_expflag == "Materialv2") {alternateIcon = ``} if (HEADER_CAST_ALTERNATE_ICON_expflag == "Camera") { castBtn.innerHTML = ``;} else { diff --git a/app/settings.js b/app/settings.js index e5645ed7..a90543c0 100644 --- a/app/settings.js +++ b/app/settings.js @@ -795,9 +795,14 @@ function settingsPage() { "subtitle": "", "options": [ { - "title": "true", - "selected": HEADER_CAST_ALTERNATE_ICON_expflag == "true", + "title": "Material", + "selected": HEADER_CAST_ALTERNATE_ICON_expflag == "Material", "selected-default": true + } + { + "title": "Materialv2", + "selected": HEADER_CAST_ALTERNATE_ICON_expflag == "Materialv2", + "selected-default": false }, { "title": "Camera", From e0cdf1a817ae7b8741ec749450b502c18854300d Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Fri, 23 Jan 2026 10:39:09 -0800 Subject: [PATCH 057/105] I forgot a comma i broke everything for like 30 secs --- app/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/settings.js b/app/settings.js index a90543c0..8b5b33c1 100644 --- a/app/settings.js +++ b/app/settings.js @@ -798,7 +798,7 @@ function settingsPage() { "title": "Material", "selected": HEADER_CAST_ALTERNATE_ICON_expflag == "Material", "selected-default": true - } + }, { "title": "Materialv2", "selected": HEADER_CAST_ALTERNATE_ICON_expflag == "Materialv2", From cd5bace900f5608d58fa185f759fc4b748c055cd Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Fri, 23 Jan 2026 12:09:32 -0800 Subject: [PATCH 058/105] Add share button functionality yay with the Web Share API --- app/watch.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/app/watch.js b/app/watch.js index 5473bc28..2b1bcd94 100644 --- a/app/watch.js +++ b/app/watch.js @@ -22,6 +22,21 @@ function renderWatchPage(parent) { insertYTmPlayer(playerCont2); + async function shareVideo() { + if (navigator.share) { + try { + await navigator.share({url:"https://youtu.be/" + playerVideoId}) + } + catch(err) { + if (err.name !== 'AbortError') { + showNotification(err); + } + } + } else { + showNotification("Web Share API not supported!"); + } + } + const getWatchData = new XMLHttpRequest(); /* getWatchData.open('GET', APIbaseURL + 'api/v1/videos/' + playerVideoId, true); */ /* getWatchData.open('GET', APIbaseURLWatch + 'api/v1/videos/' + playerVideoId, true); */ @@ -507,6 +522,7 @@ function renderWatchPage(parent) { metadataActions.appendChild(mtrlBtnCont); metadataActions.appendChild(mtrlBtnContDislike); metadataActions.appendChild(mtrlBtnContShare); + mtrlBtnContShare.querySelector("button").addEventListener("click", shareVideo); metadataActions.appendChild(actionsSpacer); if (WATCH_DOWNLOAD_BUTTON_expflag == "true") {metadataActions.appendChild(mtrlBtnContDownload);}; if (WATCH_SAVE_BUTTON_expflag == "true" && WATCH_ENABLE_NEW_UI_expflag == "true") {metadataActions.appendChild(mtrlBtnContSave);metadataActions.style.flexWrap = "nowrap"}; From 561c1cd7b15e9723a23fc6a7e9ef03e966486117 Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Fri, 23 Jan 2026 12:46:46 -0800 Subject: [PATCH 059/105] Add alt share icons player files no expflag yet --- app/ic_vidcontrol_share_alt.png | Bin 0 -> 1222 bytes app/ic_vidcontrol_share_pressed_alt.png | Bin 0 -> 1925 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/ic_vidcontrol_share_alt.png create mode 100644 app/ic_vidcontrol_share_pressed_alt.png diff --git a/app/ic_vidcontrol_share_alt.png b/app/ic_vidcontrol_share_alt.png new file mode 100644 index 0000000000000000000000000000000000000000..bb3f8840752f60e277e89b6973627d8ab9592636 GIT binary patch literal 1222 zcmV;%1UdVOP)002t}1ONa4l1H*(000DyNkl2!hc>tRh+_aMo4p1d?GH4`;zo?qQsO_Tx_ z7CNb^ddFI(;z6riKscyc*g_KH>J^L3q8Z$T6SYz-1r4uL8G`~a-3BV6n1oSE7z_?P z`0@Xd8~@drK{D6U>&69yK*2#Z0cYdmci!K?bueAodXxxR^zyRAm}x1IqtD4xKdoik zLyKF(eIH+HuMcU%UD9Uf=`W8mNFK9%xg}6=;=+xFg-#9~6(7N-rj4tgSg2=q9C^QM z&|E(A(dPM6G|`vX+q37Ffj^0m!zx#92~<4PFjY*c^T!L>I5E;Vl)%$VpLt}Ow(r=c z{r$c9E9iJVH9o&0vgvq)A>tG;i>Zmlu@t-_6q^6i!|N8+SDT!=_{PC6x|_VOtX$LD z+w|ffEgZK^}dyB9@1xqETCS+m4N^XR2v*1nz`u=lPXEGqdAx=izW4 z5t8IFkt1;+kjQJE@~~WZXx{qNvv;ToOe7$1;@&l|c~AI+agI1y%!y*4JPR8Y7d4M9 zP*YdqQj*7r=TG-?jsf&ylBslYs-WVjSI1>Iw|dBsEhVZrmc&AjWyZgYNC6iv9HlH| z#oWpuPxPC!^7`5)5{^)#(m)Uoj$-QGgyUt)q`P*2L^-1`X{vLN{<z(l1CvVZ-TsE)ex5$=Hzx`DX z5+#d?cH?quIOVIUWm;R);^~IDH~jYnk|@65i%T}F@&!A8clY1WKRmkq=cKh_?z*-G^_ton{p#e`-(Nai z-kNxA86!}USXf8|8eaTWp;^t_9&DR;Dzoom`|MgvUz=iRP-{Y1%(gsY_B zh`+F$DaCCuO1FKL=$J%_&GwE|%+Z!__Tw!sZcDqxuqco&WX6NDSS8CIN?h_1A zC}xFG>N5z?@KP6=wPIdlz#$^(pU!rlqMtYgq^uxog7d9PvPyCqDC|ER*esi6vuu{l kvRO9EX4x#8^}l5O1E`GG{sf1`%m4rY07*qoM6N<$f)5s4iU0rr literal 0 HcmV?d00001 diff --git a/app/ic_vidcontrol_share_pressed_alt.png b/app/ic_vidcontrol_share_pressed_alt.png new file mode 100644 index 0000000000000000000000000000000000000000..8796bd22ea6b4f217ee0ca8d41b11f9e5be64c7a GIT binary patch literal 1925 zcmd5+i8s`H934v~qte4ziYeKpWEb z{a3Lbp#hlu2Z45XgS#~#6m%Dg1pI+3K)@D@0?6)lmIlZG1w{e_SOFbuK?u~rBTK_F z0U(qLx&rXso{$410J~5;Fo1-hLjzcW&Orm@43uC10>}aS6i|l{;J~^FW>DZRpdc3N zU>&*$SjY-^f*H#5OZ)R1gIFK{I52?_1V&Z{{0iTO+gRAbU~KFhoO|}}vKa2IuT9 zc2My1kz;m3-7ao{P8~P}S+Qzwtq^SqV(|Dw(&$s!2)_U`vKsmm;ve0DM2&%(Z1w`( zvwnX#6_aaxoi3+U^)c?h2rUl_Js6BDO6U;OncA6+tXR1*Ie()LV{fidKlF}SI?R+R zlAZZG5P^o>(qr@Z6i{=Ft1B2QA)9ebkw1_`u7R16?!?b(jI_U(*c<)`g}_crbnLfq zbjj(b9F`R6xpe`-u9%9?rCfTVLpsbOi;b7E>Xd>@3V#&cG%n0_t6q*0&&rS)kb-;2 z%@0jihef|et?alxlydz?Dw?WR3aKc%lR}RTth$Tnr}?$tz4>x} z!Ckxo+%(-C^o4L z_f$M8&4n%UOHyzsb7{Z{mCKh`h4Y?!$FoApJ%vMzVZCPfa(G5EjuEBK_$((*$|w^>$BQ0wf-SkP3{I!;S{{OWfURj;Y-{@l(UF2D8Q z{7J$UA5Z4o=kSfm^oj2i$O$DCTHC-t+-s8_bb4_}m@=oyBp?LC*Id$4%6Zd9>k|kZ7krxf3b(U#Ma3iRN-K3!YlRreldM`vjpS6Ul*`(< z?t3iY4GkF+8)#~EK-n;NWEY4Fz2-~!&QWg5~bHsDL= zS#wRcb$E%8LvN#-saqf=n{a)#q}C{w9w15B5ZAN0(-~SQ(^qrvnZgFna>rBN@rdkQ zVqJ1eQlWibzr9k#dTV2U+q4L_p0lFoB^^~4uH#wsz~v?KW_>dfKa$ebLLU=fB(Fq# z-<;a+M56Tj7x)JAY@NxPH*u#+=2d9;25~x^?MEt=m`Q%dB>lx!Lyomn-9|N(#}YE8 lL?Z~v&Y05ThYT(H9zn$|oau&}0Qh5rnHpLcROoqN{{^n==hFZH literal 0 HcmV?d00001 From e3ef3a5c62fc185007ebe3cdb531902ec2eb0472 Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Fri, 23 Jan 2026 13:58:16 -0800 Subject: [PATCH 060/105] Add more video control icon files for later --- app/ic_vidcontrol_add_to.png | Bin 0 -> 662 bytes app/ic_vidcontrol_add_to_pressed.png | Bin 0 -> 1410 bytes app/mr_ic_media_route_off_holo_dark.png | Bin 0 -> 621 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/ic_vidcontrol_add_to.png create mode 100644 app/ic_vidcontrol_add_to_pressed.png create mode 100644 app/mr_ic_media_route_off_holo_dark.png diff --git a/app/ic_vidcontrol_add_to.png b/app/ic_vidcontrol_add_to.png new file mode 100644 index 0000000000000000000000000000000000000000..8f03f6f19962774371cf58d073aa642d24a1fc09 GIT binary patch literal 662 zcmeAS@N?(olHy`uVBq!ia0vp^-XP4u3?%s{blm__Hv)V@T>t<74`dPqn>KB_3I=P} zt_3OvGJzU_;M}=$aJ_KBGiS~q3!XlG8qS62g^NJU1d=~~{P_0m8^lZ?2@zkjW)0A& zQ>RXyJbCiOi4#BtpFe+w7zI=S6o;@O)&X4tcO+0_+O6f%KxvPXAirP+21Yg>K@m|c z8)s|H-B+(|^@5Yx4ruh>~`^p*uO7SBfRFwk*cukH*TFffBNu|J-g{Z{sXzjXr(ZMgufM%(Bx;TbJ9DY0PX3!x6k+z9CzPAEcuUtzAj1<|} zwTYukNAJb&{S!HT-SZ06W_>*N`R-if$@xYz|D4nm0Xg^ptF^RNYD*`?~L}S-YgCNo*@vYdquf z?x{idzV4F}_0x&D^8WPOFSS{l*C%}F%@(-vhP(UWi+cw1Y*u{jpImrPg17Z-rJ~ld zlfiC_jf2ze<8^%J`dpRHF5j<|m9cHh>&l;#%$0WkX1&RFJ^pWh%j%qKadZFNp0RiB oy>NNIXPncE&*eYY2l?^FIrST*#?fn4@;pFXPgg&ebxsLQ0GX&bHUIzs literal 0 HcmV?d00001 diff --git a/app/ic_vidcontrol_add_to_pressed.png b/app/ic_vidcontrol_add_to_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..99e009b367a887bfb4c8ec15108bcdb2e25f75db GIT binary patch literal 1410 zcmeAS@N?(olHy`uVBq!ia0vp^-XP4u3?%s{blqTJVC)a@332`Z|Nl?ggI~XX{r&s* z-@kuA5^ft%5GVq40FZ1svPxt%$ZSkqxI{2@VTu6t0tJyxz{*DU2*jsA z5jemT$PmMUBm`7knRpf$L#-u2e!;*fVq#`t=ip@J;TI6(<`Wi|lI9XqR8<$1Q`0jx zl@*dPKXU(&k&=P)qyGez-nee9?082K#3A^v%!tAd23PwIYda3|$Kn}ed*bY3SV0cRxzE?uRgPDesS zM33$cnRfTzhkeecPFp^;h@KamexCn#YWn=md+&d*yjO0Xw<2h%*VXz(v!}B#9^6pT zs(1g@bXE%vEiOifN*#^{gEFd#^1d+>^*%qJ7 zF_Ox#ZHxJH=3fLy=0dhJVaJX|oGt58c)B5Aj+{h_(tt-_DS|I%@4Sqm>mZ8zm+3p7x0Jc_j+o5_p{PyMFz)X3k7b zPMrX~xt({v{b_u9GtJj3U_*B8`nbJiW#7N?^WA2QR}!>jIxnv(#5sR?ZN-ND+jlGP zjO$=HH!<_t=GJpj$+gK3-^kqGn_u%nWYbqQ=5v7#D&NHq^Iq)_54Y;Qb!q*-UpFEn zZP)P^_B{Fb>*n{IO;353Yj55fcVE9=YsulWVUwob`>vqcAisFmp<4aO8IOU7)Z1N`m}? z8UFA3!s;TuuTt^fR`Yv*7YOkAFa4>nvf`6{vY6A052k+>$t&D>DEuQ^?rGA--#vB? zst59?GB4Krrepkzhi&uhcE)qc&SzH6TwTf$weDhVmgW|q$xl38978;gznyYA=#Ybe z>w8vK9tDLH+H8k^rv^BQ$TPYK1b+Bm-#&5b?h>(02j(0N@eQ9lYhP?EGs_=sjRzl^ z($6=3`0k|fCiuX~mGX*8x6a+)USLx8%sU|CV@r(3y!TT>qGYU!C!Spy^eM Date: Fri, 23 Jan 2026 14:14:36 -0800 Subject: [PATCH 061/105] Collapsable comments (only icon) (part 1) I didn't have enough time --- app/2015ytm.js | 7 ++++++- app/settings.js | 9 +++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/app/2015ytm.js b/app/2015ytm.js index 6d6f2f5a..9c8e801c 100644 --- a/app/2015ytm.js +++ b/app/2015ytm.js @@ -197,6 +197,7 @@ WATCH_SAVE_IS_ADD_TO_expflag = localStorage.getItem("WATCH_SAVE_IS_ADD_TO"); PIVOT_TRENDING_IS_EXPLORE_expflag = localStorage.getItem("PIVOT_TRENDING_IS_EXPLORE"); PIVOT_LIBRARY_UPDATED_ICON_expflag = localStorage.getItem("PIVOT_LIBRARY_UPDATED_ICON"); WATCH_SAVE_UPDATED_ICON_expflag = localStorage.getItem("WATCH_SAVE_UPDATED_ICON"); +WATCH_COLLAPSABLE_COMMENTS_expflag = localStorage.getItem("WATCH_COLLAPSABLE_COMMENTS"); newErrorHtml = ``; + if (APP_NEW_ERROR_SCREEN_expflag == "true"){error.innerHTML=newErrorHtml}; + pageCont.before(error); + error.querySelector("button").onclick = function(){ + renderData(); + error.remove(); + }; + return; + } + + return; + } + /* if (urlpage == "popular") */ if (window.location.hash.split("/").join(',').split("?").join(',').split(',').slice(1, 2)[0] == "popular") { pageCont.innerHTML = ""; @@ -408,7 +515,12 @@ function renderData() { }; eventListenFunc(); - if (window.location.hash.split("/").join(',').split("?").join(',').split(',').slice(1, 2)[0] == "popular" || window.location.hash.split("/").join(',').split("?").join(',').split(',').slice(1, 2)[0] == "trending") { + // This makes the library work offline if the invidious instance is down and also unintentionally makes switching tabs fast not start overlapping requests and page loads + if ( + window.location.hash.split("/").join(',').split("?").join(',').split(',').slice(1, 2)[0] == "popular" || + window.location.hash.split("/").join(',').split("?").join(',').split(',').slice(1, 2)[0] == "trending" || + window.location.hash.split("/").join(',').split("?").join(',').split(',').slice(1, 2)[0] == "library" + ) { return; }; From 4e77022b95de9b62833370ac7ab0c4268bcc4ad3 Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Tue, 27 Jan 2026 12:21:12 -0800 Subject: [PATCH 063/105] Library part 2 it kinda works --- app/home.js | 2 +- app/watch.js | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/home.js b/app/home.js index 819cab1f..9f1f22f2 100644 --- a/app/home.js +++ b/app/home.js @@ -353,7 +353,7 @@ function renderData() { ); }); } catch (err) { - showNotification(e); + showNotification(err); var spinner = document.querySelector(".spinner-container.full-height"); spinner.setAttribute("hidden", ""); diff --git a/app/watch.js b/app/watch.js index 2b1bcd94..22687658 100644 --- a/app/watch.js +++ b/app/watch.js @@ -36,6 +36,11 @@ function renderWatchPage(parent) { showNotification("Web Share API not supported!"); } } + function saveVideo(videoId,url,lengthSeconds,title,author,authorId,publishedText,viewCount) { + const library = JSON.parse(localStorage.getItem("WEB_LIBRARY")) || []; + library.push({videoId:videoId,videoThumbnails:[{url:url}],lengthSeconds:lengthSeconds,title:title,author:author,authorId:authorId,publishedText:publishedText,viewCount:viewCount}); + localStorage.setItem("WEB_LIBRARY",JSON.stringify(library)); + } const getWatchData = new XMLHttpRequest(); /* getWatchData.open('GET', APIbaseURL + 'api/v1/videos/' + playerVideoId, true); */ @@ -523,6 +528,7 @@ function renderWatchPage(parent) { metadataActions.appendChild(mtrlBtnContDislike); metadataActions.appendChild(mtrlBtnContShare); mtrlBtnContShare.querySelector("button").addEventListener("click", shareVideo); + mtrlBtnContSave.querySelector("button").addEventListener("click", ()=>{saveVideo(playerVideoId,"/app/subscribe_mark.png","0","Test Video!","YouTube Mobile 2015","idk","Now",0)}); metadataActions.appendChild(actionsSpacer); if (WATCH_DOWNLOAD_BUTTON_expflag == "true") {metadataActions.appendChild(mtrlBtnContDownload);}; if (WATCH_SAVE_BUTTON_expflag == "true" && WATCH_ENABLE_NEW_UI_expflag == "true") {metadataActions.appendChild(mtrlBtnContSave);metadataActions.style.flexWrap = "nowrap"}; From cf09bcbcebf78b74d72087008ee86d72b6d49790 Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Tue, 27 Jan 2026 12:35:14 -0800 Subject: [PATCH 064/105] Label library and add beta tag it showed trending before --- app/2015YTm.css | 11 +++++++++++ app/home.js | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/app/2015YTm.css b/app/2015YTm.css index 84845da7..d2e0365f 100644 --- a/app/2015YTm.css +++ b/app/2015YTm.css @@ -992,6 +992,17 @@ ytm15-header-bar[ischannel="true"] { .header-title { font-weight: 500; } +.header-title[aria-label="Library"]::after { + content: "Beta"; + text-transform: uppercase; + font-size: 1.3rem; + margin: 0 8px; + padding: 1px 6px; + background-color: rgba(0, 0, 0, 0.15); + opacity: .6; + font-weight: 500; + border-radius: 2px; +} /* Header content and other header things */ .header-content { diff --git a/app/home.js b/app/home.js index 9f1f22f2..aeaf4b50 100644 --- a/app/home.js +++ b/app/home.js @@ -298,8 +298,8 @@ function renderData() { return; } - headerTitle.setAttribute("aria-label", Trending_text_string); - headerTitle.textContent = Trending_text_string; + headerTitle.setAttribute("aria-label", Library_text_string); + headerTitle.textContent = Library_text_string; const page = document.createElement("page"); page.classList.add('home'); From 274af2baa05cb39176c55d523caafbef2337b8eb Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Wed, 28 Jan 2026 10:25:36 -0800 Subject: [PATCH 065/105] fix 6 characters of code Trending is library --- app/home.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/home.js b/app/home.js index aeaf4b50..8f63b015 100644 --- a/app/home.js +++ b/app/home.js @@ -334,7 +334,7 @@ function renderData() { var oldTitle = document.querySelector("title"); var title = document.createElement("title"); - title.textContent = Trending_text_string + ' - 2015YouTube'; + title.textContent = Library_text_string + ' - 2015YouTube'; oldTitle.parentNode.replaceChild(title, oldTitle); From 6bbafbfaf3067e11b019c49f6a4fdac2953ef5ca Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Wed, 28 Jan 2026 11:24:11 -0800 Subject: [PATCH 066/105] Fix autoplay getting cutoff kinda --- app/watch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/watch.js b/app/watch.js index 22687658..7d58ac6c 100644 --- a/app/watch.js +++ b/app/watch.js @@ -605,7 +605,7 @@ function renderWatchPage(parent) { autonavBar.innerHTML = `

${UpNext_text_string}

`; } if (WATCH_AUTOPLAY_SWITCH_expflag == "true") { - autonavBar.insertAdjacentHTML("beforeend",`

Autoplay

`); + autonavBar.insertAdjacentHTML("beforeend",`

Autoplay

`); } itemSectRelated.querySelector(".lazy-list").appendChild(autonavBar); From 5ad921a0f5032cec73c59d9845f252e8f2e61274 Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Wed, 28 Jan 2026 12:13:06 -0800 Subject: [PATCH 067/105] Collapsable Comments working (no animation yet) part 2 --- app/2015YTm.css | 3 +++ app/2015ytm.js | 2 ++ 2 files changed, 5 insertions(+) diff --git a/app/2015YTm.css b/app/2015YTm.css index d2e0365f..5bdc637c 100644 --- a/app/2015YTm.css +++ b/app/2015YTm.css @@ -3726,6 +3726,9 @@ button.comment-icon-button { height: 14px; margin-right: 2px; } +.collapse-comments .comment-simplebox,.collapse-comments .comment-separator,.collapse-comments .lazy-list,.collapse-comments .next-continuation-cont { + display:none; +} /* Community posts */ [data-is-beta="true"] .posts-header-text::after { diff --git a/app/2015ytm.js b/app/2015ytm.js index 80169ba2..df0bd6f4 100644 --- a/app/2015ytm.js +++ b/app/2015ytm.js @@ -711,7 +711,9 @@ function renderCommentSection(parent, mediaType, cmSource, isCMPage, comntId, co commentCount = `Retrieving count...`; commentsCollapseIcon = "" if (WATCH_COLLAPSABLE_COMMENTS_expflag == "true") { + commentSection.classList.add("collapse-comments"); commentsCollapseIcon = `` + commentsHeader.addEventListener("click", () => {commentSection.classList.toggle("collapse-comments");}); } commentsHeader.innerHTML = `

${Comments_text_string}${commentCount}${commentsCollapseIcon}

`; From 2f35364db810a992fd25f81d4f497f59c81af075 Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Wed, 28 Jan 2026 12:14:44 -0800 Subject: [PATCH 068/105] Add notification when saving video is it accurate? --- app/watch.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/watch.js b/app/watch.js index 7d58ac6c..bd329b51 100644 --- a/app/watch.js +++ b/app/watch.js @@ -40,6 +40,7 @@ function renderWatchPage(parent) { const library = JSON.parse(localStorage.getItem("WEB_LIBRARY")) || []; library.push({videoId:videoId,videoThumbnails:[{url:url}],lengthSeconds:lengthSeconds,title:title,author:author,authorId:authorId,publishedText:publishedText,viewCount:viewCount}); localStorage.setItem("WEB_LIBRARY",JSON.stringify(library)); + showNotification("Saved to playlist"); } const getWatchData = new XMLHttpRequest(); From 9497687155cf26b2ab866874744e9e6cdc9fd375 Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Wed, 28 Jan 2026 12:15:39 -0800 Subject: [PATCH 069/105] Add save button subtitle It works! --- app/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/settings.js b/app/settings.js index 1c7242be..9963dd70 100644 --- a/app/settings.js +++ b/app/settings.js @@ -851,7 +851,7 @@ function settingsPage() { { "type": "boolean", "title": "WATCH_SAVE_BUTTON", - "subtitle": "", + "subtitle": "Saved videos go to your Library on the homepage.", "pressed": WATCH_SAVE_BUTTON_expflag == "true", "pressed-default": false, "disabled": false, From 6c23745fade3c80827c60191c41a361524fcc634 Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Thu, 29 Jan 2026 10:44:32 -0800 Subject: [PATCH 070/105] Fix autoplay switch again it should work now --- app/watch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/watch.js b/app/watch.js index bd329b51..234ba996 100644 --- a/app/watch.js +++ b/app/watch.js @@ -606,7 +606,7 @@ function renderWatchPage(parent) { autonavBar.innerHTML = `

${UpNext_text_string}

`; } if (WATCH_AUTOPLAY_SWITCH_expflag == "true") { - autonavBar.insertAdjacentHTML("beforeend",`

Autoplay

`); + autonavBar.insertAdjacentHTML("beforeend",`

Autoplay

`); } itemSectRelated.querySelector(".lazy-list").appendChild(autonavBar); From 802405baca4d1080ea7d603cccb86db4c791578d Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Thu, 29 Jan 2026 12:32:39 -0800 Subject: [PATCH 071/105] Add animation when collapsing comments also fix something that might get back on me later aka chaining the lazy list to the comment section --- app/2015YTm.css | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/2015YTm.css b/app/2015YTm.css index 5bdc637c..22a55a02 100644 --- a/app/2015YTm.css +++ b/app/2015YTm.css @@ -3726,9 +3726,12 @@ button.comment-icon-button { height: 14px; margin-right: 2px; } -.collapse-comments .comment-simplebox,.collapse-comments .comment-separator,.collapse-comments .lazy-list,.collapse-comments .next-continuation-cont { +.collapse-comments .comment-simplebox,.collapse-comments .comment-separator,.comment-section.collapse-comments .lazy-list,.collapse-comments .next-continuation-cont { display:none; } +.comment-section .lazy-list { + transition: transform .35s cubic-bezier(.22,.9,.35,1); +} /* Community posts */ [data-is-beta="true"] .posts-header-text::after { From e50a5506b87912d87e1b9da6b99af7e815e4e4f1 Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Fri, 30 Jan 2026 13:48:36 -0800 Subject: [PATCH 072/105] Toggleable autoplay For decoration --- app/watch.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/watch.js b/app/watch.js index 234ba996..7d267754 100644 --- a/app/watch.js +++ b/app/watch.js @@ -606,7 +606,7 @@ function renderWatchPage(parent) { autonavBar.innerHTML = `

${UpNext_text_string}

`; } if (WATCH_AUTOPLAY_SWITCH_expflag == "true") { - autonavBar.insertAdjacentHTML("beforeend",`

Autoplay

`); + autonavBar.insertAdjacentHTML("beforeend",`

Autoplay

`); } itemSectRelated.querySelector(".lazy-list").appendChild(autonavBar); @@ -651,6 +651,7 @@ function renderWatchPage(parent) { parent.innerHTML = ""; parent.appendChild(scwnr); + document.getElementById('autoplay-toggle-button').setAttribute('aria-pressed',localStorage.getItem('WATCH_AUTOPLAY_SWITCH_INTERNAL')); } else { getWatchData.onerror(); } From 850f461c9bc51c5305de77345d607241876d1a03 Mon Sep 17 00:00:00 2001 From: YacineYax <117831802+Yacine-Book@users.noreply.github.com> Date: Sat, 31 Jan 2026 08:41:54 +0300 Subject: [PATCH 073/105] Improved notifications/toast CSS to look accurate --- app/2015YTm.css | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/app/2015YTm.css b/app/2015YTm.css index 22a55a02..c2942bec 100644 --- a/app/2015YTm.css +++ b/app/2015YTm.css @@ -6117,15 +6117,22 @@ html.style-2013.dark.dark-21 { .style-2013.dark.dark-21 .ytm15-video-owner .material-button-container[data-style="BRAND"] .material-button { background: linear-gradient(#323232, #252525); } +/* Implementation by legoskid */ .notification { position: fixed; bottom: 0; - left: 50%; - transform: translate(-50%, 120%); - transition: transform .35s cubic-bezier(.22,.9,.35,1), opacity .25s; + /* left: 50%; */ + left: 0; + right: 0; + transform: translate(0, 100%); + /* transition: transform .35s cubic-bezier(.22,.9,.35,1), opacity .25s; */ + transition: transform .3s ease-in-out, opacity .25s; display: inline-block; - max-width: calc(100% - 40px); - padding: 20px 32px; + display: block; + /* max-width: calc(100% - 40px); */ + max-width: 400px; + /* padding: 20px 32px; */ + padding: 14px 24px; background: #2e2e2e; color: #f1f1f1; border-radius: unset; @@ -6136,9 +6143,10 @@ html.style-2013.dark.dark-21 { font-size: 15px; z-index: 9999; white-space: normal; + margin: auto; } .notification.notification-show { - transform: translate(-50%, 0); + transform: translate(0, 0); } div#offline-bar { display: flex; @@ -6162,3 +6170,4 @@ div#offline-bar.offline-bar-show { div#offline-bar.offline-bar-online { background:green; } + From 6eed27c613140c8bfb4fa3c4f32957c7fec639f4 Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Tue, 3 Feb 2026 11:30:50 -0800 Subject: [PATCH 074/105] Expand share notification i googled it --- app/watch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/watch.js b/app/watch.js index 7d267754..534481dd 100644 --- a/app/watch.js +++ b/app/watch.js @@ -33,7 +33,7 @@ function renderWatchPage(parent) { } } } else { - showNotification("Web Share API not supported!"); + showNotification("Web Share API not supported!\nTry on Android 6.0+!"); } } function saveVideo(videoId,url,lengthSeconds,title,author,authorId,publishedText,viewCount) { From c75ed6d9a3a0d658a3426f62b8e0dea8f7d1615e Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Tue, 3 Feb 2026 12:03:54 -0800 Subject: [PATCH 075/105] HEADER_ALWAYS_SHOW_YOUTUBE_TITLE Just for the home --- app/2015ytm.js | 1 + app/home.js | 8 ++++---- app/settings.js | 9 +++++++++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/app/2015ytm.js b/app/2015ytm.js index df0bd6f4..aa45d7a0 100644 --- a/app/2015ytm.js +++ b/app/2015ytm.js @@ -198,6 +198,7 @@ PIVOT_TRENDING_IS_EXPLORE_expflag = localStorage.getItem("PIVOT_TRENDING_IS_EXPL PIVOT_LIBRARY_UPDATED_ICON_expflag = localStorage.getItem("PIVOT_LIBRARY_UPDATED_ICON"); WATCH_SAVE_UPDATED_ICON_expflag = localStorage.getItem("WATCH_SAVE_UPDATED_ICON"); WATCH_COLLAPSABLE_COMMENTS_expflag = localStorage.getItem("WATCH_COLLAPSABLE_COMMENTS"); +HEADER_ALWAYS_SHOW_YOUTUBE_TITLE_expflag = localStorage.getItem("HEADER_ALWAYS_SHOW_YOUTUBE_TITLE"); newErrorHtml = `
`; + settingsSaveAndLoad.innerHTML = `
`; const innerSettingsPageCont = document.createElement("div"); innerSettingsPageCont.classList.add("inner-settings-page-container"); From 44c352e2b756146a6b17c9212edccbc83ff162c8 Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Fri, 27 Feb 2026 12:26:16 -0800 Subject: [PATCH 098/105] Add a proper blank library page remove "This shelf is empty" notification --- app/home.js | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/app/home.js b/app/home.js index 2a07ffa1..d784785e 100644 --- a/app/home.js +++ b/app/home.js @@ -294,7 +294,7 @@ function renderData() { spinner.setAttribute("hidden", ""); if (!Array.isArray(data)) { - showNotification('This shelf is empty'); + blankLibraryPage();//showNotification('This shelf is empty'); return; } @@ -926,3 +926,43 @@ function subscriptionsPage() { }); } } + +function blankLibraryPage() { + const page = document.createElement("page"); + + const tabContainer = document.createElement("div"); + tabContainer.classList.add('tabs-content-container'); + + const tabContent = document.createElement("div"); + tabContent.classList.add('tab-content'); + tabContent.setAttribute("tab-identifier", ""); + + const subscriptionsPage = document.createElement("div"); + + const section = document.createElement("div"); + section.classList.add('section-list'); + + const sectLazyList = document.createElement("div"); + sectLazyList.classList.add('lazy-list'); + sectLazyList.innerHTML = `

You can add videos to this Library for safe keeping. Enable WATCH_SAVE_BUTTON in YTm15 Experimental Flags. You also need WATCH_ENABLE_NEW_UI enabled, in the future a save button will be added to the player.

`; + section.appendChild(sectLazyList); + + const parent = document.querySelector(".page-container"); + parent.appendChild(page); + page.appendChild(tabContainer); + tabContainer.appendChild(tabContent); + tabContent.appendChild(subscriptionsPage); + subscriptionsPage.appendChild(section); + + var title = document.querySelector("title"); + title.textContent = 'Subscriptions'; + + if (APP_DEMATERIALIZE_UI_expflag == "true") { + Array.from(sectLazyList.querySelectorAll(".ap-shelf")).forEach(function(item){ + item.classList.add('card'); + }); + Array.from(sectLazyList.querySelectorAll(".about-page-bottom-title")).forEach(function(item){ + item.classList.add('card'); + }); + } +} From 4f24c47c9cb3b74b863a71d6b0e6fb4063f366cf Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Fri, 27 Feb 2026 12:30:02 -0800 Subject: [PATCH 099/105] Expand on the compatibility note in the settings of the Install Ytm15 tab --- app/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/settings.js b/app/settings.js index 3a0db3ab..d527c8e7 100644 --- a/app/settings.js +++ b/app/settings.js @@ -304,7 +304,7 @@ function settingsPage() { headerTitle.textContent = InstallYtm15_text_string; title.textContent = InstallYtm15_text_string + ' - 2015YouTube'; - settingsPage.innerHTML=`
2015YouTube
ytm15.github.io
Get as a Webapp
Modern devices:
  1. Open Safari (iOS)/Chrome (Android)
  2. Go to https://ytm15.github.io/app
  3. Press "share"/the three dots
  4. Press "Add to Home Screen"
YTm15 is not supported on ≤iOS 9. Alternatively, there are websites online that claim to be able to insert a website into an APK.`; + settingsPage.innerHTML=`
2015YouTube
ytm15.github.io
Get as a Webapp
Modern devices:
  1. Open Safari (iOS)/Chrome (Android)
  2. Go to https://ytm15.github.io/app
  3. Press "share"/the three dots
  4. Press "Add to Home Screen"
YTm15 is not supported on ≤iOS 9, or maybe some old versions of Android, if you are using the native WebView/Browser, but this shouldn't be an issue as you can install a newer browser APK. Hopefully, that will change too. Alternatively, there are websites online that can let you turn a website into an APK, but note what I said if it uses WebView.`; } if (window.location.hash.split("/").join(',').split("?").join(',').split(',').slice(1, 2)[0] == "expflags") { /* innerSettingsPageCont.innerHTML = ` From afe048d760a195a06be69b5a86f06129f6b7cee7 Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Fri, 27 Feb 2026 12:36:10 -0800 Subject: [PATCH 100/105] Remove search tab from channel page rest in peace --- app/channel.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/channel.js b/app/channel.js index c7ea4d8b..9b3b6dc4 100644 --- a/app/channel.js +++ b/app/channel.js @@ -236,6 +236,9 @@ function channelPage() { if (item == "live") { item = "streams"; } + if (item == "search") { + return; + } tab.setAttribute('aria-label', item); if (item == "streams") { tab.setAttribute('aria-label', 'live'); From 1a00b7a4f70c8cbbd837152d27dda91f936604bb Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Mon, 2 Mar 2026 12:26:42 -0800 Subject: [PATCH 101/105] WATCH_CONDENSE_COMMENT_BUTTONS Gets rid of the huge gaps if you're on landscape on the comment section --- app/2015YTm.css | 6 ++++++ app/2015ytm.js | 7 +++++++ app/settings.js | 9 +++++++++ 3 files changed, 22 insertions(+) diff --git a/app/2015YTm.css b/app/2015YTm.css index d8f80340..5d096b86 100644 --- a/app/2015YTm.css +++ b/app/2015YTm.css @@ -3735,6 +3735,12 @@ button.comment-icon-button { .comment-section .lazy-list { transition: transform .35s cubic-bezier(.22,.9,.35,1); } +.condense-comment-buttons .comment-details { + display:inline-flex; +} +.condense-comment-buttons .comment-details #cm-icon-dislike { + margin-left:10px; +} /* Community posts */ [data-is-beta="true"] .posts-header-text::after { diff --git a/app/2015ytm.js b/app/2015ytm.js index b8d10c67..f68d9973 100644 --- a/app/2015ytm.js +++ b/app/2015ytm.js @@ -201,6 +201,7 @@ WATCH_COLLAPSABLE_COMMENTS_expflag = localStorage.getItem("WATCH_COLLAPSABLE_COM HEADER_ALWAYS_SHOW_YOUTUBE_TITLE_expflag = localStorage.getItem("HEADER_ALWAYS_SHOW_YOUTUBE_TITLE"); HEADER_MENU_BUTTON_expflag = localStorage.getItem("HEADER_MENU_BUTTON"); APP_NO_INTERNET_POPUP_NEW_STYLE_expflag = localStorage.getItem("APP_NO_INTERNET_POPUP_NEW_STYLE"); +WATCH_CONDENSE_COMMENT_BUTTONS_expflag = localStorage.getItem("WATCH_CONDENSE_COMMENT_BUTTONS"); newErrorHtml = ` -${item.likeCount.toLocaleString()} +${(WATCH_FORMAT_LIKE_COUNTS_expflag == "true") ? new Intl.NumberFormat('en-US', {notation: "compact",compactDisplay: "short"}).format(item.likeCount) : item.likeCount.toLocaleString()}
@@ -852,7 +856,7 @@ ${pinnedCMBadge}
-${cmReplyCount} +${(WATCH_FORMAT_LIKE_COUNTS_expflag == "true") ? new Intl.NumberFormat('en-US', {notation: "compact",compactDisplay: "short"}).format(cmReplyCount) : cmReplyCount}
`; diff --git a/app/settings.js b/app/settings.js index 27389e8f..30e64e49 100644 --- a/app/settings.js +++ b/app/settings.js @@ -998,6 +998,15 @@ function settingsPage() { "pressed-default": false, "disabled": false, "lsitem": "WATCH_CONDENSE_COMMENT_BUTTONS" + }, + { + "type": "boolean", + "title": "WATCH_FORMAT_LIKE_COUNTS", + "subtitle": "", + "pressed": WATCH_FORMAT_LIKE_COUNTS_expflag == "true", + "pressed-default": false, + "disabled": false, + "lsitem": "WATCH_FORMAT_LIKE_COUNTS" } ]; settingBlocks.forEach(function(item){ diff --git a/app/watch.js b/app/watch.js index f979222f..5ac4884d 100644 --- a/app/watch.js +++ b/app/watch.js @@ -405,6 +405,9 @@ function renderWatchPage(parent) { videoMetadataLikeCount = "Like"; videoMetadataLikeCountAL = "Like this video"; }; + if (WATCH_FORMAT_LIKE_COUNTS_expflag == "true") { + videoMetadataLikeCount = new Intl.NumberFormat('en-US', {notation: "compact",compactDisplay: "short"}).format(videoMetadataLikeCount.replace(/\D/g, "")); + } mtrlBtnCont.innerHTML = `` @@ -434,7 +437,7 @@ function renderWatchPage(parent) { videoMetadataDislikeCount = response.dislikes.toLocaleString(); videoMetadataDislikeCountAL = "Dislike this video along with " + videoMetadataDislikeCount + " other people"; mtrlBtnContDislike.querySelector("button").ariaLabel = videoMetadataDislikeCountAL; - mtrlBtnContDislike.querySelector(".button-text").innerHTML = videoMetadataDislikeCount; + mtrlBtnContDislike.querySelector(".button-text").innerHTML = (WATCH_FORMAT_LIKE_COUNTS_expflag == "true") ? new Intl.NumberFormat('en-US', {notation: "compact",compactDisplay: "short"}).format(videoMetadataDislikeCount.replace(/\D/g, "")) : videoMetadataDislikeCount; } else { console.error("An error occurred with this operation (" + getDislikeCount.status + ")"); } From b86983658cd80878de1657fdd3541689dba6fae7 Mon Sep 17 00:00:00 2001 From: YacineYax <117831802+Yacine-Book@users.noreply.github.com> Date: Wed, 4 Mar 2026 01:44:29 +0300 Subject: [PATCH 103/105] Made the video player return the last array it detects for the thumbnail This works via the "length" function --- app/player.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/player.js b/app/player.js index 8e1f43eb..4600c21c 100644 --- a/app/player.js +++ b/app/player.js @@ -861,7 +861,8 @@ playerxhttpr.onload = function() { playerxhttpr.onerror(); return; } - video.poster = data.thumbnail[3].url; + /* video.poster = data.thumbnail[3].url; */ + video.poster = data.thumbnail[data.thumbnail.length - 1].url; video.innerHTML = ``; video.dataset.title = data.title; /* storyboardURL = "https://inv.tux.pizza" + data.storyboards[2].url; */ @@ -914,4 +915,5 @@ sbxhttpr.onload = function() { playerxhttpr.onerror(); } }; -}; \ No newline at end of file + +}; From b9dda15448e3f3f8cf036d103c0e8ac68eb0df3f Mon Sep 17 00:00:00 2001 From: legoskid <94498086+legoskid@users.noreply.github.com> Date: Thu, 5 Mar 2026 12:23:10 -0800 Subject: [PATCH 104/105] APP_IOS_SYSTEM_FONT I know it is not exclusive to iOS --- app/2015YTm.css | 3 +++ app/2015ytm.js | 7 +++++++ app/settings.js | 9 +++++++++ 3 files changed, 19 insertions(+) diff --git a/app/2015YTm.css b/app/2015YTm.css index 5d096b86..f30bf691 100644 --- a/app/2015YTm.css +++ b/app/2015YTm.css @@ -4272,6 +4272,9 @@ label.radio-label { .helvetica-neue { font-family: 'HelveticaNeue-Light','Helvetica Neue Light','Helvetica Neue',Helvetica,Arial,sans-serif !important; } +.system-font { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Oxygen-Sans, Ubuntu, Cantarell, Roboto, "Helvetica Neue", sans-serif !important; +} /*New error screen*/ .tap-to-retry .error-content { display:unset; diff --git a/app/2015ytm.js b/app/2015ytm.js index d36f2747..870b9ad8 100644 --- a/app/2015ytm.js +++ b/app/2015ytm.js @@ -203,6 +203,7 @@ HEADER_MENU_BUTTON_expflag = localStorage.getItem("HEADER_MENU_BUTTON"); APP_NO_INTERNET_POPUP_NEW_STYLE_expflag = localStorage.getItem("APP_NO_INTERNET_POPUP_NEW_STYLE"); WATCH_CONDENSE_COMMENT_BUTTONS_expflag = localStorage.getItem("WATCH_CONDENSE_COMMENT_BUTTONS"); WATCH_FORMAT_LIKE_COUNTS_expflag = localStorage.getItem("WATCH_FORMAT_LIKE_COUNTS"); +APP_IOS_SYSTEM_FONT_expflag = localStorage.getItem("APP_IOS_SYSTEM_FONT"); newErrorHtml = `