Restore App Bar

Restores the appbar used in the classic Hitchhiker YouTube layout

目前为 2023-12-13 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Restore App Bar
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.1
  5. // @description Restores the appbar used in the classic Hitchhiker YouTube layout
  6. // @author BowDown097 and whoever made it originally
  7. // @match https://www.youtube.com/*
  8. // @icon https://www.google.com/s2/favicons?domain=youtube.com
  9. // @grant GM_addStyle
  10. // ==/UserScript==
  11.  
  12. if (typeof GM_addStyle !== "function") {
  13. function GM_addStyle(css) {
  14. let style = document.createElement('style');
  15. style.type = 'text/css';
  16. style.appendChild(document.createTextNode(css));
  17. const head = document.getElementsByTagName('head')[0];
  18. if (head) head.appendChild(style);
  19. else document.documentElement.appendChild(style);
  20. }
  21. }
  22.  
  23. function waitForElement(selector) {
  24. return new Promise(resolve => {
  25. if (document.querySelector(selector)) {
  26. return resolve(document.querySelector(selector));
  27. }
  28. const observer = new MutationObserver(mutations => {
  29. if (document.querySelector(selector)) {
  30. resolve(document.querySelector(selector));
  31. observer.disconnect();
  32. }
  33. });
  34. observer.observe(document, {
  35. childList: true,
  36. subtree: true
  37. });
  38. });
  39. }
  40.  
  41. function navigate(url, browseId) {
  42. document.querySelector("ytd-app").insertAdjacentHTML("beforeend", '<ytd-guide-entry-renderer class="ytd-guide-entry-renderer navigateTemp"></ytd-guide-entry-renderer>');
  43. document.querySelector(".navigateTemp").data = {};
  44. document.querySelector(".navigateTemp").data.navigationEndpoint = {
  45. "clickTrackingParams": "CJEBELUsGAIiEwi3y-qlp9bxAhVchuUHHSLSCts=",
  46. "commandMetadata": {
  47. "webCommandMetadata": {
  48. "url": url,
  49. "webPageType": "WEB_PAGE_TYPE_BROWSE",
  50. "rootVe": 6827,
  51. "apiUrl": "/youtubei/v1/browse"
  52. }
  53. },
  54. "browseEndpoint": {
  55. "browseId": browseId
  56. }
  57. };
  58. document.querySelector(".navigateTemp").click();
  59. document.querySelector(".navigateTemp").remove();
  60. }
  61.  
  62. function navBar() {
  63. const hasMyChannel = document.querySelector("#items > ytd-guide-entry-renderer:nth-child(2) .guide-icon").getComputedStyleValue("content") == "url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAOFJREFUeJztlL0Ng0AMhWlSZ5QMkU0o6KjpIlLAHSNkgkyQLbICA6RPT/hEAk8WxwWJKoolS5Z/3vnZhiT5y0cuvtiXZXny3t/run6i2PiIrQKrqvPROdf22gW0JWcN2FhMV3mRH1BsjUVBoaKd9TQ7pYeNTztdpM98tAPmZnPwaQ41QUBLaaDl0mkcLrVxaoKA9nUtmnssxCIG2DZNc0PnNr8IqF0AwGZtDr43eJyyLOWRZdkulEeMnOhS9Gx0GVZkOctnMyRPh93P5wpFOkKx8X192AZ0m09P6W/2c/hteQFIL1T2NRIk0wAAAABJRU5ErkJggg==\")";
  64. let headers = [{
  65. text: document.querySelector("ytd-guide-entry-renderer:first-child yt-formatted-string").innerHTML
  66. }, {
  67. text: hasMyChannel ? document.querySelector("ytd-guide-entry-renderer:nth-child(3) yt-formatted-string").innerHTML : document.querySelector("ytd-guide-entry-renderer:nth-child(2) yt-formatted-string").innerHTML
  68. }, {
  69. text: hasMyChannel ? document.querySelector("ytd-guide-entry-renderer:nth-child(5) yt-formatted-string").innerHTML : document.querySelector("ytd-guide-entry-renderer:nth-child(4) yt-formatted-string").innerHTML
  70. }];
  71. let appbar = document.createElement("div");
  72. let appbarNav = document.createElement("ul");
  73. for (const header of headers)
  74. {
  75. let item = document.createElement("li");
  76. let text = document.createElement("span");
  77. text.href = header.href;
  78. text.innerHTML = header.text;
  79. item.appendChild(text);
  80. appbarNav.appendChild(item);
  81. }
  82. let home = document.querySelector(`ytd-browse[role="main"][page-subtype="home"]`);
  83. let trending = document.querySelector(`ytd-browse[role="main"][page-subtype="trending"]`);
  84. let subscriptions = document.querySelector(`ytd-browse[role="main"][page-subtype="subscriptions"]`);
  85. home?.appendChild(appbar).appendChild(appbarNav);
  86. trending?.appendChild(appbar).appendChild(appbarNav);
  87. subscriptions?.appendChild(appbar).appendChild(appbarNav);
  88. appbar.className = "ytcp-main-appbar";
  89. appbarNav.className = "ytcp-appbar-nav";
  90. appbarNav.childNodes[0].className = "ytcp-nav-home ytcp-nav-item";
  91. appbarNav.childNodes[1].className = "ytcp-nav-trending ytcp-nav-item";
  92. appbarNav.childNodes[2].className = "ytcp-nav-subs ytcp-nav-item";
  93. appbarNav.childNodes[0].addEventListener("click", () => navigate("/", "FEwhat_to_watch"));
  94. appbarNav.childNodes[1].addEventListener("click", () => navigate("/feed/trending", "FEexplore"));
  95. appbarNav.childNodes[2].addEventListener("click", () => navigate("/feed/subscriptions", "FEsubscriptions"));
  96. }
  97.  
  98. function setupNavbar() {
  99. if (!["/", "/feed/trending", "/feed/subscriptions"].includes(window.location.pathname)) return;
  100. waitForElement("ytd-guide-entry-renderer").then(() => navBar());
  101. document.querySelector("[hidden] .ytcp-main-appbar")?.remove();
  102. }
  103.  
  104. (function() {
  105. 'use strict';
  106. window.addEventListener("yt-page-data-updated", setupNavbar, false);
  107. GM_addStyle(`
  108. .ytcp-main-appbar {
  109. margin: -12px;
  110. width: 100%;
  111. text-align: center;
  112. line-height: 40px;
  113. height: 40px;
  114. border-bottom: 1px solid #e8e8e8;
  115. border-left: 1px solid #e8e8e8;
  116. background-color: #fff;
  117. position: fixed;
  118. z-index: 2001;
  119. font-size: 13px;
  120. font-family: Roboto, arial, sans-serif;
  121. }
  122.  
  123. html:not([dark]) .ytcp-nav-item {
  124. display: inline-block;
  125. margin-left: 30px;
  126. }
  127.  
  128. html:not([dark]) .ytcp-nav-item span {
  129. display: inline-block;
  130. color: #666;
  131. text-decoration: none;
  132. cursor: pointer;
  133. }
  134.  
  135. html:not([dark]) .ytcp-nav-item span:hover {
  136. box-shadow: inset 0 -3px #cc181e;
  137. }
  138.  
  139. html:not([dark]) [page-subtype="home"] .ytcp-nav-home span,
  140. html:not([dark]) [page-subtype="subscriptions"] .ytcp-nav-subs span,
  141. html:not([dark]) [page-subtype="trending"] .ytcp-nav-trending span {
  142. box-shadow: inset 0 -3px #cc181e;
  143. color: #333;
  144. }
  145.  
  146. html:not([dark]) .ytcp-appbar-nav {
  147. display: inline-block;
  148. vertical-align: top;
  149. overflow: hidden;
  150. }
  151.  
  152. html[dark] .ytcp-main-appbar {
  153. width: 100%;
  154. text-align: center;
  155. line-height: 40px;
  156. height: 40px;
  157. background-color: var(--yt-spec-brand-background-primary);
  158. border-bottom: 1px solid var(--yt-spec-10-percent-layer);
  159. border-left: 1px solid var(--yt-spec-10-percent-layer);
  160. position: fixed;
  161. z-index: 2001;
  162. font-size: 13px;
  163. font-family: Roboto, arial, sans-serif;
  164. box-shadow: inset 0 1px #0f0f0f;
  165. }
  166.  
  167. html[dark] .ytcp-nav-item {
  168. display: inline-block;
  169. margin-left: 30px;
  170. }
  171.  
  172. html[dark] .ytcp-nav-item span {
  173. display: inline-block;
  174. color: #8f8f8f;
  175. text-decoration: none;
  176. cursor: pointer;
  177. }
  178.  
  179. html[dark] .ytcp-nav-item span:hover {
  180. box-shadow: inset 0 -3px #dcdcdc;
  181. }
  182.  
  183. html[dark] [page-subtype="home"] .ytcp-nav-home span,
  184. html[dark] [page-subtype="subscriptions"] .ytcp-nav-subs span,
  185. html[dark] [page-subtype="trending"] .ytcp-nav-trending span {
  186. box-shadow: inset 0 -3px #dcdcdc;
  187. color: #c1c1c1;
  188. }
  189.  
  190. html[dark] .ytcp-appbar-nav {
  191. display: inline-block;
  192. vertical-align: top;
  193. overflow: hidden;
  194. }
  195.  
  196. .ytcp-load-more-button {
  197. margin: 20px auto;
  198. display: block;
  199. height: 28px;
  200. border-radius: 2px;
  201. cursor: pointer;
  202. font: 11px Roboto, arial, sans-serif;
  203. padding: 0 10px;
  204. font-weight: 500;
  205. outline: 0;
  206. }
  207.  
  208. .ytcp-load-more-button.ytcp-related {
  209. margin: 0 auto !important;
  210. }
  211.  
  212. html:not([dark]) .ytcp-load-more-button {
  213. border: 1px solid #d3d3d3;
  214. box-shadow: 0 1px 0 rgba(0, 0, 0, .05);
  215. background-color: #f8f8f8;
  216. color: #333;
  217. }
  218.  
  219. html:not([dark]) .ytcp-load-more-button:hover {
  220. border-color: #c6c6c6;
  221. background-color: #f0f0f0;
  222. box-shadow: 0 1px 0 rgba(0, 0, 0, .1);
  223. }
  224.  
  225. html:not([dark]) .ytcp-load-more-button:active {
  226. border-color: #c6c6c6;
  227. background-color: #e9e9e9;
  228. box-shadow: inset 0 1px 0 #ddd;
  229. }
  230.  
  231. html[dark] .ytcp-load-more-button {
  232. border: 0;
  233. background-color: #2e2e2e;
  234. color: #c1c1c1;
  235. }
  236.  
  237. html[dark] .ytcp-load-more-button:hover {
  238. background-color: #353535;
  239. }
  240.  
  241. html[dark] .ytcp-load-more-button:active {
  242. background-color: #292929;
  243. }
  244.  
  245. [page-subtype="home"] ytd-two-column-browse-results-renderer,
  246. [page-subtype="trending"] ytd-two-column-browse-results-renderer,
  247. [page-subtype="subscriptions"] ytd-two-column-browse-results-renderer,
  248. [page-subtype="trending"] tp-yt-app-header {
  249. margin-top: 60px !important;
  250. }`);
  251. })();