YouTube - Non-Rounded Design

This script disables YouTube's new rounded corners (reverts back to the previous layout before 2022 with extra stuff included.)

当前为 2023-02-09 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name YouTube - Non-Rounded Design
  3. // @version 3.2.1
  4. // @description This script disables YouTube's new rounded corners (reverts back to the previous layout before 2022 with extra stuff included.)
  5. // @author Magma_Craft
  6. // @license MIT
  7. // @match https://www.youtube.com/*
  8. // @namespace https://gf.qytechs.cn/en/users/933798
  9. // @icon https://www.youtube.com/favicon.ico
  10. // @run-at document-start
  11. // @grant none
  12. // ==/UserScript==
  13.  
  14. // Attributes to remove from <html>
  15. const ATTRS = [
  16. "darker-dark-theme",
  17. "darker-dark-theme-deprecate"
  18. ];
  19.  
  20. // Regular config keys.
  21. const CONFIGS = {
  22. BUTTON_REWORK: false
  23. }
  24.  
  25. // Experiment flags.
  26. const EXPFLAGS = {
  27. enable_header_channel_handler_ui: false,
  28. kevlar_unavailable_video_error_ui_client: false,
  29. kevlar_refresh_on_theme_change: false,
  30. kevlar_watch_cinematics: false,
  31. kevlar_watch_metadata_refresh: false,
  32. kevlar_watch_modern_metapanel: false,
  33. web_amsterdam_playlists: false,
  34. web_animated_like: false,
  35. web_button_rework: false,
  36. web_button_rework_with_live: false,
  37. web_darker_dark_theme: false,
  38. web_filled_subscribed_button: false,
  39. web_guide_ui_refresh: false,
  40. web_modern_ads: false,
  41. web_modern_buttons: false,
  42. web_modern_chips: false,
  43. web_modern_dialogs: false,
  44. web_modern_playlists: false,
  45. web_modern_subscribe: false,
  46. web_rounded_containers: false,
  47. web_rounded_thumbnails: false,
  48. web_searchbar_style: "default",
  49. web_segmented_like_dislike_button: false,
  50. web_sheets_ui_refresh: false,
  51. web_snackbar_ui_refresh: false
  52. }
  53.  
  54. // Player flags
  55. // !!! USE STRINGS FOR VALUES !!!
  56. // For example: "true" instead of true
  57. const PLYRFLAGS = {
  58. web_rounded_containers: "false",
  59. web_rounded_thumbnails: "false"
  60. }
  61.  
  62. class YTP {
  63. static observer = new MutationObserver(this.onNewScript);
  64.  
  65. static _config = {};
  66.  
  67. static isObject(item) {
  68. return (item && typeof item === "object" && !Array.isArray(item));
  69. }
  70.  
  71. static mergeDeep(target, ...sources) {
  72. if (!sources.length) return target;
  73. const source = sources.shift();
  74.  
  75. if (this.isObject(target) && this.isObject(source)) {
  76. for (const key in source) {
  77. if (this.isObject(source[key])) {
  78. if (!target[key]) Object.assign(target, { [key]: {} });
  79. this.mergeDeep(target[key], source[key]);
  80. } else {
  81. Object.assign(target, { [key]: source[key] });
  82. }
  83. }
  84. }
  85.  
  86. return this.mergeDeep(target, ...sources);
  87. }
  88.  
  89.  
  90. static onNewScript(mutations) {
  91. for (var mut of mutations) {
  92. for (var node of mut.addedNodes) {
  93. YTP.bruteforce();
  94. }
  95. }
  96. }
  97.  
  98. static start() {
  99. this.observer.observe(document, {childList: true, subtree: true});
  100. }
  101.  
  102. static stop() {
  103. this.observer.disconnect();
  104. }
  105.  
  106. static bruteforce() {
  107. if (!window.yt) return;
  108. if (!window.yt.config_) return;
  109.  
  110. this.mergeDeep(window.yt.config_, this._config);
  111. }
  112.  
  113. static setCfg(name, value) {
  114. this._config[name] = value;
  115. }
  116.  
  117. static setCfgMulti(configs) {
  118. this.mergeDeep(this._config, configs);
  119. }
  120.  
  121. static setExp(name, value) {
  122. if (!("EXPERIMENT_FLAGS" in this._config)) this._config.EXPERIMENT_FLAGS = {};
  123.  
  124. this._config.EXPERIMENT_FLAGS[name] = value;
  125. }
  126.  
  127. static setExpMulti(exps) {
  128. if (!("EXPERIMENT_FLAGS" in this._config)) this._config.EXPERIMENT_FLAGS = {};
  129.  
  130. this.mergeDeep(this._config.EXPERIMENT_FLAGS, exps);
  131. }
  132.  
  133. static decodePlyrFlags(flags) {
  134. var obj = {},
  135. dflags = flags.split("&");
  136.  
  137. for (var i = 0; i < dflags.length; i++) {
  138. var dflag = dflags[i].split("=");
  139. obj[dflag[0]] = dflag[1];
  140. }
  141.  
  142. return obj;
  143. }
  144.  
  145. static encodePlyrFlags(flags) {
  146. var keys = Object.keys(flags),
  147. response = "";
  148.  
  149. for (var i = 0; i < keys.length; i++) {
  150. if (i > 0) {
  151. response += "&";
  152. }
  153. response += keys[i] + "=" + flags[keys[i]];
  154. }
  155.  
  156. return response;
  157. }
  158.  
  159. static setPlyrFlags(flags) {
  160. if (!window.yt) return;
  161. if (!window.yt.config_) return;
  162. if (!window.yt.config_.WEB_PLAYER_CONTEXT_CONFIGS) return;
  163. var conCfgs = window.yt.config_.WEB_PLAYER_CONTEXT_CONFIGS;
  164. if (!("WEB_PLAYER_CONTEXT_CONFIGS" in this._config)) this._config.WEB_PLAYER_CONTEXT_CONFIGS = {};
  165.  
  166. for (var cfg in conCfgs) {
  167. var dflags = this.decodePlyrFlags(conCfgs[cfg].serializedExperimentFlags);
  168. this.mergeDeep(dflags, flags);
  169. this._config.WEB_PLAYER_CONTEXT_CONFIGS[cfg] = {
  170. serializedExperimentFlags: this.encodePlyrFlags(dflags)
  171. }
  172. }
  173. }
  174. }
  175.  
  176. window.addEventListener("yt-page-data-updated", function tmp() {
  177. YTP.stop();
  178. for (i = 0; i < ATTRS.length; i++) {
  179. document.getElementsByTagName("html")[0].removeAttribute(ATTRS[i]);
  180. }
  181. window.removeEventListener("yt-page-date-updated", tmp);
  182. });
  183.  
  184. YTP.start();
  185.  
  186. YTP.setCfgMulti(CONFIGS);
  187. YTP.setExpMulti(EXPFLAGS);
  188. YTP.setPlyrFlags(PLYRFLAGS);
  189.  
  190. function $(q) {
  191. return document.querySelector(q);
  192. }
  193.  
  194. // Re-add 'Explore' tab in sidebar (it also replaces the 'Shorts' tab)
  195. function waitForElm(selector) {
  196. return new Promise(resolve => {
  197. if (document.querySelector(selector)) {
  198. return resolve(document.querySelector(selector));
  199. }
  200.  
  201. const observer = new MutationObserver(mutations => {
  202. if (document.querySelector(selector)) {
  203. resolve(document.querySelector(selector));
  204. observer.disconnect();
  205. }
  206. });
  207.  
  208. observer.observe(document.body, {
  209. childList: true,
  210. subtree: true
  211. });
  212. });
  213. }
  214.  
  215. function restoreTrending() {
  216.  
  217. var trendingData = {
  218. "navigationEndpoint": {
  219. "clickTrackingParams": "CBwQtSwYASITCNqYh-qO_fACFcoRrQYdP44D9Q==",
  220. "commandMetadata": {
  221. "webCommandMetadata": {
  222. "url": "/feed/explore",
  223. "webPageType": "WEB_PAGE_TYPE_BROWSE",
  224. "rootVe": 6827,
  225. "apiUrl": "/youtubei/v1/browse"
  226. }
  227. },
  228. "browseEndpoint": {
  229. "browseId": "FEtrending"
  230. }
  231. },
  232. "icon": {
  233. "iconType": "EXPLORE"
  234. },
  235. "trackingParams": "CBwQtSwYASITCNqYh-qO_fACFcoRrQYdP44D9Q==",
  236. "formattedTitle": {
  237. "simpleText": "Explore"
  238. },
  239. "accessibility": {
  240. "accessibilityData": {
  241. "label": "Explore"
  242. }
  243. },
  244. "isPrimary": true
  245. };
  246.  
  247. var guidetemplate = `<ytd-guide-entry-renderer class="style-scope ytd-guide-section-renderer" is-primary="" line-end-style="none"><!--css-build:shady--><a id="endpoint" class="yt-simple-endpoint style-scope ytd-guide-entry-renderer" tabindex="-1" role="tablist"><tp-yt-paper-item role="tab" class="style-scope ytd-guide-entry-renderer" tabindex="0" aria-disabled="false"><!--css-build:shady--><yt-icon class="guide-icon style-scope ytd-guide-entry-renderer" disable-upgrade=""></yt-icon><yt-img-shadow height="24" width="24" class="style-scope ytd-guide-entry-renderer" disable-upgrade=""></yt-img-shadow><yt-formatted-string class="title style-scope ytd-guide-entry-renderer"><!--css-build:shady--></yt-formatted-string><span class="guide-entry-count style-scope ytd-guide-entry-renderer"></span><yt-icon class="guide-entry-badge style-scope ytd-guide-entry-renderer" disable-upgrade=""></yt-icon><div id="newness-dot" class="style-scope ytd-guide-entry-renderer"></div></tp-yt-paper-item></a><yt-interaction class="style-scope ytd-guide-entry-renderer"><!--css-build:shady--><div class="stroke style-scope yt-interaction"></div><div class="fill style-scope yt-interaction"></div></yt-interaction></ytd-guide-entry-renderer>`;
  248. document.querySelector(`#items > ytd-guide-entry-renderer:nth-child(2)`).data = trendingData;
  249.  
  250. }
  251.  
  252.  
  253. waitForElm("#items.ytd-guide-section-renderer").then((elm) => {
  254. restoreTrending();
  255. });
  256.  
  257. // Fix for like-dislike ratio (including action buttons)
  258. const abtnconfig = {
  259. unsegmentLikeButton: false,
  260. noFlexibleItems: true
  261. };
  262.  
  263. function updateBtns() {
  264. var watchFlexy = document.querySelector("ytd-watch-flexy");
  265. var results = watchFlexy.data.contents.twoColumnWatchNextResults.results.results.contents;
  266.  
  267. for (var i = 0; i < results.length; i++) {
  268. if (results[i].videoPrimaryInfoRenderer) {
  269. var actions = results[i].videoPrimaryInfoRenderer.videoActions.menuRenderer;
  270.  
  271. if (abtnconfig.unsegmentLikeButton) {
  272. if (actions.topLevelButtons[0].segmentedLikeDislikeButtonRenderer) {
  273. var segmented = actions.topLevelButtons[0].segmentedLikeDislikeButtonRenderer;
  274. actions.topLevelButtons.splice(0, 1);
  275. actions.topLevelButtons.unshift(segmented.dislikeButton);
  276. actions.topLevelButtons.unshift(segmented.likeButton);
  277. }
  278. }
  279.  
  280. if (abtnconfig.noFlexibleItems) {
  281. for (var i = 0; i < actions.flexibleItems.length; i++) {
  282. actions.topLevelButtons.push(actions.flexibleItems[i].menuFlexibleItemRenderer.topLevelButton);
  283. }
  284.  
  285. delete actions.flexibleItems
  286. }
  287. }
  288. }
  289.  
  290. var temp = watchFlexy.data;
  291. watchFlexy.data = {};
  292. watchFlexy.data = temp;
  293. }
  294.  
  295. document.addEventListener("yt-page-data-updated", (e) => {
  296. if (e.detail.pageType == "watch") {
  297. updateBtns();
  298. }
  299. });
  300.  
  301. addEventListener('yt-page-data-updated', function() {
  302. if(!location.pathname.startsWith('/watch')) return;
  303.  
  304. var lds = $('ytd-video-primary-info-renderer div#top-level-buttons-computed');
  305. var like = $('ytd-video-primary-info-renderer div#segmented-like-button > ytd-toggle-button-renderer');
  306. var share = $('ytd-video-primary-info-renderer div#top-level-buttons-computed > ytd-segmented-like-dislike-button-renderer + ytd-button-renderer');
  307.  
  308. lds.insertBefore(like, share);
  309.  
  310. like.setAttribute('class', like.getAttribute('class').replace('ytd-segmented-like-dislike-button-renderer', 'ytd-menu-renderer force-icon-button'));
  311. like.removeAttribute('is-paper-button-with-icon');
  312. like.removeAttribute('is-paper-button');
  313. like.setAttribute('style-action-button', '');
  314. like.setAttribute('is-icon-button', '');
  315. like.querySelector('a').insertBefore(like.querySelector('yt-formatted-string'), like.querySelector('tp-yt-paper-tooltip'));
  316. try { like.querySelector('paper-ripple').remove(); } catch(e) {}
  317. var paper = like.querySelector('tp-yt-paper-button');
  318. paper.removeAttribute('style-target');
  319. paper.removeAttribute('animated');
  320. paper.removeAttribute('elevation');
  321. like.querySelector('a').insertBefore(paper.querySelector('yt-icon'), like.querySelector('yt-formatted-string'));
  322. paper.outerHTML = paper.outerHTML.replace('<tp-yt-paper-button ', '<yt-icon-button ').replace('</tp-yt-paper-button>', '</yt-icon-button>');
  323. paper = like.querySelector('yt-icon-button');
  324. paper.querySelector('button#button').appendChild(like.querySelector('yt-icon'));
  325.  
  326. var dislike = $('ytd-video-primary-info-renderer div#segmented-dislike-button > ytd-toggle-button-renderer');
  327. lds.insertBefore(dislike, share);
  328. $('ytd-video-primary-info-renderer ytd-segmented-like-dislike-button-renderer').remove();
  329. dislike.setAttribute('class', dislike.getAttribute('class').replace('ytd-segmented-like-dislike-button-renderer', 'ytd-menu-renderer force-icon-button'));
  330. dislike.removeAttribute('has-no-text');
  331. dislike.setAttribute('style-action-button', '');
  332. var dlabel = document.createElement('yt-formatted-stringx');
  333. dlabel.setAttribute('id', 'text');
  334. if(dislike.getAttribute('class').includes('style-default-active'))
  335. dlabel.setAttribute('class', dlabel.getAttribute('class').replace('style-default', 'style-default-active'));
  336. dislike.querySelector('a').insertBefore(dlabel, dislike.querySelector('tp-yt-paper-tooltip'));
  337.  
  338. $('ytd-video-primary-info-renderer').removeAttribute('flex-menu-enabled');
  339. });
  340.  
  341. // Restore old comment replies UI
  342. var observingComments = false;
  343. var hl;
  344.  
  345. const cfconfig = {
  346. unicodeEmojis: false
  347. };
  348.  
  349. const cfi18n = {
  350. en: {
  351. viewSingular: "View reply",
  352. viewMulti: "View %s replies",
  353. viewSingularOwner: "View reply from %s",
  354. viewMultiOwner: "View %s replies from %s and others",
  355. hideSingular: "Hide reply",
  356. hideMulti: "Hide replies",
  357. replyCountIsolator: /( REPLIES)|( REPLY)/
  358. }
  359. }
  360.  
  361. /**
  362. * Get a string from the localization strings.
  363. *
  364. * @param {string} string Name of string to get
  365. * @param {string} hl Language to use.
  366. * @param {...array} args Strings.
  367. * @returns {string}
  368. */
  369. function getString(string, hl = "en", ...args) {
  370. if (!string) return;
  371. var str;
  372. if (cfi18n[hl]) {
  373. if (cfi18n[hl][string]) {
  374. str = cfi18n[hl][string];
  375. } else if (cfi18n.en[string]) {
  376. str = cfi18n.en[string];
  377. } else {
  378. return;
  379. }
  380. } else {
  381. if (cfi18n.en[string]) str = cfi18n.en[string];
  382. }
  383.  
  384. for (var i = 0; i < args.length; i++) {
  385. str = str.replace(/%s/, args[i]);
  386. }
  387.  
  388. return str;
  389. }
  390.  
  391. /**
  392. * Wait for a selector to exist
  393. *
  394. * @param {string} selector CSS Selector
  395. * @param {HTMLElement} base Element to search inside
  396. * @returns {Node}
  397. */
  398. async function waitForElm(selector, base = document) {
  399. if (!selector) return null;
  400. if (!base.querySelector) return null;
  401. while (base.querySelector(selector) == null) {
  402. await new Promise(r => requestAnimationFrame(r));
  403. };
  404. return base.querySelector(selector);
  405. };
  406.  
  407. /**
  408. * Is a value in an array?
  409. *
  410. * @param {*} needle Value to search
  411. * @param {Array} haystack Array to search
  412. * @returns {boolean}
  413. */
  414. function inArray(needle, haystack) {
  415. for (var i = 0; i < haystack.length; i++) {
  416. if (needle == haystack[i]) return true;
  417. }
  418. return false;
  419. }
  420.  
  421. /**
  422. * Get text of an InnerTube string.
  423. *
  424. * @param {object} object String container.
  425. */
  426. function getSimpleString(object) {
  427. if (object.simpleText) return object.simpleText;
  428.  
  429. var str = "";
  430. for (var i = 0; i < object.runs.length; i++) {
  431. str += object.runs[i].text;
  432. }
  433. return str;
  434. }
  435.  
  436. /**
  437. * Format a commentRenderer.
  438. *
  439. * @param {object} comment commentRenderer from InnerTube.
  440. */
  441. function formatComment(comment) {
  442. if (cfconfig.unicodeEmojis) {
  443. var runs;
  444. try {
  445. runs = comment.contentText.runs
  446. for (var i = 0; i < runs.length; i++) {
  447. delete runs[i].emoji;
  448. delete runs[i].loggingDirectives;
  449. }
  450. } catch(err) {}
  451. }
  452.  
  453. return comment;
  454. }
  455.  
  456. /**
  457. * Format a commentThreadRenderer.
  458. *
  459. * @param {object} thread commentThreadRenderer from InnerTube.
  460. */
  461. async function formatCommentThread(thread) {
  462. if (thread.comment.commentRenderer) {
  463. thread.comment.commentRenderer = formatComment(thread.comment.commentRenderer);
  464. }
  465.  
  466. var replies;
  467. try {
  468. replies = thread.replies.commentRepliesRenderer;
  469. if (replies.viewRepliesIcon) {
  470. replies.viewReplies.buttonRenderer.icon = replies.viewRepliesIcon.buttonRenderer.icon;
  471. delete replies.viewRepliesIcon;
  472. }
  473.  
  474. if (replies.hideRepliesIcon) {
  475. replies.hideReplies.buttonRenderer.icon = replies.hideRepliesIcon.buttonRenderer.icon;
  476. delete replies.hideRepliesIcon;
  477. }
  478.  
  479. var creatorName;
  480. try {
  481. creatorName = replies.viewRepliesCreatorThumbnail.accessibility.accessibilityData.label;
  482. delete replies.viewRepliesCreatorThumbnail;
  483. } catch(err) {}
  484.  
  485. var replyCount = getSimpleString(replies.viewReplies.buttonRenderer.text);
  486. replyCount = +replyCount.replace(getString("replyCountIsolator", hl), "");
  487.  
  488. var viewMultiString = creatorName ? "viewMultiOwner" : "viewMulti";
  489. var viewSingleString = creatorName ? "viewSingularOwner" : "viewSingular";
  490.  
  491. replies.viewReplies.buttonRenderer.text = {
  492. runs: [
  493. {
  494. text: (replyCount > 1) ? getString(viewMultiString, hl, replyCount, creatorName) : getString(viewSingleString, hl, creatorName)
  495. }
  496. ]
  497. }
  498.  
  499. replies.hideReplies.buttonRenderer.text = {
  500. runs: [
  501. {
  502. text: (replyCount > 1) ? getString("hideMulti", hl) : getString("hideSingular", hl)
  503. }
  504. ]
  505. };
  506. } catch(err) {}
  507.  
  508. return thread;
  509. }
  510.  
  511. /**
  512. * Force Polymer to refresh data of an element.
  513. *
  514. * @param {Node} element Element to refresh data of.
  515. */
  516. function refreshData(element) {
  517. var clone = element.cloneNode();
  518. clone.data = element.data;
  519. // Let the script know we left our mark
  520. // in a way that doesn't rely on classes
  521. // because Polymer likes to cast comments
  522. // into the void for later reuse
  523. clone.data.fixedByCF = true;
  524. for (var i in element.properties) {
  525. clone[i] = element[i];
  526. }
  527. element.insertAdjacentElement("afterend", clone);
  528. element.remove();
  529. }
  530.  
  531. var commentObserver = new MutationObserver((list) => {
  532. list.forEach(async (mutation) => {
  533. if (mutation.addedNodes) {
  534. for (var i = 0; i < mutation.addedNodes.length; i++) {
  535. var elm = mutation.addedNodes[i];
  536. if (elm.classList && elm.data && !elm.data.fixedByCF) {
  537. if (elm.tagName == "YTD-COMMENT-THREAD-RENDERER") {
  538. elm.data = await formatCommentThread(elm.data);
  539. refreshData(elm);
  540. } else if (elm.tagName == "YTD-COMMENT-RENDERER") {
  541. if (!elm.classList.contains("ytd-comment-thread-renderer")) {
  542. elm.data = formatComment(elm.data);
  543. refreshData(elm);
  544. }
  545. }
  546. }
  547. }
  548. }
  549. });
  550. });
  551.  
  552. document.addEventListener("yt-page-data-updated", async (e) => {
  553. hl = yt.config_.HL;
  554. commentObserver.observe(document.querySelector("ytd-app"), { childList: true, subtree: true });
  555. });
  556.  
  557. // CSS adjustments and UI fixes
  558. (function() {
  559. ApplyCSS();
  560. function ApplyCSS() {
  561. var styles = document.createElement("style");
  562. styles.innerHTML=`
  563. /* Disable rounded corners including inform news such as covid19 */
  564. #cinematics.ytd-watch-flexy {
  565. display: none !important;
  566. }
  567.  
  568. div#clarify-box.attached-message.style-scope.ytd-watch-flexy {
  569. margin-top: 0px !important;
  570. }
  571.  
  572. ytd-clarification-renderer.style-scope.ytd-item-section-renderer {
  573. border: 1px solid !important;
  574. border-color: #0000001a !important;
  575. border-radius: 0px !important;
  576. }
  577.  
  578. ytd-clarification-renderer.style-scope.ytd-watch-flexy {
  579. border: 1px solid !important;
  580. border-color: #0000001a !important;
  581. border-radius: 0px !important;
  582. }
  583.  
  584. yt-formatted-string.description.style-scope.ytd-clarification-renderer {
  585. font-size: 1.4rem !important;
  586. }
  587.  
  588. div.content-title.style-scope.ytd-clarification-renderer {
  589. padding-bottom: 4px !important;
  590. }
  591.  
  592. ytd-playlist-panel-renderer[modern-panels]:not([within-miniplayer]) #container.ytd-playlist-panel-renderer {
  593. border-radius: 0px !important;
  594. }
  595.  
  596. ytd-playlist-panel-renderer[modern-panels]:not([hide-header-text]) .title.ytd-playlist-panel-renderer {
  597. font-family: Roboto !important;
  598. font-size: 1.4rem !important;
  599. line-height: 2rem !important;
  600. font-weight: 500 !important;
  601. }
  602.  
  603. ytd-tvfilm-offer-module-renderer[modern-panels] {
  604. border-radius: 0px !important;
  605. }
  606.  
  607. ytd-tvfilm-offer-module-renderer[modern-panels] #header.ytd-tvfilm-offer-module-renderer {
  608. border-radius: 0px !important;
  609. font-family: Roboto !important;
  610. font-size: 1.6rem !important;
  611. line-height: 2.2rem !important;
  612. font-weight: 400 !important;
  613. }
  614.  
  615. /* Disable rounded corners under the player */
  616. .ytp-ad-player-overlay-flyout-cta-rounded {
  617. border-radius: 2px !important;
  618. }
  619.  
  620. .ytp-flyout-cta .ytp-flyout-cta-action-button.ytp-flyout-cta-action-button-rounded {
  621. border-radius: 2px !important;
  622. text-transform: uppercase !important;
  623. }
  624.  
  625. .ytp-ad-action-interstitial-action-button.ytp-ad-action-interstitial-action-button-rounded {
  626. border-radius: 2px !important;
  627. text-transform: uppercase !important;
  628. }
  629.  
  630. .ytp-settings-menu.ytp-rounded-menu, .ytp-screen-mode-menu.ytp-rounded-menu {
  631. border-radius: 2px !important;
  632. }
  633.  
  634. .ytp-videowall-still-round-medium .ytp-videowall-still-image {
  635. border-radius: 2px !important;
  636. }
  637.  
  638. .ytp-sb-subscribe.ytp-sb-rounded, .ytp-sb-unsubscribe.ytp-sb-rounded {
  639. border-radius: 2px !important;
  640. }
  641.  
  642. .branding-context-container-inner.ytp-rounded-branding-context {
  643. border-radius: 2px !important;
  644. }
  645.  
  646. .ytp-autonav-endscreen-upnext-button.ytp-autonav-endscreen-upnext-button-rounded {
  647. border-radius: 2px !important;
  648. }
  649.  
  650. .ytp-autonav-cancelled-mini-mode .ytp-autonav-endscreen-upnext-thumbnail.rounded-thumbnail, .countdown-running .ytp-autonav-endscreen-small-mode .ytp-autonav-endscreen-upnext-thumbnail.rounded-thumbnail {
  651. border-radius: 2px !important;
  652. }
  653.  
  654. .ytp-autonav-endscreen-upnext-thumbnail.rounded-thumbnail {
  655. border-radius: 2px !important;
  656. }
  657.  
  658. .ytp-ad-overlay-container.ytp-rounded-overlay-ad .ytp-ad-overlay-image img, .ytp-ad-overlay-container.ytp-rounded-overlay-ad .ytp-ad-text-overlay, .ytp-ad-overlay-container.ytp-rounded-overlay-ad .ytp-ad-enhanced-overlay {
  659. border-radius: 0px !important;
  660. }
  661.  
  662. .ytp-tooltip.ytp-rounded-tooltip.ytp-text-detail.ytp-preview .ytp-tooltip-bg {
  663. border-top-left-radius: 0px !important;
  664. border-bottom-left-radius: 0px !important;
  665. }
  666.  
  667. .ytp-tooltip.ytp-rounded-tooltip.ytp-text-detail.ytp-preview {
  668. border-radius: 0px !important;
  669. }
  670.  
  671. /* Subscribe button fixes and improvements */
  672. tp-yt-paper-button.style-scope.ytd-subscribe-button-renderer {
  673. display: flex !important;
  674. }
  675.  
  676. .yt-spec-button-shape-next--size-m {
  677. background-color: transparent !important;
  678. padding-right: 6px !important;
  679. }
  680.  
  681. .yt-spec-button-shape-next--mono.yt-spec-button-shape-next--tonal {
  682. background-color: transparent !important;
  683. }
  684.  
  685. div.cbox.yt-spec-button-shape-next--button-text-content {
  686. display: none !important;
  687. }
  688.  
  689. div.yt-spec-button-shape-next__secondary-icon {
  690. display: none !important;
  691. }
  692.  
  693. /* Fix for 7KT Video Downloader */
  694. .box {
  695. margin-top: -18px !important;
  696. left: 0px !important;
  697. }`
  698. document.head.appendChild(styles);
  699. }
  700. })();

QingJ © 2025

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