YT July 2018 - November 2020 script

use: https://userstyles.world/style/6311/youtube-late-2019-mid-2020-polymer-layout and https://userstyles.world/style/6312/youtube-late-2017-mid-2019-polymer-colors.

  1. // ==UserScript==
  2. // @name YT July 2018 - November 2020 script
  3. // @version 1.5.1
  4. // @description use: https://userstyles.world/style/6311/youtube-late-2019-mid-2020-polymer-layout and https://userstyles.world/style/6312/youtube-late-2017-mid-2019-polymer-colors.
  5. // @author Manchuliit
  6. // @license none
  7. // @match *://*.youtube.com/*
  8. // @namespace https://greasyfork.org/en/users/933798
  9. // @icon https://www.youtube.com/favicon.ico
  10. // @run-at document-start
  11. // @grant none
  12. // ==/UserScript==
  13. // Attributes to remove from <html>
  14. const ATTRS = [
  15. "system-icons",
  16. "typography",
  17. "typography-spacing"
  18. ];
  19. // Regular config keys.
  20. const CONFIGS = {
  21. BUTTON_REWORK: false
  22. }
  23. // Experiment flags.
  24. const EXPFLAGS = {
  25. kevlar_updated_logo_icons: false,
  26. kevlar_updated_icons: false,
  27. kevlar_system_icons: false,
  28. kevlar_watch_color_update: false,
  29. desktop_mic_background: false,
  30. kevlar_refresh_on_theme_change: false, //disable reload when changing theme
  31. kevlar_unavailable_video_error_ui_client: false, //old video unavailable ui
  32. kevlar_watch_metadata_refresh: false,
  33. kevlar_watch_modern_metapanel: false,
  34. kevlar_watch_modern_panels: false,
  35. web_rounded_containers: false,
  36. web_rounded_thumbnails: false,
  37. web_modern_dialogs: false,
  38. web_modern_chips: false,
  39. web_modern_subscribe: false,
  40. web_modern_buttons: false,
  41. web_modern_playlists: false,
  42. enable_programmed_playlist_redesign: false,
  43. web_amsterdam_playlists: false,
  44. web_searchbar_style: "default",
  45. web_button_rework: false,
  46. web_darker_dark_theme: false,
  47. web_guide_ui_refresh: false,
  48. web_sheets_ui_refresh: false,
  49. web_snackbar_ui_refresh: false,
  50. web_segmented_like_dislike_button: false,
  51. web_animated_like: false,
  52. web_animated_like_lazy_load: false,
  53. kevlar_use_ytd_player: false
  54. }
  55. // Player flags
  56. // !!! USE STRINGS FOR VALUES !!!
  57. // For example: "true" instead of true
  58. const PLYRFLAGS = {
  59. web_player_move_autonav_toggle: "false"
  60. }
  61. class YTP {
  62. static observer = new MutationObserver(this.onNewScript);
  63. static _config = {};
  64. static isObject(item) {
  65. return (item && typeof item === "object" && !Array.isArray(item));
  66. }
  67. static mergeDeep(target, ...sources) {
  68. if (!sources.length) return target;
  69. const source = sources.shift();
  70. if (this.isObject(target) && this.isObject(source)) {
  71. for (const key in source) {
  72. if (this.isObject(source[key])) {
  73. if (!target[key]) Object.assign(target, { [key]: {} });
  74. this.mergeDeep(target[key], source[key]);
  75. } else {
  76. Object.assign(target, { [key]: source[key] });
  77. }
  78. }
  79. }
  80. return this.mergeDeep(target, ...sources);
  81. }
  82. static onNewScript(mutations) {
  83. for (var mut of mutations) {
  84. for (var node of mut.addedNodes) {
  85. YTP.bruteforce();
  86. }
  87. }
  88. }
  89. static start() {
  90. this.observer.observe(document, {childList: true, subtree: true});
  91. }
  92. static stop() {
  93. this.observer.disconnect();
  94. }
  95. static bruteforce() {
  96. if (!window.yt) return;
  97. if (!window.yt.config_) return;
  98. this.mergeDeep(window.yt.config_, this._config);
  99. }
  100. static setCfg(name, value) {
  101. this._config[name] = value;
  102. }
  103. static setCfgMulti(configs) {
  104. this.mergeDeep(this._config, configs);
  105. }
  106. static setExp(name, value) {
  107. if (!("EXPERIMENT_FLAGS" in this._config)) this._config.EXPERIMENT_FLAGS = {};
  108. this._config.EXPERIMENT_FLAGS[name] = value;
  109. }
  110. static setExpMulti(exps) {
  111. if (!("EXPERIMENT_FLAGS" in this._config)) this._config.EXPERIMENT_FLAGS = {};
  112. this.mergeDeep(this._config.EXPERIMENT_FLAGS, exps);
  113. }
  114. static decodePlyrFlags(flags) {
  115. var obj = {},
  116. dflags = flags.split("&");
  117. for (var i = 0; i < dflags.length; i++) {
  118. var dflag = dflags[i].split("=");
  119. obj[dflag[0]] = dflag[1];
  120. }
  121. return obj;
  122. }
  123. static encodePlyrFlags(flags) {
  124. var keys = Object.keys(flags),
  125. response = "";
  126. for (var i = 0; i < keys.length; i++) {
  127. if (i > 0) {
  128. response += "&";
  129. }
  130. response += keys[i] + "=" + flags[keys[i]];
  131. }
  132. return response;
  133. }
  134. static setPlyrFlags(flags) {
  135. if (!window.yt) return;
  136. if (!window.yt.config_) return;
  137. if (!window.yt.config_.WEB_PLAYER_CONTEXT_CONFIGS) return;
  138. var conCfgs = window.yt.config_.WEB_PLAYER_CONTEXT_CONFIGS;
  139. if (!("WEB_PLAYER_CONTEXT_CONFIGS" in this._config)) this._config.WEB_PLAYER_CONTEXT_CONFIGS = {};
  140. for (var cfg in conCfgs) {
  141. var dflags = this.decodePlyrFlags(conCfgs[cfg].serializedExperimentFlags);
  142. this.mergeDeep(dflags, flags);
  143. this._config.WEB_PLAYER_CONTEXT_CONFIGS[cfg] = {
  144. serializedExperimentFlags: this.encodePlyrFlags(dflags)
  145. }
  146. }
  147. }
  148. }
  149. window.addEventListener("yt-page-data-updated", function tmp() {
  150. YTP.stop();
  151. for (i = 0; i < ATTRS.length; i++) {
  152. document.getElementsByTagName("html")[0].removeAttribute(ATTRS[i]);
  153. }
  154. window.removeEventListener("yt-page-date-updated", tmp);
  155. });
  156. YTP.start();
  157. YTP.setCfgMulti(CONFIGS);
  158. YTP.setExpMulti(EXPFLAGS);
  159. YTP.setPlyrFlags(PLYRFLAGS);
  160. function $(q) {
  161. return document.querySelector(q);
  162. }
  163. // Fix for Return YouTube Dislike
  164. addEventListener('yt-page-data-updated', function() {
  165. if(!location.pathname.startsWith('/watch')) return;
  166. var lds = $('ytd-video-primary-info-renderer div#top-level-buttons-computed');
  167. var like = $('ytd-video-primary-info-renderer div#segmented-like-button > ytd-toggle-button-renderer');
  168. var share = $('ytd-video-primary-info-renderer div#top-level-buttons-computed > ytd-segmented-like-dislike-button-renderer + ytd-button-renderer');
  169. lds.insertBefore(like, share);
  170. like.setAttribute('class', like.getAttribute('class').replace('ytd-segmented-like-dislike-button-renderer', 'ytd-menu-renderer force-icon-button'));
  171. like.removeAttribute('is-paper-button-with-icon');
  172. like.removeAttribute('is-paper-button');
  173. like.setAttribute('style-action-button', '');
  174. like.setAttribute('is-icon-button', '');
  175. like.querySelector('a').insertBefore(like.querySelector('yt-formatted-string'), like.querySelector('tp-yt-paper-tooltip'));
  176. try { like.querySelector('paper-ripple').remove(); } catch(e) {}
  177. var paper = like.querySelector('tp-yt-paper-button');
  178. paper.removeAttribute('style-target');
  179. paper.removeAttribute('animated');
  180. paper.removeAttribute('elevation');
  181. like.querySelector('a').insertBefore(paper.querySelector('yt-icon'), like.querySelector('yt-formatted-string'));
  182. paper.outerHTML = paper.outerHTML.replace('<tp-yt-paper-button ', '<yt-icon-button ').replace('</tp-yt-paper-button>', '</yt-icon-button>');
  183. paper = like.querySelector('yt-icon-button');
  184. paper.querySelector('button#button').appendChild(like.querySelector('yt-icon'));
  185. var dislike = $('ytd-video-primary-info-renderer div#segmented-dislike-button > ytd-toggle-button-renderer');
  186. lds.insertBefore(dislike, share);
  187. $('ytd-video-primary-info-renderer ytd-segmented-like-dislike-button-renderer').remove();
  188. dislike.setAttribute('class', dislike.getAttribute('class').replace('ytd-segmented-like-dislike-button-renderer', 'ytd-menu-renderer force-icon-button'));
  189. dislike.removeAttribute('has-no-text');
  190. dislike.setAttribute('style-action-button', '');
  191. var dlabel = document.createElement('yt-formatted-stringx');
  192. dlabel.setAttribute('id', 'text');
  193. if(dislike.getAttribute('class').includes('style-default-active'))
  194. dlabel.setAttribute('class', dlabel.getAttribute('class').replace('style-default', 'style-default-active'));
  195. dislike.querySelector('a').insertBefore(dlabel, dislike.querySelector('tp-yt-paper-tooltip'));
  196. $('ytd-video-primary-info-renderer').removeAttribute('flex-menu-enabled');
  197. });
  198. // CSS adjustments
  199. (function() {var css = [
  200. "/*right column*/",
  201. " [d*=\"M14 9V3L22 12L14 21V15C8.44 15 4.78 17.03 2 21C3.11 15.33 6.22 10.13 14 9Z\"] {",
  202. " d: path(\"M11.7333 8.26667V4L19.2 11.4667L11.7333 18.9333V14.56C6.4 14.56 2.66667 16.2667 0 20C1.06667 14.6667 4.26667 9.33333 11.7333 8.26667Z\")",
  203. " }",
  204. " [d*=\"M14 9V3L22 12L14 21V15C8.44 15 4.78 17.03 2 21C3.11 15.33 6.22 10.13 14 9Z\"] {",
  205. " d: path(\"M11.7333 8.26667V4L19.2 11.4667L11.7333 18.9333V14.56C6.4 14.56 2.66667 16.2667 0 20C1.06667 14.6667 4.26667 9.33333 11.7333 8.26667Z\")",
  206. " }"
  207. ].join("\n");
  208. if (typeof GM_addStyle != "undefined") {
  209. GM_addStyle(css);
  210. } else if (typeof PRO_addStyle != "undefined") {
  211. PRO_addStyle(css);
  212. } else if (typeof addStyle != "undefined") {
  213. addStyle(css);
  214. } else {
  215. var node = document.createElement("style");
  216. node.type = "text/css";
  217. node.appendChild(document.createTextNode(css));
  218. var heads = document.getElementsByTagName("head");
  219. if (heads.length > 0) {
  220. heads[0].appendChild(node);
  221. } else {
  222. //
  223. document.documentElement.appendChild(node);
  224. }
  225. }
  226. })();